@tangle-network/agent-runtime 0.350.2 → 0.353.2
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/{activation-CfJMyzEs.js → activation-BkRaG5t0.js} +4 -4
- package/dist/{activation-CfJMyzEs.js.map → activation-BkRaG5t0.js.map} +1 -1
- package/dist/{activation-DyiHrTlS.d.ts → activation-CFS31SWI.d.ts} +2 -2
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +3 -3
- package/dist/{bundle-Ze8pd07a.js → bundle-DeDkJbsr.js} +2 -2
- package/dist/{bundle-Ze8pd07a.js.map → bundle-DeDkJbsr.js.map} +1 -1
- package/dist/candidate-execution/index.js +4 -4
- package/dist/chat-turn.d.ts +2 -0
- package/dist/chat-turn.js +1 -0
- package/dist/{coordination-manager-BkVfWlMz.js → coordination-manager-BrRkc55z.js} +4 -4
- package/dist/{coordination-manager-BkVfWlMz.js.map → coordination-manager-BrRkc55z.js.map} +1 -1
- package/dist/{delegate-DgEie4ad.js → delegate-CAdajnf8.js} +3 -3
- package/dist/{delegate-DgEie4ad.js.map → delegate-CAdajnf8.js.map} +1 -1
- package/dist/durable.d.ts +7 -130
- package/dist/durable.js +24 -952
- package/dist/durable.js.map +1 -1
- package/dist/{errors-wuhGvpE3.js → errors-AzSuGI23.js} +4 -1
- package/dist/errors-AzSuGI23.js.map +1 -0
- package/dist/execution-handle-Bd2_nUB6.js +167 -0
- package/dist/execution-handle-Bd2_nUB6.js.map +1 -0
- package/dist/execution-handle-CujvqgCn.d.ts +130 -0
- package/dist/{graph-Cx0FhKSE.js → graph-CyaIHVGR.js} +7 -6
- package/dist/{graph-Cx0FhKSE.js.map → graph-CyaIHVGR.js.map} +1 -1
- package/dist/{improve-i0HU1-aa.js → improve-DwG-yioQ.js} +10 -9
- package/dist/{improve-i0HU1-aa.js.map → improve-DwG-yioQ.js.map} +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +14 -11
- package/dist/index.js.map +1 -1
- package/dist/intelligence.d.ts +2 -2
- package/dist/intelligence.js +12 -10
- package/dist/intelligence.js.map +1 -1
- package/dist/journal-store-BJPMUydp.js +3925 -0
- package/dist/journal-store-BJPMUydp.js.map +1 -0
- package/dist/kernel.d.ts +1 -1
- package/dist/kernel.js +11 -10
- package/dist/{loop-runner-DvfOXVx9.d.ts → loop-runner-D9rcTNf2.d.ts} +2 -2
- package/dist/{loop-runner-BwN9MhdP.js → loop-runner-DwS3jARE.js} +3 -3
- package/dist/{loop-runner-BwN9MhdP.js.map → loop-runner-DwS3jARE.js.map} +1 -1
- package/dist/loop-runner-bin.d.ts +1 -1
- package/dist/loop-runner-bin.js +1 -1
- package/dist/mcp/bin.js +4 -4
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +8 -8
- package/dist/mcp/memory-bin.js +2 -2
- package/dist/{model-policy-GSxWwP-b.js → model-policy-C-RGAUW4.js} +2 -2
- package/dist/{model-policy-GSxWwP-b.js.map → model-policy-C-RGAUW4.js.map} +1 -1
- package/dist/{prepare-DE8TQnLu.js → prepare-XWwsOh8O.js} +4 -3
- package/dist/{prepare-DE8TQnLu.js.map → prepare-XWwsOh8O.js.map} +1 -1
- package/dist/{profile-CAhZDW2T.js → profile-C01SQZKa.js} +3 -3
- package/dist/{profile-CAhZDW2T.js.map → profile-C01SQZKa.js.map} +1 -1
- package/dist/profiles.d.ts +1 -1
- package/dist/profiles.js +2 -2
- package/dist/{provision-supervisor-Bde_FF0R.js → provision-supervisor-AEnei2Jq.js} +7 -7
- package/dist/{provision-supervisor-Bde_FF0R.js.map → provision-supervisor-AEnei2Jq.js.map} +1 -1
- package/dist/{run-cancellation-BLy_Zz-w.js → run-cancellation-CoJRKvih.js} +2 -2
- package/dist/{run-cancellation-BLy_Zz-w.js.map → run-cancellation-CoJRKvih.js.map} +1 -1
- package/dist/{runtime-6Ec9sHRe.js → runtime-DCYSaYHW.js} +42 -39
- package/dist/{runtime-6Ec9sHRe.js.map → runtime-DCYSaYHW.js.map} +1 -1
- package/dist/{sandbox-profile-compat-BxMQ1VXv.js → sandbox-profile-compat-CXjozdWL.js} +4 -623
- package/dist/{sandbox-profile-compat-BxMQ1VXv.js.map → sandbox-profile-compat-CXjozdWL.js.map} +1 -1
- package/dist/{search-executor-B7g_5Wjl.js → search-executor-B2jc63hZ.js} +14 -11
- package/dist/{search-executor-B7g_5Wjl.js.map → search-executor-B2jc63hZ.js.map} +1 -1
- package/dist/{server-fvEMwGMQ.js → server-CKBTwWM8.js} +6 -6
- package/dist/{server-fvEMwGMQ.js.map → server-CKBTwWM8.js.map} +1 -1
- package/dist/{structural-rollout-B86bSixU.js → structural-rollout-rRT3ypqz.js} +7 -5
- package/dist/{structural-rollout-B86bSixU.js.map → structural-rollout-rRT3ypqz.js.map} +1 -1
- package/dist/{supervise-CaeZcgAW.js → supervise-B3_wtgHS.js} +18 -21
- package/dist/supervise-B3_wtgHS.js.map +1 -0
- package/dist/supervision-discovery-CewADdEs.js +772 -0
- package/dist/supervision-discovery-CewADdEs.js.map +1 -0
- package/dist/{supervisor-C1OePYE-.js → supervisor-C_sDmX5H.js} +156 -3984
- package/dist/supervisor-C_sDmX5H.js.map +1 -0
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +13 -13
- package/dist/{tool-server-CwuYeW_Z.js → tool-server-CZWd_Opp.js} +2 -2
- package/dist/{tool-server-CwuYeW_Z.js.map → tool-server-CZWd_Opp.js.map} +1 -1
- package/dist/{top-snapshot-ChwpTr7A.js → top-snapshot-DcV7VG4m.js} +178 -161
- package/dist/top-snapshot-DcV7VG4m.js.map +1 -0
- package/dist/tui/bin.js +45 -74
- package/dist/tui/bin.js.map +1 -1
- package/dist/tui/index.d.ts +25 -54
- package/dist/tui/index.js +2 -2
- package/dist/{types-Fowuwdz2.d.ts → types-DTHxh4X9.d.ts} +47 -63
- package/dist/util-ebWMWzY0.js +624 -0
- package/dist/util-ebWMWzY0.js.map +1 -0
- package/dist/workspace-store/index.js +9 -3
- package/dist/workspace-store/index.js.map +1 -1
- package/package.json +18 -13
- package/dist/errors-wuhGvpE3.js.map +0 -1
- package/dist/record-events-B2GUgYdz.js +0 -261
- package/dist/record-events-B2GUgYdz.js.map +0 -1
- package/dist/supervise-CaeZcgAW.js.map +0 -1
- package/dist/supervisor-C1OePYE-.js.map +0 -1
- package/dist/top-snapshot-ChwpTr7A.js.map +0 -1
package/dist/testing.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Bv as DecideGate, By as McpToolDescriptor, Ch as ToolLoopCallContext, Ct as SuperviseProfileEntry, Dh as ToolLoopMessageRecord, Eh as ToolLoopCompactionOptions, Ip as PriorCoordination, Jv as ChildQuestionInbox, M as Budget, Nd as superviseWithTestBrain, Np as CoordinationDeliveryEvidence, Nv as CoordinationEvent, Oh as ToolLoopToolCall, Om as Inbox, Qf as ManagerWakePolicy, Rd as SuperviseTestOptions, Rf as supervisorAgentWithTestBrain, Sp as SupervisorFinalizer, Uy as BusRecord, Wv as RouteFlow, Yg as DeliverableSpec, Yv as EscalateQuestion, Zi as ResultBlobStore, _t as PeerAuditAccess, _y as MapOnSettleRoute, ap as StopRule, bt as SpawnPreflightContext, fd as runGraphWithTestBrain, ft as CoordinationTools, gt as MakeWorkerAgent, ht as GraphSubtasks, ld as RunGraphTestOptions, mt as GraphSubtaskPreparation, qf as SupervisorAgentTestDeps, rb as AnalyzeOnSettleRoute, sy as AuthorizeDownMessage, tb as AnalystRegistry, tm as SpawnResourceReader, ua as Agent, up as RunCancelRequest, uy as ContinuityMode, wh as ToolLoopChat, xt as SpawnRefusal, yh as RouterResponseReceipt, yt as SpawnPreflight, zv as WorkerWatchOptions, zx as HarnessTranscriptCapture } from "./types-DTHxh4X9.js";
|
|
2
2
|
import { AgentImprovementProposal, AgentProfile, AgentProfileImprovementMeasuredComparison, SandboxSizePreset } from "@tangle-network/agent-interface";
|
|
3
3
|
/** What the brain returned for one turn, as the recorder keeps it. */
|
|
4
4
|
interface RouterTranscriptReply {
|
package/dist/testing.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { P as canonicalCandidateDigest$1, R as immutableCandidateValue } from "./sandbox-profile-compat-
|
|
2
|
-
import { c as verifyAgentImprovementProposal } from "./activation-
|
|
3
|
-
import { a as applyExactAgentProfileDiff, v as parseExactAgentProfile } from "./profile-
|
|
4
|
-
import { N as supervisorAgentWithTestBrain, R as driverAgent, r as superviseWithTestBrain } from "./supervise-
|
|
5
|
-
import { r as runGraphWithTestBrain } from "./graph-
|
|
1
|
+
import { P as canonicalCandidateDigest$1, R as immutableCandidateValue } from "./sandbox-profile-compat-CXjozdWL.js";
|
|
2
|
+
import { c as verifyAgentImprovementProposal } from "./activation-BkRaG5t0.js";
|
|
3
|
+
import { a as applyExactAgentProfileDiff, v as parseExactAgentProfile } from "./profile-C01SQZKa.js";
|
|
4
|
+
import { N as supervisorAgentWithTestBrain, R as driverAgent, r as superviseWithTestBrain } from "./supervise-B3_wtgHS.js";
|
|
5
|
+
import { r as runGraphWithTestBrain } from "./graph-CyaIHVGR.js";
|
|
6
6
|
import { SANDBOX_SIZE_PRESET_NAMES, canonicalAgentProfileDigest } from "@tangle-network/agent-interface";
|
|
7
7
|
// src/testing/fixtures/agent-improvement-proposal.json
|
|
8
8
|
var agent_improvement_proposal_default = {
|
|
9
9
|
changedSurfaces: ["prompt"],
|
|
10
|
-
digest: "sha256:
|
|
10
|
+
digest: "sha256:c8b21629cf36d183e5a87df5ba9fd9900dc32d436fffb8c26adaf403b411a29f",
|
|
11
11
|
evaluation: {
|
|
12
12
|
"decision": {
|
|
13
13
|
"contributingChecks": [
|
|
@@ -4578,7 +4578,7 @@ var agent_improvement_proposal_default = {
|
|
|
4578
4578
|
],
|
|
4579
4579
|
"metadata": {
|
|
4580
4580
|
"fixture": "agent-improvement-proposal",
|
|
4581
|
-
"runtimeVersion": "0.
|
|
4581
|
+
"runtimeVersion": "0.353.2"
|
|
4582
4582
|
},
|
|
4583
4583
|
"objectives": [
|
|
4584
4584
|
{
|
|
@@ -4689,8 +4689,8 @@ var agent_improvement_proposal_default = {
|
|
|
4689
4689
|
"baselineContentHash": "sha256:5c21ee53e513fc604cb09754e21c392b24a424da0ef37dbf8f1ee4a8a0b08f09",
|
|
4690
4690
|
"candidateContentHash": "sha256:60fcbb1c728194bd51d7d19cb732d1c3f1881dce7e0a6266b41c8b98cfd65693",
|
|
4691
4691
|
"kind": "agent-eval-loop",
|
|
4692
|
-
"recordDigest": "sha256:
|
|
4693
|
-
"runId": "agent-runtime-0.
|
|
4692
|
+
"recordDigest": "sha256:96c004afe5a00721ff7de3a937d553a8be80d93394cbd31014e64be148f11279",
|
|
4693
|
+
"runId": "agent-runtime-0.353.2-proposal-fixture",
|
|
4694
4694
|
"schema": "agent-candidate-experiment"
|
|
4695
4695
|
}
|
|
4696
4696
|
},
|
|
@@ -4713,12 +4713,12 @@ var agent_improvement_proposal_default = {
|
|
|
4713
4713
|
}],
|
|
4714
4714
|
kind: "agent-improvement-proposal",
|
|
4715
4715
|
proposedAt: "2026-07-10T01:00:00.000Z",
|
|
4716
|
-
runId: "agent-runtime-0.
|
|
4716
|
+
runId: "agent-runtime-0.353.2-proposal-fixture"
|
|
4717
4717
|
};
|
|
4718
4718
|
// src/testing/fixtures/agent-profile-improvement-proposal.json
|
|
4719
4719
|
var agent_profile_improvement_proposal_default = {
|
|
4720
4720
|
changedSurfaces: ["prompt", "skills"],
|
|
4721
|
-
digest: "sha256:
|
|
4721
|
+
digest: "sha256:80586cfb745b31a31848f647728629712e4617fd47ae4fd6426fb85d685ca25c",
|
|
4722
4722
|
evaluation: {
|
|
4723
4723
|
"decision": {
|
|
4724
4724
|
"contributingChecks": [
|
|
@@ -6352,7 +6352,7 @@ var agent_profile_improvement_proposal_default = {
|
|
|
6352
6352
|
],
|
|
6353
6353
|
"metadata": {
|
|
6354
6354
|
"fixture": "agent-profile-improvement-proposal",
|
|
6355
|
-
"runtimeVersion": "0.
|
|
6355
|
+
"runtimeVersion": "0.353.2"
|
|
6356
6356
|
},
|
|
6357
6357
|
"objectives": [
|
|
6358
6358
|
{
|
|
@@ -6463,7 +6463,7 @@ var agent_profile_improvement_proposal_default = {
|
|
|
6463
6463
|
"baselineContentHash": "sha256:21c495a37c418c10bde64fbaa188beddeed31f1f051ea60a6a6582a9ee0db704",
|
|
6464
6464
|
"candidateContentHash": "sha256:103f77bc8481601eef1ad5fe6ba84a40dffabc3a44f421f8c8559121edab84e9",
|
|
6465
6465
|
"kind": "agent-eval-loop",
|
|
6466
|
-
"recordDigest": "sha256:
|
|
6466
|
+
"recordDigest": "sha256:0f90ddd5895d4c0e4f153decddec714d8db3b41ee25a604f6a33df28f12ec243",
|
|
6467
6467
|
"runId": "profile-improvement-1",
|
|
6468
6468
|
"schema": "agent-profile-improvement-experiment"
|
|
6469
6469
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { m as ValidationError } from "./errors-
|
|
1
|
+
import { m as ValidationError } from "./errors-AzSuGI23.js";
|
|
2
2
|
import { createInterface } from "node:readline";
|
|
3
3
|
// src/mcp/tool-server.ts
|
|
4
4
|
/**
|
|
@@ -168,4 +168,4 @@ function writeResponse(output, response) {
|
|
|
168
168
|
}
|
|
169
169
|
export { createStdioToolServer as n, PROTOCOL_VERSION as t };
|
|
170
170
|
|
|
171
|
-
//# sourceMappingURL=tool-server-
|
|
171
|
+
//# sourceMappingURL=tool-server-CZWd_Opp.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-server-CwuYeW_Z.js","names":[],"sources":["../src/mcp/tool-server.ts"],"sourcesContent":["/**\n * `createStdioToolServer` — the generic newline-delimited JSON-RPC 2.0 MCP\n * server core: `initialize` / `notifications/initialized` / `tools/list` /\n * `ping` / `tools/call` over a stdio-shaped transport. It answers the\n * client's protocol version when listed in `SUPPORTED_PROTOCOL_VERSIONS`,\n * else 2024-11-05, and publishes tool annotations when a tool declares them.\n *\n * Extracted from `createMcpServer` (server.ts) so every in-repo MCP server —\n * the delegation server, the memory server — serves the ONE wire protocol the\n * same-host client (`connectStdioMcp`, runtime/stdio-mcp-client.ts) speaks.\n * A second hand-rolled serve loop could drift from what the client expects;\n * this core makes that impossible by construction.\n *\n * @experimental\n */\n\nimport { createInterface, type Interface as ReadlineInterface } from 'node:readline'\nimport { ValidationError } from '../errors'\nimport type { JsonRpcMessage, JsonRpcResponse, McpToolDescriptor, McpTransport } from './protocol'\n\nexport type { JsonRpcMessage, JsonRpcResponse, McpToolDescriptor, McpTransport } from './protocol'\n\nexport const PROTOCOL_VERSION = '2024-11-05'\n\n/**\n * Protocol versions this server speaks, newest first. `initialize` answers with\n * the client's requested version when it is listed here, and otherwise with\n * `PROTOCOL_VERSION` (2024-11-05), which every client that speaks 2024-11-05 accepts.\n */\nconst SUPPORTED_PROTOCOL_VERSIONS: readonly string[] = [\n '2025-11-25',\n '2025-06-18',\n '2025-03-26',\n PROTOCOL_VERSION,\n]\n\n/** @experimental */\nexport interface StdioToolServerOptions {\n /** Server display name surfaced via `initialize`. */\n serverName: string\n /** Server version surfaced via `initialize`. */\n serverVersion: string\n /** The tools to serve. Duplicate names throw — a silent shadow would hide a tool. */\n tools: readonly McpToolDescriptor[]\n}\n\n/** @experimental */\nexport interface StdioToolServer {\n /** Tools currently registered, keyed by name. */\n readonly tools: ReadonlyMap<string, McpToolDescriptor>\n /** Handle a single parsed JSON-RPC message. Returns the response object (or `null` for notifications). */\n handle(message: JsonRpcMessage): Promise<JsonRpcResponse | null>\n /** Drive the server on a stdio-shaped transport until `stop()` is called. */\n serve(transport?: McpTransport): Promise<void>\n /** Stop a `serve` call. Subsequent requests are rejected. */\n stop(): void\n}\n\n/** Build the generic stdio JSON-RPC tool server. */\nexport function createStdioToolServer(options: StdioToolServerOptions): StdioToolServer {\n const tools = new Map<string, McpToolDescriptor>()\n for (const tool of options.tools) {\n if (tools.has(tool.name)) {\n throw new ValidationError(`createStdioToolServer: duplicate tool name \"${tool.name}\"`)\n }\n tools.set(tool.name, tool)\n }\n\n let stopped = false\n let activeReadline: ReadlineInterface | undefined\n\n async function handle(message: JsonRpcMessage): Promise<JsonRpcResponse | null> {\n if (stopped) {\n return rpcError(message.id ?? null, -32099, 'server stopped')\n }\n if (message.method === 'initialize') {\n const requested = (message.params as { protocolVersion?: unknown } | undefined)\n ?.protocolVersion\n return rpcResult(message.id ?? null, {\n protocolVersion:\n typeof requested === 'string' && SUPPORTED_PROTOCOL_VERSIONS.includes(requested)\n ? requested\n : PROTOCOL_VERSION,\n capabilities: { tools: {} },\n serverInfo: { name: options.serverName, version: options.serverVersion },\n })\n }\n if (message.method === 'notifications/initialized') {\n // MCP clients send this after the handshake; it has no id and expects\n // no response.\n return null\n }\n if (message.method === 'ping') {\n return rpcResult(message.id ?? null, {})\n }\n if (message.method === 'tools/list') {\n return rpcResult(message.id ?? null, {\n tools: [...tools.values()].map((tool) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n ...(tool.annotations ? { annotations: tool.annotations } : {}),\n })),\n })\n }\n if (message.method === 'tools/call') {\n const params = (message.params ?? {}) as { name?: unknown; arguments?: unknown }\n const name = typeof params.name === 'string' ? params.name : ''\n const tool = tools.get(name)\n if (!tool) {\n return rpcError(message.id ?? null, -32601, `unknown tool: ${name}`)\n }\n try {\n const output = await tool.handler(params.arguments ?? {})\n return rpcResult(message.id ?? null, toolCallResult(output))\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err)\n const code = err instanceof TypeError || err instanceof RangeError ? -32602 : -32000\n return rpcError(message.id ?? null, code, reason)\n }\n }\n if (message.id === undefined || message.id === null) return null\n return rpcError(message.id, -32601, `unknown method: ${message.method}`)\n }\n\n async function serve(transport?: McpTransport): Promise<void> {\n const input = transport?.input ?? process.stdin\n const output = transport?.output ?? process.stdout\n const rl = createInterface({ input, crlfDelay: Number.POSITIVE_INFINITY })\n activeReadline = rl\n return new Promise<void>((resolve, reject) => {\n rl.on('line', (line) => {\n const trimmed = line.trim()\n if (!trimmed) return\n let parsed: JsonRpcMessage | undefined\n try {\n parsed = JSON.parse(trimmed) as JsonRpcMessage\n } catch (err) {\n writeResponse(output, rpcError(null, -32700, `parse error: ${(err as Error).message}`))\n return\n }\n if (parsed?.jsonrpc !== '2.0' || typeof parsed.method !== 'string') {\n writeResponse(output, rpcError(parsed?.id ?? null, -32600, 'invalid request'))\n return\n }\n void handle(parsed).then((response) => {\n if (response) writeResponse(output, response)\n })\n })\n rl.on('close', () => resolve())\n rl.on('error', (err) => reject(err))\n if (stopped) {\n rl.close()\n resolve()\n }\n })\n }\n\n function stop(): void {\n stopped = true\n activeReadline?.close()\n activeReadline = undefined\n }\n\n return { tools, handle, serve, stop }\n}\n\nfunction toolCallResult(output: unknown): {\n content: [{ type: 'text'; text: string }]\n structuredContent?: Record<string, unknown>\n isError: false\n} {\n let json: string | undefined\n try {\n json = JSON.stringify(output)\n } catch (err) {\n const reason = err instanceof Error ? `: ${err.message}` : ''\n throw new TypeError(`MCP tool result must be JSON-serializable${reason}`, { cause: err })\n }\n if (json === undefined) {\n throw new TypeError('MCP tool result must be JSON-serializable')\n }\n\n const serialized = JSON.parse(json) as unknown\n // Preserve string content verbatim. MCP clients pass this text directly to the calling agent.\n const result: {\n content: [{ type: 'text'; text: string }]\n structuredContent?: Record<string, unknown>\n isError: false\n } = {\n content: [{ type: 'text', text: typeof serialized === 'string' ? serialized : json }],\n isError: false,\n }\n if (serialized !== null && typeof serialized === 'object' && !Array.isArray(serialized)) {\n result.structuredContent = serialized as Record<string, unknown>\n }\n return result\n}\n\nfunction rpcResult(id: number | string | null, result: unknown): JsonRpcResponse {\n return { jsonrpc: '2.0', id, result }\n}\n\nfunction rpcError(\n id: number | string | null,\n code: number,\n message: string,\n data?: unknown,\n): JsonRpcResponse {\n return {\n jsonrpc: '2.0',\n id,\n error: data === undefined ? { code, message } : { code, message, data },\n }\n}\n\nfunction writeResponse(output: NodeJS.WritableStream, response: JsonRpcResponse): void {\n output.write(`${JSON.stringify(response)}\\n`)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tool-server-CZWd_Opp.js","names":[],"sources":["../src/mcp/tool-server.ts"],"sourcesContent":["/**\n * `createStdioToolServer` — the generic newline-delimited JSON-RPC 2.0 MCP\n * server core: `initialize` / `notifications/initialized` / `tools/list` /\n * `ping` / `tools/call` over a stdio-shaped transport. It answers the\n * client's protocol version when listed in `SUPPORTED_PROTOCOL_VERSIONS`,\n * else 2024-11-05, and publishes tool annotations when a tool declares them.\n *\n * Extracted from `createMcpServer` (server.ts) so every in-repo MCP server —\n * the delegation server, the memory server — serves the ONE wire protocol the\n * same-host client (`connectStdioMcp`, runtime/stdio-mcp-client.ts) speaks.\n * A second hand-rolled serve loop could drift from what the client expects;\n * this core makes that impossible by construction.\n *\n * @experimental\n */\n\nimport { createInterface, type Interface as ReadlineInterface } from 'node:readline'\nimport { ValidationError } from '../errors'\nimport type { JsonRpcMessage, JsonRpcResponse, McpToolDescriptor, McpTransport } from './protocol'\n\nexport type { JsonRpcMessage, JsonRpcResponse, McpToolDescriptor, McpTransport } from './protocol'\n\nexport const PROTOCOL_VERSION = '2024-11-05'\n\n/**\n * Protocol versions this server speaks, newest first. `initialize` answers with\n * the client's requested version when it is listed here, and otherwise with\n * `PROTOCOL_VERSION` (2024-11-05), which every client that speaks 2024-11-05 accepts.\n */\nconst SUPPORTED_PROTOCOL_VERSIONS: readonly string[] = [\n '2025-11-25',\n '2025-06-18',\n '2025-03-26',\n PROTOCOL_VERSION,\n]\n\n/** @experimental */\nexport interface StdioToolServerOptions {\n /** Server display name surfaced via `initialize`. */\n serverName: string\n /** Server version surfaced via `initialize`. */\n serverVersion: string\n /** The tools to serve. Duplicate names throw — a silent shadow would hide a tool. */\n tools: readonly McpToolDescriptor[]\n}\n\n/** @experimental */\nexport interface StdioToolServer {\n /** Tools currently registered, keyed by name. */\n readonly tools: ReadonlyMap<string, McpToolDescriptor>\n /** Handle a single parsed JSON-RPC message. Returns the response object (or `null` for notifications). */\n handle(message: JsonRpcMessage): Promise<JsonRpcResponse | null>\n /** Drive the server on a stdio-shaped transport until `stop()` is called. */\n serve(transport?: McpTransport): Promise<void>\n /** Stop a `serve` call. Subsequent requests are rejected. */\n stop(): void\n}\n\n/** Build the generic stdio JSON-RPC tool server. */\nexport function createStdioToolServer(options: StdioToolServerOptions): StdioToolServer {\n const tools = new Map<string, McpToolDescriptor>()\n for (const tool of options.tools) {\n if (tools.has(tool.name)) {\n throw new ValidationError(`createStdioToolServer: duplicate tool name \"${tool.name}\"`)\n }\n tools.set(tool.name, tool)\n }\n\n let stopped = false\n let activeReadline: ReadlineInterface | undefined\n\n async function handle(message: JsonRpcMessage): Promise<JsonRpcResponse | null> {\n if (stopped) {\n return rpcError(message.id ?? null, -32099, 'server stopped')\n }\n if (message.method === 'initialize') {\n const requested = (message.params as { protocolVersion?: unknown } | undefined)\n ?.protocolVersion\n return rpcResult(message.id ?? null, {\n protocolVersion:\n typeof requested === 'string' && SUPPORTED_PROTOCOL_VERSIONS.includes(requested)\n ? requested\n : PROTOCOL_VERSION,\n capabilities: { tools: {} },\n serverInfo: { name: options.serverName, version: options.serverVersion },\n })\n }\n if (message.method === 'notifications/initialized') {\n // MCP clients send this after the handshake; it has no id and expects\n // no response.\n return null\n }\n if (message.method === 'ping') {\n return rpcResult(message.id ?? null, {})\n }\n if (message.method === 'tools/list') {\n return rpcResult(message.id ?? null, {\n tools: [...tools.values()].map((tool) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n ...(tool.annotations ? { annotations: tool.annotations } : {}),\n })),\n })\n }\n if (message.method === 'tools/call') {\n const params = (message.params ?? {}) as { name?: unknown; arguments?: unknown }\n const name = typeof params.name === 'string' ? params.name : ''\n const tool = tools.get(name)\n if (!tool) {\n return rpcError(message.id ?? null, -32601, `unknown tool: ${name}`)\n }\n try {\n const output = await tool.handler(params.arguments ?? {})\n return rpcResult(message.id ?? null, toolCallResult(output))\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err)\n const code = err instanceof TypeError || err instanceof RangeError ? -32602 : -32000\n return rpcError(message.id ?? null, code, reason)\n }\n }\n if (message.id === undefined || message.id === null) return null\n return rpcError(message.id, -32601, `unknown method: ${message.method}`)\n }\n\n async function serve(transport?: McpTransport): Promise<void> {\n const input = transport?.input ?? process.stdin\n const output = transport?.output ?? process.stdout\n const rl = createInterface({ input, crlfDelay: Number.POSITIVE_INFINITY })\n activeReadline = rl\n return new Promise<void>((resolve, reject) => {\n rl.on('line', (line) => {\n const trimmed = line.trim()\n if (!trimmed) return\n let parsed: JsonRpcMessage | undefined\n try {\n parsed = JSON.parse(trimmed) as JsonRpcMessage\n } catch (err) {\n writeResponse(output, rpcError(null, -32700, `parse error: ${(err as Error).message}`))\n return\n }\n if (parsed?.jsonrpc !== '2.0' || typeof parsed.method !== 'string') {\n writeResponse(output, rpcError(parsed?.id ?? null, -32600, 'invalid request'))\n return\n }\n void handle(parsed).then((response) => {\n if (response) writeResponse(output, response)\n })\n })\n rl.on('close', () => resolve())\n rl.on('error', (err) => reject(err))\n if (stopped) {\n rl.close()\n resolve()\n }\n })\n }\n\n function stop(): void {\n stopped = true\n activeReadline?.close()\n activeReadline = undefined\n }\n\n return { tools, handle, serve, stop }\n}\n\nfunction toolCallResult(output: unknown): {\n content: [{ type: 'text'; text: string }]\n structuredContent?: Record<string, unknown>\n isError: false\n} {\n let json: string | undefined\n try {\n json = JSON.stringify(output)\n } catch (err) {\n const reason = err instanceof Error ? `: ${err.message}` : ''\n throw new TypeError(`MCP tool result must be JSON-serializable${reason}`, { cause: err })\n }\n if (json === undefined) {\n throw new TypeError('MCP tool result must be JSON-serializable')\n }\n\n const serialized = JSON.parse(json) as unknown\n // Preserve string content verbatim. MCP clients pass this text directly to the calling agent.\n const result: {\n content: [{ type: 'text'; text: string }]\n structuredContent?: Record<string, unknown>\n isError: false\n } = {\n content: [{ type: 'text', text: typeof serialized === 'string' ? serialized : json }],\n isError: false,\n }\n if (serialized !== null && typeof serialized === 'object' && !Array.isArray(serialized)) {\n result.structuredContent = serialized as Record<string, unknown>\n }\n return result\n}\n\nfunction rpcResult(id: number | string | null, result: unknown): JsonRpcResponse {\n return { jsonrpc: '2.0', id, result }\n}\n\nfunction rpcError(\n id: number | string | null,\n code: number,\n message: string,\n data?: unknown,\n): JsonRpcResponse {\n return {\n jsonrpc: '2.0',\n id,\n error: data === undefined ? { code, message } : { code, message, data },\n }\n}\n\nfunction writeResponse(output: NodeJS.WritableStream, response: JsonRpcResponse): void {\n output.write(`${JSON.stringify(response)}\\n`)\n}\n"],"mappings":"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"}
|
|
@@ -1,23 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { _ as safeWorkerFile, b as supervisorWorkersDir, f as legacySupervisorRunsRoot, y as supervisorRunsRoot } from "./run-cancellation-
|
|
1
|
+
import { r as spawnJournalRecordEvents, t as FileSpawnJournal } from "./journal-store-BJPMUydp.js";
|
|
2
|
+
import { _ as safeWorkerFile, b as supervisorWorkersDir, f as legacySupervisorRunsRoot, y as supervisorRunsRoot } from "./run-cancellation-CoJRKvih.js";
|
|
3
|
+
import { n as projectPursuit, r as FileObserverJournal, t as discoverDurableSupervisionRun } from "./supervision-discovery-CewADdEs.js";
|
|
3
4
|
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
4
5
|
import { basename, join, resolve } from "node:path";
|
|
5
6
|
// src/tui/top-snapshot.ts
|
|
6
7
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* from `../runtime/supervise/run-layout` — the same module the writers use — so the reader cannot
|
|
12
|
-
* drift from the layout the way an independently-versioned copy of the contract would.
|
|
13
|
-
*
|
|
14
|
-
* Extracted from the `loops` repo (`src/top-model.ts`), which held a hand-joined copy of the
|
|
15
|
-
* layout. Rendering is deliberately unchanged: raw ANSI, zero dependencies.
|
|
16
|
-
*
|
|
17
|
-
* This is the OPERATOR view: what is on disk right now, for a human watching a workspace. It
|
|
18
|
-
* carries no model-call identity, so its per-supervisor totals cannot be joined with root stream
|
|
19
|
-
* events without double counting. A client that needs one execution's totals reads
|
|
20
|
-
* `projectPursuit` from `../durable` instead.
|
|
8
|
+
* Read-only operator snapshots over the writer-owned supervisor layout and explicit durable runs.
|
|
9
|
+
* Workspace reads preserve legacy files; durable reads use discovery, journals and the canonical
|
|
10
|
+
* pursuit projection for model identity, failure and accounting evidence. Run totals count once.
|
|
11
|
+
* ANSI presentation lives in `./top-frame`.
|
|
21
12
|
*
|
|
22
13
|
* @experimental
|
|
23
14
|
*/
|
|
@@ -28,16 +19,9 @@ const emptySpend = {
|
|
|
28
19
|
usd: 0,
|
|
29
20
|
ms: 0
|
|
30
21
|
};
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
* Pure with respect to the process: it only reads, and it never throws for a writer mid-append.
|
|
35
|
-
* An unreadable or half-written source is still skipped — an operator view must survive a live
|
|
36
|
-
* writer — but every skip is reported as one bounded `TopSnapshotDiagnostic`, so a client can
|
|
37
|
-
* tell a removed run from a partial read. `now` is injectable so elapsed time is deterministic
|
|
38
|
-
* under test.
|
|
39
|
-
*/
|
|
40
|
-
function loadTopSnapshot(rootDir, now = Date.now()) {
|
|
22
|
+
function loadTopSnapshot(rootDir, input = Date.now()) {
|
|
23
|
+
if (typeof input !== "number") return loadDurableTopSnapshot(rootDir, input.runDir, input.now ?? Date.now());
|
|
24
|
+
const now = input;
|
|
41
25
|
const root = resolve(rootDir);
|
|
42
26
|
const supervisors = [];
|
|
43
27
|
const diagnostics = [];
|
|
@@ -58,25 +42,83 @@ function loadTopSnapshot(rootDir, now = Date.now()) {
|
|
|
58
42
|
report(entry, state.diagnostics);
|
|
59
43
|
if (!state.value) continue;
|
|
60
44
|
const journal = readJournal(dir);
|
|
61
|
-
const progress =
|
|
45
|
+
const progress = readSourceFile(join(dir, "progress.ndjson"), "progress", "progress.ndjson");
|
|
62
46
|
const workerEvents = readWorkerEventTails(supervisorWorkersDir(dir), 8);
|
|
63
47
|
report(entry, [
|
|
64
48
|
...journal.diagnostics,
|
|
65
49
|
...progress.diagnostics,
|
|
66
50
|
...workerEvents.diagnostics
|
|
67
51
|
]);
|
|
68
|
-
supervisors.push(buildSupervisorView(state.value, dir, journal.value, progress.value, now, workerEvents.value));
|
|
52
|
+
supervisors.push(buildSupervisorView(state.value, dir, journal.value, tailLines(progress.value, 8), now, workerEvents.value));
|
|
69
53
|
}
|
|
70
54
|
}
|
|
71
55
|
supervisors.sort((a, b) => String(b.startedAt ?? "").localeCompare(String(a.startedAt ?? "")));
|
|
56
|
+
return topSnapshot(root, now, supervisors, diagnostics, discovered);
|
|
57
|
+
}
|
|
58
|
+
function topSnapshot(root, now, supervisors, diagnostics = [], discovered = 1, pursuit) {
|
|
72
59
|
return {
|
|
73
60
|
root,
|
|
74
61
|
generatedAt: now,
|
|
75
62
|
supervisors,
|
|
76
|
-
completeness: diagnostics.length
|
|
63
|
+
completeness: diagnostics.length ? "partial" : "complete",
|
|
77
64
|
diagnostics,
|
|
78
65
|
discovered,
|
|
79
|
-
loaded: supervisors.length
|
|
66
|
+
loaded: supervisors.length,
|
|
67
|
+
...pursuit ? { pursuit } : {}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
async function loadDurableTopSnapshot(rootDir, runDir, now) {
|
|
71
|
+
const root = resolve(rootDir);
|
|
72
|
+
let pursuit;
|
|
73
|
+
let source = "observer-journal";
|
|
74
|
+
let path = "observer.jsonl";
|
|
75
|
+
try {
|
|
76
|
+
if (typeof runDir !== "string" || !runDir.trim()) throw new TypeError("runDir must be non-empty");
|
|
77
|
+
const journal = await FileObserverJournal.open(join(resolve(runDir), path));
|
|
78
|
+
if (!journal) return topSnapshot(root, now, [], [{
|
|
79
|
+
source,
|
|
80
|
+
path,
|
|
81
|
+
reason: "missing"
|
|
82
|
+
}]);
|
|
83
|
+
pursuit = projectPursuit(await journal.read());
|
|
84
|
+
source = "journal";
|
|
85
|
+
path = ".";
|
|
86
|
+
const discovery = await discoverDurableSupervisionRun(runDir);
|
|
87
|
+
const latest = new Map(pursuit.runs.map((run) => [run.runId, run]));
|
|
88
|
+
path = "spawn-journal.jsonl";
|
|
89
|
+
const spawnJournal = new FileSpawnJournal(discovery.spawnJournalPath);
|
|
90
|
+
return topSnapshot(root, now, await Promise.all([...latest.values()].map(async (run) => {
|
|
91
|
+
const binding = discovery.roots.find((id) => id === run.runId);
|
|
92
|
+
if (!binding) throw new Error("observer run has no discovered spawn root");
|
|
93
|
+
const events = await spawnJournal.loadTree(binding) ?? [];
|
|
94
|
+
const rootSpawn = events.find((event) => event.kind === "spawned" && event.id === binding);
|
|
95
|
+
const budget = rootSpawn?.kind === "spawned" ? rootSpawn.budget?.maxTokens : void 0;
|
|
96
|
+
return buildSupervisorView({
|
|
97
|
+
id: run.runId,
|
|
98
|
+
status: run.status,
|
|
99
|
+
task: run.runId,
|
|
100
|
+
workspaceDir: root,
|
|
101
|
+
budget: budget ?? 0,
|
|
102
|
+
budgetKnown: budget !== void 0,
|
|
103
|
+
startedAt: new Date(run.firstObservedAt).toISOString(),
|
|
104
|
+
...run.settledAt === void 0 ? {} : { completedAt: new Date(run.settledAt).toISOString() }
|
|
105
|
+
}, discovery.runDir, events.filter(isSpawnEvent), run.error ? [run.error] : [], now, void 0, run);
|
|
106
|
+
})), [], 1, pursuit);
|
|
107
|
+
} catch (error) {
|
|
108
|
+
const reason = isRecord(error) && typeof error.code === "string" ? "unreadable" : "invalid-state";
|
|
109
|
+
return topSnapshot(root, now, [], [{
|
|
110
|
+
source,
|
|
111
|
+
path,
|
|
112
|
+
reason
|
|
113
|
+
}], 1, pursuit);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function observerSpend(spend, gaps = []) {
|
|
117
|
+
const parsed = parseSpend(spend);
|
|
118
|
+
return {
|
|
119
|
+
...parsed,
|
|
120
|
+
usdKnown: spend !== void 0 && parsed.usdKnown !== false && !gaps.includes("usd"),
|
|
121
|
+
tokensKnown: spend !== void 0 && parsed.tokensKnown !== false && !gaps.includes("tokens")
|
|
80
122
|
};
|
|
81
123
|
}
|
|
82
124
|
/**
|
|
@@ -119,15 +161,18 @@ function readJournal(eventDir) {
|
|
|
119
161
|
}] : []
|
|
120
162
|
};
|
|
121
163
|
}
|
|
122
|
-
function buildSupervisorView(state, stateDir, events, progressTail, now, workerEventTails = /* @__PURE__ */ new Map()) {
|
|
164
|
+
function buildSupervisorView(state, stateDir, events, progressTail, now, workerEventTails = /* @__PURE__ */ new Map(), accounting) {
|
|
123
165
|
const workers = /* @__PURE__ */ new Map();
|
|
124
166
|
let driverSpend = emptySpend;
|
|
125
167
|
const journalRootId = events.find((event) => event.kind === "spawned" && !event.parent && event.label === "root")?.id;
|
|
126
168
|
const isRoot = (id) => id === state.id || id === journalRootId;
|
|
127
169
|
for (const event of events) {
|
|
170
|
+
if (isRoot(event.id) || event.kind === "spawned" && !event.parent && event.label === "root") {
|
|
171
|
+
if (event.kind === "metered" && event.accountingOnly !== true) driverSpend = addSpend(driverSpend, parseSpend(event.spend));
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
const worker = ensureWorker(workers, event.id);
|
|
128
175
|
if (event.kind === "spawned") {
|
|
129
|
-
if (isRoot(event.id) || !event.parent && event.label === "root") continue;
|
|
130
|
-
const worker = ensureWorker(workers, event.id, event.label ?? event.id);
|
|
131
176
|
worker.label = event.label ?? worker.label;
|
|
132
177
|
if (event.parent) worker.parent = event.parent;
|
|
133
178
|
if (event.runtime) worker.runtime = event.runtime;
|
|
@@ -135,47 +180,30 @@ function buildSupervisorView(state, stateDir, events, progressTail, now, workerE
|
|
|
135
180
|
if (event.at) worker.startedAt = event.at;
|
|
136
181
|
const budget = parseBudget(event.budget);
|
|
137
182
|
if (budget) worker.budget = budget;
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
if (event.kind === "settled") {
|
|
141
|
-
if (isRoot(event.id)) continue;
|
|
142
|
-
const worker = ensureWorker(workers, event.id, event.id);
|
|
143
|
-
worker.status = event.status === "down" ? "down" : "done";
|
|
144
|
-
if (event.at) worker.endedAt = event.at;
|
|
145
|
-
if (event.outRef) worker.outRef = event.outRef;
|
|
146
|
-
if (event.infra !== void 0) worker.infra = event.infra;
|
|
147
|
-
const verdict = describeVerdict(event.verdict);
|
|
148
|
-
if (verdict) worker.verdict = verdict;
|
|
149
|
-
worker.spend = addSpend(worker.spend, parseSpend(event.spent));
|
|
150
|
-
worker.metered = emptySpend;
|
|
151
|
-
continue;
|
|
152
|
-
}
|
|
153
|
-
if (event.kind === "cancelled") {
|
|
154
|
-
if (isRoot(event.id)) continue;
|
|
155
|
-
const worker = ensureWorker(workers, event.id, event.id);
|
|
156
|
-
worker.status = "cancelled";
|
|
183
|
+
} else if (event.kind === "settled" || event.kind === "cancelled") {
|
|
157
184
|
if (event.at) worker.endedAt = event.at;
|
|
158
|
-
if (event.
|
|
159
|
-
|
|
185
|
+
if (event.kind === "settled") {
|
|
186
|
+
worker.status = event.status === "down" ? "down" : "done";
|
|
187
|
+
if (event.outRef) worker.outRef = event.outRef;
|
|
188
|
+
if (event.infra !== void 0) worker.infra = event.infra;
|
|
189
|
+
const verdict = describeVerdict(event.verdict);
|
|
190
|
+
if (verdict) worker.verdict = verdict;
|
|
191
|
+
} else {
|
|
192
|
+
worker.status = "cancelled";
|
|
193
|
+
if (event.reason) worker.reason = event.reason;
|
|
194
|
+
}
|
|
195
|
+
if (event.kind === "settled" || event.spent !== void 0) {
|
|
160
196
|
worker.spend = addSpend(worker.spend, parseSpend(event.spent));
|
|
161
197
|
worker.metered = emptySpend;
|
|
162
198
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
if (event.accountingOnly !== true) worker.metered = addSpend(worker.metered, spend);
|
|
172
|
-
}
|
|
173
|
-
continue;
|
|
174
|
-
}
|
|
175
|
-
if (event.kind === "progress") {
|
|
176
|
-
if (isRoot(event.id)) continue;
|
|
177
|
-
const worker = ensureWorker(workers, event.id, event.id);
|
|
178
|
-
worker.metered = parseSpend(event.spend);
|
|
199
|
+
} else if (event.kind === "progress") worker.metered = parseSpend(event.spend);
|
|
200
|
+
else if (event.accountingOnly !== true) worker.metered = addSpend(worker.metered, parseSpend(event.spend));
|
|
201
|
+
}
|
|
202
|
+
if (accounting) {
|
|
203
|
+
driverSpend = observerSpend(accounting.totals.exclusiveByNode[accounting.runId]);
|
|
204
|
+
for (const worker of workers.values()) {
|
|
205
|
+
worker.spend = observerSpend(accounting.totals.exclusiveByNode[worker.id], accounting.spendGaps?.find((gap) => gap.id === worker.id)?.channels);
|
|
206
|
+
worker.metered = emptySpend;
|
|
179
207
|
}
|
|
180
208
|
}
|
|
181
209
|
const workerViews = [...workers.values()].map((worker) => {
|
|
@@ -185,6 +213,10 @@ function buildSupervisorView(state, stateDir, events, progressTail, now, workerE
|
|
|
185
213
|
return finalizeWorker(worker, now);
|
|
186
214
|
}).sort((a, b) => compareWorker(a, b));
|
|
187
215
|
const totals = supervisorTotals(state, workerViews, driverSpend, now);
|
|
216
|
+
if (accounting) {
|
|
217
|
+
const spend = observerSpend(accounting.totals.inclusive, accounting.spendGaps?.flatMap((gap) => gap.channels));
|
|
218
|
+
Object.assign(totals, spend, { tokensTotal: spend.tokensInput + spend.tokensOutput });
|
|
219
|
+
}
|
|
188
220
|
return {
|
|
189
221
|
id: state.id,
|
|
190
222
|
stateDir,
|
|
@@ -192,18 +224,23 @@ function buildSupervisorView(state, stateDir, events, progressTail, now, workerE
|
|
|
192
224
|
task: state.task,
|
|
193
225
|
workspaceDir: state.workspaceDir,
|
|
194
226
|
budget: state.budget,
|
|
195
|
-
...state.
|
|
196
|
-
...state
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
...state
|
|
206
|
-
|
|
227
|
+
...state.budgetKnown === void 0 ? {} : { budgetKnown: state.budgetKnown },
|
|
228
|
+
...selectFields(state, [
|
|
229
|
+
"verifyCmd",
|
|
230
|
+
"workerModel",
|
|
231
|
+
"driverModel",
|
|
232
|
+
"verdict",
|
|
233
|
+
"progress",
|
|
234
|
+
"startedAt",
|
|
235
|
+
"completedAt"
|
|
236
|
+
], Boolean),
|
|
237
|
+
...selectFields(state, [
|
|
238
|
+
"maxSandboxes",
|
|
239
|
+
"maxLifetimeSeconds",
|
|
240
|
+
"idleTimeoutSeconds",
|
|
241
|
+
"maxUsd",
|
|
242
|
+
"maxDepth"
|
|
243
|
+
], (value) => value !== void 0),
|
|
207
244
|
...state.result?.spentUsd !== void 0 ? { resultSpentUsd: state.result.spentUsd } : {},
|
|
208
245
|
...state.result?.spentTokens !== void 0 ? { resultSpentTokens: state.result.spentTokens } : {},
|
|
209
246
|
workers: workerViews,
|
|
@@ -213,12 +250,17 @@ function buildSupervisorView(state, stateDir, events, progressTail, now, workerE
|
|
|
213
250
|
totals
|
|
214
251
|
};
|
|
215
252
|
}
|
|
216
|
-
function
|
|
253
|
+
function selectFields(value, keys, include) {
|
|
254
|
+
const selected = {};
|
|
255
|
+
for (const key of keys) if (include(value[key])) selected[key] = value[key];
|
|
256
|
+
return selected;
|
|
257
|
+
}
|
|
258
|
+
function ensureWorker(workers, id) {
|
|
217
259
|
const existing = workers.get(id);
|
|
218
260
|
if (existing) return existing;
|
|
219
261
|
const created = {
|
|
220
262
|
id,
|
|
221
|
-
label,
|
|
263
|
+
label: id,
|
|
222
264
|
status: "running",
|
|
223
265
|
spend: emptySpend,
|
|
224
266
|
metered: emptySpend,
|
|
@@ -232,53 +274,43 @@ function finalizeWorker(worker, now) {
|
|
|
232
274
|
const endMs = parseTime(worker.endedAt) ?? (worker.status === "running" ? now : startMs);
|
|
233
275
|
const latencyMs = startMs !== void 0 && endMs !== void 0 ? Math.max(0, endMs - startMs) : 0;
|
|
234
276
|
return {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
...worker.eventFile ? { eventFile: worker.eventFile } : {},
|
|
238
|
-
...worker.parent ? { parent: worker.parent } : {},
|
|
239
|
-
...worker.runtime ? { runtime: worker.runtime } : {},
|
|
240
|
-
status: worker.status,
|
|
241
|
-
...worker.verdict ? { verdict: worker.verdict } : {},
|
|
242
|
-
...worker.infra !== void 0 ? { infra: worker.infra } : {},
|
|
243
|
-
...worker.startedAt ? { startedAt: worker.startedAt } : {},
|
|
244
|
-
...worker.endedAt ? { endedAt: worker.endedAt } : {},
|
|
245
|
-
latencyMs,
|
|
246
|
-
...worker.budget ? { budget: worker.budget } : {},
|
|
247
|
-
spend: worker.spend,
|
|
248
|
-
metered: worker.metered,
|
|
249
|
-
liveTail: worker.liveTail,
|
|
250
|
-
...worker.outRef ? { outRef: worker.outRef } : {},
|
|
251
|
-
...worker.reason ? { reason: worker.reason } : {}
|
|
277
|
+
...worker,
|
|
278
|
+
latencyMs
|
|
252
279
|
};
|
|
253
280
|
}
|
|
254
281
|
function supervisorTotals(state, workers, driverSpend, now) {
|
|
255
|
-
const
|
|
256
|
-
const
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
282
|
+
const spend = workers.map(totalSpend).reduce(addSpend, driverSpend);
|
|
283
|
+
const counts = {
|
|
284
|
+
running: 0,
|
|
285
|
+
done: 0,
|
|
286
|
+
down: 0,
|
|
287
|
+
cancelled: 0
|
|
288
|
+
};
|
|
289
|
+
for (const worker of workers) counts[worker.status] += 1;
|
|
260
290
|
const started = parseTime(state.startedAt);
|
|
261
291
|
const completed = parseTime(state.completedAt);
|
|
262
292
|
const latencyMs = started !== void 0 ? Math.max(0, (completed ?? now) - started) : 0;
|
|
263
293
|
const latencies = workers.map((worker) => worker.latencyMs).filter((ms) => ms > 0);
|
|
264
294
|
return {
|
|
265
295
|
workers: workers.length,
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
usd,
|
|
296
|
+
...counts,
|
|
297
|
+
...spend.usdKnown === false ? { usdKnown: false } : {},
|
|
298
|
+
...spend.tokensKnown === false ? { tokensKnown: false } : {},
|
|
299
|
+
inFlight: counts.running,
|
|
300
|
+
settled: workers.length - counts.running,
|
|
301
|
+
tokensInput: spend.tokensInput,
|
|
302
|
+
tokensOutput: spend.tokensOutput,
|
|
303
|
+
tokensTotal: spend.tokensInput + spend.tokensOutput,
|
|
304
|
+
usd: spend.usd > 0 ? spend.usd : state.result?.spentUsd ?? 0,
|
|
276
305
|
latencyMs,
|
|
277
306
|
workerLatency: distribution(latencies)
|
|
278
307
|
};
|
|
279
308
|
}
|
|
280
309
|
function aggregateSnapshot(snapshot) {
|
|
310
|
+
const complete = snapshot.completeness === "complete";
|
|
281
311
|
return {
|
|
312
|
+
usdKnown: complete && snapshot.supervisors.every((row) => row.totals.usdKnown !== false),
|
|
313
|
+
tokensKnown: complete && snapshot.supervisors.every((row) => row.totals.tokensKnown !== false),
|
|
282
314
|
supervisors: snapshot.supervisors.length,
|
|
283
315
|
workers: sum(snapshot.supervisors.map((supervisor) => supervisor.totals.workers)),
|
|
284
316
|
running: sum(snapshot.supervisors.map((supervisor) => supervisor.totals.running)),
|
|
@@ -305,13 +337,17 @@ function addSpend(a, b) {
|
|
|
305
337
|
tokensInput: a.tokensInput + b.tokensInput,
|
|
306
338
|
tokensOutput: a.tokensOutput + b.tokensOutput,
|
|
307
339
|
usd: a.usd + b.usd,
|
|
308
|
-
ms: a.ms + b.ms
|
|
340
|
+
ms: a.ms + b.ms,
|
|
341
|
+
...a.usdKnown === false || b.usdKnown === false ? { usdKnown: false } : {},
|
|
342
|
+
...a.tokensKnown === false || b.tokensKnown === false ? { tokensKnown: false } : {}
|
|
309
343
|
};
|
|
310
344
|
}
|
|
311
345
|
function parseSpend(value) {
|
|
312
346
|
if (!isRecord(value)) return emptySpend;
|
|
313
347
|
const tokens = isRecord(value.tokens) ? value.tokens : {};
|
|
314
348
|
return {
|
|
349
|
+
...value.usdKnown === false ? { usdKnown: false } : {},
|
|
350
|
+
...value.tokensKnown === false || tokens.tokensKnown === false ? { tokensKnown: false } : {},
|
|
315
351
|
iterations: numberValue(value.iterations),
|
|
316
352
|
tokensInput: numberValue(tokens.input),
|
|
317
353
|
tokensOutput: numberValue(tokens.output),
|
|
@@ -334,13 +370,6 @@ function describeVerdict(value) {
|
|
|
334
370
|
if (typeof value.score === "number") return `score ${value.score.toFixed(2)}`;
|
|
335
371
|
}
|
|
336
372
|
function distribution(values) {
|
|
337
|
-
if (values.length === 0) return {
|
|
338
|
-
n: 0,
|
|
339
|
-
min: 0,
|
|
340
|
-
median: 0,
|
|
341
|
-
p90: 0,
|
|
342
|
-
max: 0
|
|
343
|
-
};
|
|
344
373
|
const sorted = [...values].sort((a, b) => a - b);
|
|
345
374
|
return {
|
|
346
375
|
n: sorted.length,
|
|
@@ -384,14 +413,6 @@ function tailLines(raw, maxLines) {
|
|
|
384
413
|
if (raw === void 0) return [];
|
|
385
414
|
return raw.trim().split("\n").filter(Boolean).slice(-maxLines);
|
|
386
415
|
}
|
|
387
|
-
function readProgressTail(dir, maxLines) {
|
|
388
|
-
const path = "progress.ndjson";
|
|
389
|
-
const read = readSourceFile(join(dir, path), "progress", path);
|
|
390
|
-
return {
|
|
391
|
-
value: tailLines(read.value, maxLines),
|
|
392
|
-
diagnostics: read.diagnostics
|
|
393
|
-
};
|
|
394
|
-
}
|
|
395
416
|
function readWorkerEventTails(dir, maxLines) {
|
|
396
417
|
const out = /* @__PURE__ */ new Map();
|
|
397
418
|
if (!existsSync(dir)) return {
|
|
@@ -436,46 +457,42 @@ function readSupervisorState(dir) {
|
|
|
436
457
|
value: void 0,
|
|
437
458
|
diagnostics: read.diagnostics
|
|
438
459
|
};
|
|
439
|
-
|
|
460
|
+
const failed = (reason) => ({
|
|
440
461
|
value: void 0,
|
|
441
462
|
diagnostics: [{
|
|
442
463
|
source: "supervisor-state",
|
|
443
464
|
path,
|
|
444
|
-
reason
|
|
465
|
+
reason
|
|
445
466
|
}]
|
|
446
|
-
};
|
|
447
|
-
|
|
467
|
+
});
|
|
468
|
+
if (read.value === void 0) return failed("missing");
|
|
448
469
|
try {
|
|
449
|
-
parsed = JSON.parse(read.value);
|
|
470
|
+
const parsed = JSON.parse(read.value);
|
|
471
|
+
return isSupervisorState(parsed) ? {
|
|
472
|
+
value: parsed,
|
|
473
|
+
diagnostics: []
|
|
474
|
+
} : failed("invalid-state");
|
|
450
475
|
} catch {
|
|
451
|
-
return
|
|
452
|
-
value: void 0,
|
|
453
|
-
diagnostics: [{
|
|
454
|
-
source: "supervisor-state",
|
|
455
|
-
path,
|
|
456
|
-
reason: "partial-json"
|
|
457
|
-
}]
|
|
458
|
-
};
|
|
476
|
+
return failed("partial-json");
|
|
459
477
|
}
|
|
460
|
-
if (!isSupervisorState(parsed)) return {
|
|
461
|
-
value: void 0,
|
|
462
|
-
diagnostics: [{
|
|
463
|
-
source: "supervisor-state",
|
|
464
|
-
path,
|
|
465
|
-
reason: "invalid-state"
|
|
466
|
-
}]
|
|
467
|
-
};
|
|
468
|
-
return {
|
|
469
|
-
value: parsed,
|
|
470
|
-
diagnostics: []
|
|
471
|
-
};
|
|
472
478
|
}
|
|
473
479
|
function isSupervisorState(value) {
|
|
474
|
-
return value
|
|
480
|
+
return isRecord(value) && Object.entries({
|
|
481
|
+
id: "string",
|
|
482
|
+
status: "string",
|
|
483
|
+
task: "string",
|
|
484
|
+
workspaceDir: "string",
|
|
485
|
+
budget: "number"
|
|
486
|
+
}).every(([key, type]) => typeof value[key] === type);
|
|
475
487
|
}
|
|
476
488
|
function isSpawnEvent(value) {
|
|
477
|
-
|
|
478
|
-
|
|
489
|
+
return isRecord(value) && typeof value.id === "string" && typeof value.kind === "string" && [
|
|
490
|
+
"spawned",
|
|
491
|
+
"settled",
|
|
492
|
+
"cancelled",
|
|
493
|
+
"metered",
|
|
494
|
+
"progress"
|
|
495
|
+
].includes(value.kind);
|
|
479
496
|
}
|
|
480
497
|
function isRecord(value) {
|
|
481
498
|
return typeof value === "object" && value !== null;
|
|
@@ -500,4 +517,4 @@ function sum(values) {
|
|
|
500
517
|
}
|
|
501
518
|
export { parseTime as a, parseSpend as i, loadTopSnapshot as n, totalSpend as o, numberValue as r, aggregateSnapshot as t };
|
|
502
519
|
|
|
503
|
-
//# sourceMappingURL=top-snapshot-
|
|
520
|
+
//# sourceMappingURL=top-snapshot-DcV7VG4m.js.map
|