@posthog/agent 2.1.82 → 2.1.83

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.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/adapters/claude/mcp/tool-metadata.ts"],"sourcesContent":["import type { McpServerConfig } from \"@anthropic-ai/claude-agent-sdk\";\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport { Logger } from \"../../../utils/logger.js\";\n\nexport interface McpToolMetadata {\n readOnly: boolean;\n}\n\nconst mcpToolMetadataCache: Map<string, McpToolMetadata> = new Map();\n\nfunction buildToolKey(serverName: string, toolName: string): string {\n return `mcp__${serverName}__${toolName}`;\n}\n\nfunction isHttpMcpServer(\n config: McpServerConfig,\n): config is McpServerConfig & { type: \"http\"; url: string } {\n return config.type === \"http\" && typeof (config as any).url === \"string\";\n}\n\nasync function fetchToolsFromHttpServer(\n _serverName: string,\n config: McpServerConfig & { type: \"http\"; url: string },\n): Promise<Tool[]> {\n const transport = new StreamableHTTPClientTransport(new URL(config.url), {\n requestInit: {\n headers: (config as any).headers || {},\n },\n });\n\n const client = new Client({\n name: \"twig-metadata-fetcher\",\n version: \"1.0.0\",\n });\n\n try {\n await client.connect(transport);\n const result = await client.listTools();\n return result.tools;\n } finally {\n await client.close().catch(() => {});\n }\n}\n\nfunction extractToolMetadata(tool: Tool): McpToolMetadata {\n return {\n readOnly: tool.annotations?.readOnlyHint === true,\n };\n}\n\nexport async function fetchMcpToolMetadata(\n mcpServers: Record<string, McpServerConfig>,\n logger: Logger = new Logger({ debug: false, prefix: \"[McpToolMetadata]\" }),\n): Promise<void> {\n const fetchPromises: Promise<void>[] = [];\n\n for (const [serverName, config] of Object.entries(mcpServers)) {\n if (!isHttpMcpServer(config)) {\n continue;\n }\n\n const fetchPromise = fetchToolsFromHttpServer(serverName, config)\n .then((tools) => {\n const toolCount = tools.length;\n const readOnlyCount = tools.filter(\n (t) => t.annotations?.readOnlyHint === true,\n ).length;\n\n for (const tool of tools) {\n const toolKey = buildToolKey(serverName, tool.name);\n mcpToolMetadataCache.set(toolKey, extractToolMetadata(tool));\n }\n\n logger.info(\"Fetched MCP tool metadata\", {\n serverName,\n toolCount,\n readOnlyCount,\n });\n })\n .catch((error) => {\n logger.error(\"Failed to fetch MCP tool metadata\", {\n serverName,\n error: error instanceof Error ? error.message : String(error),\n });\n });\n\n fetchPromises.push(fetchPromise);\n }\n\n await Promise.all(fetchPromises);\n}\n\nexport function isMcpToolReadOnly(toolName: string): boolean {\n const metadata = mcpToolMetadataCache.get(toolName);\n return metadata?.readOnly === true;\n}\n\nexport function clearMcpToolMetadataCache(): void {\n mcpToolMetadataCache.clear();\n}\n"],"mappings":";AACA,SAAS,cAAc;AACvB,SAAS,qCAAqC;AAQ9C,IAAM,uBAAqD,oBAAI,IAAI;AAoF5D,SAAS,kBAAkB,UAA2B;AAC3D,QAAM,WAAW,qBAAqB,IAAI,QAAQ;AAClD,SAAO,UAAU,aAAa;AAChC;","names":[]}
1
+ {"version":3,"sources":["../src/adapters/claude/mcp/tool-metadata.ts"],"sourcesContent":["import type {\n McpHttpServerConfig,\n McpServerConfig,\n} from \"@anthropic-ai/claude-agent-sdk\";\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport { Logger } from \"../../../utils/logger.js\";\n\nexport interface McpToolMetadata {\n readOnly: boolean;\n}\n\nconst mcpToolMetadataCache: Map<string, McpToolMetadata> = new Map();\n\nfunction buildToolKey(serverName: string, toolName: string): string {\n return `mcp__${serverName}__${toolName}`;\n}\n\nfunction isHttpMcpServer(\n config: McpServerConfig,\n): config is McpHttpServerConfig {\n return config.type === \"http\" && typeof config.url === \"string\";\n}\n\nasync function fetchToolsFromHttpServer(\n _serverName: string,\n config: McpHttpServerConfig,\n): Promise<Tool[]> {\n const transport = new StreamableHTTPClientTransport(new URL(config.url), {\n requestInit: {\n headers: config.headers ?? {},\n },\n });\n\n const client = new Client({\n name: \"twig-metadata-fetcher\",\n version: \"1.0.0\",\n });\n\n try {\n await client.connect(transport);\n const result = await client.listTools();\n return result.tools;\n } finally {\n await client.close().catch(() => {});\n }\n}\n\nfunction extractToolMetadata(tool: Tool): McpToolMetadata {\n return {\n readOnly: tool.annotations?.readOnlyHint === true,\n };\n}\n\nexport async function fetchMcpToolMetadata(\n mcpServers: Record<string, McpServerConfig>,\n logger: Logger = new Logger({ debug: false, prefix: \"[McpToolMetadata]\" }),\n): Promise<void> {\n const fetchPromises: Promise<void>[] = [];\n\n for (const [serverName, config] of Object.entries(mcpServers)) {\n if (!isHttpMcpServer(config)) {\n continue;\n }\n\n const fetchPromise = fetchToolsFromHttpServer(serverName, config)\n .then((tools) => {\n const toolCount = tools.length;\n const readOnlyCount = tools.filter(\n (t) => t.annotations?.readOnlyHint === true,\n ).length;\n\n for (const tool of tools) {\n const toolKey = buildToolKey(serverName, tool.name);\n mcpToolMetadataCache.set(toolKey, extractToolMetadata(tool));\n }\n\n logger.info(\"Fetched MCP tool metadata\", {\n serverName,\n toolCount,\n readOnlyCount,\n });\n })\n .catch((error) => {\n logger.error(\"Failed to fetch MCP tool metadata\", {\n serverName,\n error: error instanceof Error ? error.message : String(error),\n });\n });\n\n fetchPromises.push(fetchPromise);\n }\n\n await Promise.all(fetchPromises);\n}\n\nexport function isMcpToolReadOnly(toolName: string): boolean {\n const metadata = mcpToolMetadataCache.get(toolName);\n return metadata?.readOnly === true;\n}\n\nexport function clearMcpToolMetadataCache(): void {\n mcpToolMetadataCache.clear();\n}\n"],"mappings":";AAIA,SAAS,cAAc;AACvB,SAAS,qCAAqC;AAQ9C,IAAM,uBAAqD,oBAAI,IAAI;AAoF5D,SAAS,kBAAkB,UAA2B;AAC3D,QAAM,WAAW,qBAAqB,IAAI,QAAQ;AAClD,SAAO,UAAU,aAAa;AAChC;","names":[]}
@@ -1183,7 +1183,7 @@ import { v7 as uuidv7 } from "uuid";
1183
1183
  // package.json
