la-machina-engine 0.7.5 → 0.7.7
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.cjs +215 -61
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +51 -11
- package/dist/index.d.ts +51 -11
- package/dist/index.js +215 -61
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2114,11 +2114,12 @@ function createModelAdapter(config, options = {}) {
|
|
|
2114
2114
|
|
|
2115
2115
|
// src/runtime/detect.ts
|
|
2116
2116
|
init_cjs_shims();
|
|
2117
|
-
var
|
|
2117
|
+
var runtimeCache = null;
|
|
2118
|
+
var spawnCache = null;
|
|
2118
2119
|
function detectRuntime() {
|
|
2119
|
-
if (
|
|
2120
|
-
|
|
2121
|
-
return
|
|
2120
|
+
if (runtimeCache !== null) return runtimeCache;
|
|
2121
|
+
runtimeCache = isNodeRuntime() ? "node" : "worker";
|
|
2122
|
+
return runtimeCache;
|
|
2122
2123
|
}
|
|
2123
2124
|
function isNodeRuntime() {
|
|
2124
2125
|
if (typeof globalThis.process !== "undefined" && globalThis.process.versions != null && typeof globalThis.process.versions.node === "string") {
|
|
@@ -2127,10 +2128,29 @@ function isNodeRuntime() {
|
|
|
2127
2128
|
return false;
|
|
2128
2129
|
}
|
|
2129
2130
|
function canSpawnProcesses() {
|
|
2130
|
-
|
|
2131
|
+
if (spawnCache !== null) return spawnCache;
|
|
2132
|
+
spawnCache = probeSpawn();
|
|
2133
|
+
return spawnCache;
|
|
2134
|
+
}
|
|
2135
|
+
function probeSpawn() {
|
|
2136
|
+
if (typeof globalThis.process === "undefined" || globalThis.process.versions == null || typeof globalThis.process.versions.node !== "string") {
|
|
2137
|
+
return false;
|
|
2138
|
+
}
|
|
2139
|
+
try {
|
|
2140
|
+
const req = eval("require");
|
|
2141
|
+
if (typeof req !== "function") return false;
|
|
2142
|
+
const cp = req("node:child_process");
|
|
2143
|
+
return typeof cp.spawn === "function";
|
|
2144
|
+
} catch {
|
|
2145
|
+
return false;
|
|
2146
|
+
}
|
|
2131
2147
|
}
|
|
2132
2148
|
function hasProcessLifecycle() {
|
|
2133
|
-
return typeof process !== "undefined" && typeof process.on === "function" && typeof process.removeListener === "function" &&
|
|
2149
|
+
return typeof process !== "undefined" && typeof process.on === "function" && typeof process.removeListener === "function" && canSpawnProcesses();
|
|
2150
|
+
}
|
|
2151
|
+
function _resetRuntimeCachesForTests() {
|
|
2152
|
+
runtimeCache = null;
|
|
2153
|
+
spawnCache = null;
|
|
2134
2154
|
}
|
|
2135
2155
|
|
|
2136
2156
|
// src/tools/capabilityStub.ts
|
|
@@ -3165,6 +3185,19 @@ async function agentLoop(options) {
|
|
|
3165
3185
|
});
|
|
3166
3186
|
if (compactResult.compacted) {
|
|
3167
3187
|
messages = compactResult.messages;
|
|
3188
|
+
const used = ctx.getTokensUsed();
|
|
3189
|
+
const total = used.input + used.output;
|
|
3190
|
+
const ratio = total / contextLimit;
|
|
3191
|
+
const dropped = compactResult.result?.dropped ?? 0;
|
|
3192
|
+
await options.inspect?.appendEvent({
|
|
3193
|
+
type: "compaction_threshold",
|
|
3194
|
+
turn: ctx.getTurnCount(),
|
|
3195
|
+
ratio,
|
|
3196
|
+
threshold: compactionConfig.threshold,
|
|
3197
|
+
strategy: compactResult.result?.strategy ?? compactionConfig.strategy,
|
|
3198
|
+
dropped,
|
|
3199
|
+
ts: Date.now()
|
|
3200
|
+
});
|
|
3168
3201
|
}
|
|
3169
3202
|
await fireProgress("streaming");
|
|
3170
3203
|
const textBlocks = [];
|
|
@@ -3350,16 +3383,31 @@ async function agentLoop(options) {
|
|
|
3350
3383
|
const firstTool = toolCallsToDispatch[0]?.name;
|
|
3351
3384
|
await fireProgress("tool_dispatch", firstTool);
|
|
3352
3385
|
const streamExec = new StreamingToolExecutor(executor);
|
|
3386
|
+
let anyConcurrent = false;
|
|
3353
3387
|
for (const call of toolCallsToDispatch) {
|
|
3354
3388
|
const tool = options.registry?.get(call.name);
|
|
3355
3389
|
const safe = tool?.isConcurrencySafe?.(call.input) ?? false;
|
|
3390
|
+
if (safe) anyConcurrent = true;
|
|
3356
3391
|
streamExec.addTool(call.id, call.name, call.input, safe);
|
|
3357
3392
|
}
|
|
3393
|
+
await options.inspect?.appendEvent({
|
|
3394
|
+
type: "tool_batch",
|
|
3395
|
+
turn: ctx.getTurnCount(),
|
|
3396
|
+
toolNames: toolCallsToDispatch.map((c) => c.name),
|
|
3397
|
+
concurrent: anyConcurrent && toolCallsToDispatch.length > 1,
|
|
3398
|
+
ts: Date.now()
|
|
3399
|
+
});
|
|
3358
3400
|
try {
|
|
3359
3401
|
for await (const { id, result } of streamExec.results()) {
|
|
3360
3402
|
const missing = result.metadata?.capabilityMissing;
|
|
3361
3403
|
if (typeof missing === "string") {
|
|
3362
3404
|
ctx.recordCapabilityMissing(missing);
|
|
3405
|
+
await options.inspect?.appendEvent({
|
|
3406
|
+
type: "capability_stub",
|
|
3407
|
+
turn: ctx.getTurnCount(),
|
|
3408
|
+
toolName: missing,
|
|
3409
|
+
ts: Date.now()
|
|
3410
|
+
});
|
|
3363
3411
|
}
|
|
3364
3412
|
const call = toolCallsToDispatch.find((c) => c.id === id);
|
|
3365
3413
|
let contentForTranscript;
|
|
@@ -4508,25 +4556,45 @@ If omitted, defaults to "${defaultAgent.name}".`;
|
|
|
4508
4556
|
const lastAssistant = [...parentMsgs].reverse().find((m) => m.role === "assistant");
|
|
4509
4557
|
const assistantContent = lastAssistant ? Array.isArray(lastAssistant.content) ? lastAssistant.content : [] : [];
|
|
4510
4558
|
const forkedMsgs = buildForkedMessages(taskDescription, assistantContent);
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4559
|
+
let result2;
|
|
4560
|
+
try {
|
|
4561
|
+
result2 = await runAgent({
|
|
4562
|
+
agentId: spawn2.agentId,
|
|
4563
|
+
description: taskDescription,
|
|
4564
|
+
storage: options.storage,
|
|
4565
|
+
client: options.client,
|
|
4566
|
+
registry: options.childRegistry,
|
|
4567
|
+
parentLogPath: options.parentLogPath,
|
|
4568
|
+
system: options.system,
|
|
4569
|
+
// inherit parent's system prompt
|
|
4570
|
+
maxTurns: options.maxTurns,
|
|
4571
|
+
contextLimit: options.contextLimit,
|
|
4572
|
+
turnTimeoutMs: options.turnTimeoutMs,
|
|
4573
|
+
flushPolicy: options.flushPolicy,
|
|
4574
|
+
idleFlushMs: options.idleFlushMs,
|
|
4575
|
+
// Fork: prepend parent messages + forked messages
|
|
4576
|
+
prependMessages: [...parentMsgs, ...forkedMsgs],
|
|
4577
|
+
...options.gateBeforeTool !== void 0 ? { gateBeforeTool: options.gateBeforeTool } : {},
|
|
4578
|
+
...options.toolResultOffload !== void 0 ? { toolResultOffload: options.toolResultOffload } : {}
|
|
4579
|
+
});
|
|
4580
|
+
await options.inspect?.appendEvent({
|
|
4581
|
+
type: "subagent_spawn_attempt",
|
|
4582
|
+
agentId: spawn2.agentId,
|
|
4583
|
+
subagentType: "fork",
|
|
4584
|
+
success: true,
|
|
4585
|
+
ts: Date.now()
|
|
4586
|
+
});
|
|
4587
|
+
} catch (err) {
|
|
4588
|
+
await options.inspect?.appendEvent({
|
|
4589
|
+
type: "subagent_spawn_attempt",
|
|
4590
|
+
agentId: spawn2.agentId,
|
|
4591
|
+
subagentType: "fork",
|
|
4592
|
+
success: false,
|
|
4593
|
+
error: err instanceof Error ? err.message : String(err),
|
|
4594
|
+
ts: Date.now()
|
|
4595
|
+
});
|
|
4596
|
+
throw err;
|
|
4597
|
+
}
|
|
4530
4598
|
handlePausedResult(result2, spawn2.agentId, "fork");
|
|
4531
4599
|
const t2 = result2;
|
|
4532
4600
|
options.subagentRegistry.setStatus(spawn2.agentId, t2.isError ? "stopped" : "completed");
|
|
@@ -4580,7 +4648,7 @@ If omitted, defaults to "${defaultAgent.name}".`;
|
|
|
4580
4648
|
const shouldRunAsync = run_in_background === true || options.coordinatorMode === true;
|
|
4581
4649
|
if (shouldRunAsync) {
|
|
4582
4650
|
options.subagentRegistry.setBackground(spawn.agentId);
|
|
4583
|
-
const bgPromise = runAgent(runOpts).then((result2) => {
|
|
4651
|
+
const bgPromise = runAgent(runOpts).then(async (result2) => {
|
|
4584
4652
|
if (result2.kind !== "terminal") {
|
|
4585
4653
|
options.subagentRegistry.setStatus(spawn.agentId, "stopped");
|
|
4586
4654
|
options.subagentRegistry.setBackgroundResult(spawn.agentId, {
|
|
@@ -4589,6 +4657,14 @@ If omitted, defaults to "${defaultAgent.name}".`;
|
|
|
4589
4657
|
isError: true,
|
|
4590
4658
|
description: taskDescription
|
|
4591
4659
|
});
|
|
4660
|
+
await options.inspect?.appendEvent({
|
|
4661
|
+
type: "subagent_spawn_attempt",
|
|
4662
|
+
agentId: spawn.agentId,
|
|
4663
|
+
subagentType: typeName ?? "unknown",
|
|
4664
|
+
success: false,
|
|
4665
|
+
error: "background subagent paused (pause not supported for async)",
|
|
4666
|
+
ts: Date.now()
|
|
4667
|
+
});
|
|
4592
4668
|
return;
|
|
4593
4669
|
}
|
|
4594
4670
|
options.subagentRegistry.setStatus(
|
|
@@ -4601,7 +4677,15 @@ If omitted, defaults to "${defaultAgent.name}".`;
|
|
|
4601
4677
|
isError: result2.isError,
|
|
4602
4678
|
description: taskDescription
|
|
4603
4679
|
});
|
|
4604
|
-
|
|
4680
|
+
await options.inspect?.appendEvent({
|
|
4681
|
+
type: "subagent_spawn_attempt",
|
|
4682
|
+
agentId: spawn.agentId,
|
|
4683
|
+
subagentType: typeName ?? "unknown",
|
|
4684
|
+
success: !result2.isError,
|
|
4685
|
+
...result2.isError ? { error: "child returned isError" } : {},
|
|
4686
|
+
ts: Date.now()
|
|
4687
|
+
});
|
|
4688
|
+
}).catch(async (err) => {
|
|
4605
4689
|
options.subagentRegistry.setStatus(spawn.agentId, "stopped");
|
|
4606
4690
|
options.subagentRegistry.setBackgroundResult(spawn.agentId, {
|
|
4607
4691
|
agentId: spawn.agentId,
|
|
@@ -4609,6 +4693,14 @@ If omitted, defaults to "${defaultAgent.name}".`;
|
|
|
4609
4693
|
isError: true,
|
|
4610
4694
|
description: taskDescription
|
|
4611
4695
|
});
|
|
4696
|
+
await options.inspect?.appendEvent({
|
|
4697
|
+
type: "subagent_spawn_attempt",
|
|
4698
|
+
agentId: spawn.agentId,
|
|
4699
|
+
subagentType: typeName ?? "unknown",
|
|
4700
|
+
success: false,
|
|
4701
|
+
error: err instanceof Error ? err.message : String(err),
|
|
4702
|
+
ts: Date.now()
|
|
4703
|
+
});
|
|
4612
4704
|
});
|
|
4613
4705
|
options.subagentRegistry.setBackgroundPromise(spawn.agentId, bgPromise);
|
|
4614
4706
|
return {
|
|
@@ -4624,7 +4716,27 @@ Use SendMessage with to: '${spawn.agentId}' to communicate with this agent.`,
|
|
|
4624
4716
|
}
|
|
4625
4717
|
};
|
|
4626
4718
|
}
|
|
4627
|
-
|
|
4719
|
+
let result;
|
|
4720
|
+
try {
|
|
4721
|
+
result = await runAgent(runOpts);
|
|
4722
|
+
await options.inspect?.appendEvent({
|
|
4723
|
+
type: "subagent_spawn_attempt",
|
|
4724
|
+
agentId: spawn.agentId,
|
|
4725
|
+
subagentType: typeName ?? "unknown",
|
|
4726
|
+
success: true,
|
|
4727
|
+
ts: Date.now()
|
|
4728
|
+
});
|
|
4729
|
+
} catch (err) {
|
|
4730
|
+
await options.inspect?.appendEvent({
|
|
4731
|
+
type: "subagent_spawn_attempt",
|
|
4732
|
+
agentId: spawn.agentId,
|
|
4733
|
+
subagentType: typeName ?? "unknown",
|
|
4734
|
+
success: false,
|
|
4735
|
+
error: err instanceof Error ? err.message : String(err),
|
|
4736
|
+
ts: Date.now()
|
|
4737
|
+
});
|
|
4738
|
+
throw err;
|
|
4739
|
+
}
|
|
4628
4740
|
handlePausedResult(result, spawn.agentId, typeName);
|
|
4629
4741
|
const t = result;
|
|
4630
4742
|
options.subagentRegistry.setStatus(spawn.agentId, t.isError ? "stopped" : "completed");
|
|
@@ -4675,8 +4787,8 @@ init_contract();
|
|
|
4675
4787
|
var _spawn = null;
|
|
4676
4788
|
async function getSpawn() {
|
|
4677
4789
|
if (_spawn === null) {
|
|
4678
|
-
const
|
|
4679
|
-
_spawn =
|
|
4790
|
+
const cp2 = await import("child_process");
|
|
4791
|
+
_spawn = cp2.spawn;
|
|
4680
4792
|
}
|
|
4681
4793
|
return _spawn;
|
|
4682
4794
|
}
|
|
@@ -5343,12 +5455,12 @@ async function runRipgrep(input, ctx) {
|
|
|
5343
5455
|
args.push("--max-count", String(MAX_MATCHES_PER_FILE));
|
|
5344
5456
|
args.push("--", input.pattern);
|
|
5345
5457
|
if (input.path) args.push(input.path);
|
|
5346
|
-
const
|
|
5347
|
-
if (
|
|
5458
|
+
const cp2 = getChildProcessSync() ?? await getChildProcessAsync();
|
|
5459
|
+
if (cp2 === null) {
|
|
5348
5460
|
return { content: "ripgrep not available in this runtime", isError: true };
|
|
5349
5461
|
}
|
|
5350
5462
|
return new Promise((resolve) => {
|
|
5351
|
-
const child =
|
|
5463
|
+
const child = cp2.spawn("rg", args, {
|
|
5352
5464
|
stdio: ["ignore", "pipe", "pipe"],
|
|
5353
5465
|
timeout: 3e4
|
|
5354
5466
|
});
|
|
@@ -6959,7 +7071,7 @@ init_contract();
|
|
|
6959
7071
|
function mcpToolName(serverName, toolName) {
|
|
6960
7072
|
return `mcp__${serverName}__${toolName}`;
|
|
6961
7073
|
}
|
|
6962
|
-
function adaptMcpTool(client, serverName, def) {
|
|
7074
|
+
function adaptMcpTool(client, serverName, def, opts) {
|
|
6963
7075
|
const registeredName = mcpToolName(serverName, def.name);
|
|
6964
7076
|
return defineTool({
|
|
6965
7077
|
name: registeredName,
|
|
@@ -6969,6 +7081,9 @@ function adaptMcpTool(client, serverName, def) {
|
|
|
6969
7081
|
// bypassing Zod-to-JSON-Schema conversion (which would produce `{}`
|
|
6970
7082
|
// for our `z.unknown()` Zod schema).
|
|
6971
7083
|
anthropicSchemaOverride: def.inputSchema,
|
|
7084
|
+
// Plan 027 — stdio servers spawn subprocesses; flag so the engine's
|
|
7085
|
+
// capability-stub wrapper can swap them on Workers.
|
|
7086
|
+
...opts.transport === "stdio" ? { requiresNode: true } : {},
|
|
6972
7087
|
execute: async (input) => {
|
|
6973
7088
|
try {
|
|
6974
7089
|
const result = await client.callTool(def.name, input);
|
|
@@ -7012,6 +7127,8 @@ var McpManager = class {
|
|
|
7012
7127
|
this.logger = logger;
|
|
7013
7128
|
this.servers = Object.entries(config.servers).map(([name, serverConfig]) => ({
|
|
7014
7129
|
name,
|
|
7130
|
+
// Plan 027 — capture transport for the stdio-handoff wiring.
|
|
7131
|
+
transport: serverConfig.type,
|
|
7015
7132
|
client: new McpClient({
|
|
7016
7133
|
serverName: name,
|
|
7017
7134
|
config: serverConfig,
|
|
@@ -7151,7 +7268,9 @@ var McpManager = class {
|
|
|
7151
7268
|
try {
|
|
7152
7269
|
await server.client.connect();
|
|
7153
7270
|
const defs = server.client.listTools();
|
|
7154
|
-
server.tools = defs.map(
|
|
7271
|
+
server.tools = defs.map(
|
|
7272
|
+
(def) => adaptMcpTool(server.client, server.name, def, { transport: server.transport })
|
|
7273
|
+
);
|
|
7155
7274
|
server.state = "connected";
|
|
7156
7275
|
this.pendingConnected.push(server.name);
|
|
7157
7276
|
} catch (err) {
|
|
@@ -8716,8 +8835,8 @@ function truncatePreview(s) {
|
|
|
8716
8835
|
return s.slice(0, 200) + "\u2026";
|
|
8717
8836
|
}
|
|
8718
8837
|
async function loadIndex(adapter, base, cache) {
|
|
8719
|
-
const
|
|
8720
|
-
if (
|
|
8838
|
+
const cached = cache.get(base);
|
|
8839
|
+
if (cached !== void 0) return cached;
|
|
8721
8840
|
let raw = null;
|
|
8722
8841
|
try {
|
|
8723
8842
|
raw = await adapter.readFile(`${base}/_index.json`);
|
|
@@ -8998,8 +9117,8 @@ ${payload}`,
|
|
|
8998
9117
|
};
|
|
8999
9118
|
}
|
|
9000
9119
|
async function loadIndex2(adapter, base, cache) {
|
|
9001
|
-
const
|
|
9002
|
-
if (
|
|
9120
|
+
const cached = cache.get(base);
|
|
9121
|
+
if (cached !== void 0) return cached;
|
|
9003
9122
|
let raw = null;
|
|
9004
9123
|
try {
|
|
9005
9124
|
raw = await adapter.readFile(`${base}/_index.json`);
|
|
@@ -9023,8 +9142,8 @@ async function loadIndex2(adapter, base, cache) {
|
|
|
9023
9142
|
}
|
|
9024
9143
|
}
|
|
9025
9144
|
async function readFile(adapter, path, cache) {
|
|
9026
|
-
const
|
|
9027
|
-
if (
|
|
9145
|
+
const cached = cache.get(path);
|
|
9146
|
+
if (cached !== void 0) return cached;
|
|
9028
9147
|
const content = await adapter.readFile(path).catch(() => null);
|
|
9029
9148
|
if (content === null) return null;
|
|
9030
9149
|
cache.set(path, content);
|
|
@@ -9180,8 +9299,8 @@ var InlineSkillSource = class {
|
|
|
9180
9299
|
async resolve(cacheKey, inline, url, headers) {
|
|
9181
9300
|
if (inline !== void 0) return inline;
|
|
9182
9301
|
if (url === void 0) return null;
|
|
9183
|
-
const
|
|
9184
|
-
if (
|
|
9302
|
+
const cached = this.cache.get(cacheKey);
|
|
9303
|
+
if (cached !== void 0) return cached;
|
|
9185
9304
|
this.assertUrlAllowed(url);
|
|
9186
9305
|
const controller = new AbortController();
|
|
9187
9306
|
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
@@ -9490,9 +9609,9 @@ var R2StorageAdapter = class {
|
|
|
9490
9609
|
results.push(name);
|
|
9491
9610
|
}
|
|
9492
9611
|
}
|
|
9493
|
-
for (const
|
|
9494
|
-
if (!
|
|
9495
|
-
const name =
|
|
9612
|
+
for (const cp2 of resp.CommonPrefixes ?? []) {
|
|
9613
|
+
if (!cp2.Prefix) continue;
|
|
9614
|
+
const name = cp2.Prefix.slice(prefix.length).replace(/\/$/, "");
|
|
9496
9615
|
if (name) results.push(name);
|
|
9497
9616
|
}
|
|
9498
9617
|
continuationToken = resp.IsTruncated ? resp.NextContinuationToken : void 0;
|
|
@@ -10472,6 +10591,7 @@ var Engine = class {
|
|
|
10472
10591
|
systemPrompt += "\n\n" + buildSchemaPrompt(options.outputSchema);
|
|
10473
10592
|
}
|
|
10474
10593
|
const gate = this.resolveGate();
|
|
10594
|
+
const inspect = this.buildInspectWriter(storage.workspace, logPath);
|
|
10475
10595
|
const registry = buildToolRegistry({
|
|
10476
10596
|
config: this.config,
|
|
10477
10597
|
storage,
|
|
@@ -10483,6 +10603,7 @@ var Engine = class {
|
|
|
10483
10603
|
agents,
|
|
10484
10604
|
mcpTools,
|
|
10485
10605
|
memory,
|
|
10606
|
+
inspect,
|
|
10486
10607
|
...this.config.hooks.propagateGateToSubagents === true && gate !== void 0 ? { subagentGate: gate } : {},
|
|
10487
10608
|
...skillSource !== void 0 ? { skillSource } : {},
|
|
10488
10609
|
...apiConfig !== void 0 ? { apiConfig } : {},
|
|
@@ -10491,7 +10612,6 @@ var Engine = class {
|
|
|
10491
10612
|
...this.internals.fetch !== void 0 ? { fetch: this.internals.fetch } : {}
|
|
10492
10613
|
});
|
|
10493
10614
|
applyRunToolFilter(registry, options);
|
|
10494
|
-
const inspect = this.buildInspectWriter(storage.workspace, logPath);
|
|
10495
10615
|
await inspect.writeStartSnapshot({
|
|
10496
10616
|
systemPrompt,
|
|
10497
10617
|
tools: this.snapshotTools(registry, mcpTools),
|
|
@@ -10588,10 +10708,16 @@ var Engine = class {
|
|
|
10588
10708
|
// events / per-turn rows. Disabled-mode writer is a no-op.
|
|
10589
10709
|
inspect
|
|
10590
10710
|
});
|
|
10591
|
-
const result = await this.finalizeResult(
|
|
10592
|
-
|
|
10593
|
-
|
|
10594
|
-
|
|
10711
|
+
const result = await this.finalizeResult(
|
|
10712
|
+
loopResult,
|
|
10713
|
+
writer,
|
|
10714
|
+
logPath,
|
|
10715
|
+
{
|
|
10716
|
+
...options.outputFormat !== void 0 ? { outputFormat: options.outputFormat } : {},
|
|
10717
|
+
...options.outputSchema !== void 0 ? { outputSchema: options.outputSchema } : {}
|
|
10718
|
+
},
|
|
10719
|
+
inspect
|
|
10720
|
+
);
|
|
10595
10721
|
this.logRunEnd(log, runId, options.nodeId, result);
|
|
10596
10722
|
await this.firePostRunHook(runId, options.nodeId, result, ctx, logPath);
|
|
10597
10723
|
await this.writeInspectToolsSummary(inspect, storage.workspace, logPath);
|
|
@@ -10662,6 +10788,7 @@ var Engine = class {
|
|
|
10662
10788
|
systemPrompt += "\n\n" + buildSchemaPrompt(options.outputSchema);
|
|
10663
10789
|
}
|
|
10664
10790
|
const gate = this.resolveGate();
|
|
10791
|
+
const inspect = this.buildInspectWriter(storage.workspace, logPath);
|
|
10665
10792
|
const registry = buildToolRegistry({
|
|
10666
10793
|
config: this.config,
|
|
10667
10794
|
storage,
|
|
@@ -10673,6 +10800,7 @@ var Engine = class {
|
|
|
10673
10800
|
agents,
|
|
10674
10801
|
mcpTools,
|
|
10675
10802
|
memory,
|
|
10803
|
+
inspect,
|
|
10676
10804
|
...this.config.hooks.propagateGateToSubagents === true && gate !== void 0 ? { subagentGate: gate } : {},
|
|
10677
10805
|
...skillSource !== void 0 ? { skillSource } : {},
|
|
10678
10806
|
...apiConfig !== void 0 ? { apiConfig } : {},
|
|
@@ -10680,7 +10808,6 @@ var Engine = class {
|
|
|
10680
10808
|
...knowledgeRuntime !== void 0 ? { knowledge: knowledgeRuntime } : {},
|
|
10681
10809
|
...this.internals.fetch !== void 0 ? { fetch: this.internals.fetch } : {}
|
|
10682
10810
|
});
|
|
10683
|
-
const inspect = this.buildInspectWriter(storage.workspace, logPath);
|
|
10684
10811
|
await inspect.writeStartSnapshot({
|
|
10685
10812
|
systemPrompt,
|
|
10686
10813
|
tools: this.snapshotTools(registry, mcpTools),
|
|
@@ -10811,10 +10938,16 @@ ${inputJson}
|
|
|
10811
10938
|
// existing inspect/ logs.
|
|
10812
10939
|
inspect
|
|
10813
10940
|
});
|
|
10814
|
-
const result = await this.finalizeResult(
|
|
10815
|
-
|
|
10816
|
-
|
|
10817
|
-
|
|
10941
|
+
const result = await this.finalizeResult(
|
|
10942
|
+
loopResult,
|
|
10943
|
+
writer,
|
|
10944
|
+
logPath,
|
|
10945
|
+
{
|
|
10946
|
+
...options.outputFormat !== void 0 ? { outputFormat: options.outputFormat } : {},
|
|
10947
|
+
...options.outputSchema !== void 0 ? { outputSchema: options.outputSchema } : {}
|
|
10948
|
+
},
|
|
10949
|
+
inspect
|
|
10950
|
+
);
|
|
10818
10951
|
this.logRunEnd(log, snapshot.runId, snapshot.nodeId, result);
|
|
10819
10952
|
await this.firePostRunHook(snapshot.runId, snapshot.nodeId, result, ctx, logPath);
|
|
10820
10953
|
await this.writeInspectToolsSummary(inspect, storage.workspace, logPath);
|
|
@@ -11465,7 +11598,7 @@ ${inputJson}
|
|
|
11465
11598
|
};
|
|
11466
11599
|
await dispatchHooks(this.config.hooks.postRun, event);
|
|
11467
11600
|
}
|
|
11468
|
-
async finalizeResult(loopResult, writer, _logPath, jsonOptions) {
|
|
11601
|
+
async finalizeResult(loopResult, writer, _logPath, jsonOptions, inspect) {
|
|
11469
11602
|
if (loopResult.status === "done") {
|
|
11470
11603
|
await writer.setStatus("done");
|
|
11471
11604
|
let data;
|
|
@@ -11474,10 +11607,27 @@ ${inputJson}
|
|
|
11474
11607
|
if (parsed.ok) {
|
|
11475
11608
|
if (jsonOptions.outputSchema) {
|
|
11476
11609
|
const validated = validateOutput(parsed.value, jsonOptions.outputSchema);
|
|
11477
|
-
|
|
11610
|
+
if (validated.ok) {
|
|
11611
|
+
data = validated.data;
|
|
11612
|
+
} else {
|
|
11613
|
+
await inspect?.appendEvent({
|
|
11614
|
+
type: "json_parse_failure",
|
|
11615
|
+
turn: loopResult.turns,
|
|
11616
|
+
validationError: validated.error,
|
|
11617
|
+
ts: Date.now()
|
|
11618
|
+
});
|
|
11619
|
+
data = void 0;
|
|
11620
|
+
}
|
|
11478
11621
|
} else {
|
|
11479
11622
|
data = parsed.value;
|
|
11480
11623
|
}
|
|
11624
|
+
} else {
|
|
11625
|
+
await inspect?.appendEvent({
|
|
11626
|
+
type: "json_parse_failure",
|
|
11627
|
+
turn: loopResult.turns,
|
|
11628
|
+
parseError: parsed.error ?? "unknown parse error",
|
|
11629
|
+
ts: Date.now()
|
|
11630
|
+
});
|
|
11481
11631
|
}
|
|
11482
11632
|
}
|
|
11483
11633
|
return {
|
|
@@ -11955,7 +12105,10 @@ function buildToolRegistry(options) {
|
|
|
11955
12105
|
agents,
|
|
11956
12106
|
coordinatorMode: isCoordinatorMode(config),
|
|
11957
12107
|
...subagentGate !== void 0 ? { gateBeforeTool: subagentGate } : {},
|
|
11958
|
-
...options.toolResultOffload !== void 0 ? { toolResultOffload: options.toolResultOffload } : {}
|
|
12108
|
+
...options.toolResultOffload !== void 0 ? { toolResultOffload: options.toolResultOffload } : {},
|
|
12109
|
+
// Plan 026 — Agent tool emits subagent_spawn_attempt to the
|
|
12110
|
+
// parent's events.jsonl on each runAgent call (success and failure).
|
|
12111
|
+
...options.inspect !== void 0 ? { inspect: options.inspect } : {}
|
|
11959
12112
|
});
|
|
11960
12113
|
if (!disabled.has("Agent") && (wantAll || enabled.has("Agent"))) {
|
|
11961
12114
|
registry.register(agentTool);
|
|
@@ -11971,8 +12124,9 @@ function buildToolRegistry(options) {
|
|
|
11971
12124
|
for (const tool of mcpTools) {
|
|
11972
12125
|
if (disabled.has(tool.name)) continue;
|
|
11973
12126
|
if (wantAll || enabled.has(tool.name)) {
|
|
11974
|
-
|
|
11975
|
-
|
|
12127
|
+
const wrapped = withCapabilityCheck(tool, spawnAvailable);
|
|
12128
|
+
registry.register(wrapped);
|
|
12129
|
+
childRegistry.register(wrapped);
|
|
11976
12130
|
}
|
|
11977
12131
|
}
|
|
11978
12132
|
if (!disabled.has("ToolSearch") && (wantAll || enabled.has("ToolSearch"))) {
|