la-machina-engine 0.4.0 → 0.6.0

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 CHANGED
@@ -37,24 +37,113 @@ var init_cjs_shims = __esm({
37
37
  }
38
38
  });
39
39
 
40
+ // src/tools/contract.ts
41
+ function defineTool(tool) {
42
+ return tool;
43
+ }
44
+ var ToolRegistry;
45
+ var init_contract = __esm({
46
+ "src/tools/contract.ts"() {
47
+ "use strict";
48
+ init_cjs_shims();
49
+ ToolRegistry = class {
50
+ tools = /* @__PURE__ */ new Map();
51
+ register(tool) {
52
+ if (typeof tool.name !== "string" || tool.name.length === 0) {
53
+ throw new Error("ToolRegistry: tool.name must be a non-empty string");
54
+ }
55
+ if (this.tools.has(tool.name)) {
56
+ throw new Error(`ToolRegistry: "${tool.name}" is already registered`);
57
+ }
58
+ this.tools.set(tool.name, tool);
59
+ }
60
+ registerAll(tools) {
61
+ for (const tool of tools) this.register(tool);
62
+ }
63
+ unregister(name) {
64
+ this.tools.delete(name);
65
+ }
66
+ get(name) {
67
+ return this.tools.get(name);
68
+ }
69
+ has(name) {
70
+ return this.tools.has(name);
71
+ }
72
+ list() {
73
+ return Array.from(this.tools.values());
74
+ }
75
+ count() {
76
+ return this.tools.size;
77
+ }
78
+ };
79
+ }
80
+ });
81
+
82
+ // src/tools/fetchData.ts
83
+ var fetchData_exports = {};
84
+ __export(fetchData_exports, {
85
+ createFetchDataTool: () => createFetchDataTool
86
+ });
87
+ function createFetchDataTool(opts) {
88
+ return defineTool({
89
+ name: "FetchData",
90
+ description: "Fetch the full content of a tool result that was offloaded because it was too large for the main context. Pass the `ref` token from the summarized tool_result message (the text that looked like 'Use FetchData with ref=\"...\"'). Returns the raw bytes of the original tool output.",
91
+ inputSchema,
92
+ execute: async ({ ref }) => {
93
+ if (!SAFE_REF.test(ref)) {
94
+ return {
95
+ content: `ERR_OFFLOAD_INVALID_REF: ref "${ref}" contains unsafe characters`,
96
+ isError: true
97
+ };
98
+ }
99
+ const path = `${opts.logPath}/toolResults/${ref}.json`;
100
+ const raw = await opts.storage.readFile(path);
101
+ if (raw === null) {
102
+ return {
103
+ content: `ERR_OFFLOAD_REF_NOT_FOUND: no data found for ref "${ref}"`,
104
+ isError: true
105
+ };
106
+ }
107
+ return {
108
+ content: raw,
109
+ isError: false,
110
+ metadata: { ref, bytes: raw.length }
111
+ };
112
+ }
113
+ });
114
+ }
115
+ var import_zod6, SAFE_REF, inputSchema;
116
+ var init_fetchData = __esm({
117
+ "src/tools/fetchData.ts"() {
118
+ "use strict";
119
+ init_cjs_shims();
120
+ import_zod6 = require("zod");
121
+ init_contract();
122
+ SAFE_REF = /^[a-zA-Z0-9_-]+$/;
123
+ inputSchema = import_zod6.z.object({
124
+ ref: import_zod6.z.string().min(1)
125
+ });
126
+ }
127
+ });
128
+
40
129
  // src/orchestrator/types.ts
