@posthog/agent 2.3.261 → 2.3.267
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/codex/models.d.ts +7 -0
- package/dist/adapters/codex/models.js +13 -0
- package/dist/adapters/codex/models.js.map +1 -0
- package/dist/adapters/reasoning-effort.d.ts +10 -0
- package/dist/adapters/reasoning-effort.js +51 -0
- package/dist/adapters/reasoning-effort.js.map +1 -0
- package/dist/agent.js +16 -2
- package/dist/agent.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/posthog-api.js +5 -1
- package/dist/posthog-api.js.map +1 -1
- package/dist/server/agent-server.d.ts +17 -0
- package/dist/server/agent-server.js +199 -28
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +335 -128
- package/dist/server/bin.cjs.map +1 -1
- package/package.json +7 -3
- package/src/acp-extensions.ts +3 -0
- package/src/adapters/claude/permissions/permission-handlers.ts +11 -5
- package/src/adapters/codex/models.ts +16 -0
- package/src/adapters/codex/spawn.ts +5 -0
- package/src/adapters/reasoning-effort.ts +35 -0
- package/src/server/agent-server.test.ts +70 -11
- package/src/server/agent-server.ts +257 -37
- package/src/server/bin.ts +24 -0
- package/src/server/schemas.test.ts +52 -0
- package/src/server/schemas.ts +16 -0
- package/src/server/types.ts +3 -0
- package/src/test/mocks/msw-handlers.ts +24 -0
package/dist/index.d.ts
CHANGED
|
@@ -46,6 +46,8 @@ declare const POSTHOG_NOTIFICATIONS: {
|
|
|
46
46
|
readonly COMPACT_BOUNDARY: "_posthog/compact_boundary";
|
|
47
47
|
/** Token usage update for a session turn */
|
|
48
48
|
readonly USAGE_UPDATE: "_posthog/usage_update";
|
|
49
|
+
/** Response to a relayed permission request (plan approval, question) */
|
|
50
|
+
readonly PERMISSION_RESPONSE: "_posthog/permission_response";
|
|
49
51
|
};
|
|
50
52
|
type NotificationMethod = (typeof POSTHOG_NOTIFICATIONS)[keyof typeof POSTHOG_NOTIFICATIONS];
|
|
51
53
|
/**
|
package/dist/index.js
CHANGED
|
@@ -33,7 +33,9 @@ var POSTHOG_NOTIFICATIONS = {
|
|
|
33
33
|
/** Marks a boundary for log compaction */
|
|
34
34
|
COMPACT_BOUNDARY: "_posthog/compact_boundary",
|
|
35
35
|
/** Token usage update for a session turn */
|
|
36
|
-
USAGE_UPDATE: "_posthog/usage_update"
|
|
36
|
+
USAGE_UPDATE: "_posthog/usage_update",
|
|
37
|
+
/** Response to a relayed permission request (plan approval, question) */
|
|
38
|
+
PERMISSION_RESPONSE: "_posthog/permission_response"
|
|
37
39
|
};
|
|
38
40
|
function isNotification(method, notification) {
|
|
39
41
|
if (!method) return false;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/acp-extensions.ts","../src/adapters/claude/mcp/tool-metadata.ts"],"sourcesContent":["/**\n * PostHog-specific ACP extensions.\n *\n * These follow the ACP extensibility model:\n * - Custom notification methods are prefixed with `_posthog/`\n * - Custom data can be attached via `_meta` fields\n *\n * See: https://agentclientprotocol.com/docs/extensibility\n */\n\n/**\n * Custom notification methods for PostHog-specific events.\n * Used with AgentSideConnection.extNotification() or Client.extNotification()\n */\nexport const POSTHOG_NOTIFICATIONS = {\n /** Git branch was created for a task */\n BRANCH_CREATED: \"_posthog/branch_created\",\n\n /** Task run has started execution */\n RUN_STARTED: \"_posthog/run_started\",\n\n /** Task has completed (success or failure) */\n TASK_COMPLETE: \"_posthog/task_complete\",\n\n /** Agent finished processing a turn (prompt returned, waiting for next input) */\n TURN_COMPLETE: \"_posthog/turn_complete\",\n\n /** Error occurred during task execution */\n ERROR: \"_posthog/error\",\n\n /** Console/log output from the agent */\n CONSOLE: \"_posthog/console\",\n\n /** Maps taskRunId to agent's sessionId and adapter type (for resumption) */\n SDK_SESSION: \"_posthog/sdk_session\",\n\n /** Tree state snapshot captured (git tree hash + file archive) */\n TREE_SNAPSHOT: \"_posthog/tree_snapshot\",\n\n /** Agent mode changed (interactive/background) */\n MODE_CHANGE: \"_posthog/mode_change\",\n\n /** Request to resume a session from previous state */\n SESSION_RESUME: \"_posthog/session/resume\",\n\n /** User message sent from client to agent */\n USER_MESSAGE: \"_posthog/user_message\",\n\n /** Request to cancel current operation */\n CANCEL: \"_posthog/cancel\",\n\n /** Request to close the session */\n CLOSE: \"_posthog/close\",\n\n /** Agent status update (thinking, working, etc.) */\n STATUS: \"_posthog/status\",\n\n /** Task-level notification (progress, milestones) */\n TASK_NOTIFICATION: \"_posthog/task_notification\",\n\n /** Marks a boundary for log compaction */\n COMPACT_BOUNDARY: \"_posthog/compact_boundary\",\n\n /** Token usage update for a session turn */\n USAGE_UPDATE: \"_posthog/usage_update\",\n} as const;\n\ntype NotificationMethod =\n (typeof POSTHOG_NOTIFICATIONS)[keyof typeof POSTHOG_NOTIFICATIONS];\n\n/**\n * Check if an ACP method matches a PostHog notification, handling the\n * possible `__posthog/` double-prefix from extNotification().\n */\nexport function isNotification(\n method: string | undefined,\n notification: NotificationMethod,\n): boolean {\n if (!method) return false;\n return method === notification || method === `_${notification}`;\n}\n","import type { McpServerStatus, Query } from \"@anthropic-ai/claude-agent-sdk\";\nimport { Logger } from \"../../../utils/logger\";\n\nexport interface McpToolMetadata {\n readOnly: boolean;\n name: string;\n description?: string;\n}\n\nconst mcpToolMetadataCache: Map<string, McpToolMetadata> = new Map();\n\nconst PENDING_RETRY_INTERVAL_MS = 1_000;\nconst PENDING_MAX_RETRIES = 10;\n\nfunction buildToolKey(serverName: string, toolName: string): string {\n return `mcp__${serverName}__${toolName}`;\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function fetchMcpToolMetadata(\n q: Query,\n logger: Logger = new Logger({ debug: false, prefix: \"[McpToolMetadata]\" }),\n): Promise<void> {\n let retries = 0;\n\n while (retries <= PENDING_MAX_RETRIES) {\n let statuses: McpServerStatus[];\n try {\n statuses = await q.mcpServerStatus();\n } catch (error) {\n logger.error(\"Failed to fetch MCP server status\", {\n error: error instanceof Error ? error.message : String(error),\n });\n return;\n }\n\n const pendingServers = statuses.filter((s) => s.status === \"pending\");\n\n for (const server of statuses) {\n if (server.status !== \"connected\" || !server.tools) {\n continue;\n }\n\n let readOnlyCount = 0;\n for (const tool of server.tools) {\n const toolKey = buildToolKey(server.name, tool.name);\n const readOnly = tool.annotations?.readOnly === true;\n\n mcpToolMetadataCache.set(toolKey, {\n readOnly,\n name: tool.name,\n description: tool.description,\n });\n if (readOnly) readOnlyCount++;\n }\n\n logger.info(\"Fetched MCP tool metadata\", {\n serverName: server.name,\n toolCount: server.tools.length,\n readOnlyCount,\n });\n }\n\n if (pendingServers.length === 0) {\n return;\n }\n\n retries++;\n if (retries > PENDING_MAX_RETRIES) {\n logger.warn(\"Gave up waiting for pending MCP servers\", {\n pendingServers: pendingServers.map((s) => s.name),\n });\n return;\n }\n\n logger.info(\"Waiting for pending MCP servers\", {\n pendingServers: pendingServers.map((s) => s.name),\n retry: retries,\n });\n await delay(PENDING_RETRY_INTERVAL_MS);\n }\n}\n\nexport function getMcpToolMetadata(\n toolName: string,\n): McpToolMetadata | undefined {\n return mcpToolMetadataCache.get(toolName);\n}\n\nexport function isMcpToolReadOnly(toolName: string): boolean {\n const metadata = mcpToolMetadataCache.get(toolName);\n return metadata?.readOnly === true;\n}\n\nexport function getConnectedMcpServerNames(): string[] {\n const names = new Set<string>();\n for (const key of mcpToolMetadataCache.keys()) {\n const parts = key.split(\"__\");\n if (parts.length >= 3) names.add(parts[1]);\n }\n return [...names];\n}\n\nexport function clearMcpToolMetadataCache(): void {\n mcpToolMetadataCache.clear();\n}\n"],"mappings":";AAcO,IAAM,wBAAwB;AAAA;AAAA,EAEnC,gBAAgB;AAAA;AAAA,EAGhB,aAAa;AAAA;AAAA,EAGb,eAAe;AAAA;AAAA,EAGf,eAAe;AAAA;AAAA,EAGf,OAAO;AAAA;AAAA,EAGP,SAAS;AAAA;AAAA,EAGT,aAAa;AAAA;AAAA,EAGb,eAAe;AAAA;AAAA,EAGf,aAAa;AAAA;AAAA,EAGb,gBAAgB;AAAA;AAAA,EAGhB,cAAc;AAAA;AAAA,EAGd,QAAQ;AAAA;AAAA,EAGR,OAAO;AAAA;AAAA,EAGP,QAAQ;AAAA;AAAA,EAGR,mBAAmB;AAAA;AAAA,EAGnB,kBAAkB;AAAA;AAAA,EAGlB,cAAc;
|
|
1
|
+
{"version":3,"sources":["../src/acp-extensions.ts","../src/adapters/claude/mcp/tool-metadata.ts"],"sourcesContent":["/**\n * PostHog-specific ACP extensions.\n *\n * These follow the ACP extensibility model:\n * - Custom notification methods are prefixed with `_posthog/`\n * - Custom data can be attached via `_meta` fields\n *\n * See: https://agentclientprotocol.com/docs/extensibility\n */\n\n/**\n * Custom notification methods for PostHog-specific events.\n * Used with AgentSideConnection.extNotification() or Client.extNotification()\n */\nexport const POSTHOG_NOTIFICATIONS = {\n /** Git branch was created for a task */\n BRANCH_CREATED: \"_posthog/branch_created\",\n\n /** Task run has started execution */\n RUN_STARTED: \"_posthog/run_started\",\n\n /** Task has completed (success or failure) */\n TASK_COMPLETE: \"_posthog/task_complete\",\n\n /** Agent finished processing a turn (prompt returned, waiting for next input) */\n TURN_COMPLETE: \"_posthog/turn_complete\",\n\n /** Error occurred during task execution */\n ERROR: \"_posthog/error\",\n\n /** Console/log output from the agent */\n CONSOLE: \"_posthog/console\",\n\n /** Maps taskRunId to agent's sessionId and adapter type (for resumption) */\n SDK_SESSION: \"_posthog/sdk_session\",\n\n /** Tree state snapshot captured (git tree hash + file archive) */\n TREE_SNAPSHOT: \"_posthog/tree_snapshot\",\n\n /** Agent mode changed (interactive/background) */\n MODE_CHANGE: \"_posthog/mode_change\",\n\n /** Request to resume a session from previous state */\n SESSION_RESUME: \"_posthog/session/resume\",\n\n /** User message sent from client to agent */\n USER_MESSAGE: \"_posthog/user_message\",\n\n /** Request to cancel current operation */\n CANCEL: \"_posthog/cancel\",\n\n /** Request to close the session */\n CLOSE: \"_posthog/close\",\n\n /** Agent status update (thinking, working, etc.) */\n STATUS: \"_posthog/status\",\n\n /** Task-level notification (progress, milestones) */\n TASK_NOTIFICATION: \"_posthog/task_notification\",\n\n /** Marks a boundary for log compaction */\n COMPACT_BOUNDARY: \"_posthog/compact_boundary\",\n\n /** Token usage update for a session turn */\n USAGE_UPDATE: \"_posthog/usage_update\",\n\n /** Response to a relayed permission request (plan approval, question) */\n PERMISSION_RESPONSE: \"_posthog/permission_response\",\n} as const;\n\ntype NotificationMethod =\n (typeof POSTHOG_NOTIFICATIONS)[keyof typeof POSTHOG_NOTIFICATIONS];\n\n/**\n * Check if an ACP method matches a PostHog notification, handling the\n * possible `__posthog/` double-prefix from extNotification().\n */\nexport function isNotification(\n method: string | undefined,\n notification: NotificationMethod,\n): boolean {\n if (!method) return false;\n return method === notification || method === `_${notification}`;\n}\n","import type { McpServerStatus, Query } from \"@anthropic-ai/claude-agent-sdk\";\nimport { Logger } from \"../../../utils/logger\";\n\nexport interface McpToolMetadata {\n readOnly: boolean;\n name: string;\n description?: string;\n}\n\nconst mcpToolMetadataCache: Map<string, McpToolMetadata> = new Map();\n\nconst PENDING_RETRY_INTERVAL_MS = 1_000;\nconst PENDING_MAX_RETRIES = 10;\n\nfunction buildToolKey(serverName: string, toolName: string): string {\n return `mcp__${serverName}__${toolName}`;\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function fetchMcpToolMetadata(\n q: Query,\n logger: Logger = new Logger({ debug: false, prefix: \"[McpToolMetadata]\" }),\n): Promise<void> {\n let retries = 0;\n\n while (retries <= PENDING_MAX_RETRIES) {\n let statuses: McpServerStatus[];\n try {\n statuses = await q.mcpServerStatus();\n } catch (error) {\n logger.error(\"Failed to fetch MCP server status\", {\n error: error instanceof Error ? error.message : String(error),\n });\n return;\n }\n\n const pendingServers = statuses.filter((s) => s.status === \"pending\");\n\n for (const server of statuses) {\n if (server.status !== \"connected\" || !server.tools) {\n continue;\n }\n\n let readOnlyCount = 0;\n for (const tool of server.tools) {\n const toolKey = buildToolKey(server.name, tool.name);\n const readOnly = tool.annotations?.readOnly === true;\n\n mcpToolMetadataCache.set(toolKey, {\n readOnly,\n name: tool.name,\n description: tool.description,\n });\n if (readOnly) readOnlyCount++;\n }\n\n logger.info(\"Fetched MCP tool metadata\", {\n serverName: server.name,\n toolCount: server.tools.length,\n readOnlyCount,\n });\n }\n\n if (pendingServers.length === 0) {\n return;\n }\n\n retries++;\n if (retries > PENDING_MAX_RETRIES) {\n logger.warn(\"Gave up waiting for pending MCP servers\", {\n pendingServers: pendingServers.map((s) => s.name),\n });\n return;\n }\n\n logger.info(\"Waiting for pending MCP servers\", {\n pendingServers: pendingServers.map((s) => s.name),\n retry: retries,\n });\n await delay(PENDING_RETRY_INTERVAL_MS);\n }\n}\n\nexport function getMcpToolMetadata(\n toolName: string,\n): McpToolMetadata | undefined {\n return mcpToolMetadataCache.get(toolName);\n}\n\nexport function isMcpToolReadOnly(toolName: string): boolean {\n const metadata = mcpToolMetadataCache.get(toolName);\n return metadata?.readOnly === true;\n}\n\nexport function getConnectedMcpServerNames(): string[] {\n const names = new Set<string>();\n for (const key of mcpToolMetadataCache.keys()) {\n const parts = key.split(\"__\");\n if (parts.length >= 3) names.add(parts[1]);\n }\n return [...names];\n}\n\nexport function clearMcpToolMetadataCache(): void {\n mcpToolMetadataCache.clear();\n}\n"],"mappings":";AAcO,IAAM,wBAAwB;AAAA;AAAA,EAEnC,gBAAgB;AAAA;AAAA,EAGhB,aAAa;AAAA;AAAA,EAGb,eAAe;AAAA;AAAA,EAGf,eAAe;AAAA;AAAA,EAGf,OAAO;AAAA;AAAA,EAGP,SAAS;AAAA;AAAA,EAGT,aAAa;AAAA;AAAA,EAGb,eAAe;AAAA;AAAA,EAGf,aAAa;AAAA;AAAA,EAGb,gBAAgB;AAAA;AAAA,EAGhB,cAAc;AAAA;AAAA,EAGd,QAAQ;AAAA;AAAA,EAGR,OAAO;AAAA;AAAA,EAGP,QAAQ;AAAA;AAAA,EAGR,mBAAmB;AAAA;AAAA,EAGnB,kBAAkB;AAAA;AAAA,EAGlB,cAAc;AAAA;AAAA,EAGd,qBAAqB;AACvB;AASO,SAAS,eACd,QACA,cACS;AACT,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,WAAW,gBAAgB,WAAW,IAAI,YAAY;AAC/D;;;AC1EA,IAAM,uBAAqD,oBAAI,IAAI;AA6E5D,SAAS,mBACd,UAC6B;AAC7B,SAAO,qBAAqB,IAAI,QAAQ;AAC1C;AAEO,SAAS,kBAAkB,UAA2B;AAC3D,QAAM,WAAW,qBAAqB,IAAI,QAAQ;AAClD,SAAO,UAAU,aAAa;AAChC;","names":[]}
|
package/dist/posthog-api.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// package.json
|
|
2
2
|
var package_default = {
|
|
3
3
|
name: "@posthog/agent",
|
|
4
|
-
version: "2.3.
|
|
4
|
+
version: "2.3.267",
|
|
5
5
|
repository: "https://github.com/PostHog/code",
|
|
6
6
|
description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
|
|
7
7
|
exports: {
|
|
@@ -49,6 +49,10 @@ var package_default = {
|
|
|
49
49
|
types: "./dist/adapters/claude/session/models.d.ts",
|
|
50
50
|
import: "./dist/adapters/claude/session/models.js"
|
|
51
51
|
},
|
|
52
|
+
"./adapters/reasoning-effort": {
|
|
53
|
+
types: "./dist/adapters/reasoning-effort.d.ts",
|
|
54
|
+
import: "./dist/adapters/reasoning-effort.js"
|
|
55
|
+
},
|
|
52
56
|
"./execution-mode": {
|
|
53
57
|
types: "./dist/execution-mode.d.ts",
|
|
54
58
|
import: "./dist/execution-mode.js"
|
package/dist/posthog-api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../package.json","../src/utils/gateway.ts","../src/posthog-api.ts"],"sourcesContent":["{\n \"name\": \"@posthog/agent\",\n \"version\": \"2.3.261\",\n \"repository\": \"https://github.com/PostHog/code\",\n \"description\": \"TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n },\n \"./agent\": {\n \"types\": \"./dist/agent.d.ts\",\n \"import\": \"./dist/agent.js\"\n },\n \"./gateway-models\": {\n \"types\": \"./dist/gateway-models.d.ts\",\n \"import\": \"./dist/gateway-models.js\"\n },\n \"./posthog-api\": {\n \"types\": \"./dist/posthog-api.d.ts\",\n \"import\": \"./dist/posthog-api.js\"\n },\n \"./types\": {\n \"types\": \"./dist/types.d.ts\",\n \"import\": \"./dist/types.js\"\n },\n \"./adapters/claude/questions/utils\": {\n \"types\": \"./dist/adapters/claude/questions/utils.d.ts\",\n \"import\": \"./dist/adapters/claude/questions/utils.js\"\n },\n \"./adapters/claude/permissions/permission-options\": {\n \"types\": \"./dist/adapters/claude/permissions/permission-options.d.ts\",\n \"import\": \"./dist/adapters/claude/permissions/permission-options.js\"\n },\n \"./adapters/claude/tools\": {\n \"types\": \"./dist/adapters/claude/tools.d.ts\",\n \"import\": \"./dist/adapters/claude/tools.js\"\n },\n \"./adapters/claude/conversion/tool-use-to-acp\": {\n \"types\": \"./dist/adapters/claude/conversion/tool-use-to-acp.d.ts\",\n \"import\": \"./dist/adapters/claude/conversion/tool-use-to-acp.js\"\n },\n \"./adapters/claude/session/jsonl-hydration\": {\n \"types\": \"./dist/adapters/claude/session/jsonl-hydration.d.ts\",\n \"import\": \"./dist/adapters/claude/session/jsonl-hydration.js\"\n },\n \"./adapters/claude/session/models\": {\n \"types\": \"./dist/adapters/claude/session/models.d.ts\",\n \"import\": \"./dist/adapters/claude/session/models.js\"\n },\n \"./execution-mode\": {\n \"types\": \"./dist/execution-mode.d.ts\",\n \"import\": \"./dist/execution-mode.js\"\n },\n \"./server\": {\n \"types\": \"./dist/server/agent-server.d.ts\",\n \"import\": \"./dist/server/agent-server.js\"\n }\n },\n \"bin\": {\n \"agent-server\": \"./dist/server/bin.cjs\"\n },\n \"type\": \"module\",\n \"keywords\": [\n \"posthog\",\n \"claude\",\n \"agent\",\n \"ai\",\n \"git\",\n \"typescript\"\n ],\n \"author\": \"PostHog\",\n \"license\": \"SEE LICENSE IN LICENSE\",\n \"scripts\": {\n \"build\": \"node ../../scripts/rimraf.mjs dist && tsup\",\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"typecheck\": \"pnpm exec tsc --noEmit\",\n \"prepublishOnly\": \"pnpm run build\",\n \"clean\": \"node ../../scripts/rimraf.mjs dist .turbo\"\n },\n \"engines\": {\n \"node\": \">=20.0.0\"\n },\n \"devDependencies\": {\n \"@posthog/shared\": \"workspace:*\",\n \"@posthog/git\": \"workspace:*\",\n \"@types/bun\": \"latest\",\n \"@types/tar\": \"^6.1.13\",\n \"msw\": \"^2.12.7\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.20.6\",\n \"typescript\": \"^5.5.0\",\n \"vitest\": \"^2.1.8\"\n },\n \"dependencies\": {\n \"@agentclientprotocol/sdk\": \"0.16.1\",\n \"ajv\": \"^8.17.1\",\n \"@anthropic-ai/claude-agent-sdk\": \"0.2.76\",\n \"@anthropic-ai/sdk\": \"^0.78.0\",\n \"@hono/node-server\": \"^1.19.9\",\n \"@opentelemetry/api-logs\": \"^0.208.0\",\n \"@opentelemetry/exporter-logs-otlp-http\": \"^0.208.0\",\n \"@opentelemetry/resources\": \"^2.0.0\",\n \"@opentelemetry/sdk-logs\": \"^0.208.0\",\n \"@opentelemetry/semantic-conventions\": \"^1.28.0\",\n \"@types/jsonwebtoken\": \"^9.0.10\",\n \"commander\": \"^14.0.2\",\n \"hono\": \"^4.11.7\",\n \"jsonwebtoken\": \"^9.0.2\",\n \"minimatch\": \"^10.0.3\",\n \"tar\": \"^7.5.0\",\n \"uuid\": \"13.0.0\",\n \"yoga-wasm-web\": \"^0.3.3\",\n \"zod\": \"^4.2.0\"\n },\n \"files\": [\n \"dist/**/*\",\n \"src/**/*\",\n \"README.md\",\n \"CLAUDE.md\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n","export type GatewayProduct = \"posthog_code\" | \"background_agents\";\n\nexport function getLlmGatewayUrl(\n posthogHost: string,\n product: GatewayProduct = \"posthog_code\",\n): string {\n const url = new URL(posthogHost);\n const hostname = url.hostname;\n\n // Local development (normalize 127.0.0.1 to localhost)\n if (hostname === \"localhost\" || hostname === \"127.0.0.1\") {\n return `${url.protocol}//localhost:3308/${product}`;\n }\n\n // Docker containers accessing host\n if (hostname === \"host.docker.internal\") {\n return `${url.protocol}//host.docker.internal:3308/${product}`;\n }\n\n // Production - extract region from hostname, default to US\n const region = hostname.match(/^(us|eu)\\.posthog\\.com$/)?.[1] ?? \"us\";\n return `https://gateway.${region}.posthog.com/${product}`;\n}\n","import packageJson from \"../package.json\" with { type: \"json\" };\nimport type {\n ArtifactType,\n PostHogAPIConfig,\n StoredEntry,\n Task,\n TaskRun,\n TaskRunArtifact,\n} from \"./types\";\nimport { getLlmGatewayUrl } from \"./utils/gateway\";\n\nexport { getLlmGatewayUrl };\n\nconst DEFAULT_USER_AGENT = `posthog/agent.hog.dev; version: ${packageJson.version}`;\n\nexport interface TaskArtifactUploadPayload {\n name: string;\n type: ArtifactType;\n content: string;\n content_type?: string;\n}\n\nexport type TaskRunUpdate = Partial<\n Pick<\n TaskRun,\n | \"status\"\n | \"branch\"\n | \"stage\"\n | \"error_message\"\n | \"output\"\n | \"state\"\n | \"environment\"\n >\n>;\n\nexport class PostHogAPIClient {\n private config: PostHogAPIConfig;\n\n constructor(config: PostHogAPIConfig) {\n this.config = config;\n }\n\n private get baseUrl(): string {\n const host = this.config.apiUrl.endsWith(\"/\")\n ? this.config.apiUrl.slice(0, -1)\n : this.config.apiUrl;\n return host;\n }\n\n private isAuthFailure(status: number): boolean {\n return status === 401 || status === 403;\n }\n\n private async resolveApiKey(forceRefresh = false): Promise<string> {\n if (forceRefresh && this.config.refreshApiKey) {\n return this.config.refreshApiKey();\n }\n\n return this.config.getApiKey();\n }\n\n private async buildHeaders(\n options: RequestInit,\n forceRefresh = false,\n ): Promise<Headers> {\n const headers = new Headers(options.headers);\n headers.set(\n \"Authorization\",\n `Bearer ${await this.resolveApiKey(forceRefresh)}`,\n );\n headers.set(\"Content-Type\", \"application/json\");\n headers.set(\"User-Agent\", this.config.userAgent ?? DEFAULT_USER_AGENT);\n return headers;\n }\n\n private async performRequest(\n endpoint: string,\n options: RequestInit,\n forceRefresh = false,\n ): Promise<Response> {\n const url = `${this.baseUrl}${endpoint}`;\n\n return fetch(url, {\n ...options,\n headers: await this.buildHeaders(options, forceRefresh),\n });\n }\n\n private async performRequestWithRetry(\n endpoint: string,\n options: RequestInit = {},\n ): Promise<Response> {\n let response = await this.performRequest(endpoint, options);\n\n if (!response.ok && this.isAuthFailure(response.status)) {\n response = await this.performRequest(endpoint, options, true);\n }\n\n return response;\n }\n\n private async apiRequest<T>(\n endpoint: string,\n options: RequestInit = {},\n ): Promise<T> {\n const response = await this.performRequestWithRetry(endpoint, options);\n\n if (!response.ok) {\n let errorMessage: string;\n try {\n const errorResponse = await response.json();\n errorMessage = `Failed request: [${response.status}] ${JSON.stringify(errorResponse)}`;\n } catch {\n errorMessage = `Failed request: [${response.status}] ${response.statusText}`;\n }\n throw new Error(errorMessage);\n }\n\n return response.json();\n }\n\n private getTeamId(): number {\n return this.config.projectId;\n }\n\n async getApiKey(forceRefresh = false): Promise<string> {\n return this.resolveApiKey(forceRefresh);\n }\n\n getLlmGatewayUrl(): string {\n return getLlmGatewayUrl(this.baseUrl);\n }\n\n async getTask(taskId: string): Promise<Task> {\n const teamId = this.getTeamId();\n return this.apiRequest<Task>(`/api/projects/${teamId}/tasks/${taskId}/`);\n }\n\n async getTaskRun(taskId: string, runId: string): Promise<TaskRun> {\n const teamId = this.getTeamId();\n return this.apiRequest<TaskRun>(\n `/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/`,\n );\n }\n\n async updateTaskRun(\n taskId: string,\n runId: string,\n payload: TaskRunUpdate,\n ): Promise<TaskRun> {\n const teamId = this.getTeamId();\n return this.apiRequest<TaskRun>(\n `/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/`,\n {\n method: \"PATCH\",\n body: JSON.stringify(payload),\n },\n );\n }\n\n async setTaskRunOutput(\n taskId: string,\n runId: string,\n output: Record<string, unknown>,\n ): Promise<TaskRun> {\n return this.apiRequest(\n `/api/projects/${this.getTeamId()}/tasks/${taskId}/runs/${runId}/set_output/`,\n {\n method: \"PATCH\",\n body: JSON.stringify(output),\n },\n );\n }\n\n async appendTaskRunLog(\n taskId: string,\n runId: string,\n entries: StoredEntry[],\n ): Promise<TaskRun> {\n const teamId = this.getTeamId();\n return this.apiRequest<TaskRun>(\n `/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/append_log/`,\n {\n method: \"POST\",\n body: JSON.stringify({ entries }),\n },\n );\n }\n\n async relayMessage(\n taskId: string,\n runId: string,\n text: string,\n ): Promise<void> {\n const teamId = this.getTeamId();\n await this.apiRequest<{ status: string }>(\n `/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/relay_message/`,\n {\n method: \"POST\",\n body: JSON.stringify({ text }),\n },\n );\n }\n\n async uploadTaskArtifacts(\n taskId: string,\n runId: string,\n artifacts: TaskArtifactUploadPayload[],\n ): Promise<TaskRunArtifact[]> {\n if (!artifacts.length) {\n return [];\n }\n\n const teamId = this.getTeamId();\n const response = await this.apiRequest<{ artifacts: TaskRunArtifact[] }>(\n `/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/artifacts/`,\n {\n method: \"POST\",\n body: JSON.stringify({ artifacts }),\n },\n );\n\n return response.artifacts ?? [];\n }\n\n async getArtifactPresignedUrl(\n taskId: string,\n runId: string,\n storagePath: string,\n ): Promise<string | null> {\n const teamId = this.getTeamId();\n try {\n const response = await this.apiRequest<{\n url: string;\n expires_in: number;\n }>(\n `/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/artifacts/presign/`,\n {\n method: \"POST\",\n body: JSON.stringify({ storage_path: storagePath }),\n },\n );\n return response.url;\n } catch {\n return null;\n }\n }\n\n /**\n * Download artifact content by storage path\n * Gets a presigned URL and fetches the content\n */\n async downloadArtifact(\n taskId: string,\n runId: string,\n storagePath: string,\n ): Promise<ArrayBuffer | null> {\n const url = await this.getArtifactPresignedUrl(taskId, runId, storagePath);\n if (!url) {\n return null;\n }\n\n try {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to download artifact: ${response.status}`);\n }\n return response.arrayBuffer();\n } catch {\n return null;\n }\n }\n\n /**\n * Fetch logs for a task run via the logs API endpoint\n * @param taskRun - The task run to fetch logs for\n * @returns Array of stored entries, or empty array if no logs available\n */\n async fetchTaskRunLogs(taskRun: TaskRun): Promise<StoredEntry[]> {\n const teamId = this.getTeamId();\n const endpoint = `/api/projects/${teamId}/tasks/${taskRun.task}/runs/${taskRun.id}/logs`;\n\n try {\n const response = await this.performRequestWithRetry(endpoint);\n\n if (!response.ok) {\n if (response.status === 404) {\n return [];\n }\n throw new Error(\n `Failed to fetch logs: ${response.status} ${response.statusText}`,\n );\n }\n\n const content = await response.text();\n\n if (!content.trim()) {\n return [];\n }\n\n // Parse newline-delimited JSON\n return content\n .trim()\n .split(\"\\n\")\n .map((line) => JSON.parse(line) as StoredEntry);\n } catch (error) {\n throw new Error(\n `Failed to fetch task run logs: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../package.json","../src/utils/gateway.ts","../src/posthog-api.ts"],"sourcesContent":["{\n \"name\": \"@posthog/agent\",\n \"version\": \"2.3.267\",\n \"repository\": \"https://github.com/PostHog/code\",\n \"description\": \"TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n },\n \"./agent\": {\n \"types\": \"./dist/agent.d.ts\",\n \"import\": \"./dist/agent.js\"\n },\n \"./gateway-models\": {\n \"types\": \"./dist/gateway-models.d.ts\",\n \"import\": \"./dist/gateway-models.js\"\n },\n \"./posthog-api\": {\n \"types\": \"./dist/posthog-api.d.ts\",\n \"import\": \"./dist/posthog-api.js\"\n },\n \"./types\": {\n \"types\": \"./dist/types.d.ts\",\n \"import\": \"./dist/types.js\"\n },\n \"./adapters/claude/questions/utils\": {\n \"types\": \"./dist/adapters/claude/questions/utils.d.ts\",\n \"import\": \"./dist/adapters/claude/questions/utils.js\"\n },\n \"./adapters/claude/permissions/permission-options\": {\n \"types\": \"./dist/adapters/claude/permissions/permission-options.d.ts\",\n \"import\": \"./dist/adapters/claude/permissions/permission-options.js\"\n },\n \"./adapters/claude/tools\": {\n \"types\": \"./dist/adapters/claude/tools.d.ts\",\n \"import\": \"./dist/adapters/claude/tools.js\"\n },\n \"./adapters/claude/conversion/tool-use-to-acp\": {\n \"types\": \"./dist/adapters/claude/conversion/tool-use-to-acp.d.ts\",\n \"import\": \"./dist/adapters/claude/conversion/tool-use-to-acp.js\"\n },\n \"./adapters/claude/session/jsonl-hydration\": {\n \"types\": \"./dist/adapters/claude/session/jsonl-hydration.d.ts\",\n \"import\": \"./dist/adapters/claude/session/jsonl-hydration.js\"\n },\n \"./adapters/claude/session/models\": {\n \"types\": \"./dist/adapters/claude/session/models.d.ts\",\n \"import\": \"./dist/adapters/claude/session/models.js\"\n },\n \"./adapters/reasoning-effort\": {\n \"types\": \"./dist/adapters/reasoning-effort.d.ts\",\n \"import\": \"./dist/adapters/reasoning-effort.js\"\n },\n \"./execution-mode\": {\n \"types\": \"./dist/execution-mode.d.ts\",\n \"import\": \"./dist/execution-mode.js\"\n },\n \"./server\": {\n \"types\": \"./dist/server/agent-server.d.ts\",\n \"import\": \"./dist/server/agent-server.js\"\n }\n },\n \"bin\": {\n \"agent-server\": \"./dist/server/bin.cjs\"\n },\n \"type\": \"module\",\n \"keywords\": [\n \"posthog\",\n \"claude\",\n \"agent\",\n \"ai\",\n \"git\",\n \"typescript\"\n ],\n \"author\": \"PostHog\",\n \"license\": \"SEE LICENSE IN LICENSE\",\n \"scripts\": {\n \"build\": \"node ../../scripts/rimraf.mjs dist && tsup\",\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"typecheck\": \"pnpm exec tsc --noEmit\",\n \"prepublishOnly\": \"pnpm run build\",\n \"clean\": \"node ../../scripts/rimraf.mjs dist .turbo\"\n },\n \"engines\": {\n \"node\": \">=20.0.0\"\n },\n \"devDependencies\": {\n \"@posthog/shared\": \"workspace:*\",\n \"@posthog/git\": \"workspace:*\",\n \"@types/bun\": \"latest\",\n \"@types/tar\": \"^6.1.13\",\n \"msw\": \"^2.12.7\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.20.6\",\n \"typescript\": \"^5.5.0\",\n \"vitest\": \"^2.1.8\"\n },\n \"dependencies\": {\n \"@agentclientprotocol/sdk\": \"0.16.1\",\n \"ajv\": \"^8.17.1\",\n \"@anthropic-ai/claude-agent-sdk\": \"0.2.76\",\n \"@anthropic-ai/sdk\": \"^0.78.0\",\n \"@hono/node-server\": \"^1.19.9\",\n \"@opentelemetry/api-logs\": \"^0.208.0\",\n \"@opentelemetry/exporter-logs-otlp-http\": \"^0.208.0\",\n \"@opentelemetry/resources\": \"^2.0.0\",\n \"@opentelemetry/sdk-logs\": \"^0.208.0\",\n \"@opentelemetry/semantic-conventions\": \"^1.28.0\",\n \"@types/jsonwebtoken\": \"^9.0.10\",\n \"commander\": \"^14.0.2\",\n \"hono\": \"^4.11.7\",\n \"jsonwebtoken\": \"^9.0.2\",\n \"minimatch\": \"^10.0.3\",\n \"tar\": \"^7.5.0\",\n \"uuid\": \"13.0.0\",\n \"yoga-wasm-web\": \"^0.3.3\",\n \"zod\": \"^4.2.0\"\n },\n \"files\": [\n \"dist/**/*\",\n \"src/**/*\",\n \"README.md\",\n \"CLAUDE.md\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n","export type GatewayProduct = \"posthog_code\" | \"background_agents\";\n\nexport function getLlmGatewayUrl(\n posthogHost: string,\n product: GatewayProduct = \"posthog_code\",\n): string {\n const url = new URL(posthogHost);\n const hostname = url.hostname;\n\n // Local development (normalize 127.0.0.1 to localhost)\n if (hostname === \"localhost\" || hostname === \"127.0.0.1\") {\n return `${url.protocol}//localhost:3308/${product}`;\n }\n\n // Docker containers accessing host\n if (hostname === \"host.docker.internal\") {\n return `${url.protocol}//host.docker.internal:3308/${product}`;\n }\n\n // Production - extract region from hostname, default to US\n const region = hostname.match(/^(us|eu)\\.posthog\\.com$/)?.[1] ?? \"us\";\n return `https://gateway.${region}.posthog.com/${product}`;\n}\n","import packageJson from \"../package.json\" with { type: \"json\" };\nimport type {\n ArtifactType,\n PostHogAPIConfig,\n StoredEntry,\n Task,\n TaskRun,\n TaskRunArtifact,\n} from \"./types\";\nimport { getLlmGatewayUrl } from \"./utils/gateway\";\n\nexport { getLlmGatewayUrl };\n\nconst DEFAULT_USER_AGENT = `posthog/agent.hog.dev; version: ${packageJson.version}`;\n\nexport interface TaskArtifactUploadPayload {\n name: string;\n type: ArtifactType;\n content: string;\n content_type?: string;\n}\n\nexport type TaskRunUpdate = Partial<\n Pick<\n TaskRun,\n | \"status\"\n | \"branch\"\n | \"stage\"\n | \"error_message\"\n | \"output\"\n | \"state\"\n | \"environment\"\n >\n>;\n\nexport class PostHogAPIClient {\n private config: PostHogAPIConfig;\n\n constructor(config: PostHogAPIConfig) {\n this.config = config;\n }\n\n private get baseUrl(): string {\n const host = this.config.apiUrl.endsWith(\"/\")\n ? this.config.apiUrl.slice(0, -1)\n : this.config.apiUrl;\n return host;\n }\n\n private isAuthFailure(status: number): boolean {\n return status === 401 || status === 403;\n }\n\n private async resolveApiKey(forceRefresh = false): Promise<string> {\n if (forceRefresh && this.config.refreshApiKey) {\n return this.config.refreshApiKey();\n }\n\n return this.config.getApiKey();\n }\n\n private async buildHeaders(\n options: RequestInit,\n forceRefresh = false,\n ): Promise<Headers> {\n const headers = new Headers(options.headers);\n headers.set(\n \"Authorization\",\n `Bearer ${await this.resolveApiKey(forceRefresh)}`,\n );\n headers.set(\"Content-Type\", \"application/json\");\n headers.set(\"User-Agent\", this.config.userAgent ?? DEFAULT_USER_AGENT);\n return headers;\n }\n\n private async performRequest(\n endpoint: string,\n options: RequestInit,\n forceRefresh = false,\n ): Promise<Response> {\n const url = `${this.baseUrl}${endpoint}`;\n\n return fetch(url, {\n ...options,\n headers: await this.buildHeaders(options, forceRefresh),\n });\n }\n\n private async performRequestWithRetry(\n endpoint: string,\n options: RequestInit = {},\n ): Promise<Response> {\n let response = await this.performRequest(endpoint, options);\n\n if (!response.ok && this.isAuthFailure(response.status)) {\n response = await this.performRequest(endpoint, options, true);\n }\n\n return response;\n }\n\n private async apiRequest<T>(\n endpoint: string,\n options: RequestInit = {},\n ): Promise<T> {\n const response = await this.performRequestWithRetry(endpoint, options);\n\n if (!response.ok) {\n let errorMessage: string;\n try {\n const errorResponse = await response.json();\n errorMessage = `Failed request: [${response.status}] ${JSON.stringify(errorResponse)}`;\n } catch {\n errorMessage = `Failed request: [${response.status}] ${response.statusText}`;\n }\n throw new Error(errorMessage);\n }\n\n return response.json();\n }\n\n private getTeamId(): number {\n return this.config.projectId;\n }\n\n async getApiKey(forceRefresh = false): Promise<string> {\n return this.resolveApiKey(forceRefresh);\n }\n\n getLlmGatewayUrl(): string {\n return getLlmGatewayUrl(this.baseUrl);\n }\n\n async getTask(taskId: string): Promise<Task> {\n const teamId = this.getTeamId();\n return this.apiRequest<Task>(`/api/projects/${teamId}/tasks/${taskId}/`);\n }\n\n async getTaskRun(taskId: string, runId: string): Promise<TaskRun> {\n const teamId = this.getTeamId();\n return this.apiRequest<TaskRun>(\n `/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/`,\n );\n }\n\n async updateTaskRun(\n taskId: string,\n runId: string,\n payload: TaskRunUpdate,\n ): Promise<TaskRun> {\n const teamId = this.getTeamId();\n return this.apiRequest<TaskRun>(\n `/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/`,\n {\n method: \"PATCH\",\n body: JSON.stringify(payload),\n },\n );\n }\n\n async setTaskRunOutput(\n taskId: string,\n runId: string,\n output: Record<string, unknown>,\n ): Promise<TaskRun> {\n return this.apiRequest(\n `/api/projects/${this.getTeamId()}/tasks/${taskId}/runs/${runId}/set_output/`,\n {\n method: \"PATCH\",\n body: JSON.stringify(output),\n },\n );\n }\n\n async appendTaskRunLog(\n taskId: string,\n runId: string,\n entries: StoredEntry[],\n ): Promise<TaskRun> {\n const teamId = this.getTeamId();\n return this.apiRequest<TaskRun>(\n `/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/append_log/`,\n {\n method: \"POST\",\n body: JSON.stringify({ entries }),\n },\n );\n }\n\n async relayMessage(\n taskId: string,\n runId: string,\n text: string,\n ): Promise<void> {\n const teamId = this.getTeamId();\n await this.apiRequest<{ status: string }>(\n `/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/relay_message/`,\n {\n method: \"POST\",\n body: JSON.stringify({ text }),\n },\n );\n }\n\n async uploadTaskArtifacts(\n taskId: string,\n runId: string,\n artifacts: TaskArtifactUploadPayload[],\n ): Promise<TaskRunArtifact[]> {\n if (!artifacts.length) {\n return [];\n }\n\n const teamId = this.getTeamId();\n const response = await this.apiRequest<{ artifacts: TaskRunArtifact[] }>(\n `/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/artifacts/`,\n {\n method: \"POST\",\n body: JSON.stringify({ artifacts }),\n },\n );\n\n return response.artifacts ?? [];\n }\n\n async getArtifactPresignedUrl(\n taskId: string,\n runId: string,\n storagePath: string,\n ): Promise<string | null> {\n const teamId = this.getTeamId();\n try {\n const response = await this.apiRequest<{\n url: string;\n expires_in: number;\n }>(\n `/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/artifacts/presign/`,\n {\n method: \"POST\",\n body: JSON.stringify({ storage_path: storagePath }),\n },\n );\n return response.url;\n } catch {\n return null;\n }\n }\n\n /**\n * Download artifact content by storage path\n * Gets a presigned URL and fetches the content\n */\n async downloadArtifact(\n taskId: string,\n runId: string,\n storagePath: string,\n ): Promise<ArrayBuffer | null> {\n const url = await this.getArtifactPresignedUrl(taskId, runId, storagePath);\n if (!url) {\n return null;\n }\n\n try {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to download artifact: ${response.status}`);\n }\n return response.arrayBuffer();\n } catch {\n return null;\n }\n }\n\n /**\n * Fetch logs for a task run via the logs API endpoint\n * @param taskRun - The task run to fetch logs for\n * @returns Array of stored entries, or empty array if no logs available\n */\n async fetchTaskRunLogs(taskRun: TaskRun): Promise<StoredEntry[]> {\n const teamId = this.getTeamId();\n const endpoint = `/api/projects/${teamId}/tasks/${taskRun.task}/runs/${taskRun.id}/logs`;\n\n try {\n const response = await this.performRequestWithRetry(endpoint);\n\n if (!response.ok) {\n if (response.status === 404) {\n return [];\n }\n throw new Error(\n `Failed to fetch logs: ${response.status} ${response.statusText}`,\n );\n }\n\n const content = await response.text();\n\n if (!content.trim()) {\n return [];\n }\n\n // Parse newline-delimited JSON\n return content\n .trim()\n .split(\"\\n\")\n .map((line) => JSON.parse(line) as StoredEntry);\n } catch (error) {\n throw new Error(\n `Failed to fetch task run logs: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -42,6 +42,9 @@ interface AgentServerConfig {
|
|
|
42
42
|
baseBranch?: string;
|
|
43
43
|
claudeCode?: ClaudeCodeConfig;
|
|
44
44
|
allowedDomains?: string[];
|
|
45
|
+
runtimeAdapter?: "claude" | "codex";
|
|
46
|
+
model?: string;
|
|
47
|
+
reasoningEffort?: "low" | "medium" | "high" | "max";
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
declare class AgentServer {
|
|
@@ -57,10 +60,13 @@ declare class AgentServer {
|
|
|
57
60
|
private resumeState;
|
|
58
61
|
private initializationPromise;
|
|
59
62
|
private pendingEvents;
|
|
63
|
+
private pendingPermissions;
|
|
60
64
|
private detachSseController;
|
|
61
65
|
private emitConsoleLog;
|
|
62
66
|
constructor(config: AgentServerConfig);
|
|
67
|
+
private getRuntimeAdapter;
|
|
63
68
|
private getEffectiveMode;
|
|
69
|
+
private getSessionPermissionMode;
|
|
64
70
|
private createApp;
|
|
65
71
|
start(): Promise<void>;
|
|
66
72
|
private autoInitializeSession;
|
|
@@ -78,6 +84,7 @@ declare class AgentServer {
|
|
|
78
84
|
private getPendingUserPrompt;
|
|
79
85
|
private getResumeRunId;
|
|
80
86
|
private buildSessionSystemPrompt;
|
|
87
|
+
private buildCodexInstructions;
|
|
81
88
|
private getCloudInteractionOrigin;
|
|
82
89
|
/**
|
|
83
90
|
* Slack-origin cloud runs auto-publish by default. Every other origin is
|
|
@@ -105,6 +112,16 @@ declare class AgentServer {
|
|
|
105
112
|
private broadcastEvent;
|
|
106
113
|
private replayPendingEvents;
|
|
107
114
|
private sendSseEvent;
|
|
115
|
+
/**
|
|
116
|
+
* Relay a permission request (e.g., plan approval) to the connected desktop
|
|
117
|
+
* app via SSE and wait for a response via the `/command` endpoint.
|
|
118
|
+
*
|
|
119
|
+
* The promise waits indefinitely — if SSE is disconnected, the event is
|
|
120
|
+
* buffered by broadcastEvent and replayed when the client reconnects. Session
|
|
121
|
+
* cleanup force-resolves all pending permissions, so there is no leak.
|
|
122
|
+
*/
|
|
123
|
+
private relayPermissionToClient;
|
|
124
|
+
private resolvePermission;
|
|
108
125
|
}
|
|
109
126
|
|
|
110
127
|
export { AgentServer };
|
|
@@ -5687,7 +5687,7 @@ import { Hono } from "hono";
|
|
|
5687
5687
|
// package.json
|
|
5688
5688
|
var package_default = {
|
|
5689
5689
|
name: "@posthog/agent",
|
|
5690
|
-
version: "2.3.
|
|
5690
|
+
version: "2.3.267",
|
|
5691
5691
|
repository: "https://github.com/PostHog/code",
|
|
5692
5692
|
description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
|
|
5693
5693
|
exports: {
|
|
@@ -5735,6 +5735,10 @@ var package_default = {
|
|
|
5735
5735
|
types: "./dist/adapters/claude/session/models.d.ts",
|
|
5736
5736
|
import: "./dist/adapters/claude/session/models.js"
|
|
5737
5737
|
},
|
|
5738
|
+
"./adapters/reasoning-effort": {
|
|
5739
|
+
types: "./dist/adapters/reasoning-effort.d.ts",
|
|
5740
|
+
import: "./dist/adapters/reasoning-effort.js"
|
|
5741
|
+
},
|
|
5738
5742
|
"./execution-mode": {
|
|
5739
5743
|
types: "./dist/execution-mode.d.ts",
|
|
5740
5744
|
import: "./dist/execution-mode.js"
|
|
@@ -5848,7 +5852,9 @@ var POSTHOG_NOTIFICATIONS = {
|
|
|
5848
5852
|
/** Marks a boundary for log compaction */
|
|
5849
5853
|
COMPACT_BOUNDARY: "_posthog/compact_boundary",
|
|
5850
5854
|
/** Token usage update for a session turn */
|
|
5851
|
-
USAGE_UPDATE: "_posthog/usage_update"
|
|
5855
|
+
USAGE_UPDATE: "_posthog/usage_update",
|
|
5856
|
+
/** Response to a relayed permission request (plan approval, question) */
|
|
5857
|
+
PERMISSION_RESPONSE: "_posthog/permission_response"
|
|
5852
5858
|
};
|
|
5853
5859
|
function isNotification(method, notification) {
|
|
5854
5860
|
if (!method) return false;
|
|
@@ -6123,6 +6129,7 @@ function unreachable(value, logger) {
|
|
|
6123
6129
|
|
|
6124
6130
|
// src/gateway-models.ts
|
|
6125
6131
|
var DEFAULT_GATEWAY_MODEL = "claude-opus-4-6";
|
|
6132
|
+
var DEFAULT_CODEX_MODEL = "gpt-5.4";
|
|
6126
6133
|
var BLOCKED_MODELS = /* @__PURE__ */ new Set(["gpt-5-mini", "openai/gpt-5-mini"]);
|
|
6127
6134
|
var CACHE_TTL = 10 * 60 * 1e3;
|
|
6128
6135
|
var gatewayModelsCache = null;
|
|
@@ -8291,6 +8298,11 @@ async function canUseTool(context) {
|
|
|
8291
8298
|
if (planFileResult) {
|
|
8292
8299
|
return planFileResult;
|
|
8293
8300
|
}
|
|
8301
|
+
if (session.permissionMode === "plan") {
|
|
8302
|
+
const message = `This tool is not available in plan mode. Write your plan to a file in ${getClaudePlansDir()} and call ExitPlanMode when ready.`;
|
|
8303
|
+
await emitToolDenial(context, message);
|
|
8304
|
+
return { behavior: "deny", message, interrupt: false };
|
|
8305
|
+
}
|
|
8294
8306
|
return handleDefaultPermissionFlow(context);
|
|
8295
8307
|
}
|
|
8296
8308
|
|
|
@@ -10098,6 +10110,9 @@ function buildConfigArgs(options) {
|
|
|
10098
10110
|
if (options.model) {
|
|
10099
10111
|
args.push("-c", `model="${options.model}"`);
|
|
10100
10112
|
}
|
|
10113
|
+
if (options.reasoningEffort) {
|
|
10114
|
+
args.push("-c", `model_reasoning_effort="${options.reasoningEffort}"`);
|
|
10115
|
+
}
|
|
10101
10116
|
if (options.instructions) {
|
|
10102
10117
|
const escaped = options.instructions.replace(/\\/g, "\\\\").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/"/g, '\\"');
|
|
10103
10118
|
args.push("-c", `instructions="${escaped}"`);
|
|
@@ -12232,13 +12247,27 @@ var userMessageParamsSchema = z3.object({
|
|
|
12232
12247
|
z3.array(z3.record(z3.string(), z3.unknown())).min(1, "Content is required")
|
|
12233
12248
|
])
|
|
12234
12249
|
});
|
|
12250
|
+
var permissionResponseParamsSchema = z3.object({
|
|
12251
|
+
requestId: z3.string().min(1, "requestId is required"),
|
|
12252
|
+
optionId: z3.string().min(1, "optionId is required"),
|
|
12253
|
+
customInput: z3.string().optional(),
|
|
12254
|
+
answers: z3.record(z3.string(), z3.string()).optional()
|
|
12255
|
+
});
|
|
12256
|
+
var setConfigOptionParamsSchema = z3.object({
|
|
12257
|
+
configId: z3.string().min(1, "configId is required"),
|
|
12258
|
+
value: z3.string().min(1, "value is required")
|
|
12259
|
+
});
|
|
12235
12260
|
var commandParamsSchemas = {
|
|
12236
12261
|
user_message: userMessageParamsSchema,
|
|
12237
12262
|
"posthog/user_message": userMessageParamsSchema,
|
|
12238
12263
|
cancel: z3.object({}).optional(),
|
|
12239
12264
|
"posthog/cancel": z3.object({}).optional(),
|
|
12240
12265
|
close: z3.object({}).optional(),
|
|
12241
|
-
"posthog/close": z3.object({}).optional()
|
|
12266
|
+
"posthog/close": z3.object({}).optional(),
|
|
12267
|
+
permission_response: permissionResponseParamsSchema,
|
|
12268
|
+
"posthog/permission_response": permissionResponseParamsSchema,
|
|
12269
|
+
set_config_option: setConfigOptionParamsSchema,
|
|
12270
|
+
"posthog/set_config_option": setConfigOptionParamsSchema
|
|
12242
12271
|
};
|
|
12243
12272
|
function validateCommandParams(method, params) {
|
|
12244
12273
|
const schema = commandParamsSchemas[method] ?? commandParamsSchemas[method.replace("posthog/", "")];
|
|
@@ -12338,6 +12367,14 @@ function createTappedWritableStream2(underlying, onMessage, logger) {
|
|
|
12338
12367
|
}
|
|
12339
12368
|
});
|
|
12340
12369
|
}
|
|
12370
|
+
function getTaskRunStateString(taskRun, key) {
|
|
12371
|
+
const state = taskRun?.state;
|
|
12372
|
+
if (!state || typeof state !== "object") {
|
|
12373
|
+
return null;
|
|
12374
|
+
}
|
|
12375
|
+
const value = state[key];
|
|
12376
|
+
return typeof value === "string" ? value : null;
|
|
12377
|
+
}
|
|
12341
12378
|
var AgentServer = class _AgentServer {
|
|
12342
12379
|
config;
|
|
12343
12380
|
logger;
|
|
@@ -12355,6 +12392,7 @@ var AgentServer = class _AgentServer {
|
|
|
12355
12392
|
// causing a second session to be created and duplicate Slack messages to be sent.
|
|
12356
12393
|
initializationPromise = null;
|
|
12357
12394
|
pendingEvents = [];
|
|
12395
|
+
pendingPermissions = /* @__PURE__ */ new Map();
|
|
12358
12396
|
detachSseController(controller) {
|
|
12359
12397
|
if (this.session?.sseController === controller) {
|
|
12360
12398
|
this.session.sseController = null;
|
|
@@ -12389,9 +12427,15 @@ var AgentServer = class _AgentServer {
|
|
|
12389
12427
|
});
|
|
12390
12428
|
this.app = this.createApp();
|
|
12391
12429
|
}
|
|
12430
|
+
getRuntimeAdapter() {
|
|
12431
|
+
return this.config.runtimeAdapter ?? "claude";
|
|
12432
|
+
}
|
|
12392
12433
|
getEffectiveMode(payload) {
|
|
12393
12434
|
return payload.mode ?? this.config.mode;
|
|
12394
12435
|
}
|
|
12436
|
+
getSessionPermissionMode() {
|
|
12437
|
+
return this.session?.permissionMode ?? "default";
|
|
12438
|
+
}
|
|
12395
12439
|
createApp() {
|
|
12396
12440
|
const app = new Hono();
|
|
12397
12441
|
app.get("/health", (c) => {
|
|
@@ -12436,6 +12480,7 @@ var AgentServer = class _AgentServer {
|
|
|
12436
12480
|
await this.initializeSession(payload, sseController);
|
|
12437
12481
|
} else {
|
|
12438
12482
|
this.session.sseController = sseController;
|
|
12483
|
+
this.session.hasDesktopConnected = true;
|
|
12439
12484
|
this.replayPendingEvents();
|
|
12440
12485
|
}
|
|
12441
12486
|
this.sendSseEvent(sseController, {
|
|
@@ -12675,6 +12720,43 @@ var AgentServer = class _AgentServer {
|
|
|
12675
12720
|
await this.cleanupSession();
|
|
12676
12721
|
return { closed: true };
|
|
12677
12722
|
}
|
|
12723
|
+
case "posthog/set_config_option":
|
|
12724
|
+
case "set_config_option": {
|
|
12725
|
+
const configId = params.configId;
|
|
12726
|
+
const value = params.value;
|
|
12727
|
+
this.logger.info("Set config option requested", { configId, value });
|
|
12728
|
+
const result = await this.session.clientConnection.setSessionConfigOption({
|
|
12729
|
+
sessionId: this.session.acpSessionId,
|
|
12730
|
+
configId,
|
|
12731
|
+
value
|
|
12732
|
+
});
|
|
12733
|
+
return {
|
|
12734
|
+
configOptions: result.configOptions
|
|
12735
|
+
};
|
|
12736
|
+
}
|
|
12737
|
+
case POSTHOG_NOTIFICATIONS.PERMISSION_RESPONSE:
|
|
12738
|
+
case "permission_response": {
|
|
12739
|
+
const requestId = params.requestId;
|
|
12740
|
+
const optionId = params.optionId;
|
|
12741
|
+
const customInput = params.customInput;
|
|
12742
|
+
const answers = params.answers;
|
|
12743
|
+
this.logger.info("Permission response received", {
|
|
12744
|
+
requestId,
|
|
12745
|
+
optionId
|
|
12746
|
+
});
|
|
12747
|
+
const resolved = this.resolvePermission(
|
|
12748
|
+
requestId,
|
|
12749
|
+
optionId,
|
|
12750
|
+
customInput,
|
|
12751
|
+
answers
|
|
12752
|
+
);
|
|
12753
|
+
if (!resolved) {
|
|
12754
|
+
throw new Error(
|
|
12755
|
+
`No pending permission request found for id: ${requestId}`
|
|
12756
|
+
);
|
|
12757
|
+
}
|
|
12758
|
+
return { resolved: true };
|
|
12759
|
+
}
|
|
12678
12760
|
default:
|
|
12679
12761
|
throw new Error(`Unknown method: ${method}`);
|
|
12680
12762
|
}
|
|
@@ -12714,6 +12796,30 @@ var AgentServer = class _AgentServer {
|
|
|
12714
12796
|
name: process.env.HOSTNAME || "cloud-sandbox"
|
|
12715
12797
|
};
|
|
12716
12798
|
this.configureEnvironment();
|
|
12799
|
+
const [preTaskRun, preTask] = await Promise.all([
|
|
12800
|
+
this.posthogAPI.getTaskRun(payload.task_id, payload.run_id).catch((err) => {
|
|
12801
|
+
this.logger.warn("Failed to fetch task run for session context", {
|
|
12802
|
+
taskId: payload.task_id,
|
|
12803
|
+
runId: payload.run_id,
|
|
12804
|
+
error: err
|
|
12805
|
+
});
|
|
12806
|
+
return null;
|
|
12807
|
+
}),
|
|
12808
|
+
this.posthogAPI.getTask(payload.task_id).catch((err) => {
|
|
12809
|
+
this.logger.warn("Failed to fetch task for session context", {
|
|
12810
|
+
taskId: payload.task_id,
|
|
12811
|
+
error: err
|
|
12812
|
+
});
|
|
12813
|
+
return null;
|
|
12814
|
+
})
|
|
12815
|
+
]);
|
|
12816
|
+
const prUrl = getTaskRunStateString(preTaskRun, "slack_notified_pr_url");
|
|
12817
|
+
if (prUrl) {
|
|
12818
|
+
this.detectedPrUrl = prUrl;
|
|
12819
|
+
}
|
|
12820
|
+
const runtimeAdapter = this.getRuntimeAdapter();
|
|
12821
|
+
const sessionSystemPrompt = this.buildSessionSystemPrompt(prUrl);
|
|
12822
|
+
const codexInstructions = runtimeAdapter === "codex" ? this.buildCodexInstructions(sessionSystemPrompt) : void 0;
|
|
12717
12823
|
const posthogAPI = new PostHogAPIClient({
|
|
12718
12824
|
apiUrl: this.config.apiUrl,
|
|
12719
12825
|
projectId: this.config.projectId,
|
|
@@ -12732,10 +12838,20 @@ var AgentServer = class _AgentServer {
|
|
|
12732
12838
|
logger: new Logger({ debug: true, prefix: "[SessionLogWriter]" })
|
|
12733
12839
|
});
|
|
12734
12840
|
const acpConnection = createAcpConnection({
|
|
12841
|
+
adapter: runtimeAdapter,
|
|
12735
12842
|
taskRunId: payload.run_id,
|
|
12736
12843
|
taskId: payload.task_id,
|
|
12737
12844
|
deviceType: deviceInfo.type,
|
|
12738
12845
|
logWriter,
|
|
12846
|
+
logger: this.logger,
|
|
12847
|
+
codexOptions: runtimeAdapter === "codex" ? {
|
|
12848
|
+
cwd: this.config.repositoryPath ?? "/tmp/workspace",
|
|
12849
|
+
apiBaseUrl: process.env.OPENAI_BASE_URL,
|
|
12850
|
+
apiKey: this.config.apiKey,
|
|
12851
|
+
model: this.config.model ?? DEFAULT_CODEX_MODEL,
|
|
12852
|
+
reasoningEffort: this.config.reasoningEffort,
|
|
12853
|
+
instructions: codexInstructions
|
|
12854
|
+
} : void 0,
|
|
12739
12855
|
onStructuredOutput: async (output) => {
|
|
12740
12856
|
await this.posthogAPI.setTaskRunOutput(
|
|
12741
12857
|
payload.task_id,
|
|
@@ -12772,40 +12888,28 @@ var AgentServer = class _AgentServer {
|
|
|
12772
12888
|
protocolVersion: PROTOCOL_VERSION,
|
|
12773
12889
|
clientCapabilities: {}
|
|
12774
12890
|
});
|
|
12775
|
-
const
|
|
12776
|
-
|
|
12777
|
-
this.logger.warn("Failed to fetch task run for session context", {
|
|
12778
|
-
taskId: payload.task_id,
|
|
12779
|
-
runId: payload.run_id,
|
|
12780
|
-
error: err
|
|
12781
|
-
});
|
|
12782
|
-
return null;
|
|
12783
|
-
}),
|
|
12784
|
-
this.posthogAPI.getTask(payload.task_id).catch((err) => {
|
|
12785
|
-
this.logger.warn("Failed to fetch task for session context", {
|
|
12786
|
-
taskId: payload.task_id,
|
|
12787
|
-
error: err
|
|
12788
|
-
});
|
|
12789
|
-
return null;
|
|
12790
|
-
})
|
|
12791
|
-
]);
|
|
12792
|
-
const prUrl = typeof preTaskRun?.state?.slack_notified_pr_url === "string" ? (preTaskRun?.state).slack_notified_pr_url : null;
|
|
12793
|
-
if (prUrl) {
|
|
12794
|
-
this.detectedPrUrl = prUrl;
|
|
12795
|
-
}
|
|
12891
|
+
const runState = preTaskRun?.state;
|
|
12892
|
+
const initialPermissionMode = typeof runState?.initial_permission_mode === "string" ? runState.initial_permission_mode : "bypassPermissions";
|
|
12796
12893
|
const sessionResponse = await clientConnection.newSession({
|
|
12797
12894
|
cwd: this.config.repositoryPath ?? "/tmp/workspace",
|
|
12798
12895
|
mcpServers: this.config.mcpServers ?? [],
|
|
12799
12896
|
_meta: {
|
|
12800
12897
|
sessionId: payload.run_id,
|
|
12801
12898
|
taskRunId: payload.run_id,
|
|
12802
|
-
systemPrompt:
|
|
12899
|
+
systemPrompt: sessionSystemPrompt,
|
|
12900
|
+
...this.config.model && { model: this.config.model },
|
|
12803
12901
|
allowedDomains: this.config.allowedDomains,
|
|
12804
12902
|
jsonSchema: preTask?.json_schema ?? null,
|
|
12903
|
+
permissionMode: initialPermissionMode,
|
|
12805
12904
|
...this.config.claudeCode?.plugins?.length && {
|
|
12806
12905
|
claudeCode: {
|
|
12807
12906
|
options: {
|
|
12808
|
-
|
|
12907
|
+
...this.config.claudeCode?.plugins?.length && {
|
|
12908
|
+
plugins: this.config.claudeCode.plugins
|
|
12909
|
+
},
|
|
12910
|
+
...runtimeAdapter === "claude" && this.config.reasoningEffort && {
|
|
12911
|
+
effort: this.config.reasoningEffort
|
|
12912
|
+
}
|
|
12809
12913
|
}
|
|
12810
12914
|
}
|
|
12811
12915
|
}
|
|
@@ -12824,7 +12928,9 @@ var AgentServer = class _AgentServer {
|
|
|
12824
12928
|
treeTracker,
|
|
12825
12929
|
sseController,
|
|
12826
12930
|
deviceInfo,
|
|
12827
|
-
logWriter
|
|
12931
|
+
logWriter,
|
|
12932
|
+
permissionMode: initialPermissionMode,
|
|
12933
|
+
hasDesktopConnected: sseController !== null
|
|
12828
12934
|
};
|
|
12829
12935
|
this.logger = new Logger({
|
|
12830
12936
|
debug: true,
|
|
@@ -12838,6 +12944,7 @@ var AgentServer = class _AgentServer {
|
|
|
12838
12944
|
this.logger.info(
|
|
12839
12945
|
`Agent version: ${this.config.version ?? package_default.version}`
|
|
12840
12946
|
);
|
|
12947
|
+
this.logger.info(`Initial permission mode: ${initialPermissionMode}`);
|
|
12841
12948
|
this.posthogAPI.updateTaskRun(payload.task_id, payload.run_id, {
|
|
12842
12949
|
status: "in_progress"
|
|
12843
12950
|
}).catch(
|
|
@@ -13087,6 +13194,9 @@ ${toolSummary}`);
|
|
|
13087
13194
|
}
|
|
13088
13195
|
return { append: cloudAppend };
|
|
13089
13196
|
}
|
|
13197
|
+
buildCodexInstructions(systemPrompt) {
|
|
13198
|
+
return typeof systemPrompt === "string" ? systemPrompt : systemPrompt.append;
|
|
13199
|
+
}
|
|
13090
13200
|
getCloudInteractionOrigin() {
|
|
13091
13201
|
return process.env.POSTHOG_CODE_INTERACTION_ORIGIN ?? process.env.CODE_INTERACTION_ORIGIN ?? process.env.TWIG_INTERACTION_ORIGIN;
|
|
13092
13202
|
}
|
|
@@ -13328,14 +13438,16 @@ ${attributionInstructions}
|
|
|
13328
13438
|
this.logger.debug("Permission request", {
|
|
13329
13439
|
mode,
|
|
13330
13440
|
interactionOrigin,
|
|
13441
|
+
kind: params.toolCall?.kind,
|
|
13331
13442
|
options: params.options
|
|
13332
13443
|
});
|
|
13333
13444
|
const allowOption = params.options.find(
|
|
13334
13445
|
(o) => o.kind === "allow_once" || o.kind === "allow_always"
|
|
13335
13446
|
);
|
|
13336
13447
|
const selectedOptionId = allowOption?.optionId ?? params.options[0].optionId;
|
|
13448
|
+
const codeToolKind = params.toolCall?._meta?.codeToolKind;
|
|
13449
|
+
const isPlanApproval = params.toolCall?.kind === "switch_mode";
|
|
13337
13450
|
if (interactionOrigin === "slack") {
|
|
13338
|
-
const codeToolKind = params.toolCall?._meta?.codeToolKind;
|
|
13339
13451
|
if (codeToolKind === "question") {
|
|
13340
13452
|
return this.buildSlackQuestionRelayResponse(
|
|
13341
13453
|
payload,
|
|
@@ -13343,6 +13455,19 @@ ${attributionInstructions}
|
|
|
13343
13455
|
);
|
|
13344
13456
|
}
|
|
13345
13457
|
}
|
|
13458
|
+
{
|
|
13459
|
+
const isQuestion = codeToolKind === "question";
|
|
13460
|
+
const sessionPermissionMode = this.getSessionPermissionMode();
|
|
13461
|
+
const needsRelay = isQuestion || isPlanApproval || sessionPermissionMode === "default";
|
|
13462
|
+
if (needsRelay && this.session?.hasDesktopConnected) {
|
|
13463
|
+
this.logger.info("Relaying permission to connected client", {
|
|
13464
|
+
kind: params.toolCall?.kind,
|
|
13465
|
+
isQuestion,
|
|
13466
|
+
sessionPermissionMode
|
|
13467
|
+
});
|
|
13468
|
+
return this.relayPermissionToClient(params);
|
|
13469
|
+
}
|
|
13470
|
+
}
|
|
13346
13471
|
if (this.shouldBlockPublishPermission(params)) {
|
|
13347
13472
|
return {
|
|
13348
13473
|
outcome: { outcome: "cancelled" },
|
|
@@ -13362,6 +13487,12 @@ ${attributionInstructions}
|
|
|
13362
13487
|
this.logger.debug("Extension notification", { method, params });
|
|
13363
13488
|
},
|
|
13364
13489
|
sessionUpdate: async (params) => {
|
|
13490
|
+
if (params.update?.sessionUpdate === "current_mode_update" && typeof params.update?.currentModeId === "string" && this.session) {
|
|
13491
|
+
this.session.permissionMode = params.update.currentModeId;
|
|
13492
|
+
this.logger.info("Permission mode updated", {
|
|
13493
|
+
mode: params.update.currentModeId
|
|
13494
|
+
});
|
|
13495
|
+
}
|
|
13365
13496
|
if (params.update?.sessionUpdate === "tool_call_update") {
|
|
13366
13497
|
const meta = params.update?._meta?.claudeCode;
|
|
13367
13498
|
const toolName = meta?.toolName;
|
|
@@ -13540,6 +13671,13 @@ ${attributionInstructions}
|
|
|
13540
13671
|
} catch (error) {
|
|
13541
13672
|
this.logger.error("Failed to flush session logs", error);
|
|
13542
13673
|
}
|
|
13674
|
+
for (const [, pending] of this.pendingPermissions) {
|
|
13675
|
+
pending.resolve({
|
|
13676
|
+
outcome: { outcome: "selected", optionId: "reject" },
|
|
13677
|
+
_meta: { customInput: "Session is shutting down." }
|
|
13678
|
+
});
|
|
13679
|
+
}
|
|
13680
|
+
this.pendingPermissions.clear();
|
|
13543
13681
|
try {
|
|
13544
13682
|
await this.session.acpConnection.cleanup();
|
|
13545
13683
|
} catch (error) {
|
|
@@ -13617,6 +13755,39 @@ ${attributionInstructions}
|
|
|
13617
13755
|
this.detachSseController(controller);
|
|
13618
13756
|
}
|
|
13619
13757
|
}
|
|
13758
|
+
/**
|
|
13759
|
+
* Relay a permission request (e.g., plan approval) to the connected desktop
|
|
13760
|
+
* app via SSE and wait for a response via the `/command` endpoint.
|
|
13761
|
+
*
|
|
13762
|
+
* The promise waits indefinitely — if SSE is disconnected, the event is
|
|
13763
|
+
* buffered by broadcastEvent and replayed when the client reconnects. Session
|
|
13764
|
+
* cleanup force-resolves all pending permissions, so there is no leak.
|
|
13765
|
+
*/
|
|
13766
|
+
relayPermissionToClient(params) {
|
|
13767
|
+
const requestId = crypto.randomUUID();
|
|
13768
|
+
this.broadcastEvent({
|
|
13769
|
+
type: "permission_request",
|
|
13770
|
+
requestId,
|
|
13771
|
+
options: params.options,
|
|
13772
|
+
toolCall: params.toolCall
|
|
13773
|
+
});
|
|
13774
|
+
return new Promise((resolve4) => {
|
|
13775
|
+
this.pendingPermissions.set(requestId, { resolve: resolve4 });
|
|
13776
|
+
});
|
|
13777
|
+
}
|
|
13778
|
+
resolvePermission(requestId, optionId, customInput, answers) {
|
|
13779
|
+
const pending = this.pendingPermissions.get(requestId);
|
|
13780
|
+
if (!pending) return false;
|
|
13781
|
+
this.pendingPermissions.delete(requestId);
|
|
13782
|
+
const meta = {};
|
|
13783
|
+
if (customInput) meta.customInput = customInput;
|
|
13784
|
+
if (answers) meta.answers = answers;
|
|
13785
|
+
pending.resolve({
|
|
13786
|
+
outcome: { outcome: "selected", optionId },
|
|
13787
|
+
...Object.keys(meta).length > 0 ? { _meta: meta } : {}
|
|
13788
|
+
});
|
|
13789
|
+
return true;
|
|
13790
|
+
}
|
|
13620
13791
|
};
|
|
13621
13792
|
export {
|
|
13622
13793
|
AgentServer
|