@posthog/agent 2.3.443 → 2.3.449
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/claude/permissions/permission-options.d.ts +1 -1
- package/dist/adapters/claude/permissions/permission-options.js +26 -7
- package/dist/adapters/claude/permissions/permission-options.js.map +1 -1
- package/dist/agent.js +36 -10
- package/dist/agent.js.map +1 -1
- package/dist/posthog-api.js +1 -1
- package/dist/posthog-api.js.map +1 -1
- package/dist/server/agent-server.js +36 -10
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +36 -10
- package/dist/server/bin.cjs.map +1 -1
- package/package.json +3 -3
- package/src/adapters/claude/claude-agent.ts +7 -0
- package/src/adapters/claude/permissions/permission-handlers.ts +2 -2
- package/src/adapters/claude/permissions/permission-options.test.ts +51 -0
- package/src/adapters/claude/permissions/permission-options.ts +33 -7
- package/src/adapters/claude/types.ts +1 -0
|
@@ -10,6 +10,6 @@ interface PermissionOption {
|
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
12
|
declare function buildPermissionOptions(toolName: string, toolInput: Record<string, unknown>, repoRoot?: string, suggestions?: PermissionUpdate[]): PermissionOption[];
|
|
13
|
-
declare function buildExitPlanModePermissionOptions(): PermissionOption[];
|
|
13
|
+
declare function buildExitPlanModePermissionOptions(previousMode?: string): PermissionOption[];
|
|
14
14
|
|
|
15
15
|
export { type PermissionOption, buildExitPlanModePermissionOptions, buildPermissionOptions };
|
|
@@ -149,7 +149,13 @@ function buildPermissionOptions(toolName, toolInput, repoRoot, suggestions) {
|
|
|
149
149
|
}
|
|
150
150
|
return permissionOptions("Yes, always allow");
|
|
151
151
|
}
|
|
152
|
-
|
|
152
|
+
var CONTINUE_LABELS = {
|
|
153
|
+
auto: 'Yes, continue in "auto" mode',
|
|
154
|
+
acceptEdits: "Yes, continue auto-accepting edits",
|
|
155
|
+
default: "Yes, continue manually approving edits",
|
|
156
|
+
bypassPermissions: "Yes, continue bypassing all permissions"
|
|
157
|
+
};
|
|
158
|
+
function buildExitPlanModePermissionOptions(previousMode) {
|
|
153
159
|
const options = [];
|
|
154
160
|
if (ALLOW_BYPASS) {
|
|
155
161
|
options.push({
|
|
@@ -173,14 +179,27 @@ function buildExitPlanModePermissionOptions() {
|
|
|
173
179
|
kind: "allow_once",
|
|
174
180
|
name: "Yes, and manually approve edits",
|
|
175
181
|
optionId: "default"
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
kind: "reject_once",
|
|
179
|
-
name: "No, and tell the agent what to do differently",
|
|
180
|
-
optionId: "reject_with_feedback",
|
|
181
|
-
_meta: { customInput: true }
|
|
182
182
|
}
|
|
183
183
|
);
|
|
184
|
+
const previousIndex = previousMode ? options.findIndex((opt) => opt.optionId === previousMode) : -1;
|
|
185
|
+
if (previousIndex > 0) {
|
|
186
|
+
const [previous] = options.splice(previousIndex, 1);
|
|
187
|
+
const continueLabel = CONTINUE_LABELS[previous.optionId];
|
|
188
|
+
options.unshift(
|
|
189
|
+
continueLabel ? { ...previous, name: continueLabel } : previous
|
|
190
|
+
);
|
|
191
|
+
} else if (previousIndex === 0) {
|
|
192
|
+
const continueLabel = CONTINUE_LABELS[options[0].optionId];
|
|
193
|
+
if (continueLabel) {
|
|
194
|
+
options[0] = { ...options[0], name: continueLabel };
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
options.push({
|
|
198
|
+
kind: "reject_once",
|
|
199
|
+
name: "No, and tell the agent what to do differently",
|
|
200
|
+
optionId: "reject_with_feedback",
|
|
201
|
+
_meta: { customInput: true }
|
|
202
|
+
});
|
|
184
203
|
return options;
|
|
185
204
|
}
|
|
186
205
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/utils/common.ts","../../../../src/execution-mode.ts","../../../../src/adapters/claude/tools.ts","../../../../src/adapters/claude/permissions/permission-options.ts"],"sourcesContent":["import type { Logger } from \"./logger\";\n\n/**\n * Races an operation against a timeout.\n * Returns success with the value if the operation completes in time,\n * or timeout if the operation takes longer than the specified duration.\n */\nexport async function withTimeout<T>(\n operation: Promise<T>,\n timeoutMs: number,\n): Promise<{ result: \"success\"; value: T } | { result: \"timeout\" }> {\n const timeoutPromise = new Promise<{ result: \"timeout\" }>((resolve) =>\n setTimeout(() => resolve({ result: \"timeout\" }), timeoutMs),\n );\n const operationPromise = operation.then((value) => ({\n result: \"success\" as const,\n value,\n }));\n return Promise.race([operationPromise, timeoutPromise]);\n}\n\nexport const IS_ROOT =\n typeof process !== \"undefined\" &&\n (process.geteuid?.() ?? process.getuid?.()) === 0;\n\nexport const ALLOW_BYPASS = !IS_ROOT || !!process.env.IS_SANDBOX;\n\nexport function unreachable(value: never, logger: Logger): void {\n let valueAsString: string;\n try {\n valueAsString = JSON.stringify(value);\n } catch {\n valueAsString = String(value);\n }\n logger.error(`Unexpected case: ${valueAsString}`);\n}\n","import { ALLOW_BYPASS } from \"./utils/common\";\n\nexport interface ModeInfo {\n id: string;\n name: string;\n description: string;\n}\n\nconst availableModes: ModeInfo[] = [\n {\n id: \"default\",\n name: \"Default\",\n description: \"Standard behavior, prompts for dangerous operations\",\n },\n {\n id: \"acceptEdits\",\n name: \"Accept Edits\",\n description: \"Auto-accept file edit operations\",\n },\n {\n id: \"plan\",\n name: \"Plan Mode\",\n description: \"Planning mode, no actual tool execution\",\n },\n];\n\nif (ALLOW_BYPASS) {\n availableModes.push(\n {\n id: \"bypassPermissions\",\n name: \"Bypass Permissions\",\n description: \"Auto-accept all permission requests\",\n },\n {\n id: \"auto\",\n name: \"Auto Mode\",\n description: \"Use a model classifier to approve/deny permission prompts\",\n },\n );\n}\n\n// Expose execution mode IDs in type-safe order for type checks\nexport const CODE_EXECUTION_MODES = [\n \"default\",\n \"acceptEdits\",\n \"plan\",\n \"bypassPermissions\",\n \"auto\",\n] as const;\n\nexport type CodeExecutionMode = (typeof CODE_EXECUTION_MODES)[number];\n\nexport function isCodeExecutionMode(mode: string): mode is CodeExecutionMode {\n return (CODE_EXECUTION_MODES as readonly string[]).includes(mode);\n}\n\nexport function getAvailableModes(): ModeInfo[] {\n return ALLOW_BYPASS\n ? availableModes\n : availableModes.filter((m) => m.id !== \"bypassPermissions\");\n}\n\n// --- Codex-native modes ---\n\nexport const CODEX_NATIVE_MODES = [\"auto\", \"read-only\", \"full-access\"] as const;\n\nexport type CodexNativeMode = (typeof CODEX_NATIVE_MODES)[number];\n\n/** Union of all permission mode IDs across adapters */\nexport type PermissionMode = CodeExecutionMode | CodexNativeMode;\n\nexport function isCodexNativeMode(mode: string): mode is CodexNativeMode {\n return (CODEX_NATIVE_MODES as readonly string[]).includes(mode);\n}\n\nconst codexModes: ModeInfo[] = [\n {\n id: \"read-only\",\n name: \"Read Only\",\n description: \"Read-only access, no file modifications\",\n },\n {\n id: \"auto\",\n name: \"Auto\",\n description: \"Standard behavior, prompts for dangerous operations\",\n },\n];\n\nif (ALLOW_BYPASS) {\n codexModes.push({\n id: \"full-access\",\n name: \"Full Access\",\n description: \"Auto-accept all permission requests\",\n });\n}\n\nexport function getAvailableCodexModes(): ModeInfo[] {\n return ALLOW_BYPASS\n ? codexModes\n : codexModes.filter((m) => m.id !== \"full-access\");\n}\n","export {\n CODE_EXECUTION_MODES,\n type CodeExecutionMode,\n getAvailableModes,\n type ModeInfo,\n} from \"../../execution-mode\";\n\nimport type { CodeExecutionMode } from \"../../execution-mode\";\nimport { isMcpToolReadOnly } from \"./mcp/tool-metadata\";\n\nexport const READ_TOOLS: Set<string> = new Set([\"Read\", \"NotebookRead\"]);\n\nexport const WRITE_TOOLS: Set<string> = new Set([\n \"Edit\",\n \"Write\",\n \"NotebookEdit\",\n]);\n\nexport const BASH_TOOLS: Set<string> = new Set([\n \"Bash\",\n \"BashOutput\",\n \"KillShell\",\n]);\n\nexport const SEARCH_TOOLS: Set<string> = new Set([\"Glob\", \"Grep\", \"LS\"]);\n\nexport const WEB_TOOLS: Set<string> = new Set([\"WebSearch\", \"WebFetch\"]);\n\nexport const AGENT_TOOLS: Set<string> = new Set([\n \"Task\",\n \"Agent\",\n \"TodoWrite\",\n \"Skill\",\n]);\n\nconst BASE_ALLOWED_TOOLS = [\n ...READ_TOOLS,\n ...SEARCH_TOOLS,\n ...WEB_TOOLS,\n ...AGENT_TOOLS,\n];\n\nconst AUTO_ALLOWED_TOOLS: Record<string, Set<string>> = {\n auto: new Set(BASE_ALLOWED_TOOLS),\n default: new Set(BASE_ALLOWED_TOOLS),\n acceptEdits: new Set([...BASE_ALLOWED_TOOLS, ...WRITE_TOOLS]),\n plan: new Set(BASE_ALLOWED_TOOLS),\n};\n\nexport function isToolAllowedForMode(\n toolName: string,\n mode: CodeExecutionMode,\n): boolean {\n if (mode === \"bypassPermissions\") {\n return true;\n }\n if (AUTO_ALLOWED_TOOLS[mode]?.has(toolName) === true) {\n return true;\n }\n if (isMcpToolReadOnly(toolName)) {\n return true;\n }\n return false;\n}\n","import type { PermissionUpdate } from \"@anthropic-ai/claude-agent-sdk\";\nimport { ALLOW_BYPASS } from \"../../../utils/common\";\nimport { BASH_TOOLS, READ_TOOLS, SEARCH_TOOLS, WRITE_TOOLS } from \"../tools\";\n\nexport interface PermissionOption {\n kind: \"allow_once\" | \"allow_always\" | \"reject_once\" | \"reject_always\";\n name: string;\n optionId: string;\n _meta?: { description?: string; customInput?: boolean };\n}\n\nfunction permissionOptions(allowAlwaysLabel: string): PermissionOption[] {\n return [\n { kind: \"allow_once\", name: \"Yes\", optionId: \"allow\" },\n { kind: \"allow_always\", name: allowAlwaysLabel, optionId: \"allow_always\" },\n {\n kind: \"reject_once\",\n name: \"No, and tell the agent what to do differently\",\n optionId: \"reject\",\n _meta: { customInput: true },\n },\n ];\n}\n\nexport function buildPermissionOptions(\n toolName: string,\n toolInput: Record<string, unknown>,\n repoRoot?: string,\n suggestions?: PermissionUpdate[],\n): PermissionOption[] {\n if (BASH_TOOLS.has(toolName)) {\n const rawRuleContent = suggestions\n ?.flatMap((s) => (\"rules\" in s ? s.rules : []))\n .find((r) => r.toolName === \"Bash\" && r.ruleContent)?.ruleContent;\n const ruleContent = rawRuleContent?.replace(/:?\\*$/, \"\");\n\n const command = toolInput?.command as string | undefined;\n const cmdName = command?.split(/\\s+/)[0] ?? \"this command\";\n const scopeLabel = repoRoot ? ` in ${repoRoot}` : \"\";\n const label = ruleContent ?? `\\`${cmdName}\\` commands`;\n\n return permissionOptions(\n `Yes, and don't ask again for ${label}${scopeLabel}`,\n );\n }\n\n if (toolName === \"BashOutput\") {\n return permissionOptions(\"Yes, allow all background process reads\");\n }\n\n if (toolName === \"KillShell\") {\n return permissionOptions(\"Yes, allow killing processes\");\n }\n\n if (WRITE_TOOLS.has(toolName)) {\n return permissionOptions(\"Yes, allow all edits during this session\");\n }\n\n if (READ_TOOLS.has(toolName)) {\n return permissionOptions(\"Yes, allow all reads during this session\");\n }\n\n if (SEARCH_TOOLS.has(toolName)) {\n return permissionOptions(\"Yes, allow all searches during this session\");\n }\n\n if (toolName === \"WebFetch\") {\n const url = toolInput?.url as string | undefined;\n let domain = \"\";\n try {\n domain = url ? new URL(url).hostname : \"\";\n } catch {}\n return permissionOptions(\n domain\n ? `Yes, allow all fetches from ${domain}`\n : \"Yes, allow all fetches\",\n );\n }\n\n if (toolName === \"WebSearch\") {\n return permissionOptions(\"Yes, allow all web searches\");\n }\n\n if (toolName === \"Task\") {\n return permissionOptions(\"Yes, allow all sub-tasks\");\n }\n\n if (toolName === \"TodoWrite\") {\n return permissionOptions(\"Yes, allow all todo updates\");\n }\n\n return permissionOptions(\"Yes, always allow\");\n}\n\nexport function buildExitPlanModePermissionOptions(): PermissionOption[] {\n const options: PermissionOption[] = [];\n\n if (ALLOW_BYPASS) {\n options.push({\n kind: \"allow_always\",\n name: \"Yes, bypass all permissions\",\n optionId: \"bypassPermissions\",\n });\n }\n\n options.push(\n {\n kind: \"allow_always\",\n name: 'Yes, and use \"auto\" mode',\n optionId: \"auto\",\n },\n {\n kind: \"allow_always\",\n name: \"Yes, and auto-accept edits\",\n optionId: \"acceptEdits\",\n },\n {\n kind: \"allow_once\",\n name: \"Yes, and manually approve edits\",\n optionId: \"default\",\n },\n {\n kind: \"reject_once\",\n name: \"No, and tell the agent what to do differently\",\n optionId: \"reject_with_feedback\",\n _meta: { customInput: true },\n },\n );\n\n return options;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/utils/common.ts","../../../../src/execution-mode.ts","../../../../src/adapters/claude/tools.ts","../../../../src/adapters/claude/permissions/permission-options.ts"],"sourcesContent":["import type { Logger } from \"./logger\";\n\n/**\n * Races an operation against a timeout.\n * Returns success with the value if the operation completes in time,\n * or timeout if the operation takes longer than the specified duration.\n */\nexport async function withTimeout<T>(\n operation: Promise<T>,\n timeoutMs: number,\n): Promise<{ result: \"success\"; value: T } | { result: \"timeout\" }> {\n const timeoutPromise = new Promise<{ result: \"timeout\" }>((resolve) =>\n setTimeout(() => resolve({ result: \"timeout\" }), timeoutMs),\n );\n const operationPromise = operation.then((value) => ({\n result: \"success\" as const,\n value,\n }));\n return Promise.race([operationPromise, timeoutPromise]);\n}\n\nexport const IS_ROOT =\n typeof process !== \"undefined\" &&\n (process.geteuid?.() ?? process.getuid?.()) === 0;\n\nexport const ALLOW_BYPASS = !IS_ROOT || !!process.env.IS_SANDBOX;\n\nexport function unreachable(value: never, logger: Logger): void {\n let valueAsString: string;\n try {\n valueAsString = JSON.stringify(value);\n } catch {\n valueAsString = String(value);\n }\n logger.error(`Unexpected case: ${valueAsString}`);\n}\n","import { ALLOW_BYPASS } from \"./utils/common\";\n\nexport interface ModeInfo {\n id: string;\n name: string;\n description: string;\n}\n\nconst availableModes: ModeInfo[] = [\n {\n id: \"default\",\n name: \"Default\",\n description: \"Standard behavior, prompts for dangerous operations\",\n },\n {\n id: \"acceptEdits\",\n name: \"Accept Edits\",\n description: \"Auto-accept file edit operations\",\n },\n {\n id: \"plan\",\n name: \"Plan Mode\",\n description: \"Planning mode, no actual tool execution\",\n },\n];\n\nif (ALLOW_BYPASS) {\n availableModes.push(\n {\n id: \"bypassPermissions\",\n name: \"Bypass Permissions\",\n description: \"Auto-accept all permission requests\",\n },\n {\n id: \"auto\",\n name: \"Auto Mode\",\n description: \"Use a model classifier to approve/deny permission prompts\",\n },\n );\n}\n\n// Expose execution mode IDs in type-safe order for type checks\nexport const CODE_EXECUTION_MODES = [\n \"default\",\n \"acceptEdits\",\n \"plan\",\n \"bypassPermissions\",\n \"auto\",\n] as const;\n\nexport type CodeExecutionMode = (typeof CODE_EXECUTION_MODES)[number];\n\nexport function isCodeExecutionMode(mode: string): mode is CodeExecutionMode {\n return (CODE_EXECUTION_MODES as readonly string[]).includes(mode);\n}\n\nexport function getAvailableModes(): ModeInfo[] {\n return ALLOW_BYPASS\n ? availableModes\n : availableModes.filter((m) => m.id !== \"bypassPermissions\");\n}\n\n// --- Codex-native modes ---\n\nexport const CODEX_NATIVE_MODES = [\"auto\", \"read-only\", \"full-access\"] as const;\n\nexport type CodexNativeMode = (typeof CODEX_NATIVE_MODES)[number];\n\n/** Union of all permission mode IDs across adapters */\nexport type PermissionMode = CodeExecutionMode | CodexNativeMode;\n\nexport function isCodexNativeMode(mode: string): mode is CodexNativeMode {\n return (CODEX_NATIVE_MODES as readonly string[]).includes(mode);\n}\n\nconst codexModes: ModeInfo[] = [\n {\n id: \"read-only\",\n name: \"Read Only\",\n description: \"Read-only access, no file modifications\",\n },\n {\n id: \"auto\",\n name: \"Auto\",\n description: \"Standard behavior, prompts for dangerous operations\",\n },\n];\n\nif (ALLOW_BYPASS) {\n codexModes.push({\n id: \"full-access\",\n name: \"Full Access\",\n description: \"Auto-accept all permission requests\",\n });\n}\n\nexport function getAvailableCodexModes(): ModeInfo[] {\n return ALLOW_BYPASS\n ? codexModes\n : codexModes.filter((m) => m.id !== \"full-access\");\n}\n","export {\n CODE_EXECUTION_MODES,\n type CodeExecutionMode,\n getAvailableModes,\n type ModeInfo,\n} from \"../../execution-mode\";\n\nimport type { CodeExecutionMode } from \"../../execution-mode\";\nimport { isMcpToolReadOnly } from \"./mcp/tool-metadata\";\n\nexport const READ_TOOLS: Set<string> = new Set([\"Read\", \"NotebookRead\"]);\n\nexport const WRITE_TOOLS: Set<string> = new Set([\n \"Edit\",\n \"Write\",\n \"NotebookEdit\",\n]);\n\nexport const BASH_TOOLS: Set<string> = new Set([\n \"Bash\",\n \"BashOutput\",\n \"KillShell\",\n]);\n\nexport const SEARCH_TOOLS: Set<string> = new Set([\"Glob\", \"Grep\", \"LS\"]);\n\nexport const WEB_TOOLS: Set<string> = new Set([\"WebSearch\", \"WebFetch\"]);\n\nexport const AGENT_TOOLS: Set<string> = new Set([\n \"Task\",\n \"Agent\",\n \"TodoWrite\",\n \"Skill\",\n]);\n\nconst BASE_ALLOWED_TOOLS = [\n ...READ_TOOLS,\n ...SEARCH_TOOLS,\n ...WEB_TOOLS,\n ...AGENT_TOOLS,\n];\n\nconst AUTO_ALLOWED_TOOLS: Record<string, Set<string>> = {\n auto: new Set(BASE_ALLOWED_TOOLS),\n default: new Set(BASE_ALLOWED_TOOLS),\n acceptEdits: new Set([...BASE_ALLOWED_TOOLS, ...WRITE_TOOLS]),\n plan: new Set(BASE_ALLOWED_TOOLS),\n};\n\nexport function isToolAllowedForMode(\n toolName: string,\n mode: CodeExecutionMode,\n): boolean {\n if (mode === \"bypassPermissions\") {\n return true;\n }\n if (AUTO_ALLOWED_TOOLS[mode]?.has(toolName) === true) {\n return true;\n }\n if (isMcpToolReadOnly(toolName)) {\n return true;\n }\n return false;\n}\n","import type { PermissionUpdate } from \"@anthropic-ai/claude-agent-sdk\";\nimport { ALLOW_BYPASS } from \"../../../utils/common\";\nimport { BASH_TOOLS, READ_TOOLS, SEARCH_TOOLS, WRITE_TOOLS } from \"../tools\";\n\nexport interface PermissionOption {\n kind: \"allow_once\" | \"allow_always\" | \"reject_once\" | \"reject_always\";\n name: string;\n optionId: string;\n _meta?: { description?: string; customInput?: boolean };\n}\n\nfunction permissionOptions(allowAlwaysLabel: string): PermissionOption[] {\n return [\n { kind: \"allow_once\", name: \"Yes\", optionId: \"allow\" },\n { kind: \"allow_always\", name: allowAlwaysLabel, optionId: \"allow_always\" },\n {\n kind: \"reject_once\",\n name: \"No, and tell the agent what to do differently\",\n optionId: \"reject\",\n _meta: { customInput: true },\n },\n ];\n}\n\nexport function buildPermissionOptions(\n toolName: string,\n toolInput: Record<string, unknown>,\n repoRoot?: string,\n suggestions?: PermissionUpdate[],\n): PermissionOption[] {\n if (BASH_TOOLS.has(toolName)) {\n const rawRuleContent = suggestions\n ?.flatMap((s) => (\"rules\" in s ? s.rules : []))\n .find((r) => r.toolName === \"Bash\" && r.ruleContent)?.ruleContent;\n const ruleContent = rawRuleContent?.replace(/:?\\*$/, \"\");\n\n const command = toolInput?.command as string | undefined;\n const cmdName = command?.split(/\\s+/)[0] ?? \"this command\";\n const scopeLabel = repoRoot ? ` in ${repoRoot}` : \"\";\n const label = ruleContent ?? `\\`${cmdName}\\` commands`;\n\n return permissionOptions(\n `Yes, and don't ask again for ${label}${scopeLabel}`,\n );\n }\n\n if (toolName === \"BashOutput\") {\n return permissionOptions(\"Yes, allow all background process reads\");\n }\n\n if (toolName === \"KillShell\") {\n return permissionOptions(\"Yes, allow killing processes\");\n }\n\n if (WRITE_TOOLS.has(toolName)) {\n return permissionOptions(\"Yes, allow all edits during this session\");\n }\n\n if (READ_TOOLS.has(toolName)) {\n return permissionOptions(\"Yes, allow all reads during this session\");\n }\n\n if (SEARCH_TOOLS.has(toolName)) {\n return permissionOptions(\"Yes, allow all searches during this session\");\n }\n\n if (toolName === \"WebFetch\") {\n const url = toolInput?.url as string | undefined;\n let domain = \"\";\n try {\n domain = url ? new URL(url).hostname : \"\";\n } catch {}\n return permissionOptions(\n domain\n ? `Yes, allow all fetches from ${domain}`\n : \"Yes, allow all fetches\",\n );\n }\n\n if (toolName === \"WebSearch\") {\n return permissionOptions(\"Yes, allow all web searches\");\n }\n\n if (toolName === \"Task\") {\n return permissionOptions(\"Yes, allow all sub-tasks\");\n }\n\n if (toolName === \"TodoWrite\") {\n return permissionOptions(\"Yes, allow all todo updates\");\n }\n\n return permissionOptions(\"Yes, always allow\");\n}\n\nconst CONTINUE_LABELS: Record<string, string> = {\n auto: 'Yes, continue in \"auto\" mode',\n acceptEdits: \"Yes, continue auto-accepting edits\",\n default: \"Yes, continue manually approving edits\",\n bypassPermissions: \"Yes, continue bypassing all permissions\",\n};\n\nexport function buildExitPlanModePermissionOptions(\n previousMode?: string,\n): PermissionOption[] {\n const options: PermissionOption[] = [];\n\n if (ALLOW_BYPASS) {\n options.push({\n kind: \"allow_always\",\n name: \"Yes, bypass all permissions\",\n optionId: \"bypassPermissions\",\n });\n }\n\n options.push(\n {\n kind: \"allow_always\",\n name: 'Yes, and use \"auto\" mode',\n optionId: \"auto\",\n },\n {\n kind: \"allow_always\",\n name: \"Yes, and auto-accept edits\",\n optionId: \"acceptEdits\",\n },\n {\n kind: \"allow_once\",\n name: \"Yes, and manually approve edits\",\n optionId: \"default\",\n },\n );\n\n const previousIndex = previousMode\n ? options.findIndex((opt) => opt.optionId === previousMode)\n : -1;\n if (previousIndex > 0) {\n const [previous] = options.splice(previousIndex, 1);\n const continueLabel = CONTINUE_LABELS[previous.optionId];\n options.unshift(\n continueLabel ? { ...previous, name: continueLabel } : previous,\n );\n } else if (previousIndex === 0) {\n const continueLabel = CONTINUE_LABELS[options[0].optionId];\n if (continueLabel) {\n options[0] = { ...options[0], name: continueLabel };\n }\n }\n\n options.push({\n kind: \"reject_once\",\n name: \"No, and tell the agent what to do differently\",\n optionId: \"reject_with_feedback\",\n _meta: { customInput: true },\n });\n\n return options;\n}\n"],"mappings":"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","names":[]}
|
package/dist/agent.js
CHANGED
|
@@ -4030,7 +4030,7 @@ import { v7 as uuidv7 } from "uuid";
|
|
|
4030
4030
|
// package.json
|
|
4031
4031
|
var package_default = {
|
|
4032
4032
|
name: "@posthog/agent",
|
|
4033
|
-
version: "2.3.
|
|
4033
|
+
version: "2.3.449",
|
|
4034
4034
|
repository: "https://github.com/PostHog/code",
|
|
4035
4035
|
description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
|
|
4036
4036
|
exports: {
|
|
@@ -10346,7 +10346,13 @@ function buildPermissionOptions(toolName, toolInput, repoRoot, suggestions) {
|
|
|
10346
10346
|
}
|
|
10347
10347
|
return permissionOptions("Yes, always allow");
|
|
10348
10348
|
}
|
|
10349
|
-
|
|
10349
|
+
var CONTINUE_LABELS = {
|
|
10350
|
+
auto: 'Yes, continue in "auto" mode',
|
|
10351
|
+
acceptEdits: "Yes, continue auto-accepting edits",
|
|
10352
|
+
default: "Yes, continue manually approving edits",
|
|
10353
|
+
bypassPermissions: "Yes, continue bypassing all permissions"
|
|
10354
|
+
};
|
|
10355
|
+
function buildExitPlanModePermissionOptions(previousMode) {
|
|
10350
10356
|
const options = [];
|
|
10351
10357
|
if (ALLOW_BYPASS) {
|
|
10352
10358
|
options.push({
|
|
@@ -10370,14 +10376,27 @@ function buildExitPlanModePermissionOptions() {
|
|
|
10370
10376
|
kind: "allow_once",
|
|
10371
10377
|
name: "Yes, and manually approve edits",
|
|
10372
10378
|
optionId: "default"
|
|
10373
|
-
},
|
|
10374
|
-
{
|
|
10375
|
-
kind: "reject_once",
|
|
10376
|
-
name: "No, and tell the agent what to do differently",
|
|
10377
|
-
optionId: "reject_with_feedback",
|
|
10378
|
-
_meta: { customInput: true }
|
|
10379
10379
|
}
|
|
10380
10380
|
);
|
|
10381
|
+
const previousIndex = previousMode ? options.findIndex((opt) => opt.optionId === previousMode) : -1;
|
|
10382
|
+
if (previousIndex > 0) {
|
|
10383
|
+
const [previous] = options.splice(previousIndex, 1);
|
|
10384
|
+
const continueLabel = CONTINUE_LABELS[previous.optionId];
|
|
10385
|
+
options.unshift(
|
|
10386
|
+
continueLabel ? { ...previous, name: continueLabel } : previous
|
|
10387
|
+
);
|
|
10388
|
+
} else if (previousIndex === 0) {
|
|
10389
|
+
const continueLabel = CONTINUE_LABELS[options[0].optionId];
|
|
10390
|
+
if (continueLabel) {
|
|
10391
|
+
options[0] = { ...options[0], name: continueLabel };
|
|
10392
|
+
}
|
|
10393
|
+
}
|
|
10394
|
+
options.push({
|
|
10395
|
+
kind: "reject_once",
|
|
10396
|
+
name: "No, and tell the agent what to do differently",
|
|
10397
|
+
optionId: "reject_with_feedback",
|
|
10398
|
+
_meta: { customInput: true }
|
|
10399
|
+
});
|
|
10381
10400
|
return options;
|
|
10382
10401
|
}
|
|
10383
10402
|
|
|
@@ -10432,13 +10451,13 @@ async function validatePlanContent(planText, context) {
|
|
|
10432
10451
|
return { valid: true };
|
|
10433
10452
|
}
|
|
10434
10453
|
async function requestPlanApproval(context, updatedInput) {
|
|
10435
|
-
const { client, sessionId, toolUseID } = context;
|
|
10454
|
+
const { client, sessionId, toolUseID, session } = context;
|
|
10436
10455
|
const toolInfo = toolInfoFromToolUse({
|
|
10437
10456
|
name: context.toolName,
|
|
10438
10457
|
input: updatedInput
|
|
10439
10458
|
});
|
|
10440
10459
|
return await client.requestPermission({
|
|
10441
|
-
options: buildExitPlanModePermissionOptions(),
|
|
10460
|
+
options: buildExitPlanModePermissionOptions(session.modeBeforePlan),
|
|
10442
10461
|
sessionId,
|
|
10443
10462
|
toolCall: {
|
|
10444
10463
|
toolCallId: toolUseID,
|
|
@@ -17088,6 +17107,9 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
17088
17107
|
}
|
|
17089
17108
|
const previousMode = this.session.permissionMode;
|
|
17090
17109
|
this.session.permissionMode = modeId;
|
|
17110
|
+
if (modeId === "plan" && previousMode !== "plan") {
|
|
17111
|
+
this.session.modeBeforePlan = previousMode;
|
|
17112
|
+
}
|
|
17091
17113
|
try {
|
|
17092
17114
|
await this.session.query.setPermissionMode(modeId);
|
|
17093
17115
|
} catch (error) {
|
|
@@ -17310,7 +17332,11 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
17310
17332
|
createOnModeChange() {
|
|
17311
17333
|
return async (newMode) => {
|
|
17312
17334
|
if (this.session) {
|
|
17335
|
+
const previousMode = this.session.permissionMode;
|
|
17313
17336
|
this.session.permissionMode = newMode;
|
|
17337
|
+
if (newMode === "plan" && previousMode !== "plan") {
|
|
17338
|
+
this.session.modeBeforePlan = previousMode;
|
|
17339
|
+
}
|
|
17314
17340
|
}
|
|
17315
17341
|
await this.updateConfigOption("mode", newMode);
|
|
17316
17342
|
};
|