41
- var import_zod25, PlanStepSchema, PlanSchema;
130
+ var import_zod26, PlanStepSchema, PlanSchema;
42
131
  var init_types = __esm({
43
132
  "src/orchestrator/types.ts"() {
44
133
  "use strict";
45
134
  init_cjs_shims();
46
- import_zod25 = require("zod");
47
- PlanStepSchema = import_zod25.z.object({
48
- id: import_zod25.z.string().min(1),
49
- description: import_zod25.z.string().min(1),
50
- action: import_zod25.z.enum(["research", "implement", "verify", "review", "custom"]),
51
- files: import_zod25.z.array(import_zod25.z.string()).optional(),
52
- spec: import_zod25.z.string().optional(),
53
- dependsOn: import_zod25.z.array(import_zod25.z.string()).optional()
135
+ import_zod26 = require("zod");
136
+ PlanStepSchema = import_zod26.z.object({
137
+ id: import_zod26.z.string().min(1),
138
+ description: import_zod26.z.string().min(1),
139
+ action: import_zod26.z.enum(["research", "implement", "verify", "review", "custom"]),
140
+ files: import_zod26.z.array(import_zod26.z.string()).optional(),
141
+ spec: import_zod26.z.string().optional(),
142
+ dependsOn: import_zod26.z.array(import_zod26.z.string()).optional()
54
143
  });
55
- PlanSchema = import_zod25.z.object({
56
- summary: import_zod25.z.string().min(1),
57
- steps: import_zod25.z.array(PlanStepSchema).min(1)
144
+ PlanSchema = import_zod26.z.object({
145
+ summary: import_zod26.z.string().min(1),
146
+ steps: import_zod26.z.array(PlanStepSchema).min(1)
58
147
  });
59
148
  }
60
149
  });
@@ -787,12 +876,14 @@ __export(index_exports, {
787
876
  canSpawnProcesses: () => canSpawnProcesses,
788
877
  capabilityStub: () => capabilityStub,
789
878
  createApiCallTool: () => createApiCallTool,
879
+ createFetchDataTool: () => createFetchDataTool,
790
880
  createLogger: () => createLogger,
791
881
  createModelAdapter: () => createModelAdapter,
792
882
  createSendMessageTool: () => createSendMessageTool,
793
883
  createSkillPageTool: () => createSkillPageTool,
794
884
  createSmartMemory: () => createSmartMemory,
795
885
  defaultSamplingHandler: () => defaultSamplingHandler,
886
+ defaultToolResultSummarizer: () => defaultToolResultSummarizer,
796
887
  defineTool: () => defineTool,
797
888
  detectRuntime: () => detectRuntime,
798
889
  getCoordinatorBasePrompt: () => getCoordinatorBasePrompt,
@@ -817,7 +908,7 @@ __export(index_exports, {
817
908
  snapshotFiles: () => snapshotFiles,
818
909
  synthesizeSpec: () => synthesizeSpec,
819
910
  toResponse: () => toResponse,
820
- tryParseJSON: () => tryParseJSON,
911
+ tryParseJSON: () => tryParseJSON2,
821
912
  validateOutput: () => validateOutput,
822
913
  withCapabilityCheck: () => withCapabilityCheck
823
914
  });
@@ -943,7 +1034,8 @@ var ModelProviderEnum = import_zod.z.enum([
943
1034
  ]);
944
1035
  var StorageProviderEnum = import_zod.z.enum(["local", "r2", "r2-binding"]);
945
1036
  var MemoryModeEnum = import_zod.z.enum(["off", "read-only", "read-write"]);
946
- var MemoryScopeEnum = import_zod.z.enum(["workspace", "global"]);
1037
+ var MemoryScopeUserEnum = import_zod.z.enum(["workspace", "global"]);
1038
+ var MemoryScopeResolvedEnum = import_zod.z.enum(["workspace"]);
947
1039
  var FlushPolicyEnum = import_zod.z.enum(["turn-end", "entry", "manual"]);
948
1040
  var LogLevelEnum = import_zod.z.enum(["silent", "error", "warn", "info", "debug"]);
949
1041
  var R2ConfigResolved = import_zod.z.object({
@@ -982,7 +1074,7 @@ var StorageConfigResolved = import_zod.z.object({
982
1074
  });
983
1075
  var MemoryConfigResolved = import_zod.z.object({
984
1076
  mode: MemoryModeEnum,
985
- scope: MemoryScopeEnum
1077
+ scope: MemoryScopeResolvedEnum
986
1078
  }).strict();
987
1079
  var ToolsConfigResolved = import_zod.z.object({
988
1080
  enabled: import_zod.z.array(import_zod.z.string()),
@@ -1070,13 +1162,19 @@ var McpConfigResolved = import_zod.z.object({
1070
1162
  shutdownTimeoutMs: import_zod.z.number().int().positive()
1071
1163
  }).strict();
1072
1164
  var CompactionStrategyEnum = import_zod.z.enum(["drop-middle", "summarize", "session-memory", "auto"]);
1165
+ var ToolResultOffloadConfigResolved = import_zod.z.object({
1166
+ enabled: import_zod.z.boolean(),
1167
+ thresholdBytes: import_zod.z.number().int().positive(),
1168
+ maxPreviewChars: import_zod.z.number().int().positive()
1169
+ }).strict();
1073
1170
  var CompactionConfigResolved = import_zod.z.object({
1074
1171
  strategy: CompactionStrategyEnum,
1075
1172
  threshold: import_zod.z.number().min(0).max(1),
1076
1173
  keepLast: import_zod.z.number().int().positive(),
1077
1174
  summaryMaxTokens: import_zod.z.number().int().positive(),
1078
1175
  microcompact: import_zod.z.boolean(),
1079
- microcompactAgeMs: import_zod.z.number().int().nonnegative()
1176
+ microcompactAgeMs: import_zod.z.number().int().nonnegative(),
1177
+ toolResultOffload: ToolResultOffloadConfigResolved.optional()
1080
1178
  }).strict();
1081
1179
  var CoordinatorConfigResolved = import_zod.z.object({
1082
1180
  enabled: import_zod.z.boolean(),
@@ -1177,7 +1275,10 @@ var StorageConfigUser = import_zod.z.object({
1177
1275
  r2: R2ConfigUser.optional(),
1178
1276
  r2Binding: R2BucketBindingShape.optional()
1179
1277
  }).strict();
1180
- var MemoryConfigUser = MemoryConfigResolved.partial();
1278
+ var MemoryConfigUser = import_zod.z.object({
1279
+ mode: MemoryModeEnum.optional(),
1280
+ scope: MemoryScopeUserEnum.optional()
1281
+ }).strict();
1181
1282
  var ToolsConfigUser = ToolsConfigResolved.partial();
1182
1283
  var AgentsConfigUser = AgentsConfigResolved.partial();
1183
1284
  var SkillsConfigUser = SkillsConfigResolved.partial();
@@ -1209,7 +1310,16 @@ var McpConfigUser = import_zod.z.object({
1209
1310
  var PermissionsConfigUser = PermissionsConfigResolved.partial();
1210
1311
  var RunnerConfigUser = RunnerConfigResolved;
1211
1312
  var ApiConfigUser = ApiConfigResolved.partial();
1212
- var CompactionConfigUser = CompactionConfigResolved.partial();
1313
+ var ToolResultOffloadConfigUser = ToolResultOffloadConfigResolved.partial();
1314
+ var CompactionConfigUser = import_zod.z.object({
1315
+ strategy: CompactionStrategyEnum.optional(),
1316
+ threshold: import_zod.z.number().min(0).max(1).optional(),
1317
+ keepLast: import_zod.z.number().int().positive().optional(),
1318
+ summaryMaxTokens: import_zod.z.number().int().positive().optional(),
1319
+ microcompact: import_zod.z.boolean().optional(),
1320
+ microcompactAgeMs: import_zod.z.number().int().nonnegative().optional(),
1321
+ toolResultOffload: ToolResultOffloadConfigUser.optional()
1322
+ }).strict();
1213
1323
  var CoordinatorConfigUser = CoordinatorConfigResolved.partial();
1214
1324
  var OrchestratorConfigUser = OrchestratorConfigResolved.deepPartial();
1215
1325
  var UserConfigSchema = import_zod.z.object({
@@ -1290,8 +1400,41 @@ function splitApiRuntime(user) {
1290
1400
  const clone = { ...user, api: schemaSafe };
1291
1401
  return { stripped: clone, runtime };
1292
1402
  }
1403
+ function coerceDeprecatedMemoryScope(user) {
1404
+ const scope = user.memory?.scope;
1405
+ if (scope !== "global") return user;
1406
+ console.warn(
1407
+ '[la-machina] config.memory.scope: "global" is deprecated and has been rewritten to "workspace". Cross-tenant memory sharing was removed in Plan 022 \u2014 the workspace is the tenant root. This field value will be rejected outright in a future major release.'
1408
+ );
1409
+ const memory = user.memory ?? {};
1410
+ return {
1411
+ ...user,
1412
+ memory: { ...memory, scope: "workspace" }
1413
+ };
1414
+ }
1415
+ var OFFLOAD_DEFAULTS = { thresholdBytes: 2048, maxPreviewChars: 500 };
1416
+ function splitOffloadRuntime(user) {
1417
+ const block = user.compaction?.toolResultOffload;
1418
+ if (block === void 0) return { stripped: user };
1419
+ const { summarizer, ...schemaSafe } = block;
1420
+ const filled = {
1421
+ enabled: schemaSafe.enabled ?? false,
1422
+ thresholdBytes: schemaSafe.thresholdBytes ?? OFFLOAD_DEFAULTS.thresholdBytes,
1423
+ maxPreviewChars: schemaSafe.maxPreviewChars ?? OFFLOAD_DEFAULTS.maxPreviewChars
1424
+ };
1425
+ const clone = {
1426
+ ...user,
1427
+ compaction: {
1428
+ ...user.compaction ?? {},
1429
+ toolResultOffload: filled
1430
+ }
1431
+ };
1432
+ return { stripped: clone, summarizer };
1433
+ }
1293
1434
  function mergeConfig(user) {
1294
- const { stripped, runtime } = splitApiRuntime(user);
1435
+ const withCoercedScope = coerceDeprecatedMemoryScope(user);
1436
+ const { stripped: afterOffload, summarizer } = splitOffloadRuntime(withCoercedScope);
1437
+ const { stripped, runtime } = splitApiRuntime(afterOffload);
1295
1438
  const validatedUser = UserConfigSchema.parse(stripped);
1296
1439
  const merged = deepMerge(DEFAULTS, validatedUser);
1297
1440
  const resolved = ResolvedConfigSchema.parse(merged);
@@ -1303,6 +1446,13 @@ function mergeConfig(user) {
1303
1446
  };
1304
1447
  } else if (Object.keys(runtime).length > 0) {
1305
1448
  }
1449
+ if (summarizer !== void 0 && resolved.compaction.toolResultOffload !== void 0) {
1450
+ const mutable = resolved.compaction;
1451
+ mutable.toolResultOffload = {
1452
+ ...resolved.compaction.toolResultOffload,
1453
+ summarizer
1454
+ };
1455
+ }
1306
1456
  return resolved;
1307
1457
  }
1308
1458
 
@@ -1949,44 +2099,7 @@ function hasProcessLifecycle() {
1949
2099
  // src/tools/capabilityStub.ts
1950
2100
  init_cjs_shims();
1951
2101
  var import_zod2 = require("zod");
1952
-
1953
- // src/tools/contract.ts
1954
- init_cjs_shims();
1955
- function defineTool(tool) {
1956
- return tool;
1957
- }
1958
- var ToolRegistry = class {
1959
- tools = /* @__PURE__ */ new Map();
1960
- register(tool) {
1961
- if (typeof tool.name !== "string" || tool.name.length === 0) {
1962
- throw new Error("ToolRegistry: tool.name must be a non-empty string");
1963
- }
1964
- if (this.tools.has(tool.name)) {
1965
- throw new Error(`ToolRegistry: "${tool.name}" is already registered`);
1966
- }
1967
- this.tools.set(tool.name, tool);
1968
- }
1969
- registerAll(tools) {
1970
- for (const tool of tools) this.register(tool);
1971
- }
1972
- unregister(name) {
1973
- this.tools.delete(name);
1974
- }
1975
- get(name) {
1976
- return this.tools.get(name);
1977
- }
1978
- has(name) {
1979
- return this.tools.has(name);
1980
- }
1981
- list() {
1982
- return Array.from(this.tools.values());
1983
- }
1984
- count() {
1985
- return this.tools.size;
1986
- }
1987
- };
1988
-
1989
- // src/tools/capabilityStub.ts
2102
+ init_contract();
1990
2103
  var anyInput = import_zod2.z.unknown();
1991
2104
  function capabilityStub(original) {
1992
2105
  return defineTool({
@@ -2190,7 +2303,7 @@ var SubagentRegistry = class _SubagentRegistry {
2190
2303
 
2191
2304
  // src/tools/agent.ts
2192
2305
  init_cjs_shims();
2193
- var import_zod6 = require("zod");
2306
+ var import_zod7 = require("zod");
2194
2307
 
2195
2308
  // src/subagent/runner.ts
2196
2309
  init_cjs_shims();
@@ -2254,6 +2367,131 @@ async function writeSnapshot(storage, logPath, snapshot) {
2254
2367
  await storage.writeFile(snapshotPath(logPath), JSON.stringify(validated, null, 2));
2255
2368
  }
2256
2369
 
2370
+ // src/engine/toolResultOffload.ts
2371
+ init_cjs_shims();
2372
+
2373
+ // src/engine/toolResultSummarizer.ts
2374
+ init_cjs_shims();
2375
+ var MAX_ITEM_PREVIEW_CHARS = 150;
2376
+ var MAX_TOP_LEVEL_KEYS = 8;
2377
+ var defaultToolResultSummarizer = (ctx) => {
2378
+ return summarize(ctx);
2379
+ };
2380
+ function summarize(ctx) {
2381
+ const { toolName, rawContent, rawBytes, ref, maxPreviewChars } = ctx;
2382
+ const parsed = tryParseJSON(rawContent);
2383
+ if (parsed.ok) {
2384
+ if (Array.isArray(parsed.value)) {
2385
+ return summarizeArray(toolName, parsed.value, ref, rawBytes);
2386
+ }
2387
+ if (parsed.value !== null && typeof parsed.value === "object") {
2388
+ return summarizeObject(toolName, parsed.value, ref, rawBytes);
2389
+ }
2390
+ }
2391
+ const preview = rawContent.slice(0, maxPreviewChars);
2392
+ const truncated = rawContent.length > maxPreviewChars ? "\u2026" : "";
2393
+ return `[${toolName}] ${formatBytes(rawBytes)} offloaded.
2394
+ ` + (preview.length > 0 ? `Preview: ${preview}${truncated}
2395
+ ` : "") + `Use FetchData with ref="${ref}" to read the full content.`;
2396
+ }
2397
+ function summarizeArray(toolName, arr, ref, bytes) {
2398
+ const count = arr.length;
2399
+ const firstHint = arr.length > 0 ? compactPreview(arr[0]) : "";
2400
+ const hintLine = firstHint ? `First item preview: ${firstHint}
2401
+ ` : "";
2402
+ return `[${toolName}] Array of ${count} item${count === 1 ? "" : "s"} (${formatBytes(bytes)}).
2403
+ ` + hintLine + `Use FetchData with ref="${ref}" to read the full array.`;
2404
+ }
2405
+ function summarizeObject(toolName, obj, ref, bytes) {
2406
+ const keys = Object.keys(obj);
2407
+ const shown = keys.slice(0, MAX_TOP_LEVEL_KEYS);
2408
+ const overflow = keys.length > MAX_TOP_LEVEL_KEYS ? ` (+${keys.length - shown.length} more)` : "";
2409
+ const parts = shown.map((k) => `${k}=${compactPreview(obj[k])}`).join(", ");
2410
+ return `[${toolName}] Object (${formatBytes(bytes)}). Keys: ${parts}${overflow}
2411
+ Use FetchData with ref="${ref}" to read the full object.`;
2412
+ }
2413
+ function compactPreview(value) {
2414
+ let str;
2415
+ if (value === null) {
2416
+ str = "null";
2417
+ } else if (typeof value === "string") {
2418
+ str = JSON.stringify(value);
2419
+ } else if (Array.isArray(value)) {
2420
+ str = `[${value.length} item${value.length === 1 ? "" : "s"}]`;
2421
+ } else if (typeof value === "object") {
2422
+ const keys = Object.keys(value);
2423
+ str = `{${keys.slice(0, 3).join(", ")}${keys.length > 3 ? ", \u2026" : ""}}`;
2424
+ } else {
2425
+ str = String(value);
2426
+ }
2427
+ if (str.length > MAX_ITEM_PREVIEW_CHARS) {
2428
+ return str.slice(0, MAX_ITEM_PREVIEW_CHARS) + "\u2026";
2429
+ }
2430
+ return str;
2431
+ }
2432
+ function tryParseJSON(text) {
2433
+ const trimmed = text.replace(/^\uFEFF/, "").trim();
2434
+ if (trimmed.length === 0) return { ok: false };
2435
+ const first = trimmed[0];
2436
+ if (first !== "{" && first !== "[" && first !== '"') return { ok: false };
2437
+ try {
2438
+ return { ok: true, value: JSON.parse(trimmed) };
2439
+ } catch {
2440
+ return { ok: false };
2441
+ }
2442
+ }
2443
+ function formatBytes(bytes) {
2444
+ if (bytes < 1024) return `${bytes} B`;
2445
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
2446
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
2447
+ }
2448
+
2449
+ // src/engine/toolResultOffload.ts
2450
+ async function maybeOffloadToolResult(input) {
2451
+ const {
2452
+ offloadConfig,
2453
+ storage,
2454
+ logPath,
2455
+ toolUseId,
2456
+ toolName,
2457
+ toolInput,
2458
+ rawContent,
2459
+ rawIsError
2460
+ } = input;
2461
+ if (offloadConfig === void 0 || offloadConfig.enabled !== true) {
2462
+ return rawContent;
2463
+ }
2464
+ if (rawIsError) {
2465
+ return rawContent;
2466
+ }
2467
+ if (toolName === "FetchData") {
2468
+ return rawContent;
2469
+ }
2470
+ const rawBytes = byteLength(rawContent);
2471
+ if (rawBytes <= offloadConfig.thresholdBytes) {
2472
+ return rawContent;
2473
+ }
2474
+ const path = `${logPath}/toolResults/${toolUseId}.json`;
2475
+ await storage.writeFile(path, rawContent);
2476
+ const summarizer = offloadConfig.summarizer ?? defaultToolResultSummarizer;
2477
+ const summary = await summarizer({
2478
+ toolName,
2479
+ toolInput,
2480
+ rawContent,
2481
+ rawBytes,
2482
+ ref: toolUseId,
2483
+ maxPreviewChars: offloadConfig.maxPreviewChars
2484
+ });
2485
+ if (!summary.includes(toolUseId)) {
2486
+ return `${summary}
2487
+ [offloaded \u2014 ref=${toolUseId}, use FetchData to read the full content]`;
2488
+ }
2489
+ return summary;
2490
+ }
2491
+ function byteLength(s) {
2492
+ return new TextEncoder().encode(s).byteLength;
2493
+ }
2494
+
2257
2495
  // src/hooks/dispatch.ts
2258
2496
  init_cjs_shims();
2259
2497
  async function dispatchHooks(hooks, event) {
@@ -3006,7 +3244,32 @@ async function agentLoop(options) {
3006
3244
  if (typeof missing === "string") {
3007
3245
  ctx.recordCapabilityMissing(missing);
3008
3246
  }
3009
- await ctx.addToolResult(id, truncateToolResult(result.content), result.isError === true);
3247
+ const call = toolCallsToDispatch.find((c) => c.id === id);
3248
+ let contentForTranscript;
3249
+ if (options.toolResultOffload !== void 0 && options.storage !== void 0) {
3250
+ try {
3251
+ contentForTranscript = await maybeOffloadToolResult({
3252
+ offloadConfig: options.toolResultOffload,
3253
+ storage: options.storage,
3254
+ logPath: options.offloadLogPath ?? transcript.path,
3255
+ toolUseId: id,
3256
+ toolName: call?.name ?? "unknown",
3257
+ toolInput: call?.input,
3258
+ rawContent: result.content,
3259
+ rawIsError: result.isError === true
3260
+ });
3261
+ } catch (err) {
3262
+ const msg = err instanceof Error ? err.message : String(err);
3263
+ contentForTranscript = `[tool-result offload failed: ${msg}] ${result.content.slice(0, 500)}`;
3264
+ }
3265
+ } else {
3266
+ contentForTranscript = result.content;
3267
+ }
3268
+ await ctx.addToolResult(
3269
+ id,
3270
+ truncateToolResult(contentForTranscript),
3271
+ result.isError === true
3272
+ );
3010
3273
  }
3011
3274
  } catch (err) {
3012
3275
  if (err instanceof SubagentPausedError) {
@@ -3140,11 +3403,11 @@ function toAnthropicTool(tool) {
3140
3403
  target: "jsonSchema7",
3141
3404
  $refStrategy: "none"
3142
3405
  });
3143
- const { $schema: _schema, ...inputSchema17 } = schema;
3406
+ const { $schema: _schema, ...inputSchema18 } = schema;
3144
3407
  return {
3145
3408
  name: tool.name,
3146
3409
  description: tool.description,
3147
- input_schema: inputSchema17
3410
+ input_schema: inputSchema18
3148
3411
  };
3149
3412
  }
3150
3413
  function partitionToolCalls(calls, registry) {
@@ -3854,6 +4117,19 @@ async function loadWriterState(storage, logPath) {
3854
4117
  // src/subagent/runner.ts
3855
4118
  async function runAgent(options) {
3856
4119
  const childLogPath = `${options.parentLogPath}/subagents/${options.agentId}`;
4120
+ let restorePrevFetchData = null;
4121
+ if (options.toolResultOffload !== void 0 && options.toolResultOffload.enabled) {
4122
+ const { createFetchDataTool: createFetchDataTool2 } = await Promise.resolve().then(() => (init_fetchData(), fetchData_exports));
4123
+ const existing = options.registry.get("FetchData");
4124
+ options.registry.unregister("FetchData");
4125
+ options.registry.register(
4126
+ createFetchDataTool2({ storage: options.storage, logPath: childLogPath })
4127
+ );
4128
+ restorePrevFetchData = () => {
4129
+ options.registry.unregister("FetchData");
4130
+ if (existing !== void 0) options.registry.register(existing);
4131
+ };
4132
+ }
3857
4133
  const writer = new TranscriptWriter({
3858
4134
  storage: options.storage,
3859
4135
  logPath: childLogPath,
@@ -3894,7 +4170,15 @@ async function runAgent(options) {
3894
4170
  // Propagate parent's gate + storage into the child loop when set.
3895
4171
  // Without `storage`, a gate denial would fail the child instead of
3896
4172
  // pausing it, so both must travel together.
3897
- ...options.gateBeforeTool !== void 0 ? { gateBeforeTool: options.gateBeforeTool, storage: options.storage } : {}
4173
+ ...options.gateBeforeTool !== void 0 ? { gateBeforeTool: options.gateBeforeTool, storage: options.storage } : {},
4174
+ // Plan 021 — the child needs its own storage + offload config
4175
+ // so its own large tool results get offloaded into
4176
+ // `childLogPath/toolResults/...`, not the parent's folder.
4177
+ ...options.toolResultOffload !== void 0 ? {
4178
+ storage: options.storage,
4179
+ toolResultOffload: options.toolResultOffload,
4180
+ offloadLogPath: childLogPath
4181
+ } : {}
3898
4182
  });
3899
4183
  if (result.status === "done") {
3900
4184
  await writer.setStatus("done");
@@ -3950,6 +4234,7 @@ async function runAgent(options) {
3950
4234
  } catch {
3951
4235
  }
3952
4236
  await writer.close();
4237
+ restorePrevFetchData?.();
3953
4238
  }
3954
4239
  }
3955
4240
 
@@ -4022,10 +4307,11 @@ Directive: ${directive}`;
4022
4307
  }
4023
4308
 
4024
4309
  // src/tools/agent.ts
4025
- var inputSchema = import_zod6.z.object({
4026
- description: import_zod6.z.string().min(1),
4027
- subagent_type: import_zod6.z.string().optional(),
4028
- run_in_background: import_zod6.z.boolean().optional()
4310
+ init_contract();
4311
+ var inputSchema2 = import_zod7.z.object({
4312
+ description: import_zod7.z.string().min(1),
4313
+ subagent_type: import_zod7.z.string().optional(),
4314
+ run_in_background: import_zod7.z.boolean().optional()
4029
4315
  });
4030
4316
  function createAgentTool(options) {
4031
4317
  if (options.agents.length === 0) {
@@ -4045,7 +4331,7 @@ If omitted, defaults to "${defaultAgent.name}".`;
4045
4331
  return defineTool({
4046
4332
  name: "Agent",
4047
4333
  description,
4048
- inputSchema,
4334
+ inputSchema: inputSchema2,
4049
4335
  isConcurrencySafe: (input) => {
4050
4336
  const typed = input;
4051
4337
  const typeName = typed?.subagent_type ?? defaultAgent.name;
@@ -4086,7 +4372,8 @@ If omitted, defaults to "${defaultAgent.name}".`;
4086
4372
  idleFlushMs: options.idleFlushMs,
4087
4373
  // Fork: prepend parent messages + forked messages
4088
4374
  prependMessages: [...parentMsgs, ...forkedMsgs],
4089
- ...options.gateBeforeTool !== void 0 ? { gateBeforeTool: options.gateBeforeTool } : {}
4375
+ ...options.gateBeforeTool !== void 0 ? { gateBeforeTool: options.gateBeforeTool } : {},
4376
+ ...options.toolResultOffload !== void 0 ? { toolResultOffload: options.toolResultOffload } : {}
4090
4377
  });
4091
4378
  handlePausedResult(result2, spawn2.agentId, "fork");
4092
4379
  const t2 = result2;
@@ -4135,7 +4422,8 @@ If omitted, defaults to "${defaultAgent.name}".`;
4135
4422
  turnTimeoutMs: options.turnTimeoutMs,
4136
4423
  flushPolicy: options.flushPolicy,
4137
4424
  idleFlushMs: options.idleFlushMs,
4138
- ...options.gateBeforeTool !== void 0 ? { gateBeforeTool: options.gateBeforeTool } : {}
4425
+ ...options.gateBeforeTool !== void 0 ? { gateBeforeTool: options.gateBeforeTool } : {},
4426
+ ...options.toolResultOffload !== void 0 ? { toolResultOffload: options.toolResultOffload } : {}
4139
4427
  };
4140
4428
  const shouldRunAsync = run_in_background === true || options.coordinatorMode === true;
4141
4429
  if (shouldRunAsync) {
@@ -4230,7 +4518,8 @@ function handlePausedResult(result, agentId, subagentType) {
4230
4518
 
4231
4519
  // src/tools/bash.ts
4232
4520
  init_cjs_shims();
4233
- var import_zod7 = require("zod");
4521
+ var import_zod8 = require("zod");
4522
+ init_contract();
4234
4523
  var _spawn = null;
4235
4524
  async function getSpawn() {
4236
4525
  if (_spawn === null) {
@@ -4242,15 +4531,15 @@ async function getSpawn() {
4242
4531
  var MAX_OUTPUT_BYTES = 512 * 1024;
4243
4532
  var SIGKILL_GRACE_MS = 500;
4244
4533
  var BLOCKED_DEVICE_PATHS = /\b(\/dev\/zero|\/dev\/random|\/dev\/urandom|\/proc\/kcore|\/dev\/sda|\/dev\/mem)\b/;
4245
- var inputSchema2 = import_zod7.z.object({
4246
- command: import_zod7.z.string().min(1),
4247
- cwd: import_zod7.z.string().min(1).optional()
4534
+ var inputSchema3 = import_zod8.z.object({
4535
+ command: import_zod8.z.string().min(1),
4536
+ cwd: import_zod8.z.string().min(1).optional()
4248
4537
  });
4249
4538
  function createBashTool() {
4250
4539
  return defineTool({
4251
4540
  name: "Bash",
4252
4541
  description: "Execute a shell command via /bin/sh -c. Returns combined stdout+stderr and the exit code.",
4253
- inputSchema: inputSchema2,
4542
+ inputSchema: inputSchema3,
4254
4543
  requiresNode: true,
4255
4544
  execute: async ({ command, cwd }, ctx) => {
4256
4545
  if (BLOCKED_DEVICE_PATHS.test(command)) {
@@ -4331,16 +4620,17 @@ function createBashTool() {
4331
4620
 
4332
4621
  // src/tools/sendMessage.ts
4333
4622
  init_cjs_shims();
4334
- var import_zod8 = require("zod");
4335
- var inputSchema3 = import_zod8.z.object({
4336
- to: import_zod8.z.string().min(1).describe("Agent name (subagent_type) or agentId to send the message to."),
4337
- message: import_zod8.z.string().min(1).describe("Message content to deliver to the target agent.")
4623
+ var import_zod9 = require("zod");
4624
+ init_contract();
4625
+ var inputSchema4 = import_zod9.z.object({
4626
+ to: import_zod9.z.string().min(1).describe("Agent name (subagent_type) or agentId to send the message to."),
4627
+ message: import_zod9.z.string().min(1).describe("Message content to deliver to the target agent.")
4338
4628
  });
4339
4629
  function createSendMessageTool(options) {
4340
4630
  return defineTool({
4341
4631
  name: "SendMessage",
4342
4632
  description: "Send a text message to a running subagent by name or agentId. The message is queued and delivered at the start of the agent's next turn. Use this to redirect, provide additional context, or coordinate with agents you spawned.",
4343
- inputSchema: inputSchema3,
4633
+ inputSchema: inputSchema4,
4344
4634
  execute: async ({ to, message }) => {
4345
4635
  const { registry } = options;
4346
4636
  let agentId = registry.findByName(to);
@@ -4383,20 +4673,24 @@ function createSendMessageTool(options) {
4383
4673
  });
4384
4674
  }
4385
4675
 
4676
+ // src/engine/engine.ts
4677
+ init_contract();
4678
+
4386
4679
  // src/tools/fileEdit.ts
4387
4680
  init_cjs_shims();
4388
- var import_zod9 = require("zod");
4389
- var inputSchema4 = import_zod9.z.object({
4390
- path: import_zod9.z.string().min(1),
4391
- old_string: import_zod9.z.string().min(1),
4392
- new_string: import_zod9.z.string(),
4393
- replace_all: import_zod9.z.boolean().optional()
4681
+ var import_zod10 = require("zod");
4682
+ init_contract();
4683
+ var inputSchema5 = import_zod10.z.object({
4684
+ path: import_zod10.z.string().min(1),
4685
+ old_string: import_zod10.z.string().min(1),
4686
+ new_string: import_zod10.z.string(),
4687
+ replace_all: import_zod10.z.boolean().optional()
4394
4688
  });
4395
4689
  function createFileEditTool(storage) {
4396
4690
  return defineTool({
4397
4691
  name: "Edit",
4398
4692
  description: "Replace old_string with new_string in a file. By default old_string must be unique; set replace_all to replace every occurrence.",
4399
- inputSchema: inputSchema4,
4693
+ inputSchema: inputSchema5,
4400
4694
  execute: async ({ path, old_string, new_string, replace_all }) => {
4401
4695
  if (old_string === new_string) {
4402
4696
  return {
@@ -4474,13 +4768,14 @@ function normalizeQuotes(s) {
4474
4768
 
4475
4769
  // src/tools/fileRead.ts
4476
4770
  init_cjs_shims();
4477
- var import_zod10 = require("zod");
4478
- var inputSchema5 = import_zod10.z.object({
4479
- path: import_zod10.z.string().min(1),
4480
- offset: import_zod10.z.number().int().positive().optional(),
4481
- limit: import_zod10.z.number().int().positive().optional(),
4771
+ var import_zod11 = require("zod");
4772
+ init_contract();
4773
+ var inputSchema6 = import_zod11.z.object({
4774
+ path: import_zod11.z.string().min(1),
4775
+ offset: import_zod11.z.number().int().positive().optional(),
4776
+ limit: import_zod11.z.number().int().positive().optional(),
4482
4777
  /** PDF page range, e.g. "1-5", "3", "10-20". Max 20 pages per request. */
4483
- pages: import_zod10.z.string().optional()
4778
+ pages: import_zod11.z.string().optional()
4484
4779
  });
4485
4780
  var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp", ".svg"]);
4486
4781
  var PDF_EXTENSION = ".pdf";
@@ -4499,7 +4794,7 @@ function createFileReadTool(storageOrOptions) {
4499
4794
  return defineTool({
4500
4795
  name: "Read",
4501
4796
  description: "Read a file from the workspace. Text files return cat -n style line numbers. PDF files extract text per page (use pages param). Image files return base64 for visual analysis.",
4502
- inputSchema: inputSchema5,
4797
+ inputSchema: inputSchema6,
4503
4798
  isConcurrencySafe: () => true,
4504
4799
  execute: async ({ path, offset, limit, pages }) => {
4505
4800
  const ext = extname(path);
@@ -4664,10 +4959,11 @@ Base64 data is included in the metadata for visual analysis.`,
4664
4959
 
4665
4960
  // src/tools/fileWrite.ts
4666
4961
  init_cjs_shims();
4667
- var import_zod11 = require("zod");
4668
- var inputSchema6 = import_zod11.z.object({
4669
- path: import_zod11.z.string().min(1),
4670
- content: import_zod11.z.string()
4962
+ var import_zod12 = require("zod");
4963
+ init_contract();
4964
+ var inputSchema7 = import_zod12.z.object({
4965
+ path: import_zod12.z.string().min(1),
4966
+ content: import_zod12.z.string()
4671
4967
  });
4672
4968
  function createFileWriteTool(storageOrOptions) {
4673
4969
  const opts = "readFile" in storageOrOptions ? { storage: storageOrOptions } : storageOrOptions;
@@ -4675,7 +4971,7 @@ function createFileWriteTool(storageOrOptions) {
4675
4971
  return defineTool({
4676
4972
  name: "Write",
4677
4973
  description: "Write a file to the workspace. Creates parents and overwrites existing files.",
4678
- inputSchema: inputSchema6,
4974
+ inputSchema: inputSchema7,
4679
4975
  execute: async ({ path, content }) => {
4680
4976
  if (tracker !== void 0) {
4681
4977
  const exists = await storage.exists(path);
@@ -4706,7 +5002,8 @@ function createFileWriteTool(storageOrOptions) {
4706
5002
  // src/tools/glob.ts
4707
5003
  init_cjs_shims();
4708
5004
  var import_picomatch = __toESM(require("picomatch"), 1);
4709
- var import_zod12 = require("zod");
5005
+ var import_zod13 = require("zod");
5006
+ init_contract();
4710
5007
 
4711
5008
  // src/tools/walkAdapter.ts
4712
5009
  init_cjs_shims();
@@ -4743,16 +5040,16 @@ async function* walkAdapter(adapter, startPath, options = {}) {
4743
5040
  }
4744
5041
 
4745
5042
  // src/tools/glob.ts
4746
- var inputSchema7 = import_zod12.z.object({
4747
- pattern: import_zod12.z.string().min(1),
4748
- path: import_zod12.z.string().optional()
5043
+ var inputSchema8 = import_zod13.z.object({
5044
+ pattern: import_zod13.z.string().min(1),
5045
+ path: import_zod13.z.string().optional()
4749
5046
  });
4750
5047
  var MAX_RESULTS = 1e3;
4751
5048
  function createGlobTool(storage) {
4752
5049
  return defineTool({
4753
5050
  name: "Glob",
4754
5051
  description: "Find files by glob pattern. Supports *, **, ?, [abc], {a,b}. Returns paths sorted by mtime descending.",
4755
- inputSchema: inputSchema7,
5052
+ inputSchema: inputSchema8,
4756
5053
  isConcurrencySafe: () => true,
4757
5054
  execute: async ({ pattern, path: searchPath }) => {
4758
5055
  const startPath = searchPath ?? "";
@@ -4798,22 +5095,23 @@ function createGlobTool(storage) {
4798
5095
  // src/tools/grep.ts
4799
5096
  init_cjs_shims();
4800
5097
  var import_picomatch2 = __toESM(require("picomatch"), 1);
4801
- var import_zod13 = require("zod");
4802
- var inputSchema8 = import_zod13.z.object({
4803
- pattern: import_zod13.z.string().min(1),
4804
- path: import_zod13.z.string().optional(),
4805
- glob: import_zod13.z.string().optional(),
4806
- type: import_zod13.z.string().optional(),
4807
- output_mode: import_zod13.z.enum(["content", "files_with_matches", "count"]).optional(),
4808
- "-i": import_zod13.z.boolean().optional(),
4809
- "-n": import_zod13.z.boolean().optional(),
4810
- "-A": import_zod13.z.number().int().nonnegative().optional(),
4811
- "-B": import_zod13.z.number().int().nonnegative().optional(),
4812
- "-C": import_zod13.z.number().int().nonnegative().optional(),
4813
- context: import_zod13.z.number().int().nonnegative().optional(),
4814
- multiline: import_zod13.z.boolean().optional(),
4815
- head_limit: import_zod13.z.number().int().nonnegative().optional(),
4816
- offset: import_zod13.z.number().int().nonnegative().optional()
5098
+ var import_zod14 = require("zod");
5099
+ init_contract();
5100
+ var inputSchema9 = import_zod14.z.object({
5101
+ pattern: import_zod14.z.string().min(1),
5102
+ path: import_zod14.z.string().optional(),
5103
+ glob: import_zod14.z.string().optional(),
5104
+ type: import_zod14.z.string().optional(),
5105
+ output_mode: import_zod14.z.enum(["content", "files_with_matches", "count"]).optional(),
5106
+ "-i": import_zod14.z.boolean().optional(),
5107
+ "-n": import_zod14.z.boolean().optional(),
5108
+ "-A": import_zod14.z.number().int().nonnegative().optional(),
5109
+ "-B": import_zod14.z.number().int().nonnegative().optional(),
5110
+ "-C": import_zod14.z.number().int().nonnegative().optional(),
5111
+ context: import_zod14.z.number().int().nonnegative().optional(),
5112
+ multiline: import_zod14.z.boolean().optional(),
5113
+ head_limit: import_zod14.z.number().int().nonnegative().optional(),
5114
+ offset: import_zod14.z.number().int().nonnegative().optional()
4817
5115
  });
4818
5116
  var MAX_FILES_SCANNED = 5e3;
4819
5117
  var MAX_MATCHES_PER_FILE = 100;
@@ -4859,7 +5157,7 @@ function createGrepTool(storage) {
4859
5157
  return defineTool({
4860
5158
  name: "Grep",
4861
5159
  description: "Search for a regex pattern across files. Supports ripgrep when available (context lines, multiline, type filters, pagination). Falls back to JS RegExp scanner.",
4862
- inputSchema: inputSchema8,
5160
+ inputSchema: inputSchema9,
4863
5161
  isConcurrencySafe: () => true,
4864
5162
  execute: async (input, ctx) => {
4865
5163
  if (rgAvailable && input.path !== void 0) {
@@ -5037,10 +5335,11 @@ function formatJsResults(results, mode, limit) {
5037
5335
 
5038
5336
  // src/tools/webFetch.ts
5039
5337
  init_cjs_shims();
5040
- var import_zod14 = require("zod");
5041
- var inputSchema9 = import_zod14.z.object({
5042
- url: import_zod14.z.string().url(),
5043
- prompt: import_zod14.z.string().optional()
5338
+ var import_zod15 = require("zod");
5339
+ init_contract();
5340
+ var inputSchema10 = import_zod15.z.object({
5341
+ url: import_zod15.z.string().url(),
5342
+ prompt: import_zod15.z.string().optional()
5044
5343
  });
5045
5344
  var MAX_OUTPUT_BYTES2 = 256 * 1024;
5046
5345
  function createWebFetchTool(options = {}) {
@@ -5048,7 +5347,7 @@ function createWebFetchTool(options = {}) {
5048
5347
  return defineTool({
5049
5348
  name: "WebFetch",
5050
5349
  description: "Fetch a URL and return its content as plain text. HTML is stripped to its readable text.",
5051
- inputSchema: inputSchema9,
5350
+ inputSchema: inputSchema10,
5052
5351
  isConcurrencySafe: () => true,
5053
5352
  execute: async ({ url }, ctx) => {
5054
5353
  let response;
@@ -5169,16 +5468,17 @@ function normalizePath(p) {
5169
5468
 
5170
5469
  // src/tools/webSearch.ts
5171
5470
  init_cjs_shims();
5172
- var import_zod15 = require("zod");
5173
- var inputSchema10 = import_zod15.z.object({
5174
- query: import_zod15.z.string().min(2),
5175
- max_results: import_zod15.z.number().int().positive().optional()
5471
+ var import_zod16 = require("zod");
5472
+ init_contract();
5473
+ var inputSchema11 = import_zod16.z.object({
5474
+ query: import_zod16.z.string().min(2),
5475
+ max_results: import_zod16.z.number().int().positive().optional()
5176
5476
  });
5177
5477
  function createWebSearchTool() {
5178
5478
  return defineTool({
5179
5479
  name: "WebSearch",
5180
5480
  description: "Search the web for information. Returns search result snippets. Use when you need current information not available in local files.",
5181
- inputSchema: inputSchema10,
5481
+ inputSchema: inputSchema11,
5182
5482
  isConcurrencySafe: () => true,
5183
5483
  execute: async ({ query }) => {
5184
5484
  const encoded = encodeURIComponent(query);
@@ -5229,16 +5529,17 @@ function htmlToText2(html) {
5229
5529
 
5230
5530
  // src/tools/sleep.ts
5231
5531
  init_cjs_shims();
5232
- var import_zod16 = require("zod");
5233
- var inputSchema11 = import_zod16.z.object({
5234
- durationMs: import_zod16.z.number().int().nonnegative().max(3e5),
5235
- reason: import_zod16.z.string().optional()
5532
+ var import_zod17 = require("zod");
5533
+ init_contract();
5534
+ var inputSchema12 = import_zod17.z.object({
5535
+ durationMs: import_zod17.z.number().int().nonnegative().max(3e5),
5536
+ reason: import_zod17.z.string().optional()
5236
5537
  });
5237
5538
  function createSleepTool() {
5238
5539
  return defineTool({
5239
5540
  name: "Sleep",
5240
5541
  description: "Pause execution for the given number of milliseconds (max 300000 = 5 minutes). Use when you need to wait for an external process or rate limit.",
5241
- inputSchema: inputSchema11,
5542
+ inputSchema: inputSchema12,
5242
5543
  isConcurrencySafe: () => true,
5243
5544
  execute: async ({ durationMs, reason }, ctx) => {
5244
5545
  if (durationMs === 0) {
@@ -5272,16 +5573,17 @@ function createSleepTool() {
5272
5573
 
5273
5574
  // src/tools/toolSearch.ts
5274
5575
  init_cjs_shims();
5275
- var import_zod17 = require("zod");
5276
- var inputSchema12 = import_zod17.z.object({
5277
- query: import_zod17.z.string().min(1),
5278
- max_results: import_zod17.z.number().int().positive().optional()
5576
+ var import_zod18 = require("zod");
5577
+ init_contract();
5578
+ var inputSchema13 = import_zod18.z.object({
5579
+ query: import_zod18.z.string().min(1),
5580
+ max_results: import_zod18.z.number().int().positive().optional()
5279
5581
  });
5280
5582
  function createToolSearchTool(registry) {
5281
5583
  return defineTool({
5282
5584
  name: "ToolSearch",
5283
5585
  description: "Search the available tools by keyword. Returns matching tool names and descriptions. Use when you want to discover what tools are available for a task.",
5284
- inputSchema: inputSchema12,
5586
+ inputSchema: inputSchema13,
5285
5587
  isConcurrencySafe: () => true,
5286
5588
  execute: async ({ query, max_results }) => {
5287
5589
  const limit = max_results ?? 10;
@@ -5318,17 +5620,18 @@ ${lines.join("\n")}`,
5318
5620
 
5319
5621
  // src/tools/memorize.ts
5320
5622
  init_cjs_shims();
5321
- var import_zod18 = require("zod");
5322
- var inputSchema13 = import_zod18.z.object({
5323
- text: import_zod18.z.string().min(1),
5324
- kind: import_zod18.z.enum(["rule", "lesson"]).default("lesson"),
5325
- topic: import_zod18.z.string().optional()
5623
+ var import_zod19 = require("zod");
5624
+ init_contract();
5625
+ var inputSchema14 = import_zod19.z.object({
5626
+ text: import_zod19.z.string().min(1),
5627
+ kind: import_zod19.z.enum(["rule", "lesson"]).default("lesson"),
5628
+ topic: import_zod19.z.string().optional()
5326
5629
  });
5327
5630
  function createMemorizeTool(memory) {
5328
5631
  return defineTool({
5329
5632
  name: "Memorize",
5330
5633
  description: 'Save a fact, rule, or lesson to persistent memory. Memories survive across runs and are included in the system prompt of future runs. Use "rule" for behavioral constraints (always/never do X). Use "lesson" for learnings and observations.',
5331
- inputSchema: inputSchema13,
5634
+ inputSchema: inputSchema14,
5332
5635
  execute: async ({ text, kind, topic }) => {
5333
5636
  if (memory.mode === "off" || memory.mode === "read-only") {
5334
5637
  return {
@@ -5354,17 +5657,18 @@ function createMemorizeTool(memory) {
5354
5657
 
5355
5658
  // src/tools/recall.ts
5356
5659
  init_cjs_shims();
5357
- var import_zod19 = require("zod");
5358
- var inputSchema14 = import_zod19.z.object({
5359
- query: import_zod19.z.string().min(1),
5360
- scope: import_zod19.z.enum(["identity", "rules", "lessons", "all"]).default("all"),
5361
- topic: import_zod19.z.string().optional()
5660
+ var import_zod20 = require("zod");
5661
+ init_contract();
5662
+ var inputSchema15 = import_zod20.z.object({
5663
+ query: import_zod20.z.string().min(1),
5664
+ scope: import_zod20.z.enum(["identity", "rules", "lessons", "all"]).default("all"),
5665
+ topic: import_zod20.z.string().optional()
5362
5666
  });
5363
5667
  function createRecallTool(memory) {
5364
5668
  return defineTool({
5365
5669
  name: "Recall",
5366
5670
  description: "Search persistent memory for previously saved facts, rules, and lessons. Use when you need to recall information from prior runs or check what rules/lessons are stored.",
5367
- inputSchema: inputSchema14,
5671
+ inputSchema: inputSchema15,
5368
5672
  isConcurrencySafe: () => true,
5369
5673
  execute: async ({ query, scope, topic }) => {
5370
5674
  if (memory.mode === "off") {
@@ -5413,19 +5717,20 @@ ${content}`,
5413
5717
 
5414
5718
  // src/tools/notebookEdit.ts
5415
5719
  init_cjs_shims();
5416
- var import_zod20 = require("zod");
5417
- var inputSchema15 = import_zod20.z.object({
5418
- notebook_path: import_zod20.z.string().min(1),
5419
- edit_mode: import_zod20.z.enum(["replace", "insert", "delete"]).default("replace"),
5420
- cell_index: import_zod20.z.number().int().nonnegative(),
5421
- new_source: import_zod20.z.string().optional(),
5422
- cell_type: import_zod20.z.enum(["code", "markdown"]).optional()
5720
+ var import_zod21 = require("zod");
5721
+ init_contract();
5722
+ var inputSchema16 = import_zod21.z.object({
5723
+ notebook_path: import_zod21.z.string().min(1),
5724
+ edit_mode: import_zod21.z.enum(["replace", "insert", "delete"]).default("replace"),
5725
+ cell_index: import_zod21.z.number().int().nonnegative(),
5726
+ new_source: import_zod21.z.string().optional(),
5727
+ cell_type: import_zod21.z.enum(["code", "markdown"]).optional()
5423
5728
  });
5424
5729
  function createNotebookEditTool(storage) {
5425
5730
  return defineTool({
5426
5731
  name: "NotebookEdit",
5427
5732
  description: "Edit a Jupyter notebook (.ipynb) by inserting, replacing, or deleting cells. Specify the cell_index (0-based) and the operation.",
5428
- inputSchema: inputSchema15,
5733
+ inputSchema: inputSchema16,
5429
5734
  execute: async ({
5430
5735
  notebook_path,
5431
5736
  edit_mode,
@@ -5574,12 +5879,13 @@ var TaskStore = class {
5574
5879
 
5575
5880
  // src/tools/tasks/tools.ts
5576
5881
  init_cjs_shims();
5577
- var import_zod21 = require("zod");
5578
- var TaskStatusEnum = import_zod21.z.enum(["pending", "in_progress", "completed", "deleted"]);
5579
- var createSchema = import_zod21.z.object({
5580
- subject: import_zod21.z.string().min(1),
5581
- description: import_zod21.z.string().default(""),
5582
- metadata: import_zod21.z.record(import_zod21.z.unknown()).optional()
5882
+ var import_zod22 = require("zod");
5883
+ init_contract();
5884
+ var TaskStatusEnum = import_zod22.z.enum(["pending", "in_progress", "completed", "deleted"]);
5885
+ var createSchema = import_zod22.z.object({
5886
+ subject: import_zod22.z.string().min(1),
5887
+ description: import_zod22.z.string().default(""),
5888
+ metadata: import_zod22.z.record(import_zod22.z.unknown()).optional()
5583
5889
  });
5584
5890
  function createTaskCreateTool(store) {
5585
5891
  return defineTool({
@@ -5595,8 +5901,8 @@ function createTaskCreateTool(store) {
5595
5901
  }
5596
5902
  });
5597
5903
  }
5598
- var getSchema = import_zod21.z.object({
5599
- taskId: import_zod21.z.string().min(1)
5904
+ var getSchema = import_zod22.z.object({
5905
+ taskId: import_zod22.z.string().min(1)
5600
5906
  });
5601
5907
  function createTaskGetTool(store) {
5602
5908
  return defineTool({
@@ -5617,7 +5923,7 @@ ${task.description}`,
5617
5923
  }
5618
5924
  });
5619
5925
  }
5620
- var listSchema = import_zod21.z.object({
5926
+ var listSchema = import_zod22.z.object({
5621
5927
  status: TaskStatusEnum.optional()
5622
5928
  });
5623
5929
  function createTaskListTool(store) {
@@ -5643,12 +5949,12 @@ ${lines.join("\n")}`,
5643
5949
  }
5644
5950
  });
5645
5951
  }
5646
- var updateSchema = import_zod21.z.object({
5647
- taskId: import_zod21.z.string().min(1),
5648
- subject: import_zod21.z.string().min(1).optional(),
5952
+ var updateSchema = import_zod22.z.object({
5953
+ taskId: import_zod22.z.string().min(1),
5954
+ subject: import_zod22.z.string().min(1).optional(),
5649
5955
  status: TaskStatusEnum.optional(),
5650
- description: import_zod21.z.string().optional(),
5651
- metadata: import_zod21.z.record(import_zod21.z.unknown()).optional()
5956
+ description: import_zod22.z.string().optional(),
5957
+ metadata: import_zod22.z.record(import_zod22.z.unknown()).optional()
5652
5958
  });
5653
5959
  function createTaskUpdateTool(store) {
5654
5960
  return defineTool({
@@ -6385,8 +6691,8 @@ function normalizeToolList(response, serverName) {
6385
6691
  const name = typeof obj.name === "string" ? obj.name : null;
6386
6692
  if (name === null) continue;
6387
6693
  const description = typeof obj.description === "string" ? obj.description : "";
6388
- const inputSchema17 = obj.inputSchema !== null && typeof obj.inputSchema === "object" && !Array.isArray(obj.inputSchema) ? obj.inputSchema : { type: "object", properties: {} };
6389
- out.push({ name, description, inputSchema: inputSchema17 });
6694
+ const inputSchema18 = obj.inputSchema !== null && typeof obj.inputSchema === "object" && !Array.isArray(obj.inputSchema) ? obj.inputSchema : { type: "object", properties: {} };
6695
+ out.push({ name, description, inputSchema: inputSchema18 });
6390
6696
  }
6391
6697
  return out;
6392
6698
  }
@@ -6495,7 +6801,8 @@ function wrapFetchWithHeadersProvider(baseFetch, headersProvider, staticHeaders)
6495
6801
 
6496
6802
  // src/mcp/toolAdapter.ts
6497
6803
  init_cjs_shims();
6498
- var import_zod22 = require("zod");
6804
+ var import_zod23 = require("zod");
6805
+ init_contract();
6499
6806
  function mcpToolName(serverName, toolName) {
6500
6807
  return `mcp__${serverName}__${toolName}`;
6501
6808
  }
@@ -6504,7 +6811,7 @@ function adaptMcpTool(client, serverName, def) {
6504
6811
  return defineTool({
6505
6812
  name: registeredName,
6506
6813
  description: def.description.length > 0 ? def.description : `MCP tool ${serverName}/${def.name}`,
6507
- inputSchema: import_zod22.z.unknown(),
6814
+ inputSchema: import_zod23.z.unknown(),
6508
6815
  // Pass the MCP server's JSON Schema through to Anthropic verbatim,
6509
6816
  // bypassing Zod-to-JSON-Schema conversion (which would produce `{}`
6510
6817
  // for our `z.unknown()` Zod schema).
@@ -7165,7 +7472,7 @@ ${entries.map((e) => `- ${e}`).join("\n")}
7165
7472
  // src/memory/memoryConfig.ts
7166
7473
  function createSmartMemory(options) {
7167
7474
  const { storage, config } = options;
7168
- const adapter = config.scope === "global" ? storage.global : storage.workspace;
7475
+ const adapter = storage.workspace;
7169
7476
  const hippocampus = new Hippocampus(adapter, "smart-memory");
7170
7477
  const writesEnabled = config.mode === "read-write";
7171
7478
  const readsEnabled = config.mode !== "off";
@@ -7536,18 +7843,7 @@ ${lessons}`);
7536
7843
  }
7537
7844
  async function collectSkills(storage, skillsDir) {
7538
7845
  const workspace = await loadSkills(storage.workspace, skillsDir);
7539
- const global = await loadSkills(storage.global, skillsDir);
7540
- const seen = /* @__PURE__ */ new Set();
7541
- const out = [];
7542
- for (const s of workspace) {
7543
- seen.add(s.name);
7544
- out.push({ name: s.name, description: s.description });
7545
- }
7546
- for (const s of global) {
7547
- if (seen.has(s.name)) continue;
7548
- out.push({ name: s.name, description: s.description });
7549
- }
7550
- return out;
7846
+ return workspace.map((s) => ({ name: s.name, description: s.description }));
7551
7847
  }
7552
7848
 
7553
7849
  // src/engine/jsonOutput.ts
@@ -7573,7 +7869,7 @@ function buildSchemaPrompt(schema) {
7573
7869
  }
7574
7870
  return lines.join("\n");
7575
7871
  }
7576
- function tryParseJSON(text) {
7872
+ function tryParseJSON2(text) {
7577
7873
  const trimmed = text.trim();
7578
7874
  try {
7579
7875
  return { ok: true, value: JSON.parse(trimmed) };
@@ -7613,17 +7909,18 @@ ${issues.join("\n")}` };
7613
7909
 
7614
7910
  // src/skills/skillPage.ts
7615
7911
  init_cjs_shims();
7616
- var import_zod23 = require("zod");
7912
+ var import_zod24 = require("zod");
7913
+ init_contract();
7617
7914
  var SAFE_NAME3 = /^[a-zA-Z0-9_-]+$/;
7618
- var inputSchema16 = import_zod23.z.object({
7619
- skill: import_zod23.z.string().min(1),
7620
- page: import_zod23.z.string().min(1).optional()
7915
+ var inputSchema17 = import_zod24.z.object({
7916
+ skill: import_zod24.z.string().min(1),
7917
+ page: import_zod24.z.string().min(1).optional()
7621
7918
  });
7622
7919
  function createSkillPageTool(options) {
7623
7920
  return defineTool({
7624
7921
  name: "SkillPage",
7625
7922
  description: "Load a skill. Pass `skill` alone to read the main SKILL.md; pass both `skill` and `page` to read a supplemental page. Skill names appear in the system prompt skill index.",
7626
- inputSchema: inputSchema16,
7923
+ inputSchema: inputSchema17,
7627
7924
  execute: async ({ skill, page }) => {
7628
7925
  if (!SAFE_NAME3.test(skill)) {
7629
7926
  return {
@@ -7675,7 +7972,8 @@ The skill "${skill}" has no pages.`;
7675
7972
 
7676
7973
  // src/tools/apiCall.ts
7677
7974
  init_cjs_shims();
7678
- var import_zod24 = require("zod");
7975
+ var import_zod25 = require("zod");
7976
+ init_contract();
7679
7977
  var ALL_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
7680
7978
  var DEFAULT_MAX_BODY_BYTES = 256 * 1024;
7681
7979
  var DEFAULT_MAX_RESPONSE_BYTES = 100 * 1024;
@@ -7700,19 +7998,19 @@ function createApiCallTool(opts) {
7700
7998
  }
7701
7999
  const fetchFn = opts.fetch ?? globalThis.fetch.bind(globalThis);
7702
8000
  const maxResponseBytes = opts.maxResponseBytes ?? DEFAULT_MAX_RESPONSE_BYTES;
7703
- const inputSchema17 = import_zod24.z.object({
7704
- service: import_zod24.z.enum(serviceNames),
7705
- method: import_zod24.z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]),
7706
- path: import_zod24.z.string().regex(/^\//, "path must start with /"),
7707
- query: import_zod24.z.record(import_zod24.z.string(), import_zod24.z.string()).optional(),
7708
- body: import_zod24.z.unknown().optional(),
7709
- headers: import_zod24.z.record(import_zod24.z.string(), import_zod24.z.string()).optional()
8001
+ const inputSchema18 = import_zod25.z.object({
8002
+ service: import_zod25.z.enum(serviceNames),
8003
+ method: import_zod25.z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]),
8004
+ path: import_zod25.z.string().regex(/^\//, "path must start with /"),
8005
+ query: import_zod25.z.record(import_zod25.z.string(), import_zod25.z.string()).optional(),
8006
+ body: import_zod25.z.unknown().optional(),
8007
+ headers: import_zod25.z.record(import_zod25.z.string(), import_zod25.z.string()).optional()
7710
8008
  });
7711
8009
  const description = opts.toolDescription ?? `Call a configured external API. Services: ${serviceNames.join(", ")}. Auth is injected automatically \u2014 do not pass credentials via headers.`;
7712
8010
  return defineTool({
7713
8011
  name: opts.toolName ?? "ApiCall",
7714
8012
  description,
7715
- inputSchema: inputSchema17,
8013
+ inputSchema: inputSchema18,
7716
8014
  execute: async (input) => {
7717
8015
  const svc = services.get(input.service);
7718
8016
  if (!svc) {
@@ -7731,7 +8029,7 @@ function createApiCallTool(opts) {
7731
8029
  if (input.body !== void 0) {
7732
8030
  bodyText = JSON.stringify(input.body);
7733
8031
  const cap = svc.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES;
7734
- if (byteLength(bodyText) > cap) {
8032
+ if (byteLength2(bodyText) > cap) {
7735
8033
  return errResult(`ERR_API_BODY_TOO_LARGE: exceeds ${cap} bytes`);
7736
8034
  }
7737
8035
  }
@@ -7805,7 +8103,7 @@ function pathAllowed(path, allowed) {
7805
8103
  }
7806
8104
  return false;
7807
8105
  }
7808
- function byteLength(s) {
8106
+ function byteLength2(s) {
7809
8107
  return new TextEncoder().encode(s).byteLength;
7810
8108
  }
7811
8109
  function buildUrl(baseUrl, path, query) {
@@ -7870,6 +8168,9 @@ async function invokeHook(hook, event) {
7870
8168
  }
7871
8169
  }
7872
8170
 
8171
+ // src/engine/engine.ts
8172
+ init_fetchData();
8173
+
7873
8174
  // src/skills/storageSkillSource.ts
7874
8175
  init_cjs_shims();
7875
8176
  var SAFE_NAME4 = /^[a-zA-Z0-9_-]+$/;
@@ -7881,14 +8182,8 @@ var StorageSkillSource = class {
7881
8182
  this.baseDir = options.baseDir ?? "skills";
7882
8183
  }
7883
8184
  async list() {
7884
- const [workspace, global] = await Promise.all([
7885
- loadSkills(this.storage.workspace, this.baseDir),
7886
- loadSkills(this.storage.global, this.baseDir)
7887
- ]);
7888
- const byName = /* @__PURE__ */ new Map();
7889
- for (const s of global) byName.set(s.name, s);
7890
- for (const s of workspace) byName.set(s.name, s);
7891
- return Array.from(byName.values()).map((s) => ({
8185
+ const loaded = await loadSkills(this.storage.workspace, this.baseDir);
8186
+ return loaded.map((s) => ({
7892
8187
  name: s.name,
7893
8188
  description: s.description,
7894
8189
  hasPages: s.hasPages
@@ -7896,8 +8191,7 @@ var StorageSkillSource = class {
7896
8191
  }
7897
8192
  async getSkillFile(skill) {
7898
8193
  if (!SAFE_NAME4.test(skill)) return null;
7899
- const found = await this.findFile(skill, "SKILL.md");
7900
- return found;
8194
+ return this.findFile(skill, "SKILL.md");
7901
8195
  }
7902
8196
  async getPage(skill, page) {
7903
8197
  if (!SAFE_NAME4.test(skill)) return null;
@@ -7906,9 +8200,7 @@ var StorageSkillSource = class {
7906
8200
  }
7907
8201
  async listPages(skill) {
7908
8202
  if (!SAFE_NAME4.test(skill)) return [];
7909
- const wsPages = await this.listPagesIn(this.storage.workspace, skill);
7910
- if (wsPages.length > 0) return wsPages;
7911
- return this.listPagesIn(this.storage.global, skill);
8203
+ return this.listPagesIn(this.storage.workspace, skill);
7912
8204
  }
7913
8205
  async listPagesIn(adapter, skill) {
7914
8206
  const pagesDir = `${this.baseDir}/${skill}/pages`;
@@ -7921,9 +8213,7 @@ var StorageSkillSource = class {
7921
8213
  }
7922
8214
  async findFile(skill, relative) {
7923
8215
  const path = `${this.baseDir}/${skill}/${relative}`;
7924
- const fromWorkspace = await this.readIfExists(this.storage.workspace, path);
7925
- if (fromWorkspace !== null) return fromWorkspace;
7926
- return this.readIfExists(this.storage.global, path);
8216
+ return this.readIfExists(this.storage.workspace, path);
7927
8217
  }
7928
8218
  async readIfExists(adapter, path) {
7929
8219
  try {
@@ -8506,7 +8796,6 @@ async function createEngineStorage(config) {
8506
8796
  }
8507
8797
  async function createLocalStorage(config) {
8508
8798
  const path = await import("path");
8509
- const globalRoot = path.join(config.rootPath, ENGINE_DATA_FOLDER);
8510
8799
  const workspaceRoot = path.join(
8511
8800
  config.rootPath,
8512
8801
  WORKSPACES_FOLDER,
@@ -8514,7 +8803,6 @@ async function createLocalStorage(config) {
8514
8803
  ENGINE_DATA_FOLDER
8515
8804
  );
8516
8805
  return {
8517
- global: new LocalStorageAdapter(globalRoot),
8518
8806
  workspace: new LocalStorageAdapter(workspaceRoot)
8519
8807
  };
8520
8808
  }
@@ -8523,10 +8811,8 @@ function createR2Storage(config) {
8523
8811
  throw new StorageError('storage.r2 is required when storage.provider === "r2"');
8524
8812
  }
8525
8813
  const rootPrefix = config.rootPath.replace(/^\/+|\/+$/g, "");
8526
- const globalPrefix = `${rootPrefix}/${ENGINE_DATA_FOLDER}`;
8527
8814
  const workspacePrefix = `${rootPrefix}/${WORKSPACES_FOLDER}/${config.workspaceId}/${ENGINE_DATA_FOLDER}`;
8528
8815
  return {
8529
- global: new R2StorageAdapter(config.r2, globalPrefix),
8530
8816
  workspace: new R2StorageAdapter(config.r2, workspacePrefix)
8531
8817
  };
8532
8818
  }
@@ -8535,10 +8821,8 @@ function createR2BindingStorage(config) {
8535
8821
  throw new StorageError('storage.r2Binding is required when storage.provider === "r2-binding"');
8536
8822
  }
8537
8823
  const rootPrefix = config.rootPath.replace(/^\/+|\/+$/g, "");
8538
- const globalPrefix = `${rootPrefix}/${ENGINE_DATA_FOLDER}`;
8539
8824
  const workspacePrefix = `${rootPrefix}/${WORKSPACES_FOLDER}/${config.workspaceId}/${ENGINE_DATA_FOLDER}`;
8540
8825
  return {
8541
- global: new R2BindingStorageAdapter(config.r2Binding, globalPrefix),
8542
8826
  workspace: new R2BindingStorageAdapter(config.r2Binding, workspacePrefix)
8543
8827
  };
8544
8828
  }
@@ -9044,6 +9328,7 @@ var Engine = class {
9044
9328
  const skillSource = this.resolveSkillSource(options.skills, storage);
9045
9329
  const skillList = skillSource !== void 0 ? await skillSource.list() : void 0;
9046
9330
  const apiConfig = this.resolveApiConfig(options.api);
9331
+ const offloadConfig = this.resolveOffloadConfig(options.compaction?.toolResultOffload);
9047
9332
  let systemPrompt = await buildSystemPrompt({
9048
9333
  ...coordinatorBase !== void 0 ? { base: coordinatorBase } : {},
9049
9334
  memory,
@@ -9076,6 +9361,7 @@ var Engine = class {
9076
9361
  ...this.config.hooks.propagateGateToSubagents === true && gate !== void 0 ? { subagentGate: gate } : {},
9077
9362
  ...skillSource !== void 0 ? { skillSource } : {},
9078
9363
  ...apiConfig !== void 0 ? { apiConfig } : {},
9364
+ ...offloadConfig !== void 0 ? { toolResultOffload: offloadConfig } : {},
9079
9365
  ...this.internals.fetch !== void 0 ? { fetch: this.internals.fetch } : {}
9080
9366
  });
9081
9367
  const writer = new TranscriptWriter({
@@ -9131,7 +9417,8 @@ var Engine = class {
9131
9417
  ...options.tokenBudget !== void 0 ? { tokenBudget: options.tokenBudget } : {},
9132
9418
  ...runTimeout.signal !== void 0 ? { runSignal: runTimeout.signal, runTimeoutMs: this.config.execution.runTimeoutMs } : {},
9133
9419
  ...gate !== void 0 ? { gateBeforeTool: gate } : {},
9134
- ..._internal?.handoffToRunner === true ? { handoffToRunner: true } : {}
9420
+ ..._internal?.handoffToRunner === true ? { handoffToRunner: true } : {},
9421
+ ...offloadConfig !== void 0 ? { toolResultOffload: offloadConfig } : {}
9135
9422
  });
9136
9423
  const result = await this.finalizeResult(loopResult, writer, logPath, {
9137
9424
  ...options.outputFormat !== void 0 ? { outputFormat: options.outputFormat } : {},
@@ -9186,6 +9473,7 @@ var Engine = class {
9186
9473
  const skillSource = this.resolveSkillSource(options.skills, storage);
9187
9474
  const skillList = skillSource !== void 0 ? await skillSource.list() : void 0;
9188
9475
  const apiConfig = this.resolveApiConfig(options.api);
9476
+ const offloadConfig = this.resolveOffloadConfig(options.compaction?.toolResultOffload);
9189
9477
  let systemPrompt = await buildSystemPrompt({
9190
9478
  ...coordinatorBase !== void 0 ? { base: coordinatorBase } : {},
9191
9479
  memory,
@@ -9218,6 +9506,7 @@ var Engine = class {
9218
9506
  ...this.config.hooks.propagateGateToSubagents === true && gate !== void 0 ? { subagentGate: gate } : {},
9219
9507
  ...skillSource !== void 0 ? { skillSource } : {},
9220
9508
  ...apiConfig !== void 0 ? { apiConfig } : {},
9509
+ ...offloadConfig !== void 0 ? { toolResultOffload: offloadConfig } : {},
9221
9510
  ...this.internals.fetch !== void 0 ? { fetch: this.internals.fetch } : {}
9222
9511
  });
9223
9512
  const priorState = await loadWriterState(storage.workspace, logPath);
@@ -9308,7 +9597,8 @@ ${inputJson}
9308
9597
  onProgress: this.buildHeartbeat(storage, snapshot.runId, snapshot.nodeId),
9309
9598
  ...runTimeout.signal !== void 0 ? { runSignal: runTimeout.signal, runTimeoutMs: this.config.execution.runTimeoutMs } : {},
9310
9599
  ...gate !== void 0 ? { gateBeforeTool: gate } : {},
9311
- ..._internal?.handoffToRunner === true ? { handoffToRunner: true } : {}
9600
+ ..._internal?.handoffToRunner === true ? { handoffToRunner: true } : {},
9601
+ ...offloadConfig !== void 0 ? { toolResultOffload: offloadConfig } : {}
9312
9602
  });
9313
9603
  const result = await this.finalizeResult(loopResult, writer, logPath, {
9314
9604
  ...options.outputFormat !== void 0 ? { outputFormat: options.outputFormat } : {},
@@ -9854,6 +10144,11 @@ ${inputJson}
9854
10144
  names.add("ApiCall");
9855
10145
  }
9856
10146
  }
10147
+ if (this.config.compaction.toolResultOffload?.enabled === true) {
10148
+ if (!disabled.has("FetchData") && (wantAll || enabled.has("FetchData"))) {
10149
+ names.add("FetchData");
10150
+ }
10151
+ }
9857
10152
  for (const tool of this.config.tools.custom) {
9858
10153
  names.add(tool.name);
9859
10154
  }
@@ -9955,7 +10250,7 @@ ${inputJson}
9955
10250
  await writer.setStatus("done");
9956
10251
  let data;
9957
10252
  if (jsonOptions?.outputFormat === "json") {
9958
- const parsed = tryParseJSON(loopResult.output);
10253
+ const parsed = tryParseJSON2(loopResult.output);
9959
10254
  if (parsed.ok) {
9960
10255
  if (jsonOptions.outputSchema) {
9961
10256
  const validated = validateOutput(parsed.value, jsonOptions.outputSchema);
@@ -10020,6 +10315,31 @@ ${inputJson}
10020
10315
  * tool isn't registered at all. Env + resolveAuth + hooks flow
10021
10316
  * through untouched — they never hit the Zod schema.
10022
10317
  */
10318
+ /**
10319
+ * Plan 021 — resolve the effective tool-result offload config.
10320
+ *
10321
+ * Precedence (each field independently):
10322
+ * RunOptions.compaction.toolResultOffload.X >
10323
+ * config.compaction.toolResultOffload.X
10324
+ *
10325
+ * When neither side enables offload, returns undefined and no
10326
+ * `FetchData` tool is registered.
10327
+ */
10328
+ resolveOffloadConfig(override) {
10329
+ const base = this.config.compaction.toolResultOffload;
10330
+ if (override === void 0 && base === void 0) return void 0;
10331
+ const enabled = override?.enabled ?? base?.enabled ?? false;
10332
+ if (!enabled) return void 0;
10333
+ const thresholdBytes = override?.thresholdBytes ?? base?.thresholdBytes ?? 2048;
10334
+ const maxPreviewChars = override?.maxPreviewChars ?? base?.maxPreviewChars ?? 500;
10335
+ const summarizer = override?.summarizer ?? base?.summarizer;
10336
+ return {
10337
+ enabled: true,
10338
+ thresholdBytes,
10339
+ maxPreviewChars,
10340
+ ...summarizer !== void 0 ? { summarizer } : {}
10341
+ };
10342
+ }
10023
10343
  resolveApiConfig(override) {
10024
10344
  const base = this.config.api;
10025
10345
  if (override === void 0 && base === void 0) return void 0;
@@ -10194,6 +10514,15 @@ function buildToolRegistry(options) {
10194
10514
  childRegistry.register(apiTool);
10195
10515
  }
10196
10516
  }
10517
+ if (options.toolResultOffload?.enabled === true) {
10518
+ if (!disabled.has("FetchData") && (wantAll || enabled.has("FetchData"))) {
10519
+ const fetchDataTool = createFetchDataTool({
10520
+ storage: storage.workspace,
10521
+ logPath: options.parentLogPath
10522
+ });
10523
+ registry.register(fetchDataTool);
10524
+ }
10525
+ }
10197
10526
  const agentTool = createAgentTool({
10198
10527
  storage: storage.workspace,
10199
10528
  client,
@@ -10209,7 +10538,8 @@ function buildToolRegistry(options) {
10209
10538
  idleFlushMs: config.transcript.idleFlushMs,
10210
10539
  agents,
10211
10540
  coordinatorMode: isCoordinatorMode(config),
10212
- ...subagentGate !== void 0 ? { gateBeforeTool: subagentGate } : {}
10541
+ ...subagentGate !== void 0 ? { gateBeforeTool: subagentGate } : {},
10542
+ ...options.toolResultOffload !== void 0 ? { toolResultOffload: options.toolResultOffload } : {}
10213
10543
  });
10214
10544
  if (!disabled.has("Agent") && (wantAll || enabled.has("Agent"))) {
10215
10545
  registry.register(agentTool);
@@ -10238,6 +10568,8 @@ function buildToolRegistry(options) {
10238
10568
  }
10239
10569
 
10240
10570
  // src/index.ts
10571
+ init_contract();
10572
+ init_fetchData();
10241
10573
  init_orchestrate();
10242
10574
  init_planParser();
10243
10575
  init_retry();
@@ -10318,12 +10650,14 @@ function resolveApiKey(config) {
10318
10650
  canSpawnProcesses,
10319
10651
  capabilityStub,
10320
10652
  createApiCallTool,
10653
+ createFetchDataTool,
10321
10654
  createLogger,
10322
10655
  createModelAdapter,
10323
10656
  createSendMessageTool,
10324
10657
  createSkillPageTool,
10325
10658
  createSmartMemory,
10326
10659
  defaultSamplingHandler,
10660
+ defaultToolResultSummarizer,
10327
10661
  defineTool,
10328
10662
  detectRuntime,
10329
10663
  getCoordinatorBasePrompt,