@posthog/agent 2.1.107 → 2.1.112

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.
@@ -904,7 +904,7 @@ var import_hono = require("hono");
904
904
  // package.json
905
905
  var package_default = {
906
906
  name: "@posthog/agent",
907
- version: "2.1.107",
907
+ version: "2.1.112",
908
908
  repository: "https://github.com/PostHog/twig",
909
909
  description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
910
910
  exports: {
@@ -989,10 +989,9 @@ var package_default = {
989
989
  },
990
990
  dependencies: {
991
991
  "@agentclientprotocol/sdk": "^0.14.0",
992
- "@anthropic-ai/claude-agent-sdk": "0.2.58",
992
+ "@anthropic-ai/claude-agent-sdk": "0.2.59",
993
993
  "@anthropic-ai/sdk": "^0.71.0",
994
994
  "@hono/node-server": "^1.19.9",
995
- "@modelcontextprotocol/sdk": "^1.25.3",
996
995
  "@opentelemetry/api-logs": "^0.208.0",
997
996
  "@opentelemetry/exporter-logs-otlp-http": "^0.208.0",
998
997
  "@opentelemetry/resources": "^2.0.0",
@@ -2477,68 +2476,61 @@ async function handleUserAssistantMessage(message, context) {
2477
2476
  }
2478
2477
 
2479
2478
  // src/adapters/claude/mcp/tool-metadata.ts
2480
- var import_client = require("@modelcontextprotocol/sdk/client/index.js");
2481
- var import_streamableHttp = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
2482
2479
  var mcpToolMetadataCache = /* @__PURE__ */ new Map();
2480
+ var PENDING_RETRY_INTERVAL_MS = 1e3;
2481
+ var PENDING_MAX_RETRIES = 10;
2483
2482
  function buildToolKey(serverName, toolName) {
2484
2483
  return `mcp__${serverName}__${toolName}`;
2485
2484
  }
2486
- function isHttpMcpServer(config) {
2487
- return config.type === "http" && typeof config.url === "string";
2485
+ function delay(ms) {
2486
+ return new Promise((resolve4) => setTimeout(resolve4, ms));
2488
2487
  }
2489
- async function fetchToolsFromHttpServer(_serverName, config) {
2490
- const transport = new import_streamableHttp.StreamableHTTPClientTransport(new URL(config.url), {
2491
- requestInit: {
2492
- headers: config.headers ?? {}
2493
- }
2494
- });
2495
- const client = new import_client.Client({
2496
- name: "twig-metadata-fetcher",
2497
- version: "1.0.0"
2498
- });
2499
- try {
2500
- await client.connect(transport);
2501
- const result = await client.listTools();
2502
- return result.tools;
2503
- } finally {
2504
- await client.close().catch(() => {
2505
- });
2506
- }
2507
- }
2508
- function extractToolMetadata(tool) {
2509
- return {
2510
- readOnly: tool.annotations?.readOnlyHint === true
2511
- };
2512
- }
2513
- async function fetchMcpToolMetadata(mcpServers, logger = new Logger({ debug: false, prefix: "[McpToolMetadata]" })) {
2514
- const fetchPromises = [];
2515
- for (const [serverName, config] of Object.entries(mcpServers)) {
2516
- if (!isHttpMcpServer(config)) {
2517
- continue;
2488
+ async function fetchMcpToolMetadata(q, logger = new Logger({ debug: false, prefix: "[McpToolMetadata]" })) {
2489
+ let retries = 0;
2490
+ while (retries <= PENDING_MAX_RETRIES) {
2491
+ let statuses;
2492
+ try {
2493
+ statuses = await q.mcpServerStatus();
2494
+ } catch (error) {
2495
+ logger.error("Failed to fetch MCP server status", {
2496
+ error: error instanceof Error ? error.message : String(error)
2497
+ });
2498
+ return;
2518
2499
  }
2519
- const fetchPromise = fetchToolsFromHttpServer(serverName, config).then((tools) => {
2520
- const toolCount = tools.length;
2521
- const readOnlyCount = tools.filter(
2522
- (t) => t.annotations?.readOnlyHint === true
2523
- ).length;
2524
- for (const tool of tools) {
2525
- const toolKey = buildToolKey(serverName, tool.name);
2526
- mcpToolMetadataCache.set(toolKey, extractToolMetadata(tool));
2500
+ const pendingServers = statuses.filter((s) => s.status === "pending");
2501
+ for (const server of statuses) {
2502
+ if (server.status !== "connected" || !server.tools) {
2503
+ continue;
2504
+ }
2505
+ let readOnlyCount = 0;
2506
+ for (const tool of server.tools) {
2507
+ const toolKey = buildToolKey(server.name, tool.name);
2508
+ const readOnly = tool.annotations?.readOnly === true;
2509
+ mcpToolMetadataCache.set(toolKey, { readOnly });
2510
+ if (readOnly) readOnlyCount++;
2527
2511
  }
2528
2512
  logger.info("Fetched MCP tool metadata", {
2529
- serverName,
2530
- toolCount,
2513
+ serverName: server.name,
2514
+ toolCount: server.tools.length,
2531
2515
  readOnlyCount
2532
2516
  });
2533
- }).catch((error) => {
2534
- logger.error("Failed to fetch MCP tool metadata", {
2535
- serverName,
2536
- error: error instanceof Error ? error.message : String(error)
2517
+ }
2518
+ if (pendingServers.length === 0) {
2519
+ return;
2520
+ }
2521
+ retries++;
2522
+ if (retries > PENDING_MAX_RETRIES) {
2523
+ logger.warn("Gave up waiting for pending MCP servers", {
2524
+ pendingServers: pendingServers.map((s) => s.name)
2537
2525
  });
2526
+ return;
2527
+ }
2528
+ logger.info("Waiting for pending MCP servers", {
2529
+ pendingServers: pendingServers.map((s) => s.name),
2530
+ retry: retries
2538
2531
  });
2539
- fetchPromises.push(fetchPromise);
2532
+ await delay(PENDING_RETRY_INTERVAL_MS);
2540
2533
  }
2541
- await Promise.all(fetchPromises);
2542
2534
  }
2543
2535
  function isMcpToolReadOnly(toolName) {
2544
2536
  const metadata = mcpToolMetadataCache.get(toolName);
@@ -3171,7 +3163,8 @@ function buildEnvironment() {
3171
3163
  ...process.env,
3172
3164
  ELECTRON_RUN_AS_NODE: "1",
3173
3165
  CLAUDE_CODE_ENABLE_ASK_USER_QUESTION_TOOL: "true",
3174
- ENABLE_EXPERIMENTAL_MCP_CLI: "true"
3166
+ // Offload all MCP tools by default
3167
+ ENABLE_TOOL_SEARCH: "auto:0"
3175
3168
  };
3176
3169
  }
3177
3170
  function buildHooks(userHooks, onModeChange) {
@@ -3410,7 +3403,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
3410
3403
  });
3411
3404
  }
3412
3405
  const modelOptions = await this.getModelConfigOptions();
3413
- this.deferBackgroundFetches(q, sessionId, mcpServers);
3406
+ this.deferBackgroundFetches(q, sessionId);
3414
3407
  session.modelId = modelOptions.currentModelId;
3415
3408
  const resolvedSdkModel = toSdkModelId(modelOptions.currentModelId);
3416
3409
  if (resolvedSdkModel !== DEFAULT_MODEL) {
@@ -3455,7 +3448,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
3455
3448
  if (validation.result === "timeout") {
3456
3449
  throw new Error("Session validation timed out");
3457
3450
  }
3458
- this.deferBackgroundFetches(q, sessionId, mcpServers);
3451
+ this.deferBackgroundFetches(q, sessionId);
3459
3452
  const configOptions = await this.buildConfigOptions();
3460
3453
  return { configOptions };
3461
3454
  }
@@ -3643,10 +3636,10 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
3643
3636
  * Fire-and-forget: fetch slash commands and MCP tool metadata in parallel.
3644
3637
  * Both populate caches used later — neither is needed to return configOptions.
3645
3638
  */
3646
- deferBackgroundFetches(q, sessionId, mcpServers) {
3639
+ deferBackgroundFetches(q, sessionId) {
3647
3640
  Promise.all([
3648
3641
  getAvailableSlashCommands(q),
3649
- fetchMcpToolMetadata(mcpServers, this.logger)
3642
+ fetchMcpToolMetadata(q, this.logger)
3650
3643
  ]).then(([slashCommands]) => {
3651
3644
  this.sendAvailableCommandsUpdate(sessionId, slashCommands);
3652
3645
  }).catch((err) => {
@@ -3744,9 +3737,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
3744
3737
  case "tool_use_summary":
3745
3738
  return null;
3746
3739
  default:
3747
- this.logger.warn("Unhandled message type", {
3748
- type: message.type
3749
- });
3740
+ unreachable(message, this.logger);
3750
3741
  return null;
3751
3742
  }
3752
3743
  }
@@ -4580,18 +4571,18 @@ var SessionLogWriter = class _SessionLogWriter {
4580
4571
  const retryCount = this.retryCounts.get(sessionId) ?? 0;
4581
4572
  const lastAttempt = this.lastFlushAttemptTime.get(sessionId) ?? 0;
4582
4573
  const elapsed = Date.now() - lastAttempt;
4583
- let delay2;
4574
+ let delay3;
4584
4575
  if (retryCount > 0) {
4585
- delay2 = Math.min(
4576
+ delay3 = Math.min(
4586
4577
  _SessionLogWriter.FLUSH_DEBOUNCE_MS * 2 ** retryCount,
4587
4578
  _SessionLogWriter.MAX_RETRY_DELAY_MS
4588
4579
  );
4589
4580
  } else if (elapsed >= _SessionLogWriter.FLUSH_MAX_INTERVAL_MS) {
4590
- delay2 = 0;
4581
+ delay3 = 0;
4591
4582
  } else {
4592
- delay2 = _SessionLogWriter.FLUSH_DEBOUNCE_MS;
4583
+ delay3 = _SessionLogWriter.FLUSH_DEBOUNCE_MS;
4593
4584
  }
4594
- const timeout = setTimeout(() => this.flush(sessionId), delay2);
4585
+ const timeout = setTimeout(() => this.flush(sessionId), delay3);
4595
4586
  this.flushTimeouts.set(sessionId, timeout);
4596
4587
  }
4597
4588
  writeToLocalCache(sessionId, entry) {
@@ -4813,7 +4804,7 @@ function pick(source, properties) {
4813
4804
  });
4814
4805
  return out;
4815
4806
  }
4816
- function delay(duration = 0) {
4807
+ function delay2(duration = 0) {
4817
4808
  return new Promise((done) => setTimeout(done, duration));
4818
4809
  }
4819
4810
  function orVoid(input) {
@@ -5080,7 +5071,7 @@ __export(utils_exports, {
5080
5071
  bufferToString: () => bufferToString,
5081
5072
  callTaskParser: () => callTaskParser,
5082
5073
  createInstanceConfig: () => createInstanceConfig,
5083
- delay: () => delay,
5074
+ delay: () => delay2,
5084
5075
  filterArray: () => filterArray,
5085
5076
  filterFunction: () => filterFunction,
5086
5077
  filterHasLength: () => filterHasLength,
@@ -8893,7 +8884,7 @@ function completionDetectionPlugin({
8893
8884
  if (flag === false) {
8894
8885
  return;
8895
8886
  }
8896
- (flag === true ? event.promise : event.promise.then(() => delay(flag))).then(timeout.done);
8887
+ (flag === true ? event.promise : event.promise.then(() => delay2(flag))).then(timeout.done);
8897
8888
  }
8898
8889
  return {
8899
8890
  type: "spawn.after",
@@ -8909,7 +8900,7 @@ function completionDetectionPlugin({
8909
8900
  try {
8910
8901
  await events.result;
8911
8902
  if (deferClose) {
8912
- await delay(50);
8903
+ await delay2(50);
8913
8904
  }
8914
8905
  close(events.exitCode);
8915
8906
  } catch (err) {