@kavienw/deepseek-cli 0.1.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 +470 -0
- package/dist/agent.js +864 -0
- package/dist/agent.js.map +1 -0
- package/dist/attachments.js +54 -0
- package/dist/attachments.js.map +1 -0
- package/dist/btw.js +52 -0
- package/dist/btw.js.map +1 -0
- package/dist/client.js +88 -0
- package/dist/client.js.map +1 -0
- package/dist/commands.js +922 -0
- package/dist/commands.js.map +1 -0
- package/dist/config.js +98 -0
- package/dist/config.js.map +1 -0
- package/dist/hooks.js +90 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.js +149 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp.js +408 -0
- package/dist/mcp.js.map +1 -0
- package/dist/permissions.js +30 -0
- package/dist/permissions.js.map +1 -0
- package/dist/plugins.js +341 -0
- package/dist/plugins.js.map +1 -0
- package/dist/project.js +114 -0
- package/dist/project.js.map +1 -0
- package/dist/session.js +57 -0
- package/dist/session.js.map +1 -0
- package/dist/skills.js +147 -0
- package/dist/skills.js.map +1 -0
- package/dist/todo.js +67 -0
- package/dist/todo.js.map +1 -0
- package/dist/tools/bash.js +61 -0
- package/dist/tools/bash.js.map +1 -0
- package/dist/tools/diff.js +26 -0
- package/dist/tools/diff.js.map +1 -0
- package/dist/tools/edit.js +73 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/glob.js +47 -0
- package/dist/tools/glob.js.map +1 -0
- package/dist/tools/grep.js +133 -0
- package/dist/tools/grep.js.map +1 -0
- package/dist/tools/index.js +60 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/read.js +62 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/setThinking.js +46 -0
- package/dist/tools/setThinking.js.map +1 -0
- package/dist/tools/task.js +40 -0
- package/dist/tools/task.js.map +1 -0
- package/dist/tools/todo.js +73 -0
- package/dist/tools/todo.js.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/webFetch.js +64 -0
- package/dist/tools/webFetch.js.map +1 -0
- package/dist/tools/webSearch.js +200 -0
- package/dist/tools/webSearch.js.map +1 -0
- package/dist/tools/write.js +46 -0
- package/dist/tools/write.js.map +1 -0
- package/dist/ui/render.js +248 -0
- package/dist/ui/render.js.map +1 -0
- package/dist/ui/repl.js +429 -0
- package/dist/ui/repl.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { readTool } from "./read.js";
|
|
2
|
+
import { writeTool } from "./write.js";
|
|
3
|
+
import { editTool } from "./edit.js";
|
|
4
|
+
import { bashTool } from "./bash.js";
|
|
5
|
+
import { grepTool } from "./grep.js";
|
|
6
|
+
import { globTool } from "./glob.js";
|
|
7
|
+
import { webSearchTool } from "./webSearch.js";
|
|
8
|
+
import { webFetchTool } from "./webFetch.js";
|
|
9
|
+
import { setThinkingTool } from "./setThinking.js";
|
|
10
|
+
import { todoReadTool, todoWriteTool } from "./todo.js";
|
|
11
|
+
import { taskTool } from "./task.js";
|
|
12
|
+
const BASE_TOOLS = [
|
|
13
|
+
readTool,
|
|
14
|
+
writeTool,
|
|
15
|
+
editTool,
|
|
16
|
+
bashTool,
|
|
17
|
+
grepTool,
|
|
18
|
+
globTool,
|
|
19
|
+
webSearchTool,
|
|
20
|
+
webFetchTool,
|
|
21
|
+
setThinkingTool,
|
|
22
|
+
todoReadTool,
|
|
23
|
+
todoWriteTool,
|
|
24
|
+
taskTool,
|
|
25
|
+
];
|
|
26
|
+
export const ALL_TOOLS = [...BASE_TOOLS];
|
|
27
|
+
const TOOL_MAP = new Map(ALL_TOOLS.map((t) => [t.name, t]));
|
|
28
|
+
export function registerExternalTools(tools) {
|
|
29
|
+
for (const tool of tools) {
|
|
30
|
+
const existingIndex = ALL_TOOLS.findIndex((candidate) => candidate.name === tool.name);
|
|
31
|
+
if (existingIndex === -1)
|
|
32
|
+
ALL_TOOLS.push(tool);
|
|
33
|
+
else
|
|
34
|
+
ALL_TOOLS[existingIndex] = tool;
|
|
35
|
+
TOOL_MAP.set(tool.name, tool);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export function clearExternalTools(prefix = "mcp__") {
|
|
39
|
+
for (let index = ALL_TOOLS.length - 1; index >= 0; index--) {
|
|
40
|
+
if (ALL_TOOLS[index].name.startsWith(prefix)) {
|
|
41
|
+
TOOL_MAP.delete(ALL_TOOLS[index].name);
|
|
42
|
+
ALL_TOOLS.splice(index, 1);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export function getTool(name) {
|
|
47
|
+
return TOOL_MAP.get(name);
|
|
48
|
+
}
|
|
49
|
+
/** Convert our tool definitions into the OpenAI function-calling schema. */
|
|
50
|
+
export function toOpenAITools() {
|
|
51
|
+
return ALL_TOOLS.map((tool) => ({
|
|
52
|
+
type: "function",
|
|
53
|
+
function: {
|
|
54
|
+
name: tool.name,
|
|
55
|
+
description: tool.description,
|
|
56
|
+
parameters: tool.parameters,
|
|
57
|
+
},
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAIrC,MAAM,UAAU,GAAW;IACzB,QAAQ;IACR,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,aAAa;IACb,YAAY;IACZ,eAAe;IACf,YAAY;IACZ,aAAa;IACb,QAAQ;CACT,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAW,CAAC,GAAG,UAAU,CAAC,CAAC;AACjD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAE5D,MAAM,UAAU,qBAAqB,CAAC,KAAa;IACjD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,aAAa,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC;QACvF,IAAI,aAAa,KAAK,CAAC,CAAC;YAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;;YAC1C,SAAS,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;QACrC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAChC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAM,GAAG,OAAO;IACjD,KAAK,IAAI,KAAK,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QAC3D,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7C,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;YACvC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,aAAa;IAC3B,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC9B,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE;YACR,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B;KACF,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const MAX_LINES = 2000;
|
|
4
|
+
const MAX_LINE_LEN = 2000;
|
|
5
|
+
export const readTool = {
|
|
6
|
+
name: "read_file",
|
|
7
|
+
description: "Read a file from the local filesystem. Returns the contents with line numbers. " +
|
|
8
|
+
"Use this before editing a file. Long files are truncated.",
|
|
9
|
+
needsApproval: false,
|
|
10
|
+
parameters: {
|
|
11
|
+
type: "object",
|
|
12
|
+
properties: {
|
|
13
|
+
path: {
|
|
14
|
+
type: "string",
|
|
15
|
+
description: "Path to the file (absolute, or relative to the working directory).",
|
|
16
|
+
},
|
|
17
|
+
offset: {
|
|
18
|
+
type: "number",
|
|
19
|
+
description: "1-based line number to start reading from (optional).",
|
|
20
|
+
},
|
|
21
|
+
limit: {
|
|
22
|
+
type: "number",
|
|
23
|
+
description: `Maximum number of lines to read (optional, default ${MAX_LINES}).`,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
required: ["path"],
|
|
27
|
+
},
|
|
28
|
+
preview(args) {
|
|
29
|
+
return `read ${String(args.path)}`;
|
|
30
|
+
},
|
|
31
|
+
async run(args, ctx) {
|
|
32
|
+
const rel = String(args.path);
|
|
33
|
+
const abs = path.isAbsolute(rel) ? rel : path.join(ctx.cwd, rel);
|
|
34
|
+
if (!fs.existsSync(abs)) {
|
|
35
|
+
return { content: `Error: file not found: ${rel}`, isError: true };
|
|
36
|
+
}
|
|
37
|
+
const stat = fs.statSync(abs);
|
|
38
|
+
if (stat.isDirectory()) {
|
|
39
|
+
return { content: `Error: ${rel} is a directory, not a file.`, isError: true };
|
|
40
|
+
}
|
|
41
|
+
const raw = fs.readFileSync(abs, "utf8");
|
|
42
|
+
const allLines = raw.split("\n");
|
|
43
|
+
const offset = args.offset ? Math.max(1, Number(args.offset)) : 1;
|
|
44
|
+
const limit = args.limit ? Number(args.limit) : MAX_LINES;
|
|
45
|
+
const slice = allLines.slice(offset - 1, offset - 1 + limit);
|
|
46
|
+
const numbered = slice
|
|
47
|
+
.map((line, i) => {
|
|
48
|
+
const n = offset + i;
|
|
49
|
+
const truncated = line.length > MAX_LINE_LEN ? line.slice(0, MAX_LINE_LEN) + " …[truncated]" : line;
|
|
50
|
+
return `${String(n).padStart(6)}\t${truncated}`;
|
|
51
|
+
})
|
|
52
|
+
.join("\n");
|
|
53
|
+
const more = offset - 1 + limit < allLines.length
|
|
54
|
+
? `\n\n[file has ${allLines.length} lines total; showing ${offset}-${offset + slice.length - 1}]`
|
|
55
|
+
: "";
|
|
56
|
+
return {
|
|
57
|
+
content: numbered + more || "[empty file]",
|
|
58
|
+
summary: `Read ${rel} (${slice.length} lines)`,
|
|
59
|
+
};
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=read.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
function normalize(raw) {
|
|
2
|
+
const v = raw.trim().toLowerCase();
|
|
3
|
+
if (["off", "hide", "none", "disable", "false"].includes(v))
|
|
4
|
+
return "off";
|
|
5
|
+
if (["collapsed", "short", "fold"].includes(v))
|
|
6
|
+
return "collapsed";
|
|
7
|
+
if (["full", "on", "show", "all", "enable", "true"].includes(v))
|
|
8
|
+
return "full";
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
export const setThinkingTool = {
|
|
12
|
+
name: "set_thinking",
|
|
13
|
+
description: "Show or hide your own reasoning/thinking trace in the terminal. Call this ONLY when the user " +
|
|
14
|
+
"explicitly asks to turn the thinking/reasoning display on or off (e.g. \"关闭思考\", \"显示你的思考\", " +
|
|
15
|
+
"\"hide your thinking\", \"show reasoning\"). mode: off = hide, full = show everything, collapsed = show first lines.",
|
|
16
|
+
needsApproval: false,
|
|
17
|
+
parameters: {
|
|
18
|
+
type: "object",
|
|
19
|
+
properties: {
|
|
20
|
+
mode: {
|
|
21
|
+
type: "string",
|
|
22
|
+
description: "off (hide), full/on (show all), or collapsed (show first lines).",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
required: ["mode"],
|
|
26
|
+
},
|
|
27
|
+
preview(args) {
|
|
28
|
+
return `set thinking display: ${String(args.mode)}`;
|
|
29
|
+
},
|
|
30
|
+
async run(args, ctx) {
|
|
31
|
+
const mode = normalize(String(args.mode ?? ""));
|
|
32
|
+
if (!mode) {
|
|
33
|
+
return { content: `Invalid mode '${String(args.mode)}'. Use off, collapsed, or full.`, isError: true };
|
|
34
|
+
}
|
|
35
|
+
if (!ctx.setThinkingMode) {
|
|
36
|
+
return { content: "Thinking display cannot be changed in this context.", isError: true };
|
|
37
|
+
}
|
|
38
|
+
ctx.setThinkingMode(mode);
|
|
39
|
+
const label = mode === "off" ? "hidden" : mode === "collapsed" ? "collapsed (first lines)" : "full";
|
|
40
|
+
return {
|
|
41
|
+
content: `Thinking display is now ${label}. This takes effect on the next reply.`,
|
|
42
|
+
summary: `thinking display → ${mode}`,
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=setThinking.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setThinking.js","sourceRoot":"","sources":["../../src/tools/setThinking.ts"],"names":[],"mappings":"AAGA,SAAS,SAAS,CAAC,GAAW;IAC5B,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACnC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1E,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,WAAW,CAAC;IACnE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAC/E,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAS;IACnC,IAAI,EAAE,cAAc;IACpB,WAAW,EACT,+FAA+F;QAC/F,+FAA+F;QAC/F,sHAAsH;IACxH,aAAa,EAAE,KAAK;IACpB,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,kEAAkE;aAChF;SACF;QACD,QAAQ,EAAE,CAAC,MAAM,CAAC;KACnB;IACD,OAAO,CAAC,IAAI;QACV,OAAO,yBAAyB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IACtD,CAAC;IACD,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG;QACjB,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;QAChD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,EAAE,OAAO,EAAE,iBAAiB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,iCAAiC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACzG,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;YACzB,OAAO,EAAE,OAAO,EAAE,qDAAqD,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3F,CAAC;QACD,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,KAAK,GAAG,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,MAAM,CAAC;QACpG,OAAO;YACL,OAAO,EAAE,2BAA2B,KAAK,wCAAwC;YACjF,OAAO,EAAE,sBAAsB,IAAI,EAAE;SACtC,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export const taskTool = {
|
|
2
|
+
name: "task",
|
|
3
|
+
description: "Delegate a self-contained sub-task to an isolated sub-agent that has its own fresh context and the " +
|
|
4
|
+
"standard tools (read_file, search_text, list_files, edit_file, bash, etc.). Returns the sub-agent's " +
|
|
5
|
+
"final answer. Use it for focused research or multi-step work you want handled separately so it does " +
|
|
6
|
+
"not clutter the main conversation. Provide a complete, standalone prompt — the sub-agent cannot see " +
|
|
7
|
+
"this conversation.",
|
|
8
|
+
needsApproval: false,
|
|
9
|
+
parameters: {
|
|
10
|
+
type: "object",
|
|
11
|
+
properties: {
|
|
12
|
+
prompt: {
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "The complete, standalone task for the sub-agent (it has no other context).",
|
|
15
|
+
},
|
|
16
|
+
tools: {
|
|
17
|
+
type: "array",
|
|
18
|
+
items: { type: "string" },
|
|
19
|
+
description: "Optional allowlist of tool names the sub-agent may use (defaults to all except 'task').",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
required: ["prompt"],
|
|
23
|
+
},
|
|
24
|
+
preview(args) {
|
|
25
|
+
return `task: ${String(args.prompt ?? "").slice(0, 80)}`;
|
|
26
|
+
},
|
|
27
|
+
async run(args, ctx) {
|
|
28
|
+
if (!ctx.runSubagent) {
|
|
29
|
+
return { content: "Sub-agent execution is not available in this context.", isError: true };
|
|
30
|
+
}
|
|
31
|
+
const prompt = String(args.prompt ?? "").trim();
|
|
32
|
+
if (!prompt) {
|
|
33
|
+
return { content: "task requires a non-empty 'prompt'.", isError: true };
|
|
34
|
+
}
|
|
35
|
+
const tools = Array.isArray(args.tools) ? args.tools.map(String) : undefined;
|
|
36
|
+
const answer = await ctx.runSubagent(prompt, tools ? { tools } : undefined);
|
|
37
|
+
return { content: answer, summary: "task complete" };
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=task.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task.js","sourceRoot":"","sources":["../../src/tools/task.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,QAAQ,GAAS;IAC5B,IAAI,EAAE,MAAM;IACZ,WAAW,EACT,qGAAqG;QACrG,sGAAsG;QACtG,sGAAsG;QACtG,sGAAsG;QACtG,oBAAoB;IACtB,aAAa,EAAE,KAAK;IACpB,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,4EAA4E;aAC1F;YACD,KAAK,EAAE;gBACL,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACzB,WAAW,EAAE,yFAAyF;aACvG;SACF;QACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;KACrB;IACD,OAAO,CAAC,IAAI;QACV,OAAO,SAAS,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;IAC3D,CAAC;IACD,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG;QACjB,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YACrB,OAAO,EAAE,OAAO,EAAE,uDAAuD,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC7F,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAChD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,EAAE,OAAO,EAAE,qCAAqC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3E,CAAC;QACD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC7E,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;IACvD,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { formatTodoList, validateTodos } from "../todo.js";
|
|
2
|
+
export const todoReadTool = {
|
|
3
|
+
name: "todo_read",
|
|
4
|
+
description: "Read the current task list. Use this before updating todos when you are not sure what is already tracked.",
|
|
5
|
+
needsApproval: false,
|
|
6
|
+
parameters: {
|
|
7
|
+
type: "object",
|
|
8
|
+
properties: {},
|
|
9
|
+
additionalProperties: false,
|
|
10
|
+
},
|
|
11
|
+
async run(_args, ctx) {
|
|
12
|
+
const todos = ctx.todoStore?.list() ?? [];
|
|
13
|
+
const formatted = formatTodoList(todos);
|
|
14
|
+
return {
|
|
15
|
+
content: formatted,
|
|
16
|
+
summary: todos.length === 0 ? "todos: none" : `todos: ${todos.length} item${todos.length === 1 ? "" : "s"}`,
|
|
17
|
+
display: formatted,
|
|
18
|
+
};
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
export const todoWriteTool = {
|
|
22
|
+
name: "todo_write",
|
|
23
|
+
description: "Create or update the session task list for multi-step work. Use this for non-trivial coding tasks, keeping exactly one item in_progress at a time. " +
|
|
24
|
+
"Replace the whole list each time with concise pending/in_progress/completed items.",
|
|
25
|
+
needsApproval: false,
|
|
26
|
+
parameters: {
|
|
27
|
+
type: "object",
|
|
28
|
+
properties: {
|
|
29
|
+
todos: {
|
|
30
|
+
type: "array",
|
|
31
|
+
description: "The complete replacement todo list.",
|
|
32
|
+
items: {
|
|
33
|
+
type: "object",
|
|
34
|
+
properties: {
|
|
35
|
+
id: { type: "string", description: "Stable short id, e.g. inspect, implement, verify." },
|
|
36
|
+
content: { type: "string", description: "Concise task text." },
|
|
37
|
+
status: {
|
|
38
|
+
type: "string",
|
|
39
|
+
enum: ["pending", "in_progress", "completed"],
|
|
40
|
+
description: "Current task status. Only one item may be in_progress.",
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
required: ["content", "status"],
|
|
44
|
+
additionalProperties: false,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
required: ["todos"],
|
|
49
|
+
additionalProperties: false,
|
|
50
|
+
},
|
|
51
|
+
preview(args) {
|
|
52
|
+
const count = Array.isArray(args.todos) ? args.todos.length : 0;
|
|
53
|
+
return `update todo list (${count} item${count === 1 ? "" : "s"})`;
|
|
54
|
+
},
|
|
55
|
+
async run(args, ctx) {
|
|
56
|
+
if (!ctx.todoStore) {
|
|
57
|
+
return { content: "Error: todo store is unavailable.", isError: true };
|
|
58
|
+
}
|
|
59
|
+
const result = validateTodos(args.todos);
|
|
60
|
+
if (result.error) {
|
|
61
|
+
return { content: `Error: ${result.error}`, isError: true };
|
|
62
|
+
}
|
|
63
|
+
const todos = result.todos ?? [];
|
|
64
|
+
ctx.todoStore.replace(todos);
|
|
65
|
+
const formatted = formatTodoList(todos);
|
|
66
|
+
return {
|
|
67
|
+
content: `Todo list updated.\n${formatted}`,
|
|
68
|
+
summary: todos.length === 0 ? "todos cleared" : `todos updated (${todos.length})`,
|
|
69
|
+
display: formatted,
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=todo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"todo.js","sourceRoot":"","sources":["../../src/tools/todo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const MAX_CHARS = 20_000;
|
|
2
|
+
export function htmlToText(html) {
|
|
3
|
+
return html
|
|
4
|
+
.replace(/<script[\s\S]*?<\/script>/gi, " ")
|
|
5
|
+
.replace(/<style[\s\S]*?<\/style>/gi, " ")
|
|
6
|
+
.replace(/<noscript[\s\S]*?<\/noscript>/gi, " ")
|
|
7
|
+
.replace(/<!--[\s\S]*?-->/g, " ")
|
|
8
|
+
.replace(/<\/(p|div|h[1-6]|li|tr|br|section|article)>/gi, "\n")
|
|
9
|
+
.replace(/<br\s*\/?>/gi, "\n")
|
|
10
|
+
.replace(/<[^>]+>/g, " ")
|
|
11
|
+
.replace(/ /g, " ")
|
|
12
|
+
.replace(/&/g, "&")
|
|
13
|
+
.replace(/</g, "<")
|
|
14
|
+
.replace(/>/g, ">")
|
|
15
|
+
.replace(/"/g, '"')
|
|
16
|
+
.replace(/'/g, "'")
|
|
17
|
+
.replace(/[ \t]+/g, " ")
|
|
18
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
19
|
+
.trim();
|
|
20
|
+
}
|
|
21
|
+
export const webFetchTool = {
|
|
22
|
+
name: "web_fetch",
|
|
23
|
+
description: "Fetch a URL and return its text content (HTML is stripped to readable text). " +
|
|
24
|
+
"Use for reading documentation or pages the user links to.",
|
|
25
|
+
needsApproval: false,
|
|
26
|
+
parameters: {
|
|
27
|
+
type: "object",
|
|
28
|
+
properties: {
|
|
29
|
+
url: { type: "string", description: "The absolute URL to fetch (http/https)." },
|
|
30
|
+
},
|
|
31
|
+
required: ["url"],
|
|
32
|
+
},
|
|
33
|
+
preview(args) {
|
|
34
|
+
return `fetch ${String(args.url)}`;
|
|
35
|
+
},
|
|
36
|
+
async run(args) {
|
|
37
|
+
const url = String(args.url);
|
|
38
|
+
if (!/^https?:\/\//i.test(url)) {
|
|
39
|
+
return { content: "Error: url must start with http:// or https://", isError: true };
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
const controller = new AbortController();
|
|
43
|
+
const timer = setTimeout(() => controller.abort(), 30_000);
|
|
44
|
+
const res = await fetch(url, {
|
|
45
|
+
signal: controller.signal,
|
|
46
|
+
headers: { "User-Agent": "deepseek-cli/0.1 (+https://github.com)" },
|
|
47
|
+
});
|
|
48
|
+
clearTimeout(timer);
|
|
49
|
+
if (!res.ok) {
|
|
50
|
+
return { content: `Error: HTTP ${res.status} ${res.statusText} for ${url}`, isError: true };
|
|
51
|
+
}
|
|
52
|
+
const contentType = res.headers.get("content-type") || "";
|
|
53
|
+
const body = await res.text();
|
|
54
|
+
const text = contentType.includes("html") ? htmlToText(body) : body;
|
|
55
|
+
const clipped = text.length > MAX_CHARS ? text.slice(0, MAX_CHARS) + "\n…[content truncated]" : text;
|
|
56
|
+
return { content: clipped || "(empty response)", summary: `Fetched ${url}` };
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
60
|
+
return { content: `Error fetching ${url}: ${msg}`, isError: true };
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=webFetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webFetch.js","sourceRoot":"","sources":["../../src/tools/webFetch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
const TIMEOUT_MS = 20_000;
|
|
2
|
+
function decodeEntities(s) {
|
|
3
|
+
return s
|
|
4
|
+
.replace(/<[^>]+>/g, "")
|
|
5
|
+
.replace(/ /g, " ")
|
|
6
|
+
.replace(/&/g, "&")
|
|
7
|
+
.replace(/</g, "<")
|
|
8
|
+
.replace(/>/g, ">")
|
|
9
|
+
.replace(/"/g, '"')
|
|
10
|
+
.replace(/'|'/g, "'")
|
|
11
|
+
.trim();
|
|
12
|
+
}
|
|
13
|
+
async function fetchWithTimeout(url, init) {
|
|
14
|
+
const controller = new AbortController();
|
|
15
|
+
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
16
|
+
try {
|
|
17
|
+
return await fetch(url, { ...init, signal: controller.signal });
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
clearTimeout(timer);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** Decide which provider to use based on env configuration. */
|
|
24
|
+
function selectProvider() {
|
|
25
|
+
const explicit = (process.env.WEB_SEARCH_PROVIDER || "").trim().toLowerCase();
|
|
26
|
+
if (explicit === "bocha")
|
|
27
|
+
return "bocha";
|
|
28
|
+
if (explicit === "tavily")
|
|
29
|
+
return "tavily";
|
|
30
|
+
if (explicit === "duckduckgo" || explicit === "ddg")
|
|
31
|
+
return "duckduckgo";
|
|
32
|
+
if (process.env.BOCHA_API_KEY)
|
|
33
|
+
return "bocha";
|
|
34
|
+
if (process.env.TAVILY_API_KEY)
|
|
35
|
+
return "tavily";
|
|
36
|
+
return "duckduckgo";
|
|
37
|
+
}
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Bocha (博查) — https://open.bochaai.com | China-friendly, AI search API.
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
async function searchBocha(query, limit) {
|
|
42
|
+
const key = process.env.BOCHA_API_KEY;
|
|
43
|
+
if (!key)
|
|
44
|
+
throw new Error("BOCHA_API_KEY is not set");
|
|
45
|
+
const res = await fetchWithTimeout("https://api.bochaai.com/v1/web-search", {
|
|
46
|
+
method: "POST",
|
|
47
|
+
headers: {
|
|
48
|
+
Authorization: `Bearer ${key}`,
|
|
49
|
+
"Content-Type": "application/json",
|
|
50
|
+
},
|
|
51
|
+
body: JSON.stringify({ query, summary: true, count: limit, page: 1 }),
|
|
52
|
+
});
|
|
53
|
+
if (!res.ok) {
|
|
54
|
+
const body = await res.text().catch(() => "");
|
|
55
|
+
throw new Error(`Bocha HTTP ${res.status} ${res.statusText} ${body.slice(0, 200)}`.trim());
|
|
56
|
+
}
|
|
57
|
+
const data = (await res.json());
|
|
58
|
+
if (data.code !== undefined && data.code !== 200) {
|
|
59
|
+
throw new Error(`Bocha error ${data.code}: ${data.msg ?? "unknown"}`);
|
|
60
|
+
}
|
|
61
|
+
const value = data.data?.webPages?.value ?? [];
|
|
62
|
+
const hits = value.slice(0, limit).map((item) => ({
|
|
63
|
+
title: item.name ?? "(untitled)",
|
|
64
|
+
url: item.url ?? "",
|
|
65
|
+
snippet: (item.summary || item.snippet || "").trim(),
|
|
66
|
+
}));
|
|
67
|
+
return { hits };
|
|
68
|
+
}
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// Tavily — https://tavily.com | reliable international AI search API.
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
async function searchTavily(query, limit) {
|
|
73
|
+
const key = process.env.TAVILY_API_KEY;
|
|
74
|
+
if (!key)
|
|
75
|
+
throw new Error("TAVILY_API_KEY is not set");
|
|
76
|
+
const res = await fetchWithTimeout("https://api.tavily.com/search", {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: {
|
|
79
|
+
Authorization: `Bearer ${key}`,
|
|
80
|
+
"Content-Type": "application/json",
|
|
81
|
+
},
|
|
82
|
+
body: JSON.stringify({ query, max_results: limit, search_depth: "basic" }),
|
|
83
|
+
});
|
|
84
|
+
if (!res.ok) {
|
|
85
|
+
const body = await res.text().catch(() => "");
|
|
86
|
+
throw new Error(`Tavily HTTP ${res.status} ${res.statusText} ${body.slice(0, 200)}`.trim());
|
|
87
|
+
}
|
|
88
|
+
const data = (await res.json());
|
|
89
|
+
const hits = (data.results ?? []).slice(0, limit).map((item) => ({
|
|
90
|
+
title: item.title ?? "(untitled)",
|
|
91
|
+
url: item.url ?? "",
|
|
92
|
+
snippet: (item.content ?? "").trim(),
|
|
93
|
+
}));
|
|
94
|
+
return { hits, answer: data.answer?.trim() || undefined };
|
|
95
|
+
}
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// DuckDuckGo HTML — no key, but often blocked/unreliable (e.g. mainland China).
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
function unwrapDuckUrl(href) {
|
|
100
|
+
try {
|
|
101
|
+
const u = href.startsWith("//") ? "https:" + href : href;
|
|
102
|
+
const parsed = new URL(u, "https://duckduckgo.com");
|
|
103
|
+
const uddg = parsed.searchParams.get("uddg");
|
|
104
|
+
return uddg ? decodeURIComponent(uddg) : href;
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return href;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function parseDuckResults(html, limit) {
|
|
111
|
+
const hits = [];
|
|
112
|
+
const linkRe = /<a[^>]*class="result__a"[^>]*href="([^"]+)"[^>]*>([\s\S]*?)<\/a>/gi;
|
|
113
|
+
const snippetRe = /<a[^>]*class="result__snippet"[^>]*>([\s\S]*?)<\/a>/gi;
|
|
114
|
+
const snippets = [];
|
|
115
|
+
let sm;
|
|
116
|
+
while ((sm = snippetRe.exec(html)) !== null)
|
|
117
|
+
snippets.push(decodeEntities(sm[1]));
|
|
118
|
+
let m;
|
|
119
|
+
let i = 0;
|
|
120
|
+
while ((m = linkRe.exec(html)) !== null && hits.length < limit) {
|
|
121
|
+
hits.push({
|
|
122
|
+
url: unwrapDuckUrl(m[1]),
|
|
123
|
+
title: decodeEntities(m[2]),
|
|
124
|
+
snippet: snippets[i] ?? "",
|
|
125
|
+
});
|
|
126
|
+
i++;
|
|
127
|
+
}
|
|
128
|
+
return hits;
|
|
129
|
+
}
|
|
130
|
+
async function searchDuckDuckGo(query, limit) {
|
|
131
|
+
const url = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`;
|
|
132
|
+
const res = await fetchWithTimeout(url, {
|
|
133
|
+
headers: {
|
|
134
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120 Safari/537.36",
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
if (!res.ok)
|
|
138
|
+
throw new Error(`DuckDuckGo HTTP ${res.status}`);
|
|
139
|
+
const html = await res.text();
|
|
140
|
+
return { hits: parseDuckResults(html, limit) };
|
|
141
|
+
}
|
|
142
|
+
const PROVIDERS = {
|
|
143
|
+
bocha: searchBocha,
|
|
144
|
+
tavily: searchTavily,
|
|
145
|
+
duckduckgo: searchDuckDuckGo,
|
|
146
|
+
};
|
|
147
|
+
export const webSearchTool = {
|
|
148
|
+
name: "web_search",
|
|
149
|
+
description: "Search the web and return a list of result titles, URLs, and snippets. " +
|
|
150
|
+
"Uses the configured provider (Bocha or Tavily via API key; DuckDuckGo otherwise). " +
|
|
151
|
+
"Follow up with web_fetch to read a specific result.",
|
|
152
|
+
needsApproval: false,
|
|
153
|
+
parameters: {
|
|
154
|
+
type: "object",
|
|
155
|
+
properties: {
|
|
156
|
+
query: { type: "string", description: "The search query." },
|
|
157
|
+
limit: { type: "number", description: "Max results to return (optional, default 8)." },
|
|
158
|
+
},
|
|
159
|
+
required: ["query"],
|
|
160
|
+
},
|
|
161
|
+
preview(args) {
|
|
162
|
+
return `search "${String(args.query)}"`;
|
|
163
|
+
},
|
|
164
|
+
async run(args) {
|
|
165
|
+
const query = String(args.query);
|
|
166
|
+
const limit = Math.min(Number(args.limit) || 8, 15);
|
|
167
|
+
const provider = selectProvider();
|
|
168
|
+
try {
|
|
169
|
+
const { hits, answer } = await PROVIDERS[provider](query, limit);
|
|
170
|
+
if (hits.length === 0 && !answer) {
|
|
171
|
+
return {
|
|
172
|
+
content: `No results for "${query}" (provider: ${provider}).`,
|
|
173
|
+
summary: `search "${query}" via ${provider}: 0 results`,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
const sections = [];
|
|
177
|
+
if (answer)
|
|
178
|
+
sections.push(`Answer: ${answer}`);
|
|
179
|
+
sections.push(hits
|
|
180
|
+
.map((h, i) => `${i + 1}. ${h.title}\n ${h.url}\n ${h.snippet}`.trimEnd())
|
|
181
|
+
.join("\n\n"));
|
|
182
|
+
return {
|
|
183
|
+
content: sections.filter(Boolean).join("\n\n"),
|
|
184
|
+
summary: `search "${query}" via ${provider}: ${hits.length} results`,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
catch (err) {
|
|
188
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
189
|
+
const hint = provider === "duckduckgo"
|
|
190
|
+
? " DuckDuckGo may be blocked on this network — set BOCHA_API_KEY (recommended in China) or TAVILY_API_KEY to use a reliable provider."
|
|
191
|
+
: "";
|
|
192
|
+
return {
|
|
193
|
+
content: `Error searching via ${provider}: ${msg}.${hint}`,
|
|
194
|
+
summary: `search "${query}" via ${provider}: failed`,
|
|
195
|
+
isError: true,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
//# sourceMappingURL=webSearch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webSearch.js","sourceRoot":"","sources":["../../src/tools/webSearch.ts"],"names":[],"mappings":"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"}
|