la-machina-engine 0.5.0 → 0.7.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/README.md +305 -6
- package/dist/index.cjs +1452 -286
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +412 -20
- package/dist/index.d.ts +412 -20
- package/dist/index.js +1443 -284
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -37,35 +37,124 @@ 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
|
|
130
|
+
var import_zod28, PlanStepSchema, PlanSchema;
|
|
42
131
|
var init_types = __esm({
|
|
43
132
|
"src/orchestrator/types.ts"() {
|
|
44
133
|
"use strict";
|
|
45
134
|
init_cjs_shims();
|
|
46
|
-
|
|
47
|
-
PlanStepSchema =
|
|
48
|
-
id:
|
|
49
|
-
description:
|
|
50
|
-
action:
|
|
51
|
-
files:
|
|
52
|
-
spec:
|
|
53
|
-
dependsOn:
|
|
135
|
+
import_zod28 = require("zod");
|
|
136
|
+
PlanStepSchema = import_zod28.z.object({
|
|
137
|
+
id: import_zod28.z.string().min(1),
|
|
138
|
+
description: import_zod28.z.string().min(1),
|
|
139
|
+
action: import_zod28.z.enum(["research", "implement", "verify", "review", "custom"]),
|
|
140
|
+
files: import_zod28.z.array(import_zod28.z.string()).optional(),
|
|
141
|
+
spec: import_zod28.z.string().optional(),
|
|
142
|
+
dependsOn: import_zod28.z.array(import_zod28.z.string()).optional()
|
|
54
143
|
});
|
|
55
|
-
PlanSchema =
|
|
56
|
-
summary:
|
|
57
|
-
steps:
|
|
144
|
+
PlanSchema = import_zod28.z.object({
|
|
145
|
+
summary: import_zod28.z.string().min(1),
|
|
146
|
+
steps: import_zod28.z.array(PlanStepSchema).min(1)
|
|
58
147
|
});
|
|
59
148
|
}
|
|
60
149
|
});
|
|
61
150
|
|
|
62
151
|
// src/orchestrator/planParser.ts
|
|
63
152
|
function parsePlan(raw, maxSteps) {
|
|
64
|
-
const
|
|
65
|
-
if (
|
|
153
|
+
const json2 = extractJson(raw);
|
|
154
|
+
if (json2 === null) return null;
|
|
66
155
|
let parsed;
|
|
67
156
|
try {
|
|
68
|
-
parsed = JSON.parse(
|
|
157
|
+
parsed = JSON.parse(json2);
|
|
69
158
|
} catch {
|
|
70
159
|
return null;
|
|
71
160
|
}
|
|
@@ -75,23 +164,23 @@ function parsePlan(raw, maxSteps) {
|
|
|
75
164
|
if (plan.steps.length > maxSteps) return null;
|
|
76
165
|
return plan;
|
|
77
166
|
}
|
|
78
|
-
function extractJson(
|
|
79
|
-
const fenceMatch =
|
|
167
|
+
function extractJson(text2) {
|
|
168
|
+
const fenceMatch = text2.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
|
|
80
169
|
if (fenceMatch?.[1]) {
|
|
81
170
|
const inner = fenceMatch[1].trim();
|
|
82
171
|
if (inner.startsWith("{")) return inner;
|
|
83
172
|
}
|
|
84
173
|
let start = -1;
|
|
85
174
|
let depth = 0;
|
|
86
|
-
for (let i = 0; i <
|
|
87
|
-
const c =
|
|
175
|
+
for (let i = 0; i < text2.length; i++) {
|
|
176
|
+
const c = text2[i];
|
|
88
177
|
if (c === "{") {
|
|
89
178
|
if (depth === 0) start = i;
|
|
90
179
|
depth++;
|
|
91
180
|
} else if (c === "}") {
|
|
92
181
|
depth--;
|
|
93
182
|
if (depth === 0 && start !== -1) {
|
|
94
|
-
return
|
|
183
|
+
return text2.slice(start, i + 1);
|
|
95
184
|
}
|
|
96
185
|
}
|
|
97
186
|
}
|
|
@@ -780,6 +869,7 @@ __export(index_exports, {
|
|
|
780
869
|
WebhookDispatcher: () => WebhookDispatcher,
|
|
781
870
|
adaptMcpTool: () => adaptMcpTool,
|
|
782
871
|
buildForkedMessages: () => buildForkedMessages,
|
|
872
|
+
buildKnowledgeIndex: () => buildKnowledgeIndex,
|
|
783
873
|
buildPermissionPolicy: () => buildPermissionPolicy,
|
|
784
874
|
buildSchemaPrompt: () => buildSchemaPrompt,
|
|
785
875
|
buildSystemPrompt: () => buildSystemPrompt,
|
|
@@ -787,16 +877,21 @@ __export(index_exports, {
|
|
|
787
877
|
canSpawnProcesses: () => canSpawnProcesses,
|
|
788
878
|
capabilityStub: () => capabilityStub,
|
|
789
879
|
createApiCallTool: () => createApiCallTool,
|
|
880
|
+
createFetchDataTool: () => createFetchDataTool,
|
|
790
881
|
createLogger: () => createLogger,
|
|
791
882
|
createModelAdapter: () => createModelAdapter,
|
|
883
|
+
createReadKnowledgeTool: () => createReadKnowledgeTool,
|
|
884
|
+
createSearchKnowledgeTool: () => createSearchKnowledgeTool,
|
|
792
885
|
createSendMessageTool: () => createSendMessageTool,
|
|
793
886
|
createSkillPageTool: () => createSkillPageTool,
|
|
794
887
|
createSmartMemory: () => createSmartMemory,
|
|
795
888
|
defaultSamplingHandler: () => defaultSamplingHandler,
|
|
889
|
+
defaultToolResultSummarizer: () => defaultToolResultSummarizer,
|
|
796
890
|
defineTool: () => defineTool,
|
|
797
891
|
detectRuntime: () => detectRuntime,
|
|
798
892
|
getCoordinatorBasePrompt: () => getCoordinatorBasePrompt,
|
|
799
893
|
getCoordinatorSystemPrompt: () => getCoordinatorSystemPrompt,
|
|
894
|
+
getExtractor: () => getExtractor,
|
|
800
895
|
hasProcessLifecycle: () => hasProcessLifecycle,
|
|
801
896
|
initEngine: () => initEngine,
|
|
802
897
|
isCoordinatorMode: () => isCoordinatorMode,
|
|
@@ -817,9 +912,10 @@ __export(index_exports, {
|
|
|
817
912
|
snapshotFiles: () => snapshotFiles,
|
|
818
913
|
synthesizeSpec: () => synthesizeSpec,
|
|
819
914
|
toResponse: () => toResponse,
|
|
820
|
-
tryParseJSON: () =>
|
|
915
|
+
tryParseJSON: () => tryParseJSON2,
|
|
821
916
|
validateOutput: () => validateOutput,
|
|
822
|
-
withCapabilityCheck: () => withCapabilityCheck
|
|
917
|
+
withCapabilityCheck: () => withCapabilityCheck,
|
|
918
|
+
writeKnowledgeIndex: () => writeKnowledgeIndex
|
|
823
919
|
});
|
|
824
920
|
module.exports = __toCommonJS(index_exports);
|
|
825
921
|
init_cjs_shims();
|
|
@@ -1071,13 +1167,19 @@ var McpConfigResolved = import_zod.z.object({
|
|
|
1071
1167
|
shutdownTimeoutMs: import_zod.z.number().int().positive()
|
|
1072
1168
|
}).strict();
|
|
1073
1169
|
var CompactionStrategyEnum = import_zod.z.enum(["drop-middle", "summarize", "session-memory", "auto"]);
|
|
1170
|
+
var ToolResultOffloadConfigResolved = import_zod.z.object({
|
|
1171
|
+
enabled: import_zod.z.boolean(),
|
|
1172
|
+
thresholdBytes: import_zod.z.number().int().positive(),
|
|
1173
|
+
maxPreviewChars: import_zod.z.number().int().positive()
|
|
1174
|
+
}).strict();
|
|
1074
1175
|
var CompactionConfigResolved = import_zod.z.object({
|
|
1075
1176
|
strategy: CompactionStrategyEnum,
|
|
1076
1177
|
threshold: import_zod.z.number().min(0).max(1),
|
|
1077
1178
|
keepLast: import_zod.z.number().int().positive(),
|
|
1078
1179
|
summaryMaxTokens: import_zod.z.number().int().positive(),
|
|
1079
1180
|
microcompact: import_zod.z.boolean(),
|
|
1080
|
-
microcompactAgeMs: import_zod.z.number().int().nonnegative()
|
|
1181
|
+
microcompactAgeMs: import_zod.z.number().int().nonnegative(),
|
|
1182
|
+
toolResultOffload: ToolResultOffloadConfigResolved.optional()
|
|
1081
1183
|
}).strict();
|
|
1082
1184
|
var CoordinatorConfigResolved = import_zod.z.object({
|
|
1083
1185
|
enabled: import_zod.z.boolean(),
|
|
@@ -1146,6 +1248,11 @@ var ApiConfigResolved = import_zod.z.object({
|
|
|
1146
1248
|
services: import_zod.z.array(ApiServiceSchema),
|
|
1147
1249
|
maxResponseBytes: import_zod.z.number().int().positive().optional()
|
|
1148
1250
|
}).strict();
|
|
1251
|
+
var KnowledgeConfigResolved = import_zod.z.object({
|
|
1252
|
+
enabled: import_zod.z.boolean(),
|
|
1253
|
+
maxSearchResults: import_zod.z.number().int().positive(),
|
|
1254
|
+
maxReadBytes: import_zod.z.number().int().positive()
|
|
1255
|
+
}).strict();
|
|
1149
1256
|
var RunnerConfigResolved = import_zod.z.object({
|
|
1150
1257
|
url: import_zod.z.string().url(),
|
|
1151
1258
|
secret: import_zod.z.string().min(1, "runner.secret cannot be empty")
|
|
@@ -1167,7 +1274,8 @@ var ResolvedConfigSchema = import_zod.z.object({
|
|
|
1167
1274
|
coordinator: CoordinatorConfigResolved,
|
|
1168
1275
|
orchestrator: OrchestratorConfigResolved,
|
|
1169
1276
|
runner: RunnerConfigResolved.optional(),
|
|
1170
|
-
api: ApiConfigResolved.optional()
|
|
1277
|
+
api: ApiConfigResolved.optional(),
|
|
1278
|
+
knowledge: KnowledgeConfigResolved.optional()
|
|
1171
1279
|
}).strict();
|
|
1172
1280
|
var R2ConfigUser = R2ConfigResolved.partial();
|
|
1173
1281
|
var ModelConfigUser = ModelConfigResolved.partial();
|
|
@@ -1178,6 +1286,7 @@ var StorageConfigUser = import_zod.z.object({
|
|
|
1178
1286
|
r2: R2ConfigUser.optional(),
|
|
1179
1287
|
r2Binding: R2BucketBindingShape.optional()
|
|
1180
1288
|
}).strict();
|
|
1289
|
+
var KnowledgeConfigUser = KnowledgeConfigResolved.partial();
|
|
1181
1290
|
var MemoryConfigUser = import_zod.z.object({
|
|
1182
1291
|
mode: MemoryModeEnum.optional(),
|
|
1183
1292
|
scope: MemoryScopeUserEnum.optional()
|
|
@@ -1213,7 +1322,16 @@ var McpConfigUser = import_zod.z.object({
|
|
|
1213
1322
|
var PermissionsConfigUser = PermissionsConfigResolved.partial();
|
|
1214
1323
|
var RunnerConfigUser = RunnerConfigResolved;
|
|
1215
1324
|
var ApiConfigUser = ApiConfigResolved.partial();
|
|
1216
|
-
var
|
|
1325
|
+
var ToolResultOffloadConfigUser = ToolResultOffloadConfigResolved.partial();
|
|
1326
|
+
var CompactionConfigUser = import_zod.z.object({
|
|
1327
|
+
strategy: CompactionStrategyEnum.optional(),
|
|
1328
|
+
threshold: import_zod.z.number().min(0).max(1).optional(),
|
|
1329
|
+
keepLast: import_zod.z.number().int().positive().optional(),
|
|
1330
|
+
summaryMaxTokens: import_zod.z.number().int().positive().optional(),
|
|
1331
|
+
microcompact: import_zod.z.boolean().optional(),
|
|
1332
|
+
microcompactAgeMs: import_zod.z.number().int().nonnegative().optional(),
|
|
1333
|
+
toolResultOffload: ToolResultOffloadConfigUser.optional()
|
|
1334
|
+
}).strict();
|
|
1217
1335
|
var CoordinatorConfigUser = CoordinatorConfigResolved.partial();
|
|
1218
1336
|
var OrchestratorConfigUser = OrchestratorConfigResolved.deepPartial();
|
|
1219
1337
|
var UserConfigSchema = import_zod.z.object({
|
|
@@ -1233,7 +1351,8 @@ var UserConfigSchema = import_zod.z.object({
|
|
|
1233
1351
|
coordinator: CoordinatorConfigUser.optional(),
|
|
1234
1352
|
orchestrator: OrchestratorConfigUser.optional(),
|
|
1235
1353
|
runner: RunnerConfigUser.optional(),
|
|
1236
|
-
api: ApiConfigUser.optional()
|
|
1354
|
+
api: ApiConfigUser.optional(),
|
|
1355
|
+
knowledge: KnowledgeConfigUser.optional()
|
|
1237
1356
|
}).strict();
|
|
1238
1357
|
|
|
1239
1358
|
// src/config/merge.ts
|
|
@@ -1306,9 +1425,41 @@ function coerceDeprecatedMemoryScope(user) {
|
|
|
1306
1425
|
memory: { ...memory, scope: "workspace" }
|
|
1307
1426
|
};
|
|
1308
1427
|
}
|
|
1428
|
+
var OFFLOAD_DEFAULTS = { thresholdBytes: 2048, maxPreviewChars: 500 };
|
|
1429
|
+
function splitOffloadRuntime(user) {
|
|
1430
|
+
const block = user.compaction?.toolResultOffload;
|
|
1431
|
+
if (block === void 0) return { stripped: user };
|
|
1432
|
+
const { summarizer, ...schemaSafe } = block;
|
|
1433
|
+
const filled = {
|
|
1434
|
+
enabled: schemaSafe.enabled ?? false,
|
|
1435
|
+
thresholdBytes: schemaSafe.thresholdBytes ?? OFFLOAD_DEFAULTS.thresholdBytes,
|
|
1436
|
+
maxPreviewChars: schemaSafe.maxPreviewChars ?? OFFLOAD_DEFAULTS.maxPreviewChars
|
|
1437
|
+
};
|
|
1438
|
+
const clone = {
|
|
1439
|
+
...user,
|
|
1440
|
+
compaction: {
|
|
1441
|
+
...user.compaction ?? {},
|
|
1442
|
+
toolResultOffload: filled
|
|
1443
|
+
}
|
|
1444
|
+
};
|
|
1445
|
+
return { stripped: clone, summarizer };
|
|
1446
|
+
}
|
|
1447
|
+
var KNOWLEDGE_DEFAULTS = { maxSearchResults: 5, maxReadBytes: 1e4 };
|
|
1448
|
+
function fillKnowledgeDefaults(user) {
|
|
1449
|
+
const block = user.knowledge;
|
|
1450
|
+
if (block === void 0) return user;
|
|
1451
|
+
const filled = {
|
|
1452
|
+
enabled: block.enabled ?? false,
|
|
1453
|
+
maxSearchResults: block.maxSearchResults ?? KNOWLEDGE_DEFAULTS.maxSearchResults,
|
|
1454
|
+
maxReadBytes: block.maxReadBytes ?? KNOWLEDGE_DEFAULTS.maxReadBytes
|
|
1455
|
+
};
|
|
1456
|
+
return { ...user, knowledge: filled };
|
|
1457
|
+
}
|
|
1309
1458
|
function mergeConfig(user) {
|
|
1310
1459
|
const withCoercedScope = coerceDeprecatedMemoryScope(user);
|
|
1311
|
-
const
|
|
1460
|
+
const withKnowledge = fillKnowledgeDefaults(withCoercedScope);
|
|
1461
|
+
const { stripped: afterOffload, summarizer } = splitOffloadRuntime(withKnowledge);
|
|
1462
|
+
const { stripped, runtime } = splitApiRuntime(afterOffload);
|
|
1312
1463
|
const validatedUser = UserConfigSchema.parse(stripped);
|
|
1313
1464
|
const merged = deepMerge(DEFAULTS, validatedUser);
|
|
1314
1465
|
const resolved = ResolvedConfigSchema.parse(merged);
|
|
@@ -1320,6 +1471,13 @@ function mergeConfig(user) {
|
|
|
1320
1471
|
};
|
|
1321
1472
|
} else if (Object.keys(runtime).length > 0) {
|
|
1322
1473
|
}
|
|
1474
|
+
if (summarizer !== void 0 && resolved.compaction.toolResultOffload !== void 0) {
|
|
1475
|
+
const mutable = resolved.compaction;
|
|
1476
|
+
mutable.toolResultOffload = {
|
|
1477
|
+
...resolved.compaction.toolResultOffload,
|
|
1478
|
+
summarizer
|
|
1479
|
+
};
|
|
1480
|
+
}
|
|
1323
1481
|
return resolved;
|
|
1324
1482
|
}
|
|
1325
1483
|
|
|
@@ -1966,44 +2124,7 @@ function hasProcessLifecycle() {
|
|
|
1966
2124
|
// src/tools/capabilityStub.ts
|
|
1967
2125
|
init_cjs_shims();
|
|
1968
2126
|
var import_zod2 = require("zod");
|
|
1969
|
-
|
|
1970
|
-
// src/tools/contract.ts
|
|
1971
|
-
init_cjs_shims();
|
|
1972
|
-
function defineTool(tool) {
|
|
1973
|
-
return tool;
|
|
1974
|
-
}
|
|
1975
|
-
var ToolRegistry = class {
|
|
1976
|
-
tools = /* @__PURE__ */ new Map();
|
|
1977
|
-
register(tool) {
|
|
1978
|
-
if (typeof tool.name !== "string" || tool.name.length === 0) {
|
|
1979
|
-
throw new Error("ToolRegistry: tool.name must be a non-empty string");
|
|
1980
|
-
}
|
|
1981
|
-
if (this.tools.has(tool.name)) {
|
|
1982
|
-
throw new Error(`ToolRegistry: "${tool.name}" is already registered`);
|
|
1983
|
-
}
|
|
1984
|
-
this.tools.set(tool.name, tool);
|
|
1985
|
-
}
|
|
1986
|
-
registerAll(tools) {
|
|
1987
|
-
for (const tool of tools) this.register(tool);
|
|
1988
|
-
}
|
|
1989
|
-
unregister(name) {
|
|
1990
|
-
this.tools.delete(name);
|
|
1991
|
-
}
|
|
1992
|
-
get(name) {
|
|
1993
|
-
return this.tools.get(name);
|
|
1994
|
-
}
|
|
1995
|
-
has(name) {
|
|
1996
|
-
return this.tools.has(name);
|
|
1997
|
-
}
|
|
1998
|
-
list() {
|
|
1999
|
-
return Array.from(this.tools.values());
|
|
2000
|
-
}
|
|
2001
|
-
count() {
|
|
2002
|
-
return this.tools.size;
|
|
2003
|
-
}
|
|
2004
|
-
};
|
|
2005
|
-
|
|
2006
|
-
// src/tools/capabilityStub.ts
|
|
2127
|
+
init_contract();
|
|
2007
2128
|
var anyInput = import_zod2.z.unknown();
|
|
2008
2129
|
function capabilityStub(original) {
|
|
2009
2130
|
return defineTool({
|
|
@@ -2207,7 +2328,7 @@ var SubagentRegistry = class _SubagentRegistry {
|
|
|
2207
2328
|
|
|
2208
2329
|
// src/tools/agent.ts
|
|
2209
2330
|
init_cjs_shims();
|
|
2210
|
-
var
|
|
2331
|
+
var import_zod7 = require("zod");
|
|
2211
2332
|
|
|
2212
2333
|
// src/subagent/runner.ts
|
|
2213
2334
|
init_cjs_shims();
|
|
@@ -2271,6 +2392,131 @@ async function writeSnapshot(storage, logPath, snapshot) {
|
|
|
2271
2392
|
await storage.writeFile(snapshotPath(logPath), JSON.stringify(validated, null, 2));
|
|
2272
2393
|
}
|
|
2273
2394
|
|
|
2395
|
+
// src/engine/toolResultOffload.ts
|
|
2396
|
+
init_cjs_shims();
|
|
2397
|
+
|
|
2398
|
+
// src/engine/toolResultSummarizer.ts
|
|
2399
|
+
init_cjs_shims();
|
|
2400
|
+
var MAX_ITEM_PREVIEW_CHARS = 150;
|
|
2401
|
+
var MAX_TOP_LEVEL_KEYS = 8;
|
|
2402
|
+
var defaultToolResultSummarizer = (ctx) => {
|
|
2403
|
+
return summarize(ctx);
|
|
2404
|
+
};
|
|
2405
|
+
function summarize(ctx) {
|
|
2406
|
+
const { toolName, rawContent, rawBytes, ref, maxPreviewChars } = ctx;
|
|
2407
|
+
const parsed = tryParseJSON(rawContent);
|
|
2408
|
+
if (parsed.ok) {
|
|
2409
|
+
if (Array.isArray(parsed.value)) {
|
|
2410
|
+
return summarizeArray(toolName, parsed.value, ref, rawBytes);
|
|
2411
|
+
}
|
|
2412
|
+
if (parsed.value !== null && typeof parsed.value === "object") {
|
|
2413
|
+
return summarizeObject(toolName, parsed.value, ref, rawBytes);
|
|
2414
|
+
}
|
|
2415
|
+
}
|
|
2416
|
+
const preview = rawContent.slice(0, maxPreviewChars);
|
|
2417
|
+
const truncated = rawContent.length > maxPreviewChars ? "\u2026" : "";
|
|
2418
|
+
return `[${toolName}] ${formatBytes(rawBytes)} offloaded.
|
|
2419
|
+
` + (preview.length > 0 ? `Preview: ${preview}${truncated}
|
|
2420
|
+
` : "") + `Use FetchData with ref="${ref}" to read the full content.`;
|
|
2421
|
+
}
|
|
2422
|
+
function summarizeArray(toolName, arr, ref, bytes) {
|
|
2423
|
+
const count = arr.length;
|
|
2424
|
+
const firstHint = arr.length > 0 ? compactPreview(arr[0]) : "";
|
|
2425
|
+
const hintLine = firstHint ? `First item preview: ${firstHint}
|
|
2426
|
+
` : "";
|
|
2427
|
+
return `[${toolName}] Array of ${count} item${count === 1 ? "" : "s"} (${formatBytes(bytes)}).
|
|
2428
|
+
` + hintLine + `Use FetchData with ref="${ref}" to read the full array.`;
|
|
2429
|
+
}
|
|
2430
|
+
function summarizeObject(toolName, obj, ref, bytes) {
|
|
2431
|
+
const keys = Object.keys(obj);
|
|
2432
|
+
const shown = keys.slice(0, MAX_TOP_LEVEL_KEYS);
|
|
2433
|
+
const overflow = keys.length > MAX_TOP_LEVEL_KEYS ? ` (+${keys.length - shown.length} more)` : "";
|
|
2434
|
+
const parts = shown.map((k) => `${k}=${compactPreview(obj[k])}`).join(", ");
|
|
2435
|
+
return `[${toolName}] Object (${formatBytes(bytes)}). Keys: ${parts}${overflow}
|
|
2436
|
+
Use FetchData with ref="${ref}" to read the full object.`;
|
|
2437
|
+
}
|
|
2438
|
+
function compactPreview(value) {
|
|
2439
|
+
let str;
|
|
2440
|
+
if (value === null) {
|
|
2441
|
+
str = "null";
|
|
2442
|
+
} else if (typeof value === "string") {
|
|
2443
|
+
str = JSON.stringify(value);
|
|
2444
|
+
} else if (Array.isArray(value)) {
|
|
2445
|
+
str = `[${value.length} item${value.length === 1 ? "" : "s"}]`;
|
|
2446
|
+
} else if (typeof value === "object") {
|
|
2447
|
+
const keys = Object.keys(value);
|
|
2448
|
+
str = `{${keys.slice(0, 3).join(", ")}${keys.length > 3 ? ", \u2026" : ""}}`;
|
|
2449
|
+
} else {
|
|
2450
|
+
str = String(value);
|
|
2451
|
+
}
|
|
2452
|
+
if (str.length > MAX_ITEM_PREVIEW_CHARS) {
|
|
2453
|
+
return str.slice(0, MAX_ITEM_PREVIEW_CHARS) + "\u2026";
|
|
2454
|
+
}
|
|
2455
|
+
return str;
|
|
2456
|
+
}
|
|
2457
|
+
function tryParseJSON(text2) {
|
|
2458
|
+
const trimmed = text2.replace(/^\uFEFF/, "").trim();
|
|
2459
|
+
if (trimmed.length === 0) return { ok: false };
|
|
2460
|
+
const first = trimmed[0];
|
|
2461
|
+
if (first !== "{" && first !== "[" && first !== '"') return { ok: false };
|
|
2462
|
+
try {
|
|
2463
|
+
return { ok: true, value: JSON.parse(trimmed) };
|
|
2464
|
+
} catch {
|
|
2465
|
+
return { ok: false };
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2468
|
+
function formatBytes(bytes) {
|
|
2469
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
2470
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
2471
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
2472
|
+
}
|
|
2473
|
+
|
|
2474
|
+
// src/engine/toolResultOffload.ts
|
|
2475
|
+
async function maybeOffloadToolResult(input) {
|
|
2476
|
+
const {
|
|
2477
|
+
offloadConfig,
|
|
2478
|
+
storage,
|
|
2479
|
+
logPath,
|
|
2480
|
+
toolUseId,
|
|
2481
|
+
toolName,
|
|
2482
|
+
toolInput,
|
|
2483
|
+
rawContent,
|
|
2484
|
+
rawIsError
|
|
2485
|
+
} = input;
|
|
2486
|
+
if (offloadConfig === void 0 || offloadConfig.enabled !== true) {
|
|
2487
|
+
return rawContent;
|
|
2488
|
+
}
|
|
2489
|
+
if (rawIsError) {
|
|
2490
|
+
return rawContent;
|
|
2491
|
+
}
|
|
2492
|
+
if (toolName === "FetchData") {
|
|
2493
|
+
return rawContent;
|
|
2494
|
+
}
|
|
2495
|
+
const rawBytes = byteLength(rawContent);
|
|
2496
|
+
if (rawBytes <= offloadConfig.thresholdBytes) {
|
|
2497
|
+
return rawContent;
|
|
2498
|
+
}
|
|
2499
|
+
const path = `${logPath}/toolResults/${toolUseId}.json`;
|
|
2500
|
+
await storage.writeFile(path, rawContent);
|
|
2501
|
+
const summarizer = offloadConfig.summarizer ?? defaultToolResultSummarizer;
|
|
2502
|
+
const summary = await summarizer({
|
|
2503
|
+
toolName,
|
|
2504
|
+
toolInput,
|
|
2505
|
+
rawContent,
|
|
2506
|
+
rawBytes,
|
|
2507
|
+
ref: toolUseId,
|
|
2508
|
+
maxPreviewChars: offloadConfig.maxPreviewChars
|
|
2509
|
+
});
|
|
2510
|
+
if (!summary.includes(toolUseId)) {
|
|
2511
|
+
return `${summary}
|
|
2512
|
+
[offloaded \u2014 ref=${toolUseId}, use FetchData to read the full content]`;
|
|
2513
|
+
}
|
|
2514
|
+
return summary;
|
|
2515
|
+
}
|
|
2516
|
+
function byteLength(s) {
|
|
2517
|
+
return new TextEncoder().encode(s).byteLength;
|
|
2518
|
+
}
|
|
2519
|
+
|
|
2274
2520
|
// src/hooks/dispatch.ts
|
|
2275
2521
|
init_cjs_shims();
|
|
2276
2522
|
async function dispatchHooks(hooks, event) {
|
|
@@ -2293,8 +2539,8 @@ var INTERNAL_BLOCK_PATTERNS = [
|
|
|
2293
2539
|
/<git_signature>[\s\S]*?<\/git_signature>/g,
|
|
2294
2540
|
/<caller>[\s\S]*?<\/caller>/g
|
|
2295
2541
|
];
|
|
2296
|
-
function stripInternalBlocks(
|
|
2297
|
-
let result =
|
|
2542
|
+
function stripInternalBlocks(text2) {
|
|
2543
|
+
let result = text2;
|
|
2298
2544
|
for (const pattern of INTERNAL_BLOCK_PATTERNS) {
|
|
2299
2545
|
pattern.lastIndex = 0;
|
|
2300
2546
|
result = result.replace(pattern, "");
|
|
@@ -2942,8 +3188,8 @@ async function agentLoop(options) {
|
|
|
2942
3188
|
assistantContent.push({ type: "thinking", thinking });
|
|
2943
3189
|
}
|
|
2944
3190
|
}
|
|
2945
|
-
for (const
|
|
2946
|
-
if (
|
|
3191
|
+
for (const text2 of textBlocks) {
|
|
3192
|
+
if (text2.length > 0) assistantContent.push({ type: "text", text: text2 });
|
|
2947
3193
|
}
|
|
2948
3194
|
for (const tc of toolCalls) {
|
|
2949
3195
|
assistantContent.push({
|
|
@@ -3023,7 +3269,32 @@ async function agentLoop(options) {
|
|
|
3023
3269
|
if (typeof missing === "string") {
|
|
3024
3270
|
ctx.recordCapabilityMissing(missing);
|
|
3025
3271
|
}
|
|
3026
|
-
|
|
3272
|
+
const call = toolCallsToDispatch.find((c) => c.id === id);
|
|
3273
|
+
let contentForTranscript;
|
|
3274
|
+
if (options.toolResultOffload !== void 0 && options.storage !== void 0) {
|
|
3275
|
+
try {
|
|
3276
|
+
contentForTranscript = await maybeOffloadToolResult({
|
|
3277
|
+
offloadConfig: options.toolResultOffload,
|
|
3278
|
+
storage: options.storage,
|
|
3279
|
+
logPath: options.offloadLogPath ?? transcript.path,
|
|
3280
|
+
toolUseId: id,
|
|
3281
|
+
toolName: call?.name ?? "unknown",
|
|
3282
|
+
toolInput: call?.input,
|
|
3283
|
+
rawContent: result.content,
|
|
3284
|
+
rawIsError: result.isError === true
|
|
3285
|
+
});
|
|
3286
|
+
} catch (err) {
|
|
3287
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
3288
|
+
contentForTranscript = `[tool-result offload failed: ${msg}] ${result.content.slice(0, 500)}`;
|
|
3289
|
+
}
|
|
3290
|
+
} else {
|
|
3291
|
+
contentForTranscript = result.content;
|
|
3292
|
+
}
|
|
3293
|
+
await ctx.addToolResult(
|
|
3294
|
+
id,
|
|
3295
|
+
truncateToolResult(contentForTranscript),
|
|
3296
|
+
result.isError === true
|
|
3297
|
+
);
|
|
3027
3298
|
}
|
|
3028
3299
|
} catch (err) {
|
|
3029
3300
|
if (err instanceof SubagentPausedError) {
|
|
@@ -3157,11 +3428,11 @@ function toAnthropicTool(tool) {
|
|
|
3157
3428
|
target: "jsonSchema7",
|
|
3158
3429
|
$refStrategy: "none"
|
|
3159
3430
|
});
|
|
3160
|
-
const { $schema: _schema, ...
|
|
3431
|
+
const { $schema: _schema, ...inputSchema20 } = schema;
|
|
3161
3432
|
return {
|
|
3162
3433
|
name: tool.name,
|
|
3163
3434
|
description: tool.description,
|
|
3164
|
-
input_schema:
|
|
3435
|
+
input_schema: inputSchema20
|
|
3165
3436
|
};
|
|
3166
3437
|
}
|
|
3167
3438
|
function partitionToolCalls(calls, registry) {
|
|
@@ -3296,8 +3567,8 @@ var RunContext = class {
|
|
|
3296
3567
|
this.episodes = options.episodes ?? null;
|
|
3297
3568
|
}
|
|
3298
3569
|
// ---------- message mutators ----------
|
|
3299
|
-
async addUserMessage(
|
|
3300
|
-
const content = [{ type: "text", text }];
|
|
3570
|
+
async addUserMessage(text2) {
|
|
3571
|
+
const content = [{ type: "text", text: text2 }];
|
|
3301
3572
|
this.messages.push({ role: "user", content });
|
|
3302
3573
|
await this.writeEntry({
|
|
3303
3574
|
type: "user",
|
|
@@ -3306,7 +3577,7 @@ var RunContext = class {
|
|
|
3306
3577
|
ts: this.now(),
|
|
3307
3578
|
message: { role: "user", content }
|
|
3308
3579
|
});
|
|
3309
|
-
this.episodes?.logTurn(this.turnCount, "user",
|
|
3580
|
+
this.episodes?.logTurn(this.turnCount, "user", text2);
|
|
3310
3581
|
}
|
|
3311
3582
|
async addAssistantMessage(content) {
|
|
3312
3583
|
this.messages.push({ role: "assistant", content });
|
|
@@ -3871,6 +4142,19 @@ async function loadWriterState(storage, logPath) {
|
|
|
3871
4142
|
// src/subagent/runner.ts
|
|
3872
4143
|
async function runAgent(options) {
|
|
3873
4144
|
const childLogPath = `${options.parentLogPath}/subagents/${options.agentId}`;
|
|
4145
|
+
let restorePrevFetchData = null;
|
|
4146
|
+
if (options.toolResultOffload !== void 0 && options.toolResultOffload.enabled) {
|
|
4147
|
+
const { createFetchDataTool: createFetchDataTool2 } = await Promise.resolve().then(() => (init_fetchData(), fetchData_exports));
|
|
4148
|
+
const existing = options.registry.get("FetchData");
|
|
4149
|
+
options.registry.unregister("FetchData");
|
|
4150
|
+
options.registry.register(
|
|
4151
|
+
createFetchDataTool2({ storage: options.storage, logPath: childLogPath })
|
|
4152
|
+
);
|
|
4153
|
+
restorePrevFetchData = () => {
|
|
4154
|
+
options.registry.unregister("FetchData");
|
|
4155
|
+
if (existing !== void 0) options.registry.register(existing);
|
|
4156
|
+
};
|
|
4157
|
+
}
|
|
3874
4158
|
const writer = new TranscriptWriter({
|
|
3875
4159
|
storage: options.storage,
|
|
3876
4160
|
logPath: childLogPath,
|
|
@@ -3911,7 +4195,15 @@ async function runAgent(options) {
|
|
|
3911
4195
|
// Propagate parent's gate + storage into the child loop when set.
|
|
3912
4196
|
// Without `storage`, a gate denial would fail the child instead of
|
|
3913
4197
|
// pausing it, so both must travel together.
|
|
3914
|
-
...options.gateBeforeTool !== void 0 ? { gateBeforeTool: options.gateBeforeTool, storage: options.storage } : {}
|
|
4198
|
+
...options.gateBeforeTool !== void 0 ? { gateBeforeTool: options.gateBeforeTool, storage: options.storage } : {},
|
|
4199
|
+
// Plan 021 — the child needs its own storage + offload config
|
|
4200
|
+
// so its own large tool results get offloaded into
|
|
4201
|
+
// `childLogPath/toolResults/...`, not the parent's folder.
|
|
4202
|
+
...options.toolResultOffload !== void 0 ? {
|
|
4203
|
+
storage: options.storage,
|
|
4204
|
+
toolResultOffload: options.toolResultOffload,
|
|
4205
|
+
offloadLogPath: childLogPath
|
|
4206
|
+
} : {}
|
|
3915
4207
|
});
|
|
3916
4208
|
if (result.status === "done") {
|
|
3917
4209
|
await writer.setStatus("done");
|
|
@@ -3967,6 +4259,7 @@ async function runAgent(options) {
|
|
|
3967
4259
|
} catch {
|
|
3968
4260
|
}
|
|
3969
4261
|
await writer.close();
|
|
4262
|
+
restorePrevFetchData?.();
|
|
3970
4263
|
}
|
|
3971
4264
|
}
|
|
3972
4265
|
|
|
@@ -4039,10 +4332,11 @@ Directive: ${directive}`;
|
|
|
4039
4332
|
}
|
|
4040
4333
|
|
|
4041
4334
|
// src/tools/agent.ts
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4335
|
+
init_contract();
|
|
4336
|
+
var inputSchema2 = import_zod7.z.object({
|
|
4337
|
+
description: import_zod7.z.string().min(1),
|
|
4338
|
+
subagent_type: import_zod7.z.string().optional(),
|
|
4339
|
+
run_in_background: import_zod7.z.boolean().optional()
|
|
4046
4340
|
});
|
|
4047
4341
|
function createAgentTool(options) {
|
|
4048
4342
|
if (options.agents.length === 0) {
|
|
@@ -4062,7 +4356,7 @@ If omitted, defaults to "${defaultAgent.name}".`;
|
|
|
4062
4356
|
return defineTool({
|
|
4063
4357
|
name: "Agent",
|
|
4064
4358
|
description,
|
|
4065
|
-
inputSchema,
|
|
4359
|
+
inputSchema: inputSchema2,
|
|
4066
4360
|
isConcurrencySafe: (input) => {
|
|
4067
4361
|
const typed = input;
|
|
4068
4362
|
const typeName = typed?.subagent_type ?? defaultAgent.name;
|
|
@@ -4103,7 +4397,8 @@ If omitted, defaults to "${defaultAgent.name}".`;
|
|
|
4103
4397
|
idleFlushMs: options.idleFlushMs,
|
|
4104
4398
|
// Fork: prepend parent messages + forked messages
|
|
4105
4399
|
prependMessages: [...parentMsgs, ...forkedMsgs],
|
|
4106
|
-
...options.gateBeforeTool !== void 0 ? { gateBeforeTool: options.gateBeforeTool } : {}
|
|
4400
|
+
...options.gateBeforeTool !== void 0 ? { gateBeforeTool: options.gateBeforeTool } : {},
|
|
4401
|
+
...options.toolResultOffload !== void 0 ? { toolResultOffload: options.toolResultOffload } : {}
|
|
4107
4402
|
});
|
|
4108
4403
|
handlePausedResult(result2, spawn2.agentId, "fork");
|
|
4109
4404
|
const t2 = result2;
|
|
@@ -4152,7 +4447,8 @@ If omitted, defaults to "${defaultAgent.name}".`;
|
|
|
4152
4447
|
turnTimeoutMs: options.turnTimeoutMs,
|
|
4153
4448
|
flushPolicy: options.flushPolicy,
|
|
4154
4449
|
idleFlushMs: options.idleFlushMs,
|
|
4155
|
-
...options.gateBeforeTool !== void 0 ? { gateBeforeTool: options.gateBeforeTool } : {}
|
|
4450
|
+
...options.gateBeforeTool !== void 0 ? { gateBeforeTool: options.gateBeforeTool } : {},
|
|
4451
|
+
...options.toolResultOffload !== void 0 ? { toolResultOffload: options.toolResultOffload } : {}
|
|
4156
4452
|
};
|
|
4157
4453
|
const shouldRunAsync = run_in_background === true || options.coordinatorMode === true;
|
|
4158
4454
|
if (shouldRunAsync) {
|
|
@@ -4247,7 +4543,8 @@ function handlePausedResult(result, agentId, subagentType) {
|
|
|
4247
4543
|
|
|
4248
4544
|
// src/tools/bash.ts
|
|
4249
4545
|
init_cjs_shims();
|
|
4250
|
-
var
|
|
4546
|
+
var import_zod8 = require("zod");
|
|
4547
|
+
init_contract();
|
|
4251
4548
|
var _spawn = null;
|
|
4252
4549
|
async function getSpawn() {
|
|
4253
4550
|
if (_spawn === null) {
|
|
@@ -4259,15 +4556,15 @@ async function getSpawn() {
|
|
|
4259
4556
|
var MAX_OUTPUT_BYTES = 512 * 1024;
|
|
4260
4557
|
var SIGKILL_GRACE_MS = 500;
|
|
4261
4558
|
var BLOCKED_DEVICE_PATHS = /\b(\/dev\/zero|\/dev\/random|\/dev\/urandom|\/proc\/kcore|\/dev\/sda|\/dev\/mem)\b/;
|
|
4262
|
-
var
|
|
4263
|
-
command:
|
|
4264
|
-
cwd:
|
|
4559
|
+
var inputSchema3 = import_zod8.z.object({
|
|
4560
|
+
command: import_zod8.z.string().min(1),
|
|
4561
|
+
cwd: import_zod8.z.string().min(1).optional()
|
|
4265
4562
|
});
|
|
4266
4563
|
function createBashTool() {
|
|
4267
4564
|
return defineTool({
|
|
4268
4565
|
name: "Bash",
|
|
4269
4566
|
description: "Execute a shell command via /bin/sh -c. Returns combined stdout+stderr and the exit code.",
|
|
4270
|
-
inputSchema:
|
|
4567
|
+
inputSchema: inputSchema3,
|
|
4271
4568
|
requiresNode: true,
|
|
4272
4569
|
execute: async ({ command, cwd }, ctx) => {
|
|
4273
4570
|
if (BLOCKED_DEVICE_PATHS.test(command)) {
|
|
@@ -4348,16 +4645,17 @@ function createBashTool() {
|
|
|
4348
4645
|
|
|
4349
4646
|
// src/tools/sendMessage.ts
|
|
4350
4647
|
init_cjs_shims();
|
|
4351
|
-
var
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4648
|
+
var import_zod9 = require("zod");
|
|
4649
|
+
init_contract();
|
|
4650
|
+
var inputSchema4 = import_zod9.z.object({
|
|
4651
|
+
to: import_zod9.z.string().min(1).describe("Agent name (subagent_type) or agentId to send the message to."),
|
|
4652
|
+
message: import_zod9.z.string().min(1).describe("Message content to deliver to the target agent.")
|
|
4355
4653
|
});
|
|
4356
4654
|
function createSendMessageTool(options) {
|
|
4357
4655
|
return defineTool({
|
|
4358
4656
|
name: "SendMessage",
|
|
4359
4657
|
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.",
|
|
4360
|
-
inputSchema:
|
|
4658
|
+
inputSchema: inputSchema4,
|
|
4361
4659
|
execute: async ({ to, message }) => {
|
|
4362
4660
|
const { registry } = options;
|
|
4363
4661
|
let agentId = registry.findByName(to);
|
|
@@ -4400,20 +4698,24 @@ function createSendMessageTool(options) {
|
|
|
4400
4698
|
});
|
|
4401
4699
|
}
|
|
4402
4700
|
|
|
4701
|
+
// src/engine/engine.ts
|
|
4702
|
+
init_contract();
|
|
4703
|
+
|
|
4403
4704
|
// src/tools/fileEdit.ts
|
|
4404
4705
|
init_cjs_shims();
|
|
4405
|
-
var
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4706
|
+
var import_zod10 = require("zod");
|
|
4707
|
+
init_contract();
|
|
4708
|
+
var inputSchema5 = import_zod10.z.object({
|
|
4709
|
+
path: import_zod10.z.string().min(1),
|
|
4710
|
+
old_string: import_zod10.z.string().min(1),
|
|
4711
|
+
new_string: import_zod10.z.string(),
|
|
4712
|
+
replace_all: import_zod10.z.boolean().optional()
|
|
4411
4713
|
});
|
|
4412
4714
|
function createFileEditTool(storage) {
|
|
4413
4715
|
return defineTool({
|
|
4414
4716
|
name: "Edit",
|
|
4415
4717
|
description: "Replace old_string with new_string in a file. By default old_string must be unique; set replace_all to replace every occurrence.",
|
|
4416
|
-
inputSchema:
|
|
4718
|
+
inputSchema: inputSchema5,
|
|
4417
4719
|
execute: async ({ path, old_string, new_string, replace_all }) => {
|
|
4418
4720
|
if (old_string === new_string) {
|
|
4419
4721
|
return {
|
|
@@ -4491,13 +4793,14 @@ function normalizeQuotes(s) {
|
|
|
4491
4793
|
|
|
4492
4794
|
// src/tools/fileRead.ts
|
|
4493
4795
|
init_cjs_shims();
|
|
4494
|
-
var
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4796
|
+
var import_zod11 = require("zod");
|
|
4797
|
+
init_contract();
|
|
4798
|
+
var inputSchema6 = import_zod11.z.object({
|
|
4799
|
+
path: import_zod11.z.string().min(1),
|
|
4800
|
+
offset: import_zod11.z.number().int().positive().optional(),
|
|
4801
|
+
limit: import_zod11.z.number().int().positive().optional(),
|
|
4499
4802
|
/** PDF page range, e.g. "1-5", "3", "10-20". Max 20 pages per request. */
|
|
4500
|
-
pages:
|
|
4803
|
+
pages: import_zod11.z.string().optional()
|
|
4501
4804
|
});
|
|
4502
4805
|
var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp", ".svg"]);
|
|
4503
4806
|
var PDF_EXTENSION = ".pdf";
|
|
@@ -4516,7 +4819,7 @@ function createFileReadTool(storageOrOptions) {
|
|
|
4516
4819
|
return defineTool({
|
|
4517
4820
|
name: "Read",
|
|
4518
4821
|
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.",
|
|
4519
|
-
inputSchema:
|
|
4822
|
+
inputSchema: inputSchema6,
|
|
4520
4823
|
isConcurrencySafe: () => true,
|
|
4521
4824
|
execute: async ({ path, offset, limit, pages }) => {
|
|
4522
4825
|
const ext = extname(path);
|
|
@@ -4681,10 +4984,11 @@ Base64 data is included in the metadata for visual analysis.`,
|
|
|
4681
4984
|
|
|
4682
4985
|
// src/tools/fileWrite.ts
|
|
4683
4986
|
init_cjs_shims();
|
|
4684
|
-
var
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4987
|
+
var import_zod12 = require("zod");
|
|
4988
|
+
init_contract();
|
|
4989
|
+
var inputSchema7 = import_zod12.z.object({
|
|
4990
|
+
path: import_zod12.z.string().min(1),
|
|
4991
|
+
content: import_zod12.z.string()
|
|
4688
4992
|
});
|
|
4689
4993
|
function createFileWriteTool(storageOrOptions) {
|
|
4690
4994
|
const opts = "readFile" in storageOrOptions ? { storage: storageOrOptions } : storageOrOptions;
|
|
@@ -4692,7 +4996,7 @@ function createFileWriteTool(storageOrOptions) {
|
|
|
4692
4996
|
return defineTool({
|
|
4693
4997
|
name: "Write",
|
|
4694
4998
|
description: "Write a file to the workspace. Creates parents and overwrites existing files.",
|
|
4695
|
-
inputSchema:
|
|
4999
|
+
inputSchema: inputSchema7,
|
|
4696
5000
|
execute: async ({ path, content }) => {
|
|
4697
5001
|
if (tracker !== void 0) {
|
|
4698
5002
|
const exists = await storage.exists(path);
|
|
@@ -4723,7 +5027,8 @@ function createFileWriteTool(storageOrOptions) {
|
|
|
4723
5027
|
// src/tools/glob.ts
|
|
4724
5028
|
init_cjs_shims();
|
|
4725
5029
|
var import_picomatch = __toESM(require("picomatch"), 1);
|
|
4726
|
-
var
|
|
5030
|
+
var import_zod13 = require("zod");
|
|
5031
|
+
init_contract();
|
|
4727
5032
|
|
|
4728
5033
|
// src/tools/walkAdapter.ts
|
|
4729
5034
|
init_cjs_shims();
|
|
@@ -4760,16 +5065,16 @@ async function* walkAdapter(adapter, startPath, options = {}) {
|
|
|
4760
5065
|
}
|
|
4761
5066
|
|
|
4762
5067
|
// src/tools/glob.ts
|
|
4763
|
-
var
|
|
4764
|
-
pattern:
|
|
4765
|
-
path:
|
|
5068
|
+
var inputSchema8 = import_zod13.z.object({
|
|
5069
|
+
pattern: import_zod13.z.string().min(1),
|
|
5070
|
+
path: import_zod13.z.string().optional()
|
|
4766
5071
|
});
|
|
4767
5072
|
var MAX_RESULTS = 1e3;
|
|
4768
5073
|
function createGlobTool(storage) {
|
|
4769
5074
|
return defineTool({
|
|
4770
5075
|
name: "Glob",
|
|
4771
5076
|
description: "Find files by glob pattern. Supports *, **, ?, [abc], {a,b}. Returns paths sorted by mtime descending.",
|
|
4772
|
-
inputSchema:
|
|
5077
|
+
inputSchema: inputSchema8,
|
|
4773
5078
|
isConcurrencySafe: () => true,
|
|
4774
5079
|
execute: async ({ pattern, path: searchPath }) => {
|
|
4775
5080
|
const startPath = searchPath ?? "";
|
|
@@ -4815,22 +5120,23 @@ function createGlobTool(storage) {
|
|
|
4815
5120
|
// src/tools/grep.ts
|
|
4816
5121
|
init_cjs_shims();
|
|
4817
5122
|
var import_picomatch2 = __toESM(require("picomatch"), 1);
|
|
4818
|
-
var
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
"-
|
|
4827
|
-
"-
|
|
4828
|
-
"-
|
|
4829
|
-
"-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
5123
|
+
var import_zod14 = require("zod");
|
|
5124
|
+
init_contract();
|
|
5125
|
+
var inputSchema9 = import_zod14.z.object({
|
|
5126
|
+
pattern: import_zod14.z.string().min(1),
|
|
5127
|
+
path: import_zod14.z.string().optional(),
|
|
5128
|
+
glob: import_zod14.z.string().optional(),
|
|
5129
|
+
type: import_zod14.z.string().optional(),
|
|
5130
|
+
output_mode: import_zod14.z.enum(["content", "files_with_matches", "count"]).optional(),
|
|
5131
|
+
"-i": import_zod14.z.boolean().optional(),
|
|
5132
|
+
"-n": import_zod14.z.boolean().optional(),
|
|
5133
|
+
"-A": import_zod14.z.number().int().nonnegative().optional(),
|
|
5134
|
+
"-B": import_zod14.z.number().int().nonnegative().optional(),
|
|
5135
|
+
"-C": import_zod14.z.number().int().nonnegative().optional(),
|
|
5136
|
+
context: import_zod14.z.number().int().nonnegative().optional(),
|
|
5137
|
+
multiline: import_zod14.z.boolean().optional(),
|
|
5138
|
+
head_limit: import_zod14.z.number().int().nonnegative().optional(),
|
|
5139
|
+
offset: import_zod14.z.number().int().nonnegative().optional()
|
|
4834
5140
|
});
|
|
4835
5141
|
var MAX_FILES_SCANNED = 5e3;
|
|
4836
5142
|
var MAX_MATCHES_PER_FILE = 100;
|
|
@@ -4876,7 +5182,7 @@ function createGrepTool(storage) {
|
|
|
4876
5182
|
return defineTool({
|
|
4877
5183
|
name: "Grep",
|
|
4878
5184
|
description: "Search for a regex pattern across files. Supports ripgrep when available (context lines, multiline, type filters, pagination). Falls back to JS RegExp scanner.",
|
|
4879
|
-
inputSchema:
|
|
5185
|
+
inputSchema: inputSchema9,
|
|
4880
5186
|
isConcurrencySafe: () => true,
|
|
4881
5187
|
execute: async (input, ctx) => {
|
|
4882
5188
|
if (rgAvailable && input.path !== void 0) {
|
|
@@ -5054,10 +5360,11 @@ function formatJsResults(results, mode, limit) {
|
|
|
5054
5360
|
|
|
5055
5361
|
// src/tools/webFetch.ts
|
|
5056
5362
|
init_cjs_shims();
|
|
5057
|
-
var
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5363
|
+
var import_zod15 = require("zod");
|
|
5364
|
+
init_contract();
|
|
5365
|
+
var inputSchema10 = import_zod15.z.object({
|
|
5366
|
+
url: import_zod15.z.string().url(),
|
|
5367
|
+
prompt: import_zod15.z.string().optional()
|
|
5061
5368
|
});
|
|
5062
5369
|
var MAX_OUTPUT_BYTES2 = 256 * 1024;
|
|
5063
5370
|
function createWebFetchTool(options = {}) {
|
|
@@ -5065,7 +5372,7 @@ function createWebFetchTool(options = {}) {
|
|
|
5065
5372
|
return defineTool({
|
|
5066
5373
|
name: "WebFetch",
|
|
5067
5374
|
description: "Fetch a URL and return its content as plain text. HTML is stripped to its readable text.",
|
|
5068
|
-
inputSchema:
|
|
5375
|
+
inputSchema: inputSchema10,
|
|
5069
5376
|
isConcurrencySafe: () => true,
|
|
5070
5377
|
execute: async ({ url }, ctx) => {
|
|
5071
5378
|
let response;
|
|
@@ -5123,8 +5430,8 @@ Make a new WebFetch request with the redirect URL if you want to follow it.`,
|
|
|
5123
5430
|
isError: true
|
|
5124
5431
|
};
|
|
5125
5432
|
}
|
|
5126
|
-
const
|
|
5127
|
-
const { content, truncated } = truncate(
|
|
5433
|
+
const text2 = isHtml(contentType) ? htmlToText(raw) : raw;
|
|
5434
|
+
const { content, truncated } = truncate(text2, MAX_OUTPUT_BYTES2);
|
|
5128
5435
|
return {
|
|
5129
5436
|
content,
|
|
5130
5437
|
metadata: {
|
|
@@ -5140,24 +5447,24 @@ Make a new WebFetch request with the redirect URL if you want to follow it.`,
|
|
|
5140
5447
|
function isHtml(contentType) {
|
|
5141
5448
|
return contentType.toLowerCase().includes("html");
|
|
5142
5449
|
}
|
|
5143
|
-
function htmlToText(
|
|
5144
|
-
return
|
|
5450
|
+
function htmlToText(html2) {
|
|
5451
|
+
return html2.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "").replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, "").replace(/<[^>]+>/g, " ").replace(/ /g, " ").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/[ \t]+/g, " ").replace(/\n[ \t]+/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
5145
5452
|
}
|
|
5146
|
-
function truncate(
|
|
5147
|
-
if (Buffer.byteLength(
|
|
5148
|
-
return { content:
|
|
5453
|
+
function truncate(text2, maxBytes) {
|
|
5454
|
+
if (Buffer.byteLength(text2, "utf8") <= maxBytes) {
|
|
5455
|
+
return { content: text2, truncated: false };
|
|
5149
5456
|
}
|
|
5150
5457
|
let lo = 0;
|
|
5151
|
-
let hi =
|
|
5458
|
+
let hi = text2.length;
|
|
5152
5459
|
while (lo < hi) {
|
|
5153
5460
|
const mid = lo + hi + 1 >>> 1;
|
|
5154
|
-
if (Buffer.byteLength(
|
|
5461
|
+
if (Buffer.byteLength(text2.slice(0, mid), "utf8") <= maxBytes) {
|
|
5155
5462
|
lo = mid;
|
|
5156
5463
|
} else {
|
|
5157
5464
|
hi = mid - 1;
|
|
5158
5465
|
}
|
|
5159
5466
|
}
|
|
5160
|
-
return { content:
|
|
5467
|
+
return { content: text2.slice(0, lo) + "\n... (truncated)", truncated: true };
|
|
5161
5468
|
}
|
|
5162
5469
|
async function safeText(response) {
|
|
5163
5470
|
try {
|
|
@@ -5186,16 +5493,17 @@ function normalizePath(p) {
|
|
|
5186
5493
|
|
|
5187
5494
|
// src/tools/webSearch.ts
|
|
5188
5495
|
init_cjs_shims();
|
|
5189
|
-
var
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5496
|
+
var import_zod16 = require("zod");
|
|
5497
|
+
init_contract();
|
|
5498
|
+
var inputSchema11 = import_zod16.z.object({
|
|
5499
|
+
query: import_zod16.z.string().min(2),
|
|
5500
|
+
max_results: import_zod16.z.number().int().positive().optional()
|
|
5193
5501
|
});
|
|
5194
5502
|
function createWebSearchTool() {
|
|
5195
5503
|
return defineTool({
|
|
5196
5504
|
name: "WebSearch",
|
|
5197
5505
|
description: "Search the web for information. Returns search result snippets. Use when you need current information not available in local files.",
|
|
5198
|
-
inputSchema:
|
|
5506
|
+
inputSchema: inputSchema11,
|
|
5199
5507
|
isConcurrencySafe: () => true,
|
|
5200
5508
|
execute: async ({ query }) => {
|
|
5201
5509
|
const encoded = encodeURIComponent(query);
|
|
@@ -5220,17 +5528,17 @@ function createWebSearchTool() {
|
|
|
5220
5528
|
isError: true
|
|
5221
5529
|
};
|
|
5222
5530
|
}
|
|
5223
|
-
let
|
|
5531
|
+
let html2;
|
|
5224
5532
|
try {
|
|
5225
|
-
|
|
5533
|
+
html2 = await response.text();
|
|
5226
5534
|
} catch (err) {
|
|
5227
5535
|
return {
|
|
5228
5536
|
content: `Failed to read search response: ${err.message}`,
|
|
5229
5537
|
isError: true
|
|
5230
5538
|
};
|
|
5231
5539
|
}
|
|
5232
|
-
const
|
|
5233
|
-
const trimmed =
|
|
5540
|
+
const text2 = htmlToText2(html2);
|
|
5541
|
+
const trimmed = text2.slice(0, 8e3);
|
|
5234
5542
|
return {
|
|
5235
5543
|
content: `Search results for "${query}":
|
|
5236
5544
|
|
|
@@ -5240,22 +5548,23 @@ ${trimmed}`,
|
|
|
5240
5548
|
}
|
|
5241
5549
|
});
|
|
5242
5550
|
}
|
|
5243
|
-
function htmlToText2(
|
|
5244
|
-
return
|
|
5551
|
+
function htmlToText2(html2) {
|
|
5552
|
+
return html2.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "").replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, "").replace(/<[^>]+>/g, " ").replace(/ /g, " ").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/[ \t]+/g, " ").replace(/\n[ \t]+/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
5245
5553
|
}
|
|
5246
5554
|
|
|
5247
5555
|
// src/tools/sleep.ts
|
|
5248
5556
|
init_cjs_shims();
|
|
5249
|
-
var
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5557
|
+
var import_zod17 = require("zod");
|
|
5558
|
+
init_contract();
|
|
5559
|
+
var inputSchema12 = import_zod17.z.object({
|
|
5560
|
+
durationMs: import_zod17.z.number().int().nonnegative().max(3e5),
|
|
5561
|
+
reason: import_zod17.z.string().optional()
|
|
5253
5562
|
});
|
|
5254
5563
|
function createSleepTool() {
|
|
5255
5564
|
return defineTool({
|
|
5256
5565
|
name: "Sleep",
|
|
5257
5566
|
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.",
|
|
5258
|
-
inputSchema:
|
|
5567
|
+
inputSchema: inputSchema12,
|
|
5259
5568
|
isConcurrencySafe: () => true,
|
|
5260
5569
|
execute: async ({ durationMs, reason }, ctx) => {
|
|
5261
5570
|
if (durationMs === 0) {
|
|
@@ -5289,16 +5598,17 @@ function createSleepTool() {
|
|
|
5289
5598
|
|
|
5290
5599
|
// src/tools/toolSearch.ts
|
|
5291
5600
|
init_cjs_shims();
|
|
5292
|
-
var
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5601
|
+
var import_zod18 = require("zod");
|
|
5602
|
+
init_contract();
|
|
5603
|
+
var inputSchema13 = import_zod18.z.object({
|
|
5604
|
+
query: import_zod18.z.string().min(1),
|
|
5605
|
+
max_results: import_zod18.z.number().int().positive().optional()
|
|
5296
5606
|
});
|
|
5297
5607
|
function createToolSearchTool(registry) {
|
|
5298
5608
|
return defineTool({
|
|
5299
5609
|
name: "ToolSearch",
|
|
5300
5610
|
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.",
|
|
5301
|
-
inputSchema:
|
|
5611
|
+
inputSchema: inputSchema13,
|
|
5302
5612
|
isConcurrencySafe: () => true,
|
|
5303
5613
|
execute: async ({ query, max_results }) => {
|
|
5304
5614
|
const limit = max_results ?? 10;
|
|
@@ -5335,18 +5645,19 @@ ${lines.join("\n")}`,
|
|
|
5335
5645
|
|
|
5336
5646
|
// src/tools/memorize.ts
|
|
5337
5647
|
init_cjs_shims();
|
|
5338
|
-
var
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5648
|
+
var import_zod19 = require("zod");
|
|
5649
|
+
init_contract();
|
|
5650
|
+
var inputSchema14 = import_zod19.z.object({
|
|
5651
|
+
text: import_zod19.z.string().min(1),
|
|
5652
|
+
kind: import_zod19.z.enum(["rule", "lesson"]).default("lesson"),
|
|
5653
|
+
topic: import_zod19.z.string().optional()
|
|
5343
5654
|
});
|
|
5344
5655
|
function createMemorizeTool(memory) {
|
|
5345
5656
|
return defineTool({
|
|
5346
5657
|
name: "Memorize",
|
|
5347
5658
|
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.',
|
|
5348
|
-
inputSchema:
|
|
5349
|
-
execute: async ({ text, kind, topic }) => {
|
|
5659
|
+
inputSchema: inputSchema14,
|
|
5660
|
+
execute: async ({ text: text2, kind, topic }) => {
|
|
5350
5661
|
if (memory.mode === "off" || memory.mode === "read-only") {
|
|
5351
5662
|
return {
|
|
5352
5663
|
content: `Cannot memorize: memory mode is "${memory.mode}". Set config.memory.mode to "read-write" to enable.`,
|
|
@@ -5354,15 +5665,15 @@ function createMemorizeTool(memory) {
|
|
|
5354
5665
|
};
|
|
5355
5666
|
}
|
|
5356
5667
|
if (kind === "rule") {
|
|
5357
|
-
await memory.encodeRule(
|
|
5668
|
+
await memory.encodeRule(text2, "always");
|
|
5358
5669
|
return {
|
|
5359
|
-
content: `Memorized rule: "${
|
|
5670
|
+
content: `Memorized rule: "${text2.slice(0, 80)}${text2.length > 80 ? "\u2026" : ""}"`,
|
|
5360
5671
|
metadata: { kind: "rule" }
|
|
5361
5672
|
};
|
|
5362
5673
|
}
|
|
5363
|
-
await memory.encodeLesson(
|
|
5674
|
+
await memory.encodeLesson(text2, topic);
|
|
5364
5675
|
return {
|
|
5365
|
-
content: `Memorized lesson: "${
|
|
5676
|
+
content: `Memorized lesson: "${text2.slice(0, 80)}${text2.length > 80 ? "\u2026" : ""}"${topic ? ` (topic: ${topic})` : ""}`,
|
|
5366
5677
|
metadata: { kind: "lesson", topic }
|
|
5367
5678
|
};
|
|
5368
5679
|
}
|
|
@@ -5371,17 +5682,18 @@ function createMemorizeTool(memory) {
|
|
|
5371
5682
|
|
|
5372
5683
|
// src/tools/recall.ts
|
|
5373
5684
|
init_cjs_shims();
|
|
5374
|
-
var
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5685
|
+
var import_zod20 = require("zod");
|
|
5686
|
+
init_contract();
|
|
5687
|
+
var inputSchema15 = import_zod20.z.object({
|
|
5688
|
+
query: import_zod20.z.string().min(1),
|
|
5689
|
+
scope: import_zod20.z.enum(["identity", "rules", "lessons", "all"]).default("all"),
|
|
5690
|
+
topic: import_zod20.z.string().optional()
|
|
5379
5691
|
});
|
|
5380
5692
|
function createRecallTool(memory) {
|
|
5381
5693
|
return defineTool({
|
|
5382
5694
|
name: "Recall",
|
|
5383
5695
|
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.",
|
|
5384
|
-
inputSchema:
|
|
5696
|
+
inputSchema: inputSchema15,
|
|
5385
5697
|
isConcurrencySafe: () => true,
|
|
5386
5698
|
execute: async ({ query, scope, topic }) => {
|
|
5387
5699
|
if (memory.mode === "off") {
|
|
@@ -5430,19 +5742,20 @@ ${content}`,
|
|
|
5430
5742
|
|
|
5431
5743
|
// src/tools/notebookEdit.ts
|
|
5432
5744
|
init_cjs_shims();
|
|
5433
|
-
var
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5745
|
+
var import_zod21 = require("zod");
|
|
5746
|
+
init_contract();
|
|
5747
|
+
var inputSchema16 = import_zod21.z.object({
|
|
5748
|
+
notebook_path: import_zod21.z.string().min(1),
|
|
5749
|
+
edit_mode: import_zod21.z.enum(["replace", "insert", "delete"]).default("replace"),
|
|
5750
|
+
cell_index: import_zod21.z.number().int().nonnegative(),
|
|
5751
|
+
new_source: import_zod21.z.string().optional(),
|
|
5752
|
+
cell_type: import_zod21.z.enum(["code", "markdown"]).optional()
|
|
5440
5753
|
});
|
|
5441
5754
|
function createNotebookEditTool(storage) {
|
|
5442
5755
|
return defineTool({
|
|
5443
5756
|
name: "NotebookEdit",
|
|
5444
5757
|
description: "Edit a Jupyter notebook (.ipynb) by inserting, replacing, or deleting cells. Specify the cell_index (0-based) and the operation.",
|
|
5445
|
-
inputSchema:
|
|
5758
|
+
inputSchema: inputSchema16,
|
|
5446
5759
|
execute: async ({
|
|
5447
5760
|
notebook_path,
|
|
5448
5761
|
edit_mode,
|
|
@@ -5591,12 +5904,13 @@ var TaskStore = class {
|
|
|
5591
5904
|
|
|
5592
5905
|
// src/tools/tasks/tools.ts
|
|
5593
5906
|
init_cjs_shims();
|
|
5594
|
-
var
|
|
5595
|
-
|
|
5596
|
-
var
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5907
|
+
var import_zod22 = require("zod");
|
|
5908
|
+
init_contract();
|
|
5909
|
+
var TaskStatusEnum = import_zod22.z.enum(["pending", "in_progress", "completed", "deleted"]);
|
|
5910
|
+
var createSchema = import_zod22.z.object({
|
|
5911
|
+
subject: import_zod22.z.string().min(1),
|
|
5912
|
+
description: import_zod22.z.string().default(""),
|
|
5913
|
+
metadata: import_zod22.z.record(import_zod22.z.unknown()).optional()
|
|
5600
5914
|
});
|
|
5601
5915
|
function createTaskCreateTool(store) {
|
|
5602
5916
|
return defineTool({
|
|
@@ -5612,8 +5926,8 @@ function createTaskCreateTool(store) {
|
|
|
5612
5926
|
}
|
|
5613
5927
|
});
|
|
5614
5928
|
}
|
|
5615
|
-
var getSchema =
|
|
5616
|
-
taskId:
|
|
5929
|
+
var getSchema = import_zod22.z.object({
|
|
5930
|
+
taskId: import_zod22.z.string().min(1)
|
|
5617
5931
|
});
|
|
5618
5932
|
function createTaskGetTool(store) {
|
|
5619
5933
|
return defineTool({
|
|
@@ -5634,7 +5948,7 @@ ${task.description}`,
|
|
|
5634
5948
|
}
|
|
5635
5949
|
});
|
|
5636
5950
|
}
|
|
5637
|
-
var listSchema =
|
|
5951
|
+
var listSchema = import_zod22.z.object({
|
|
5638
5952
|
status: TaskStatusEnum.optional()
|
|
5639
5953
|
});
|
|
5640
5954
|
function createTaskListTool(store) {
|
|
@@ -5660,12 +5974,12 @@ ${lines.join("\n")}`,
|
|
|
5660
5974
|
}
|
|
5661
5975
|
});
|
|
5662
5976
|
}
|
|
5663
|
-
var updateSchema =
|
|
5664
|
-
taskId:
|
|
5665
|
-
subject:
|
|
5977
|
+
var updateSchema = import_zod22.z.object({
|
|
5978
|
+
taskId: import_zod22.z.string().min(1),
|
|
5979
|
+
subject: import_zod22.z.string().min(1).optional(),
|
|
5666
5980
|
status: TaskStatusEnum.optional(),
|
|
5667
|
-
description:
|
|
5668
|
-
metadata:
|
|
5981
|
+
description: import_zod22.z.string().optional(),
|
|
5982
|
+
metadata: import_zod22.z.record(import_zod22.z.unknown()).optional()
|
|
5669
5983
|
});
|
|
5670
5984
|
function createTaskUpdateTool(store) {
|
|
5671
5985
|
return defineTool({
|
|
@@ -6036,17 +6350,17 @@ var BindingHttpTransport = class {
|
|
|
6036
6350
|
}
|
|
6037
6351
|
if (response.status === 202 || response.status === 204) return;
|
|
6038
6352
|
if (!response.ok) {
|
|
6039
|
-
const
|
|
6353
|
+
const text2 = await safeText2(response);
|
|
6040
6354
|
const err = new Error(
|
|
6041
|
-
`BindingHttpTransport: HTTP ${String(response.status)} ${response.statusText}${
|
|
6355
|
+
`BindingHttpTransport: HTTP ${String(response.status)} ${response.statusText}${text2 ? ` \u2014 ${text2}` : ""}`
|
|
6042
6356
|
);
|
|
6043
6357
|
this.onerror?.(err);
|
|
6044
6358
|
throw err;
|
|
6045
6359
|
}
|
|
6046
6360
|
const contentType = response.headers.get("Content-Type") ?? "";
|
|
6047
6361
|
if (!contentType.includes("application/json")) {
|
|
6048
|
-
const
|
|
6049
|
-
const parsed2 = parseSseFrames(
|
|
6362
|
+
const text2 = await response.text();
|
|
6363
|
+
const parsed2 = parseSseFrames(text2);
|
|
6050
6364
|
for (const msg of parsed2) this.onmessage?.(msg);
|
|
6051
6365
|
return;
|
|
6052
6366
|
}
|
|
@@ -6113,9 +6427,9 @@ async function safeText2(r) {
|
|
|
6113
6427
|
return "";
|
|
6114
6428
|
}
|
|
6115
6429
|
}
|
|
6116
|
-
function parseSseFrames(
|
|
6430
|
+
function parseSseFrames(text2) {
|
|
6117
6431
|
const out = [];
|
|
6118
|
-
for (const block of
|
|
6432
|
+
for (const block of text2.split(/\r?\n\r?\n/)) {
|
|
6119
6433
|
const lines = block.split(/\r?\n/).filter((l) => l.startsWith("data:"));
|
|
6120
6434
|
if (lines.length === 0) continue;
|
|
6121
6435
|
const raw = lines.map((l) => l.slice(5).trimStart()).join("\n");
|
|
@@ -6402,8 +6716,8 @@ function normalizeToolList(response, serverName) {
|
|
|
6402
6716
|
const name = typeof obj.name === "string" ? obj.name : null;
|
|
6403
6717
|
if (name === null) continue;
|
|
6404
6718
|
const description = typeof obj.description === "string" ? obj.description : "";
|
|
6405
|
-
const
|
|
6406
|
-
out.push({ name, description, inputSchema:
|
|
6719
|
+
const inputSchema20 = obj.inputSchema !== null && typeof obj.inputSchema === "object" && !Array.isArray(obj.inputSchema) ? obj.inputSchema : { type: "object", properties: {} };
|
|
6720
|
+
out.push({ name, description, inputSchema: inputSchema20 });
|
|
6407
6721
|
}
|
|
6408
6722
|
return out;
|
|
6409
6723
|
}
|
|
@@ -6512,7 +6826,8 @@ function wrapFetchWithHeadersProvider(baseFetch, headersProvider, staticHeaders)
|
|
|
6512
6826
|
|
|
6513
6827
|
// src/mcp/toolAdapter.ts
|
|
6514
6828
|
init_cjs_shims();
|
|
6515
|
-
var
|
|
6829
|
+
var import_zod23 = require("zod");
|
|
6830
|
+
init_contract();
|
|
6516
6831
|
function mcpToolName(serverName, toolName) {
|
|
6517
6832
|
return `mcp__${serverName}__${toolName}`;
|
|
6518
6833
|
}
|
|
@@ -6521,7 +6836,7 @@ function adaptMcpTool(client, serverName, def) {
|
|
|
6521
6836
|
return defineTool({
|
|
6522
6837
|
name: registeredName,
|
|
6523
6838
|
description: def.description.length > 0 ? def.description : `MCP tool ${serverName}/${def.name}`,
|
|
6524
|
-
inputSchema:
|
|
6839
|
+
inputSchema: import_zod23.z.unknown(),
|
|
6525
6840
|
// Pass the MCP server's JSON Schema through to Anthropic verbatim,
|
|
6526
6841
|
// bypassing Zod-to-JSON-Schema conversion (which would produce `{}`
|
|
6527
6842
|
// for our `z.unknown()` Zod schema).
|
|
@@ -7053,15 +7368,15 @@ var Hippocampus = class _Hippocampus {
|
|
|
7053
7368
|
return (content ?? "").trim();
|
|
7054
7369
|
}
|
|
7055
7370
|
// ---------- encode (write) ----------
|
|
7056
|
-
async encodeRule(
|
|
7371
|
+
async encodeRule(text2, kind, confidence = "medium", source = "llm") {
|
|
7057
7372
|
const ts = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
7058
7373
|
const metadata = `<!-- confidence:${confidence} source:${source} ts:${ts} -->`;
|
|
7059
|
-
const entry = `- ${
|
|
7374
|
+
const entry = `- ${text2} ${metadata}
|
|
7060
7375
|
`;
|
|
7061
7376
|
const sectionHeader = `## ${kind.charAt(0).toUpperCase()}${kind.slice(1)}`;
|
|
7062
7377
|
let content = await this.storage.readFile(this.rulesPath);
|
|
7063
7378
|
if (content === null) content = RULES_SKELETON;
|
|
7064
|
-
if (_Hippocampus.extractEntryTexts(content).has(
|
|
7379
|
+
if (_Hippocampus.extractEntryTexts(content).has(text2)) return;
|
|
7065
7380
|
const lines = content.split(/(?<=\n)/);
|
|
7066
7381
|
const out = [];
|
|
7067
7382
|
let inserted = false;
|
|
@@ -7094,17 +7409,17 @@ ${entry}`);
|
|
|
7094
7409
|
}
|
|
7095
7410
|
await this.storage.writeFile(this.rulesPath, out.join(""));
|
|
7096
7411
|
}
|
|
7097
|
-
async encodeLesson(
|
|
7412
|
+
async encodeLesson(text2, topic = "", source = "llm") {
|
|
7098
7413
|
const ts = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
7099
7414
|
const topicTag = topic ? ` topic:${topic}` : "";
|
|
7100
7415
|
const sourceTag = source !== "llm" ? ` source:${source}` : "";
|
|
7101
|
-
const entry = `- ${
|
|
7416
|
+
const entry = `- ${text2} <!--${topicTag}${sourceTag} ts:${ts} -->
|
|
7102
7417
|
`;
|
|
7103
7418
|
const existing = await this.storage.readFile(this.lessonsPath);
|
|
7104
7419
|
if (existing === null) {
|
|
7105
7420
|
await this.storage.writeFile(this.lessonsPath, `# Lessons
|
|
7106
7421
|
${entry}`);
|
|
7107
|
-
} else if (!_Hippocampus.extractEntryTexts(existing).has(
|
|
7422
|
+
} else if (!_Hippocampus.extractEntryTexts(existing).has(text2)) {
|
|
7108
7423
|
await this.storage.appendFile(this.lessonsPath, entry);
|
|
7109
7424
|
}
|
|
7110
7425
|
if (topic) {
|
|
@@ -7114,7 +7429,7 @@ ${entry}`);
|
|
|
7114
7429
|
if (topicContent === null) {
|
|
7115
7430
|
await this.storage.writeFile(topicPath, `# ${topic}
|
|
7116
7431
|
${entry}`);
|
|
7117
|
-
} else if (!_Hippocampus.extractEntryTexts(topicContent).has(
|
|
7432
|
+
} else if (!_Hippocampus.extractEntryTexts(topicContent).has(text2)) {
|
|
7118
7433
|
await this.storage.appendFile(topicPath, entry);
|
|
7119
7434
|
}
|
|
7120
7435
|
}
|
|
@@ -7170,12 +7485,12 @@ ${entries.map((e) => `- ${e}`).join("\n")}
|
|
|
7170
7485
|
}
|
|
7171
7486
|
/** Sanitize a topic name into a safe file slug. */
|
|
7172
7487
|
static sanitizeSlug(name) {
|
|
7173
|
-
let
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
return
|
|
7488
|
+
let text2 = name.toLowerCase().trim();
|
|
7489
|
+
text2 = text2.replace(/[^a-z0-9\s_-]/g, "");
|
|
7490
|
+
text2 = text2.replace(/\s+/g, "-");
|
|
7491
|
+
text2 = text2.replace(/-+/g, "-");
|
|
7492
|
+
text2 = text2.replace(/^-|-$/g, "");
|
|
7493
|
+
return text2.length > 0 ? text2 : "general";
|
|
7179
7494
|
}
|
|
7180
7495
|
};
|
|
7181
7496
|
|
|
@@ -7207,13 +7522,13 @@ function createSmartMemory(options) {
|
|
|
7207
7522
|
if (!readsEnabled) return "";
|
|
7208
7523
|
return hippocampus.recallTopic(slug);
|
|
7209
7524
|
},
|
|
7210
|
-
async encodeRule(
|
|
7525
|
+
async encodeRule(text2, kind, confidence, source) {
|
|
7211
7526
|
if (!writesEnabled) return;
|
|
7212
|
-
await hippocampus.encodeRule(
|
|
7527
|
+
await hippocampus.encodeRule(text2, kind, confidence, source);
|
|
7213
7528
|
},
|
|
7214
|
-
async encodeLesson(
|
|
7529
|
+
async encodeLesson(text2, topic, source) {
|
|
7215
7530
|
if (!writesEnabled) return;
|
|
7216
|
-
await hippocampus.encodeLesson(
|
|
7531
|
+
await hippocampus.encodeLesson(text2, topic, source);
|
|
7217
7532
|
},
|
|
7218
7533
|
async rewriteIdentity(entries) {
|
|
7219
7534
|
if (!writesEnabled) return;
|
|
@@ -7579,8 +7894,8 @@ function buildSchemaPrompt(schema) {
|
|
|
7579
7894
|
}
|
|
7580
7895
|
return lines.join("\n");
|
|
7581
7896
|
}
|
|
7582
|
-
function
|
|
7583
|
-
const trimmed =
|
|
7897
|
+
function tryParseJSON2(text2) {
|
|
7898
|
+
const trimmed = text2.trim();
|
|
7584
7899
|
try {
|
|
7585
7900
|
return { ok: true, value: JSON.parse(trimmed) };
|
|
7586
7901
|
} catch {
|
|
@@ -7619,17 +7934,18 @@ ${issues.join("\n")}` };
|
|
|
7619
7934
|
|
|
7620
7935
|
// src/skills/skillPage.ts
|
|
7621
7936
|
init_cjs_shims();
|
|
7622
|
-
var
|
|
7937
|
+
var import_zod24 = require("zod");
|
|
7938
|
+
init_contract();
|
|
7623
7939
|
var SAFE_NAME3 = /^[a-zA-Z0-9_-]+$/;
|
|
7624
|
-
var
|
|
7625
|
-
skill:
|
|
7626
|
-
page:
|
|
7940
|
+
var inputSchema17 = import_zod24.z.object({
|
|
7941
|
+
skill: import_zod24.z.string().min(1),
|
|
7942
|
+
page: import_zod24.z.string().min(1).optional()
|
|
7627
7943
|
});
|
|
7628
7944
|
function createSkillPageTool(options) {
|
|
7629
7945
|
return defineTool({
|
|
7630
7946
|
name: "SkillPage",
|
|
7631
7947
|
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.",
|
|
7632
|
-
inputSchema:
|
|
7948
|
+
inputSchema: inputSchema17,
|
|
7633
7949
|
execute: async ({ skill, page }) => {
|
|
7634
7950
|
if (!SAFE_NAME3.test(skill)) {
|
|
7635
7951
|
return {
|
|
@@ -7681,7 +7997,8 @@ The skill "${skill}" has no pages.`;
|
|
|
7681
7997
|
|
|
7682
7998
|
// src/tools/apiCall.ts
|
|
7683
7999
|
init_cjs_shims();
|
|
7684
|
-
var
|
|
8000
|
+
var import_zod25 = require("zod");
|
|
8001
|
+
init_contract();
|
|
7685
8002
|
var ALL_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
7686
8003
|
var DEFAULT_MAX_BODY_BYTES = 256 * 1024;
|
|
7687
8004
|
var DEFAULT_MAX_RESPONSE_BYTES = 100 * 1024;
|
|
@@ -7706,19 +8023,19 @@ function createApiCallTool(opts) {
|
|
|
7706
8023
|
}
|
|
7707
8024
|
const fetchFn = opts.fetch ?? globalThis.fetch.bind(globalThis);
|
|
7708
8025
|
const maxResponseBytes = opts.maxResponseBytes ?? DEFAULT_MAX_RESPONSE_BYTES;
|
|
7709
|
-
const
|
|
7710
|
-
service:
|
|
7711
|
-
method:
|
|
7712
|
-
path:
|
|
7713
|
-
query:
|
|
7714
|
-
body:
|
|
7715
|
-
headers:
|
|
8026
|
+
const inputSchema20 = import_zod25.z.object({
|
|
8027
|
+
service: import_zod25.z.enum(serviceNames),
|
|
8028
|
+
method: import_zod25.z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]),
|
|
8029
|
+
path: import_zod25.z.string().regex(/^\//, "path must start with /"),
|
|
8030
|
+
query: import_zod25.z.record(import_zod25.z.string(), import_zod25.z.string()).optional(),
|
|
8031
|
+
body: import_zod25.z.unknown().optional(),
|
|
8032
|
+
headers: import_zod25.z.record(import_zod25.z.string(), import_zod25.z.string()).optional()
|
|
7716
8033
|
});
|
|
7717
8034
|
const description = opts.toolDescription ?? `Call a configured external API. Services: ${serviceNames.join(", ")}. Auth is injected automatically \u2014 do not pass credentials via headers.`;
|
|
7718
8035
|
return defineTool({
|
|
7719
8036
|
name: opts.toolName ?? "ApiCall",
|
|
7720
8037
|
description,
|
|
7721
|
-
inputSchema:
|
|
8038
|
+
inputSchema: inputSchema20,
|
|
7722
8039
|
execute: async (input) => {
|
|
7723
8040
|
const svc = services.get(input.service);
|
|
7724
8041
|
if (!svc) {
|
|
@@ -7737,7 +8054,7 @@ function createApiCallTool(opts) {
|
|
|
7737
8054
|
if (input.body !== void 0) {
|
|
7738
8055
|
bodyText = JSON.stringify(input.body);
|
|
7739
8056
|
const cap = svc.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES;
|
|
7740
|
-
if (
|
|
8057
|
+
if (byteLength2(bodyText) > cap) {
|
|
7741
8058
|
return errResult(`ERR_API_BODY_TOO_LARGE: exceeds ${cap} bytes`);
|
|
7742
8059
|
}
|
|
7743
8060
|
}
|
|
@@ -7811,7 +8128,7 @@ function pathAllowed(path, allowed) {
|
|
|
7811
8128
|
}
|
|
7812
8129
|
return false;
|
|
7813
8130
|
}
|
|
7814
|
-
function
|
|
8131
|
+
function byteLength2(s) {
|
|
7815
8132
|
return new TextEncoder().encode(s).byteLength;
|
|
7816
8133
|
}
|
|
7817
8134
|
function buildUrl(baseUrl, path, query) {
|
|
@@ -7876,6 +8193,572 @@ async function invokeHook(hook, event) {
|
|
|
7876
8193
|
}
|
|
7877
8194
|
}
|
|
7878
8195
|
|
|
8196
|
+
// src/engine/engine.ts
|
|
8197
|
+
init_fetchData();
|
|
8198
|
+
|
|
8199
|
+
// src/tools/searchKnowledge.ts
|
|
8200
|
+
init_cjs_shims();
|
|
8201
|
+
var import_zod26 = require("zod");
|
|
8202
|
+
init_contract();
|
|
8203
|
+
|
|
8204
|
+
// src/knowledge/scope.ts
|
|
8205
|
+
init_cjs_shims();
|
|
8206
|
+
var SAFE_PATH_RE = /^[a-zA-Z0-9_\-./]+$/;
|
|
8207
|
+
function parseFolderRef(raw) {
|
|
8208
|
+
if (typeof raw !== "string" || raw.length === 0) {
|
|
8209
|
+
throw new Error(`invalid knowledge folder ref: empty`);
|
|
8210
|
+
}
|
|
8211
|
+
if (raw.startsWith("/")) {
|
|
8212
|
+
throw new Error(`invalid knowledge folder ref: absolute paths not allowed ("${raw}")`);
|
|
8213
|
+
}
|
|
8214
|
+
const trimmed = raw.replace(/\/+$/g, "");
|
|
8215
|
+
if (trimmed.length === 0) {
|
|
8216
|
+
throw new Error(`invalid knowledge folder ref: "${raw}"`);
|
|
8217
|
+
}
|
|
8218
|
+
if (!SAFE_PATH_RE.test(trimmed)) {
|
|
8219
|
+
throw new Error(`invalid knowledge folder ref: unsafe characters in "${raw}"`);
|
|
8220
|
+
}
|
|
8221
|
+
if (trimmed.split("/").some((seg) => seg === ".." || seg === "." || seg === "")) {
|
|
8222
|
+
throw new Error(`invalid knowledge folder ref: traversal in "${raw}"`);
|
|
8223
|
+
}
|
|
8224
|
+
const segs = trimmed.split("/");
|
|
8225
|
+
const base = segs[0];
|
|
8226
|
+
const subPath = segs.slice(1).join("/");
|
|
8227
|
+
return { path: trimmed, base, subPath };
|
|
8228
|
+
}
|
|
8229
|
+
function relPathInScope(folder, relPath) {
|
|
8230
|
+
if (folder.subPath === "") return true;
|
|
8231
|
+
return relPath === folder.subPath || relPath.startsWith(`${folder.subPath}/`);
|
|
8232
|
+
}
|
|
8233
|
+
function parseKnowledgeRef(raw) {
|
|
8234
|
+
if (typeof raw !== "string" || raw.length === 0) {
|
|
8235
|
+
throw new Error("invalid knowledge ref: empty");
|
|
8236
|
+
}
|
|
8237
|
+
if (raw.startsWith("ext:")) {
|
|
8238
|
+
const name = raw.slice("ext:".length);
|
|
8239
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(name) || name.length === 0) {
|
|
8240
|
+
throw new Error(`invalid knowledge ref: external name "${name}" has unsafe characters`);
|
|
8241
|
+
}
|
|
8242
|
+
return { kind: "ext", target: name };
|
|
8243
|
+
}
|
|
8244
|
+
if (raw.startsWith("/")) {
|
|
8245
|
+
throw new Error(`invalid knowledge ref: absolute paths not allowed ("${raw}")`);
|
|
8246
|
+
}
|
|
8247
|
+
const hashAt = raw.indexOf("#");
|
|
8248
|
+
const filePath = hashAt === -1 ? raw : raw.slice(0, hashAt);
|
|
8249
|
+
const section = hashAt === -1 ? void 0 : raw.slice(hashAt + 1);
|
|
8250
|
+
if (!SAFE_PATH_RE.test(filePath)) {
|
|
8251
|
+
throw new Error(`invalid knowledge ref: unsafe characters in "${filePath}"`);
|
|
8252
|
+
}
|
|
8253
|
+
if (filePath.split("/").some((seg) => seg === ".." || seg === "." || seg === "")) {
|
|
8254
|
+
throw new Error(`invalid knowledge ref: traversal in "${filePath}"`);
|
|
8255
|
+
}
|
|
8256
|
+
if (section !== void 0) {
|
|
8257
|
+
if (section.length > 0 && !/^[a-zA-Z0-9_-]+$/.test(section)) {
|
|
8258
|
+
throw new Error(`invalid knowledge ref: unsafe characters in section "${section}"`);
|
|
8259
|
+
}
|
|
8260
|
+
return { kind: "section", target: filePath, section };
|
|
8261
|
+
}
|
|
8262
|
+
return { kind: "file", target: filePath };
|
|
8263
|
+
}
|
|
8264
|
+
function refInScope(folders, filePath) {
|
|
8265
|
+
return folders.some((f) => {
|
|
8266
|
+
if (filePath === f.base || filePath.startsWith(`${f.base}/`)) {
|
|
8267
|
+
const relInBase = filePath === f.base ? "" : filePath.slice(f.base.length + 1);
|
|
8268
|
+
return relPathInScope(f, relInBase);
|
|
8269
|
+
}
|
|
8270
|
+
return false;
|
|
8271
|
+
});
|
|
8272
|
+
}
|
|
8273
|
+
|
|
8274
|
+
// src/knowledge/tokenize.ts
|
|
8275
|
+
init_cjs_shims();
|
|
8276
|
+
var STOP_WORDS = /* @__PURE__ */ new Set([
|
|
8277
|
+
"the",
|
|
8278
|
+
"and",
|
|
8279
|
+
"of",
|
|
8280
|
+
"to",
|
|
8281
|
+
"a",
|
|
8282
|
+
"in",
|
|
8283
|
+
"is",
|
|
8284
|
+
"it",
|
|
8285
|
+
"you",
|
|
8286
|
+
"that",
|
|
8287
|
+
"was",
|
|
8288
|
+
"for",
|
|
8289
|
+
"on",
|
|
8290
|
+
"are",
|
|
8291
|
+
"with",
|
|
8292
|
+
"as",
|
|
8293
|
+
"this",
|
|
8294
|
+
"by",
|
|
8295
|
+
"from",
|
|
8296
|
+
"or",
|
|
8297
|
+
"but",
|
|
8298
|
+
"not",
|
|
8299
|
+
"all",
|
|
8300
|
+
"an",
|
|
8301
|
+
"has",
|
|
8302
|
+
"have",
|
|
8303
|
+
"had",
|
|
8304
|
+
"will",
|
|
8305
|
+
"can",
|
|
8306
|
+
"do",
|
|
8307
|
+
"did",
|
|
8308
|
+
"be",
|
|
8309
|
+
"been",
|
|
8310
|
+
"being",
|
|
8311
|
+
"your",
|
|
8312
|
+
"our",
|
|
8313
|
+
"their",
|
|
8314
|
+
"his",
|
|
8315
|
+
"her",
|
|
8316
|
+
"my",
|
|
8317
|
+
"we",
|
|
8318
|
+
"they",
|
|
8319
|
+
"them",
|
|
8320
|
+
"than",
|
|
8321
|
+
"so",
|
|
8322
|
+
"if",
|
|
8323
|
+
"at",
|
|
8324
|
+
"no",
|
|
8325
|
+
"yes",
|
|
8326
|
+
"me",
|
|
8327
|
+
"us",
|
|
8328
|
+
"i",
|
|
8329
|
+
"he",
|
|
8330
|
+
"she"
|
|
8331
|
+
]);
|
|
8332
|
+
function tokenize(text2) {
|
|
8333
|
+
if (typeof text2 !== "string" || text2.length === 0) return [];
|
|
8334
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8335
|
+
for (const raw of text2.toLowerCase().split(/[\W_]+/)) {
|
|
8336
|
+
if (raw.length < 2) continue;
|
|
8337
|
+
if (STOP_WORDS.has(raw)) continue;
|
|
8338
|
+
seen.add(raw);
|
|
8339
|
+
}
|
|
8340
|
+
return [...seen].sort();
|
|
8341
|
+
}
|
|
8342
|
+
function scoreOverlap(sectionWords, queryTokens) {
|
|
8343
|
+
const set = sectionWords instanceof Set ? sectionWords : new Set(sectionWords);
|
|
8344
|
+
let n = 0;
|
|
8345
|
+
for (const t of queryTokens) if (set.has(t)) n++;
|
|
8346
|
+
return n;
|
|
8347
|
+
}
|
|
8348
|
+
|
|
8349
|
+
// src/tools/searchKnowledge.ts
|
|
8350
|
+
var DEFAULT_MAX_RESULTS = 5;
|
|
8351
|
+
var inputSchema18 = import_zod26.z.object({
|
|
8352
|
+
query: import_zod26.z.string().min(1),
|
|
8353
|
+
maxResults: import_zod26.z.number().int().positive().optional()
|
|
8354
|
+
});
|
|
8355
|
+
function createSearchKnowledgeTool(opts) {
|
|
8356
|
+
const scoped = opts.folders.map(parseFolderRef);
|
|
8357
|
+
const indexCache = /* @__PURE__ */ new Map();
|
|
8358
|
+
const cap = opts.maxSearchResults ?? DEFAULT_MAX_RESULTS;
|
|
8359
|
+
const externals = opts.external;
|
|
8360
|
+
return defineTool({
|
|
8361
|
+
name: "SearchKnowledge",
|
|
8362
|
+
description: "Search the agent's knowledge base. Returns up to K ranked snippets matching the query (across all configured knowledge folders + any attached external file links). Each result carries a `ref` you can pass back to the `ReadKnowledge` tool to load the full content of that section or file.",
|
|
8363
|
+
inputSchema: inputSchema18,
|
|
8364
|
+
execute: async ({ query, maxResults }) => {
|
|
8365
|
+
const limit = Math.min(maxResults ?? cap, cap);
|
|
8366
|
+
const queryTokens = tokenize(query);
|
|
8367
|
+
if (queryTokens.length === 0) {
|
|
8368
|
+
return { content: "no searchable tokens in query", isError: false };
|
|
8369
|
+
}
|
|
8370
|
+
const sectionHits = [];
|
|
8371
|
+
const seenBases = /* @__PURE__ */ new Set();
|
|
8372
|
+
for (const folder of scoped) {
|
|
8373
|
+
if (!seenBases.has(folder.base)) {
|
|
8374
|
+
seenBases.add(folder.base);
|
|
8375
|
+
}
|
|
8376
|
+
}
|
|
8377
|
+
for (const baseName of seenBases) {
|
|
8378
|
+
const idx = await loadIndex(opts.adapter, baseName, indexCache);
|
|
8379
|
+
if (idx === null) continue;
|
|
8380
|
+
for (const section of idx.sections) {
|
|
8381
|
+
const eligible = scoped.some(
|
|
8382
|
+
(f) => f.base === baseName && relPathInScope(f, section.relPath)
|
|
8383
|
+
);
|
|
8384
|
+
if (!eligible) continue;
|
|
8385
|
+
const score = scoreOverlap(section.words, queryTokens);
|
|
8386
|
+
if (score > 0) sectionHits.push({ section, base: baseName, score });
|
|
8387
|
+
}
|
|
8388
|
+
}
|
|
8389
|
+
const externalHits = [];
|
|
8390
|
+
for (const link of externals) {
|
|
8391
|
+
const score = scoreOverlap(tokenize(link.description), queryTokens);
|
|
8392
|
+
if (score > 0) externalHits.push({ link, score });
|
|
8393
|
+
}
|
|
8394
|
+
const all = [
|
|
8395
|
+
...sectionHits.map((h) => ({
|
|
8396
|
+
kind: "knowledge",
|
|
8397
|
+
score: h.score,
|
|
8398
|
+
render: () => `[knowledge] ${h.base}/${h.section.relPath} \xA7"${h.section.heading || "(lead-in)"}"
|
|
8399
|
+
${truncatePreview(h.section.preview)}
|
|
8400
|
+
ref: ${h.base}/${h.section.slug}`
|
|
8401
|
+
})),
|
|
8402
|
+
...externalHits.map((h) => ({
|
|
8403
|
+
kind: "external",
|
|
8404
|
+
score: h.score,
|
|
8405
|
+
render: () => `[external] ${h.link.name} (${h.link.format})
|
|
8406
|
+
${h.link.description}
|
|
8407
|
+
ref: ext:${h.link.name}`
|
|
8408
|
+
}))
|
|
8409
|
+
];
|
|
8410
|
+
if (all.length === 0) {
|
|
8411
|
+
return { content: `no knowledge matches for "${query}"`, isError: false };
|
|
8412
|
+
}
|
|
8413
|
+
all.sort((a, b) => b.score - a.score);
|
|
8414
|
+
const top = all.slice(0, limit);
|
|
8415
|
+
const body = top.map((h, i) => `${i + 1}. ${h.render()}`).join("\n\n");
|
|
8416
|
+
return {
|
|
8417
|
+
content: `Found ${top.length} knowledge match${top.length === 1 ? "" : "es"} (of ${all.length} ranked):
|
|
8418
|
+
|
|
8419
|
+
${body}`,
|
|
8420
|
+
isError: false,
|
|
8421
|
+
metadata: { hits: all.length, returned: top.length }
|
|
8422
|
+
};
|
|
8423
|
+
}
|
|
8424
|
+
});
|
|
8425
|
+
}
|
|
8426
|
+
function truncatePreview(s) {
|
|
8427
|
+
if (s.length <= 200) return s;
|
|
8428
|
+
return s.slice(0, 200) + "\u2026";
|
|
8429
|
+
}
|
|
8430
|
+
async function loadIndex(adapter, base, cache) {
|
|
8431
|
+
const cached2 = cache.get(base);
|
|
8432
|
+
if (cached2 !== void 0) return cached2;
|
|
8433
|
+
let raw;
|
|
8434
|
+
try {
|
|
8435
|
+
raw = await adapter.readFile(`${base}/_index.json`);
|
|
8436
|
+
} catch {
|
|
8437
|
+
return null;
|
|
8438
|
+
}
|
|
8439
|
+
if (raw === null) return null;
|
|
8440
|
+
try {
|
|
8441
|
+
const parsed = JSON.parse(raw);
|
|
8442
|
+
cache.set(base, parsed);
|
|
8443
|
+
return parsed;
|
|
8444
|
+
} catch {
|
|
8445
|
+
return null;
|
|
8446
|
+
}
|
|
8447
|
+
}
|
|
8448
|
+
|
|
8449
|
+
// src/tools/readKnowledge.ts
|
|
8450
|
+
init_cjs_shims();
|
|
8451
|
+
var import_zod27 = require("zod");
|
|
8452
|
+
init_contract();
|
|
8453
|
+
|
|
8454
|
+
// src/knowledge/extractors.ts
|
|
8455
|
+
init_cjs_shims();
|
|
8456
|
+
var CSV_MAX_ROWS = 100;
|
|
8457
|
+
var HTML_TAG_RE = /<[^>]+>/g;
|
|
8458
|
+
var HTML_ENTITIES = {
|
|
8459
|
+
"&": "&",
|
|
8460
|
+
"<": "<",
|
|
8461
|
+
">": ">",
|
|
8462
|
+
""": '"',
|
|
8463
|
+
"'": "'",
|
|
8464
|
+
" ": " "
|
|
8465
|
+
};
|
|
8466
|
+
function decodeHtmlEntities(s) {
|
|
8467
|
+
return s.replace(/&(amp|lt|gt|quot|#39|nbsp);/g, (m) => HTML_ENTITIES[m] ?? m);
|
|
8468
|
+
}
|
|
8469
|
+
var text = {
|
|
8470
|
+
format: "txt",
|
|
8471
|
+
requiresNode: false,
|
|
8472
|
+
extract: async (raw) => raw
|
|
8473
|
+
};
|
|
8474
|
+
var md = {
|
|
8475
|
+
format: "md",
|
|
8476
|
+
requiresNode: false,
|
|
8477
|
+
extract: async (raw) => raw
|
|
8478
|
+
};
|
|
8479
|
+
var json = {
|
|
8480
|
+
format: "json",
|
|
8481
|
+
requiresNode: false,
|
|
8482
|
+
extract: async (raw) => {
|
|
8483
|
+
try {
|
|
8484
|
+
return JSON.stringify(JSON.parse(raw), null, 2);
|
|
8485
|
+
} catch {
|
|
8486
|
+
return raw;
|
|
8487
|
+
}
|
|
8488
|
+
}
|
|
8489
|
+
};
|
|
8490
|
+
var csv = {
|
|
8491
|
+
format: "csv",
|
|
8492
|
+
requiresNode: false,
|
|
8493
|
+
extract: async (raw) => {
|
|
8494
|
+
const lines = raw.split(/\r?\n/).filter((l) => l.length > 0);
|
|
8495
|
+
if (lines.length === 0) return "";
|
|
8496
|
+
if (lines.length <= CSV_MAX_ROWS + 1) return lines.join("\n");
|
|
8497
|
+
const head = lines.slice(0, CSV_MAX_ROWS + 1);
|
|
8498
|
+
const remaining = lines.length - head.length;
|
|
8499
|
+
return `${head.join("\n")}
|
|
8500
|
+
\u2026[${remaining.toLocaleString()} more row${remaining === 1 ? "" : "s"} truncated]`;
|
|
8501
|
+
}
|
|
8502
|
+
};
|
|
8503
|
+
var html = {
|
|
8504
|
+
format: "html",
|
|
8505
|
+
requiresNode: false,
|
|
8506
|
+
extract: async (raw) => {
|
|
8507
|
+
const stripped = raw.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "").replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, "").replace(HTML_TAG_RE, " ");
|
|
8508
|
+
return decodeHtmlEntities(stripped).replace(/\s+/g, " ").trim();
|
|
8509
|
+
}
|
|
8510
|
+
};
|
|
8511
|
+
var pdf = {
|
|
8512
|
+
format: "pdf",
|
|
8513
|
+
requiresNode: true,
|
|
8514
|
+
extract: async (raw) => {
|
|
8515
|
+
let pdfParse;
|
|
8516
|
+
try {
|
|
8517
|
+
const mod = await import("pdf-parse");
|
|
8518
|
+
pdfParse = mod.default ?? mod;
|
|
8519
|
+
} catch {
|
|
8520
|
+
throw new Error(
|
|
8521
|
+
"ERR_KNOWLEDGE_FORMAT_UNSUPPORTED: pdf-parse is not installed. Run `npm install pdf-parse` to enable PDF extraction."
|
|
8522
|
+
);
|
|
8523
|
+
}
|
|
8524
|
+
const buf = Buffer.from(raw, "binary");
|
|
8525
|
+
const result = await pdfParse(buf);
|
|
8526
|
+
return result.text;
|
|
8527
|
+
}
|
|
8528
|
+
};
|
|
8529
|
+
var docx = {
|
|
8530
|
+
format: "docx",
|
|
8531
|
+
requiresNode: true,
|
|
8532
|
+
extract: async (raw) => {
|
|
8533
|
+
let mammoth;
|
|
8534
|
+
try {
|
|
8535
|
+
mammoth = await import("mammoth");
|
|
8536
|
+
} catch {
|
|
8537
|
+
throw new Error(
|
|
8538
|
+
"ERR_KNOWLEDGE_FORMAT_UNSUPPORTED: mammoth is not installed. Run `npm install mammoth` to enable DOCX extraction."
|
|
8539
|
+
);
|
|
8540
|
+
}
|
|
8541
|
+
const buf = Buffer.from(raw, "binary");
|
|
8542
|
+
const result = await mammoth.extractRawText({ buffer: buf });
|
|
8543
|
+
return result.value;
|
|
8544
|
+
}
|
|
8545
|
+
};
|
|
8546
|
+
var EXTRACTORS = {
|
|
8547
|
+
md,
|
|
8548
|
+
txt: text,
|
|
8549
|
+
json,
|
|
8550
|
+
csv,
|
|
8551
|
+
html,
|
|
8552
|
+
pdf,
|
|
8553
|
+
docx
|
|
8554
|
+
};
|
|
8555
|
+
function getExtractor(format) {
|
|
8556
|
+
const e = EXTRACTORS[format];
|
|
8557
|
+
if (e === void 0) throw new Error(`ERR_KNOWLEDGE_FORMAT_UNSUPPORTED: ${format}`);
|
|
8558
|
+
return e;
|
|
8559
|
+
}
|
|
8560
|
+
|
|
8561
|
+
// src/tools/readKnowledge.ts
|
|
8562
|
+
var DEFAULT_MAX_READ_BYTES = 1e4;
|
|
8563
|
+
var inputSchema19 = import_zod27.z.object({
|
|
8564
|
+
ref: import_zod27.z.string().min(1)
|
|
8565
|
+
});
|
|
8566
|
+
function createReadKnowledgeTool(opts) {
|
|
8567
|
+
const scoped = opts.folders.map(parseFolderRef);
|
|
8568
|
+
const indexCache = /* @__PURE__ */ new Map();
|
|
8569
|
+
const fileCache = /* @__PURE__ */ new Map();
|
|
8570
|
+
const cap = opts.maxReadBytes ?? DEFAULT_MAX_READ_BYTES;
|
|
8571
|
+
const externalsByName = new Map(opts.external.map((e) => [e.name, e]));
|
|
8572
|
+
const fetchFn = opts.fetch ?? globalThis.fetch.bind(globalThis);
|
|
8573
|
+
return defineTool({
|
|
8574
|
+
name: "ReadKnowledge",
|
|
8575
|
+
description: "Load the full content of a knowledge ref returned by SearchKnowledge. Use the `ref` value verbatim from the search results \u2014 section refs return one section, file refs return the whole file (with format-specific extraction for non-markdown formats), and `ext:{name}` refs fetch a pre-registered external file.",
|
|
8576
|
+
inputSchema: inputSchema19,
|
|
8577
|
+
execute: async ({ ref }) => {
|
|
8578
|
+
let parsed;
|
|
8579
|
+
try {
|
|
8580
|
+
parsed = parseKnowledgeRef(ref);
|
|
8581
|
+
} catch (err) {
|
|
8582
|
+
return {
|
|
8583
|
+
content: `ERR_KNOWLEDGE_REF_INVALID: ${err instanceof Error ? err.message : String(err)}`,
|
|
8584
|
+
isError: true
|
|
8585
|
+
};
|
|
8586
|
+
}
|
|
8587
|
+
if (parsed.kind === "ext") {
|
|
8588
|
+
return readExternal(parsed.target, externalsByName, fetchFn, cap);
|
|
8589
|
+
}
|
|
8590
|
+
if (!refInScope(scoped, parsed.target)) {
|
|
8591
|
+
return {
|
|
8592
|
+
content: `ERR_KNOWLEDGE_FOLDER_NOT_ALLOWED: ref "${parsed.target}" is outside the run's allowed folders`,
|
|
8593
|
+
isError: true
|
|
8594
|
+
};
|
|
8595
|
+
}
|
|
8596
|
+
const base = parsed.target.split("/")[0];
|
|
8597
|
+
const relPath = parsed.target.slice(base.length + 1);
|
|
8598
|
+
if (parsed.kind === "section") {
|
|
8599
|
+
const idx = await loadIndex2(opts.adapter, base, indexCache);
|
|
8600
|
+
if (idx === null) {
|
|
8601
|
+
return {
|
|
8602
|
+
content: `ERR_KNOWLEDGE_INDEX_MISSING: no _index.json for base "${base}"`,
|
|
8603
|
+
isError: true
|
|
8604
|
+
};
|
|
8605
|
+
}
|
|
8606
|
+
const sectionSlug = parsed.section ?? "";
|
|
8607
|
+
const section = idx.sections.find(
|
|
8608
|
+
(s) => s.relPath === relPath && extractAnchor(s.slug) === sectionSlug
|
|
8609
|
+
);
|
|
8610
|
+
if (section === void 0) {
|
|
8611
|
+
return {
|
|
8612
|
+
content: `ERR_KNOWLEDGE_REF_NOT_FOUND: section ${parsed.target}#${sectionSlug} not in index for "${base}"`,
|
|
8613
|
+
isError: true
|
|
8614
|
+
};
|
|
8615
|
+
}
|
|
8616
|
+
const fullContent = await readFile(opts.adapter, parsed.target, fileCache);
|
|
8617
|
+
if (fullContent === null) {
|
|
8618
|
+
return {
|
|
8619
|
+
content: `ERR_KNOWLEDGE_REF_NOT_FOUND: file ${parsed.target} not found in storage`,
|
|
8620
|
+
isError: true
|
|
8621
|
+
};
|
|
8622
|
+
}
|
|
8623
|
+
const sliced = sliceLines(fullContent, section.startLine, section.endLine);
|
|
8624
|
+
return wrapResult(`[knowledge] ${parsed.target}#${sectionSlug}`, sliced, cap);
|
|
8625
|
+
}
|
|
8626
|
+
const fmt = inferFormat(parsed.target);
|
|
8627
|
+
if (fmt === null) {
|
|
8628
|
+
return {
|
|
8629
|
+
content: `ERR_KNOWLEDGE_FORMAT_UNSUPPORTED: cannot infer format for "${parsed.target}"`,
|
|
8630
|
+
isError: true
|
|
8631
|
+
};
|
|
8632
|
+
}
|
|
8633
|
+
const raw = await readFile(opts.adapter, parsed.target, fileCache);
|
|
8634
|
+
if (raw === null) {
|
|
8635
|
+
return {
|
|
8636
|
+
content: `ERR_KNOWLEDGE_REF_NOT_FOUND: file ${parsed.target} not found in storage`,
|
|
8637
|
+
isError: true
|
|
8638
|
+
};
|
|
8639
|
+
}
|
|
8640
|
+
let extracted;
|
|
8641
|
+
try {
|
|
8642
|
+
extracted = await getExtractor(fmt).extract(raw);
|
|
8643
|
+
} catch (err) {
|
|
8644
|
+
return {
|
|
8645
|
+
content: `ERR_KNOWLEDGE_EXTRACTOR_FAILED: ${err instanceof Error ? err.message : String(err)}`,
|
|
8646
|
+
isError: true
|
|
8647
|
+
};
|
|
8648
|
+
}
|
|
8649
|
+
return wrapResult(`[knowledge] ${parsed.target} (${fmt})`, extracted, cap);
|
|
8650
|
+
}
|
|
8651
|
+
});
|
|
8652
|
+
}
|
|
8653
|
+
async function readExternal(name, registry, fetchFn, cap) {
|
|
8654
|
+
const link = registry.get(name);
|
|
8655
|
+
if (link === void 0) {
|
|
8656
|
+
return {
|
|
8657
|
+
content: `ERR_KNOWLEDGE_REF_NOT_FOUND: no external link named "${name}"`,
|
|
8658
|
+
isError: true
|
|
8659
|
+
};
|
|
8660
|
+
}
|
|
8661
|
+
let res;
|
|
8662
|
+
try {
|
|
8663
|
+
res = await fetchFn(link.url, {
|
|
8664
|
+
headers: link.headers ?? {}
|
|
8665
|
+
});
|
|
8666
|
+
} catch (err) {
|
|
8667
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
8668
|
+
return {
|
|
8669
|
+
content: `ERR_KNOWLEDGE_NETWORK: ${msg.slice(0, 200)}`,
|
|
8670
|
+
isError: true
|
|
8671
|
+
};
|
|
8672
|
+
}
|
|
8673
|
+
if (!res.ok) {
|
|
8674
|
+
return {
|
|
8675
|
+
content: `ERR_KNOWLEDGE_NETWORK: HTTP ${res.status} fetching ext:${name}`,
|
|
8676
|
+
isError: true
|
|
8677
|
+
};
|
|
8678
|
+
}
|
|
8679
|
+
const raw = await res.text();
|
|
8680
|
+
let extracted;
|
|
8681
|
+
try {
|
|
8682
|
+
extracted = await getExtractor(link.format).extract(raw);
|
|
8683
|
+
} catch (err) {
|
|
8684
|
+
return {
|
|
8685
|
+
content: `ERR_KNOWLEDGE_EXTRACTOR_FAILED: ${err instanceof Error ? err.message : String(err)}`,
|
|
8686
|
+
isError: true
|
|
8687
|
+
};
|
|
8688
|
+
}
|
|
8689
|
+
return wrapResult(`[external] ${name} (${link.format})`, extracted, cap);
|
|
8690
|
+
}
|
|
8691
|
+
function wrapResult(header, body, cap) {
|
|
8692
|
+
let payload = body;
|
|
8693
|
+
if (body.length > cap) {
|
|
8694
|
+
payload = body.slice(0, cap) + `
|
|
8695
|
+
\u2026[+${body.length - cap} more chars truncated]`;
|
|
8696
|
+
}
|
|
8697
|
+
return {
|
|
8698
|
+
content: `${header}
|
|
8699
|
+
|
|
8700
|
+
${payload}`,
|
|
8701
|
+
isError: false,
|
|
8702
|
+
metadata: { bytes: body.length }
|
|
8703
|
+
};
|
|
8704
|
+
}
|
|
8705
|
+
async function loadIndex2(adapter, base, cache) {
|
|
8706
|
+
const cached2 = cache.get(base);
|
|
8707
|
+
if (cached2 !== void 0) return cached2;
|
|
8708
|
+
let raw;
|
|
8709
|
+
try {
|
|
8710
|
+
raw = await adapter.readFile(`${base}/_index.json`);
|
|
8711
|
+
} catch {
|
|
8712
|
+
return null;
|
|
8713
|
+
}
|
|
8714
|
+
if (raw === null) return null;
|
|
8715
|
+
try {
|
|
8716
|
+
const idx = JSON.parse(raw);
|
|
8717
|
+
cache.set(base, idx);
|
|
8718
|
+
return idx;
|
|
8719
|
+
} catch {
|
|
8720
|
+
return null;
|
|
8721
|
+
}
|
|
8722
|
+
}
|
|
8723
|
+
async function readFile(adapter, path, cache) {
|
|
8724
|
+
const cached2 = cache.get(path);
|
|
8725
|
+
if (cached2 !== void 0) return cached2;
|
|
8726
|
+
const content = await adapter.readFile(path).catch(() => null);
|
|
8727
|
+
if (content === null) return null;
|
|
8728
|
+
cache.set(path, content);
|
|
8729
|
+
return content;
|
|
8730
|
+
}
|
|
8731
|
+
function sliceLines(content, start, end) {
|
|
8732
|
+
const lines = content.split(/\r?\n/);
|
|
8733
|
+
return lines.slice(start - 1, end).join("\n");
|
|
8734
|
+
}
|
|
8735
|
+
function extractAnchor(slug) {
|
|
8736
|
+
const i = slug.indexOf("#");
|
|
8737
|
+
return i === -1 ? "" : slug.slice(i + 1);
|
|
8738
|
+
}
|
|
8739
|
+
function inferFormat(filePath) {
|
|
8740
|
+
const ext = (filePath.split(".").pop() ?? "").toLowerCase();
|
|
8741
|
+
switch (ext) {
|
|
8742
|
+
case "md":
|
|
8743
|
+
case "markdown":
|
|
8744
|
+
return "md";
|
|
8745
|
+
case "txt":
|
|
8746
|
+
return "txt";
|
|
8747
|
+
case "json":
|
|
8748
|
+
return "json";
|
|
8749
|
+
case "csv":
|
|
8750
|
+
return "csv";
|
|
8751
|
+
case "html":
|
|
8752
|
+
case "htm":
|
|
8753
|
+
return "html";
|
|
8754
|
+
case "pdf":
|
|
8755
|
+
return "pdf";
|
|
8756
|
+
case "docx":
|
|
8757
|
+
return "docx";
|
|
8758
|
+
}
|
|
8759
|
+
return null;
|
|
8760
|
+
}
|
|
8761
|
+
|
|
7879
8762
|
// src/skills/storageSkillSource.ts
|
|
7880
8763
|
init_cjs_shims();
|
|
7881
8764
|
var SAFE_NAME4 = /^[a-zA-Z0-9_-]+$/;
|
|
@@ -8015,9 +8898,9 @@ var InlineSkillSource = class {
|
|
|
8015
8898
|
`InlineSkillSource: fetch ${url} \u2192 HTTP ${String(response.status)} ${response.statusText}`
|
|
8016
8899
|
);
|
|
8017
8900
|
}
|
|
8018
|
-
const
|
|
8019
|
-
this.cache.set(cacheKey,
|
|
8020
|
-
return
|
|
8901
|
+
const text2 = await response.text();
|
|
8902
|
+
this.cache.set(cacheKey, text2);
|
|
8903
|
+
return text2;
|
|
8021
8904
|
}
|
|
8022
8905
|
assertUrlAllowed(url) {
|
|
8023
8906
|
const hosts = this.allowedHosts;
|
|
@@ -8489,47 +9372,60 @@ var R2BindingStorageAdapter = class {
|
|
|
8489
9372
|
// src/storage/factory.ts
|
|
8490
9373
|
var ENGINE_DATA_FOLDER = ".claude";
|
|
8491
9374
|
var WORKSPACES_FOLDER = "workspaces";
|
|
8492
|
-
|
|
9375
|
+
var KNOWLEDGE_FOLDER = "knowledge";
|
|
9376
|
+
async function createEngineStorage(config, options = {}) {
|
|
8493
9377
|
switch (config.provider) {
|
|
8494
9378
|
case "local":
|
|
8495
|
-
return createLocalStorage(config);
|
|
9379
|
+
return createLocalStorage(config, options);
|
|
8496
9380
|
case "r2":
|
|
8497
|
-
return createR2Storage(config);
|
|
9381
|
+
return createR2Storage(config, options);
|
|
8498
9382
|
case "r2-binding":
|
|
8499
|
-
return createR2BindingStorage(config);
|
|
9383
|
+
return createR2BindingStorage(config, options);
|
|
8500
9384
|
}
|
|
8501
9385
|
}
|
|
8502
|
-
async function createLocalStorage(config) {
|
|
9386
|
+
async function createLocalStorage(config, options) {
|
|
8503
9387
|
const path = await import("path");
|
|
8504
|
-
const
|
|
8505
|
-
|
|
8506
|
-
|
|
8507
|
-
|
|
8508
|
-
|
|
8509
|
-
|
|
8510
|
-
|
|
8511
|
-
|
|
8512
|
-
};
|
|
9388
|
+
const tenantRoot = path.join(config.rootPath, WORKSPACES_FOLDER, config.workspaceId);
|
|
9389
|
+
const workspaceRoot = path.join(tenantRoot, ENGINE_DATA_FOLDER);
|
|
9390
|
+
const out = { workspace: new LocalStorageAdapter(workspaceRoot) };
|
|
9391
|
+
if (options.withKnowledge) {
|
|
9392
|
+
const knowledgeRoot = path.join(tenantRoot, KNOWLEDGE_FOLDER);
|
|
9393
|
+
return { ...out, knowledge: new LocalStorageAdapter(knowledgeRoot) };
|
|
9394
|
+
}
|
|
9395
|
+
return out;
|
|
8513
9396
|
}
|
|
8514
|
-
function createR2Storage(config) {
|
|
9397
|
+
function createR2Storage(config, options) {
|
|
8515
9398
|
if (!config.r2) {
|
|
8516
9399
|
throw new StorageError('storage.r2 is required when storage.provider === "r2"');
|
|
8517
9400
|
}
|
|
8518
9401
|
const rootPrefix = config.rootPath.replace(/^\/+|\/+$/g, "");
|
|
8519
|
-
const
|
|
8520
|
-
|
|
8521
|
-
|
|
8522
|
-
|
|
9402
|
+
const tenantPrefix = `${rootPrefix}/${WORKSPACES_FOLDER}/${config.workspaceId}`;
|
|
9403
|
+
const workspacePrefix = `${tenantPrefix}/${ENGINE_DATA_FOLDER}`;
|
|
9404
|
+
const out = { workspace: new R2StorageAdapter(config.r2, workspacePrefix) };
|
|
9405
|
+
if (options.withKnowledge) {
|
|
9406
|
+
const knowledgePrefix = `${tenantPrefix}/${KNOWLEDGE_FOLDER}`;
|
|
9407
|
+
return { ...out, knowledge: new R2StorageAdapter(config.r2, knowledgePrefix) };
|
|
9408
|
+
}
|
|
9409
|
+
return out;
|
|
8523
9410
|
}
|
|
8524
|
-
function createR2BindingStorage(config) {
|
|
9411
|
+
function createR2BindingStorage(config, options) {
|
|
8525
9412
|
if (!config.r2Binding) {
|
|
8526
9413
|
throw new StorageError('storage.r2Binding is required when storage.provider === "r2-binding"');
|
|
8527
9414
|
}
|
|
8528
9415
|
const rootPrefix = config.rootPath.replace(/^\/+|\/+$/g, "");
|
|
8529
|
-
const
|
|
8530
|
-
|
|
9416
|
+
const tenantPrefix = `${rootPrefix}/${WORKSPACES_FOLDER}/${config.workspaceId}`;
|
|
9417
|
+
const workspacePrefix = `${tenantPrefix}/${ENGINE_DATA_FOLDER}`;
|
|
9418
|
+
const out = {
|
|
8531
9419
|
workspace: new R2BindingStorageAdapter(config.r2Binding, workspacePrefix)
|
|
8532
9420
|
};
|
|
9421
|
+
if (options.withKnowledge) {
|
|
9422
|
+
const knowledgePrefix = `${tenantPrefix}/${KNOWLEDGE_FOLDER}`;
|
|
9423
|
+
return {
|
|
9424
|
+
...out,
|
|
9425
|
+
knowledge: new R2BindingStorageAdapter(config.r2Binding, knowledgePrefix)
|
|
9426
|
+
};
|
|
9427
|
+
}
|
|
9428
|
+
return out;
|
|
8533
9429
|
}
|
|
8534
9430
|
|
|
8535
9431
|
// src/transcript/reader.ts
|
|
@@ -9033,6 +9929,8 @@ var Engine = class {
|
|
|
9033
9929
|
const skillSource = this.resolveSkillSource(options.skills, storage);
|
|
9034
9930
|
const skillList = skillSource !== void 0 ? await skillSource.list() : void 0;
|
|
9035
9931
|
const apiConfig = this.resolveApiConfig(options.api);
|
|
9932
|
+
const offloadConfig = this.resolveOffloadConfig(options.compaction?.toolResultOffload);
|
|
9933
|
+
const knowledgeRuntime = this.resolveKnowledgeRuntime(options.knowledge, storage);
|
|
9036
9934
|
let systemPrompt = await buildSystemPrompt({
|
|
9037
9935
|
...coordinatorBase !== void 0 ? { base: coordinatorBase } : {},
|
|
9038
9936
|
memory,
|
|
@@ -9065,6 +9963,8 @@ var Engine = class {
|
|
|
9065
9963
|
...this.config.hooks.propagateGateToSubagents === true && gate !== void 0 ? { subagentGate: gate } : {},
|
|
9066
9964
|
...skillSource !== void 0 ? { skillSource } : {},
|
|
9067
9965
|
...apiConfig !== void 0 ? { apiConfig } : {},
|
|
9966
|
+
...offloadConfig !== void 0 ? { toolResultOffload: offloadConfig } : {},
|
|
9967
|
+
...knowledgeRuntime !== void 0 ? { knowledge: knowledgeRuntime } : {},
|
|
9068
9968
|
...this.internals.fetch !== void 0 ? { fetch: this.internals.fetch } : {}
|
|
9069
9969
|
});
|
|
9070
9970
|
const writer = new TranscriptWriter({
|
|
@@ -9120,7 +10020,8 @@ var Engine = class {
|
|
|
9120
10020
|
...options.tokenBudget !== void 0 ? { tokenBudget: options.tokenBudget } : {},
|
|
9121
10021
|
...runTimeout.signal !== void 0 ? { runSignal: runTimeout.signal, runTimeoutMs: this.config.execution.runTimeoutMs } : {},
|
|
9122
10022
|
...gate !== void 0 ? { gateBeforeTool: gate } : {},
|
|
9123
|
-
..._internal?.handoffToRunner === true ? { handoffToRunner: true } : {}
|
|
10023
|
+
..._internal?.handoffToRunner === true ? { handoffToRunner: true } : {},
|
|
10024
|
+
...offloadConfig !== void 0 ? { toolResultOffload: offloadConfig } : {}
|
|
9124
10025
|
});
|
|
9125
10026
|
const result = await this.finalizeResult(loopResult, writer, logPath, {
|
|
9126
10027
|
...options.outputFormat !== void 0 ? { outputFormat: options.outputFormat } : {},
|
|
@@ -9175,6 +10076,8 @@ var Engine = class {
|
|
|
9175
10076
|
const skillSource = this.resolveSkillSource(options.skills, storage);
|
|
9176
10077
|
const skillList = skillSource !== void 0 ? await skillSource.list() : void 0;
|
|
9177
10078
|
const apiConfig = this.resolveApiConfig(options.api);
|
|
10079
|
+
const offloadConfig = this.resolveOffloadConfig(options.compaction?.toolResultOffload);
|
|
10080
|
+
const knowledgeRuntime = this.resolveKnowledgeRuntime(options.knowledge, storage);
|
|
9178
10081
|
let systemPrompt = await buildSystemPrompt({
|
|
9179
10082
|
...coordinatorBase !== void 0 ? { base: coordinatorBase } : {},
|
|
9180
10083
|
memory,
|
|
@@ -9207,6 +10110,8 @@ var Engine = class {
|
|
|
9207
10110
|
...this.config.hooks.propagateGateToSubagents === true && gate !== void 0 ? { subagentGate: gate } : {},
|
|
9208
10111
|
...skillSource !== void 0 ? { skillSource } : {},
|
|
9209
10112
|
...apiConfig !== void 0 ? { apiConfig } : {},
|
|
10113
|
+
...offloadConfig !== void 0 ? { toolResultOffload: offloadConfig } : {},
|
|
10114
|
+
...knowledgeRuntime !== void 0 ? { knowledge: knowledgeRuntime } : {},
|
|
9210
10115
|
...this.internals.fetch !== void 0 ? { fetch: this.internals.fetch } : {}
|
|
9211
10116
|
});
|
|
9212
10117
|
const priorState = await loadWriterState(storage.workspace, logPath);
|
|
@@ -9297,7 +10202,8 @@ ${inputJson}
|
|
|
9297
10202
|
onProgress: this.buildHeartbeat(storage, snapshot.runId, snapshot.nodeId),
|
|
9298
10203
|
...runTimeout.signal !== void 0 ? { runSignal: runTimeout.signal, runTimeoutMs: this.config.execution.runTimeoutMs } : {},
|
|
9299
10204
|
...gate !== void 0 ? { gateBeforeTool: gate } : {},
|
|
9300
|
-
..._internal?.handoffToRunner === true ? { handoffToRunner: true } : {}
|
|
10205
|
+
..._internal?.handoffToRunner === true ? { handoffToRunner: true } : {},
|
|
10206
|
+
...offloadConfig !== void 0 ? { toolResultOffload: offloadConfig } : {}
|
|
9301
10207
|
});
|
|
9302
10208
|
const result = await this.finalizeResult(loopResult, writer, logPath, {
|
|
9303
10209
|
...options.outputFormat !== void 0 ? { outputFormat: options.outputFormat } : {},
|
|
@@ -9843,6 +10749,19 @@ ${inputJson}
|
|
|
9843
10749
|
names.add("ApiCall");
|
|
9844
10750
|
}
|
|
9845
10751
|
}
|
|
10752
|
+
if (this.config.compaction.toolResultOffload?.enabled === true) {
|
|
10753
|
+
if (!disabled.has("FetchData") && (wantAll || enabled.has("FetchData"))) {
|
|
10754
|
+
names.add("FetchData");
|
|
10755
|
+
}
|
|
10756
|
+
}
|
|
10757
|
+
if (this.config.knowledge?.enabled === true) {
|
|
10758
|
+
if (!disabled.has("SearchKnowledge") && (wantAll || enabled.has("SearchKnowledge"))) {
|
|
10759
|
+
names.add("SearchKnowledge");
|
|
10760
|
+
}
|
|
10761
|
+
if (!disabled.has("ReadKnowledge") && (wantAll || enabled.has("ReadKnowledge"))) {
|
|
10762
|
+
names.add("ReadKnowledge");
|
|
10763
|
+
}
|
|
10764
|
+
}
|
|
9846
10765
|
for (const tool of this.config.tools.custom) {
|
|
9847
10766
|
names.add(tool.name);
|
|
9848
10767
|
}
|
|
@@ -9944,7 +10863,7 @@ ${inputJson}
|
|
|
9944
10863
|
await writer.setStatus("done");
|
|
9945
10864
|
let data;
|
|
9946
10865
|
if (jsonOptions?.outputFormat === "json") {
|
|
9947
|
-
const parsed =
|
|
10866
|
+
const parsed = tryParseJSON2(loopResult.output);
|
|
9948
10867
|
if (parsed.ok) {
|
|
9949
10868
|
if (jsonOptions.outputSchema) {
|
|
9950
10869
|
const validated = validateOutput(parsed.value, jsonOptions.outputSchema);
|
|
@@ -10009,6 +10928,61 @@ ${inputJson}
|
|
|
10009
10928
|
* tool isn't registered at all. Env + resolveAuth + hooks flow
|
|
10010
10929
|
* through untouched — they never hit the Zod schema.
|
|
10011
10930
|
*/
|
|
10931
|
+
/**
|
|
10932
|
+
* Plan 021 — resolve the effective tool-result offload config.
|
|
10933
|
+
*
|
|
10934
|
+
* Precedence (each field independently):
|
|
10935
|
+
* RunOptions.compaction.toolResultOffload.X >
|
|
10936
|
+
* config.compaction.toolResultOffload.X
|
|
10937
|
+
*
|
|
10938
|
+
* When neither side enables offload, returns undefined and no
|
|
10939
|
+
* `FetchData` tool is registered.
|
|
10940
|
+
*/
|
|
10941
|
+
resolveOffloadConfig(override) {
|
|
10942
|
+
const base = this.config.compaction.toolResultOffload;
|
|
10943
|
+
if (override === void 0 && base === void 0) return void 0;
|
|
10944
|
+
const enabled = override?.enabled ?? base?.enabled ?? false;
|
|
10945
|
+
if (!enabled) return void 0;
|
|
10946
|
+
const thresholdBytes = override?.thresholdBytes ?? base?.thresholdBytes ?? 2048;
|
|
10947
|
+
const maxPreviewChars = override?.maxPreviewChars ?? base?.maxPreviewChars ?? 500;
|
|
10948
|
+
const summarizer = override?.summarizer ?? base?.summarizer;
|
|
10949
|
+
return {
|
|
10950
|
+
enabled: true,
|
|
10951
|
+
thresholdBytes,
|
|
10952
|
+
maxPreviewChars,
|
|
10953
|
+
...summarizer !== void 0 ? { summarizer } : {}
|
|
10954
|
+
};
|
|
10955
|
+
}
|
|
10956
|
+
/**
|
|
10957
|
+
* Plan 023 — resolve the effective runtime knowledge bundle for a
|
|
10958
|
+
* single run.
|
|
10959
|
+
*
|
|
10960
|
+
* Engine-level config (`config.knowledge`) carries the capability
|
|
10961
|
+
* flag + scalar caps. The actual folders + external links are
|
|
10962
|
+
* RUNTIME-only, supplied via `RunOptions.knowledge`. Returning
|
|
10963
|
+
* `undefined` means "don't register the knowledge tools" — callers
|
|
10964
|
+
* skip the bundle entirely.
|
|
10965
|
+
*
|
|
10966
|
+
* Three gates must all pass:
|
|
10967
|
+
* 1. `config.knowledge.enabled === true` (engine opt-in)
|
|
10968
|
+
* 2. `storage.knowledge !== undefined` (adapter was built)
|
|
10969
|
+
* 3. There IS something to look at — at least one folder OR
|
|
10970
|
+
* one external link supplied for this run.
|
|
10971
|
+
*/
|
|
10972
|
+
resolveKnowledgeRuntime(override, storage) {
|
|
10973
|
+
if (this.config.knowledge?.enabled !== true) return void 0;
|
|
10974
|
+
if (storage.knowledge === void 0) return void 0;
|
|
10975
|
+
const folders = override?.folders ?? [];
|
|
10976
|
+
const external = override?.external ?? [];
|
|
10977
|
+
if (folders.length === 0 && external.length === 0) return void 0;
|
|
10978
|
+
return {
|
|
10979
|
+
adapter: storage.knowledge,
|
|
10980
|
+
folders,
|
|
10981
|
+
external,
|
|
10982
|
+
maxSearchResults: this.config.knowledge.maxSearchResults,
|
|
10983
|
+
maxReadBytes: this.config.knowledge.maxReadBytes
|
|
10984
|
+
};
|
|
10985
|
+
}
|
|
10012
10986
|
resolveApiConfig(override) {
|
|
10013
10987
|
const base = this.config.api;
|
|
10014
10988
|
if (override === void 0 && base === void 0) return void 0;
|
|
@@ -10071,7 +11045,9 @@ ${inputJson}
|
|
|
10071
11045
|
if (this.internals.buildStorage !== void 0) {
|
|
10072
11046
|
return this.internals.buildStorage();
|
|
10073
11047
|
}
|
|
10074
|
-
return createEngineStorage(this.config.storage
|
|
11048
|
+
return createEngineStorage(this.config.storage, {
|
|
11049
|
+
withKnowledge: this.config.knowledge?.enabled === true
|
|
11050
|
+
});
|
|
10075
11051
|
}
|
|
10076
11052
|
buildClient() {
|
|
10077
11053
|
return createModelAdapter(this.config.model, {
|
|
@@ -10183,6 +11159,39 @@ function buildToolRegistry(options) {
|
|
|
10183
11159
|
childRegistry.register(apiTool);
|
|
10184
11160
|
}
|
|
10185
11161
|
}
|
|
11162
|
+
if (options.toolResultOffload?.enabled === true) {
|
|
11163
|
+
if (!disabled.has("FetchData") && (wantAll || enabled.has("FetchData"))) {
|
|
11164
|
+
const fetchDataTool = createFetchDataTool({
|
|
11165
|
+
storage: storage.workspace,
|
|
11166
|
+
logPath: options.parentLogPath
|
|
11167
|
+
});
|
|
11168
|
+
registry.register(fetchDataTool);
|
|
11169
|
+
}
|
|
11170
|
+
}
|
|
11171
|
+
if (options.knowledge !== void 0) {
|
|
11172
|
+
const k = options.knowledge;
|
|
11173
|
+
if (!disabled.has("SearchKnowledge") && (wantAll || enabled.has("SearchKnowledge"))) {
|
|
11174
|
+
const searchTool = createSearchKnowledgeTool({
|
|
11175
|
+
adapter: k.adapter,
|
|
11176
|
+
folders: k.folders,
|
|
11177
|
+
external: k.external,
|
|
11178
|
+
maxSearchResults: k.maxSearchResults
|
|
11179
|
+
});
|
|
11180
|
+
registry.register(searchTool);
|
|
11181
|
+
childRegistry.register(searchTool);
|
|
11182
|
+
}
|
|
11183
|
+
if (!disabled.has("ReadKnowledge") && (wantAll || enabled.has("ReadKnowledge"))) {
|
|
11184
|
+
const readTool = createReadKnowledgeTool({
|
|
11185
|
+
adapter: k.adapter,
|
|
11186
|
+
folders: k.folders,
|
|
11187
|
+
external: k.external,
|
|
11188
|
+
maxReadBytes: k.maxReadBytes,
|
|
11189
|
+
...options.fetch !== void 0 ? { fetch: options.fetch } : {}
|
|
11190
|
+
});
|
|
11191
|
+
registry.register(readTool);
|
|
11192
|
+
childRegistry.register(readTool);
|
|
11193
|
+
}
|
|
11194
|
+
}
|
|
10186
11195
|
const agentTool = createAgentTool({
|
|
10187
11196
|
storage: storage.workspace,
|
|
10188
11197
|
client,
|
|
@@ -10198,7 +11207,8 @@ function buildToolRegistry(options) {
|
|
|
10198
11207
|
idleFlushMs: config.transcript.idleFlushMs,
|
|
10199
11208
|
agents,
|
|
10200
11209
|
coordinatorMode: isCoordinatorMode(config),
|
|
10201
|
-
...subagentGate !== void 0 ? { gateBeforeTool: subagentGate } : {}
|
|
11210
|
+
...subagentGate !== void 0 ? { gateBeforeTool: subagentGate } : {},
|
|
11211
|
+
...options.toolResultOffload !== void 0 ? { toolResultOffload: options.toolResultOffload } : {}
|
|
10202
11212
|
});
|
|
10203
11213
|
if (!disabled.has("Agent") && (wantAll || enabled.has("Agent"))) {
|
|
10204
11214
|
registry.register(agentTool);
|
|
@@ -10226,6 +11236,155 @@ function buildToolRegistry(options) {
|
|
|
10226
11236
|
return registry;
|
|
10227
11237
|
}
|
|
10228
11238
|
|
|
11239
|
+
// src/index.ts
|
|
11240
|
+
init_contract();
|
|
11241
|
+
init_fetchData();
|
|
11242
|
+
|
|
11243
|
+
// src/knowledge/indexer.ts
|
|
11244
|
+
init_cjs_shims();
|
|
11245
|
+
var HEADING_RE = /^(#{1,6})[ \t]+(.+?)\s*$/;
|
|
11246
|
+
var WIKI_LINK_RE = /\[\[([^\]|#]+)(?:[#|][^\]]*)?\]\]/g;
|
|
11247
|
+
var FORMAT_BY_EXT = {
|
|
11248
|
+
md: "md",
|
|
11249
|
+
markdown: "md",
|
|
11250
|
+
txt: "txt",
|
|
11251
|
+
json: "json",
|
|
11252
|
+
csv: "csv",
|
|
11253
|
+
html: "html",
|
|
11254
|
+
htm: "html",
|
|
11255
|
+
pdf: "pdf",
|
|
11256
|
+
docx: "docx"
|
|
11257
|
+
};
|
|
11258
|
+
var PREVIEW_CHARS = 200;
|
|
11259
|
+
async function buildKnowledgeIndex(options) {
|
|
11260
|
+
const { adapter, base } = options;
|
|
11261
|
+
const safeBase = base.replace(/^\/+|\/+$/g, "");
|
|
11262
|
+
if (safeBase.length === 0 || safeBase.includes("..")) {
|
|
11263
|
+
throw new Error(`buildKnowledgeIndex: invalid base "${base}"`);
|
|
11264
|
+
}
|
|
11265
|
+
const files = await listFilesRecursive(adapter, safeBase);
|
|
11266
|
+
const sections = [];
|
|
11267
|
+
const filesMeta = {};
|
|
11268
|
+
for (const fileRel of files) {
|
|
11269
|
+
if (fileRel === "_index.json") continue;
|
|
11270
|
+
const fullPath = `${safeBase}/${fileRel}`;
|
|
11271
|
+
const ext = (fileRel.split(".").pop() ?? "").toLowerCase();
|
|
11272
|
+
const format = FORMAT_BY_EXT[ext];
|
|
11273
|
+
if (format === void 0) continue;
|
|
11274
|
+
const raw = await adapter.readFile(fullPath);
|
|
11275
|
+
if (raw === null) continue;
|
|
11276
|
+
const sizeBytes = byteLength3(raw);
|
|
11277
|
+
const meta = { format, size: sizeBytes };
|
|
11278
|
+
if (format === "md" || format === "txt") {
|
|
11279
|
+
const fileSections = splitSections(raw, fileRel);
|
|
11280
|
+
sections.push(...fileSections);
|
|
11281
|
+
const wikiLinks = extractWikiLinks(raw);
|
|
11282
|
+
if (wikiLinks.length > 0) meta.wikiLinks = wikiLinks;
|
|
11283
|
+
}
|
|
11284
|
+
filesMeta[fileRel] = meta;
|
|
11285
|
+
}
|
|
11286
|
+
return {
|
|
11287
|
+
schema: "v1",
|
|
11288
|
+
base: safeBase,
|
|
11289
|
+
builtAt: options.nowIso ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
11290
|
+
fileCount: Object.keys(filesMeta).length,
|
|
11291
|
+
sections,
|
|
11292
|
+
files: filesMeta
|
|
11293
|
+
};
|
|
11294
|
+
}
|
|
11295
|
+
async function writeKnowledgeIndex(options) {
|
|
11296
|
+
const index = await buildKnowledgeIndex(options);
|
|
11297
|
+
await options.adapter.writeFile(`${index.base}/_index.json`, JSON.stringify(index, null, 2));
|
|
11298
|
+
return index;
|
|
11299
|
+
}
|
|
11300
|
+
async function listFilesRecursive(adapter, dir) {
|
|
11301
|
+
const out = [];
|
|
11302
|
+
const stack = [""];
|
|
11303
|
+
while (stack.length > 0) {
|
|
11304
|
+
const sub = stack.pop();
|
|
11305
|
+
const fullDir = sub === "" ? dir : `${dir}/${sub}`;
|
|
11306
|
+
let entries = [];
|
|
11307
|
+
try {
|
|
11308
|
+
entries = await adapter.listDir(fullDir);
|
|
11309
|
+
} catch {
|
|
11310
|
+
continue;
|
|
11311
|
+
}
|
|
11312
|
+
for (const name of entries) {
|
|
11313
|
+
const childRel = sub === "" ? name : `${sub}/${name}`;
|
|
11314
|
+
const childFull = `${dir}/${childRel}`;
|
|
11315
|
+
const isDir = await adapter.isDirectory(childFull).catch(() => false);
|
|
11316
|
+
if (isDir) {
|
|
11317
|
+
stack.push(childRel);
|
|
11318
|
+
} else {
|
|
11319
|
+
out.push(childRel);
|
|
11320
|
+
}
|
|
11321
|
+
}
|
|
11322
|
+
}
|
|
11323
|
+
return out.sort();
|
|
11324
|
+
}
|
|
11325
|
+
function splitSections(content, relPath) {
|
|
11326
|
+
const lines = content.split(/\r?\n/);
|
|
11327
|
+
const out = [];
|
|
11328
|
+
const heads = [];
|
|
11329
|
+
for (let i = 0; i < lines.length; i++) {
|
|
11330
|
+
const line = lines[i];
|
|
11331
|
+
const m = HEADING_RE.exec(line);
|
|
11332
|
+
if (m) heads.push({ line: i + 1, depth: m[1].length, heading: m[2].trim() });
|
|
11333
|
+
}
|
|
11334
|
+
const leadInEndLine = heads.length > 0 ? heads[0].line - 1 : lines.length;
|
|
11335
|
+
const leadInBody = lines.slice(0, leadInEndLine).join("\n").trim();
|
|
11336
|
+
if (leadInBody.length > 0) {
|
|
11337
|
+
out.push({
|
|
11338
|
+
relPath,
|
|
11339
|
+
heading: "",
|
|
11340
|
+
slug: `${relPath}#`,
|
|
11341
|
+
depth: 0,
|
|
11342
|
+
words: tokenize(leadInBody),
|
|
11343
|
+
preview: makePreview(leadInBody),
|
|
11344
|
+
startLine: 1,
|
|
11345
|
+
endLine: leadInEndLine
|
|
11346
|
+
});
|
|
11347
|
+
}
|
|
11348
|
+
for (let i = 0; i < heads.length; i++) {
|
|
11349
|
+
const h = heads[i];
|
|
11350
|
+
const startLine = h.line;
|
|
11351
|
+
const endLine = i + 1 < heads.length ? heads[i + 1].line - 1 : lines.length;
|
|
11352
|
+
const body = lines.slice(startLine - 1, endLine).join("\n");
|
|
11353
|
+
out.push({
|
|
11354
|
+
relPath,
|
|
11355
|
+
heading: h.heading,
|
|
11356
|
+
slug: `${relPath}#${slugify(h.heading)}`,
|
|
11357
|
+
depth: h.depth,
|
|
11358
|
+
words: tokenize(body),
|
|
11359
|
+
preview: makePreview(body),
|
|
11360
|
+
startLine,
|
|
11361
|
+
endLine
|
|
11362
|
+
});
|
|
11363
|
+
}
|
|
11364
|
+
return out;
|
|
11365
|
+
}
|
|
11366
|
+
function makePreview(body) {
|
|
11367
|
+
const trimmed = body.replace(/^#{1,6}\s+.+$\r?\n?/m, "").trim();
|
|
11368
|
+
if (trimmed.length <= PREVIEW_CHARS) return trimmed;
|
|
11369
|
+
return trimmed.slice(0, PREVIEW_CHARS) + "\u2026";
|
|
11370
|
+
}
|
|
11371
|
+
function slugify(text2) {
|
|
11372
|
+
return text2.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
11373
|
+
}
|
|
11374
|
+
function extractWikiLinks(text2) {
|
|
11375
|
+
const seen = /* @__PURE__ */ new Set();
|
|
11376
|
+
let m;
|
|
11377
|
+
WIKI_LINK_RE.lastIndex = 0;
|
|
11378
|
+
while ((m = WIKI_LINK_RE.exec(text2)) !== null) {
|
|
11379
|
+
const target = m[1].trim();
|
|
11380
|
+
if (target.length > 0) seen.add(target);
|
|
11381
|
+
}
|
|
11382
|
+
return [...seen].sort();
|
|
11383
|
+
}
|
|
11384
|
+
function byteLength3(s) {
|
|
11385
|
+
return new TextEncoder().encode(s).byteLength;
|
|
11386
|
+
}
|
|
11387
|
+
|
|
10229
11388
|
// src/index.ts
|
|
10230
11389
|
init_orchestrate();
|
|
10231
11390
|
init_planParser();
|
|
@@ -10300,6 +11459,7 @@ function resolveApiKey(config) {
|
|
|
10300
11459
|
WebhookDispatcher,
|
|
10301
11460
|
adaptMcpTool,
|
|
10302
11461
|
buildForkedMessages,
|
|
11462
|
+
buildKnowledgeIndex,
|
|
10303
11463
|
buildPermissionPolicy,
|
|
10304
11464
|
buildSchemaPrompt,
|
|
10305
11465
|
buildSystemPrompt,
|
|
@@ -10307,16 +11467,21 @@ function resolveApiKey(config) {
|
|
|
10307
11467
|
canSpawnProcesses,
|
|
10308
11468
|
capabilityStub,
|
|
10309
11469
|
createApiCallTool,
|
|
11470
|
+
createFetchDataTool,
|
|
10310
11471
|
createLogger,
|
|
10311
11472
|
createModelAdapter,
|
|
11473
|
+
createReadKnowledgeTool,
|
|
11474
|
+
createSearchKnowledgeTool,
|
|
10312
11475
|
createSendMessageTool,
|
|
10313
11476
|
createSkillPageTool,
|
|
10314
11477
|
createSmartMemory,
|
|
10315
11478
|
defaultSamplingHandler,
|
|
11479
|
+
defaultToolResultSummarizer,
|
|
10316
11480
|
defineTool,
|
|
10317
11481
|
detectRuntime,
|
|
10318
11482
|
getCoordinatorBasePrompt,
|
|
10319
11483
|
getCoordinatorSystemPrompt,
|
|
11484
|
+
getExtractor,
|
|
10320
11485
|
hasProcessLifecycle,
|
|
10321
11486
|
initEngine,
|
|
10322
11487
|
isCoordinatorMode,
|
|
@@ -10339,6 +11504,7 @@ function resolveApiKey(config) {
|
|
|
10339
11504
|
toResponse,
|
|
10340
11505
|
tryParseJSON,
|
|
10341
11506
|
validateOutput,
|
|
10342
|
-
withCapabilityCheck
|
|
11507
|
+
withCapabilityCheck,
|
|
11508
|
+
writeKnowledgeIndex
|
|
10343
11509
|
});
|
|
10344
11510
|
//# sourceMappingURL=index.cjs.map
|