Files
tutti/packages/agent/daemon/runtime/standard_acp_permissions.go
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

112 lines
3.2 KiB
Go

package agentruntime
import (
"context"
"strings"
)
func (a *standardACPAdapter) ApplyPermissionMode(ctx context.Context, session Session) error {
if a != nil && a.config.launchPermission != nil {
return nil
}
// Permission changes are live settings RPCs too. Keep their client lookup
// and protocol call in the same lifecycle fence as other settings updates
// so idle release cannot close the transport between them.
unlockLifecycle := a.lockSessionLifecycle(session.AgentSessionID)
defer unlockLifecycle()
acpSession := a.getUsableSession(session.AgentSessionID)
if acpSession == nil || acpSession.client == nil {
return nil
}
if strings.TrimSpace(session.ProviderSessionID) == "" {
session.ProviderSessionID = acpSession.providerSessionID
}
// Track the live tier so automatic decisions (for example full-access
// approval or read-only denial) affect subsequent requests without respawn.
a.setSessionPermissionModeID(session.AgentSessionID, session.PermissionModeID)
if a.config.permissionModeID == nil || a.config.permissionModeID(session.PermissionModeID) == "" {
return nil
}
return a.applyACPMode(ctx, acpSession.client, session, a.effectiveModeID(session))
}
func (a *standardACPAdapter) effectiveWorkflowModeConfigOptionID() string {
if a == nil {
return ""
}
if a.config.planModeRuntimeID != "" && a.config.planModeDisabledRuntimeID != "" {
return "mode"
}
return a.effectivePermissionConfigOptionID()
}
func (a *standardACPAdapter) setSessionPermissionModeID(agentSessionID string, permissionModeID string) {
if a == nil {
return
}
a.mu.Lock()
defer a.mu.Unlock()
if session := a.sessions[strings.TrimSpace(agentSessionID)]; session != nil {
session.permissionModeID = strings.TrimSpace(permissionModeID)
}
}
func (a *standardACPAdapter) setSessionPlanMode(agentSessionID string, enabled bool) {
if a == nil {
return
}
a.mu.Lock()
defer a.mu.Unlock()
if session := a.sessions[strings.TrimSpace(agentSessionID)]; session != nil {
session.planMode = enabled
}
}
// automaticPermissionDecision resolves the decision the provider's live
// permission tier applies to a permission request, or "" to prompt the user.
func (a *standardACPAdapter) automaticPermissionDecision(agentSessionID string) string {
if a == nil {
return ""
}
a.mu.Lock()
session := a.sessions[strings.TrimSpace(agentSessionID)]
permissionModeID := ""
planMode := false
if session != nil {
permissionModeID = session.permissionModeID
planMode = session.planMode
}
a.mu.Unlock()
if planMode {
return "denied"
}
if a.config.automaticPermissionDecision == nil {
return ""
}
return a.config.automaticPermissionDecision(permissionModeID)
}
func (a *standardACPAdapter) effectiveModeID(session Session) string {
if a == nil || a.config.permissionModeID == nil {
return ""
}
if session.SettingsValue().PlanMode {
if a.config.planModeRuntimeID != "" {
return a.config.planModeRuntimeID
}
if modeID := a.config.permissionModeID("plan"); modeID != "" {
return modeID
}
if a.config.launchPermission != nil {
return ""
}
}
if a.config.planModeDisabledRuntimeID != "" {
return a.config.planModeDisabledRuntimeID
}
if a.config.launchPermission != nil {
return ""
}
return a.config.permissionModeID(session.PermissionModeID)
}