mirror of
https://github.com/stablyai/orca.git
synced 2026-11-03 18:47:40 +00:00
* feat(agents): store each agent's permission itself instead of typing flags into Arguments Terminals and new chats read one stored choice per agent (Use the agent's own settings, Ask for approval, Accept edits, Approve for me, Full access). Orca adds the flag at launch; Arguments hold only the user's own text. A one-time move lifts Orca's flags out of saved Arguments. Older clients still see and write the flag as part of Arguments; the host translates. * fix(agents): say the all-agents switch resets agents set separately; keep primitives unstyled * test(agents): the one-time move returns every launch-profile field * Fix permission carrier ownership and surface-specific defaults * Preserve uncertain permission operands and name the option inventory * Check env entries without indexing typed agent maps * Combine Chat permission capability imports * Use folder execution-host platform for permission environment * Preserve launch map replacement and acknowledge permission saves * Keep permission feedback fallbacks statically discoverable * Provide preload platform to Agents settings render tests * Preserve Gemini approval arguments under Full access * fix(settings): retain complete environment edits through save outcomes * fix(settings): narrow local failure scope and preserve host messages * fix(settings): retire argument drafts after acknowledged saves * fix(settings): keep Goose environment editable after reset * fix(settings): show resolved arguments for legacy hosts * Preserve pending environment resets and bound launch settings work * Keep optional settings fallback in repository metadata reads * Read repository visibility defaults through the raw settings fixtures * Prepare whole Environment edits and retire unchanged drafts * Keep Environment settings transitions in an acyclic module * Update raw settings reader test fixtures * Place test fixture safety notes on assertion starts * test: pin permission settings work and recovery contracts * test: type permission settings work fixtures * test: cover migrated permission inputs and captured CLI grammar * test: preserve typed permissions in WSL Claude restarts
96 lines
3.4 KiB
TypeScript
96 lines
3.4 KiB
TypeScript
import { agentPermissionHostPlatform, permissionEnvNameMatches } from './agent-permission-env'
|
|
import type {
|
|
AgentLaunchSettingsMutation,
|
|
AgentLaunchSettingsSource
|
|
} from './agent-launch-settings'
|
|
import { resolveTuiAgentLaunchEnv } from './tui-agent-launch-defaults'
|
|
import {
|
|
agentPermissionEnv,
|
|
applyAgentPermissionOverrides,
|
|
hasTypedAgentPermission,
|
|
resolveAgentPermission,
|
|
type AgentPermissionChoice
|
|
} from './tui-agent-permission-choice'
|
|
import { liftAgentPermissionEnv } from './tui-agent-permission-lift'
|
|
import type { TuiAgent } from './tui-agent'
|
|
|
|
/** An agent's choice changed only when it differs from what it resolves to now. */
|
|
export function choiceUpdate(
|
|
settings: AgentLaunchSettingsSource,
|
|
agent: TuiAgent,
|
|
choice: AgentPermissionChoice
|
|
): AgentLaunchSettingsSource {
|
|
return resolveAgentPermission(agent, settings).choice === choice
|
|
? {}
|
|
: applyAgentPermissionOverrides(settings, [agent], choice)
|
|
}
|
|
|
|
function hasEnvPermission(agent: TuiAgent): boolean {
|
|
return Object.keys(agentPermissionEnv(agent, 'full-access')).length > 0
|
|
}
|
|
|
|
/** A whole env record as its terminal gets it; for Goose, the bypass entry is the choice. */
|
|
export function legacyEnvUpdates(
|
|
settings: AgentLaunchSettingsSource,
|
|
agent: TuiAgent,
|
|
env: Record<string, string>,
|
|
platform: NodeJS.Platform | undefined = agentPermissionHostPlatform()
|
|
): AgentLaunchSettingsSource {
|
|
if (!hasEnvPermission(agent)) {
|
|
return { agentDefaultEnv: { ...settings.agentDefaultEnv, [agent]: env } }
|
|
}
|
|
const previous = resolveTuiAgentLaunchEnv(agent, settings, platform)
|
|
const names = Object.keys(agentPermissionEnv(agent, 'full-access'))
|
|
const carrier = (value: Record<string, string>) =>
|
|
Object.entries(value)
|
|
.filter(([key]) => names.some((name) => permissionEnvNameMatches(key, name, platform)))
|
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
if (JSON.stringify(carrier(previous)) === JSON.stringify(carrier(env))) {
|
|
const user = { ...env }
|
|
for (const [key] of carrier(env)) {
|
|
delete user[key]
|
|
}
|
|
return {
|
|
agentDefaultEnv: {
|
|
...settings.agentDefaultEnv,
|
|
[agent]: {
|
|
...user,
|
|
...Object.fromEntries(carrier(settings.agentDefaultEnv?.[agent] ?? {}))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const lifted = liftAgentPermissionEnv(agent, env, platform)
|
|
return {
|
|
agentDefaultEnv: { ...settings.agentDefaultEnv, [agent]: lifted.env },
|
|
...choiceUpdate(settings, agent, lifted.choice ?? 'own')
|
|
}
|
|
}
|
|
|
|
export function agentEnvironmentMutationUpdates(
|
|
settings: AgentLaunchSettingsSource,
|
|
mutation: Extract<
|
|
AgentLaunchSettingsMutation,
|
|
{ type: 'environment-set' | 'environment-remove' }
|
|
>,
|
|
platform: NodeJS.Platform
|
|
): AgentLaunchSettingsSource {
|
|
// Edits the env the terminal gets, so removing Goose's published bypass entry means own.
|
|
const env = { ...resolveTuiAgentLaunchEnv(mutation.agent, settings, platform) }
|
|
// Windows environment names are case insensitive on the execution host.
|
|
for (const name of Object.keys(env)) {
|
|
if (
|
|
name === mutation.name ||
|
|
(platform === 'win32' && name.toLowerCase() === mutation.name.toLowerCase())
|
|
) {
|
|
delete env[name]
|
|
}
|
|
}
|
|
const nextEnv =
|
|
mutation.type === 'environment-set' ? { ...env, [mutation.name]: mutation.value } : env
|
|
if (hasTypedAgentPermission(settings)) {
|
|
return legacyEnvUpdates(settings, mutation.agent, nextEnv, platform)
|
|
}
|
|
return { agentDefaultEnv: { ...settings.agentDefaultEnv, [mutation.agent]: nextEnv } }
|
|
}
|