1184
1184
  var package_default = {
1185
1185
  name: "@posthog/agent",
1186
- version: "2.1.82",
1186
+ version: "2.1.83",
1187
1187
  repository: "https://github.com/PostHog/twig",
1188
1188
  description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
1189
1189
  exports: {
@@ -2475,7 +2475,7 @@ function isHttpMcpServer(config) {
2475
2475
  async function fetchToolsFromHttpServer(_serverName, config) {
2476
2476
  const transport = new StreamableHTTPClientTransport(new URL(config.url), {
2477
2477
  requestInit: {
2478
- headers: config.headers || {}
2478
+ headers: config.headers ?? {}
2479
2479
  }
2480
2480
  });
2481
2481
  const client = new Client({
@@ -2855,7 +2855,7 @@ async function applyPlanApproval(response, context, updatedInput) {
2855
2855
  return { behavior: "deny", message, interrupt: false };
2856
2856
  }
2857
2857
  async function handleEnterPlanModeTool(context) {
2858
- const { session, toolInput, logger } = context;
2858
+ const { session, toolInput } = context;
2859
2859
  session.permissionMode = "plan";
2860
2860
  await session.query.setPermissionMode("plan");
2861
2861
  await context.emitConfigOptionsUpdate();
@@ -3203,6 +3203,11 @@ function buildSpawnWrapper(sessionId, onProcessSpawned, onProcessExited) {
3203
3203
  child.kill("SIGTERM");
3204
3204
  });
3205
3205
  }
3206
+ if (!child.stdin || !child.stdout) {
3207
+ throw new Error(
3208
+ `Failed to get stdio streams for spawned process (pid=${child.pid})`
3209
+ );
3210
+ }
3206
3211
  return {
3207
3212
  stdin: child.stdin,
3208
3213
  stdout: child.stdout,
@@ -3215,12 +3220,15 @@ function buildSpawnWrapper(sessionId, onProcessSpawned, onProcessExited) {
3215
3220
  kill(signal) {
3216
3221
  return child.kill(signal);
3217
3222
  },
3223
+ // biome-ignore lint/suspicious/noExplicitAny: ChildProcess event listener types require any[]
3218
3224
  on(event, listener) {
3219
3225
  child.on(event, listener);
3220
3226
  },
3227
+ // biome-ignore lint/suspicious/noExplicitAny: ChildProcess event listener types require any[]
3221
3228
  once(event, listener) {
3222
3229
  child.once(event, listener);
3223
3230
  },
3231
+ // biome-ignore lint/suspicious/noExplicitAny: ChildProcess event listener types require any[]
3224
3232
  off(event, listener) {
3225
3233
  child.off(event, listener);
3226
3234
  }
@@ -3901,15 +3909,16 @@ function createClaudeConnection(config) {
3901
3909
  deviceType: config.deviceType
3902
3910
  });
3903
3911
  }
3912
+ const taskRunId = config.taskRunId;
3904
3913
  agentWritable = createTappedWritableStream(streams.agent.writable, {
3905
3914
  onMessage: (line) => {
3906
- logWriter.appendRawLine(config.taskRunId, line);
3915
+ logWriter.appendRawLine(taskRunId, line);
3907
3916
  },
3908
3917
  logger
3909
3918
  });
3910
3919
  clientWritable = createTappedWritableStream(streams.client.writable, {
3911
3920
  onMessage: (line) => {
3912
- logWriter.appendRawLine(config.taskRunId, line);
3921
+ logWriter.appendRawLine(taskRunId, line);
3913
3922
  },
3914
3923
  logger
3915
3924
  });
@@ -4105,7 +4114,7 @@ function createCodexConnection(config) {
4105
4114
  }
4106
4115
  });
4107
4116
  const shouldTapLogs = config.taskRunId && logWriter;
4108
- if (shouldTapLogs) {
4117
+ if (shouldTapLogs && config.taskRunId) {
4109
4118
  const taskRunId2 = config.taskRunId;
4110
4119
  if (!logWriter.isRegistered(taskRunId2)) {
4111
4120
  logWriter.register(taskRunId2, {
@@ -9237,11 +9246,13 @@ var AsyncReaderWriterLock = class {
9237
9246
  return;
9238
9247
  if (this.writeQueue.length > 0) {
9239
9248
  const next = this.writeQueue.shift();
9240
- next();
9249
+ if (next)
9250
+ next();
9241
9251
  } else {
9242
9252
  while (this.readQueue.length > 0 && !this.writerWaiting) {
9243
9253
  const next = this.readQueue.shift();
9244
- next();
9254
+ if (next)
9255
+ next();
9245
9256
  }
9246
9257
  }
9247
9258
  }
@@ -9757,27 +9768,29 @@ var ApplySnapshotSaga = class extends Saga {
9757
9768
  if (!snapshot.archiveUrl) {
9758
9769
  throw new Error("Cannot apply snapshot: no archive URL");
9759
9770
  }
9771
+ const archiveUrl = snapshot.archiveUrl;
9760
9772
  await this.step({
9761
9773
  name: "create_tmp_dir",
9762
9774
  execute: () => mkdir3(tmpDir, { recursive: true }),
9763
9775
  rollback: async () => {
9764
9776
  }
9765
9777
  });
9766
- this.archivePath = join5(tmpDir, `${snapshot.treeHash}.tar.gz`);
9778
+ const archivePath = join5(tmpDir, `${snapshot.treeHash}.tar.gz`);
9779
+ this.archivePath = archivePath;
9767
9780
  await this.step({
9768
9781
  name: "download_archive",
9769
9782
  execute: async () => {
9770
9783
  const arrayBuffer = await apiClient.downloadArtifact(
9771
9784
  taskId,
9772
9785
  runId,
9773
- snapshot.archiveUrl
9786
+ archiveUrl
9774
9787
  );
9775
9788
  if (!arrayBuffer) {
9776
9789
  throw new Error("Failed to download archive");
9777
9790
  }
9778
9791
  const base64Content = Buffer.from(arrayBuffer).toString("utf-8");
9779
9792
  const binaryContent = Buffer.from(base64Content, "base64");
9780
- await writeFile3(this.archivePath, binaryContent);
9793
+ await writeFile3(archivePath, binaryContent);
9781
9794
  },
9782
9795
  rollback: async () => {
9783
9796
  if (this.archivePath) {