@posthog/agent 2.1.111 → 2.1.113
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/claude/conversion/tool-use-to-acp.js +20 -1
- package/dist/adapters/claude/conversion/tool-use-to-acp.js.map +1 -1
- package/dist/adapters/claude/permissions/permission-options.js +0 -4
- package/dist/adapters/claude/permissions/permission-options.js.map +1 -1
- package/dist/adapters/claude/tools.js +0 -2
- package/dist/adapters/claude/tools.js.map +1 -1
- package/dist/agent.js +93 -81
- package/dist/agent.js.map +1 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +1 -1
- package/dist/posthog-api.js +1 -2
- package/dist/posthog-api.js.map +1 -1
- package/dist/server/agent-server.js +97 -85
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +97 -85
- package/dist/server/bin.cjs.map +1 -1
- package/package.json +1 -2
- package/src/adapters/claude/claude-agent.ts +4 -8
- package/src/adapters/claude/conversion/tool-use-to-acp.ts +22 -1
- package/src/adapters/claude/mcp/tool-metadata.ts +65 -71
package/dist/server/bin.cjs
CHANGED
|
@@ -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.
|
|
907
|
+
version: "2.1.113",
|
|
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",
|
|
@@ -1603,6 +1602,75 @@ var createPostToolUseHook = ({ onModeChange }) => async (input, toolUseID) => {
|
|
|
1603
1602
|
return { continue: true };
|
|
1604
1603
|
};
|
|
1605
1604
|
|
|
1605
|
+
// src/adapters/claude/mcp/tool-metadata.ts
|
|
1606
|
+
var mcpToolMetadataCache = /* @__PURE__ */ new Map();
|
|
1607
|
+
var PENDING_RETRY_INTERVAL_MS = 1e3;
|
|
1608
|
+
var PENDING_MAX_RETRIES = 10;
|
|
1609
|
+
function buildToolKey(serverName, toolName) {
|
|
1610
|
+
return `mcp__${serverName}__${toolName}`;
|
|
1611
|
+
}
|
|
1612
|
+
function delay(ms) {
|
|
1613
|
+
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
1614
|
+
}
|
|
1615
|
+
async function fetchMcpToolMetadata(q, logger = new Logger({ debug: false, prefix: "[McpToolMetadata]" })) {
|
|
1616
|
+
let retries = 0;
|
|
1617
|
+
while (retries <= PENDING_MAX_RETRIES) {
|
|
1618
|
+
let statuses;
|
|
1619
|
+
try {
|
|
1620
|
+
statuses = await q.mcpServerStatus();
|
|
1621
|
+
} catch (error) {
|
|
1622
|
+
logger.error("Failed to fetch MCP server status", {
|
|
1623
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1624
|
+
});
|
|
1625
|
+
return;
|
|
1626
|
+
}
|
|
1627
|
+
const pendingServers = statuses.filter((s) => s.status === "pending");
|
|
1628
|
+
for (const server of statuses) {
|
|
1629
|
+
if (server.status !== "connected" || !server.tools) {
|
|
1630
|
+
continue;
|
|
1631
|
+
}
|
|
1632
|
+
let readOnlyCount = 0;
|
|
1633
|
+
for (const tool of server.tools) {
|
|
1634
|
+
const toolKey = buildToolKey(server.name, tool.name);
|
|
1635
|
+
const readOnly = tool.annotations?.readOnly === true;
|
|
1636
|
+
mcpToolMetadataCache.set(toolKey, {
|
|
1637
|
+
readOnly,
|
|
1638
|
+
name: tool.name,
|
|
1639
|
+
description: tool.description
|
|
1640
|
+
});
|
|
1641
|
+
if (readOnly) readOnlyCount++;
|
|
1642
|
+
}
|
|
1643
|
+
logger.info("Fetched MCP tool metadata", {
|
|
1644
|
+
serverName: server.name,
|
|
1645
|
+
toolCount: server.tools.length,
|
|
1646
|
+
readOnlyCount
|
|
1647
|
+
});
|
|
1648
|
+
}
|
|
1649
|
+
if (pendingServers.length === 0) {
|
|
1650
|
+
return;
|
|
1651
|
+
}
|
|
1652
|
+
retries++;
|
|
1653
|
+
if (retries > PENDING_MAX_RETRIES) {
|
|
1654
|
+
logger.warn("Gave up waiting for pending MCP servers", {
|
|
1655
|
+
pendingServers: pendingServers.map((s) => s.name)
|
|
1656
|
+
});
|
|
1657
|
+
return;
|
|
1658
|
+
}
|
|
1659
|
+
logger.info("Waiting for pending MCP servers", {
|
|
1660
|
+
pendingServers: pendingServers.map((s) => s.name),
|
|
1661
|
+
retry: retries
|
|
1662
|
+
});
|
|
1663
|
+
await delay(PENDING_RETRY_INTERVAL_MS);
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
function getMcpToolMetadata(toolName) {
|
|
1667
|
+
return mcpToolMetadataCache.get(toolName);
|
|
1668
|
+
}
|
|
1669
|
+
function isMcpToolReadOnly(toolName) {
|
|
1670
|
+
const metadata = mcpToolMetadataCache.get(toolName);
|
|
1671
|
+
return metadata?.readOnly === true;
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1606
1674
|
// src/adapters/claude/conversion/tool-use-to-acp.ts
|
|
1607
1675
|
var SYSTEM_REMINDER = `
|
|
1608
1676
|
|
|
@@ -1933,14 +2001,27 @@ function toolInfoFromToolUse(toolUse, cachedFileContent, logger = new Logger({ d
|
|
|
1933
2001
|
${output}\`\`\``).build()
|
|
1934
2002
|
};
|
|
1935
2003
|
}
|
|
1936
|
-
default:
|
|
2004
|
+
default: {
|
|
2005
|
+
if (name?.startsWith("mcp__")) {
|
|
2006
|
+
return mcpToolInfo(name, input);
|
|
2007
|
+
}
|
|
1937
2008
|
return {
|
|
1938
2009
|
title: name || "Unknown Tool",
|
|
1939
2010
|
kind: "other",
|
|
1940
2011
|
content: []
|
|
1941
2012
|
};
|
|
2013
|
+
}
|
|
1942
2014
|
}
|
|
1943
2015
|
}
|
|
2016
|
+
function mcpToolInfo(name, _input) {
|
|
2017
|
+
const metadata = getMcpToolMetadata(name);
|
|
2018
|
+
const title = metadata?.name ?? (name.split("__").slice(2).join("__") || name);
|
|
2019
|
+
return {
|
|
2020
|
+
title,
|
|
2021
|
+
kind: "other",
|
|
2022
|
+
content: []
|
|
2023
|
+
};
|
|
2024
|
+
}
|
|
1944
2025
|
function toolUpdateFromToolResult(toolResult, toolUse) {
|
|
1945
2026
|
switch (toolUse?.name) {
|
|
1946
2027
|
case "Read":
|
|
@@ -2476,75 +2557,6 @@ async function handleUserAssistantMessage(message, context) {
|
|
|
2476
2557
|
return {};
|
|
2477
2558
|
}
|
|
2478
2559
|
|
|
2479
|
-
// 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
|
-
var mcpToolMetadataCache = /* @__PURE__ */ new Map();
|
|
2483
|
-
function buildToolKey(serverName, toolName) {
|
|
2484
|
-
return `mcp__${serverName}__${toolName}`;
|
|
2485
|
-
}
|
|
2486
|
-
function isHttpMcpServer(config) {
|
|
2487
|
-
return config.type === "http" && typeof config.url === "string";
|
|
2488
|
-
}
|
|
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;
|
|
2518
|
-
}
|
|
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));
|
|
2527
|
-
}
|
|
2528
|
-
logger.info("Fetched MCP tool metadata", {
|
|
2529
|
-
serverName,
|
|
2530
|
-
toolCount,
|
|
2531
|
-
readOnlyCount
|
|
2532
|
-
});
|
|
2533
|
-
}).catch((error) => {
|
|
2534
|
-
logger.error("Failed to fetch MCP tool metadata", {
|
|
2535
|
-
serverName,
|
|
2536
|
-
error: error instanceof Error ? error.message : String(error)
|
|
2537
|
-
});
|
|
2538
|
-
});
|
|
2539
|
-
fetchPromises.push(fetchPromise);
|
|
2540
|
-
}
|
|
2541
|
-
await Promise.all(fetchPromises);
|
|
2542
|
-
}
|
|
2543
|
-
function isMcpToolReadOnly(toolName) {
|
|
2544
|
-
const metadata = mcpToolMetadataCache.get(toolName);
|
|
2545
|
-
return metadata?.readOnly === true;
|
|
2546
|
-
}
|
|
2547
|
-
|
|
2548
2560
|
// src/adapters/claude/plan/utils.ts
|
|
2549
2561
|
var os = __toESM(require("os"), 1);
|
|
2550
2562
|
var path = __toESM(require("path"), 1);
|
|
@@ -3411,7 +3423,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
3411
3423
|
});
|
|
3412
3424
|
}
|
|
3413
3425
|
const modelOptions = await this.getModelConfigOptions();
|
|
3414
|
-
this.deferBackgroundFetches(q, sessionId
|
|
3426
|
+
this.deferBackgroundFetches(q, sessionId);
|
|
3415
3427
|
session.modelId = modelOptions.currentModelId;
|
|
3416
3428
|
const resolvedSdkModel = toSdkModelId(modelOptions.currentModelId);
|
|
3417
3429
|
if (resolvedSdkModel !== DEFAULT_MODEL) {
|
|
@@ -3456,7 +3468,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
3456
3468
|
if (validation.result === "timeout") {
|
|
3457
3469
|
throw new Error("Session validation timed out");
|
|
3458
3470
|
}
|
|
3459
|
-
this.deferBackgroundFetches(q, sessionId
|
|
3471
|
+
this.deferBackgroundFetches(q, sessionId);
|
|
3460
3472
|
const configOptions = await this.buildConfigOptions();
|
|
3461
3473
|
return { configOptions };
|
|
3462
3474
|
}
|
|
@@ -3644,10 +3656,10 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
3644
3656
|
* Fire-and-forget: fetch slash commands and MCP tool metadata in parallel.
|
|
3645
3657
|
* Both populate caches used later — neither is needed to return configOptions.
|
|
3646
3658
|
*/
|
|
3647
|
-
deferBackgroundFetches(q, sessionId
|
|
3659
|
+
deferBackgroundFetches(q, sessionId) {
|
|
3648
3660
|
Promise.all([
|
|
3649
3661
|
getAvailableSlashCommands(q),
|
|
3650
|
-
fetchMcpToolMetadata(
|
|
3662
|
+
fetchMcpToolMetadata(q, this.logger)
|
|
3651
3663
|
]).then(([slashCommands]) => {
|
|
3652
3664
|
this.sendAvailableCommandsUpdate(sessionId, slashCommands);
|
|
3653
3665
|
}).catch((err) => {
|
|
@@ -4579,18 +4591,18 @@ var SessionLogWriter = class _SessionLogWriter {
|
|
|
4579
4591
|
const retryCount = this.retryCounts.get(sessionId) ?? 0;
|
|
4580
4592
|
const lastAttempt = this.lastFlushAttemptTime.get(sessionId) ?? 0;
|
|
4581
4593
|
const elapsed = Date.now() - lastAttempt;
|
|
4582
|
-
let
|
|
4594
|
+
let delay3;
|
|
4583
4595
|
if (retryCount > 0) {
|
|
4584
|
-
|
|
4596
|
+
delay3 = Math.min(
|
|
4585
4597
|
_SessionLogWriter.FLUSH_DEBOUNCE_MS * 2 ** retryCount,
|
|
4586
4598
|
_SessionLogWriter.MAX_RETRY_DELAY_MS
|
|
4587
4599
|
);
|
|
4588
4600
|
} else if (elapsed >= _SessionLogWriter.FLUSH_MAX_INTERVAL_MS) {
|
|
4589
|
-
|
|
4601
|
+
delay3 = 0;
|
|
4590
4602
|
} else {
|
|
4591
|
-
|
|
4603
|
+
delay3 = _SessionLogWriter.FLUSH_DEBOUNCE_MS;
|
|
4592
4604
|
}
|
|
4593
|
-
const timeout = setTimeout(() => this.flush(sessionId),
|
|
4605
|
+
const timeout = setTimeout(() => this.flush(sessionId), delay3);
|
|
4594
4606
|
this.flushTimeouts.set(sessionId, timeout);
|
|
4595
4607
|
}
|
|
4596
4608
|
writeToLocalCache(sessionId, entry) {
|
|
@@ -4812,7 +4824,7 @@ function pick(source, properties) {
|
|
|
4812
4824
|
});
|
|
4813
4825
|
return out;
|
|
4814
4826
|
}
|
|
4815
|
-
function
|
|
4827
|
+
function delay2(duration = 0) {
|
|
4816
4828
|
return new Promise((done) => setTimeout(done, duration));
|
|
4817
4829
|
}
|
|
4818
4830
|
function orVoid(input) {
|
|
@@ -5079,7 +5091,7 @@ __export(utils_exports, {
|
|
|
5079
5091
|
bufferToString: () => bufferToString,
|
|
5080
5092
|
callTaskParser: () => callTaskParser,
|
|
5081
5093
|
createInstanceConfig: () => createInstanceConfig,
|
|
5082
|
-
delay: () =>
|
|
5094
|
+
delay: () => delay2,
|
|
5083
5095
|
filterArray: () => filterArray,
|
|
5084
5096
|
filterFunction: () => filterFunction,
|
|
5085
5097
|
filterHasLength: () => filterHasLength,
|
|
@@ -8892,7 +8904,7 @@ function completionDetectionPlugin({
|
|
|
8892
8904
|
if (flag === false) {
|
|
8893
8905
|
return;
|
|
8894
8906
|
}
|
|
8895
|
-
(flag === true ? event.promise : event.promise.then(() =>
|
|
8907
|
+
(flag === true ? event.promise : event.promise.then(() => delay2(flag))).then(timeout.done);
|
|
8896
8908
|
}
|
|
8897
8909
|
return {
|
|
8898
8910
|
type: "spawn.after",
|
|
@@ -8908,7 +8920,7 @@ function completionDetectionPlugin({
|
|
|
8908
8920
|
try {
|
|
8909
8921
|
await events.result;
|
|
8910
8922
|
if (deferClose) {
|
|
8911
|
-
await
|
|
8923
|
+
await delay2(50);
|
|
8912
8924
|
}
|
|
8913
8925
|
close(events.exitCode);
|
|
8914
8926
|
} catch (err) {
|