@linghun/tui 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/background-control-runtime.js +29 -29
- package/dist/cache-command-runtime.js +3 -3
- package/dist/capability-runtime.js +17 -17
- package/dist/{chunk-QD4SCW4A.js → chunk-2JFSRRK7.js} +21 -21
- package/dist/{chunk-6JPUBF7B.js → chunk-2JZBPXHF.js} +12 -12
- package/dist/{chunk-J7AAPUTV.js → chunk-33WA4BDG.js} +4 -4
- package/dist/{chunk-NWZ44SFI.js → chunk-3KRRVLS4.js} +111 -78
- package/dist/{chunk-ZPFOP557.js → chunk-4UER2AKI.js} +0 -190
- package/dist/{chunk-YBTXLLO5.js → chunk-7ODJHN53.js} +1 -1
- package/dist/{chunk-6DBBXNEG.js → chunk-7VGFNZPN.js} +38 -2
- package/dist/{chunk-QXV2N4F2.js → chunk-AFNWUI6R.js} +1 -1
- package/dist/{chunk-G7O26P5X.js → chunk-BRNV6757.js} +1 -1
- package/dist/{chunk-7XAOTGHZ.js → chunk-CL3U56EI.js} +1 -1
- package/dist/{chunk-OH35XDD4.js → chunk-HMGGPN4J.js} +1 -1
- package/dist/{chunk-CQCJGMXG.js → chunk-IU7NZO6B.js} +2 -2
- package/dist/{chunk-3LT6OWQ2.js → chunk-IWBV4CEI.js} +1 -1
- package/dist/{chunk-DEIYY6NI.js → chunk-JY2DO7OF.js} +4 -155
- package/dist/{chunk-OV5OT66G.js → chunk-KI7NO6IF.js} +216 -5
- package/dist/{chunk-KKZBBCHK.js → chunk-NL4M3V5D.js} +1 -1
- package/dist/{chunk-IQS34W5A.js → chunk-NR3MFRPO.js} +1 -1
- package/dist/{chunk-ESAACKVG.js → chunk-R7BB45CP.js} +1 -1
- package/dist/{chunk-RDTVAQBD.js → chunk-RKFC3V6A.js} +112 -26
- package/dist/{chunk-PBIPV4LD.js → chunk-RMXEIZYR.js} +1 -1
- package/dist/{chunk-4TO2LDMP.js → chunk-SEVD3KES.js} +2 -2
- package/dist/{chunk-5OZEJQBH.js → chunk-T2V2USR3.js} +1 -1
- package/dist/{chunk-XYY5LRSF.js → chunk-T7LHFTVM.js} +3 -3
- package/dist/{chunk-7RZE45OT.js → chunk-UN3MMVE4.js} +1 -1
- package/dist/{chunk-TO6IN4LA.js → chunk-UUWG4VXV.js} +5 -195
- package/dist/{chunk-GYHEUVR2.js → chunk-UYEVRXUA.js} +3 -3
- package/dist/{chunk-RDGM4RUE.js → chunk-VZFP7NWI.js} +1 -1
- package/dist/{chunk-7ZMDQZ22.js → chunk-W6O7KDNM.js} +1 -1
- package/dist/{chunk-2YL5VKJ5.js → chunk-WO56RSMP.js} +1 -1
- package/dist/{chunk-BEDD7OFL.js → chunk-WRVHCSM2.js} +24 -8
- package/dist/{chunk-EGHM55EV.js → chunk-WXQSF2AS.js} +3 -3
- package/dist/{chunk-Q57WS7YZ.js → chunk-ZNAYWBBI.js} +2 -2
- package/dist/command-panel-runtime.js +16 -16
- package/dist/compact-cache-command-runtime.js +29 -29
- package/dist/compact-preflight-runtime.js +10 -10
- package/dist/connector-runtime.js +18 -18
- package/dist/deferred-tools-catalog.d.ts +2 -1
- package/dist/deferred-tools-catalog.d.ts.map +1 -1
- package/dist/deferred-tools-catalog.js +3 -1
- package/dist/details-status-runtime.js +16 -16
- package/dist/evidence-runtime.d.ts.map +1 -1
- package/dist/evidence-runtime.js +6 -6
- package/dist/extension-command-runtime.js +3 -3
- package/dist/extension-slash-runtime.js +17 -17
- package/dist/failure-learning-command-runtime.js +17 -17
- package/dist/final-answer-gate.d.ts +0 -1
- package/dist/final-answer-gate.d.ts.map +1 -1
- package/dist/final-answer-gate.js +2 -4
- package/dist/git-command-runtime.js +17 -17
- package/dist/handoff-session-runtime.js +3 -3
- package/dist/headless-bench-runtime.d.ts +1 -19
- package/dist/headless-bench-runtime.d.ts.map +1 -1
- package/dist/headless-bench-runtime.js +1 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -42
- package/dist/job-agent-command-runtime.js +16 -16
- package/dist/mcp-index-runtime.d.ts +8 -0
- package/dist/mcp-index-runtime.d.ts.map +1 -1
- package/dist/mcp-index-runtime.js +19 -17
- package/dist/memory-command-runtime.js +17 -17
- package/dist/meta-scheduler-runtime.js +2 -2
- package/dist/model-command-runtime.js +17 -17
- package/dist/model-doctor-runtime.d.ts +1 -0
- package/dist/model-doctor-runtime.d.ts.map +1 -1
- package/dist/model-doctor-runtime.js +1 -1
- package/dist/model-loop-runtime.d.ts +15 -1
- package/dist/model-loop-runtime.d.ts.map +1 -1
- package/dist/model-loop-runtime.js +29 -1
- package/dist/model-prompt-runtime.d.ts.map +1 -1
- package/dist/model-prompt-runtime.js +3 -3
- package/dist/model-stream-runtime.js +29 -29
- package/dist/model-tool-runtime.d.ts +7 -0
- package/dist/model-tool-runtime.d.ts.map +1 -1
- package/dist/model-tool-runtime.js +31 -29
- package/dist/permission-approval-runtime.js +29 -29
- package/dist/provider-loop-runtime.js +3 -3
- package/dist/remote-command-runtime.js +17 -17
- package/dist/shell/components/ProductBlock.js +2 -2
- package/dist/shell/components/ShellApp.js +12 -12
- package/dist/shell/ink-renderer.js +12 -12
- package/dist/shell/view-model.js +4 -4
- package/dist/slash-command-runtime.js +29 -29
- package/dist/terminal-readiness-runtime.js +3 -3
- package/dist/tui-agent-job-runtime.js +4 -4
- package/dist/tui-context-runtime.js +3 -3
- package/dist/tui-model-runtime.js +2 -2
- package/dist/tui-output-surface.js +5 -5
- package/dist/verification-command-runtime.js +5 -5
- package/dist/workflow-command-runtime.js +16 -16
- package/package.json +4 -4
- package/dist/{chunk-Z265MCGC.js → chunk-VWEAK3UV.js} +3 -3
|
@@ -55,10 +55,6 @@ async function resolveHeadlessBenchConfig(input) {
|
|
|
55
55
|
testTimeoutMs,
|
|
56
56
|
maxRepairAttempts,
|
|
57
57
|
requiredArtifacts,
|
|
58
|
-
validationContract: createValidationContract({
|
|
59
|
-
prompt: input.prompt,
|
|
60
|
-
requiredArtifacts
|
|
61
|
-
}),
|
|
62
58
|
preflight: input.options?.preflight ?? parseBoolean(env.LINGHUN_HEADLESS_PREFLIGHT) ?? true,
|
|
63
59
|
environmentSetupRetries
|
|
64
60
|
};
|
|
@@ -81,7 +77,6 @@ async function runHeadlessEnvironmentPreflight(projectPath) {
|
|
|
81
77
|
function createHeadlessBenchInitialPrompt(input) {
|
|
82
78
|
if (!input.config.enabled) return input.originalPrompt;
|
|
83
79
|
const required = input.config.requiredArtifacts.length ? `Required artifacts detected: ${input.config.requiredArtifacts.join(", ")}. Verify they exist and are readable before final.` : "No explicit output artifact path was detected; still verify observable task completion.";
|
|
84
|
-
const contract = formatValidationContractPromptLines(input.config.validationContract);
|
|
85
80
|
const test = input.config.testCommand ? `Official test command available: ${input.config.testCommand}. Prefer it over ad-hoc smoke tests before final.` : "No official test command was detected; use the strongest task-local verification available.";
|
|
86
81
|
const preflight = input.preflight ? `Environment preflight: ${input.preflight.summary}` : "";
|
|
87
82
|
return [
|
|
@@ -90,11 +85,9 @@ function createHeadlessBenchInitialPrompt(input) {
|
|
|
90
85
|
"[Linghun headless bench guard]",
|
|
91
86
|
test,
|
|
92
87
|
required,
|
|
93
|
-
...contract,
|
|
94
88
|
preflight,
|
|
95
89
|
formatInitialProfileStrategy(input.config.profile),
|
|
96
90
|
"If rg is unavailable, use grep/find/sed/awk fallbacks instead of failing the task.",
|
|
97
|
-
...formatCommonBenchStabilityGuidance(),
|
|
98
91
|
"Do not claim completion from a self-written smoke test when an official test entrypoint is available."
|
|
99
92
|
].filter(Boolean).join("\n");
|
|
100
93
|
}
|
|
@@ -224,9 +217,7 @@ function createHeadlessBenchRepairPrompt(input) {
|
|
|
224
217
|
"Continue from the current workspace. Do not restart from scratch unless necessary.",
|
|
225
218
|
"Use the official test failure and current files to make the smallest fix, then rerun the official test or artifact check.",
|
|
226
219
|
formatRepairProfileStrategy(input.failure.category, input.profile ?? "generic"),
|
|
227
|
-
...formatCommonBenchStabilityGuidance(),
|
|
228
220
|
input.preflight?.missingTools.includes("rg") ? "rg is missing in this environment; use grep/find/sed/awk fallbacks." : "",
|
|
229
|
-
...formatValidationContractPromptLines(input.validationContract),
|
|
230
221
|
artifactLine,
|
|
231
222
|
logLine,
|
|
232
223
|
"",
|
|
@@ -237,183 +228,6 @@ function createHeadlessBenchRepairPrompt(input) {
|
|
|
237
228
|
input.originalPrompt
|
|
238
229
|
].filter(Boolean).join("\n");
|
|
239
230
|
}
|
|
240
|
-
function createValidationContract(input) {
|
|
241
|
-
const items = [];
|
|
242
|
-
for (const path of input.requiredArtifacts) {
|
|
243
|
-
pushValidationContractItem(items, {
|
|
244
|
-
id: `artifact:${path}`,
|
|
245
|
-
kind: "artifact",
|
|
246
|
-
path,
|
|
247
|
-
requiredTool: "Bash.artifact"
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
for (const target of detectExplicitServiceTargets(input.prompt)) {
|
|
251
|
-
const semanticTokens = detectServiceSemanticTokens(input.prompt);
|
|
252
|
-
const semantic = semanticTokens.length >= 2 && hasSemanticServiceExpectation(input.prompt);
|
|
253
|
-
const validationTarget = semantic ? normalizeServiceReadinessTarget(target) : target;
|
|
254
|
-
pushValidationContractItem(items, {
|
|
255
|
-
id: `service:${validationTarget}`,
|
|
256
|
-
kind: "service",
|
|
257
|
-
target: validationTarget,
|
|
258
|
-
validation: semantic ? "semantic" : "readiness",
|
|
259
|
-
...semantic ? { semanticTokens } : {},
|
|
260
|
-
requiredTool: "Bash.service"
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
if (hasPreservationRequirement(input.prompt)) {
|
|
264
|
-
for (const path of detectEngineeringArtifactTargets(input.prompt)) {
|
|
265
|
-
pushValidationContractItem(items, {
|
|
266
|
-
id: `preservation:${path}`,
|
|
267
|
-
kind: "preservation",
|
|
268
|
-
path,
|
|
269
|
-
requiredTool: "Bash.artifact"
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
for (const path of uniqueStrings([
|
|
274
|
-
...input.requiredArtifacts.filter(isBinaryLikePath),
|
|
275
|
-
...detectEngineeringArtifactTargets(input.prompt).filter(
|
|
276
|
-
(path2) => isBinaryLikePath(path2) || hasBinaryRequirementNearPath(input.prompt, path2)
|
|
277
|
-
)
|
|
278
|
-
])) {
|
|
279
|
-
pushValidationContractItem(items, {
|
|
280
|
-
id: `binary:${path}`,
|
|
281
|
-
kind: "binary",
|
|
282
|
-
path,
|
|
283
|
-
requiredTool: "Bash.binary"
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
|
-
return { items };
|
|
287
|
-
}
|
|
288
|
-
function pushValidationContractItem(items, item) {
|
|
289
|
-
if (items.some(
|
|
290
|
-
(existing) => existing.kind === item.kind && existing.path === item.path && normalizeContractTarget(existing.target) === normalizeContractTarget(item.target)
|
|
291
|
-
)) {
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
items.push(item);
|
|
295
|
-
}
|
|
296
|
-
function formatValidationContractPromptLines(contract) {
|
|
297
|
-
if (!contract?.items.length) return [];
|
|
298
|
-
return [
|
|
299
|
-
"Validation contract: before final, satisfy each item with the required explicit tool.",
|
|
300
|
-
...contract.items.map((item) => {
|
|
301
|
-
const subject = item.path ?? item.target ?? item.id;
|
|
302
|
-
const semantic = item.kind === "service" && item.validation === "semantic" ? `; also run semantic request/response probes for expected fields/values (${(item.semanticTokens ?? []).join(", ")}) including representative and adversarial cases` : "";
|
|
303
|
-
return `- ${item.kind}: ${subject}; required Bash input: ${formatValidationContractToolInput(item)}${semantic}`;
|
|
304
|
-
})
|
|
305
|
-
];
|
|
306
|
-
}
|
|
307
|
-
function formatValidationContractToolInput(item) {
|
|
308
|
-
if (item.requiredTool === "Bash.service") {
|
|
309
|
-
const target = item.target ?? "http://127.0.0.1:PORT/";
|
|
310
|
-
const url = target.startsWith("http://") || target.startsWith("https://") ? target : `http://${target}`;
|
|
311
|
-
return `{ "service": { "action": "fetch", "url": ${JSON.stringify(url)}, "expectStatus": 200, "retry": 5 } }`;
|
|
312
|
-
}
|
|
313
|
-
if (item.requiredTool === "Bash.binary") {
|
|
314
|
-
return `{ "binary": { "path": ${JSON.stringify(item.path ?? "PATH")} } }`;
|
|
315
|
-
}
|
|
316
|
-
if (item.kind === "preservation") {
|
|
317
|
-
return `{ "artifact": { "path": ${JSON.stringify(item.path ?? "PATH")}, "preserve": { "mode": "compareNormalizedHtml", "expectedPath": "EXPECTED_PATH" } } }`;
|
|
318
|
-
}
|
|
319
|
-
return `{ "artifact": { "path": ${JSON.stringify(item.path ?? "PATH")} } }`;
|
|
320
|
-
}
|
|
321
|
-
function detectExplicitServiceTargets(prompt) {
|
|
322
|
-
const targets = [];
|
|
323
|
-
const urlPattern = /https?:\/\/(?:localhost|127\.0\.0\.1)(?::\d{1,5})?(?:\/[^\s`"')\]}<>]*)?/giu;
|
|
324
|
-
for (const match of prompt.matchAll(urlPattern)) {
|
|
325
|
-
targets.push(normalizeServiceTarget(match[0]));
|
|
326
|
-
}
|
|
327
|
-
const hostPortPattern = /\b(?:localhost|127\.0\.0\.1):\d{1,5}\b/giu;
|
|
328
|
-
for (const match of prompt.matchAll(hostPortPattern)) {
|
|
329
|
-
targets.push(normalizeServiceTarget(match[0]));
|
|
330
|
-
}
|
|
331
|
-
if (hasExplicitServicePortContext(prompt)) {
|
|
332
|
-
const portPattern = /\b(?:port\s+(\d{1,5})|listen(?:ing)?(?:\s+on)?\s+(?:port\s+)?(\d{1,5})|localhost\s+port\s+(\d{1,5})|127\.0\.0\.1\s+port\s+(\d{1,5}))\b/giu;
|
|
333
|
-
for (const match of prompt.matchAll(portPattern)) {
|
|
334
|
-
const port = match[1] ?? match[2] ?? match[3] ?? match[4];
|
|
335
|
-
if (port) targets.push(`127.0.0.1:${port}`);
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
return uniqueStrings(targets).filter(hasValidServicePort);
|
|
339
|
-
}
|
|
340
|
-
function hasExplicitServicePortContext(prompt) {
|
|
341
|
-
return /\b(?:service|server|serve|listen|http|endpoint|health|localhost|127\.0\.0\.1)\b/iu.test(prompt);
|
|
342
|
-
}
|
|
343
|
-
function hasSemanticServiceExpectation(prompt) {
|
|
344
|
-
return /\b(?:api|endpoint|json|response|respond|return|schema|field|classification|sentiment|confidence|prediction|inference|request)\b|接口|响应|返回|字段|分类|预测/iu.test(
|
|
345
|
-
prompt
|
|
346
|
-
);
|
|
347
|
-
}
|
|
348
|
-
function detectServiceSemanticTokens(prompt) {
|
|
349
|
-
const tokens = [];
|
|
350
|
-
for (const match of prompt.matchAll(/["']([A-Za-z][A-Za-z0-9_-]{1,39})["']\s*:/gu)) {
|
|
351
|
-
tokens.push(match[1]);
|
|
352
|
-
}
|
|
353
|
-
for (const match of prompt.matchAll(/\b(?:positive|negative|true|false|pass|fail|success|error|valid|invalid)\b/giu)) {
|
|
354
|
-
tokens.push(match[0].toLowerCase());
|
|
355
|
-
}
|
|
356
|
-
return uniqueStrings(tokens).slice(0, 8);
|
|
357
|
-
}
|
|
358
|
-
function normalizeServiceTarget(value) {
|
|
359
|
-
return value.replace(/[),.;!?]+$/u, "");
|
|
360
|
-
}
|
|
361
|
-
function normalizeServiceReadinessTarget(target) {
|
|
362
|
-
try {
|
|
363
|
-
const url = target.startsWith("http://") || target.startsWith("https://") ? new URL(target) : new URL(`http://${target}`);
|
|
364
|
-
return target.startsWith("http://") || target.startsWith("https://") ? url.origin : `${url.hostname}:${url.port || (url.protocol === "https:" ? "443" : "80")}`;
|
|
365
|
-
} catch {
|
|
366
|
-
return target;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
function normalizeContractTarget(target) {
|
|
370
|
-
if (!target) return void 0;
|
|
371
|
-
try {
|
|
372
|
-
const url = target.startsWith("http://") || target.startsWith("https://") ? new URL(target) : new URL(`http://${target}`);
|
|
373
|
-
const port = url.port || (url.protocol === "https:" ? "443" : "80");
|
|
374
|
-
const path = url.pathname.replace(/\/$/u, "");
|
|
375
|
-
return `${url.hostname}:${port}${path}`;
|
|
376
|
-
} catch {
|
|
377
|
-
return target.replace(/\/$/u, "");
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
function hasValidServicePort(target) {
|
|
381
|
-
try {
|
|
382
|
-
const url = target.startsWith("http://") || target.startsWith("https://") ? new URL(target) : new URL(`http://${target}`);
|
|
383
|
-
const port = Number(url.port || (url.protocol === "https:" ? 443 : 80));
|
|
384
|
-
return Number.isInteger(port) && port > 0 && port <= 65535;
|
|
385
|
-
} catch {
|
|
386
|
-
return false;
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
function hasPreservationRequirement(prompt) {
|
|
390
|
-
return /(?:\bpreserve\b|\bclean\b|\boriginal\b|\bunchanged\b|don't modify|do not modify|不要修改|保持原样|保留原始)/iu.test(
|
|
391
|
-
prompt
|
|
392
|
-
);
|
|
393
|
-
}
|
|
394
|
-
function isBinaryLikePath(path) {
|
|
395
|
-
return /\.(?:bin|elf|so|dll|dylib|exe|o|a|class|wasm|7z|zip|tar|gz|xz|bz2)$/iu.test(path);
|
|
396
|
-
}
|
|
397
|
-
function hasBinaryRequirementNearPath(prompt, path) {
|
|
398
|
-
const index = prompt.indexOf(path);
|
|
399
|
-
if (index < 0) return false;
|
|
400
|
-
const window = prompt.slice(Math.max(0, index - 80), Math.min(prompt.length, index + path.length + 80));
|
|
401
|
-
return /(?:\bbinary\b|\bELF\b|二进制)/iu.test(window);
|
|
402
|
-
}
|
|
403
|
-
function formatCommonBenchStabilityGuidance() {
|
|
404
|
-
return [
|
|
405
|
-
"Command environment: prefer python3 over bare python. If a command reports python not found, treat it as recoverable and retry with python3.",
|
|
406
|
-
'Python dependencies: before relying on optional imports, probe with python3 -c "import X"; install only when appropriate, otherwise use a stdlib fallback.',
|
|
407
|
-
"Services: after starting HTTP/gRPC/server processes, poll the port or health endpoint with a bounded timeout and inspect logs before final verification.",
|
|
408
|
-
"Time budget: build the smallest verifiable solution first, run focused checks early, and avoid long blind builds/training runs near the deadline.",
|
|
409
|
-
"Verifier alignment: read task-local tests/verifier expectations and confirm output path, filename, port, and answer format instead of only matching examples.",
|
|
410
|
-
"Artifact checks: match validation commands to the artifact language or file type; do not run shell syntax checks on Python/JS/C++ source files.",
|
|
411
|
-
"Preservation tasks: when unchanged/clean/original content must survive, avoid parser/serializer round-trips unless tests allow reformatting; make targeted edits and compare preserved regions.",
|
|
412
|
-
"Sanitizer/filter tasks: run negative clean-sample checks that compare parser-normalized or whitespace-stripped output against the original; unsafe-case smoke tests alone are not enough.",
|
|
413
|
-
"Answer extraction: inspect tests/expected files for required count, ordering, and multi-line answers; do not stop at the first plausible value when the verifier expects multiple outputs.",
|
|
414
|
-
"Puzzle answer tasks: if multiple equally optimal or valid answers can exist and the output format allows a list, enumerate all required answers rather than a single example."
|
|
415
|
-
];
|
|
416
|
-
}
|
|
417
231
|
async function detectHeadlessBenchTaskProfile(input) {
|
|
418
232
|
const files = await listProjectFiles(input.projectPath, 220);
|
|
419
233
|
const haystack = `${input.prompt}
|
|
@@ -553,9 +367,6 @@ function formatRepairProfileStrategy(category, profile) {
|
|
|
553
367
|
if (category === "missing_artifact") {
|
|
554
368
|
return "Repair route: generate or write the required artifact now, then verify it exists, is readable, and is non-empty.";
|
|
555
369
|
}
|
|
556
|
-
if (category === "validation_contract") {
|
|
557
|
-
return "Repair route: run the required explicit validation tool for the contract item, then repair any failed evidence before final.";
|
|
558
|
-
}
|
|
559
370
|
if (category === "test_timeout") {
|
|
560
371
|
return "Repair route: narrow validation to focused tests or logs first; avoid repeatedly launching full expensive runs.";
|
|
561
372
|
}
|
|
@@ -816,7 +627,6 @@ export {
|
|
|
816
627
|
collectHeadlessArtifactChecklist,
|
|
817
628
|
classifyEnvironmentSetupFailure,
|
|
818
629
|
createHeadlessBenchRepairPrompt,
|
|
819
|
-
createValidationContract,
|
|
820
630
|
detectHeadlessBenchTaskProfile,
|
|
821
631
|
detectEngineeringTaskProfile,
|
|
822
632
|
classifyHeadlessFailure,
|
|
@@ -75,6 +75,28 @@ var CODEBASE_MEMORY_DESCRIPTIONS = {
|
|
|
75
75
|
trace_path: "Trace a function call chain from -> to in an indexed project.",
|
|
76
76
|
search_graph: "Find similar implementations / SIMILAR_TO entries in a project."
|
|
77
77
|
};
|
|
78
|
+
var PRE_ENGINE_DESCRIPTIONS = {
|
|
79
|
+
pre_context: "Repository analysis: provide structured code facts (AST-based) for the current task context.",
|
|
80
|
+
pre_impact: "Repository impact analysis: analyze planned change scope via AST cross-references.",
|
|
81
|
+
pre_plan: "Repository edit planning: generate structured implementation hints from AST analysis.",
|
|
82
|
+
pre_verify: "Repository analysis verification: verify code change correctness via AST structural checks."
|
|
83
|
+
};
|
|
84
|
+
var PRE_ENGINE_REQUIRED_ARGS = {
|
|
85
|
+
pre_context: ["symbol"],
|
|
86
|
+
pre_impact: ["changes"],
|
|
87
|
+
pre_plan: ["task"],
|
|
88
|
+
pre_verify: ["changed_files"]
|
|
89
|
+
};
|
|
90
|
+
function listPreEngineDeferredTools() {
|
|
91
|
+
return Object.keys(PRE_ENGINE_DESCRIPTIONS).sort((a, b) => a.localeCompare(b)).map((name) => ({
|
|
92
|
+
name,
|
|
93
|
+
kind: "pre-engine",
|
|
94
|
+
description: PRE_ENGINE_DESCRIPTIONS[name] ?? `pre-engine tool: ${name}`,
|
|
95
|
+
requiredArgs: PRE_ENGINE_REQUIRED_ARGS[name] ?? [],
|
|
96
|
+
executable: true,
|
|
97
|
+
reason: "pre-engine static whitelist; readonly AST query, no mutation."
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
78
100
|
function listCodebaseMemoryDeferredTools() {
|
|
79
101
|
const required = codebaseMemoryRequiredArgs();
|
|
80
102
|
return Object.keys(required).sort((a, b) => a.localeCompare(b)).map((name) => ({
|
|
@@ -161,6 +183,7 @@ function pluginManifestHasContribution(plugin) {
|
|
|
161
183
|
function listDeferredTools(context) {
|
|
162
184
|
return [
|
|
163
185
|
...listCodebaseMemoryDeferredTools(),
|
|
186
|
+
...listPreEngineDeferredTools(),
|
|
164
187
|
...listMcpDeferredTools(context),
|
|
165
188
|
...listSkillDeferredTools(context),
|
|
166
189
|
...listPluginDeferredTools(context)
|
|
@@ -170,6 +193,7 @@ function snapshotDeferredTools(context) {
|
|
|
170
193
|
const tools = listDeferredTools(context);
|
|
171
194
|
const byKind = {
|
|
172
195
|
"codebase-memory": 0,
|
|
196
|
+
"pre-engine": 0,
|
|
173
197
|
mcp: 0,
|
|
174
198
|
skill: 0,
|
|
175
199
|
plugin: 0
|
|
@@ -195,6 +219,13 @@ function snapshotDeferredToolsSummary(context) {
|
|
|
195
219
|
executableCount: snapshot.executableCount
|
|
196
220
|
};
|
|
197
221
|
}
|
|
222
|
+
function registerPreEngineDeferredToolsForRuntime(context, snapshot) {
|
|
223
|
+
const names = snapshot.tools.filter((tool) => tool.kind === "pre-engine" && tool.executable).map((tool) => tool.name).sort((a, b) => a.localeCompare(b));
|
|
224
|
+
for (const name of names) {
|
|
225
|
+
context.discoveredDeferredToolNames.add(name);
|
|
226
|
+
}
|
|
227
|
+
return names;
|
|
228
|
+
}
|
|
198
229
|
var DISCOVERED_NAME_MAX_LEN = 80;
|
|
199
230
|
var DISCOVERED_NAMES_MAX_COUNT = 32;
|
|
200
231
|
function sanitizeDiscoveredDeferredToolName(name) {
|
|
@@ -217,9 +248,13 @@ function snapshotDiscoveredDeferredToolsSummary(context) {
|
|
|
217
248
|
function searchDeferredTools(query, tools) {
|
|
218
249
|
const trimmed = query.trim().toLowerCase();
|
|
219
250
|
if (trimmed === "") return tools;
|
|
251
|
+
const tokens = trimmed.split(/[^a-z0-9_:.-]+/u).filter((token) => token.length >= 3);
|
|
220
252
|
return tools.filter((tool) => {
|
|
221
253
|
const haystack = `${tool.name} ${tool.description} ${tool.kind}`.toLowerCase();
|
|
222
|
-
|
|
254
|
+
if (haystack.includes(trimmed)) return true;
|
|
255
|
+
if (tokens.length === 0) return false;
|
|
256
|
+
const hits = tokens.filter((token) => haystack.includes(token)).length;
|
|
257
|
+
return hits >= Math.min(2, tokens.length);
|
|
223
258
|
});
|
|
224
259
|
}
|
|
225
260
|
function findDeferredTool(toolName, tools) {
|
|
@@ -235,7 +270,7 @@ function deferredToolListHashInput(tools) {
|
|
|
235
270
|
}
|
|
236
271
|
function formatDeferredToolsSystemReminder(language, snapshot) {
|
|
237
272
|
if (snapshot.total === 0) return void 0;
|
|
238
|
-
return language === "en-US" ? "Additional tools must be discovered via SearchExtraTools, then invoked via ExecuteExtraTool. Built-in tools (Read/ReadSnippets/SourcePack/Edit/Write/Bash/Grep/Glob/Todo) are still called directly." : "Additional tools must be discovered via SearchExtraTools, then invoked via ExecuteExtraTool.";
|
|
273
|
+
return language === "en-US" ? "Additional tools must be discovered via SearchExtraTools, then invoked via ExecuteExtraTool. For repository code understanding, impact analysis, edit planning, or quick verification, discover specialized repository tools before broad manual exploration. If codebase-memory index is ready, prefer index-backed search/graph/architecture tools for broad repository discovery, then use pre-engine for AST precision; if the index is missing or stale, use pre-engine as the fast repository-analysis entry. Built-in tools (Read/ReadSnippets/SourcePack/Edit/Write/Bash/Grep/Glob/Todo) are still called directly." : "Additional tools must be discovered via SearchExtraTools, then invoked via ExecuteExtraTool. For repository code understanding, impact analysis, edit planning, or quick verification, discover specialized repository tools before broad manual exploration. If codebase-memory index is ready, prefer index-backed search/graph/architecture tools for broad repository discovery, then use pre-engine for AST precision; if the index is missing or stale, use pre-engine as the fast repository-analysis entry.";
|
|
239
274
|
}
|
|
240
275
|
function isCodebaseMemoryToolName(name) {
|
|
241
276
|
return name in codebaseMemoryRequiredArgs();
|
|
@@ -268,6 +303,7 @@ export {
|
|
|
268
303
|
listDeferredTools,
|
|
269
304
|
snapshotDeferredTools,
|
|
270
305
|
snapshotDeferredToolsSummary,
|
|
306
|
+
registerPreEngineDeferredToolsForRuntime,
|
|
271
307
|
sanitizeDiscoveredDeferredToolName,
|
|
272
308
|
snapshotDiscoveredDeferredToolsSummary,
|
|
273
309
|
searchDeferredTools,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ensureSession,
|
|
3
3
|
showCommandPanel
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-2JZBPXHF.js";
|
|
5
5
|
import {
|
|
6
6
|
decidePermission
|
|
7
7
|
} from "./chunk-PHPEPZAA.js";
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
budgetToolResultTranscriptContent,
|
|
11
11
|
createEvidenceRecord,
|
|
12
12
|
rememberEvidence
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-JY2DO7OF.js";
|
|
14
14
|
import {
|
|
15
15
|
sanitizeDiagnosticText,
|
|
16
16
|
truncateDisplay,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MAX_EVIDENCE_RECORDS
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-VZFP7NWI.js";
|
|
4
4
|
import {
|
|
5
5
|
applyToolResultBudgetToMessages,
|
|
6
6
|
formatToolResultBudgetEvidenceSummary,
|
|
@@ -15,10 +15,10 @@ import {
|
|
|
15
15
|
} from "./chunk-IWUIOLMF.js";
|
|
16
16
|
import {
|
|
17
17
|
writeHandoffPacket
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-W6O7KDNM.js";
|
|
19
19
|
import {
|
|
20
20
|
deriveToolSupportsClaims
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-3KRRVLS4.js";
|
|
22
22
|
import {
|
|
23
23
|
mergeFailureRecord,
|
|
24
24
|
writeFailureRecord
|
|
@@ -234,10 +234,6 @@ async function recordToolEvidence(context, sessionId, name, output, input) {
|
|
|
234
234
|
output.fullOutputPath ?? name,
|
|
235
235
|
supportsClaims
|
|
236
236
|
);
|
|
237
|
-
const semanticProbe = supportsClaims.includes("bash_exit_0") ? compactSemanticProbeEvidence(context, output, input) : void 0;
|
|
238
|
-
if (semanticProbe) {
|
|
239
|
-
evidence.data = { ...typeof evidence.data === "object" && evidence.data ? evidence.data : {}, semanticProbe };
|
|
240
|
-
}
|
|
241
237
|
rememberEvidence(context, evidence);
|
|
242
238
|
await context.store.appendEvent(sessionId, {
|
|
243
239
|
type: "evidence_record",
|
|
@@ -498,23 +494,14 @@ function compactToolOutputDataForTranscript(data) {
|
|
|
498
494
|
};
|
|
499
495
|
}
|
|
500
496
|
function compactToolStructuredDataForTranscript(data) {
|
|
501
|
-
const compact = {};
|
|
502
497
|
const diagnostics = compactDiagnosticsDataForTranscript(data);
|
|
503
|
-
|
|
504
|
-
if (diagnostics) Object.assign(compact, diagnostics);
|
|
505
|
-
if (validationEvidence) Object.assign(compact, validationEvidence);
|
|
506
|
-
return Object.keys(compact).length > 0 ? compact : void 0;
|
|
498
|
+
return diagnostics;
|
|
507
499
|
}
|
|
508
500
|
function compactDiagnosticsDataForTranscript(data) {
|
|
509
501
|
const diagnostics = readDiagnosticsForTranscript(data);
|
|
510
502
|
if (!diagnostics) return void 0;
|
|
511
503
|
return { diagnostics };
|
|
512
504
|
}
|
|
513
|
-
function compactValidationEvidenceDataForTranscript(data) {
|
|
514
|
-
const validationEvidence = readValidationEvidenceForTranscript(data);
|
|
515
|
-
if (!validationEvidence) return void 0;
|
|
516
|
-
return { validationEvidence };
|
|
517
|
-
}
|
|
518
505
|
function readDiagnosticsForTranscript(data) {
|
|
519
506
|
if (!data || typeof data !== "object") return void 0;
|
|
520
507
|
const diagnostics = data.diagnostics;
|
|
@@ -638,45 +625,8 @@ function compactToolEvidenceData(data) {
|
|
|
638
625
|
for (const key of ["service", "serviceHint", "artifactHint", "binaryHint", "binaryPreflight"]) {
|
|
639
626
|
if (record[key] !== void 0) compact[key] = record[key];
|
|
640
627
|
}
|
|
641
|
-
const validationEvidence = readValidationEvidenceForTranscript(data);
|
|
642
|
-
if (validationEvidence) compact.validationEvidence = validationEvidence;
|
|
643
628
|
return Object.keys(compact).length > 0 ? compact : void 0;
|
|
644
629
|
}
|
|
645
|
-
function compactSemanticProbeEvidence(context, output, input) {
|
|
646
|
-
const tokens = collectSemanticContractTokens(context);
|
|
647
|
-
if (tokens.length === 0) return void 0;
|
|
648
|
-
if (!looksLikeServiceProbeCommand(input)) return void 0;
|
|
649
|
-
const haystack = [output.text, output.summary, output.preview].filter((item) => typeof item === "string" && item.length > 0).join("\n").toLowerCase();
|
|
650
|
-
if (!haystack) return void 0;
|
|
651
|
-
const matched = tokens.filter((token) => haystack.includes(token.toLowerCase()));
|
|
652
|
-
const required = Math.min(2, tokens.length);
|
|
653
|
-
if (matched.length < required) return void 0;
|
|
654
|
-
return { tokens: matched.slice(0, 12) };
|
|
655
|
-
}
|
|
656
|
-
function looksLikeServiceProbeCommand(input) {
|
|
657
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) return false;
|
|
658
|
-
const command = input.command;
|
|
659
|
-
if (typeof command !== "string") return false;
|
|
660
|
-
return /\b(?:curl|wget|http|httpie|python|python3|node|deno|ruby|perl|php)\b|(?:requests|fetch|urllib|http\.client|axios|localhost|127\.0\.0\.1)/iu.test(
|
|
661
|
-
command
|
|
662
|
-
);
|
|
663
|
-
}
|
|
664
|
-
function collectSemanticContractTokens(context) {
|
|
665
|
-
const tools = context.tools;
|
|
666
|
-
if (tools.headlessBench?.enabled !== true) return [];
|
|
667
|
-
const tokens = /* @__PURE__ */ new Set();
|
|
668
|
-
for (const item of tools.validationContract?.items ?? []) {
|
|
669
|
-
if (item.kind !== "service" || item.validation !== "semantic" || !Array.isArray(item.semanticTokens)) {
|
|
670
|
-
continue;
|
|
671
|
-
}
|
|
672
|
-
for (const token of item.semanticTokens) {
|
|
673
|
-
if (typeof token === "string" && token.trim()) {
|
|
674
|
-
tokens.add(token.trim());
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
return [...tokens];
|
|
679
|
-
}
|
|
680
630
|
function rememberRecentDiagnostics(context, source, content, toolUseId, evidenceId) {
|
|
681
631
|
const diagnostics = readDiagnosticsForTranscript(content?.data);
|
|
682
632
|
if (!diagnostics || diagnostics.length === 0) return;
|
|
@@ -706,107 +656,6 @@ function appendToolResultContentDiagnostics(content) {
|
|
|
706
656
|
text: diagnostics ? appendCompactDiagnostics(output.text, diagnostics) : output.text
|
|
707
657
|
};
|
|
708
658
|
}
|
|
709
|
-
function readValidationEvidenceForTranscript(data) {
|
|
710
|
-
if (!data || typeof data !== "object") return void 0;
|
|
711
|
-
const record = data;
|
|
712
|
-
const entries = [
|
|
713
|
-
readArtifactValidationEvidence(record),
|
|
714
|
-
readPreservationValidationEvidence(record),
|
|
715
|
-
readServiceValidationEvidence(record),
|
|
716
|
-
readBinaryValidationEvidence(record)
|
|
717
|
-
].filter((item) => Boolean(item));
|
|
718
|
-
return entries.length > 0 ? entries : void 0;
|
|
719
|
-
}
|
|
720
|
-
function readArtifactValidationEvidence(record) {
|
|
721
|
-
const artifact = readRecord(record.artifact);
|
|
722
|
-
if (!artifact) return void 0;
|
|
723
|
-
const path = readString(artifact.path);
|
|
724
|
-
if (!path) return void 0;
|
|
725
|
-
return {
|
|
726
|
-
kind: "artifact",
|
|
727
|
-
path,
|
|
728
|
-
tool: "Bash.artifact",
|
|
729
|
-
ok: record.exitCode === 0 && artifact.exists === true && checksOk(readRecord(artifact.checks)),
|
|
730
|
-
...artifact.checks && typeof artifact.checks === "object" ? { checks: compactArtifactChecks(artifact.checks) } : {}
|
|
731
|
-
};
|
|
732
|
-
}
|
|
733
|
-
function readPreservationValidationEvidence(record) {
|
|
734
|
-
const artifact = readRecord(record.artifact);
|
|
735
|
-
const checks = readRecord(artifact?.checks);
|
|
736
|
-
const preserve = readRecord(checks?.preserve);
|
|
737
|
-
const path = readString(artifact?.path);
|
|
738
|
-
if (!artifact || !checks || !preserve || !path) return void 0;
|
|
739
|
-
return {
|
|
740
|
-
kind: "preservation",
|
|
741
|
-
path,
|
|
742
|
-
tool: "Bash.artifact",
|
|
743
|
-
ok: record.exitCode === 0 && preserve.ok === true,
|
|
744
|
-
checks: { preserve: compactCheckRecord(preserve) }
|
|
745
|
-
};
|
|
746
|
-
}
|
|
747
|
-
function readServiceValidationEvidence(record) {
|
|
748
|
-
const service = readRecord(record.service);
|
|
749
|
-
if (!service) return void 0;
|
|
750
|
-
const target = readString(service.target) ?? readServiceTargetFromHostPort(service);
|
|
751
|
-
if (!target) return void 0;
|
|
752
|
-
const readiness = readRecord(service.readiness);
|
|
753
|
-
const fetch = readRecord(service.fetch);
|
|
754
|
-
return {
|
|
755
|
-
kind: "service",
|
|
756
|
-
target,
|
|
757
|
-
tool: "Bash.service",
|
|
758
|
-
ok: record.exitCode === 0 && (service.ready === true || readiness?.ok === true),
|
|
759
|
-
...readiness || fetch ? { checks: { ...readiness ? { readiness: compactCheckRecord(readiness) } : {}, ...fetch ? { fetch: compactCheckRecord(fetch) } : {} } } : {}
|
|
760
|
-
};
|
|
761
|
-
}
|
|
762
|
-
function readBinaryValidationEvidence(record) {
|
|
763
|
-
const binary = readRecord(record.binary);
|
|
764
|
-
if (!binary) return void 0;
|
|
765
|
-
const path = readString(binary.path);
|
|
766
|
-
if (!path) return void 0;
|
|
767
|
-
return {
|
|
768
|
-
kind: "binary",
|
|
769
|
-
path,
|
|
770
|
-
tool: "Bash.binary",
|
|
771
|
-
ok: record.exitCode === 0,
|
|
772
|
-
checks: compactCheckRecord(binary)
|
|
773
|
-
};
|
|
774
|
-
}
|
|
775
|
-
function readRecord(value) {
|
|
776
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
777
|
-
}
|
|
778
|
-
function readString(value) {
|
|
779
|
-
return typeof value === "string" && value.trim() ? value : void 0;
|
|
780
|
-
}
|
|
781
|
-
function readServiceTargetFromHostPort(service) {
|
|
782
|
-
const host = readString(service.targetHost);
|
|
783
|
-
const port = typeof service.targetPort === "number" ? service.targetPort : void 0;
|
|
784
|
-
return host && port !== void 0 ? `${host}:${port}` : void 0;
|
|
785
|
-
}
|
|
786
|
-
function checksOk(checks) {
|
|
787
|
-
if (!checks) return true;
|
|
788
|
-
return Object.values(checks).every((value) => {
|
|
789
|
-
const check = readRecord(value);
|
|
790
|
-
return !check || check.ok !== false;
|
|
791
|
-
});
|
|
792
|
-
}
|
|
793
|
-
function compactArtifactChecks(value) {
|
|
794
|
-
const checks = readRecord(value);
|
|
795
|
-
if (!checks) return {};
|
|
796
|
-
const compact = {};
|
|
797
|
-
for (const key of ["header", "json", "executable", "text", "preserve"]) {
|
|
798
|
-
const check = readRecord(checks[key]);
|
|
799
|
-
if (check) compact[key] = compactCheckRecord(check);
|
|
800
|
-
}
|
|
801
|
-
return compact;
|
|
802
|
-
}
|
|
803
|
-
function compactCheckRecord(record) {
|
|
804
|
-
const compact = {};
|
|
805
|
-
for (const key of ["ok", "mode", "status", "expectedStatus", "missingBody", "contains", "lineSet", "exact", "magic", "size"]) {
|
|
806
|
-
if (record[key] !== void 0) compact[key] = record[key];
|
|
807
|
-
}
|
|
808
|
-
return compact;
|
|
809
|
-
}
|
|
810
659
|
async function budgetToolResultTranscriptContent(context, sessionId, toolUseId, content) {
|
|
811
660
|
const contentText = stringifyToolResultContentForBudget(content);
|
|
812
661
|
if (!contentText || contentText.startsWith("<persisted-tool-result>")) return content;
|