la-machina-engine 0.7.4 → 0.7.5
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 +521 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +376 -44
- package/dist/index.d.ts +376 -44
- package/dist/index.js +519 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -841,6 +841,7 @@ __export(index_exports, {
|
|
|
841
841
|
EpisodicMemory: () => EpisodicMemory,
|
|
842
842
|
Hippocampus: () => Hippocampus,
|
|
843
843
|
InlineSkillSource: () => InlineSkillSource,
|
|
844
|
+
InspectWriter: () => InspectWriter,
|
|
844
845
|
LocalStorageAdapter: () => LocalStorageAdapter,
|
|
845
846
|
MAX_ATTEMPTS: () => MAX_ATTEMPTS,
|
|
846
847
|
McpClient: () => McpClient,
|
|
@@ -848,6 +849,7 @@ __export(index_exports, {
|
|
|
848
849
|
McpManager: () => McpManager,
|
|
849
850
|
McpProtocolError: () => McpProtocolError,
|
|
850
851
|
McpTimeoutError: () => McpTimeoutError,
|
|
852
|
+
NULL_INSPECT_WRITER: () => NULL_INSPECT_WRITER,
|
|
851
853
|
NodeBackgroundExecutor: () => NodeBackgroundExecutor,
|
|
852
854
|
NotImplementedError: () => NotImplementedError,
|
|
853
855
|
PlanSchema: () => PlanSchema,
|
|
@@ -1022,6 +1024,10 @@ var DEFAULTS = {
|
|
|
1022
1024
|
enableRollback: true,
|
|
1023
1025
|
maxPlanSteps: 20,
|
|
1024
1026
|
agentMaxTurns: 15
|
|
1027
|
+
},
|
|
1028
|
+
inspect: {
|
|
1029
|
+
enabled: true,
|
|
1030
|
+
redactBaseURL: false
|
|
1025
1031
|
}
|
|
1026
1032
|
};
|
|
1027
1033
|
|
|
@@ -1257,6 +1263,11 @@ var RunnerConfigResolved = import_zod.z.object({
|
|
|
1257
1263
|
url: import_zod.z.string().url(),
|
|
1258
1264
|
secret: import_zod.z.string().min(1, "runner.secret cannot be empty")
|
|
1259
1265
|
}).strict();
|
|
1266
|
+
var InspectConfigResolved = import_zod.z.object({
|
|
1267
|
+
enabled: import_zod.z.boolean(),
|
|
1268
|
+
redactBaseURL: import_zod.z.boolean()
|
|
1269
|
+
}).strict();
|
|
1270
|
+
var InspectConfigUser = InspectConfigResolved.partial();
|
|
1260
1271
|
var ResolvedConfigSchema = import_zod.z.object({
|
|
1261
1272
|
model: ModelConfigResolved,
|
|
1262
1273
|
storage: StorageConfigResolved,
|
|
@@ -1275,7 +1286,8 @@ var ResolvedConfigSchema = import_zod.z.object({
|
|
|
1275
1286
|
orchestrator: OrchestratorConfigResolved,
|
|
1276
1287
|
runner: RunnerConfigResolved.optional(),
|
|
1277
1288
|
api: ApiConfigResolved.optional(),
|
|
1278
|
-
knowledge: KnowledgeConfigResolved.optional()
|
|
1289
|
+
knowledge: KnowledgeConfigResolved.optional(),
|
|
1290
|
+
inspect: InspectConfigResolved
|
|
1279
1291
|
}).strict();
|
|
1280
1292
|
var R2ConfigUser = R2ConfigResolved.partial();
|
|
1281
1293
|
var ModelConfigUser = ModelConfigResolved.partial();
|
|
@@ -1352,7 +1364,8 @@ var UserConfigSchema = import_zod.z.object({
|
|
|
1352
1364
|
orchestrator: OrchestratorConfigUser.optional(),
|
|
1353
1365
|
runner: RunnerConfigUser.optional(),
|
|
1354
1366
|
api: ApiConfigUser.optional(),
|
|
1355
|
-
knowledge: KnowledgeConfigUser.optional()
|
|
1367
|
+
knowledge: KnowledgeConfigUser.optional(),
|
|
1368
|
+
inspect: InspectConfigUser.optional()
|
|
1356
1369
|
}).strict();
|
|
1357
1370
|
|
|
1358
1371
|
// src/config/merge.ts
|
|
@@ -3025,6 +3038,30 @@ function isSubagentPausedError(err) {
|
|
|
3025
3038
|
}
|
|
3026
3039
|
|
|
3027
3040
|
// src/engine/agentLoop.ts
|
|
3041
|
+
async function emitInspectTurn(args) {
|
|
3042
|
+
const writer = args.inspect;
|
|
3043
|
+
if (writer === void 0) return;
|
|
3044
|
+
const completedAt = Date.now();
|
|
3045
|
+
const cacheCreate = args.endTokens.cacheCreationInput !== void 0 ? args.endTokens.cacheCreationInput - (args.startTokens.cacheCreationInput ?? 0) : void 0;
|
|
3046
|
+
const cacheRead = args.endTokens.cacheReadInput !== void 0 ? args.endTokens.cacheReadInput - (args.startTokens.cacheReadInput ?? 0) : void 0;
|
|
3047
|
+
const delta = {
|
|
3048
|
+
input: args.endTokens.input - args.startTokens.input,
|
|
3049
|
+
output: args.endTokens.output - args.startTokens.output,
|
|
3050
|
+
...cacheCreate !== void 0 ? { cacheCreationInput: cacheCreate } : {},
|
|
3051
|
+
...cacheRead !== void 0 ? { cacheReadInput: cacheRead } : {}
|
|
3052
|
+
};
|
|
3053
|
+
await writer.appendTurn({
|
|
3054
|
+
turn: args.turn,
|
|
3055
|
+
startedAt: args.startedAt,
|
|
3056
|
+
completedAt,
|
|
3057
|
+
durationMs: completedAt - args.startedAt,
|
|
3058
|
+
tokensUsed: delta,
|
|
3059
|
+
stopReason: args.stopReason,
|
|
3060
|
+
toolCallsCount: args.toolCallsCount,
|
|
3061
|
+
...cacheCreate !== void 0 ? { cacheCreationInput: cacheCreate } : {},
|
|
3062
|
+
...cacheRead !== void 0 ? { cacheReadInput: cacheRead } : {}
|
|
3063
|
+
});
|
|
3064
|
+
}
|
|
3028
3065
|
var DEFAULT_COMPACTION = {
|
|
3029
3066
|
strategy: "drop-middle",
|
|
3030
3067
|
threshold: 0.85,
|
|
@@ -3067,6 +3104,8 @@ async function agentLoop(options) {
|
|
|
3067
3104
|
};
|
|
3068
3105
|
for (; ; ) {
|
|
3069
3106
|
compactedThisTurn = false;
|
|
3107
|
+
const turnStartedAt = Date.now();
|
|
3108
|
+
const turnStartTokens = { ...ctx.getTokensUsed() };
|
|
3070
3109
|
if (options.runSignal?.aborted === true) {
|
|
3071
3110
|
return failed(new RunTimeoutError(options.runTimeoutMs ?? 0), transcript);
|
|
3072
3111
|
}
|
|
@@ -3076,6 +3115,12 @@ async function agentLoop(options) {
|
|
|
3076
3115
|
if (options.tokenBudget !== void 0) {
|
|
3077
3116
|
const used = ctx.getTokensUsed();
|
|
3078
3117
|
if (used.input + used.output >= options.tokenBudget) {
|
|
3118
|
+
await options.inspect?.appendEvent({
|
|
3119
|
+
type: "budget_hit",
|
|
3120
|
+
totalTokens: used.input + used.output,
|
|
3121
|
+
budget: options.tokenBudget,
|
|
3122
|
+
ts: Date.now()
|
|
3123
|
+
});
|
|
3079
3124
|
return {
|
|
3080
3125
|
status: "done",
|
|
3081
3126
|
output: lastAssistantText || "[Token budget exhausted]",
|
|
@@ -3132,13 +3177,21 @@ async function agentLoop(options) {
|
|
|
3132
3177
|
turnCount: ctx.getTurnCount(),
|
|
3133
3178
|
maxTurns: ctx.getMaxTurns()
|
|
3134
3179
|
})) {
|
|
3180
|
+
const instruction = lastTurnInstruction(options.outputFormat);
|
|
3135
3181
|
messagesForApi = [
|
|
3136
3182
|
...messages,
|
|
3137
3183
|
{
|
|
3138
3184
|
role: "user",
|
|
3139
|
-
content: [{ type: "text", text:
|
|
3185
|
+
content: [{ type: "text", text: instruction }]
|
|
3140
3186
|
}
|
|
3141
3187
|
];
|
|
3188
|
+
await options.inspect?.appendEvent({
|
|
3189
|
+
type: "last_turn_guard",
|
|
3190
|
+
turn: ctx.getTurnCount(),
|
|
3191
|
+
outputFormat: options.outputFormat ?? "text",
|
|
3192
|
+
instruction,
|
|
3193
|
+
ts: Date.now()
|
|
3194
|
+
});
|
|
3142
3195
|
}
|
|
3143
3196
|
const normalizedMessages = normalizeMessages(
|
|
3144
3197
|
messagesForApi
|
|
@@ -3173,6 +3226,13 @@ async function agentLoop(options) {
|
|
|
3173
3226
|
system
|
|
3174
3227
|
});
|
|
3175
3228
|
if (emergency.compacted) {
|
|
3229
|
+
await options.inspect?.appendEvent({
|
|
3230
|
+
type: "compaction_413",
|
|
3231
|
+
turn: ctx.getTurnCount(),
|
|
3232
|
+
droppedMessages: messages.length - emergency.messages.length,
|
|
3233
|
+
strategy: compactionConfig.strategy,
|
|
3234
|
+
ts: Date.now()
|
|
3235
|
+
});
|
|
3176
3236
|
ctx.rehydrate({
|
|
3177
3237
|
messages: emergency.messages,
|
|
3178
3238
|
turnCount: ctx.getTurnCount(),
|
|
@@ -3200,6 +3260,14 @@ async function agentLoop(options) {
|
|
|
3200
3260
|
}
|
|
3201
3261
|
const retryAfter = err instanceof RateLimitError && err.retryAfterMs ? err.retryAfterMs : BASE_BACKOFF_MS * Math.pow(2, apiRetryCount - 1);
|
|
3202
3262
|
const delay = Math.min(retryAfter, 3e4);
|
|
3263
|
+
await options.inspect?.appendEvent({
|
|
3264
|
+
type: "api_retry",
|
|
3265
|
+
turn: ctx.getTurnCount(),
|
|
3266
|
+
status: err instanceof Error && "status" in err ? err.status ?? null : null,
|
|
3267
|
+
attempt: apiRetryCount,
|
|
3268
|
+
delayMs: delay,
|
|
3269
|
+
ts: Date.now()
|
|
3270
|
+
});
|
|
3203
3271
|
await new Promise((r) => setTimeout(r, delay));
|
|
3204
3272
|
continue;
|
|
3205
3273
|
}
|
|
@@ -3351,6 +3419,15 @@ async function agentLoop(options) {
|
|
|
3351
3419
|
apiRetryCount = 0;
|
|
3352
3420
|
consecutive529 = 0;
|
|
3353
3421
|
await ctx.endTurn();
|
|
3422
|
+
await emitInspectTurn({
|
|
3423
|
+
inspect: options.inspect,
|
|
3424
|
+
turn: ctx.getTurnCount() - 1,
|
|
3425
|
+
startedAt: turnStartedAt,
|
|
3426
|
+
startTokens: turnStartTokens,
|
|
3427
|
+
endTokens: ctx.getTokensUsed(),
|
|
3428
|
+
stopReason,
|
|
3429
|
+
toolCallsCount: toolCallsToDispatch.length
|
|
3430
|
+
});
|
|
3354
3431
|
await fireProgress("idle");
|
|
3355
3432
|
if (options.postTurnHooks && options.postTurnHooks.length > 0) {
|
|
3356
3433
|
await dispatchHooks(options.postTurnHooks, {
|
|
@@ -3382,6 +3459,15 @@ async function agentLoop(options) {
|
|
|
3382
3459
|
continue;
|
|
3383
3460
|
}
|
|
3384
3461
|
await ctx.endTurn();
|
|
3462
|
+
await emitInspectTurn({
|
|
3463
|
+
inspect: options.inspect,
|
|
3464
|
+
turn: ctx.getTurnCount() - 1,
|
|
3465
|
+
startedAt: turnStartedAt,
|
|
3466
|
+
startTokens: turnStartTokens,
|
|
3467
|
+
endTokens: ctx.getTokensUsed(),
|
|
3468
|
+
stopReason,
|
|
3469
|
+
toolCallsCount: 0
|
|
3470
|
+
});
|
|
3385
3471
|
if (options.postTurnHooks && options.postTurnHooks.length > 0) {
|
|
3386
3472
|
await dispatchHooks(options.postTurnHooks, {
|
|
3387
3473
|
runId: ctx.runId,
|
|
@@ -3408,11 +3494,25 @@ async function agentLoop(options) {
|
|
|
3408
3494
|
if (!maxTokensEscalated) {
|
|
3409
3495
|
maxTokensEscalated = true;
|
|
3410
3496
|
escalatedMaxTokens = ESCALATED_MAX_TOKENS;
|
|
3497
|
+
await options.inspect?.appendEvent({
|
|
3498
|
+
type: "recovery_max_tokens",
|
|
3499
|
+
turn: ctx.getTurnCount(),
|
|
3500
|
+
attempt: 0,
|
|
3501
|
+
escalatedTo: ESCALATED_MAX_TOKENS,
|
|
3502
|
+
ts: Date.now()
|
|
3503
|
+
});
|
|
3411
3504
|
continue;
|
|
3412
3505
|
}
|
|
3413
3506
|
if (recoveryCount < MAX_OUTPUT_TOKENS_RECOVERY_LIMIT) {
|
|
3414
3507
|
recoveryCount++;
|
|
3415
3508
|
escalatedMaxTokens = void 0;
|
|
3509
|
+
await options.inspect?.appendEvent({
|
|
3510
|
+
type: "recovery_max_tokens",
|
|
3511
|
+
turn: ctx.getTurnCount(),
|
|
3512
|
+
attempt: recoveryCount,
|
|
3513
|
+
escalatedTo: 0,
|
|
3514
|
+
ts: Date.now()
|
|
3515
|
+
});
|
|
3416
3516
|
await ctx.addUserMessage(
|
|
3417
3517
|
"Output token limit hit. Resume directly \u2014 no apology, no recap of what you were doing. Pick up mid-thought if that is where the cut happened. Break remaining work into smaller pieces."
|
|
3418
3518
|
);
|
|
@@ -4727,6 +4827,7 @@ function createSendMessageTool(options) {
|
|
|
4727
4827
|
|
|
4728
4828
|
// src/engine/engine.ts
|
|
4729
4829
|
init_contract();
|
|
4830
|
+
var import_zod_to_json_schema4 = require("zod-to-json-schema");
|
|
4730
4831
|
|
|
4731
4832
|
// src/tools/fileEdit.ts
|
|
4732
4833
|
init_cjs_shims();
|
|
@@ -9721,6 +9822,198 @@ function applyRunToolFilter(registry, options) {
|
|
|
9721
9822
|
}
|
|
9722
9823
|
}
|
|
9723
9824
|
|
|
9825
|
+
// src/inspect/writer.ts
|
|
9826
|
+
init_cjs_shims();
|
|
9827
|
+
var InspectWriter = class {
|
|
9828
|
+
storage;
|
|
9829
|
+
logger;
|
|
9830
|
+
enabled;
|
|
9831
|
+
/** Subdirectory holding all inspect files. Constant per writer. */
|
|
9832
|
+
dir;
|
|
9833
|
+
constructor(opts) {
|
|
9834
|
+
this.storage = opts.storage;
|
|
9835
|
+
if (opts.logger !== void 0) this.logger = opts.logger;
|
|
9836
|
+
this.enabled = opts.enabled;
|
|
9837
|
+
this.dir = `${opts.logPath}/inspect`;
|
|
9838
|
+
}
|
|
9839
|
+
/**
|
|
9840
|
+
* Write the eight start-snapshot files atomically (well, sequentially —
|
|
9841
|
+
* R2 has no multi-object atomic; failures partially-write and the
|
|
9842
|
+
* fail-soft path logs each one).
|
|
9843
|
+
*/
|
|
9844
|
+
async writeStartSnapshot(input) {
|
|
9845
|
+
if (!this.enabled) return;
|
|
9846
|
+
await this.safeWrite("system-prompt.txt", input.systemPrompt);
|
|
9847
|
+
await this.safeWriteJson("tools.json", input.tools);
|
|
9848
|
+
await this.safeWriteJson("run-options.json", input.runOptions);
|
|
9849
|
+
await this.safeWriteJson("model-config.json", input.modelConfig);
|
|
9850
|
+
if (input.skills !== void 0) {
|
|
9851
|
+
await this.safeWriteJson("skills.json", input.skills);
|
|
9852
|
+
}
|
|
9853
|
+
if (input.mcpServers !== void 0) {
|
|
9854
|
+
await this.safeWriteJson("mcp-servers.json", input.mcpServers);
|
|
9855
|
+
}
|
|
9856
|
+
if (input.apiServices !== void 0) {
|
|
9857
|
+
await this.safeWriteJson("api-services.json", input.apiServices);
|
|
9858
|
+
}
|
|
9859
|
+
if (input.knowledge !== void 0) {
|
|
9860
|
+
await this.safeWriteJson("knowledge-scope.json", input.knowledge);
|
|
9861
|
+
}
|
|
9862
|
+
}
|
|
9863
|
+
/** Append one event line to events.jsonl. */
|
|
9864
|
+
async appendEvent(event) {
|
|
9865
|
+
if (!this.enabled) return;
|
|
9866
|
+
await this.safeAppend("events.jsonl", JSON.stringify(event) + "\n");
|
|
9867
|
+
}
|
|
9868
|
+
/** Append one row to turns.jsonl. */
|
|
9869
|
+
async appendTurn(row) {
|
|
9870
|
+
if (!this.enabled) return;
|
|
9871
|
+
await this.safeAppend("turns.jsonl", JSON.stringify(row) + "\n");
|
|
9872
|
+
}
|
|
9873
|
+
/** Write the terminal `tools-summary.json` once at run end. */
|
|
9874
|
+
async writeToolsSummary(summary) {
|
|
9875
|
+
if (!this.enabled) return;
|
|
9876
|
+
await this.safeWriteJson("tools-summary.json", summary);
|
|
9877
|
+
}
|
|
9878
|
+
// ---------- private fail-soft helpers ----------
|
|
9879
|
+
async safeWrite(name, content) {
|
|
9880
|
+
try {
|
|
9881
|
+
await this.storage.writeFile(`${this.dir}/${name}`, content);
|
|
9882
|
+
} catch (err) {
|
|
9883
|
+
this.logFailure("writeFile", name, err);
|
|
9884
|
+
}
|
|
9885
|
+
}
|
|
9886
|
+
async safeWriteJson(name, value) {
|
|
9887
|
+
try {
|
|
9888
|
+
await this.storage.writeFile(`${this.dir}/${name}`, JSON.stringify(value, null, 2));
|
|
9889
|
+
} catch (err) {
|
|
9890
|
+
this.logFailure("writeFile (json)", name, err);
|
|
9891
|
+
}
|
|
9892
|
+
}
|
|
9893
|
+
async safeAppend(name, line) {
|
|
9894
|
+
try {
|
|
9895
|
+
await this.storage.appendFile(`${this.dir}/${name}`, line);
|
|
9896
|
+
} catch (err) {
|
|
9897
|
+
this.logFailure("appendFile", name, err);
|
|
9898
|
+
}
|
|
9899
|
+
}
|
|
9900
|
+
logFailure(op, name, err) {
|
|
9901
|
+
if (this.logger === void 0) return;
|
|
9902
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
9903
|
+
this.logger.warn?.("inspect-writer failed", {
|
|
9904
|
+
op,
|
|
9905
|
+
file: `${this.dir}/${name}`,
|
|
9906
|
+
error: msg
|
|
9907
|
+
});
|
|
9908
|
+
}
|
|
9909
|
+
};
|
|
9910
|
+
var NULL_INSPECT_WRITER = {
|
|
9911
|
+
writeStartSnapshot: async () => void 0,
|
|
9912
|
+
appendEvent: async () => void 0,
|
|
9913
|
+
appendTurn: async () => void 0,
|
|
9914
|
+
writeToolsSummary: async () => void 0
|
|
9915
|
+
};
|
|
9916
|
+
|
|
9917
|
+
// src/inspect/scrub.ts
|
|
9918
|
+
init_cjs_shims();
|
|
9919
|
+
var import_zod_to_json_schema3 = require("zod-to-json-schema");
|
|
9920
|
+
function scrubModelConfig(cfg, opts = { redactBaseURL: false }) {
|
|
9921
|
+
const out = {
|
|
9922
|
+
schemaVersion: 1,
|
|
9923
|
+
provider: cfg.provider,
|
|
9924
|
+
modelId: cfg.modelId
|
|
9925
|
+
};
|
|
9926
|
+
if (!opts.redactBaseURL && cfg.baseURL !== void 0) out.baseURL = cfg.baseURL;
|
|
9927
|
+
if (cfg.temperature !== void 0) out.temperature = cfg.temperature;
|
|
9928
|
+
if (cfg.maxTokens !== void 0) out.maxTokens = cfg.maxTokens;
|
|
9929
|
+
if (cfg.maxRetries !== void 0) out.maxRetries = cfg.maxRetries;
|
|
9930
|
+
return out;
|
|
9931
|
+
}
|
|
9932
|
+
function scrubRunOptions(opts) {
|
|
9933
|
+
const out = {
|
|
9934
|
+
schemaVersion: 1,
|
|
9935
|
+
runId: opts.runId ?? "",
|
|
9936
|
+
nodeId: opts.nodeId,
|
|
9937
|
+
task: opts.task
|
|
9938
|
+
};
|
|
9939
|
+
if (opts.maxTurns !== void 0) out.maxTurns = opts.maxTurns;
|
|
9940
|
+
if (opts.outputFormat !== void 0) out.outputFormat = opts.outputFormat;
|
|
9941
|
+
if (opts.outputSchema !== void 0) out.outputSchema = serializeOutputSchema(opts.outputSchema);
|
|
9942
|
+
if (opts.tools !== void 0) out.tools = [...opts.tools];
|
|
9943
|
+
if (opts.toolChoice !== void 0) out.toolChoice = opts.toolChoice;
|
|
9944
|
+
if (opts.tokenBudget !== void 0) out.tokenBudget = opts.tokenBudget;
|
|
9945
|
+
if (opts.knowledge !== void 0) {
|
|
9946
|
+
const k = {};
|
|
9947
|
+
if (opts.knowledge.folders !== void 0) k.folders = [...opts.knowledge.folders];
|
|
9948
|
+
if (opts.knowledge.external !== void 0) {
|
|
9949
|
+
k.external = opts.knowledge.external.map((e) => {
|
|
9950
|
+
const link = { url: e.url };
|
|
9951
|
+
if (e.description !== void 0) link.description = e.description;
|
|
9952
|
+
return link;
|
|
9953
|
+
});
|
|
9954
|
+
}
|
|
9955
|
+
out.knowledge = k;
|
|
9956
|
+
}
|
|
9957
|
+
if (opts.api !== void 0 && opts.api.services !== void 0) {
|
|
9958
|
+
out.api = {
|
|
9959
|
+
services: opts.api.services.map((s) => {
|
|
9960
|
+
const svc = { name: s.name };
|
|
9961
|
+
if (s.description !== void 0) svc.description = s.description;
|
|
9962
|
+
if (s.baseUrl !== void 0) svc.baseUrl = s.baseUrl;
|
|
9963
|
+
return svc;
|
|
9964
|
+
})
|
|
9965
|
+
};
|
|
9966
|
+
}
|
|
9967
|
+
if (opts.skills !== void 0) {
|
|
9968
|
+
out.skills = opts.skills.map((s) => ({
|
|
9969
|
+
name: s.name,
|
|
9970
|
+
description: s.description ?? "",
|
|
9971
|
+
hasBody: "body" in s && typeof s.body === "string",
|
|
9972
|
+
hasUrl: "url" in s && typeof s.url === "string"
|
|
9973
|
+
}));
|
|
9974
|
+
}
|
|
9975
|
+
if (opts.compaction !== void 0) out.compaction = opts.compaction;
|
|
9976
|
+
if (opts.context !== void 0) out.context = { ...opts.context };
|
|
9977
|
+
return out;
|
|
9978
|
+
}
|
|
9979
|
+
function serializeOutputSchema(schema) {
|
|
9980
|
+
if (schema === null || typeof schema !== "object") return schema;
|
|
9981
|
+
const candidate = schema;
|
|
9982
|
+
if (candidate._def !== void 0 && typeof candidate.safeParse === "function") {
|
|
9983
|
+
try {
|
|
9984
|
+
return (0, import_zod_to_json_schema3.zodToJsonSchema)(schema, {
|
|
9985
|
+
target: "jsonSchema7",
|
|
9986
|
+
$refStrategy: "none"
|
|
9987
|
+
});
|
|
9988
|
+
} catch {
|
|
9989
|
+
return { error: "failed to serialize Zod schema for inspect" };
|
|
9990
|
+
}
|
|
9991
|
+
}
|
|
9992
|
+
return schema;
|
|
9993
|
+
}
|
|
9994
|
+
function scrubSkills(skills) {
|
|
9995
|
+
return {
|
|
9996
|
+
schemaVersion: 1,
|
|
9997
|
+
skills: skills.map((s) => ({
|
|
9998
|
+
name: s.name,
|
|
9999
|
+
description: s.description ?? "",
|
|
10000
|
+
hasPages: s.hasPages ?? false
|
|
10001
|
+
}))
|
|
10002
|
+
};
|
|
10003
|
+
}
|
|
10004
|
+
function scrubApiServices(services) {
|
|
10005
|
+
return {
|
|
10006
|
+
schemaVersion: 1,
|
|
10007
|
+
services: services.map((s) => {
|
|
10008
|
+
const out = { name: s.name };
|
|
10009
|
+
if (s.description !== void 0) out.description = s.description;
|
|
10010
|
+
if (s.baseUrl !== void 0) out.baseUrl = s.baseUrl;
|
|
10011
|
+
if (s.methods !== void 0) out.methods = s.methods.map((m) => m.name);
|
|
10012
|
+
return out;
|
|
10013
|
+
})
|
|
10014
|
+
};
|
|
10015
|
+
}
|
|
10016
|
+
|
|
9724
10017
|
// src/engine/rehydrate.ts
|
|
9725
10018
|
init_cjs_shims();
|
|
9726
10019
|
function rebuildMessagesFromEntries(entries) {
|
|
@@ -10198,6 +10491,37 @@ var Engine = class {
|
|
|
10198
10491
|
...this.internals.fetch !== void 0 ? { fetch: this.internals.fetch } : {}
|
|
10199
10492
|
});
|
|
10200
10493
|
applyRunToolFilter(registry, options);
|
|
10494
|
+
const inspect = this.buildInspectWriter(storage.workspace, logPath);
|
|
10495
|
+
await inspect.writeStartSnapshot({
|
|
10496
|
+
systemPrompt,
|
|
10497
|
+
tools: this.snapshotTools(registry, mcpTools),
|
|
10498
|
+
runOptions: scrubRunOptions({ ...options, runId }),
|
|
10499
|
+
modelConfig: scrubModelConfig(
|
|
10500
|
+
{
|
|
10501
|
+
provider: this.config.model.provider,
|
|
10502
|
+
modelId: this.config.model.modelId,
|
|
10503
|
+
...this.config.model.baseURL !== void 0 ? { baseURL: this.config.model.baseURL } : {},
|
|
10504
|
+
...this.config.model.temperature !== void 0 ? { temperature: this.config.model.temperature } : {},
|
|
10505
|
+
...this.config.model.maxTokens !== void 0 ? { maxTokens: this.config.model.maxTokens } : {},
|
|
10506
|
+
...this.config.model.maxRetries !== void 0 ? { maxRetries: this.config.model.maxRetries } : {}
|
|
10507
|
+
},
|
|
10508
|
+
{ redactBaseURL: this.config.inspect.redactBaseURL }
|
|
10509
|
+
),
|
|
10510
|
+
...skillList !== void 0 ? { skills: scrubSkills(skillList) } : {},
|
|
10511
|
+
...mcpTools.length > 0 ? { mcpServers: this.snapshotMcpServers(mcpTools) } : {},
|
|
10512
|
+
...apiConfig !== void 0 && apiConfig.services.length > 0 ? { apiServices: scrubApiServices(apiConfig.services) } : {},
|
|
10513
|
+
...knowledgeRuntime !== void 0 ? {
|
|
10514
|
+
knowledge: {
|
|
10515
|
+
schemaVersion: 1,
|
|
10516
|
+
folders: [...knowledgeRuntime.folders],
|
|
10517
|
+
external: knowledgeRuntime.external.map((e) => {
|
|
10518
|
+
const link = { url: e.url };
|
|
10519
|
+
if (e.description !== void 0) link.description = e.description;
|
|
10520
|
+
return link;
|
|
10521
|
+
})
|
|
10522
|
+
}
|
|
10523
|
+
} : {}
|
|
10524
|
+
});
|
|
10201
10525
|
const writer = new TranscriptWriter({
|
|
10202
10526
|
storage: storage.workspace,
|
|
10203
10527
|
logPath,
|
|
@@ -10259,7 +10583,10 @@ var Engine = class {
|
|
|
10259
10583
|
// is already handled above by stripping the tool list, so the
|
|
10260
10584
|
// loop only ever sees `'auto'` or `'required'`.
|
|
10261
10585
|
...options.outputFormat !== void 0 ? { outputFormat: options.outputFormat } : {},
|
|
10262
|
-
...options.toolChoice === "required" ? { toolChoice: "required" } : {}
|
|
10586
|
+
...options.toolChoice === "required" ? { toolChoice: "required" } : {},
|
|
10587
|
+
// Plan 026 — pass the inspect writer so the loop can append
|
|
10588
|
+
// events / per-turn rows. Disabled-mode writer is a no-op.
|
|
10589
|
+
inspect
|
|
10263
10590
|
});
|
|
10264
10591
|
const result = await this.finalizeResult(loopResult, writer, logPath, {
|
|
10265
10592
|
...options.outputFormat !== void 0 ? { outputFormat: options.outputFormat } : {},
|
|
@@ -10267,6 +10594,7 @@ var Engine = class {
|
|
|
10267
10594
|
});
|
|
10268
10595
|
this.logRunEnd(log, runId, options.nodeId, result);
|
|
10269
10596
|
await this.firePostRunHook(runId, options.nodeId, result, ctx, logPath);
|
|
10597
|
+
await this.writeInspectToolsSummary(inspect, storage.workspace, logPath);
|
|
10270
10598
|
const capabilitiesMissing = ctx.getCapabilitiesMissing();
|
|
10271
10599
|
return toResponse(result, {
|
|
10272
10600
|
runId,
|
|
@@ -10352,6 +10680,43 @@ var Engine = class {
|
|
|
10352
10680
|
...knowledgeRuntime !== void 0 ? { knowledge: knowledgeRuntime } : {},
|
|
10353
10681
|
...this.internals.fetch !== void 0 ? { fetch: this.internals.fetch } : {}
|
|
10354
10682
|
});
|
|
10683
|
+
const inspect = this.buildInspectWriter(storage.workspace, logPath);
|
|
10684
|
+
await inspect.writeStartSnapshot({
|
|
10685
|
+
systemPrompt,
|
|
10686
|
+
tools: this.snapshotTools(registry, mcpTools),
|
|
10687
|
+
runOptions: scrubRunOptions({
|
|
10688
|
+
runId: snapshot.runId,
|
|
10689
|
+
nodeId: snapshot.nodeId,
|
|
10690
|
+
task: "[resumed run \u2014 original task in transcript]",
|
|
10691
|
+
...options.outputFormat !== void 0 ? { outputFormat: options.outputFormat } : {},
|
|
10692
|
+
...options.outputSchema !== void 0 ? { outputSchema: options.outputSchema } : {}
|
|
10693
|
+
}),
|
|
10694
|
+
modelConfig: scrubModelConfig(
|
|
10695
|
+
{
|
|
10696
|
+
provider: this.config.model.provider,
|
|
10697
|
+
modelId: this.config.model.modelId,
|
|
10698
|
+
...this.config.model.baseURL !== void 0 ? { baseURL: this.config.model.baseURL } : {},
|
|
10699
|
+
...this.config.model.temperature !== void 0 ? { temperature: this.config.model.temperature } : {},
|
|
10700
|
+
...this.config.model.maxTokens !== void 0 ? { maxTokens: this.config.model.maxTokens } : {},
|
|
10701
|
+
...this.config.model.maxRetries !== void 0 ? { maxRetries: this.config.model.maxRetries } : {}
|
|
10702
|
+
},
|
|
10703
|
+
{ redactBaseURL: this.config.inspect.redactBaseURL }
|
|
10704
|
+
),
|
|
10705
|
+
...skillList !== void 0 ? { skills: scrubSkills(skillList) } : {},
|
|
10706
|
+
...mcpTools.length > 0 ? { mcpServers: this.snapshotMcpServers(mcpTools) } : {},
|
|
10707
|
+
...apiConfig !== void 0 && apiConfig.services.length > 0 ? { apiServices: scrubApiServices(apiConfig.services) } : {},
|
|
10708
|
+
...knowledgeRuntime !== void 0 ? {
|
|
10709
|
+
knowledge: {
|
|
10710
|
+
schemaVersion: 1,
|
|
10711
|
+
folders: [...knowledgeRuntime.folders],
|
|
10712
|
+
external: knowledgeRuntime.external.map((e) => {
|
|
10713
|
+
const link = { url: e.url };
|
|
10714
|
+
if (e.description !== void 0) link.description = e.description;
|
|
10715
|
+
return link;
|
|
10716
|
+
})
|
|
10717
|
+
}
|
|
10718
|
+
} : {}
|
|
10719
|
+
});
|
|
10355
10720
|
const priorState = await loadWriterState(storage.workspace, logPath);
|
|
10356
10721
|
const writer = new TranscriptWriter({
|
|
10357
10722
|
storage: storage.workspace,
|
|
@@ -10441,7 +10806,10 @@ ${inputJson}
|
|
|
10441
10806
|
...runTimeout.signal !== void 0 ? { runSignal: runTimeout.signal, runTimeoutMs: this.config.execution.runTimeoutMs } : {},
|
|
10442
10807
|
...gate !== void 0 ? { gateBeforeTool: gate } : {},
|
|
10443
10808
|
..._internal?.handoffToRunner === true ? { handoffToRunner: true } : {},
|
|
10444
|
-
...offloadConfig !== void 0 ? { toolResultOffload: offloadConfig } : {}
|
|
10809
|
+
...offloadConfig !== void 0 ? { toolResultOffload: offloadConfig } : {},
|
|
10810
|
+
// Plan 026 — append resume's events / per-turn rows to the
|
|
10811
|
+
// existing inspect/ logs.
|
|
10812
|
+
inspect
|
|
10445
10813
|
});
|
|
10446
10814
|
const result = await this.finalizeResult(loopResult, writer, logPath, {
|
|
10447
10815
|
...options.outputFormat !== void 0 ? { outputFormat: options.outputFormat } : {},
|
|
@@ -10449,6 +10817,7 @@ ${inputJson}
|
|
|
10449
10817
|
});
|
|
10450
10818
|
this.logRunEnd(log, snapshot.runId, snapshot.nodeId, result);
|
|
10451
10819
|
await this.firePostRunHook(snapshot.runId, snapshot.nodeId, result, ctx, logPath);
|
|
10820
|
+
await this.writeInspectToolsSummary(inspect, storage.workspace, logPath);
|
|
10452
10821
|
const capabilitiesMissing = ctx.getCapabilitiesMissing();
|
|
10453
10822
|
return toResponse(result, {
|
|
10454
10823
|
runId: snapshot.runId,
|
|
@@ -11292,7 +11661,147 @@ ${inputJson}
|
|
|
11292
11661
|
...this.internals.fetch !== void 0 ? { fetch: this.internals.fetch } : {}
|
|
11293
11662
|
});
|
|
11294
11663
|
}
|
|
11664
|
+
// Plan 026 — inspect-bundle helpers ----------------------------
|
|
11665
|
+
buildInspectWriter(storage, logPath) {
|
|
11666
|
+
const inspect = this.config.inspect;
|
|
11667
|
+
return new InspectWriter({
|
|
11668
|
+
storage,
|
|
11669
|
+
logPath,
|
|
11670
|
+
enabled: inspect.enabled
|
|
11671
|
+
});
|
|
11672
|
+
}
|
|
11673
|
+
/**
|
|
11674
|
+
* Snapshot the live ToolRegistry into the inspect-bundle shape.
|
|
11675
|
+
* Tool source is inferred by name: MCP tools have the
|
|
11676
|
+
* `mcp__{server}__{tool}` prefix; everything else is core.
|
|
11677
|
+
*/
|
|
11678
|
+
snapshotTools(registry, mcpTools) {
|
|
11679
|
+
const mcpNameSet = new Set(mcpTools.map((t) => t.name));
|
|
11680
|
+
return {
|
|
11681
|
+
schemaVersion: 1,
|
|
11682
|
+
tools: registry.list().map((t) => {
|
|
11683
|
+
const out = {
|
|
11684
|
+
name: t.name,
|
|
11685
|
+
description: t.description ?? "",
|
|
11686
|
+
inputSchema: this.toolInputSchemaToJson(t),
|
|
11687
|
+
source: mcpNameSet.has(t.name) ? "mcp" : "core",
|
|
11688
|
+
...t.isCapabilityStub === true ? { isCapabilityStub: true } : {}
|
|
11689
|
+
};
|
|
11690
|
+
return out;
|
|
11691
|
+
})
|
|
11692
|
+
};
|
|
11693
|
+
}
|
|
11694
|
+
/** Convert a Zod input schema to JSON Schema for persistence. */
|
|
11695
|
+
toolInputSchemaToJson(t) {
|
|
11696
|
+
const raw = t.inputSchema;
|
|
11697
|
+
if (raw === void 0 || raw === null) return {};
|
|
11698
|
+
const candidate = raw;
|
|
11699
|
+
if (typeof candidate === "object" && candidate._def !== void 0 && typeof candidate.safeParse === "function") {
|
|
11700
|
+
try {
|
|
11701
|
+
const json2 = (0, import_zod_to_json_schema4.zodToJsonSchema)(raw, {
|
|
11702
|
+
target: "jsonSchema7",
|
|
11703
|
+
$refStrategy: "none"
|
|
11704
|
+
});
|
|
11705
|
+
return json2;
|
|
11706
|
+
} catch {
|
|
11707
|
+
return {};
|
|
11708
|
+
}
|
|
11709
|
+
}
|
|
11710
|
+
return raw;
|
|
11711
|
+
}
|
|
11712
|
+
/**
|
|
11713
|
+
* Plan 026 — aggregate `tools-summary.json` from the persisted
|
|
11714
|
+
* transcript shards. Walks meta.json for shard count, reads each
|
|
11715
|
+
* shard, counts every tool_use block by name. Best-effort; the
|
|
11716
|
+
* InspectWriter swallows write failures.
|
|
11717
|
+
*/
|
|
11718
|
+
async writeInspectToolsSummary(inspect, storage, logPath) {
|
|
11719
|
+
const counts = /* @__PURE__ */ new Map();
|
|
11720
|
+
let total = 0;
|
|
11721
|
+
try {
|
|
11722
|
+
const metaRaw = await storage.readFile(`${logPath}/meta.json`);
|
|
11723
|
+
if (!metaRaw) return;
|
|
11724
|
+
const meta = JSON.parse(metaRaw);
|
|
11725
|
+
const shardCount = meta.shardCount ?? 0;
|
|
11726
|
+
for (let i = 0; i < shardCount; i++) {
|
|
11727
|
+
const name = `${String(i).padStart(6, "0")}.jsonl`;
|
|
11728
|
+
const text2 = await storage.readFile(`${logPath}/${name}`);
|
|
11729
|
+
if (!text2) continue;
|
|
11730
|
+
for (const line of text2.split("\n")) {
|
|
11731
|
+
if (!line) continue;
|
|
11732
|
+
try {
|
|
11733
|
+
const entry = JSON.parse(line);
|
|
11734
|
+
if (entry.type !== "assistant") continue;
|
|
11735
|
+
const content = entry.message?.content;
|
|
11736
|
+
if (!Array.isArray(content)) continue;
|
|
11737
|
+
for (const block of content) {
|
|
11738
|
+
const b = block;
|
|
11739
|
+
if (b.type === "tool_use" && typeof b.name === "string") {
|
|
11740
|
+
counts.set(b.name, (counts.get(b.name) ?? 0) + 1);
|
|
11741
|
+
total++;
|
|
11742
|
+
}
|
|
11743
|
+
}
|
|
11744
|
+
} catch {
|
|
11745
|
+
}
|
|
11746
|
+
}
|
|
11747
|
+
}
|
|
11748
|
+
} catch {
|
|
11749
|
+
return;
|
|
11750
|
+
}
|
|
11751
|
+
await inspect.writeToolsSummary({
|
|
11752
|
+
schemaVersion: 1,
|
|
11753
|
+
tools: [...counts.entries()].map(([name, callCount]) => ({ name, callCount })).sort((a, b) => b.callCount - a.callCount),
|
|
11754
|
+
totalCalls: total
|
|
11755
|
+
});
|
|
11756
|
+
}
|
|
11757
|
+
/**
|
|
11758
|
+
* Snapshot the resolved MCP servers. Right now `mcpManager.getTools()`
|
|
11759
|
+
* returns the flat tool list; we group them by server-name prefix to
|
|
11760
|
+
* recover which server exposed which tool.
|
|
11761
|
+
*/
|
|
11762
|
+
snapshotMcpServers(mcpTools) {
|
|
11763
|
+
const byServer = /* @__PURE__ */ new Map();
|
|
11764
|
+
for (const t of mcpTools) {
|
|
11765
|
+
const m = t.name.match(/^mcp__([^_]+)__(.+)$/);
|
|
11766
|
+
const server = m?.[1] ?? "unknown";
|
|
11767
|
+
const list = byServer.get(server) ?? [];
|
|
11768
|
+
list.push(t.name);
|
|
11769
|
+
byServer.set(server, list);
|
|
11770
|
+
}
|
|
11771
|
+
const declaredMap = this.config.mcp.servers;
|
|
11772
|
+
return {
|
|
11773
|
+
schemaVersion: 1,
|
|
11774
|
+
servers: [...byServer.entries()].map(([name, tools]) => {
|
|
11775
|
+
const declared = declaredMap[name];
|
|
11776
|
+
const out = {
|
|
11777
|
+
name,
|
|
11778
|
+
// If the server isn't in the declared map (synthetic / dynamic),
|
|
11779
|
+
// default to 'http' as a best-effort label.
|
|
11780
|
+
type: declared?.type ?? "http",
|
|
11781
|
+
state: "connected",
|
|
11782
|
+
tools
|
|
11783
|
+
};
|
|
11784
|
+
if (declared !== void 0) {
|
|
11785
|
+
if (declared.type === "stdio") {
|
|
11786
|
+
out.command = declared.command;
|
|
11787
|
+
out.args = [...declared.args];
|
|
11788
|
+
} else {
|
|
11789
|
+
out.url = declared.url;
|
|
11790
|
+
if (declared.headers !== void 0) {
|
|
11791
|
+
out.headers = redactHeadersInline(declared.headers);
|
|
11792
|
+
}
|
|
11793
|
+
}
|
|
11794
|
+
}
|
|
11795
|
+
return out;
|
|
11796
|
+
})
|
|
11797
|
+
};
|
|
11798
|
+
}
|
|
11295
11799
|
};
|
|
11800
|
+
function redactHeadersInline(headers) {
|
|
11801
|
+
const out = {};
|
|
11802
|
+
for (const k of Object.keys(headers)) out[k] = "<redacted>";
|
|
11803
|
+
return out;
|
|
11804
|
+
}
|
|
11296
11805
|
function buildToolRegistry(options) {
|
|
11297
11806
|
const {
|
|
11298
11807
|
config,
|
|
@@ -11483,6 +11992,11 @@ init_retry();
|
|
|
11483
11992
|
init_snapshot();
|
|
11484
11993
|
init_synthesize();
|
|
11485
11994
|
init_types();
|
|
11995
|
+
|
|
11996
|
+
// src/inspect/index.ts
|
|
11997
|
+
init_cjs_shims();
|
|
11998
|
+
|
|
11999
|
+
// src/index.ts
|
|
11486
12000
|
var ENGINE_VERSION = "0.0.0";
|
|
11487
12001
|
function initEngine(user = {}) {
|
|
11488
12002
|
let resolved;
|
|
@@ -11522,6 +12036,7 @@ function resolveApiKey(config) {
|
|
|
11522
12036
|
EpisodicMemory,
|
|
11523
12037
|
Hippocampus,
|
|
11524
12038
|
InlineSkillSource,
|
|
12039
|
+
InspectWriter,
|
|
11525
12040
|
LocalStorageAdapter,
|
|
11526
12041
|
MAX_ATTEMPTS,
|
|
11527
12042
|
McpClient,
|
|
@@ -11529,6 +12044,7 @@ function resolveApiKey(config) {
|
|
|
11529
12044
|
McpManager,
|
|
11530
12045
|
McpProtocolError,
|
|
11531
12046
|
McpTimeoutError,
|
|
12047
|
+
NULL_INSPECT_WRITER,
|
|
11532
12048
|
NodeBackgroundExecutor,
|
|
11533
12049
|
NotImplementedError,
|
|
11534
12050
|
PlanSchema,
|