@posthog/agent 2.3.259 → 2.3.263

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/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;AAChB;AASO,SAAS,eACd,QACA,cACS;AACT,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,WAAW,gBAAgB,WAAW,IAAI,YAAY;AAC/D;;;ACvEA,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":[]}
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":[]}
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var package_default = {
3
3
  name: "@posthog/agent",
4
- version: "2.3.259",
4
+ version: "2.3.263",
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: {
@@ -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.259\",\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.263\",\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":[]}
@@ -36,6 +36,7 @@ interface AgentServerConfig {
36
36
  mode: AgentMode;
37
37
  taskId: string;
38
38
  runId: string;
39
+ createPr?: boolean;
39
40
  version?: string;
40
41
  mcpServers?: RemoteMcpServer[];
41
42
  baseBranch?: string;
@@ -56,10 +57,12 @@ declare class AgentServer {
56
57
  private resumeState;
57
58
  private initializationPromise;
58
59
  private pendingEvents;
60
+ private pendingPermissions;
59
61
  private detachSseController;
60
62
  private emitConsoleLog;
61
63
  constructor(config: AgentServerConfig);
62
64
  private getEffectiveMode;
65
+ private getSessionPermissionMode;
63
66
  private createApp;
64
67
  start(): Promise<void>;
65
68
  private autoInitializeSession;
@@ -77,11 +80,21 @@ declare class AgentServer {
77
80
  private getPendingUserPrompt;
78
81
  private getResumeRunId;
79
82
  private buildSessionSystemPrompt;
83
+ private getCloudInteractionOrigin;
84
+ /**
85
+ * Slack-origin cloud runs auto-publish by default. Every other origin is
86
+ * review-first unless the user explicitly asks, and createPr=false always
87
+ * disables publishing.
88
+ */
89
+ private shouldAutoPublishCloudChanges;
90
+ private buildDetectedPrContext;
80
91
  private buildCloudSystemPrompt;
81
92
  private getCurrentGitBranch;
82
93
  private syncCloudBranchMetadata;
83
94
  private signalTaskComplete;
84
95
  private configureEnvironment;
96
+ private buildSlackQuestionRelayResponse;
97
+ private shouldBlockPublishPermission;
85
98
  private createCloudClient;
86
99
  private relayAgentResponse;
87
100
  private relaySlackQuestion;
@@ -94,6 +107,16 @@ declare class AgentServer {
94
107
  private broadcastEvent;
95
108
  private replayPendingEvents;
96
109
  private sendSseEvent;
110
+ /**
111
+ * Relay a permission request (e.g., plan approval) to the connected desktop
112
+ * app via SSE and wait for a response via the `/command` endpoint.
113
+ *
114
+ * The promise waits indefinitely — if SSE is disconnected, the event is
115
+ * buffered by broadcastEvent and replayed when the client reconnects. Session
116
+ * cleanup force-resolves all pending permissions, so there is no leak.
117
+ */
118
+ private relayPermissionToClient;
119
+ private resolvePermission;
97
120
  }
98
121
 
99
122
  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.259",
5690
+ version: "2.3.263",
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: {
@@ -5848,7 +5848,9 @@ var POSTHOG_NOTIFICATIONS = {
5848
5848
  /** Marks a boundary for log compaction */
5849
5849
  COMPACT_BOUNDARY: "_posthog/compact_boundary",
5850
5850
  /** Token usage update for a session turn */
5851
- USAGE_UPDATE: "_posthog/usage_update"
5851
+ USAGE_UPDATE: "_posthog/usage_update",
5852
+ /** Response to a relayed permission request (plan approval, question) */
5853
+ PERMISSION_RESPONSE: "_posthog/permission_response"
5852
5854
  };
5853
5855
  function isNotification(method, notification) {
5854
5856
  if (!method) return false;
@@ -8291,6 +8293,11 @@ async function canUseTool(context) {
8291
8293
  if (planFileResult) {
8292
8294
  return planFileResult;
8293
8295
  }
8296
+ if (session.permissionMode === "plan") {
8297
+ const message = `This tool is not available in plan mode. Write your plan to a file in ${getClaudePlansDir()} and call ExitPlanMode when ready.`;
8298
+ await emitToolDenial(context, message);
8299
+ return { behavior: "deny", message, interrupt: false };
8300
+ }
8294
8301
  return handleDefaultPermissionFlow(context);
8295
8302
  }
8296
8303
 
@@ -12232,13 +12239,27 @@ var userMessageParamsSchema = z3.object({
12232
12239
  z3.array(z3.record(z3.string(), z3.unknown())).min(1, "Content is required")
12233
12240
  ])
12234
12241
  });
12242
+ var permissionResponseParamsSchema = z3.object({
12243
+ requestId: z3.string().min(1, "requestId is required"),
12244
+ optionId: z3.string().min(1, "optionId is required"),
12245
+ customInput: z3.string().optional(),
12246
+ answers: z3.record(z3.string(), z3.string()).optional()
12247
+ });
12248
+ var setConfigOptionParamsSchema = z3.object({
12249
+ configId: z3.string().min(1, "configId is required"),
12250
+ value: z3.string().min(1, "value is required")
12251
+ });
12235
12252
  var commandParamsSchemas = {
12236
12253
  user_message: userMessageParamsSchema,
12237
12254
  "posthog/user_message": userMessageParamsSchema,
12238
12255
  cancel: z3.object({}).optional(),
12239
12256
  "posthog/cancel": z3.object({}).optional(),
12240
12257
  close: z3.object({}).optional(),
12241
- "posthog/close": z3.object({}).optional()
12258
+ "posthog/close": z3.object({}).optional(),
12259
+ permission_response: permissionResponseParamsSchema,
12260
+ "posthog/permission_response": permissionResponseParamsSchema,
12261
+ set_config_option: setConfigOptionParamsSchema,
12262
+ "posthog/set_config_option": setConfigOptionParamsSchema
12242
12263
  };
12243
12264
  function validateCommandParams(method, params) {
12244
12265
  const schema = commandParamsSchemas[method] ?? commandParamsSchemas[method.replace("posthog/", "")];
@@ -12355,6 +12376,7 @@ var AgentServer = class _AgentServer {
12355
12376
  // causing a second session to be created and duplicate Slack messages to be sent.
12356
12377
  initializationPromise = null;
12357
12378
  pendingEvents = [];
12379
+ pendingPermissions = /* @__PURE__ */ new Map();
12358
12380
  detachSseController(controller) {
12359
12381
  if (this.session?.sseController === controller) {
12360
12382
  this.session.sseController = null;
@@ -12392,6 +12414,9 @@ var AgentServer = class _AgentServer {
12392
12414
  getEffectiveMode(payload) {
12393
12415
  return payload.mode ?? this.config.mode;
12394
12416
  }
12417
+ getSessionPermissionMode() {
12418
+ return this.session?.permissionMode ?? "default";
12419
+ }
12395
12420
  createApp() {
12396
12421
  const app = new Hono();
12397
12422
  app.get("/health", (c) => {
@@ -12436,6 +12461,7 @@ var AgentServer = class _AgentServer {
12436
12461
  await this.initializeSession(payload, sseController);
12437
12462
  } else {
12438
12463
  this.session.sseController = sseController;
12464
+ this.session.hasDesktopConnected = true;
12439
12465
  this.replayPendingEvents();
12440
12466
  }
12441
12467
  this.sendSseEvent(sseController, {
@@ -12625,12 +12651,9 @@ var AgentServer = class _AgentServer {
12625
12651
  prompt,
12626
12652
  ...this.detectedPrUrl && {
12627
12653
  _meta: {
12628
- prContext: `IMPORTANT \u2014 OVERRIDE PREVIOUS INSTRUCTIONS ABOUT CREATING BRANCHES/PRs.
12629
- You already have an open pull request: ${this.detectedPrUrl}
12630
- You MUST:
12631
- 1. Check out the existing PR branch with \`gh pr checkout ${this.detectedPrUrl}\`
12632
- 2. Make changes, commit, and push to that branch
12633
- You MUST NOT create a new branch, close the existing PR, or create a new PR.`
12654
+ // Keep the live-session PR override aligned with the startup
12655
+ // prompt policy so non-Slack runs remain review-first.
12656
+ prContext: this.buildDetectedPrContext(this.detectedPrUrl)
12634
12657
  }
12635
12658
  }
12636
12659
  });
@@ -12678,6 +12701,43 @@ You MUST NOT create a new branch, close the existing PR, or create a new PR.`
12678
12701
  await this.cleanupSession();
12679
12702
  return { closed: true };
12680
12703
  }
12704
+ case "posthog/set_config_option":
12705
+ case "set_config_option": {
12706
+ const configId = params.configId;
12707
+ const value = params.value;
12708
+ this.logger.info("Set config option requested", { configId, value });
12709
+ const result = await this.session.clientConnection.setSessionConfigOption({
12710
+ sessionId: this.session.acpSessionId,
12711
+ configId,
12712
+ value
12713
+ });
12714
+ return {
12715
+ configOptions: result.configOptions
12716
+ };
12717
+ }
12718
+ case POSTHOG_NOTIFICATIONS.PERMISSION_RESPONSE:
12719
+ case "permission_response": {
12720
+ const requestId = params.requestId;
12721
+ const optionId = params.optionId;
12722
+ const customInput = params.customInput;
12723
+ const answers = params.answers;
12724
+ this.logger.info("Permission response received", {
12725
+ requestId,
12726
+ optionId
12727
+ });
12728
+ const resolved = this.resolvePermission(
12729
+ requestId,
12730
+ optionId,
12731
+ customInput,
12732
+ answers
12733
+ );
12734
+ if (!resolved) {
12735
+ throw new Error(
12736
+ `No pending permission request found for id: ${requestId}`
12737
+ );
12738
+ }
12739
+ return { resolved: true };
12740
+ }
12681
12741
  default:
12682
12742
  throw new Error(`Unknown method: ${method}`);
12683
12743
  }
@@ -12796,6 +12856,8 @@ You MUST NOT create a new branch, close the existing PR, or create a new PR.`
12796
12856
  if (prUrl) {
12797
12857
  this.detectedPrUrl = prUrl;
12798
12858
  }
12859
+ const runState = preTaskRun?.state;
12860
+ const initialPermissionMode = typeof runState?.initial_permission_mode === "string" ? runState.initial_permission_mode : "bypassPermissions";
12799
12861
  const sessionResponse = await clientConnection.newSession({
12800
12862
  cwd: this.config.repositoryPath ?? "/tmp/workspace",
12801
12863
  mcpServers: this.config.mcpServers ?? [],
@@ -12805,6 +12867,7 @@ You MUST NOT create a new branch, close the existing PR, or create a new PR.`
12805
12867
  systemPrompt: this.buildSessionSystemPrompt(prUrl),
12806
12868
  allowedDomains: this.config.allowedDomains,
12807
12869
  jsonSchema: preTask?.json_schema ?? null,
12870
+ permissionMode: initialPermissionMode,
12808
12871
  ...this.config.claudeCode?.plugins?.length && {
12809
12872
  claudeCode: {
12810
12873
  options: {
@@ -12827,7 +12890,9 @@ You MUST NOT create a new branch, close the existing PR, or create a new PR.`
12827
12890
  treeTracker,
12828
12891
  sseController,
12829
12892
  deviceInfo,
12830
- logWriter
12893
+ logWriter,
12894
+ permissionMode: initialPermissionMode,
12895
+ hasDesktopConnected: sseController !== null
12831
12896
  };
12832
12897
  this.logger = new Logger({
12833
12898
  debug: true,
@@ -12841,6 +12906,7 @@ You MUST NOT create a new branch, close the existing PR, or create a new PR.`
12841
12906
  this.logger.info(
12842
12907
  `Agent version: ${this.config.version ?? package_default.version}`
12843
12908
  );
12909
+ this.logger.info(`Initial permission mode: ${initialPermissionMode}`);
12844
12910
  this.posthogAPI.updateTaskRun(payload.task_id, payload.run_id, {
12845
12911
  status: "in_progress"
12846
12912
  }).catch(
@@ -13090,13 +13156,38 @@ ${toolSummary}`);
13090
13156
  }
13091
13157
  return { append: cloudAppend };
13092
13158
  }
13159
+ getCloudInteractionOrigin() {
13160
+ return process.env.POSTHOG_CODE_INTERACTION_ORIGIN ?? process.env.CODE_INTERACTION_ORIGIN ?? process.env.TWIG_INTERACTION_ORIGIN;
13161
+ }
13162
+ /**
13163
+ * Slack-origin cloud runs auto-publish by default. Every other origin is
13164
+ * review-first unless the user explicitly asks, and createPr=false always
13165
+ * disables publishing.
13166
+ */
13167
+ shouldAutoPublishCloudChanges() {
13168
+ return this.getCloudInteractionOrigin() === "slack" && this.config.createPr !== false;
13169
+ }
13170
+ buildDetectedPrContext(prUrl) {
13171
+ if (!this.shouldAutoPublishCloudChanges()) {
13172
+ return `An open pull request already exists: ${prUrl}
13173
+ Use that PR as context if it is helpful, but stop with local changes ready for review.
13174
+ Do NOT create commits, push to the PR branch, update the pull request, create a new branch, or create a new pull request unless the user explicitly asks.`;
13175
+ }
13176
+ return `IMPORTANT \u2014 OVERRIDE PREVIOUS INSTRUCTIONS ABOUT CREATING BRANCHES/PRs.
13177
+ You already have an open pull request: ${prUrl}
13178
+ You MUST:
13179
+ 1. Check out the existing PR branch with \`gh pr checkout ${prUrl}\`
13180
+ 2. Make changes, commit, and push to that branch
13181
+ You MUST NOT create a new branch, close the existing PR, or create a new PR.`;
13182
+ }
13093
13183
  buildCloudSystemPrompt(prUrl) {
13094
13184
  const taskId = this.config.taskId;
13185
+ const shouldAutoCreatePr = this.shouldAutoPublishCloudChanges();
13095
13186
  const attributionInstructions = `
13096
13187
  ## Attribution
13097
13188
  Do NOT use Claude Code's default attribution (no "Co-Authored-By" trailers, no "Generated with [Claude Code]" lines).
13098
13189
 
13099
- Instead, add the following trailers to EVERY commit message (after a blank line at the end):
13190
+ If you create a commit, add the following trailers to the commit message (after a blank line at the end):
13100
13191
  Generated-By: PostHog Code
13101
13192
  Task-Id: ${taskId}
13102
13193
 
@@ -13111,6 +13202,20 @@ EOF
13111
13202
  )"
13112
13203
  \`\`\``;
13113
13204
  if (prUrl) {
13205
+ if (!shouldAutoCreatePr) {
13206
+ return `
13207
+ # Cloud Task Execution
13208
+
13209
+ This task already has an open pull request: ${prUrl}
13210
+
13211
+ Do the requested work, but stop with local changes ready for review.
13212
+
13213
+ Important:
13214
+ - Do NOT create new commits, push to the branch, or update the pull request unless the user explicitly asks.
13215
+ - Do NOT create a new branch or a new pull request.
13216
+ ${attributionInstructions}
13217
+ `;
13218
+ }
13114
13219
  return `
13115
13220
  # Cloud Task Execution
13116
13221
 
@@ -13144,6 +13249,17 @@ When the user asks for code changes or software engineering tasks:
13144
13249
  Important:
13145
13250
  - Do NOT create branches, commits, or pull requests in this mode.
13146
13251
  - Prefer using MCP tools to answer questions with real data over giving generic advice.
13252
+ `;
13253
+ }
13254
+ if (!shouldAutoCreatePr) {
13255
+ return `
13256
+ # Cloud Task Execution
13257
+
13258
+ Do the requested work, but stop with local changes ready for review.
13259
+
13260
+ Important:
13261
+ - Do NOT create a branch, commit, push, or open a pull request unless the user explicitly asks.
13262
+ ${attributionInstructions}
13147
13263
  `;
13148
13264
  }
13149
13265
  return `
@@ -13252,32 +13368,73 @@ ${attributionInstructions}
13252
13368
  LLM_GATEWAY_URL: gatewayUrl
13253
13369
  });
13254
13370
  }
13371
+ buildSlackQuestionRelayResponse(payload, toolMeta2) {
13372
+ this.relaySlackQuestion(payload, toolMeta2);
13373
+ return {
13374
+ outcome: { outcome: "cancelled" },
13375
+ _meta: {
13376
+ message: "This question has been relayed to the Slack thread where this task originated. The user will reply there. Do NOT re-ask the question or pick an answer yourself. Simply let the user know you are waiting for their reply."
13377
+ }
13378
+ };
13379
+ }
13380
+ shouldBlockPublishPermission(params) {
13381
+ if (this.config.createPr !== false) {
13382
+ return false;
13383
+ }
13384
+ const meta = params.toolCall?._meta && typeof params.toolCall._meta === "object" && !Array.isArray(params.toolCall._meta) ? params.toolCall._meta : null;
13385
+ const rawInput = params.toolCall?.rawInput && typeof params.toolCall.rawInput === "object" && !Array.isArray(params.toolCall.rawInput) ? params.toolCall.rawInput : null;
13386
+ const toolName = typeof meta?.toolName === "string" ? meta.toolName : null;
13387
+ const command = typeof rawInput?.command === "string" ? rawInput.command : null;
13388
+ return Boolean(
13389
+ toolName && (toolName === "Bash" || toolName.includes("bash")) && command && /\bgit\s+push\b|\bgh\s+pr\s+(create|edit|ready|merge)\b/.test(command)
13390
+ );
13391
+ }
13255
13392
  createCloudClient(payload) {
13256
13393
  const mode = this.getEffectiveMode(payload);
13257
- const interactionOrigin = process.env.CODE_INTERACTION_ORIGIN ?? process.env.TWIG_INTERACTION_ORIGIN;
13394
+ const interactionOrigin = process.env.POSTHOG_CODE_INTERACTION_ORIGIN ?? process.env.CODE_INTERACTION_ORIGIN ?? process.env.TWIG_INTERACTION_ORIGIN;
13258
13395
  return {
13259
13396
  requestPermission: async (params) => {
13260
13397
  this.logger.debug("Permission request", {
13261
13398
  mode,
13262
13399
  interactionOrigin,
13400
+ kind: params.toolCall?.kind,
13263
13401
  options: params.options
13264
13402
  });
13265
13403
  const allowOption = params.options.find(
13266
13404
  (o) => o.kind === "allow_once" || o.kind === "allow_always"
13267
13405
  );
13268
13406
  const selectedOptionId = allowOption?.optionId ?? params.options[0].optionId;
13407
+ const codeToolKind = params.toolCall?._meta?.codeToolKind;
13408
+ const isPlanApproval = params.toolCall?.kind === "switch_mode";
13269
13409
  if (interactionOrigin === "slack") {
13270
- const codeToolKind = params.toolCall?._meta?.codeToolKind;
13271
13410
  if (codeToolKind === "question") {
13272
- this.relaySlackQuestion(payload, params.toolCall?._meta);
13273
- return {
13274
- outcome: { outcome: "cancelled" },
13275
- _meta: {
13276
- message: "This question has been relayed to the Slack thread where this task originated. The user will reply there. Do NOT re-ask the question or pick an answer yourself. Simply let the user know you are waiting for their reply."
13277
- }
13278
- };
13411
+ return this.buildSlackQuestionRelayResponse(
13412
+ payload,
13413
+ params.toolCall?._meta
13414
+ );
13415
+ }
13416
+ }
13417
+ {
13418
+ const isQuestion = codeToolKind === "question";
13419
+ const sessionPermissionMode = this.getSessionPermissionMode();
13420
+ const needsRelay = isQuestion || isPlanApproval || sessionPermissionMode === "default";
13421
+ if (needsRelay && this.session?.hasDesktopConnected) {
13422
+ this.logger.info("Relaying permission to connected client", {
13423
+ kind: params.toolCall?.kind,
13424
+ isQuestion,
13425
+ sessionPermissionMode
13426
+ });
13427
+ return this.relayPermissionToClient(params);
13279
13428
  }
13280
13429
  }
13430
+ if (this.shouldBlockPublishPermission(params)) {
13431
+ return {
13432
+ outcome: { outcome: "cancelled" },
13433
+ _meta: {
13434
+ message: "This run is configured to stop before publishing. Do not push commits or create/update pull requests unless the user explicitly asks."
13435
+ }
13436
+ };
13437
+ }
13281
13438
  return {
13282
13439
  outcome: {
13283
13440
  outcome: "selected",
@@ -13289,6 +13446,12 @@ ${attributionInstructions}
13289
13446
  this.logger.debug("Extension notification", { method, params });
13290
13447
  },
13291
13448
  sessionUpdate: async (params) => {
13449
+ if (params.update?.sessionUpdate === "current_mode_update" && typeof params.update?.currentModeId === "string" && this.session) {
13450
+ this.session.permissionMode = params.update.currentModeId;
13451
+ this.logger.info("Permission mode updated", {
13452
+ mode: params.update.currentModeId
13453
+ });
13454
+ }
13292
13455
  if (params.update?.sessionUpdate === "tool_call_update") {
13293
13456
  const meta = params.update?._meta?.claudeCode;
13294
13457
  const toolName = meta?.toolName;
@@ -13467,6 +13630,13 @@ ${attributionInstructions}
13467
13630
  } catch (error) {
13468
13631
  this.logger.error("Failed to flush session logs", error);
13469
13632
  }
13633
+ for (const [, pending] of this.pendingPermissions) {
13634
+ pending.resolve({
13635
+ outcome: { outcome: "selected", optionId: "reject" },
13636
+ _meta: { customInput: "Session is shutting down." }
13637
+ });
13638
+ }
13639
+ this.pendingPermissions.clear();
13470
13640
  try {
13471
13641
  await this.session.acpConnection.cleanup();
13472
13642
  } catch (error) {
@@ -13544,6 +13714,39 @@ ${attributionInstructions}
13544
13714
  this.detachSseController(controller);
13545
13715
  }
13546
13716
  }
13717
+ /**
13718
+ * Relay a permission request (e.g., plan approval) to the connected desktop
13719
+ * app via SSE and wait for a response via the `/command` endpoint.
13720
+ *
13721
+ * The promise waits indefinitely — if SSE is disconnected, the event is
13722
+ * buffered by broadcastEvent and replayed when the client reconnects. Session
13723
+ * cleanup force-resolves all pending permissions, so there is no leak.
13724
+ */
13725
+ relayPermissionToClient(params) {
13726
+ const requestId = crypto.randomUUID();
13727
+ this.broadcastEvent({
13728
+ type: "permission_request",
13729
+ requestId,
13730
+ options: params.options,
13731
+ toolCall: params.toolCall
13732
+ });
13733
+ return new Promise((resolve4) => {
13734
+ this.pendingPermissions.set(requestId, { resolve: resolve4 });
13735
+ });
13736
+ }
13737
+ resolvePermission(requestId, optionId, customInput, answers) {
13738
+ const pending = this.pendingPermissions.get(requestId);
13739
+ if (!pending) return false;
13740
+ this.pendingPermissions.delete(requestId);
13741
+ const meta = {};
13742
+ if (customInput) meta.customInput = customInput;
13743
+ if (answers) meta.answers = answers;
13744
+ pending.resolve({
13745
+ outcome: { outcome: "selected", optionId },
13746
+ ...Object.keys(meta).length > 0 ? { _meta: meta } : {}
13747
+ });
13748
+ return true;
13749
+ }
13547
13750
  };
13548
13751
  export {
13549
13752
  AgentServer