reasonix 0.46.1 → 0.47.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 +62 -13
- package/README.zh-CN.md +52 -10
- package/dashboard/dist/app.js +217 -60
- package/dashboard/dist/app.js.map +1 -1
- package/dist/cli/{acp-LKJU5DZX.js → acp-QK3DMC53.js} +22 -22
- package/dist/cli/chat-VV5UWY4V.js +51 -0
- package/dist/cli/{chunk-DGA5QYFM.js → chunk-24A7FHGJ.js} +42 -13
- package/dist/cli/chunk-24A7FHGJ.js.map +1 -0
- package/dist/cli/{chunk-K3AIFMI6.js → chunk-6J6BSUCR.js} +2 -2
- package/dist/cli/{chunk-C72TNHDE.js → chunk-BWYVFFKR.js} +2 -2
- package/dist/cli/{chunk-EAOL43HB.js → chunk-BYYVYJDX.js} +3 -3
- package/dist/cli/{chunk-HNXDZGC6.js → chunk-CI2PF5QX.js} +2 -2
- package/dist/cli/{chunk-JVQT5IYP.js → chunk-COWPEX54.js} +19 -9
- package/dist/cli/chunk-COWPEX54.js.map +1 -0
- package/dist/cli/{chunk-IYQ325V7.js → chunk-E5WCLUIU.js} +2 -2
- package/dist/cli/{chunk-YRLC2EDF.js → chunk-EQATK2L2.js} +2 -2
- package/dist/cli/{chunk-R2ASNSEO.js → chunk-FDKOUJKZ.js} +8 -8
- package/dist/cli/{chunk-TEUDEGX2.js → chunk-FY4S7TJZ.js} +19 -5
- package/dist/cli/chunk-FY4S7TJZ.js.map +1 -0
- package/dist/cli/{chunk-JVFEJAJX.js → chunk-GDKB2PPK.js} +2 -2
- package/dist/cli/{chunk-WQ6ZRDQM.js → chunk-HIYTRCSW.js} +16 -12
- package/dist/cli/chunk-HIYTRCSW.js.map +1 -0
- package/dist/cli/{chunk-ZOQHVQON.js → chunk-ICAFSZHS.js} +307 -30
- package/dist/cli/chunk-ICAFSZHS.js.map +1 -0
- package/dist/cli/{chunk-SPXN5JIT.js → chunk-ICSYGIPN.js} +1386 -1021
- package/dist/cli/chunk-ICSYGIPN.js.map +1 -0
- package/dist/cli/{chunk-XPAUNFOL.js → chunk-K6GUKSXH.js} +3 -2
- package/dist/cli/chunk-K6GUKSXH.js.map +1 -0
- package/dist/cli/{chunk-6VANO7KB.js → chunk-KDRUEXII.js} +147 -20
- package/dist/cli/chunk-KDRUEXII.js.map +1 -0
- package/dist/cli/{chunk-NCBP5D6E.js → chunk-LBLR4CUZ.js} +2 -2
- package/dist/cli/{chunk-2425HK6U.js → chunk-LGEKVMMV.js} +7 -2
- package/dist/cli/{chunk-2425HK6U.js.map → chunk-LGEKVMMV.js.map} +1 -1
- package/dist/cli/{chunk-7SGGXNB2.js → chunk-OJVITDGB.js} +2 -2
- package/dist/cli/{chunk-SE7C5ZSI.js → chunk-QVDWH2A2.js} +3 -3
- package/dist/cli/{chunk-WRONKNIH.js → chunk-QVUFWDD2.js} +2 -2
- package/dist/cli/{chunk-3AAG2CUT.js → chunk-R6GQKKBW.js} +2 -2
- package/dist/cli/{chunk-E7TAHQ4A.js → chunk-RRXUIPWG.js} +19 -18
- package/dist/cli/chunk-RRXUIPWG.js.map +1 -0
- package/dist/cli/{chunk-CXVWUPA3.js → chunk-TKVXTQ3T.js} +26 -26
- package/dist/cli/chunk-TKVXTQ3T.js.map +1 -0
- package/dist/cli/{chunk-DHRVZJ2D.js → chunk-UDVFBEXC.js} +3 -3
- package/dist/cli/{chunk-7YW6TPXK.js → chunk-VC2CQA5D.js} +9 -9
- package/dist/cli/{chunk-M4E5JK6S.js → chunk-VJMBISEI.js} +2 -2
- package/dist/cli/{chunk-TDSBASOF.js → chunk-VKYSZKH2.js} +2 -2
- package/dist/cli/{chunk-7LOJS3LV.js → chunk-VMUUFWFF.js} +2 -2
- package/dist/cli/{chunk-MIIZJD5O.js → chunk-VNQGCA3Q.js} +2 -2
- package/dist/cli/{chunk-2AASOSD5.js → chunk-WF7TPVZM.js} +2 -2
- package/dist/cli/{chunk-JLQDNLZF.js → chunk-YDPLF7XR.js} +26 -14
- package/dist/cli/chunk-YDPLF7XR.js.map +1 -0
- package/dist/cli/{code-2JIHL5M2.js → code-C24TUAE5.js} +39 -34
- package/dist/cli/code-C24TUAE5.js.map +1 -0
- package/dist/cli/{commands-OPT5AJNH.js → commands-RR3GIYOK.js} +4 -4
- package/dist/cli/{commit-KA37H6GM.js → commit-FSHPIINM.js} +3 -3
- package/dist/cli/{desktop-5ONTRU3C.js → desktop-7NCHPEFB.js} +263 -36
- package/dist/cli/desktop-7NCHPEFB.js.map +1 -0
- package/dist/cli/{diff-SOIA7AKH.js → diff-RAAHHLHV.js} +8 -8
- package/dist/cli/{doctor-RCUP4XRV.js → doctor-PKVQIXRT.js} +9 -9
- package/dist/cli/{events-6KHITNX4.js → events-VRYXOSKI.js} +3 -3
- package/dist/cli/index.js +81 -40
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/{mcp-JP5OWD6R.js → mcp-CRJ26PP4.js} +2 -2
- package/dist/cli/{mcp-browse-ONCJJPJN.js → mcp-browse-QPAOWZOP.js} +2 -2
- package/dist/cli/{mcp-inspect-TPLHW5JA.js → mcp-inspect-CVCLABRS.js} +4 -4
- package/dist/cli/{prompt-RJDNCQAP.js → prompt-SKYXERSI.js} +4 -4
- package/dist/cli/{prune-sessions-MKEATRVL.js → prune-sessions-SEWX7GP6.js} +2 -2
- package/dist/cli/{replay-4NILJG4U.js → replay-KPDW2ZMJ.js} +9 -9
- package/dist/cli/{run-WFGXB4SB.js → run-WIKDIXTG.js} +17 -17
- package/dist/cli/{server-5VFQP3PV.js → server-P6V2G3P6.js} +82 -34
- package/dist/cli/server-P6V2G3P6.js.map +1 -0
- package/dist/cli/{sessions-5XDJDALO.js → sessions-2NULRMSA.js} +15 -15
- package/dist/cli/{setup-F6XSWLRA.js → setup-Y5WDBQFL.js} +6 -6
- package/dist/cli/{stats-ALHBZICE.js → stats-T7BL2YOR.js} +6 -6
- package/dist/cli/{version-JVRAHBMM.js → version-3KWDNWLN.js} +15 -15
- package/dist/index.d.ts +31 -10
- package/dist/index.js +505 -66
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/cli/chat-W7LAWEN6.js +0 -51
- package/dist/cli/chunk-6VANO7KB.js.map +0 -1
- package/dist/cli/chunk-CXVWUPA3.js.map +0 -1
- package/dist/cli/chunk-DGA5QYFM.js.map +0 -1
- package/dist/cli/chunk-E7TAHQ4A.js.map +0 -1
- package/dist/cli/chunk-JLQDNLZF.js.map +0 -1
- package/dist/cli/chunk-JVQT5IYP.js.map +0 -1
- package/dist/cli/chunk-SPXN5JIT.js.map +0 -1
- package/dist/cli/chunk-TEUDEGX2.js.map +0 -1
- package/dist/cli/chunk-WQ6ZRDQM.js.map +0 -1
- package/dist/cli/chunk-XPAUNFOL.js.map +0 -1
- package/dist/cli/chunk-ZOQHVQON.js.map +0 -1
- package/dist/cli/code-2JIHL5M2.js.map +0 -1
- package/dist/cli/desktop-5ONTRU3C.js.map +0 -1
- package/dist/cli/server-5VFQP3PV.js.map +0 -1
- /package/dist/cli/{acp-LKJU5DZX.js.map → acp-QK3DMC53.js.map} +0 -0
- /package/dist/cli/{chat-W7LAWEN6.js.map → chat-VV5UWY4V.js.map} +0 -0
- /package/dist/cli/{chunk-K3AIFMI6.js.map → chunk-6J6BSUCR.js.map} +0 -0
- /package/dist/cli/{chunk-C72TNHDE.js.map → chunk-BWYVFFKR.js.map} +0 -0
- /package/dist/cli/{chunk-EAOL43HB.js.map → chunk-BYYVYJDX.js.map} +0 -0
- /package/dist/cli/{chunk-HNXDZGC6.js.map → chunk-CI2PF5QX.js.map} +0 -0
- /package/dist/cli/{chunk-IYQ325V7.js.map → chunk-E5WCLUIU.js.map} +0 -0
- /package/dist/cli/{chunk-YRLC2EDF.js.map → chunk-EQATK2L2.js.map} +0 -0
- /package/dist/cli/{chunk-R2ASNSEO.js.map → chunk-FDKOUJKZ.js.map} +0 -0
- /package/dist/cli/{chunk-JVFEJAJX.js.map → chunk-GDKB2PPK.js.map} +0 -0
- /package/dist/cli/{chunk-NCBP5D6E.js.map → chunk-LBLR4CUZ.js.map} +0 -0
- /package/dist/cli/{chunk-7SGGXNB2.js.map → chunk-OJVITDGB.js.map} +0 -0
- /package/dist/cli/{chunk-SE7C5ZSI.js.map → chunk-QVDWH2A2.js.map} +0 -0
- /package/dist/cli/{chunk-WRONKNIH.js.map → chunk-QVUFWDD2.js.map} +0 -0
- /package/dist/cli/{chunk-3AAG2CUT.js.map → chunk-R6GQKKBW.js.map} +0 -0
- /package/dist/cli/{chunk-DHRVZJ2D.js.map → chunk-UDVFBEXC.js.map} +0 -0
- /package/dist/cli/{chunk-7YW6TPXK.js.map → chunk-VC2CQA5D.js.map} +0 -0
- /package/dist/cli/{chunk-M4E5JK6S.js.map → chunk-VJMBISEI.js.map} +0 -0
- /package/dist/cli/{chunk-TDSBASOF.js.map → chunk-VKYSZKH2.js.map} +0 -0
- /package/dist/cli/{chunk-7LOJS3LV.js.map → chunk-VMUUFWFF.js.map} +0 -0
- /package/dist/cli/{chunk-MIIZJD5O.js.map → chunk-VNQGCA3Q.js.map} +0 -0
- /package/dist/cli/{chunk-2AASOSD5.js.map → chunk-WF7TPVZM.js.map} +0 -0
- /package/dist/cli/{commands-OPT5AJNH.js.map → commands-RR3GIYOK.js.map} +0 -0
- /package/dist/cli/{commit-KA37H6GM.js.map → commit-FSHPIINM.js.map} +0 -0
- /package/dist/cli/{diff-SOIA7AKH.js.map → diff-RAAHHLHV.js.map} +0 -0
- /package/dist/cli/{doctor-RCUP4XRV.js.map → doctor-PKVQIXRT.js.map} +0 -0
- /package/dist/cli/{events-6KHITNX4.js.map → events-VRYXOSKI.js.map} +0 -0
- /package/dist/cli/{mcp-JP5OWD6R.js.map → mcp-CRJ26PP4.js.map} +0 -0
- /package/dist/cli/{mcp-browse-ONCJJPJN.js.map → mcp-browse-QPAOWZOP.js.map} +0 -0
- /package/dist/cli/{mcp-inspect-TPLHW5JA.js.map → mcp-inspect-CVCLABRS.js.map} +0 -0
- /package/dist/cli/{prompt-RJDNCQAP.js.map → prompt-SKYXERSI.js.map} +0 -0
- /package/dist/cli/{prune-sessions-MKEATRVL.js.map → prune-sessions-SEWX7GP6.js.map} +0 -0
- /package/dist/cli/{replay-4NILJG4U.js.map → replay-KPDW2ZMJ.js.map} +0 -0
- /package/dist/cli/{run-WFGXB4SB.js.map → run-WIKDIXTG.js.map} +0 -0
- /package/dist/cli/{sessions-5XDJDALO.js.map → sessions-2NULRMSA.js.map} +0 -0
- /package/dist/cli/{setup-F6XSWLRA.js.map → setup-Y5WDBQFL.js.map} +0 -0
- /package/dist/cli/{stats-ALHBZICE.js.map → stats-T7BL2YOR.js.map} +0 -0
- /package/dist/cli/{version-JVRAHBMM.js.map → version-3KWDNWLN.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-UDVFBEXC.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-VNQGCA3Q.js";
|
|
16
16
|
import {
|
|
17
17
|
applyEdit,
|
|
18
18
|
applyMultiEdit,
|
|
19
19
|
pauseGate
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-GDKB2PPK.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-FY4S7TJZ.js";
|
|
28
28
|
import {
|
|
29
29
|
formatHookOutcomeMessage,
|
|
30
30
|
runHooks
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-BWYVFFKR.js";
|
|
32
32
|
import {
|
|
33
33
|
ignoredByLayers,
|
|
34
34
|
loadGitignoreAt,
|
|
@@ -41,25 +41,26 @@ import {
|
|
|
41
41
|
loadSessionMeta,
|
|
42
42
|
rewriteSession,
|
|
43
43
|
timestampSuffix
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-RRXUIPWG.js";
|
|
45
45
|
import {
|
|
46
46
|
DEEPSEEK_CONTEXT_TOKENS,
|
|
47
47
|
DEFAULT_CONTEXT_TOKENS,
|
|
48
48
|
SessionStats
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-VJMBISEI.js";
|
|
50
50
|
import {
|
|
51
51
|
t
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-KDRUEXII.js";
|
|
53
53
|
import {
|
|
54
54
|
DEFAULT_INDEX_EXCLUDES,
|
|
55
55
|
addProjectPathAllowed,
|
|
56
56
|
loadMemoryTypeRegistry,
|
|
57
57
|
loadMetasoApiKey,
|
|
58
58
|
loadProjectPathAllowed,
|
|
59
|
+
loadTavilyApiKey,
|
|
59
60
|
require_picomatch,
|
|
60
61
|
webSearchEndpoint,
|
|
61
62
|
webSearchEngine
|
|
62
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-24A7FHGJ.js";
|
|
63
64
|
import {
|
|
64
65
|
__commonJS,
|
|
65
66
|
__esm,
|
|
@@ -6124,11 +6125,42 @@ async function bridgeMcpTools(client, opts = {}) {
|
|
|
6124
6125
|
return { ...result, env };
|
|
6125
6126
|
}
|
|
6126
6127
|
function flattenMcpResult(result, opts = {}) {
|
|
6128
|
+
validateResultShape(result);
|
|
6127
6129
|
const parts = result.content.map(blockToString);
|
|
6128
6130
|
const joined = parts.join("\n").trim();
|
|
6129
6131
|
const prefixed = result.isError ? `ERROR: ${joined || "(no error message from server)"}` : joined;
|
|
6130
6132
|
return opts.maxChars ? truncateForModel(prefixed, opts.maxChars) : prefixed;
|
|
6131
6133
|
}
|
|
6134
|
+
function validateResultShape(result) {
|
|
6135
|
+
if (typeof result !== "object" || !result)
|
|
6136
|
+
throw new Error(`MCP server returned non-object result: ${typeof result}`);
|
|
6137
|
+
const { content, isError: _isError } = result;
|
|
6138
|
+
if (!Array.isArray(content))
|
|
6139
|
+
throw new Error(`MCP server returned result with non-array content: ${typeof content}`);
|
|
6140
|
+
for (let i = 0; i < content.length; i++) {
|
|
6141
|
+
const block = content[i];
|
|
6142
|
+
if (typeof block !== "object" || !block)
|
|
6143
|
+
throw new Error(`MCP server returned result.content[${i}] is not an object`);
|
|
6144
|
+
if (block.type !== "text" && block.type !== "image")
|
|
6145
|
+
throw new Error(
|
|
6146
|
+
`MCP server returned result.content[${i}] with unknown type ${JSON.stringify(block.type)}`
|
|
6147
|
+
);
|
|
6148
|
+
if (block.type === "text" && typeof block.text !== "string")
|
|
6149
|
+
throw new Error(
|
|
6150
|
+
`MCP server returned result.content[${i}] with non-string text (${typeof block.text})`
|
|
6151
|
+
);
|
|
6152
|
+
if (block.type === "image") {
|
|
6153
|
+
if (typeof block.data !== "string")
|
|
6154
|
+
throw new Error(
|
|
6155
|
+
`MCP server returned result.content[${i}] with non-string data (${typeof block.data})`
|
|
6156
|
+
);
|
|
6157
|
+
if (typeof block.mimeType !== "string")
|
|
6158
|
+
throw new Error(
|
|
6159
|
+
`MCP server returned result.content[${i}] with non-string mimeType (${typeof block.mimeType})`
|
|
6160
|
+
);
|
|
6161
|
+
}
|
|
6162
|
+
}
|
|
6163
|
+
}
|
|
6132
6164
|
function truncateForModel(s, maxChars) {
|
|
6133
6165
|
if (s.length <= maxChars) return s;
|
|
6134
6166
|
const tailBudget = Math.min(1024, Math.floor(maxChars * 0.1));
|
|
@@ -6394,6 +6426,12 @@ var ToolRegistry = class {
|
|
|
6394
6426
|
});
|
|
6395
6427
|
}
|
|
6396
6428
|
}
|
|
6429
|
+
if (opts.signal?.aborted) {
|
|
6430
|
+
return JSON.stringify({
|
|
6431
|
+
error: `${name}: aborted before dispatch (user interrupt)`,
|
|
6432
|
+
rejectedReason: "aborted"
|
|
6433
|
+
});
|
|
6434
|
+
}
|
|
6397
6435
|
let finalResult;
|
|
6398
6436
|
try {
|
|
6399
6437
|
try {
|
|
@@ -7877,6 +7915,32 @@ ${reason}`
|
|
|
7877
7915
|
}
|
|
7878
7916
|
return userText;
|
|
7879
7917
|
}
|
|
7918
|
+
/** Rewind to the N-th user turn (0-indexed). Drops that turn + everything after. */
|
|
7919
|
+
rewindToUserTurn(userTurnIndex) {
|
|
7920
|
+
const entries = this.log.entries;
|
|
7921
|
+
let count = 0;
|
|
7922
|
+
let targetIdx = -1;
|
|
7923
|
+
for (let i = 0; i < entries.length; i++) {
|
|
7924
|
+
if (entries[i].role !== "user") continue;
|
|
7925
|
+
if (count === userTurnIndex) {
|
|
7926
|
+
targetIdx = i;
|
|
7927
|
+
break;
|
|
7928
|
+
}
|
|
7929
|
+
count++;
|
|
7930
|
+
}
|
|
7931
|
+
if (targetIdx < 0) return null;
|
|
7932
|
+
const raw = entries[targetIdx].content;
|
|
7933
|
+
const userText = typeof raw === "string" ? raw : "";
|
|
7934
|
+
const preserved = entries.slice(0, targetIdx).map((m) => ({ ...m }));
|
|
7935
|
+
this.log.compactInPlace(preserved);
|
|
7936
|
+
if (this.sessionName) {
|
|
7937
|
+
try {
|
|
7938
|
+
rewriteSession(this.sessionName, preserved);
|
|
7939
|
+
} catch {
|
|
7940
|
+
}
|
|
7941
|
+
}
|
|
7942
|
+
return userText;
|
|
7943
|
+
}
|
|
7880
7944
|
async *step(userInput) {
|
|
7881
7945
|
this._steerConsumed = false;
|
|
7882
7946
|
if (this.budgetUsd !== null) {
|
|
@@ -9157,6 +9221,7 @@ var FETCH_MAX_BYTES = 10 * 1024 * 1024;
|
|
|
9157
9221
|
var USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";
|
|
9158
9222
|
var MOJEEK_ENDPOINT = "https://www.mojeek.com/search";
|
|
9159
9223
|
var METASO_ENDPOINT = "https://metaso.cn/api/v1";
|
|
9224
|
+
var TAVILY_ENDPOINT = "https://api.tavily.com/search";
|
|
9160
9225
|
function searchStatusError(status) {
|
|
9161
9226
|
if (status === 429) return t("webErrors.rateLimit429");
|
|
9162
9227
|
if (status === 403) return t("webErrors.forbidden403");
|
|
@@ -9176,6 +9241,9 @@ async function webSearch(query, opts = {}) {
|
|
|
9176
9241
|
if (opts.engine === "searxng") {
|
|
9177
9242
|
return searchSearxng(query, opts);
|
|
9178
9243
|
}
|
|
9244
|
+
if (opts.engine === "tavily") {
|
|
9245
|
+
return searchTavily(query, opts);
|
|
9246
|
+
}
|
|
9179
9247
|
return searchMojeek(query, opts);
|
|
9180
9248
|
}
|
|
9181
9249
|
async function searchMojeek(query, opts = {}) {
|
|
@@ -9310,6 +9378,55 @@ async function searchMetaso(query, opts = {}) {
|
|
|
9310
9378
|
snippet: wp.snippet ?? wp.summary ?? ""
|
|
9311
9379
|
}));
|
|
9312
9380
|
}
|
|
9381
|
+
async function searchTavily(query, opts = {}) {
|
|
9382
|
+
const topK = Math.max(1, Math.min(20, opts.topK ?? DEFAULT_TOPK));
|
|
9383
|
+
const apiKey = loadTavilyApiKey();
|
|
9384
|
+
if (!apiKey) throw new Error(t("webErrors.tavilyMissingKey"));
|
|
9385
|
+
let resp;
|
|
9386
|
+
try {
|
|
9387
|
+
resp = await fetch(TAVILY_ENDPOINT, {
|
|
9388
|
+
method: "POST",
|
|
9389
|
+
headers: {
|
|
9390
|
+
"Content-Type": "application/json",
|
|
9391
|
+
Accept: "application/json"
|
|
9392
|
+
},
|
|
9393
|
+
body: JSON.stringify({
|
|
9394
|
+
api_key: apiKey,
|
|
9395
|
+
query,
|
|
9396
|
+
search_depth: "basic",
|
|
9397
|
+
max_results: topK,
|
|
9398
|
+
include_answer: false,
|
|
9399
|
+
include_raw_content: false,
|
|
9400
|
+
include_images: false
|
|
9401
|
+
}),
|
|
9402
|
+
signal: opts.signal
|
|
9403
|
+
});
|
|
9404
|
+
} catch (err) {
|
|
9405
|
+
if (err instanceof TypeError && err.message.includes("fetch")) {
|
|
9406
|
+
throw new Error(t("webErrors.cannotReach", { endpoint: TAVILY_ENDPOINT }));
|
|
9407
|
+
}
|
|
9408
|
+
throw err;
|
|
9409
|
+
}
|
|
9410
|
+
if (!resp.ok) {
|
|
9411
|
+
if (resp.status === 401 || resp.status === 403) {
|
|
9412
|
+
throw new Error(t("webErrors.tavilyUnauthorized"));
|
|
9413
|
+
}
|
|
9414
|
+
if (resp.status === 429) throw new Error(t("webErrors.tavilyRateLimit"));
|
|
9415
|
+
throw new Error(t("webErrors.tavilyServerError", { status: resp.status }));
|
|
9416
|
+
}
|
|
9417
|
+
let data;
|
|
9418
|
+
try {
|
|
9419
|
+
data = await resp.json();
|
|
9420
|
+
} catch {
|
|
9421
|
+
throw new Error(t("webErrors.tavilyParseError", { status: resp.status }));
|
|
9422
|
+
}
|
|
9423
|
+
const results = data.results ?? [];
|
|
9424
|
+
return results.slice(0, topK).map((r) => ({
|
|
9425
|
+
title: r.title,
|
|
9426
|
+
url: r.url,
|
|
9427
|
+
snippet: r.content ?? ""
|
|
9428
|
+
}));
|
|
9429
|
+
}
|
|
9313
9430
|
function parseSearxngHtmlResults(html) {
|
|
9314
9431
|
const root = (0, import_node_html_parser.parse)(html);
|
|
9315
9432
|
const results = [];
|
|
@@ -9528,7 +9645,7 @@ function registerWebTools(registry, opts = {}) {
|
|
|
9528
9645
|
const maxFetchChars = opts.maxFetchChars ?? DEFAULT_FETCH_MAX_CHARS;
|
|
9529
9646
|
registry.register({
|
|
9530
9647
|
name: "web_search",
|
|
9531
|
-
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. To change the backend, use /search-engine mojeek|searxng|metaso.",
|
|
9648
|
+
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. To change the backend, use /search-engine mojeek|searxng|metaso|tavily.",
|
|
9532
9649
|
readOnly: true,
|
|
9533
9650
|
parallelSafe: true,
|
|
9534
9651
|
parameters: {
|
|
@@ -9600,13 +9717,13 @@ import * as pathMod4 from "path";
|
|
|
9600
9717
|
// src/memory/subdir.ts
|
|
9601
9718
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
9602
9719
|
import { dirname, join as join2, relative as relative2, resolve as resolve2 } from "path";
|
|
9603
|
-
function
|
|
9720
|
+
function findDirMemory(absDir, rootDir) {
|
|
9604
9721
|
const root = resolve2(rootDir);
|
|
9605
|
-
const target = resolve2(
|
|
9722
|
+
const target = resolve2(absDir);
|
|
9606
9723
|
const rel = relative2(root, target);
|
|
9607
|
-
if (
|
|
9724
|
+
if (rel.startsWith("..")) return [];
|
|
9608
9725
|
const found = [];
|
|
9609
|
-
let cur =
|
|
9726
|
+
let cur = target;
|
|
9610
9727
|
while (cur !== root) {
|
|
9611
9728
|
const r = relative2(root, cur);
|
|
9612
9729
|
if (!r || r.startsWith("..")) break;
|
|
@@ -9623,6 +9740,9 @@ function findSubdirMemoryAncestors(absPath, rootDir) {
|
|
|
9623
9740
|
}
|
|
9624
9741
|
return found;
|
|
9625
9742
|
}
|
|
9743
|
+
function findSubdirMemoryAncestors(absPath, rootDir) {
|
|
9744
|
+
return findDirMemory(dirname(resolve2(absPath)), rootDir);
|
|
9745
|
+
}
|
|
9626
9746
|
function readSubdirMemoryContent(path) {
|
|
9627
9747
|
let raw;
|
|
9628
9748
|
try {
|
|
@@ -9891,6 +10011,129 @@ function formatOutline(entries) {
|
|
|
9891
10011
|
// src/tools/fs/search.ts
|
|
9892
10012
|
import { promises as fs2 } from "fs";
|
|
9893
10013
|
import * as pathMod3 from "path";
|
|
10014
|
+
|
|
10015
|
+
// src/tools/fs/regex-runner.ts
|
|
10016
|
+
import { Worker } from "worker_threads";
|
|
10017
|
+
var WORKER_SOURCE = `
|
|
10018
|
+
const { parentPort } = require("node:worker_threads");
|
|
10019
|
+
parentPort.on("message", (msg) => {
|
|
10020
|
+
const { id, text, source, flags } = msg;
|
|
10021
|
+
let re;
|
|
10022
|
+
try {
|
|
10023
|
+
re = new RegExp(source, flags);
|
|
10024
|
+
} catch (err) {
|
|
10025
|
+
parentPort.postMessage({ id, error: (err && err.message) ? err.message : String(err) });
|
|
10026
|
+
return;
|
|
10027
|
+
}
|
|
10028
|
+
const lines = text.split(/\\r?\\n/);
|
|
10029
|
+
const hits = [];
|
|
10030
|
+
for (let i = 0; i < lines.length; i++) {
|
|
10031
|
+
if (re.test(lines[i])) hits.push(i);
|
|
10032
|
+
}
|
|
10033
|
+
parentPort.postMessage({ id, hits });
|
|
10034
|
+
});
|
|
10035
|
+
`;
|
|
10036
|
+
var DEFAULT_TIMEOUT_MS = 6e4;
|
|
10037
|
+
var RegexRunner = class {
|
|
10038
|
+
worker = null;
|
|
10039
|
+
pending = /* @__PURE__ */ new Map();
|
|
10040
|
+
nextId = 1;
|
|
10041
|
+
defaultTimeoutMs;
|
|
10042
|
+
constructor(opts = {}) {
|
|
10043
|
+
this.defaultTimeoutMs = opts.defaultTimeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
10044
|
+
}
|
|
10045
|
+
testLines(text, source, flags, opts = {}) {
|
|
10046
|
+
return new Promise((resolve5, reject) => {
|
|
10047
|
+
if (opts.signal?.aborted) {
|
|
10048
|
+
reject(new Error("regex evaluation aborted"));
|
|
10049
|
+
return;
|
|
10050
|
+
}
|
|
10051
|
+
if (!this.worker) this.worker = this.spawn();
|
|
10052
|
+
const id = this.nextId++;
|
|
10053
|
+
const timeoutMs = opts.timeoutMs ?? this.defaultTimeoutMs;
|
|
10054
|
+
const timer = setTimeout(() => {
|
|
10055
|
+
this.pending.delete(id);
|
|
10056
|
+
this.killWorker();
|
|
10057
|
+
reject(new Error(`regex evaluation exceeded ${timeoutMs}ms`));
|
|
10058
|
+
}, timeoutMs);
|
|
10059
|
+
const entry = { resolve: resolve5, reject, timer };
|
|
10060
|
+
if (opts.signal) {
|
|
10061
|
+
entry.signal = opts.signal;
|
|
10062
|
+
entry.onAbort = () => {
|
|
10063
|
+
this.pending.delete(id);
|
|
10064
|
+
clearTimeout(timer);
|
|
10065
|
+
this.killWorker();
|
|
10066
|
+
reject(new Error("regex evaluation aborted"));
|
|
10067
|
+
};
|
|
10068
|
+
opts.signal.addEventListener("abort", entry.onAbort, { once: true });
|
|
10069
|
+
}
|
|
10070
|
+
this.pending.set(id, entry);
|
|
10071
|
+
this.worker.postMessage({ id, text, source, flags });
|
|
10072
|
+
});
|
|
10073
|
+
}
|
|
10074
|
+
async shutdown() {
|
|
10075
|
+
if (this.worker) {
|
|
10076
|
+
const w = this.worker;
|
|
10077
|
+
this.worker = null;
|
|
10078
|
+
await w.terminate();
|
|
10079
|
+
}
|
|
10080
|
+
for (const entry of this.pending.values()) {
|
|
10081
|
+
clearTimeout(entry.timer);
|
|
10082
|
+
if (entry.onAbort && entry.signal) {
|
|
10083
|
+
entry.signal.removeEventListener("abort", entry.onAbort);
|
|
10084
|
+
}
|
|
10085
|
+
entry.reject(new Error("regex runner shut down"));
|
|
10086
|
+
}
|
|
10087
|
+
this.pending.clear();
|
|
10088
|
+
}
|
|
10089
|
+
spawn() {
|
|
10090
|
+
const w = new Worker(WORKER_SOURCE, { eval: true });
|
|
10091
|
+
w.on("message", (msg) => {
|
|
10092
|
+
const entry = this.pending.get(msg.id);
|
|
10093
|
+
if (!entry) return;
|
|
10094
|
+
clearTimeout(entry.timer);
|
|
10095
|
+
if (entry.onAbort && entry.signal) {
|
|
10096
|
+
entry.signal.removeEventListener("abort", entry.onAbort);
|
|
10097
|
+
}
|
|
10098
|
+
this.pending.delete(msg.id);
|
|
10099
|
+
if (msg.error !== void 0) entry.reject(new Error(msg.error));
|
|
10100
|
+
else entry.resolve(msg.hits ?? []);
|
|
10101
|
+
});
|
|
10102
|
+
w.on("error", (err) => {
|
|
10103
|
+
if (this.worker !== w) return;
|
|
10104
|
+
this.failPending(err);
|
|
10105
|
+
});
|
|
10106
|
+
w.on("exit", () => {
|
|
10107
|
+
if (this.worker !== w) return;
|
|
10108
|
+
this.worker = null;
|
|
10109
|
+
if (this.pending.size > 0) this.failPending(new Error("regex worker exited"));
|
|
10110
|
+
});
|
|
10111
|
+
return w;
|
|
10112
|
+
}
|
|
10113
|
+
killWorker() {
|
|
10114
|
+
if (!this.worker) return;
|
|
10115
|
+
const w = this.worker;
|
|
10116
|
+
this.worker = null;
|
|
10117
|
+
void w.terminate();
|
|
10118
|
+
}
|
|
10119
|
+
failPending(err) {
|
|
10120
|
+
for (const entry of this.pending.values()) {
|
|
10121
|
+
clearTimeout(entry.timer);
|
|
10122
|
+
if (entry.onAbort && entry.signal) {
|
|
10123
|
+
entry.signal.removeEventListener("abort", entry.onAbort);
|
|
10124
|
+
}
|
|
10125
|
+
entry.reject(err);
|
|
10126
|
+
}
|
|
10127
|
+
this.pending.clear();
|
|
10128
|
+
}
|
|
10129
|
+
};
|
|
10130
|
+
var _runner = null;
|
|
10131
|
+
function getRegexRunner() {
|
|
10132
|
+
if (!_runner) _runner = new RegexRunner();
|
|
10133
|
+
return _runner;
|
|
10134
|
+
}
|
|
10135
|
+
|
|
10136
|
+
// src/tools/fs/search.ts
|
|
9894
10137
|
function throwIfAborted(signal) {
|
|
9895
10138
|
if (!signal?.aborted) return;
|
|
9896
10139
|
throw new DOMException("search aborted by user", "AbortError");
|
|
@@ -9943,17 +10186,20 @@ async function searchFiles(ctx, startAbs, args) {
|
|
|
9943
10186
|
}
|
|
9944
10187
|
var MAX_HITS_PER_FILE = 30;
|
|
9945
10188
|
var SUMMARY_MODE_TRIGGER_RATIO = 0.8;
|
|
10189
|
+
var WALK_DEADLINE_MS = 12e4;
|
|
9946
10190
|
async function searchContent(ctx, startAbs, args) {
|
|
9947
10191
|
throwIfAborted(args.signal);
|
|
9948
10192
|
const caseSensitive = args.case_sensitive === true;
|
|
9949
10193
|
const includeDeps = args.include_deps === true;
|
|
9950
10194
|
const ctxLines = Math.max(0, Math.min(20, Math.floor(args.context ?? 0)));
|
|
9951
10195
|
const summaryOnly = args.summary_only === true;
|
|
9952
|
-
|
|
10196
|
+
const reFlags = caseSensitive ? "" : "i";
|
|
10197
|
+
let reSource = null;
|
|
9953
10198
|
try {
|
|
9954
|
-
|
|
10199
|
+
new RegExp(args.pattern, reFlags);
|
|
10200
|
+
reSource = args.pattern;
|
|
9955
10201
|
} catch {
|
|
9956
|
-
|
|
10202
|
+
reSource = null;
|
|
9957
10203
|
}
|
|
9958
10204
|
const needle = caseSensitive ? args.pattern : args.pattern.toLowerCase();
|
|
9959
10205
|
const matches = [];
|
|
@@ -9963,6 +10209,15 @@ async function searchContent(ctx, startAbs, args) {
|
|
|
9963
10209
|
let summaryMode = summaryOnly;
|
|
9964
10210
|
let summaryNoticeEmitted = false;
|
|
9965
10211
|
const fileHitCounts = /* @__PURE__ */ new Map();
|
|
10212
|
+
const regexSkippedFiles = [];
|
|
10213
|
+
const t0 = Date.now();
|
|
10214
|
+
const throwIfTimedOut = () => {
|
|
10215
|
+
if (Date.now() - t0 > WALK_DEADLINE_MS) {
|
|
10216
|
+
throw new Error(
|
|
10217
|
+
`search_content exceeded ${WALK_DEADLINE_MS}ms \u2014 narrow the scope (path/glob) or simplify the pattern`
|
|
10218
|
+
);
|
|
10219
|
+
}
|
|
10220
|
+
};
|
|
9966
10221
|
const pushLine = (out) => {
|
|
9967
10222
|
if (totalBytes + out.length + 1 > ctx.maxListBytes) {
|
|
9968
10223
|
matches.push(`[\u2026 truncated at ${ctx.maxListBytes} bytes \u2014 refine pattern or path \u2026]`);
|
|
@@ -9997,6 +10252,7 @@ async function searchContent(ctx, startAbs, args) {
|
|
|
9997
10252
|
for (const e of entries) {
|
|
9998
10253
|
if (truncated) return;
|
|
9999
10254
|
throwIfAborted(args.signal);
|
|
10255
|
+
throwIfTimedOut();
|
|
10000
10256
|
if (e.isDirectory()) {
|
|
10001
10257
|
if (!includeDeps && ctx.skipDirNames.has(e.name)) continue;
|
|
10002
10258
|
await walk2(pathMod3.join(dir, e.name));
|
|
@@ -10033,13 +10289,25 @@ async function searchContent(ctx, startAbs, args) {
|
|
|
10033
10289
|
const text = raw.toString("utf8");
|
|
10034
10290
|
const rel = displayRel2(ctx.rootDir, full);
|
|
10035
10291
|
const lines = text.split(/\r?\n/);
|
|
10036
|
-
|
|
10037
|
-
|
|
10038
|
-
|
|
10039
|
-
|
|
10040
|
-
|
|
10041
|
-
|
|
10042
|
-
|
|
10292
|
+
let hits;
|
|
10293
|
+
if (reSource !== null) {
|
|
10294
|
+
try {
|
|
10295
|
+
hits = await getRegexRunner().testLines(text, reSource, reFlags, {
|
|
10296
|
+
signal: args.signal
|
|
10297
|
+
});
|
|
10298
|
+
} catch (err) {
|
|
10299
|
+
const reason = err.message;
|
|
10300
|
+
if (reason.includes("aborted")) throw err;
|
|
10301
|
+
regexSkippedFiles.push({ rel, reason });
|
|
10302
|
+
continue;
|
|
10303
|
+
}
|
|
10304
|
+
} else {
|
|
10305
|
+
hits = [];
|
|
10306
|
+
for (let li = 0; li < lines.length; li++) {
|
|
10307
|
+
throwIfAborted(args.signal);
|
|
10308
|
+
const lineForCheck = caseSensitive ? lines[li] : lines[li].toLowerCase();
|
|
10309
|
+
if (lineForCheck.includes(needle)) hits.push(li);
|
|
10310
|
+
}
|
|
10043
10311
|
}
|
|
10044
10312
|
scanned++;
|
|
10045
10313
|
if (hits.length === 0) continue;
|
|
@@ -10088,6 +10356,11 @@ async function searchContent(ctx, startAbs, args) {
|
|
|
10088
10356
|
}
|
|
10089
10357
|
};
|
|
10090
10358
|
await walk2(startAbs);
|
|
10359
|
+
if (regexSkippedFiles.length > 0) {
|
|
10360
|
+
pushLine(
|
|
10361
|
+
`[regex timed out on ${regexSkippedFiles.length} file${regexSkippedFiles.length === 1 ? "" : "s"} \u2014 pattern may have catastrophic backtracking; first: ${regexSkippedFiles[0].rel}]`
|
|
10362
|
+
);
|
|
10363
|
+
}
|
|
10091
10364
|
if (matches.length === 0) {
|
|
10092
10365
|
return scanned === 0 ? "(no files scanned \u2014 path empty or all files filtered out)" : `(no matches across ${scanned} file${scanned === 1 ? "" : "s"})`;
|
|
10093
10366
|
}
|
|
@@ -10152,11 +10425,15 @@ function registerFilesystemTools(registry, opts) {
|
|
|
10152
10425
|
const sessionApproved = /* @__PURE__ */ new Set();
|
|
10153
10426
|
const shownSubdirMemory = /* @__PURE__ */ new Set();
|
|
10154
10427
|
function withSubdirMemory(absPath, body) {
|
|
10155
|
-
|
|
10156
|
-
|
|
10157
|
-
|
|
10428
|
+
return prependMemorySections(findSubdirMemoryAncestors(absPath, rootDir), body);
|
|
10429
|
+
}
|
|
10430
|
+
function withDirMemory(absDir, body) {
|
|
10431
|
+
return prependMemorySections(findDirMemory(absDir, rootDir), body);
|
|
10432
|
+
}
|
|
10433
|
+
function prependMemorySections(memPaths, body) {
|
|
10434
|
+
if (!memoryEnabled() || memPaths.length === 0) return body;
|
|
10158
10435
|
const sections = [];
|
|
10159
|
-
for (const memPath of [...
|
|
10436
|
+
for (const memPath of [...memPaths].reverse()) {
|
|
10160
10437
|
if (shownSubdirMemory.has(memPath)) continue;
|
|
10161
10438
|
const content = readSubdirMemoryContent(memPath);
|
|
10162
10439
|
if (!content) continue;
|
|
@@ -10349,7 +10626,7 @@ ${slice.join("\n")}`);
|
|
|
10349
10626
|
for (const e of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
10350
10627
|
lines.push(e.isDirectory() ? `${e.name}/` : e.name);
|
|
10351
10628
|
}
|
|
10352
|
-
return lines.join("\n") || "(empty directory)";
|
|
10629
|
+
return withDirMemory(abs, lines.join("\n") || "(empty directory)");
|
|
10353
10630
|
}
|
|
10354
10631
|
});
|
|
10355
10632
|
registry.register({
|
|
@@ -11571,4 +11848,4 @@ export {
|
|
|
11571
11848
|
he/he.js:
|
|
11572
11849
|
(*! https://mths.be/he v1.2.0 by @mathias | MIT license *)
|
|
11573
11850
|
*/
|
|
11574
|
-
//# sourceMappingURL=chunk-
|
|
11851
|
+
//# sourceMappingURL=chunk-ICAFSZHS.js.map
|