fix: forward project permissions to agent launches (#198)

This commit is contained in:
Harshit Singh Bhandari 2026-06-12 16:26:42 +05:30 committed by GitHub
parent d432738b1c
commit 295cda5787
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 60 additions and 4 deletions

View File

@ -216,13 +216,15 @@ func (m *Manager) Spawn(ctx context.Context, cfg ports.SpawnConfig) (domain.Sess
m.markSpawnFailedTerminated(ctx, id) m.markSpawnFailedTerminated(ctx, id)
return domain.SessionRecord{}, fmt.Errorf("spawn %s: %w", id, err) return domain.SessionRecord{}, fmt.Errorf("spawn %s: %w", id, err)
} }
agentConfig := effectiveAgentConfig(cfg.Kind, project.Config)
argv, err := agent.GetLaunchCommand(ctx, ports.LaunchConfig{ argv, err := agent.GetLaunchCommand(ctx, ports.LaunchConfig{
SessionID: string(id), SessionID: string(id),
WorkspacePath: ws.Path, WorkspacePath: ws.Path,
Prompt: prompt, Prompt: prompt,
SystemPrompt: systemPrompt, SystemPrompt: systemPrompt,
IssueID: string(cfg.IssueID), IssueID: string(cfg.IssueID),
Config: effectiveAgentConfig(cfg.Kind, project.Config), Config: agentConfig,
Permissions: agentConfig.Permissions,
}) })
if err != nil { if err != nil {
_ = m.workspace.Destroy(ctx, ws) _ = m.workspace.Destroy(ctx, ws)
@ -823,7 +825,7 @@ func restoreArgv(ctx context.Context, agent ports.Agent, id domain.SessionID, wo
WorkspacePath: workspacePath, WorkspacePath: workspacePath,
Metadata: map[string]string{ports.MetadataKeyAgentSessionID: meta.AgentSessionID}, Metadata: map[string]string{ports.MetadataKeyAgentSessionID: meta.AgentSessionID},
} }
cmd, ok, err := agent.GetRestoreCommand(ctx, ports.RestoreConfig{Session: ref, Config: agentConfig}) cmd, ok, err := agent.GetRestoreCommand(ctx, ports.RestoreConfig{Session: ref, Config: agentConfig, Permissions: agentConfig.Permissions})
if err != nil { if err != nil {
return nil, fmt.Errorf("restore command: %w", err) return nil, fmt.Errorf("restore command: %w", err)
} }
@ -835,6 +837,7 @@ func restoreArgv(ctx context.Context, agent ports.Agent, id domain.SessionID, wo
WorkspacePath: workspacePath, WorkspacePath: workspacePath,
Prompt: meta.Prompt, Prompt: meta.Prompt,
Config: agentConfig, Config: agentConfig,
Permissions: agentConfig.Permissions,
}) })
if err != nil { if err != nil {
return nil, fmt.Errorf("launch command: %w", err) return nil, fmt.Errorf("launch command: %w", err)

View File

@ -154,8 +154,9 @@ func (fakeAgents) Agent(domain.AgentHarness) (ports.Agent, bool) { return fakeAg
// session manager resolved and forwarded a project's agent config. // session manager resolved and forwarded a project's agent config.
type recordingAgent struct { type recordingAgent struct {
fakeAgent fakeAgent
lastConfig ports.AgentConfig lastConfig ports.AgentConfig
lastLaunch ports.LaunchConfig lastLaunch ports.LaunchConfig
lastRestore ports.RestoreConfig
} }
func (a *recordingAgent) GetLaunchCommand(_ context.Context, cfg ports.LaunchConfig) ([]string, error) { func (a *recordingAgent) GetLaunchCommand(_ context.Context, cfg ports.LaunchConfig) ([]string, error) {
@ -166,6 +167,7 @@ func (a *recordingAgent) GetLaunchCommand(_ context.Context, cfg ports.LaunchCon
func (a *recordingAgent) GetRestoreCommand(_ context.Context, cfg ports.RestoreConfig) ([]string, bool, error) { func (a *recordingAgent) GetRestoreCommand(_ context.Context, cfg ports.RestoreConfig) ([]string, bool, error) {
a.lastConfig = cfg.Config a.lastConfig = cfg.Config
a.lastRestore = cfg
return []string{"resume"}, true, nil return []string{"resume"}, true, nil
} }
@ -497,6 +499,57 @@ func TestSpawn_DefaultsBranchFromSessionID(t *testing.T) {
} }
} }
func TestSpawn_ForwardsResolvedAgentConfigPermissions(t *testing.T) {
st := newFakeStore()
st.projects["mer"] = domain.ProjectRecord{ID: "mer", Config: domain.ProjectConfig{
AgentConfig: domain.AgentConfig{Permissions: domain.PermissionModeAuto},
Worker: domain.RoleOverride{AgentConfig: domain.AgentConfig{Permissions: domain.PermissionModeBypassPermissions}},
}}
agent := &recordingAgent{}
lookPath := func(string) (string, error) { return "/bin/true", nil }
m := New(Deps{Runtime: &fakeRuntime{}, Agents: singleAgent{agent: agent}, Workspace: &fakeWorkspace{}, Store: st, Messenger: &fakeMessenger{}, Lifecycle: &fakeLCM{store: st}, LookPath: lookPath})
_, err := m.Spawn(ctx, ports.SpawnConfig{ProjectID: "mer", Kind: domain.KindWorker})
if err != nil {
t.Fatal(err)
}
if agent.lastLaunch.Config.Permissions != domain.PermissionModeBypassPermissions {
t.Fatalf("launch config permissions = %q, want bypass", agent.lastLaunch.Config.Permissions)
}
if agent.lastLaunch.Permissions != domain.PermissionModeBypassPermissions {
t.Fatalf("launch permissions = %q, want bypass", agent.lastLaunch.Permissions)
}
}
func TestRestore_ForwardsResolvedAgentConfigPermissions(t *testing.T) {
st := newFakeStore()
st.projects["mer"] = domain.ProjectRecord{ID: "mer", Config: domain.ProjectConfig{
AgentConfig: domain.AgentConfig{Permissions: domain.PermissionModeBypassPermissions},
}}
st.sessions["mer-1"] = domain.SessionRecord{
ID: "mer-1",
ProjectID: "mer",
Kind: domain.KindWorker,
IsTerminated: true,
Metadata: domain.SessionMetadata{Branch: "ao/mer-1", WorkspacePath: "/tmp/ws", AgentSessionID: "native-1"},
}
agent := &recordingAgent{}
m := New(Deps{Runtime: &fakeRuntime{}, Agents: singleAgent{agent: agent}, Workspace: &fakeWorkspace{}, Store: st, Messenger: &fakeMessenger{}, Lifecycle: &fakeLCM{store: st}, LookPath: func(string) (string, error) { return "/bin/true", nil }})
_, err := m.Restore(ctx, "mer-1")
if err != nil {
t.Fatal(err)
}
if agent.lastRestore.Config.Permissions != domain.PermissionModeBypassPermissions {
t.Fatalf("restore config permissions = %q, want bypass", agent.lastRestore.Config.Permissions)
}
if agent.lastRestore.Permissions != domain.PermissionModeBypassPermissions {
t.Fatalf("restore permissions = %q, want bypass", agent.lastRestore.Permissions)
}
}
func TestSpawnWorker_AppendsActiveOrchestratorContact(t *testing.T) { func TestSpawnWorker_AppendsActiveOrchestratorContact(t *testing.T) {
st := newFakeStore() st := newFakeStore()
st.num = 1 st.num = 1