@posthog/agent 2.1.111 → 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.111",
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: {
@@ -992,7 +992,6 @@ var package_default = {
992
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);
@@ -3411,7 +3403,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
3411
3403
  });
3412
3404
  }
3413
3405
  const modelOptions = await this.getModelConfigOptions();
3414
- this.deferBackgroundFetches(q, sessionId, mcpServers);
3406
+ this.deferBackgroundFetches(q, sessionId);
3415
3407
  session.modelId = modelOptions.currentModelId;
3416
3408
  const resolvedSdkModel = toSdkModelId(modelOptions.currentModelId);
3417
3409
  if (resolvedSdkModel !== DEFAULT_MODEL) {
@@ -3456,7 +3448,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
3456
3448
  if (validation.result === "timeout") {
3457
3449
  throw new Error("Session validation timed out");
3458
3450
  }
3459
- this.deferBackgroundFetches(q, sessionId, mcpServers);
3451
+ this.deferBackgroundFetches(q, sessionId);
3460
3452
  const configOptions = await this.buildConfigOptions();
3461
3453
  return { configOptions };
3462
3454
  }
@@ -3644,10 +3636,10 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
3644
3636
  * Fire-and-forget: fetch slash commands and MCP tool metadata in parallel.
3645
3637
  * Both populate caches used later — neither is needed to return configOptions.
3646
3638
  */
3647
- deferBackgroundFetches(q, sessionId, mcpServers) {
3639
+ deferBackgroundFetches(q, sessionId) {
3648
3640
  Promise.all([
3649
3641
  getAvailableSlashCommands(q),
3650
- fetchMcpToolMetadata(mcpServers, this.logger)
3642
+ fetchMcpToolMetadata(q, this.logger)
3651
3643
  ]).then(([slashCommands]) => {
3652
3644
  this.sendAvailableCommandsUpdate(sessionId, slashCommands);
3653
3645
  }).catch((err) => {
@@ -4579,18 +4571,18 @@ var SessionLogWriter = class _SessionLogWriter {
4579
4571
  const retryCount = this.retryCounts.get(sessionId) ?? 0;
4580
4572
  const lastAttempt = this.lastFlushAttemptTime.get(sessionId) ?? 0;
4581
4573
  const elapsed = Date.now() - lastAttempt;
4582
- let delay2;
4574
+ let delay3;
4583
4575
  if (retryCount > 0) {
4584
- delay2 = Math.min(
4576
+ delay3 = Math.min(
4585
4577
  _SessionLogWriter.FLUSH_DEBOUNCE_MS * 2 ** retryCount,
4586
4578
  _SessionLogWriter.MAX_RETRY_DELAY_MS
4587
4579
  );
4588
4580
  } else if (elapsed >= _SessionLogWriter.FLUSH_MAX_INTERVAL_MS) {
4589
- delay2 = 0;
4581
+ delay3 = 0;
4590
4582
  } else {
4591
- delay2 = _SessionLogWriter.FLUSH_DEBOUNCE_MS;
4583
+ delay3 = _SessionLogWriter.FLUSH_DEBOUNCE_MS;
4592
4584
  }
4593
- const timeout = setTimeout(() => this.flush(sessionId), delay2);
4585
+ const timeout = setTimeout(() => this.flush(sessionId), delay3);
4594
4586
  this.flushTimeouts.set(sessionId, timeout);
4595
4587
  }
4596
4588
  writeToLocalCache(sessionId, entry) {
@@ -4812,7 +4804,7 @@ function pick(source, properties) {
4812
4804
  });
4813
4805
  return out;
4814
4806
  }
4815
- function delay(duration = 0) {
4807
+ function delay2(duration = 0) {
4816
4808
  return new Promise((done) => setTimeout(done, duration));
4817
4809
  }
4818
4810
  function orVoid(input) {
@@ -5079,7 +5071,7 @@ __export(utils_exports, {
5079
5071
  bufferToString: () => bufferToString,
5080
5072
  callTaskParser: () => callTaskParser,
5081
5073
  createInstanceConfig: () => createInstanceConfig,
5082
- delay: () => delay,
5074
+ delay: () => delay2,
5083
5075
  filterArray: () => filterArray,
5084
5076
  filterFunction: () => filterFunction,
5085
5077
  filterHasLength: () => filterHasLength,
@@ -8892,7 +8884,7 @@ function completionDetectionPlugin({
8892
8884
  if (flag === false) {
8893
8885
  return;
8894
8886
  }
8895
- (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);
8896
8888
  }
8897
8889
  return {
8898
8890
  type: "spawn.after",
@@ -8908,7 +8900,7 @@ function completionDetectionPlugin({
8908
8900
  try {
8909
8901
  await events.result;
8910
8902
  if (deferClose) {
8911
- await delay(50);
8903
+ await delay2(50);
8912
8904
  }
8913
8905
  close(events.exitCode);
8914
8906
  } catch (err) {