reasonix 0.47.2 → 0.48.1
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 +14 -26
- package/README.zh-CN.md +5 -26
- package/dist/cli/{acp-GEOAKSTU.js → acp-QJGGHQLA.js} +52 -135
- package/dist/cli/acp-QJGGHQLA.js.map +1 -0
- package/dist/cli/{chat-YTPATMMG.js → chat-ZXF227MP.js} +25 -25
- package/dist/cli/{chunk-DN4B5S6Y.js → chunk-3FULTFRB.js} +2 -2
- package/dist/cli/chunk-43ROGEX2.js +5190 -0
- package/dist/cli/chunk-43ROGEX2.js.map +1 -0
- package/dist/cli/{chunk-DQ6K5ZQ7.js → chunk-4E2BHJU4.js} +4 -4
- package/dist/cli/chunk-4E2BHJU4.js.map +1 -0
- package/dist/cli/{chunk-T5A7EY6B.js → chunk-5AW6NIHU.js} +2 -2
- package/dist/cli/{chunk-DWPAKZTY.js → chunk-5U5LMMFF.js} +2 -2
- package/dist/cli/{chunk-TRSAHHCL.js → chunk-6FRNXWDZ.js} +321 -76
- package/dist/cli/chunk-6FRNXWDZ.js.map +1 -0
- package/dist/cli/{chunk-KYQVQ5X4.js → chunk-B5CZL2SE.js} +9 -4
- package/dist/cli/chunk-B5CZL2SE.js.map +1 -0
- package/dist/cli/{chunk-XMHP7BEE.js → chunk-DABAOQSV.js} +2273 -2517
- package/dist/cli/chunk-DABAOQSV.js.map +1 -0
- package/dist/cli/chunk-EO6RPTJG.js +831 -0
- package/dist/cli/chunk-EO6RPTJG.js.map +1 -0
- package/dist/cli/{chunk-BQ6HC66J.js → chunk-FD7SNDWW.js} +4 -14
- package/dist/cli/chunk-FD7SNDWW.js.map +1 -0
- package/dist/cli/chunk-FPME5QOO.js +17747 -0
- package/dist/cli/chunk-FPME5QOO.js.map +1 -0
- package/dist/cli/{chunk-6QC5RQLE.js → chunk-H2F4LDNH.js} +2 -2
- package/dist/cli/{chunk-QCFLPSPH.js → chunk-IKSYVBBZ.js} +2 -2
- package/dist/cli/{chunk-5QCB62C4.js → chunk-J2TQAWOM.js} +135 -18
- package/dist/cli/{chunk-5QCB62C4.js.map → chunk-J2TQAWOM.js.map} +1 -1
- package/dist/cli/{chunk-JBH5RM7X.js → chunk-JFBGSWQB.js} +395 -85
- package/dist/cli/chunk-JFBGSWQB.js.map +1 -0
- package/dist/cli/{chunk-CCJAP7G3.js → chunk-KH5JIJJD.js} +2 -2
- package/dist/cli/{chunk-TDHXB2ER.js → chunk-NQZ5U37J.js} +2 -2
- package/dist/cli/{chunk-CNG32VAB.js → chunk-O3AGYTG2.js} +2 -2
- package/dist/cli/{chunk-NRQ5UP5T.js → chunk-PIC5HJRD.js} +234 -40
- package/dist/cli/chunk-PIC5HJRD.js.map +1 -0
- package/dist/cli/{chunk-GH7DC2Y5.js → chunk-PJIQIYTV.js} +6 -3
- package/dist/cli/chunk-PJIQIYTV.js.map +1 -0
- package/dist/cli/{chunk-KVZZ5U75.js → chunk-R7U44O3Y.js} +2 -2
- package/dist/cli/{chunk-ZXSCAODE.js → chunk-RCLS63KE.js} +71 -3
- package/dist/cli/chunk-RCLS63KE.js.map +1 -0
- package/dist/cli/{chunk-FY4S7TJZ.js → chunk-SLAFMXAZ.js} +10 -2
- package/dist/cli/chunk-SLAFMXAZ.js.map +1 -0
- package/dist/cli/{chunk-TRWHTFG7.js → chunk-SWUMD2LX.js} +2 -2
- package/dist/cli/{chunk-2XY77LW7.js → chunk-TIJ4ZHD6.js} +56 -24
- package/dist/cli/chunk-TIJ4ZHD6.js.map +1 -0
- package/dist/cli/{chunk-4MFCAZ2W.js → chunk-WKOXKCF3.js} +3 -3
- package/dist/cli/{chunk-HUILPCYX.js → chunk-XMR2VCGT.js} +3 -3
- package/dist/cli/{code-Q4NRVEDG.js → code-OKA5YPOH.js} +31 -32
- package/dist/cli/code-OKA5YPOH.js.map +1 -0
- package/dist/cli/{commands-4CDI4GFM.js → commands-3U6PUVSS.js} +4 -4
- package/dist/cli/{commit-GW7LDQP5.js → commit-HFB7SRBU.js} +3 -3
- package/dist/cli/{desktop-EG6P5SF2.js → desktop-G7UMW3CJ.js} +503 -48
- package/dist/cli/desktop-G7UMW3CJ.js.map +1 -0
- package/dist/cli/{diff-VI2YX4FN.js → diff-PGXW4YZD.js} +8 -8
- package/dist/cli/{doctor-CQTTZP27.js → doctor-WWJFLVCB.js} +9 -9
- package/dist/cli/index.js +53 -41
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/{mcp-J2UCD4RZ.js → mcp-Y3VKIK3T.js} +2 -2
- package/dist/cli/{mcp-browse-GSX34JEK.js → mcp-browse-4IN2QIFR.js} +2 -2
- package/dist/cli/{mcp-inspect-RRFYF4ZV.js → mcp-inspect-BUXFXDHB.js} +2 -2
- package/dist/cli/{prompt-5TQPIVHV.js → prompt-US57R6BA.js} +5 -4
- package/dist/cli/{replay-MJCEMODU.js → replay-EQJMZRB3.js} +8 -8
- package/dist/cli/{run-P4D5VDYE.js → run-KVEI66TR.js} +14 -14
- package/dist/cli/{server-C25JNNZV.js → server-D6C4GHWN.js} +18 -15
- package/dist/cli/server-D6C4GHWN.js.map +1 -0
- package/dist/cli/{sessions-QIONZJQ6.js → sessions-TGVS2RQZ.js} +13 -13
- package/dist/cli/{setup-NLQ6G5G4.js → setup-WLKX6GGG.js} +5 -5
- package/dist/cli/{stats-DFZEXHP4.js → stats-TCD7Q6MB.js} +6 -6
- package/dist/cli/{version-GR3X3MPI.js → version-BCWWS2OU.js} +13 -13
- package/dist/grammars/tree-sitter-go.wasm +0 -0
- package/dist/grammars/tree-sitter-java.wasm +0 -0
- package/dist/grammars/tree-sitter-javascript.wasm +0 -0
- package/dist/grammars/tree-sitter-python.wasm +0 -0
- package/dist/grammars/tree-sitter-rust.wasm +0 -0
- package/dist/grammars/tree-sitter-tsx.wasm +0 -0
- package/dist/grammars/tree-sitter-typescript.wasm +0 -0
- package/dist/grammars/web-tree-sitter.wasm +0 -0
- package/dist/index.d.ts +46 -12
- package/dist/index.js +684 -129
- package/dist/index.js.map +1 -1
- package/package.json +16 -4
- package/dist/cli/acp-GEOAKSTU.js.map +0 -1
- package/dist/cli/chunk-2XY77LW7.js.map +0 -1
- package/dist/cli/chunk-6CRPCJAU.js +0 -3141
- package/dist/cli/chunk-6CRPCJAU.js.map +0 -1
- package/dist/cli/chunk-BQ6HC66J.js.map +0 -1
- package/dist/cli/chunk-DQ6K5ZQ7.js.map +0 -1
- package/dist/cli/chunk-FY4S7TJZ.js.map +0 -1
- package/dist/cli/chunk-GH7DC2Y5.js.map +0 -1
- package/dist/cli/chunk-JBH5RM7X.js.map +0 -1
- package/dist/cli/chunk-KYQVQ5X4.js.map +0 -1
- package/dist/cli/chunk-NRQ5UP5T.js.map +0 -1
- package/dist/cli/chunk-TRSAHHCL.js.map +0 -1
- package/dist/cli/chunk-XD6P7AFH.js +0 -375
- package/dist/cli/chunk-XD6P7AFH.js.map +0 -1
- package/dist/cli/chunk-XMHP7BEE.js.map +0 -1
- package/dist/cli/chunk-YFP3MYMY.js +0 -323
- package/dist/cli/chunk-YFP3MYMY.js.map +0 -1
- package/dist/cli/chunk-ZXSCAODE.js.map +0 -1
- package/dist/cli/code-Q4NRVEDG.js.map +0 -1
- package/dist/cli/desktop-EG6P5SF2.js.map +0 -1
- package/dist/cli/server-C25JNNZV.js.map +0 -1
- /package/dist/cli/{chat-YTPATMMG.js.map → chat-ZXF227MP.js.map} +0 -0
- /package/dist/cli/{chunk-DN4B5S6Y.js.map → chunk-3FULTFRB.js.map} +0 -0
- /package/dist/cli/{chunk-T5A7EY6B.js.map → chunk-5AW6NIHU.js.map} +0 -0
- /package/dist/cli/{chunk-DWPAKZTY.js.map → chunk-5U5LMMFF.js.map} +0 -0
- /package/dist/cli/{chunk-6QC5RQLE.js.map → chunk-H2F4LDNH.js.map} +0 -0
- /package/dist/cli/{chunk-QCFLPSPH.js.map → chunk-IKSYVBBZ.js.map} +0 -0
- /package/dist/cli/{chunk-CCJAP7G3.js.map → chunk-KH5JIJJD.js.map} +0 -0
- /package/dist/cli/{chunk-TDHXB2ER.js.map → chunk-NQZ5U37J.js.map} +0 -0
- /package/dist/cli/{chunk-CNG32VAB.js.map → chunk-O3AGYTG2.js.map} +0 -0
- /package/dist/cli/{chunk-KVZZ5U75.js.map → chunk-R7U44O3Y.js.map} +0 -0
- /package/dist/cli/{chunk-TRWHTFG7.js.map → chunk-SWUMD2LX.js.map} +0 -0
- /package/dist/cli/{chunk-4MFCAZ2W.js.map → chunk-WKOXKCF3.js.map} +0 -0
- /package/dist/cli/{chunk-HUILPCYX.js.map → chunk-XMR2VCGT.js.map} +0 -0
- /package/dist/cli/{commands-4CDI4GFM.js.map → commands-3U6PUVSS.js.map} +0 -0
- /package/dist/cli/{commit-GW7LDQP5.js.map → commit-HFB7SRBU.js.map} +0 -0
- /package/dist/cli/{diff-VI2YX4FN.js.map → diff-PGXW4YZD.js.map} +0 -0
- /package/dist/cli/{doctor-CQTTZP27.js.map → doctor-WWJFLVCB.js.map} +0 -0
- /package/dist/cli/{mcp-J2UCD4RZ.js.map → mcp-Y3VKIK3T.js.map} +0 -0
- /package/dist/cli/{mcp-browse-GSX34JEK.js.map → mcp-browse-4IN2QIFR.js.map} +0 -0
- /package/dist/cli/{mcp-inspect-RRFYF4ZV.js.map → mcp-inspect-BUXFXDHB.js.map} +0 -0
- /package/dist/cli/{prompt-5TQPIVHV.js.map → prompt-US57R6BA.js.map} +0 -0
- /package/dist/cli/{replay-MJCEMODU.js.map → replay-EQJMZRB3.js.map} +0 -0
- /package/dist/cli/{run-P4D5VDYE.js.map → run-KVEI66TR.js.map} +0 -0
- /package/dist/cli/{sessions-QIONZJQ6.js.map → sessions-TGVS2RQZ.js.map} +0 -0
- /package/dist/cli/{setup-NLQ6G5G4.js.map → setup-WLKX6GGG.js.map} +0 -0
- /package/dist/cli/{stats-DFZEXHP4.js.map → stats-TCD7Q6MB.js.map} +0 -0
- /package/dist/cli/{version-GR3X3MPI.js.map → version-BCWWS2OU.js.map} +0 -0
|
@@ -3,7 +3,7 @@ import { createRequire as __cr } from 'node:module'; if (typeof globalThis.requi
|
|
|
3
3
|
import {
|
|
4
4
|
MemoryStore,
|
|
5
5
|
sanitizeMemoryName
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-FD7SNDWW.js";
|
|
7
7
|
import {
|
|
8
8
|
countTokens,
|
|
9
9
|
countTokensBounded,
|
|
@@ -12,23 +12,23 @@ import {
|
|
|
12
12
|
} from "./chunk-6OWJV3YW.js";
|
|
13
13
|
import {
|
|
14
14
|
Usage
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-5U5LMMFF.js";
|
|
16
16
|
import {
|
|
17
17
|
applyEdit,
|
|
18
18
|
applyMultiEdit,
|
|
19
19
|
pauseGate
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-6FRNXWDZ.js";
|
|
21
21
|
import {
|
|
22
22
|
NEGATIVE_CLAIM_RULE,
|
|
23
23
|
PROJECT_MEMORY_FILES,
|
|
24
24
|
PROJECT_MEMORY_MAX_CHARS,
|
|
25
25
|
TUI_FORMATTING_RULES,
|
|
26
26
|
memoryEnabled
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-SLAFMXAZ.js";
|
|
28
28
|
import {
|
|
29
29
|
formatHookOutcomeMessage,
|
|
30
30
|
runHooks
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-PJIQIYTV.js";
|
|
32
32
|
import {
|
|
33
33
|
ignoredByLayers,
|
|
34
34
|
loadGitignoreAt,
|
|
@@ -46,21 +46,23 @@ import {
|
|
|
46
46
|
DEEPSEEK_CONTEXT_TOKENS,
|
|
47
47
|
DEFAULT_CONTEXT_TOKENS,
|
|
48
48
|
SessionStats
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-IKSYVBBZ.js";
|
|
50
50
|
import {
|
|
51
51
|
t
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-PIC5HJRD.js";
|
|
53
53
|
import {
|
|
54
54
|
DEFAULT_INDEX_EXCLUDES,
|
|
55
55
|
addProjectPathAllowed,
|
|
56
|
+
loadExaApiKey,
|
|
56
57
|
loadMemoryTypeRegistry,
|
|
57
58
|
loadMetasoApiKey,
|
|
59
|
+
loadPerplexityApiKey,
|
|
58
60
|
loadProjectPathAllowed,
|
|
59
61
|
loadTavilyApiKey,
|
|
60
62
|
require_picomatch,
|
|
61
63
|
webSearchEndpoint,
|
|
62
64
|
webSearchEngine
|
|
63
|
-
} from "./chunk-
|
|
65
|
+
} from "./chunk-FPME5QOO.js";
|
|
64
66
|
import {
|
|
65
67
|
__commonJS,
|
|
66
68
|
__esm,
|
|
@@ -2597,10 +2599,10 @@ var require_helpers = __commonJS({
|
|
|
2597
2599
|
return !arr.includes(node, i + 1);
|
|
2598
2600
|
});
|
|
2599
2601
|
nodes.sort(function(a, b) {
|
|
2600
|
-
var
|
|
2601
|
-
if (
|
|
2602
|
+
var relative7 = compareDocumentPosition(a, b);
|
|
2603
|
+
if (relative7 & DocumentPosition.PRECEDING) {
|
|
2602
2604
|
return -1;
|
|
2603
|
-
} else if (
|
|
2605
|
+
} else if (relative7 & DocumentPosition.FOLLOWING) {
|
|
2604
2606
|
return 1;
|
|
2605
2607
|
}
|
|
2606
2608
|
return 0;
|
|
@@ -6314,8 +6316,8 @@ var ToolRegistry = class {
|
|
|
6314
6316
|
_resultAugmenter = null;
|
|
6315
6317
|
/** Per-tool fingerprint of the last call that failed schema validation. Cleared by any successful validation for that tool. */
|
|
6316
6318
|
_lastMalformed = /* @__PURE__ */ new Map();
|
|
6317
|
-
/** Per-tool fingerprint of the last host-side
|
|
6318
|
-
|
|
6319
|
+
/** Per-tool fingerprint of the last host-side gate rejection. */
|
|
6320
|
+
_lastGateRejection = /* @__PURE__ */ new Map();
|
|
6319
6321
|
constructor(opts = {}) {
|
|
6320
6322
|
this._autoFlatten = opts.autoFlatten !== false;
|
|
6321
6323
|
}
|
|
@@ -6402,20 +6404,21 @@ var ToolRegistry = class {
|
|
|
6402
6404
|
if (!tool) {
|
|
6403
6405
|
return JSON.stringify({ error: `unknown tool: ${name}` });
|
|
6404
6406
|
}
|
|
6405
|
-
const
|
|
6407
|
+
const rawFingerprint = rawFingerprintArgs(argumentsRaw);
|
|
6406
6408
|
let args;
|
|
6407
6409
|
try {
|
|
6408
6410
|
args = typeof argumentsRaw === "string" ? argumentsRaw.trim() ? JSON.parse(argumentsRaw) ?? {} : {} : argumentsRaw ?? {};
|
|
6409
6411
|
} catch (err) {
|
|
6410
6412
|
return this._noteMalformed(
|
|
6411
6413
|
name,
|
|
6412
|
-
|
|
6414
|
+
rawFingerprint,
|
|
6413
6415
|
`invalid tool arguments JSON: ${err.message}`
|
|
6414
6416
|
);
|
|
6415
6417
|
}
|
|
6416
6418
|
if (tool.flatSchema && args && typeof args === "object" && hasDotKey(args)) {
|
|
6417
6419
|
args = nestArguments(args);
|
|
6418
6420
|
}
|
|
6421
|
+
const fingerprint = fingerprintArgs(args);
|
|
6419
6422
|
const missing = tool.parameters ? missingRequiredParam(tool.parameters, args) : null;
|
|
6420
6423
|
if (missing) {
|
|
6421
6424
|
return this._noteMalformed(
|
|
@@ -6436,7 +6439,7 @@ var ToolRegistry = class {
|
|
|
6436
6439
|
try {
|
|
6437
6440
|
const short = await interceptor(name, args);
|
|
6438
6441
|
if (typeof short === "string") {
|
|
6439
|
-
const guarded = this.
|
|
6442
|
+
const guarded = this._noteGateRejection(name, fingerprint, short);
|
|
6440
6443
|
return this._augmentResult(name, args, guarded);
|
|
6441
6444
|
}
|
|
6442
6445
|
} catch (err) {
|
|
@@ -6445,7 +6448,6 @@ var ToolRegistry = class {
|
|
|
6445
6448
|
});
|
|
6446
6449
|
}
|
|
6447
6450
|
}
|
|
6448
|
-
this._lastInterceptorRejection.delete(name);
|
|
6449
6451
|
if (opts.signal?.aborted) {
|
|
6450
6452
|
return JSON.stringify({
|
|
6451
6453
|
error: `${name}: aborted before dispatch (user interrupt)`,
|
|
@@ -6483,6 +6485,7 @@ var ToolRegistry = class {
|
|
|
6483
6485
|
finalResult = JSON.stringify({ error: `${e.name}: ${e.message}` });
|
|
6484
6486
|
}
|
|
6485
6487
|
}
|
|
6488
|
+
finalResult = this._noteGateRejection(name, fingerprint, finalResult);
|
|
6486
6489
|
return this._augmentResult(name, args, finalResult);
|
|
6487
6490
|
}
|
|
6488
6491
|
_augmentResult(name, args, result) {
|
|
@@ -6506,18 +6509,18 @@ var ToolRegistry = class {
|
|
|
6506
6509
|
}
|
|
6507
6510
|
return JSON.stringify({ error: `${name}: ${detail}` });
|
|
6508
6511
|
}
|
|
6509
|
-
|
|
6510
|
-
const reason = rejectedReason(result);
|
|
6512
|
+
_noteGateRejection(name, fingerprint, result) {
|
|
6513
|
+
const reason = rejectedReason(name, result);
|
|
6511
6514
|
if (!reason) {
|
|
6512
|
-
this.
|
|
6515
|
+
this._lastGateRejection.delete(name);
|
|
6513
6516
|
return result;
|
|
6514
6517
|
}
|
|
6515
6518
|
const key = `${reason}:${fingerprint}`;
|
|
6516
|
-
const prev = this.
|
|
6517
|
-
this.
|
|
6519
|
+
const prev = this._lastGateRejection.get(name);
|
|
6520
|
+
this._lastGateRejection.set(name, key);
|
|
6518
6521
|
if (prev === key) {
|
|
6519
6522
|
return JSON.stringify({
|
|
6520
|
-
error: `${name}: same call was just rejected by ${reason} \u2014 do not retry identical args.
|
|
6523
|
+
error: `${name}: same call was just rejected by ${reason} \u2014 do not retry identical args. ${rejectionRecoveryHint(reason)}`,
|
|
6521
6524
|
rejectedReason: reason,
|
|
6522
6525
|
consecutiveInterceptorRejection: true
|
|
6523
6526
|
});
|
|
@@ -6525,16 +6528,44 @@ var ToolRegistry = class {
|
|
|
6525
6528
|
return result;
|
|
6526
6529
|
}
|
|
6527
6530
|
};
|
|
6528
|
-
function rejectedReason(result) {
|
|
6531
|
+
function rejectedReason(name, result) {
|
|
6532
|
+
const textReason = plainTextRejectedReason(name, result);
|
|
6533
|
+
if (textReason) return textReason;
|
|
6529
6534
|
try {
|
|
6530
6535
|
const parsed = JSON.parse(result);
|
|
6531
6536
|
if (!parsed || typeof parsed !== "object") return null;
|
|
6532
6537
|
const reason = parsed.rejectedReason;
|
|
6533
|
-
|
|
6538
|
+
if (typeof reason === "string" && reason) return reason;
|
|
6539
|
+
const error = parsed.error;
|
|
6540
|
+
if (typeof error === "string") return plainTextRejectedReason(name, error);
|
|
6541
|
+
return null;
|
|
6534
6542
|
} catch {
|
|
6535
6543
|
return null;
|
|
6536
6544
|
}
|
|
6537
6545
|
}
|
|
6546
|
+
function plainTextRejectedReason(name, result) {
|
|
6547
|
+
if ((name === "edit_file" || name === "write_file") && /rejected this edit/i.test(result)) {
|
|
6548
|
+
return "edit-gate";
|
|
6549
|
+
}
|
|
6550
|
+
if ((name === "run_command" || name === "run_background") && /\buser denied:/i.test(result)) {
|
|
6551
|
+
return "shell-gate";
|
|
6552
|
+
}
|
|
6553
|
+
return null;
|
|
6554
|
+
}
|
|
6555
|
+
function rejectionRecoveryHint(reason) {
|
|
6556
|
+
switch (reason) {
|
|
6557
|
+
case "edit-gate":
|
|
6558
|
+
return "Do not re-emit the same edit. Try a genuinely different edit or ask the user how to proceed.";
|
|
6559
|
+
case "shell-gate":
|
|
6560
|
+
return "Do not retry the same command. Use an allowlisted/read-only command, wait for approval, or ask the user how to proceed.";
|
|
6561
|
+
case "engineering-lifecycle":
|
|
6562
|
+
return "Switch to read-only exploration, submit or revise the plan, or choose a different tool call.";
|
|
6563
|
+
case "engineering-lifecycle-evidence":
|
|
6564
|
+
return "Submit completion evidence or revise/checkpoint the plan before marking the step complete.";
|
|
6565
|
+
default:
|
|
6566
|
+
return "Choose a different tool call or ask the user how to proceed.";
|
|
6567
|
+
}
|
|
6568
|
+
}
|
|
6538
6569
|
function isReadOnlyCall(tool, args) {
|
|
6539
6570
|
if (tool.readOnlyCheck) {
|
|
6540
6571
|
try {
|
|
@@ -6553,14 +6584,27 @@ function hasDotKey(obj) {
|
|
|
6553
6584
|
}
|
|
6554
6585
|
return false;
|
|
6555
6586
|
}
|
|
6556
|
-
function
|
|
6587
|
+
function rawFingerprintArgs(argumentsRaw) {
|
|
6557
6588
|
if (typeof argumentsRaw === "string") return argumentsRaw;
|
|
6589
|
+
return fingerprintArgs(argumentsRaw);
|
|
6590
|
+
}
|
|
6591
|
+
function fingerprintArgs(args) {
|
|
6558
6592
|
try {
|
|
6559
|
-
return JSON.stringify(
|
|
6593
|
+
return JSON.stringify(sortJson(args));
|
|
6560
6594
|
} catch {
|
|
6561
6595
|
return "";
|
|
6562
6596
|
}
|
|
6563
6597
|
}
|
|
6598
|
+
function sortJson(value) {
|
|
6599
|
+
if (Array.isArray(value)) return value.map(sortJson);
|
|
6600
|
+
if (!value || typeof value !== "object") return value;
|
|
6601
|
+
const out = {};
|
|
6602
|
+
for (const key of Object.keys(value).sort()) {
|
|
6603
|
+
const item = value[key];
|
|
6604
|
+
if (item !== void 0) out[key] = sortJson(item);
|
|
6605
|
+
}
|
|
6606
|
+
return out;
|
|
6607
|
+
}
|
|
6564
6608
|
function missingRequiredParam(schema, args) {
|
|
6565
6609
|
const required = schema.required;
|
|
6566
6610
|
if (!required || required.length === 0) return null;
|
|
@@ -6713,14 +6757,16 @@ function buildSyntheticAssistantMessage(content, fallbackModel) {
|
|
|
6713
6757
|
}
|
|
6714
6758
|
|
|
6715
6759
|
// src/context-manager.ts
|
|
6716
|
-
var HISTORY_FOLD_THRESHOLD = 0.
|
|
6760
|
+
var HISTORY_FOLD_THRESHOLD = 0.75;
|
|
6717
6761
|
var HISTORY_FOLD_TAIL_FRACTION = 0.2;
|
|
6718
|
-
var HISTORY_FOLD_AGGRESSIVE_THRESHOLD = 0.
|
|
6762
|
+
var HISTORY_FOLD_AGGRESSIVE_THRESHOLD = 0.78;
|
|
6719
6763
|
var HISTORY_FOLD_AGGRESSIVE_TAIL_FRACTION = 0.1;
|
|
6720
6764
|
var HISTORY_FOLD_MIN_SAVINGS_FRACTION = 0.3;
|
|
6721
6765
|
var FORCE_SUMMARY_THRESHOLD = 0.8;
|
|
6722
6766
|
var PREFLIGHT_EMERGENCY_THRESHOLD = 0.95;
|
|
6723
6767
|
var PREFLIGHT_MECHANICAL_TARGET_FRACTION = 0.7;
|
|
6768
|
+
var MAX_BODY_BYTES = 7e5;
|
|
6769
|
+
var MAX_BODY_BYTES_TARGET = 5e5;
|
|
6724
6770
|
var HISTORY_FOLD_SUMMARY_TIMEOUT_MS = 15e3;
|
|
6725
6771
|
var HISTORY_FOLD_MARKER = "[CONVERSATION HISTORY SUMMARY \u2014 earlier turns folded for context efficiency]\n\n";
|
|
6726
6772
|
var SKILL_PIN_MEMO_HEADER = "[Active skill memos \u2014 preserved verbatim across the fold:]";
|
|
@@ -6745,6 +6791,20 @@ var ContextManager = class {
|
|
|
6745
6791
|
this.deps = deps;
|
|
6746
6792
|
}
|
|
6747
6793
|
deps;
|
|
6794
|
+
/** Real-time token count of the current log — used by Desktop to refresh the
|
|
6795
|
+
* context meter after /compact when no API usage event is available. */
|
|
6796
|
+
getLogTokens() {
|
|
6797
|
+
const entries = this.deps.log.toMessages();
|
|
6798
|
+
let total = 0;
|
|
6799
|
+
for (const e of entries) {
|
|
6800
|
+
const content = typeof e.content === "string" ? e.content : "";
|
|
6801
|
+
total += countTokensBounded(content);
|
|
6802
|
+
if (e.role === "assistant" && Array.isArray(e.tool_calls) && e.tool_calls.length > 0) {
|
|
6803
|
+
total += countTokensBounded(JSON.stringify(e.tool_calls));
|
|
6804
|
+
}
|
|
6805
|
+
}
|
|
6806
|
+
return total;
|
|
6807
|
+
}
|
|
6748
6808
|
/** Decision after a turn's response — fold, exit with summary, or carry on. */
|
|
6749
6809
|
decideAfterUsage(usage, model, alreadyFoldedThisTurn) {
|
|
6750
6810
|
const ctxMax = DEEPSEEK_CONTEXT_TOKENS[model] ?? DEFAULT_CONTEXT_TOKENS;
|
|
@@ -6773,14 +6833,25 @@ var ContextManager = class {
|
|
|
6773
6833
|
}
|
|
6774
6834
|
return { kind: "none", ...base };
|
|
6775
6835
|
}
|
|
6776
|
-
/** Local-side preflight before sending a request — catches oversized payloads early.
|
|
6836
|
+
/** Local-side preflight before sending a request — catches oversized payloads early.
|
|
6837
|
+
* Two independent signals trip mechanical truncate: token estimate above the context-window
|
|
6838
|
+
* fraction, OR JSON body bytes above the gateway limit (see `MAX_BODY_BYTES`). */
|
|
6777
6839
|
decidePreflight(messages, toolSpecs, model) {
|
|
6778
6840
|
const ctxMax = DEEPSEEK_CONTEXT_TOKENS[model] ?? DEFAULT_CONTEXT_TOKENS;
|
|
6779
6841
|
const estimate = estimateRequestTokens(messages, toolSpecs ?? null, true);
|
|
6842
|
+
const estimateBytes = Buffer.byteLength(JSON.stringify(messages), "utf8");
|
|
6843
|
+
const tokensOver = estimate / ctxMax > PREFLIGHT_EMERGENCY_THRESHOLD;
|
|
6844
|
+
const bytesOver = estimateBytes > MAX_BODY_BYTES;
|
|
6845
|
+
let trigger = "none";
|
|
6846
|
+
if (tokensOver && bytesOver) trigger = "both";
|
|
6847
|
+
else if (tokensOver) trigger = "tokens";
|
|
6848
|
+
else if (bytesOver) trigger = "bytes";
|
|
6780
6849
|
return {
|
|
6781
|
-
needsAction:
|
|
6850
|
+
needsAction: tokensOver || bytesOver,
|
|
6782
6851
|
estimateTokens: estimate,
|
|
6783
|
-
|
|
6852
|
+
estimateBytes,
|
|
6853
|
+
ctxMax,
|
|
6854
|
+
trigger
|
|
6784
6855
|
};
|
|
6785
6856
|
}
|
|
6786
6857
|
/** Replace older turns with one summary message; keep tail within keepRecentTokens budget. */
|
|
@@ -6833,10 +6904,13 @@ ${pinnedBodies.join("\n\n")}` : "";
|
|
|
6833
6904
|
summaryChars: summary.content.length
|
|
6834
6905
|
};
|
|
6835
6906
|
}
|
|
6836
|
-
/** Pure local emergency compaction for preflight: drop oldest log entries and keep a valid tail.
|
|
6907
|
+
/** Pure local emergency compaction for preflight: drop oldest log entries and keep a valid tail.
|
|
6908
|
+
* Bounded by tokens AND bytes — bytes matter because DeepSeek's gateway 400s on bodies past
|
|
6909
|
+
* `MAX_BODY_BYTES` even when the token budget is far from exhausted. */
|
|
6837
6910
|
mechanicalTruncate(model, opts) {
|
|
6838
6911
|
const ctxMax = DEEPSEEK_CONTEXT_TOKENS[model] ?? DEFAULT_CONTEXT_TOKENS;
|
|
6839
6912
|
const targetTokens = opts?.targetTokens ?? Math.floor(ctxMax * PREFLIGHT_MECHANICAL_TARGET_FRACTION);
|
|
6913
|
+
const targetBytes = opts?.targetBytes ?? MAX_BODY_BYTES_TARGET;
|
|
6840
6914
|
const all = this.deps.log.toMessages();
|
|
6841
6915
|
const noop = {
|
|
6842
6916
|
folded: false,
|
|
@@ -6846,6 +6920,7 @@ ${pinnedBodies.join("\n\n")}` : "";
|
|
|
6846
6920
|
};
|
|
6847
6921
|
if (all.length === 0) return noop;
|
|
6848
6922
|
const tokenCounts = all.map((m) => estimateConversationTokens([m], true));
|
|
6923
|
+
const byteCounts = all.map((m) => Buffer.byteLength(JSON.stringify(m), "utf8"));
|
|
6849
6924
|
let latestUserBoundary = -1;
|
|
6850
6925
|
for (let i = all.length - 1; i >= 0; i--) {
|
|
6851
6926
|
if (all[i].role === "user") {
|
|
@@ -6854,12 +6929,15 @@ ${pinnedBodies.join("\n\n")}` : "";
|
|
|
6854
6929
|
}
|
|
6855
6930
|
}
|
|
6856
6931
|
let cumTokens = 0;
|
|
6932
|
+
let cumBytes = 0;
|
|
6857
6933
|
let boundary = all.length;
|
|
6858
6934
|
let foundSafeBoundary = false;
|
|
6859
6935
|
for (let i = all.length - 1; i >= 0; i--) {
|
|
6860
|
-
const
|
|
6861
|
-
|
|
6862
|
-
|
|
6936
|
+
const nextTokens = cumTokens + tokenCounts[i];
|
|
6937
|
+
const nextBytes = cumBytes + byteCounts[i];
|
|
6938
|
+
if (nextTokens > targetTokens || nextBytes > targetBytes) break;
|
|
6939
|
+
cumTokens = nextTokens;
|
|
6940
|
+
cumBytes = nextBytes;
|
|
6863
6941
|
if (all[i].role === "user") {
|
|
6864
6942
|
boundary = i;
|
|
6865
6943
|
foundSafeBoundary = true;
|
|
@@ -7096,13 +7174,11 @@ async function* forceSummaryAfterIterLimit(ctx, opts) {
|
|
|
7096
7174
|
content: "The turn is being force-summarized (context guard or stuck-state). Summarize in plain prose what you learned from the tool results above. Do NOT emit any tool calls, function-call markup, DSML invocations, or SEARCH/REPLACE edit blocks \u2014 they will be silently discarded. Just plain text."
|
|
7097
7175
|
});
|
|
7098
7176
|
const summaryModel = "deepseek-v4-flash";
|
|
7099
|
-
const summaryEffort = "high";
|
|
7100
7177
|
const resp = await ctx.client.chat({
|
|
7101
7178
|
model: summaryModel,
|
|
7102
7179
|
messages,
|
|
7103
7180
|
signal: ctx.signal,
|
|
7104
|
-
thinking:
|
|
7105
|
-
reasoningEffort: summaryEffort
|
|
7181
|
+
thinking: "disabled"
|
|
7106
7182
|
});
|
|
7107
7183
|
const rawContent = resp.content?.trim() ?? "";
|
|
7108
7184
|
const cleaned = stripHallucinatedToolMarkup(rawContent);
|
|
@@ -7733,6 +7809,10 @@ var CacheFirstLoop = class {
|
|
|
7733
7809
|
async compactHistory(opts) {
|
|
7734
7810
|
return this.context.fold(this.model, opts);
|
|
7735
7811
|
}
|
|
7812
|
+
/** Real-time token count of the current log — forwarded to Desktop for meter refresh. */
|
|
7813
|
+
getCurrentLogTokens() {
|
|
7814
|
+
return this.context.getLogTokens();
|
|
7815
|
+
}
|
|
7736
7816
|
appendAndPersist(message) {
|
|
7737
7817
|
this.log.append(message);
|
|
7738
7818
|
if (this.sessionName) {
|
|
@@ -8048,21 +8128,24 @@ ${reason}`
|
|
|
8048
8128
|
const toolSpecs = this.prefix.tools();
|
|
8049
8129
|
for (let iter = 0; ; iter++) {
|
|
8050
8130
|
if (signal.aborted) {
|
|
8051
|
-
|
|
8052
|
-
|
|
8053
|
-
|
|
8054
|
-
|
|
8055
|
-
|
|
8056
|
-
|
|
8057
|
-
|
|
8058
|
-
|
|
8059
|
-
|
|
8060
|
-
|
|
8061
|
-
|
|
8062
|
-
|
|
8063
|
-
|
|
8064
|
-
|
|
8065
|
-
|
|
8131
|
+
try {
|
|
8132
|
+
yield {
|
|
8133
|
+
turn: this._turn,
|
|
8134
|
+
role: "warning",
|
|
8135
|
+
content: t("loop.abortedAtIter", { iter })
|
|
8136
|
+
};
|
|
8137
|
+
const stoppedMsg = "[aborted by user (Esc) \u2014 no summary produced. Ask again or /retry when ready; prior tool output is still in the log.]";
|
|
8138
|
+
this.appendAndPersist(buildSyntheticAssistantMessage(stoppedMsg, this.model));
|
|
8139
|
+
yield {
|
|
8140
|
+
turn: this._turn,
|
|
8141
|
+
role: "assistant_final",
|
|
8142
|
+
content: stoppedMsg,
|
|
8143
|
+
forcedSummary: true
|
|
8144
|
+
};
|
|
8145
|
+
yield { turn: this._turn, role: "done", content: stoppedMsg };
|
|
8146
|
+
} finally {
|
|
8147
|
+
this._turnAbort = new AbortController();
|
|
8148
|
+
}
|
|
8066
8149
|
return;
|
|
8067
8150
|
}
|
|
8068
8151
|
if (iter > 0) {
|
|
@@ -8089,7 +8172,7 @@ ${reason}`
|
|
|
8089
8172
|
{
|
|
8090
8173
|
const decision2 = this.context.decidePreflight(messages, this.prefix.toolSpecs, this.model);
|
|
8091
8174
|
if (decision2.needsAction) {
|
|
8092
|
-
const { estimateTokens: estimate, ctxMax } = decision2;
|
|
8175
|
+
const { estimateTokens: estimate, estimateBytes, ctxMax } = decision2;
|
|
8093
8176
|
yield {
|
|
8094
8177
|
turn: this._turn,
|
|
8095
8178
|
role: "status",
|
|
@@ -8111,6 +8194,7 @@ ${reason}`
|
|
|
8111
8194
|
estimate: after.estimateTokens.toLocaleString(),
|
|
8112
8195
|
ctxMax: after.ctxMax.toLocaleString(),
|
|
8113
8196
|
pct: Math.round(after.estimateTokens / after.ctxMax * 100),
|
|
8197
|
+
bodyKB: Math.round(after.estimateBytes / 1024).toLocaleString(),
|
|
8114
8198
|
beforeMessages: result.beforeMessages,
|
|
8115
8199
|
afterMessages: result.afterMessages
|
|
8116
8200
|
}
|
|
@@ -8123,7 +8207,8 @@ ${reason}`
|
|
|
8123
8207
|
content: t("loop.preflightNoFold", {
|
|
8124
8208
|
estimate: estimate.toLocaleString(),
|
|
8125
8209
|
ctxMax: ctxMax.toLocaleString(),
|
|
8126
|
-
pct: Math.round(estimate / ctxMax * 100)
|
|
8210
|
+
pct: Math.round(estimate / ctxMax * 100),
|
|
8211
|
+
bodyKB: Math.round(estimateBytes / 1024).toLocaleString()
|
|
8127
8212
|
})
|
|
8128
8213
|
};
|
|
8129
8214
|
}
|
|
@@ -8238,8 +8323,11 @@ ${reason}`
|
|
|
8238
8323
|
}
|
|
8239
8324
|
} catch (err) {
|
|
8240
8325
|
if (signal.aborted) {
|
|
8241
|
-
|
|
8242
|
-
|
|
8326
|
+
try {
|
|
8327
|
+
yield { turn: this._turn, role: "done", content: "" };
|
|
8328
|
+
} finally {
|
|
8329
|
+
this._turnAbort = new AbortController();
|
|
8330
|
+
}
|
|
8243
8331
|
return;
|
|
8244
8332
|
}
|
|
8245
8333
|
const probe = is5xxError(err) ? await probeDeepSeekReachable(this.client) : void 0;
|
|
@@ -9273,6 +9361,8 @@ var USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (
|
|
|
9273
9361
|
var MOJEEK_ENDPOINT = "https://www.mojeek.com/search";
|
|
9274
9362
|
var METASO_ENDPOINT = "https://metaso.cn/api/v1";
|
|
9275
9363
|
var TAVILY_ENDPOINT = "https://api.tavily.com/search";
|
|
9364
|
+
var PERPLEXITY_ENDPOINT = "https://api.perplexity.ai/chat/completions";
|
|
9365
|
+
var EXA_ENDPOINT = "https://api.exa.ai/answer";
|
|
9276
9366
|
function searchStatusError(status) {
|
|
9277
9367
|
if (status === 429) return t("webErrors.rateLimit429");
|
|
9278
9368
|
if (status === 403) return t("webErrors.forbidden403");
|
|
@@ -9295,6 +9385,12 @@ async function webSearch(query, opts = {}) {
|
|
|
9295
9385
|
if (opts.engine === "tavily") {
|
|
9296
9386
|
return searchTavily(query, opts);
|
|
9297
9387
|
}
|
|
9388
|
+
if (opts.engine === "perplexity") {
|
|
9389
|
+
return searchPerplexity(query, opts);
|
|
9390
|
+
}
|
|
9391
|
+
if (opts.engine === "exa") {
|
|
9392
|
+
return searchExa(query, opts);
|
|
9393
|
+
}
|
|
9298
9394
|
return searchMojeek(query, opts);
|
|
9299
9395
|
}
|
|
9300
9396
|
async function searchMojeek(query, opts = {}) {
|
|
@@ -9370,6 +9466,7 @@ async function searchSearxng(query, opts = {}) {
|
|
|
9370
9466
|
async function searchMetaso(query, opts = {}) {
|
|
9371
9467
|
const topK = Math.max(1, Math.min(100, opts.topK ?? DEFAULT_TOPK));
|
|
9372
9468
|
const apiKey = loadMetasoApiKey();
|
|
9469
|
+
if (!apiKey) throw new Error(t("webErrors.metasoMissingKey"));
|
|
9373
9470
|
let resp;
|
|
9374
9471
|
try {
|
|
9375
9472
|
resp = await fetch(`${METASO_ENDPOINT}/search`, {
|
|
@@ -9478,6 +9575,121 @@ async function searchTavily(query, opts = {}) {
|
|
|
9478
9575
|
snippet: r.content ?? ""
|
|
9479
9576
|
}));
|
|
9480
9577
|
}
|
|
9578
|
+
async function searchPerplexity(query, opts = {}) {
|
|
9579
|
+
const topK = Math.max(1, Math.min(20, opts.topK ?? DEFAULT_TOPK));
|
|
9580
|
+
const apiKey = loadPerplexityApiKey();
|
|
9581
|
+
if (!apiKey) throw new Error(t("webErrors.perplexityMissingKey"));
|
|
9582
|
+
let resp;
|
|
9583
|
+
try {
|
|
9584
|
+
resp = await fetch(PERPLEXITY_ENDPOINT, {
|
|
9585
|
+
method: "POST",
|
|
9586
|
+
headers: {
|
|
9587
|
+
Authorization: `Bearer ${apiKey}`,
|
|
9588
|
+
"Content-Type": "application/json"
|
|
9589
|
+
},
|
|
9590
|
+
body: JSON.stringify({
|
|
9591
|
+
model: "sonar",
|
|
9592
|
+
messages: [{ role: "user", content: query }],
|
|
9593
|
+
max_tokens: 1024,
|
|
9594
|
+
return_related_questions: false
|
|
9595
|
+
}),
|
|
9596
|
+
signal: opts.signal
|
|
9597
|
+
});
|
|
9598
|
+
} catch (err) {
|
|
9599
|
+
if (err instanceof TypeError && err.message.includes("fetch")) {
|
|
9600
|
+
throw new Error(t("webErrors.cannotReach", { endpoint: PERPLEXITY_ENDPOINT }));
|
|
9601
|
+
}
|
|
9602
|
+
throw err;
|
|
9603
|
+
}
|
|
9604
|
+
if (!resp.ok) {
|
|
9605
|
+
if (resp.status === 401 || resp.status === 403) {
|
|
9606
|
+
throw new Error(t("webErrors.perplexityUnauthorized"));
|
|
9607
|
+
}
|
|
9608
|
+
if (resp.status === 429) throw new Error(t("webErrors.perplexityRateLimit"));
|
|
9609
|
+
throw new Error(t("webErrors.perplexityServerError", { status: resp.status }));
|
|
9610
|
+
}
|
|
9611
|
+
const raw = await resp.text();
|
|
9612
|
+
let data;
|
|
9613
|
+
try {
|
|
9614
|
+
data = JSON.parse(raw);
|
|
9615
|
+
} catch {
|
|
9616
|
+
throw new Error(t("webErrors.perplexityParseError", { status: resp.status }));
|
|
9617
|
+
}
|
|
9618
|
+
const answer = data.choices?.[0]?.message?.content ?? "";
|
|
9619
|
+
const citations = Array.isArray(data.citations) ? data.citations : [];
|
|
9620
|
+
const results = [];
|
|
9621
|
+
if (answer) {
|
|
9622
|
+
results.push({ title: answer, url: "", snippet: "", answer });
|
|
9623
|
+
}
|
|
9624
|
+
const count = Math.min(citations.length, topK);
|
|
9625
|
+
for (let i = 0; i < count; i++) {
|
|
9626
|
+
const c = citations[i];
|
|
9627
|
+
if (typeof c === "string") {
|
|
9628
|
+
results.push({ title: `Source ${i + 1}`, url: c, snippet: "" });
|
|
9629
|
+
} else if (c && typeof c === "object" && typeof c.url === "string") {
|
|
9630
|
+
const item = c;
|
|
9631
|
+
results.push({
|
|
9632
|
+
title: typeof item.title === "string" ? item.title : `Source ${i + 1}`,
|
|
9633
|
+
url: item.url,
|
|
9634
|
+
snippet: ""
|
|
9635
|
+
});
|
|
9636
|
+
}
|
|
9637
|
+
}
|
|
9638
|
+
return results;
|
|
9639
|
+
}
|
|
9640
|
+
async function searchExa(query, opts = {}) {
|
|
9641
|
+
const topK = Math.max(1, Math.min(20, opts.topK ?? DEFAULT_TOPK));
|
|
9642
|
+
const apiKey = loadExaApiKey();
|
|
9643
|
+
if (!apiKey) throw new Error(t("webErrors.exaMissingKey"));
|
|
9644
|
+
let resp;
|
|
9645
|
+
try {
|
|
9646
|
+
resp = await fetch(EXA_ENDPOINT, {
|
|
9647
|
+
method: "POST",
|
|
9648
|
+
headers: {
|
|
9649
|
+
"x-api-key": apiKey,
|
|
9650
|
+
"Content-Type": "application/json"
|
|
9651
|
+
},
|
|
9652
|
+
body: JSON.stringify({ query, text: true }),
|
|
9653
|
+
signal: opts.signal
|
|
9654
|
+
});
|
|
9655
|
+
} catch (err) {
|
|
9656
|
+
if (err instanceof TypeError && err.message.includes("fetch")) {
|
|
9657
|
+
throw new Error(t("webErrors.cannotReach", { endpoint: EXA_ENDPOINT }));
|
|
9658
|
+
}
|
|
9659
|
+
throw err;
|
|
9660
|
+
}
|
|
9661
|
+
if (!resp.ok) {
|
|
9662
|
+
if (resp.status === 401 || resp.status === 403) {
|
|
9663
|
+
throw new Error(t("webErrors.exaUnauthorized"));
|
|
9664
|
+
}
|
|
9665
|
+
if (resp.status === 429) throw new Error(t("webErrors.exaRateLimit"));
|
|
9666
|
+
throw new Error(t("webErrors.exaServerError", { status: resp.status }));
|
|
9667
|
+
}
|
|
9668
|
+
const raw = await resp.text();
|
|
9669
|
+
let data;
|
|
9670
|
+
try {
|
|
9671
|
+
data = JSON.parse(raw);
|
|
9672
|
+
} catch {
|
|
9673
|
+
throw new Error(t("webErrors.exaParseError", { status: resp.status }));
|
|
9674
|
+
}
|
|
9675
|
+
const answer = data.answer ?? "";
|
|
9676
|
+
const citations = data.citations ?? [];
|
|
9677
|
+
const results = [];
|
|
9678
|
+
if (answer) {
|
|
9679
|
+
results.push({ title: answer, url: "", snippet: "", answer });
|
|
9680
|
+
}
|
|
9681
|
+
const count = Math.min(citations.length, topK);
|
|
9682
|
+
for (let i = 0; i < count; i++) {
|
|
9683
|
+
const c = citations[i];
|
|
9684
|
+
if (!c.url) continue;
|
|
9685
|
+
results.push({
|
|
9686
|
+
title: c.title || `Source ${i + 1}`,
|
|
9687
|
+
url: c.url,
|
|
9688
|
+
snippet: c.text ?? ""
|
|
9689
|
+
});
|
|
9690
|
+
}
|
|
9691
|
+
return results;
|
|
9692
|
+
}
|
|
9481
9693
|
function parseSearxngHtmlResults(html) {
|
|
9482
9694
|
const root = (0, import_node_html_parser.parse)(html);
|
|
9483
9695
|
const results = [];
|
|
@@ -9696,7 +9908,7 @@ function registerWebTools(registry, opts = {}) {
|
|
|
9696
9908
|
const maxFetchChars = opts.maxFetchChars ?? DEFAULT_FETCH_MAX_CHARS;
|
|
9697
9909
|
registry.register({
|
|
9698
9910
|
name: "web_search",
|
|
9699
|
-
description: "Search the public web. Returns ranked results with title, url, and snippet. Call this when the answer's correctness depends on current state \u2014 anything that changes over time (events, prices, releases, status of a thing in the real world). Composing such answers from training memory invents stale numbers; search first, then ground the answer in the results. For evergreen / definitional questions you don't need this.
|
|
9911
|
+
description: "Search the public web. Returns ranked results with title, url, and snippet. Call this when the answer's correctness depends on current state \u2014 anything that changes over time (events, prices, releases, status of a thing in the real world). Composing such answers from training memory invents stale numbers; search first, then ground the answer in the results. For evergreen / definitional questions you don't need this.",
|
|
9700
9912
|
readOnly: true,
|
|
9701
9913
|
parallelSafe: true,
|
|
9702
9914
|
parameters: {
|
|
@@ -9705,7 +9917,7 @@ function registerWebTools(registry, opts = {}) {
|
|
|
9705
9917
|
query: { type: "string", description: "Natural-language search query." },
|
|
9706
9918
|
topK: {
|
|
9707
9919
|
type: "integer",
|
|
9708
|
-
description: `Number of results to return
|
|
9920
|
+
description: `Number of results to return. Default ${defaultTopK}.`
|
|
9709
9921
|
}
|
|
9710
9922
|
},
|
|
9711
9923
|
required: ["query"]
|
|
@@ -9749,14 +9961,30 @@ ${page.text}`;
|
|
|
9749
9961
|
return registry;
|
|
9750
9962
|
}
|
|
9751
9963
|
function formatSearchResults(query, results) {
|
|
9752
|
-
const lines = [`query: ${query}
|
|
9753
|
-
|
|
9754
|
-
|
|
9964
|
+
const lines = [`query: ${query}`];
|
|
9965
|
+
const hasAnswer = results.length > 0 && results[0]?.url === "" && results[0]?.answer;
|
|
9966
|
+
if (hasAnswer) {
|
|
9967
|
+
lines.push("\nanswer:");
|
|
9968
|
+
lines.push(` ${results[0].answer}`);
|
|
9969
|
+
const sources = results.slice(1);
|
|
9755
9970
|
lines.push(`
|
|
9971
|
+
sources (${sources.length}):`);
|
|
9972
|
+
sources.forEach((r, i) => {
|
|
9973
|
+
lines.push(`
|
|
9756
9974
|
${i + 1}. ${r.title}`);
|
|
9757
|
-
|
|
9758
|
-
|
|
9759
|
-
|
|
9975
|
+
lines.push(` ${r.url}`);
|
|
9976
|
+
if (r.snippet) lines.push(` ${r.snippet}`);
|
|
9977
|
+
});
|
|
9978
|
+
} else {
|
|
9979
|
+
lines.push(`
|
|
9980
|
+
results (${results.length}):`);
|
|
9981
|
+
results.forEach((r, i) => {
|
|
9982
|
+
lines.push(`
|
|
9983
|
+
${i + 1}. ${r.title}`);
|
|
9984
|
+
lines.push(` ${r.url}`);
|
|
9985
|
+
if (r.snippet) lines.push(` ${r.snippet}`);
|
|
9986
|
+
});
|
|
9987
|
+
}
|
|
9760
9988
|
return lines.join("\n");
|
|
9761
9989
|
}
|
|
9762
9990
|
|
|
@@ -10391,8 +10619,8 @@ async function searchContent(ctx, startAbs, args) {
|
|
|
10391
10619
|
for (let i = realStart; i <= winEnd; i++) {
|
|
10392
10620
|
const line = lines[i];
|
|
10393
10621
|
const display = line.length > 200 ? `${line.slice(0, 200)}\u2026` : line;
|
|
10394
|
-
const
|
|
10395
|
-
if (!pushLine(`${rel}:${i + 1}${
|
|
10622
|
+
const sep = hitSet.has(i) ? ":" : "-";
|
|
10623
|
+
if (!pushLine(`${rel}:${i + 1}${sep} ${display}`)) return;
|
|
10396
10624
|
}
|
|
10397
10625
|
prevWindowEnd = winEnd;
|
|
10398
10626
|
}
|
|
@@ -10423,7 +10651,9 @@ var DEFAULT_OUTLINE_THRESHOLD_BYTES = 64 * 1024;
|
|
|
10423
10651
|
var DEFAULT_MAX_LIST_BYTES = 256 * 1024;
|
|
10424
10652
|
var HARD_MAX_FILE_BYTES = 32 * 1024 * 1024;
|
|
10425
10653
|
var OUTLINE_HEAD_LINES = 80;
|
|
10426
|
-
var SKIP_DIR_NAMES = new Set(
|
|
10654
|
+
var SKIP_DIR_NAMES = new Set(
|
|
10655
|
+
DEFAULT_INDEX_EXCLUDES.dirs.filter((d) => d !== ".reasonix")
|
|
10656
|
+
);
|
|
10427
10657
|
var BINARY_EXTENSIONS = new Set(DEFAULT_INDEX_EXCLUDES.exts);
|
|
10428
10658
|
function displayRel3(rootDir, full) {
|
|
10429
10659
|
return pathMod4.relative(rootDir, full).replaceAll("\\", "/");
|
|
@@ -11150,6 +11380,21 @@ function sanitizeEvidence(raw) {
|
|
|
11150
11380
|
}
|
|
11151
11381
|
return out.length > 0 ? out : void 0;
|
|
11152
11382
|
}
|
|
11383
|
+
function summarizeEvidence(evidence) {
|
|
11384
|
+
if (!evidence || evidence.length === 0) return void 0;
|
|
11385
|
+
const parts = evidence.map((item) => `${item.kind}: ${item.summary}`);
|
|
11386
|
+
return parts.join("; ");
|
|
11387
|
+
}
|
|
11388
|
+
function compactStepCompletion(update) {
|
|
11389
|
+
const compact = {
|
|
11390
|
+
kind: "step_completed",
|
|
11391
|
+
stepId: update.stepId,
|
|
11392
|
+
result: update.result
|
|
11393
|
+
};
|
|
11394
|
+
const evidenceSummary = summarizeEvidence(update.evidence);
|
|
11395
|
+
if (evidenceSummary) compact.evidenceSummary = evidenceSummary;
|
|
11396
|
+
return compact;
|
|
11397
|
+
}
|
|
11153
11398
|
function registerSubmitPlan(registry, opts) {
|
|
11154
11399
|
registry.register({
|
|
11155
11400
|
name: "submit_plan",
|
|
@@ -11263,9 +11508,9 @@ function registerMarkStepComplete(registry, opts) {
|
|
|
11263
11508
|
opts.onStepCompleted?.(update);
|
|
11264
11509
|
const verdict = await (ctx?.confirmationGate ?? pauseGate).ask({
|
|
11265
11510
|
kind: "plan_checkpoint",
|
|
11266
|
-
payload: { stepId, title, result, notes }
|
|
11511
|
+
payload: { stepId, title, result, notes, completion: update }
|
|
11267
11512
|
});
|
|
11268
|
-
if (verdict.type === "continue") return JSON.stringify(update);
|
|
11513
|
+
if (verdict.type === "continue") return JSON.stringify(compactStepCompletion(update));
|
|
11269
11514
|
if (verdict.type === "revise") {
|
|
11270
11515
|
if (verdict.feedback) return `revision requested: ${verdict.feedback}`;
|
|
11271
11516
|
throw new Error("user requested revision at checkpoint");
|
|
@@ -11478,6 +11723,7 @@ function nextRunId() {
|
|
|
11478
11723
|
runIdCounter++;
|
|
11479
11724
|
return `sub-${runIdCounter.toString(36)}`;
|
|
11480
11725
|
}
|
|
11726
|
+
var SHARED_SUBAGENT_SINK = { current: null };
|
|
11481
11727
|
var SUBAGENT_BASE_SYSTEM = `You are a Reasonix subagent. The parent agent spawned you to handle one focused subtask, then return.
|
|
11482
11728
|
|
|
11483
11729
|
Rules:
|
|
@@ -11576,12 +11822,40 @@ async function spawnSubagent(opts) {
|
|
|
11576
11822
|
let toolIter = 0;
|
|
11577
11823
|
let summarisingEmitted = false;
|
|
11578
11824
|
let forcedSummaryFired = false;
|
|
11825
|
+
let outputChars = 0;
|
|
11826
|
+
let reasoningChars = 0;
|
|
11827
|
+
let toolReadChars = 0;
|
|
11828
|
+
let lastStreamEmitAt = 0;
|
|
11829
|
+
let charsSinceLastEmit = 0;
|
|
11830
|
+
const STREAM_EMIT_INTERVAL_MS = 200;
|
|
11831
|
+
const STREAM_EMIT_CHARS = 400;
|
|
11832
|
+
const maybeEmitStreamProgress = (now, force) => {
|
|
11833
|
+
if (!sink?.current) return;
|
|
11834
|
+
if (!force && now - lastStreamEmitAt < STREAM_EMIT_INTERVAL_MS && charsSinceLastEmit < STREAM_EMIT_CHARS) {
|
|
11835
|
+
return;
|
|
11836
|
+
}
|
|
11837
|
+
lastStreamEmitAt = now;
|
|
11838
|
+
charsSinceLastEmit = 0;
|
|
11839
|
+
sink.current({
|
|
11840
|
+
kind: "stream-progress",
|
|
11841
|
+
runId,
|
|
11842
|
+
task: taskPreview,
|
|
11843
|
+
skillName,
|
|
11844
|
+
model,
|
|
11845
|
+
iter: toolIter,
|
|
11846
|
+
elapsedMs: now - startedAt,
|
|
11847
|
+
outputChars,
|
|
11848
|
+
reasoningChars,
|
|
11849
|
+
toolReadChars
|
|
11850
|
+
});
|
|
11851
|
+
};
|
|
11579
11852
|
try {
|
|
11580
11853
|
for await (const ev of childLoop.step(opts.task)) {
|
|
11581
11854
|
sink?.current?.({ kind: "inner", runId, task: taskPreview, skillName, model, inner: ev });
|
|
11582
11855
|
if (ev.role === "tool") {
|
|
11583
11856
|
toolIter++;
|
|
11584
11857
|
summarisingEmitted = false;
|
|
11858
|
+
toolReadChars += ev.content?.length ?? 0;
|
|
11585
11859
|
sink?.current?.({
|
|
11586
11860
|
kind: "progress",
|
|
11587
11861
|
runId,
|
|
@@ -11591,6 +11865,17 @@ async function spawnSubagent(opts) {
|
|
|
11591
11865
|
iter: toolIter,
|
|
11592
11866
|
elapsedMs: Date.now() - startedAt
|
|
11593
11867
|
});
|
|
11868
|
+
maybeEmitStreamProgress(Date.now(), true);
|
|
11869
|
+
}
|
|
11870
|
+
if (ev.role === "assistant_delta") {
|
|
11871
|
+
const dContent = ev.content?.length ?? 0;
|
|
11872
|
+
const dReason = ev.reasoningDelta?.length ?? 0;
|
|
11873
|
+
if (dContent > 0 || dReason > 0) {
|
|
11874
|
+
outputChars += dContent;
|
|
11875
|
+
reasoningChars += dReason;
|
|
11876
|
+
charsSinceLastEmit += dContent + dReason;
|
|
11877
|
+
maybeEmitStreamProgress(Date.now(), false);
|
|
11878
|
+
}
|
|
11594
11879
|
}
|
|
11595
11880
|
if (ev.role === "assistant_delta" && !summarisingEmitted && (ev.content ?? "").length > 0) {
|
|
11596
11881
|
summarisingEmitted = true;
|
|
@@ -11746,7 +12031,7 @@ import {
|
|
|
11746
12031
|
writeFileSync,
|
|
11747
12032
|
writeSync
|
|
11748
12033
|
} from "fs";
|
|
11749
|
-
import { dirname as dirname3, resolve as resolve4 } from "path";
|
|
12034
|
+
import { dirname as dirname3, isAbsolute as isAbsolute3, relative as relative6, resolve as resolve4 } from "path";
|
|
11750
12035
|
var BLOCK_RE = /^(\S[^\n]*)\n<{7} SEARCH\n([\s\S]*?)\n?={7}\n([\s\S]*?)\n?>{7} REPLACE/gm;
|
|
11751
12036
|
function parseEditBlocks(text) {
|
|
11752
12037
|
const out = [];
|
|
@@ -11763,10 +12048,30 @@ function parseEditBlocks(text) {
|
|
|
11763
12048
|
}
|
|
11764
12049
|
return out;
|
|
11765
12050
|
}
|
|
12051
|
+
function resolveEditPath(rootDir, rawPath) {
|
|
12052
|
+
const absRoot = resolve4(rootDir);
|
|
12053
|
+
if (/^[A-Za-z]:[\\/]/.test(rawPath) || looksLikeAbsoluteSystemPath2(rawPath)) {
|
|
12054
|
+
return resolve4(rawPath);
|
|
12055
|
+
}
|
|
12056
|
+
let rooted = rawPath;
|
|
12057
|
+
while (rooted.startsWith("/") || rooted.startsWith("\\")) {
|
|
12058
|
+
rooted = rooted.slice(1);
|
|
12059
|
+
}
|
|
12060
|
+
return resolve4(absRoot, rooted || ".");
|
|
12061
|
+
}
|
|
12062
|
+
function looksLikeAbsoluteSystemPath2(rawPath) {
|
|
12063
|
+
return /^\/(?:home|Users|etc|var|opt|tmp|usr|mnt|Library|Volumes|proc|sys|dev|run|srv|media|Applications|System|root|boot|private)(?:[/\\]|$)/.test(
|
|
12064
|
+
rawPath
|
|
12065
|
+
);
|
|
12066
|
+
}
|
|
12067
|
+
function pathIsUnder2(child, parent) {
|
|
12068
|
+
const rel = relative6(parent, child);
|
|
12069
|
+
return rel === "" || !rel.startsWith("..") && !isAbsolute3(rel);
|
|
12070
|
+
}
|
|
11766
12071
|
function applyEditBlock(block, rootDir) {
|
|
11767
12072
|
const absRoot = resolve4(rootDir);
|
|
11768
|
-
const absTarget =
|
|
11769
|
-
if (absTarget
|
|
12073
|
+
const absTarget = resolveEditPath(rootDir, block.path);
|
|
12074
|
+
if (!pathIsUnder2(absTarget, absRoot)) {
|
|
11770
12075
|
return {
|
|
11771
12076
|
path: block.path,
|
|
11772
12077
|
status: "path-escape",
|
|
@@ -11831,6 +12136,14 @@ function applyEditBlock(block, rootDir) {
|
|
|
11831
12136
|
message: "SEARCH text does not match the current file content exactly"
|
|
11832
12137
|
};
|
|
11833
12138
|
}
|
|
12139
|
+
const nextIdx = content.indexOf(adaptedSearch, idx + 1);
|
|
12140
|
+
if (nextIdx !== -1) {
|
|
12141
|
+
return {
|
|
12142
|
+
path: block.path,
|
|
12143
|
+
status: "not-found",
|
|
12144
|
+
message: "SEARCH text appears multiple times; include more context to disambiguate"
|
|
12145
|
+
};
|
|
12146
|
+
}
|
|
11834
12147
|
const replaced = `${content.slice(0, idx)}${adaptedReplace}${content.slice(idx + adaptedSearch.length)}`;
|
|
11835
12148
|
const outBuf = Buffer.from(replaced, "utf8");
|
|
11836
12149
|
ftruncateSync(fd, outBuf.length);
|
|
@@ -11852,7 +12165,7 @@ function applyEditBlocks(blocks, rootDir) {
|
|
|
11852
12165
|
return blocks.map((b) => applyEditBlock(b, rootDir));
|
|
11853
12166
|
}
|
|
11854
12167
|
function toWholeFileEditBlock(path, content, rootDir) {
|
|
11855
|
-
const abs =
|
|
12168
|
+
const abs = resolveEditPath(rootDir, path);
|
|
11856
12169
|
let search = "";
|
|
11857
12170
|
if (existsSync3(abs)) {
|
|
11858
12171
|
try {
|
|
@@ -11864,13 +12177,12 @@ function toWholeFileEditBlock(path, content, rootDir) {
|
|
|
11864
12177
|
return { path, search, replace: content, offset: 0 };
|
|
11865
12178
|
}
|
|
11866
12179
|
function snapshotBeforeEdits(blocks, rootDir) {
|
|
11867
|
-
const absRoot = resolve4(rootDir);
|
|
11868
12180
|
const seen = /* @__PURE__ */ new Set();
|
|
11869
12181
|
const snapshots = [];
|
|
11870
12182
|
for (const b of blocks) {
|
|
11871
|
-
|
|
11872
|
-
seen.
|
|
11873
|
-
|
|
12183
|
+
const abs = resolveEditPath(rootDir, b.path);
|
|
12184
|
+
if (seen.has(abs)) continue;
|
|
12185
|
+
seen.add(abs);
|
|
11874
12186
|
if (!existsSync3(abs)) {
|
|
11875
12187
|
snapshots.push({ path: b.path, prevContent: null });
|
|
11876
12188
|
continue;
|
|
@@ -11886,8 +12198,8 @@ function snapshotBeforeEdits(blocks, rootDir) {
|
|
|
11886
12198
|
function restoreSnapshots(snapshots, rootDir) {
|
|
11887
12199
|
const absRoot = resolve4(rootDir);
|
|
11888
12200
|
return snapshots.map((snap) => {
|
|
11889
|
-
const abs =
|
|
11890
|
-
if (abs
|
|
12201
|
+
const abs = resolveEditPath(rootDir, snap.path);
|
|
12202
|
+
if (!pathIsUnder2(abs, absRoot)) {
|
|
11891
12203
|
return {
|
|
11892
12204
|
path: snap.path,
|
|
11893
12205
|
status: "path-escape",
|
|
@@ -11914,9 +12226,6 @@ function restoreSnapshots(snapshots, rootDir) {
|
|
|
11914
12226
|
}
|
|
11915
12227
|
});
|
|
11916
12228
|
}
|
|
11917
|
-
function sep() {
|
|
11918
|
-
return process.platform === "win32" ? "\\" : "/";
|
|
11919
|
-
}
|
|
11920
12229
|
function lineEndingOf(text) {
|
|
11921
12230
|
return text.includes("\r\n") ? "\r\n" : "\n";
|
|
11922
12231
|
}
|
|
@@ -11942,6 +12251,7 @@ export {
|
|
|
11942
12251
|
registerChoiceTool,
|
|
11943
12252
|
registerPlanTool,
|
|
11944
12253
|
registerTodoTool,
|
|
12254
|
+
SHARED_SUBAGENT_SINK,
|
|
11945
12255
|
spawnSubagent,
|
|
11946
12256
|
formatSubagentResult,
|
|
11947
12257
|
webFetch,
|
|
@@ -11957,4 +12267,4 @@ export {
|
|
|
11957
12267
|
he/he.js:
|
|
11958
12268
|
(*! https://mths.be/he v1.2.0 by @mathias | MIT license *)
|
|
11959
12269
|
*/
|
|
11960
|
-
//# sourceMappingURL=chunk-
|
|
12270
|
+
//# sourceMappingURL=chunk-JFBGSWQB.js.map
|