deepseek-web-retrieval 0.5.0 → 0.6.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/CHANGELOG.md +15 -0
- package/README.md +95 -42
- package/dist/cli.js +397 -307
- package/docs/agents/codex.md +15 -8
- package/docs/agents/opencode-v2.md +12 -6
- package/docs/agents/pi.md +14 -6
- package/docs/design/installer-design.md +25 -20
- package/docs/integration.md +38 -7
- package/docs/research/control-matrix.md +2 -2
- package/docs/research/mcp-compatibility.md +5 -1
- package/package.json +1 -1
- package/src/installer/apply.ts +5 -3
- package/src/installer/cli.ts +43 -10
- package/src/installer/state.ts +1 -0
- package/src/installer/types.ts +2 -0
- package/src/mcp/cli.ts +8 -51
- package/src/mcp/serve.ts +51 -0
- package/src/version.ts +12 -0
package/dist/cli.js
CHANGED
|
@@ -15,12 +15,11 @@ var __export = (target, all) => {
|
|
|
15
15
|
};
|
|
16
16
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
17
17
|
|
|
18
|
-
// src/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
MAX_RESPONSE_BYTES = 5 * 1024 * 1024;
|
|
18
|
+
// src/version.ts
|
|
19
|
+
import { readFileSync } from "node:fs";
|
|
20
|
+
var TOOL_VERSION;
|
|
21
|
+
var init_version = __esm(() => {
|
|
22
|
+
TOOL_VERSION = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
24
23
|
});
|
|
25
24
|
|
|
26
25
|
// src/installer/persistence.ts
|
|
@@ -32,7 +31,7 @@ import {
|
|
|
32
31
|
lstatSync,
|
|
33
32
|
mkdirSync,
|
|
34
33
|
openSync,
|
|
35
|
-
readFileSync,
|
|
34
|
+
readFileSync as readFileSync2,
|
|
36
35
|
realpathSync,
|
|
37
36
|
renameSync,
|
|
38
37
|
rmSync,
|
|
@@ -66,7 +65,7 @@ function atomicWrite(file, text, mode) {
|
|
|
66
65
|
try {
|
|
67
66
|
fd = openSync(temporary, "wx", 384);
|
|
68
67
|
writeFileSync(fd, text);
|
|
69
|
-
if (
|
|
68
|
+
if (readFileSync2(temporary, "utf8") !== text)
|
|
70
69
|
throw new Error(`Incomplete write to ${file}`);
|
|
71
70
|
fchmodSync(fd, mode ?? existingMode ?? 438 & ~process.umask());
|
|
72
71
|
fsyncSync(fd);
|
|
@@ -806,10 +805,10 @@ function parse(text, errors = [], options = ParseOptions.DEFAULT) {
|
|
|
806
805
|
}
|
|
807
806
|
const visitor = {
|
|
808
807
|
onObjectBegin: () => {
|
|
809
|
-
const
|
|
810
|
-
onValue(
|
|
808
|
+
const object = {};
|
|
809
|
+
onValue(object);
|
|
811
810
|
previousParents.push(currentParent);
|
|
812
|
-
currentParent =
|
|
811
|
+
currentParent = object;
|
|
813
812
|
currentProperty = null;
|
|
814
813
|
},
|
|
815
814
|
onObjectProperty: (name) => {
|
|
@@ -1506,11 +1505,11 @@ function appendEntries(existing, entries, path) {
|
|
|
1506
1505
|
var init_value = () => {};
|
|
1507
1506
|
|
|
1508
1507
|
// src/installer/formats/json.ts
|
|
1509
|
-
import { existsSync, readFileSync as
|
|
1508
|
+
import { existsSync, readFileSync as readFileSync3 } from "node:fs";
|
|
1510
1509
|
function loadJson(file) {
|
|
1511
1510
|
if (!existsSync(file))
|
|
1512
1511
|
return { exists: false, text: "", value: {}, lossy: false };
|
|
1513
|
-
const text =
|
|
1512
|
+
const text = readFileSync3(file, "utf8");
|
|
1514
1513
|
try {
|
|
1515
1514
|
return { exists: true, text, value: parseJsonc(text), lossy: false };
|
|
1516
1515
|
} catch (error) {
|
|
@@ -1642,7 +1641,7 @@ var init_json = __esm(() => {
|
|
|
1642
1641
|
});
|
|
1643
1642
|
|
|
1644
1643
|
// src/installer/formats/rules.ts
|
|
1645
|
-
import { existsSync as existsSync2, readFileSync as
|
|
1644
|
+
import { existsSync as existsSync2, readFileSync as readFileSync4 } from "node:fs";
|
|
1646
1645
|
function rulesMarkers(host) {
|
|
1647
1646
|
return {
|
|
1648
1647
|
begin: `<!-- deepseek-web-retrieval:${host}:rules:begin -->`,
|
|
@@ -1697,7 +1696,7 @@ function rulesCodec(host) {
|
|
|
1697
1696
|
format: "rules",
|
|
1698
1697
|
load: (file) => {
|
|
1699
1698
|
const exists = existsSync2(file);
|
|
1700
|
-
const text = exists ?
|
|
1699
|
+
const text = exists ? readFileSync4(file, "utf8") : "";
|
|
1701
1700
|
try {
|
|
1702
1701
|
blockRange(host, text);
|
|
1703
1702
|
return { exists, text, value: {}, lossy: false };
|
|
@@ -1718,12 +1717,12 @@ function rulesCodec(host) {
|
|
|
1718
1717
|
var init_rules = () => {};
|
|
1719
1718
|
|
|
1720
1719
|
// node_modules/smol-toml/dist/error.js
|
|
1721
|
-
function getLineColFromPtr(
|
|
1722
|
-
let lines =
|
|
1720
|
+
function getLineColFromPtr(string, ptr) {
|
|
1721
|
+
let lines = string.slice(0, ptr).split(/\r?\n/);
|
|
1723
1722
|
return [lines.length, lines.pop().length + 1];
|
|
1724
1723
|
}
|
|
1725
|
-
function makeCodeBlock(
|
|
1726
|
-
let lines =
|
|
1724
|
+
function makeCodeBlock(string, line, column) {
|
|
1725
|
+
let lines = string.split(/\r?\n/);
|
|
1727
1726
|
let codeblock = "";
|
|
1728
1727
|
let numberLen = (Math.log10(line + 1) | 0) + 1;
|
|
1729
1728
|
for (let i = line - 1;i <= line + 1; i++) {
|
|
@@ -2905,11 +2904,11 @@ var init_dist = __esm(() => {
|
|
|
2905
2904
|
});
|
|
2906
2905
|
|
|
2907
2906
|
// src/installer/formats/toml.ts
|
|
2908
|
-
import { existsSync as existsSync3, readFileSync as
|
|
2907
|
+
import { existsSync as existsSync3, readFileSync as readFileSync5 } from "node:fs";
|
|
2909
2908
|
function loadToml(file) {
|
|
2910
2909
|
if (!existsSync3(file))
|
|
2911
2910
|
return { exists: false, text: "", value: {}, lossy: false };
|
|
2912
|
-
const text =
|
|
2911
|
+
const text = readFileSync5(file, "utf8");
|
|
2913
2912
|
try {
|
|
2914
2913
|
return { exists: true, text, value: parse3(text), lossy: hasTomlComment(text) };
|
|
2915
2914
|
} catch (error) {
|
|
@@ -3082,7 +3081,7 @@ var init_formats = __esm(() => {
|
|
|
3082
3081
|
});
|
|
3083
3082
|
|
|
3084
3083
|
// src/installer/revert.ts
|
|
3085
|
-
import { existsSync as existsSync4, readFileSync as
|
|
3084
|
+
import { existsSync as existsSync4, readFileSync as readFileSync6, rmdirSync, unlinkSync } from "node:fs";
|
|
3086
3085
|
import { dirname as dirname2 } from "node:path";
|
|
3087
3086
|
function pruneEmptyDir(dir) {
|
|
3088
3087
|
try {
|
|
@@ -3096,7 +3095,7 @@ function revertRecordedFile(file, host, opts) {
|
|
|
3096
3095
|
return lines;
|
|
3097
3096
|
}
|
|
3098
3097
|
const codec = codecFor(file.format, host);
|
|
3099
|
-
const text =
|
|
3098
|
+
const text = readFileSync6(file.file, "utf8");
|
|
3100
3099
|
if (file.format === "rules") {
|
|
3101
3100
|
const edit2 = { file: file.file, format: "rules", block: file.blockApplied ?? "" };
|
|
3102
3101
|
if (!codec.verify(text, edit2)) {
|
|
@@ -3145,16 +3144,16 @@ function stateDir(roots, scope) {
|
|
|
3145
3144
|
var init_paths = () => {};
|
|
3146
3145
|
|
|
3147
3146
|
// src/installer/state.ts
|
|
3148
|
-
import { existsSync as existsSync5, lstatSync as lstatSync2, readdirSync, readFileSync as
|
|
3147
|
+
import { existsSync as existsSync5, lstatSync as lstatSync2, readdirSync, readFileSync as readFileSync7, rmSync as rmSync2 } from "node:fs";
|
|
3149
3148
|
import { isAbsolute, join as join3 } from "node:path";
|
|
3150
|
-
import { z
|
|
3149
|
+
import { z } from "zod/v4";
|
|
3151
3150
|
function statePathFor(input) {
|
|
3152
3151
|
return join3(stateDir(input, input.scope), `install.${input.host}.json`);
|
|
3153
3152
|
}
|
|
3154
3153
|
function readRecordFile(file, host, scope) {
|
|
3155
3154
|
let text;
|
|
3156
3155
|
try {
|
|
3157
|
-
text =
|
|
3156
|
+
text = readFileSync7(file, "utf8");
|
|
3158
3157
|
} catch (error) {
|
|
3159
3158
|
if (error.code === "ENOENT") {
|
|
3160
3159
|
try {
|
|
@@ -3241,31 +3240,32 @@ var keyPath, tier, operation, recordSchema, InstallRecordError;
|
|
|
3241
3240
|
var init_state = __esm(() => {
|
|
3242
3241
|
init_paths();
|
|
3243
3242
|
init_persistence();
|
|
3244
|
-
keyPath =
|
|
3245
|
-
tier =
|
|
3246
|
-
operation =
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
op:
|
|
3243
|
+
keyPath = z.array(z.string().min(1)).min(1);
|
|
3244
|
+
tier = z.enum(["optional", "preferred", "forced", "off"]);
|
|
3245
|
+
operation = z.discriminatedUnion("op", [
|
|
3246
|
+
z.object({ op: z.literal("set"), path: keyPath, applied: z.unknown(), previous: z.unknown().optional() }),
|
|
3247
|
+
z.object({
|
|
3248
|
+
op: z.literal("append-array"),
|
|
3250
3249
|
path: keyPath,
|
|
3251
|
-
applied:
|
|
3252
|
-
previous:
|
|
3250
|
+
applied: z.array(z.unknown()),
|
|
3251
|
+
previous: z.unknown().optional()
|
|
3253
3252
|
})
|
|
3254
3253
|
]);
|
|
3255
|
-
recordSchema =
|
|
3256
|
-
version:
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3254
|
+
recordSchema = z.object({
|
|
3255
|
+
version: z.literal(1),
|
|
3256
|
+
installerVersion: z.string().optional(),
|
|
3257
|
+
host: z.enum(["opencode", "pi", "codex"]),
|
|
3258
|
+
scope: z.enum(["global", "project"]),
|
|
3259
|
+
tiers: z.object({ search: tier, fetch: tier }),
|
|
3260
|
+
createdAt: z.string().refine((value) => Number.isFinite(Date.parse(value))),
|
|
3261
|
+
files: z.array(z.object({
|
|
3262
|
+
file: z.string().refine(isAbsolute),
|
|
3263
|
+
format: z.enum(["json", "toml", "rules"]),
|
|
3264
|
+
created: z.boolean(),
|
|
3265
|
+
shared: z.literal(true).optional(),
|
|
3266
|
+
ops: z.array(operation),
|
|
3267
|
+
blockApplied: z.string().optional(),
|
|
3268
|
+
createdParents: z.array(keyPath).optional()
|
|
3269
3269
|
}))
|
|
3270
3270
|
});
|
|
3271
3271
|
InstallRecordError = class InstallRecordError extends Error {
|
|
@@ -3281,7 +3281,7 @@ var init_state = __esm(() => {
|
|
|
3281
3281
|
});
|
|
3282
3282
|
|
|
3283
3283
|
// src/installer/ownership.ts
|
|
3284
|
-
import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as
|
|
3284
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync8, realpathSync as realpathSync2, rmSync as rmSync3, writeFileSync as writeFileSync2 } from "node:fs";
|
|
3285
3285
|
import { basename as basename2, dirname as dirname3, join as join4, resolve } from "node:path";
|
|
3286
3286
|
function canonicalPath(file) {
|
|
3287
3287
|
const absolute = resolve(file);
|
|
@@ -3304,7 +3304,7 @@ function readOwner(file) {
|
|
|
3304
3304
|
if (!existsSync6(file))
|
|
3305
3305
|
return;
|
|
3306
3306
|
try {
|
|
3307
|
-
const value = JSON.parse(
|
|
3307
|
+
const value = JSON.parse(readFileSync8(file, "utf8"));
|
|
3308
3308
|
if (isPlainObject(value) && typeof value.recordPath === "string" && typeof value.cwd === "string" && (value.scope === "project" || value.scope === "global")) {
|
|
3309
3309
|
return { recordPath: value.recordPath, cwd: value.cwd, scope: value.scope };
|
|
3310
3310
|
}
|
|
@@ -3418,7 +3418,7 @@ var init_operation_lock = __esm(() => {
|
|
|
3418
3418
|
});
|
|
3419
3419
|
|
|
3420
3420
|
// src/installer/apply.ts
|
|
3421
|
-
import { existsSync as existsSync7, readFileSync as
|
|
3421
|
+
import { existsSync as existsSync7, readFileSync as readFileSync9, rmSync as rmSync5 } from "node:fs";
|
|
3422
3422
|
import { dirname as dirname5 } from "node:path";
|
|
3423
3423
|
function applyPlan(plan, input) {
|
|
3424
3424
|
if (plan.errors.length > 0) {
|
|
@@ -3456,6 +3456,7 @@ function applyLocked(plan, input) {
|
|
|
3456
3456
|
lines.push(...verification.lines);
|
|
3457
3457
|
const record = {
|
|
3458
3458
|
version: 1,
|
|
3459
|
+
installerVersion: TOOL_VERSION,
|
|
3459
3460
|
host: plan.host,
|
|
3460
3461
|
scope: plan.scope,
|
|
3461
3462
|
tiers: plan.tiers,
|
|
@@ -3483,7 +3484,7 @@ function applyLocked(plan, input) {
|
|
|
3483
3484
|
} catch (error) {
|
|
3484
3485
|
throw new ApplyError("recovery_required", `apply was written and verified, but old config ownership could not be released (${errorMessage(error)}). ` + "The new install record is retained; repair the reported ownership metadata before re-running init.", error);
|
|
3485
3486
|
}
|
|
3486
|
-
return { lines
|
|
3487
|
+
return { lines };
|
|
3487
3488
|
}
|
|
3488
3489
|
function errorMessage(error) {
|
|
3489
3490
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -3515,7 +3516,7 @@ function snapshotTouchedFiles(plan) {
|
|
|
3515
3516
|
const snapshots = new Map;
|
|
3516
3517
|
const touched = [...plan.edits.map((edit2) => edit2.file), ...(plan.reverts ?? []).map((revert) => revert.file)];
|
|
3517
3518
|
for (const file of new Set(touched)) {
|
|
3518
|
-
snapshots.set(file, existsSync7(file) ? { exists: true, text:
|
|
3519
|
+
snapshots.set(file, existsSync7(file) ? { exists: true, text: readFileSync9(file, "utf8") } : { exists: false, text: "" });
|
|
3519
3520
|
}
|
|
3520
3521
|
return snapshots;
|
|
3521
3522
|
}
|
|
@@ -3525,10 +3526,10 @@ function rollbackApply(input, previous, snapshots) {
|
|
|
3525
3526
|
for (const [file, snapshot] of [...snapshots.entries()].reverse()) {
|
|
3526
3527
|
try {
|
|
3527
3528
|
if (snapshot.exists) {
|
|
3528
|
-
if (existsSync7(file) &&
|
|
3529
|
+
if (existsSync7(file) && readFileSync9(file, "utf8") === snapshot.text)
|
|
3529
3530
|
continue;
|
|
3530
3531
|
writeConfig(file, snapshot.text);
|
|
3531
|
-
if (
|
|
3532
|
+
if (readFileSync9(file, "utf8") !== snapshot.text)
|
|
3532
3533
|
throw new Error("restored contents differ from the snapshot");
|
|
3533
3534
|
} else {
|
|
3534
3535
|
if (!existsSync7(file))
|
|
@@ -3621,7 +3622,7 @@ function verifyEdits(edits, host) {
|
|
|
3621
3622
|
continue;
|
|
3622
3623
|
}
|
|
3623
3624
|
const codec = codecFor(edit2.format, host);
|
|
3624
|
-
const text =
|
|
3625
|
+
const text = readFileSync9(edit2.file, "utf8");
|
|
3625
3626
|
if (edit2.format === "rules") {
|
|
3626
3627
|
const good = codec.verify(text, edit2);
|
|
3627
3628
|
lines.push(`${good ? "pass" : "FAIL"} ${edit2.file}: rules block ${good ? "present" : "missing"}`);
|
|
@@ -3643,6 +3644,7 @@ function describeOp(op) {
|
|
|
3643
3644
|
}
|
|
3644
3645
|
var ApplyError;
|
|
3645
3646
|
var init_apply = __esm(() => {
|
|
3647
|
+
init_version();
|
|
3646
3648
|
init_formats();
|
|
3647
3649
|
init_value();
|
|
3648
3650
|
init_operation_lock();
|
|
@@ -3659,8 +3661,16 @@ var init_apply = __esm(() => {
|
|
|
3659
3661
|
};
|
|
3660
3662
|
});
|
|
3661
3663
|
|
|
3664
|
+
// src/core/constants.ts
|
|
3665
|
+
var SEARCH_ENDPOINT = "https://api.deepseek.com/v1/tools/search", FETCH_ENDPOINT = "https://api.deepseek.com/v1/tools/fetch", DEFAULT_SEARCH_COUNT = 10, DEFAULT_MAX_RESULTS = 10, DEFAULT_MIN_RERANK = 0, DEFAULT_MIN_AUTHORITY = 0, DEFAULT_MAX_SUMMARY_CHARS = 1200, DEFAULT_FETCH_MAX_CHARS = 16000, DEFAULT_TIMEOUT_MS = 30000, MIN_TIMEOUT_MS = 1000, MAX_TIMEOUT_MS = 120000, MAX_QUERY_CHARS = 128, MAX_URL_CHARS = 8192, MAX_ERROR_BODY_CHARS = 2000, MAX_RESPONSE_BYTES, FETCH_TRUNCATION_MARKER = `
|
|
3666
|
+
|
|
3667
|
+
[content truncated]`, DEFAULT_API_KEY_SOURCE = "auto", DEFAULT_MAX_RETRIES = 0, MAX_RETRIES = 5, DEFAULT_RETRY_BASE_DELAY_MS = 250, MAX_RETRY_DELAY_MS = 1e4, API_KEY_ENV = "DEEPSEEK_API_KEY", ENABLE_SEARCH_ENV = "DEEPSEEK_ENABLE_SEARCH", ENABLE_FETCH_ENV = "DEEPSEEK_ENABLE_FETCH";
|
|
3668
|
+
var init_constants = __esm(() => {
|
|
3669
|
+
MAX_RESPONSE_BYTES = 5 * 1024 * 1024;
|
|
3670
|
+
});
|
|
3671
|
+
|
|
3662
3672
|
// src/installer/detect.ts
|
|
3663
|
-
import { existsSync as existsSync8, readFileSync as
|
|
3673
|
+
import { existsSync as existsSync8, readFileSync as readFileSync10 } from "node:fs";
|
|
3664
3674
|
function replacingExistingEntryNote(path) {
|
|
3665
3675
|
return `An existing ${path} entry is being replaced; its previous form is recorded for uninstall.`;
|
|
3666
3676
|
}
|
|
@@ -3685,7 +3695,7 @@ function findCompetitorSteering(host, file) {
|
|
|
3685
3695
|
return [];
|
|
3686
3696
|
let text;
|
|
3687
3697
|
try {
|
|
3688
|
-
text =
|
|
3698
|
+
text = readFileSync10(file, "utf8");
|
|
3689
3699
|
} catch {
|
|
3690
3700
|
return [];
|
|
3691
3701
|
}
|
|
@@ -4452,7 +4462,8 @@ var init_uninstall = __esm(() => {
|
|
|
4452
4462
|
// src/installer/cli.ts
|
|
4453
4463
|
var exports_cli = {};
|
|
4454
4464
|
__export(exports_cli, {
|
|
4455
|
-
runInstallerCli: () => runInstallerCli
|
|
4465
|
+
runInstallerCli: () => runInstallerCli,
|
|
4466
|
+
exitCodeForError: () => exitCodeForError
|
|
4456
4467
|
});
|
|
4457
4468
|
import { homedir } from "node:os";
|
|
4458
4469
|
import { resolve as resolve2 } from "node:path";
|
|
@@ -4473,6 +4484,10 @@ function parseFlags(args) {
|
|
|
4473
4484
|
problems.push(`--${name} does not accept a value; use --${name} to enable it or omit it`);
|
|
4474
4485
|
continue;
|
|
4475
4486
|
}
|
|
4487
|
+
if (booleans.has(name)) {
|
|
4488
|
+
problems.push(`--${name} was given more than once`);
|
|
4489
|
+
continue;
|
|
4490
|
+
}
|
|
4476
4491
|
booleans.add(name);
|
|
4477
4492
|
continue;
|
|
4478
4493
|
}
|
|
@@ -4480,6 +4495,10 @@ function parseFlags(args) {
|
|
|
4480
4495
|
problems.push(`unknown flag --${name}`);
|
|
4481
4496
|
continue;
|
|
4482
4497
|
}
|
|
4498
|
+
if (values.has(name)) {
|
|
4499
|
+
problems.push(`--${name} was given more than once`);
|
|
4500
|
+
continue;
|
|
4501
|
+
}
|
|
4483
4502
|
if (eq !== -1) {
|
|
4484
4503
|
values.set(name, arg.slice(eq + 1));
|
|
4485
4504
|
continue;
|
|
@@ -4498,9 +4517,17 @@ async function runInstallerCli(argv, io = {}) {
|
|
|
4498
4517
|
const out = io.out ?? ((line) => console.log(line));
|
|
4499
4518
|
const err = io.err ?? ((line) => console.error(line));
|
|
4500
4519
|
const [command, ...rest] = argv;
|
|
4501
|
-
if (command ===
|
|
4520
|
+
if (command === "version" || command === "--version") {
|
|
4521
|
+
out(TOOL_VERSION);
|
|
4522
|
+
return 0;
|
|
4523
|
+
}
|
|
4524
|
+
if (command === undefined) {
|
|
4525
|
+
err(USAGE);
|
|
4526
|
+
return EXIT_USAGE;
|
|
4527
|
+
}
|
|
4528
|
+
if (command === "help" || command === "--help") {
|
|
4502
4529
|
out(USAGE);
|
|
4503
|
-
return
|
|
4530
|
+
return 0;
|
|
4504
4531
|
}
|
|
4505
4532
|
const flags = parseFlags(rest);
|
|
4506
4533
|
if (flags.problems.length > 0) {
|
|
@@ -4508,7 +4535,7 @@ async function runInstallerCli(argv, io = {}) {
|
|
|
4508
4535
|
err(`error: ${problem}`);
|
|
4509
4536
|
err(`
|
|
4510
4537
|
${USAGE}`);
|
|
4511
|
-
return
|
|
4538
|
+
return EXIT_USAGE;
|
|
4512
4539
|
}
|
|
4513
4540
|
const cwd = resolve2(flags.values.get("cwd") ?? process.cwd());
|
|
4514
4541
|
const home = process.env.HOME ?? homedir();
|
|
@@ -4526,7 +4553,8 @@ ${USAGE}`);
|
|
|
4526
4553
|
return 0;
|
|
4527
4554
|
}
|
|
4528
4555
|
for (const record of records) {
|
|
4529
|
-
|
|
4556
|
+
const by = record.installerVersion ? ` by v${record.installerVersion}` : "";
|
|
4557
|
+
out(`${record.host} (${record.scope}) — search=${record.tiers.search}, fetch=${record.tiers.fetch}, installed ${record.createdAt}${by}`);
|
|
4530
4558
|
for (const file of record.files)
|
|
4531
4559
|
out(` ${file.created ? "created" : "modified"} ${file.file}`);
|
|
4532
4560
|
}
|
|
@@ -4549,7 +4577,7 @@ ${USAGE}`);
|
|
|
4549
4577
|
err(`Unknown command "${command}".
|
|
4550
4578
|
|
|
4551
4579
|
${USAGE}`);
|
|
4552
|
-
return
|
|
4580
|
+
return EXIT_USAGE;
|
|
4553
4581
|
}
|
|
4554
4582
|
const required = requireInput(flags, cwd, home, configHome2, true);
|
|
4555
4583
|
if (!required.ok)
|
|
@@ -4574,18 +4602,21 @@ Plan only — re-run with --apply to write these changes.`);
|
|
|
4574
4602
|
const result = applyPlan(plan, input);
|
|
4575
4603
|
for (const line of result.lines)
|
|
4576
4604
|
out(line);
|
|
4577
|
-
return
|
|
4605
|
+
return 0;
|
|
4578
4606
|
} catch (error) {
|
|
4579
4607
|
err(error instanceof Error ? error.message : String(error));
|
|
4580
|
-
return
|
|
4608
|
+
return exitCodeForError(error);
|
|
4581
4609
|
}
|
|
4582
4610
|
}
|
|
4611
|
+
function exitCodeForError(error) {
|
|
4612
|
+
return error instanceof ApplyError && error.status === "recovery_required" ? EXIT_RECOVERY : EXIT_FAILURE;
|
|
4613
|
+
}
|
|
4583
4614
|
function usageError(problems, err) {
|
|
4584
4615
|
for (const problem of problems)
|
|
4585
4616
|
err(`error: ${problem}`);
|
|
4586
4617
|
err(`
|
|
4587
4618
|
${USAGE}`);
|
|
4588
|
-
return
|
|
4619
|
+
return EXIT_USAGE;
|
|
4589
4620
|
}
|
|
4590
4621
|
function resolveConfigHome(home) {
|
|
4591
4622
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
@@ -4642,8 +4673,9 @@ function requireInput(flags, cwd, home, configHome2, needsTiers) {
|
|
|
4642
4673
|
}
|
|
4643
4674
|
};
|
|
4644
4675
|
}
|
|
4645
|
-
var HOSTS, HOST_CHOICES, SCOPES, TIERS, USAGE, VALUE_FLAGS, BOOLEAN_FLAGS, PATH_CHOICES;
|
|
4676
|
+
var HOSTS, HOST_CHOICES, SCOPES, TIERS, EXIT_FAILURE = 1, EXIT_USAGE = 2, EXIT_RECOVERY = 3, USAGE, VALUE_FLAGS, BOOLEAN_FLAGS, PATH_CHOICES;
|
|
4646
4677
|
var init_cli = __esm(() => {
|
|
4678
|
+
init_version();
|
|
4647
4679
|
init_apply();
|
|
4648
4680
|
init_hosts();
|
|
4649
4681
|
init_state();
|
|
@@ -4656,6 +4688,7 @@ var init_cli = __esm(() => {
|
|
|
4656
4688
|
deepseek-web-retrieval init --host ${HOST_CHOICES} --scope <project|global> --search <optional|preferred|forced|off> --fetch <optional|preferred|forced|off> [--path <extension|mcp>] [--package <npm ref>] [--cwd <dir>] [--apply]
|
|
4657
4689
|
deepseek-web-retrieval uninstall --host ${HOST_CHOICES} --scope <project|global> [--cwd <dir>]
|
|
4658
4690
|
deepseek-web-retrieval list [--cwd <dir>]
|
|
4691
|
+
deepseek-web-retrieval version
|
|
4659
4692
|
|
|
4660
4693
|
init prints the full plan (every file, old value → new value) and writes nothing
|
|
4661
4694
|
until --apply is passed. uninstall restores what the plan applied. --path picks
|
|
@@ -4663,27 +4696,25 @@ the integration mechanism for hosts with more than one (Pi: extension by
|
|
|
4663
4696
|
default, mcp for the stdio MCP server). --package overrides the package ref
|
|
4664
4697
|
written into host config; the Pi extension path turns it into the packages
|
|
4665
4698
|
source (a bare name is prefixed with npm:, a ref that already starts with npm:
|
|
4666
|
-
is written as-is)
|
|
4699
|
+
is written as-is).
|
|
4700
|
+
|
|
4701
|
+
Exit codes: 0 success; 1 refused or failed with nothing written (a failed apply
|
|
4702
|
+
is fully rolled back); 2 invalid command line; 3 recovery required — a failed
|
|
4703
|
+
apply could not roll back completely, follow the reported guidance before
|
|
4704
|
+
re-running.`;
|
|
4667
4705
|
VALUE_FLAGS = new Set(["host", "scope", "search", "fetch", "path", "package", "cwd"]);
|
|
4668
4706
|
BOOLEAN_FLAGS = new Set(["apply"]);
|
|
4669
4707
|
PATH_CHOICES = ["extension", "mcp"];
|
|
4670
4708
|
});
|
|
4671
4709
|
|
|
4672
|
-
// src/mcp/cli.ts
|
|
4673
|
-
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
4674
|
-
|
|
4675
4710
|
// src/core/auth.ts
|
|
4676
|
-
init_constants();
|
|
4677
4711
|
function apiKeyFromEnv(env = process.env) {
|
|
4678
4712
|
const key = env[API_KEY_ENV]?.trim();
|
|
4679
4713
|
return key ? key : undefined;
|
|
4680
4714
|
}
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
// src/core/options.ts
|
|
4686
|
-
init_constants();
|
|
4715
|
+
var init_auth = __esm(() => {
|
|
4716
|
+
init_constants();
|
|
4717
|
+
});
|
|
4687
4718
|
|
|
4688
4719
|
// src/core/domains.ts
|
|
4689
4720
|
import { isIP } from "node:net";
|
|
@@ -4791,6 +4822,7 @@ function ipv4FromIpv6Hextets(value, pattern) {
|
|
|
4791
4822
|
return;
|
|
4792
4823
|
return `${high >> 8}.${high & 255}.${low >> 8}.${low & 255}`;
|
|
4793
4824
|
}
|
|
4825
|
+
var init_domains = () => {};
|
|
4794
4826
|
|
|
4795
4827
|
// src/core/options.ts
|
|
4796
4828
|
function resolvePluginOptions(input) {
|
|
@@ -4851,35 +4883,12 @@ function clampInt(value, fallback, min, max) {
|
|
|
4851
4883
|
const number = typeof value === "number" && Number.isFinite(value) ? Math.trunc(value) : fallback;
|
|
4852
4884
|
return Math.min(max, Math.max(min, number));
|
|
4853
4885
|
}
|
|
4886
|
+
var init_options = __esm(() => {
|
|
4887
|
+
init_constants();
|
|
4888
|
+
init_domains();
|
|
4889
|
+
});
|
|
4854
4890
|
|
|
4855
4891
|
// src/core/env.ts
|
|
4856
|
-
var NUMBER_ENV = {
|
|
4857
|
-
count: "DEEPSEEK_SEARCH_COUNT",
|
|
4858
|
-
maxResults: "DEEPSEEK_SEARCH_MAX_RESULTS",
|
|
4859
|
-
minRerank: "DEEPSEEK_SEARCH_MIN_RERANK",
|
|
4860
|
-
minAuthority: "DEEPSEEK_SEARCH_MIN_AUTHORITY",
|
|
4861
|
-
maxSummaryChars: "DEEPSEEK_SEARCH_MAX_SUMMARY_CHARS",
|
|
4862
|
-
searchTimeoutMs: "DEEPSEEK_SEARCH_TIMEOUT_MS",
|
|
4863
|
-
fetchMaxChars: "DEEPSEEK_FETCH_MAX_CHARS",
|
|
4864
|
-
fetchTimeoutMs: "DEEPSEEK_FETCH_TIMEOUT_MS",
|
|
4865
|
-
maxRetries: "DEEPSEEK_MAX_RETRIES",
|
|
4866
|
-
retryBaseDelayMs: "DEEPSEEK_RETRY_BASE_DELAY_MS"
|
|
4867
|
-
};
|
|
4868
|
-
var TEXT_ENV = {
|
|
4869
|
-
language: "DEEPSEEK_SEARCH_LANGUAGE"
|
|
4870
|
-
};
|
|
4871
|
-
var DOMAINS_ENV = {
|
|
4872
|
-
blockedDomains: "DEEPSEEK_SEARCH_BLOCKED_DOMAINS",
|
|
4873
|
-
includeDomains: "DEEPSEEK_SEARCH_INCLUDE_DOMAINS",
|
|
4874
|
-
fetchAllowedDomains: "DEEPSEEK_FETCH_ALLOWED_DOMAINS",
|
|
4875
|
-
fetchBlockedDomains: "DEEPSEEK_FETCH_BLOCKED_DOMAINS"
|
|
4876
|
-
};
|
|
4877
|
-
var FALSE_ONLY_ENV = {
|
|
4878
|
-
allowUnknownAuthority: "DEEPSEEK_SEARCH_ALLOW_UNKNOWN_AUTHORITY",
|
|
4879
|
-
fetchBlockPrivateHosts: "DEEPSEEK_FETCH_BLOCK_PRIVATE_HOSTS",
|
|
4880
|
-
searchEnabled: ENABLE_SEARCH_ENV,
|
|
4881
|
-
fetchEnabled: ENABLE_FETCH_ENV
|
|
4882
|
-
};
|
|
4883
4892
|
function resolveEnvOptions(env = process.env) {
|
|
4884
4893
|
return resolvePluginOptions(pluginOptionsFromEnv(env));
|
|
4885
4894
|
}
|
|
@@ -4941,20 +4950,55 @@ function isFalseValue(value) {
|
|
|
4941
4950
|
const trimmed = value?.trim().toLowerCase();
|
|
4942
4951
|
return trimmed === "false" || trimmed === "0" || trimmed === "no" || trimmed === "off";
|
|
4943
4952
|
}
|
|
4953
|
+
var NUMBER_ENV, TEXT_ENV, DOMAINS_ENV, FALSE_ONLY_ENV;
|
|
4954
|
+
var init_env = __esm(() => {
|
|
4955
|
+
init_constants();
|
|
4956
|
+
init_options();
|
|
4957
|
+
NUMBER_ENV = {
|
|
4958
|
+
count: "DEEPSEEK_SEARCH_COUNT",
|
|
4959
|
+
maxResults: "DEEPSEEK_SEARCH_MAX_RESULTS",
|
|
4960
|
+
minRerank: "DEEPSEEK_SEARCH_MIN_RERANK",
|
|
4961
|
+
minAuthority: "DEEPSEEK_SEARCH_MIN_AUTHORITY",
|
|
4962
|
+
maxSummaryChars: "DEEPSEEK_SEARCH_MAX_SUMMARY_CHARS",
|
|
4963
|
+
searchTimeoutMs: "DEEPSEEK_SEARCH_TIMEOUT_MS",
|
|
4964
|
+
fetchMaxChars: "DEEPSEEK_FETCH_MAX_CHARS",
|
|
4965
|
+
fetchTimeoutMs: "DEEPSEEK_FETCH_TIMEOUT_MS",
|
|
4966
|
+
maxRetries: "DEEPSEEK_MAX_RETRIES",
|
|
4967
|
+
retryBaseDelayMs: "DEEPSEEK_RETRY_BASE_DELAY_MS"
|
|
4968
|
+
};
|
|
4969
|
+
TEXT_ENV = {
|
|
4970
|
+
language: "DEEPSEEK_SEARCH_LANGUAGE"
|
|
4971
|
+
};
|
|
4972
|
+
DOMAINS_ENV = {
|
|
4973
|
+
blockedDomains: "DEEPSEEK_SEARCH_BLOCKED_DOMAINS",
|
|
4974
|
+
includeDomains: "DEEPSEEK_SEARCH_INCLUDE_DOMAINS",
|
|
4975
|
+
fetchAllowedDomains: "DEEPSEEK_FETCH_ALLOWED_DOMAINS",
|
|
4976
|
+
fetchBlockedDomains: "DEEPSEEK_FETCH_BLOCKED_DOMAINS"
|
|
4977
|
+
};
|
|
4978
|
+
FALSE_ONLY_ENV = {
|
|
4979
|
+
allowUnknownAuthority: "DEEPSEEK_SEARCH_ALLOW_UNKNOWN_AUTHORITY",
|
|
4980
|
+
fetchBlockPrivateHosts: "DEEPSEEK_FETCH_BLOCK_PRIVATE_HOSTS",
|
|
4981
|
+
searchEnabled: ENABLE_SEARCH_ENV,
|
|
4982
|
+
fetchEnabled: ENABLE_FETCH_ENV
|
|
4983
|
+
};
|
|
4984
|
+
});
|
|
4944
4985
|
|
|
4945
4986
|
// src/mcp/auth.ts
|
|
4946
|
-
init_constants();
|
|
4947
|
-
var MISSING_API_KEY_MESSAGE = `DeepSeek API key not found. Set ${API_KEY_ENV} in the MCP server's env configuration.`;
|
|
4948
4987
|
function requireApiKey(env) {
|
|
4949
4988
|
const apiKey = apiKeyFromEnv(env);
|
|
4950
4989
|
if (!apiKey)
|
|
4951
4990
|
throw new Error(MISSING_API_KEY_MESSAGE);
|
|
4952
4991
|
return apiKey;
|
|
4953
4992
|
}
|
|
4993
|
+
var MISSING_API_KEY_MESSAGE;
|
|
4994
|
+
var init_auth2 = __esm(() => {
|
|
4995
|
+
init_auth();
|
|
4996
|
+
init_constants();
|
|
4997
|
+
MISSING_API_KEY_MESSAGE = `DeepSeek API key not found. Set ${API_KEY_ENV} in the MCP server's env configuration.`;
|
|
4998
|
+
});
|
|
4954
4999
|
|
|
4955
5000
|
// src/mcp/client.ts
|
|
4956
5001
|
import { CLIENT_INFO_META_KEY } from "@modelcontextprotocol/server";
|
|
4957
|
-
var JSON_REPLACING_CLIENT_NAMES = new Set(["codex-mcp-client"]);
|
|
4958
5002
|
function clientNameOf(server, ctx) {
|
|
4959
5003
|
const envelope = ctx.mcpReq.envelope;
|
|
4960
5004
|
const name = envelope?.[CLIENT_INFO_META_KEY];
|
|
@@ -4969,119 +5013,119 @@ function isJsonReplacingClient(name) {
|
|
|
4969
5013
|
function omitStructuredContent(server, ctx) {
|
|
4970
5014
|
return isJsonReplacingClient(clientNameOf(server, ctx));
|
|
4971
5015
|
}
|
|
5016
|
+
var JSON_REPLACING_CLIENT_NAMES;
|
|
5017
|
+
var init_client = __esm(() => {
|
|
5018
|
+
JSON_REPLACING_CLIENT_NAMES = new Set(["codex-mcp-client"]);
|
|
5019
|
+
});
|
|
4972
5020
|
|
|
4973
|
-
// src/mcp/server.ts
|
|
4974
|
-
import { McpServer } from "@modelcontextprotocol/server";
|
|
4975
|
-
import * as z from "zod/v4";
|
|
4976
5021
|
// package.json
|
|
4977
|
-
var package_default
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
bugs: "https://github.com/gwokhou/deepseek-web-retrieval/issues",
|
|
4990
|
-
keywords: [
|
|
4991
|
-
"opencode",
|
|
4992
|
-
"opencode-plugin",
|
|
4993
|
-
"pi",
|
|
4994
|
-
"pi-extension",
|
|
4995
|
-
"deepseek",
|
|
4996
|
-
"websearch",
|
|
4997
|
-
"webfetch",
|
|
4998
|
-
"coding-agent",
|
|
4999
|
-
"mcp"
|
|
5000
|
-
],
|
|
5001
|
-
exports: {
|
|
5002
|
-
".": "./index.ts",
|
|
5003
|
-
"./core": "./src/core/index.ts",
|
|
5004
|
-
"./mcp": "./src/mcp/server.ts",
|
|
5005
|
-
"./pi": "./src/pi/extension.ts"
|
|
5006
|
-
},
|
|
5007
|
-
pi: {
|
|
5008
|
-
extensions: [
|
|
5009
|
-
"./src/pi/extension.ts"
|
|
5010
|
-
]
|
|
5011
|
-
},
|
|
5012
|
-
bin: {
|
|
5013
|
-
"deepseek-web-retrieval": "dist/cli.js"
|
|
5014
|
-
},
|
|
5015
|
-
files: [
|
|
5016
|
-
"index.ts",
|
|
5017
|
-
"src",
|
|
5018
|
-
"dist",
|
|
5019
|
-
"docs",
|
|
5020
|
-
"README.md",
|
|
5021
|
-
"LICENSE",
|
|
5022
|
-
"CHANGELOG.md",
|
|
5023
|
-
"examples"
|
|
5024
|
-
],
|
|
5025
|
-
scripts: {
|
|
5026
|
-
lint: "biome check --error-on-warnings .",
|
|
5027
|
-
"lint:ci": "biome ci --error-on-warnings .",
|
|
5028
|
-
"lint:fix": "biome check --write --error-on-warnings .",
|
|
5029
|
-
format: "biome format --write .",
|
|
5030
|
-
typecheck: "tsc --noEmit",
|
|
5031
|
-
build: "bun build src/mcp/cli.ts --target=node --format=esm --outdir=dist --external @modelcontextprotocol/server --external @modelcontextprotocol/server/stdio --external zod --external zod/v4",
|
|
5032
|
-
prepublishOnly: "bun run check:release",
|
|
5033
|
-
test: "bun test",
|
|
5034
|
-
"test:package": "node scripts/test-package.mjs",
|
|
5035
|
-
"test:e2e:keyless": "bun run test:e2e pi pi-extension installer reinit upgrade pkg capability-off",
|
|
5036
|
-
"check:release": "bun run check && bun run test:package && bun run test:e2e:keyless",
|
|
5037
|
-
"test:e2e": "bun run test/e2e/run.ts",
|
|
5038
|
-
"docs:matrix": "bun run scripts/render-matrix.ts",
|
|
5039
|
-
"test:coverage": "bun test --coverage",
|
|
5040
|
-
check: "bun run lint && bun run typecheck && bun run docs:matrix --check && bun run build && bun test"
|
|
5041
|
-
},
|
|
5042
|
-
peerDependencies: {
|
|
5043
|
-
"@earendil-works/pi-ai": "^1.3.0",
|
|
5044
|
-
"@earendil-works/pi-coding-agent": "^1.3.0",
|
|
5045
|
-
"@opencode/plugin": "^2.0.32"
|
|
5046
|
-
},
|
|
5047
|
-
peerDependenciesMeta: {
|
|
5048
|
-
"@earendil-works/pi-ai": {
|
|
5049
|
-
optional: true
|
|
5022
|
+
var package_default;
|
|
5023
|
+
var init_package = __esm(() => {
|
|
5024
|
+
package_default = {
|
|
5025
|
+
$schema: "https://json.schemastore.org/package.json",
|
|
5026
|
+
name: "deepseek-web-retrieval",
|
|
5027
|
+
version: "0.6.0",
|
|
5028
|
+
description: "Token-efficient DeepSeek Search and Fetch for coding agents, starting with OpenCode v2.",
|
|
5029
|
+
type: "module",
|
|
5030
|
+
license: "MIT",
|
|
5031
|
+
repository: {
|
|
5032
|
+
type: "git",
|
|
5033
|
+
url: "git+https://github.com/gwokhou/deepseek-web-retrieval.git"
|
|
5050
5034
|
},
|
|
5051
|
-
"
|
|
5052
|
-
|
|
5035
|
+
homepage: "https://github.com/gwokhou/deepseek-web-retrieval#readme",
|
|
5036
|
+
bugs: "https://github.com/gwokhou/deepseek-web-retrieval/issues",
|
|
5037
|
+
keywords: [
|
|
5038
|
+
"opencode",
|
|
5039
|
+
"opencode-plugin",
|
|
5040
|
+
"pi",
|
|
5041
|
+
"pi-extension",
|
|
5042
|
+
"deepseek",
|
|
5043
|
+
"websearch",
|
|
5044
|
+
"webfetch",
|
|
5045
|
+
"coding-agent",
|
|
5046
|
+
"mcp"
|
|
5047
|
+
],
|
|
5048
|
+
exports: {
|
|
5049
|
+
".": "./index.ts",
|
|
5050
|
+
"./core": "./src/core/index.ts",
|
|
5051
|
+
"./mcp": "./src/mcp/server.ts",
|
|
5052
|
+
"./pi": "./src/pi/extension.ts"
|
|
5053
5053
|
},
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5054
|
+
pi: {
|
|
5055
|
+
extensions: [
|
|
5056
|
+
"./src/pi/extension.ts"
|
|
5057
|
+
]
|
|
5058
|
+
},
|
|
5059
|
+
bin: {
|
|
5060
|
+
"deepseek-web-retrieval": "dist/cli.js"
|
|
5061
|
+
},
|
|
5062
|
+
files: [
|
|
5063
|
+
"index.ts",
|
|
5064
|
+
"src",
|
|
5065
|
+
"dist",
|
|
5066
|
+
"docs",
|
|
5067
|
+
"README.md",
|
|
5068
|
+
"LICENSE",
|
|
5069
|
+
"CHANGELOG.md",
|
|
5070
|
+
"examples"
|
|
5071
|
+
],
|
|
5072
|
+
scripts: {
|
|
5073
|
+
lint: "biome check --error-on-warnings .",
|
|
5074
|
+
"lint:ci": "biome ci --error-on-warnings .",
|
|
5075
|
+
"lint:fix": "biome check --write --error-on-warnings .",
|
|
5076
|
+
format: "biome format --write .",
|
|
5077
|
+
typecheck: "tsc --noEmit",
|
|
5078
|
+
build: "bun build src/mcp/cli.ts --target=node --format=esm --outdir=dist --external @modelcontextprotocol/server --external @modelcontextprotocol/server/stdio --external zod --external zod/v4",
|
|
5079
|
+
prepublishOnly: "bun run check:release",
|
|
5080
|
+
test: "bun test",
|
|
5081
|
+
"test:package": "node scripts/test-package.mjs",
|
|
5082
|
+
"test:e2e:keyless": "bun run test:e2e pi pi-extension installer reinit upgrade pkg capability-off",
|
|
5083
|
+
"check:release": "bun run check && bun run test:package && bun run test:e2e:keyless",
|
|
5084
|
+
"test:e2e": "bun run test/e2e/run.ts",
|
|
5085
|
+
"docs:matrix": "bun run scripts/render-matrix.ts",
|
|
5086
|
+
"test:coverage": "bun test --coverage",
|
|
5087
|
+
check: "bun run lint && bun run typecheck && bun run docs:matrix --check && bun run build && bun test"
|
|
5088
|
+
},
|
|
5089
|
+
peerDependencies: {
|
|
5090
|
+
"@earendil-works/pi-ai": "^1.3.0",
|
|
5091
|
+
"@earendil-works/pi-coding-agent": "^1.3.0",
|
|
5092
|
+
"@opencode/plugin": "^2.0.32"
|
|
5093
|
+
},
|
|
5094
|
+
peerDependenciesMeta: {
|
|
5095
|
+
"@earendil-works/pi-ai": {
|
|
5096
|
+
optional: true
|
|
5097
|
+
},
|
|
5098
|
+
"@earendil-works/pi-coding-agent": {
|
|
5099
|
+
optional: true
|
|
5100
|
+
},
|
|
5101
|
+
"@opencode/plugin": {
|
|
5102
|
+
optional: true
|
|
5103
|
+
}
|
|
5104
|
+
},
|
|
5105
|
+
devDependencies: {
|
|
5106
|
+
"@biomejs/biome": "2.5.15",
|
|
5107
|
+
"@earendil-works/pi-ai": "1.3.0",
|
|
5108
|
+
"@earendil-works/pi-coding-agent": "1.3.0",
|
|
5109
|
+
"@modelcontextprotocol/client": "^2.3.1",
|
|
5110
|
+
"@opencode/plugin": "2.0.32",
|
|
5111
|
+
"@types/bun": "1.4.0",
|
|
5112
|
+
"@types/node": "^26.6.5",
|
|
5113
|
+
typescript: "5.9.3"
|
|
5114
|
+
},
|
|
5115
|
+
engines: {
|
|
5116
|
+
bun: ">=1.3.0",
|
|
5117
|
+
node: ">=20"
|
|
5118
|
+
},
|
|
5119
|
+
dependencies: {
|
|
5120
|
+
"@modelcontextprotocol/server": "^2.3.1",
|
|
5121
|
+
"jsonc-parser": "^3.3.1",
|
|
5122
|
+
"smol-toml": "^1.9.1",
|
|
5123
|
+
zod: "^4"
|
|
5124
|
+
}
|
|
5125
|
+
};
|
|
5126
|
+
});
|
|
5082
5127
|
|
|
5083
5128
|
// src/core/format.ts
|
|
5084
|
-
init_constants();
|
|
5085
5129
|
function truncate(value, maxChars) {
|
|
5086
5130
|
if (maxChars <= 0)
|
|
5087
5131
|
return "";
|
|
@@ -5127,16 +5171,16 @@ function normalizeHeading(value) {
|
|
|
5127
5171
|
function redactSecrets(value) {
|
|
5128
5172
|
return value.replace(/\bsk-[A-Za-z0-9_-]{8,}\b/g, "sk-***").replace(/\bBearer\s+[A-Za-z0-9._~+/=-]{8,}/gi, "Bearer ***");
|
|
5129
5173
|
}
|
|
5130
|
-
function formatApiError(
|
|
5174
|
+
function formatApiError(operation2, status, body) {
|
|
5131
5175
|
const detail = redactSecrets(body.trim());
|
|
5132
5176
|
const detailChars = Array.from(detail);
|
|
5133
5177
|
const text = detail ? detailChars.length > MAX_ERROR_BODY_CHARS ? `${detailChars.slice(0, MAX_ERROR_BODY_CHARS).join("")}…` : detail : "empty response body";
|
|
5134
5178
|
const hint = status === 401 ? "invalid API key" : status === 402 ? "insufficient balance" : status === 403 ? "permission denied" : status === 429 ? "rate limited" : undefined;
|
|
5135
|
-
const label = hint ? `${
|
|
5179
|
+
const label = hint ? `${operation2} failed (HTTP ${status}, ${hint})` : `${operation2} failed (HTTP ${status})`;
|
|
5136
5180
|
return `${label}: ${text}`;
|
|
5137
5181
|
}
|
|
5138
|
-
function formatTimeoutError(
|
|
5139
|
-
return `${
|
|
5182
|
+
function formatTimeoutError(operation2, timeoutMs) {
|
|
5183
|
+
return `${operation2} timed out after ${timeoutMs} ms`;
|
|
5140
5184
|
}
|
|
5141
5185
|
function formatSearchResults(results) {
|
|
5142
5186
|
if (results.length === 0)
|
|
@@ -5171,9 +5215,11 @@ function escapeBrackets(value) {
|
|
|
5171
5215
|
function formatPublished(epochMs) {
|
|
5172
5216
|
return new Date(epochMs).toISOString().slice(0, 10);
|
|
5173
5217
|
}
|
|
5218
|
+
var init_format2 = __esm(() => {
|
|
5219
|
+
init_constants();
|
|
5220
|
+
});
|
|
5174
5221
|
|
|
5175
5222
|
// src/core/url.ts
|
|
5176
|
-
init_constants();
|
|
5177
5223
|
function parseFetchUrl(value) {
|
|
5178
5224
|
const input = value.trim();
|
|
5179
5225
|
if (!input)
|
|
@@ -5215,6 +5261,10 @@ function normalizeResultUrl(value) {
|
|
|
5215
5261
|
return;
|
|
5216
5262
|
}
|
|
5217
5263
|
}
|
|
5264
|
+
var init_url = __esm(() => {
|
|
5265
|
+
init_constants();
|
|
5266
|
+
init_domains();
|
|
5267
|
+
});
|
|
5218
5268
|
|
|
5219
5269
|
// src/core/search.ts
|
|
5220
5270
|
function buildQuery(query, options) {
|
|
@@ -5280,33 +5330,20 @@ function optionalText2(value) {
|
|
|
5280
5330
|
const trimmed = value.trim();
|
|
5281
5331
|
return trimmed ? trimmed : undefined;
|
|
5282
5332
|
}
|
|
5333
|
+
var init_search = __esm(() => {
|
|
5334
|
+
init_domains();
|
|
5335
|
+
init_format2();
|
|
5336
|
+
init_url();
|
|
5337
|
+
});
|
|
5283
5338
|
|
|
5284
5339
|
// src/core/transport.ts
|
|
5285
|
-
|
|
5286
|
-
class DeepSeekApiError extends Error {
|
|
5287
|
-
operation;
|
|
5288
|
-
status;
|
|
5289
|
-
body;
|
|
5290
|
-
retryable;
|
|
5291
|
-
retryAfterMs;
|
|
5292
|
-
constructor(input) {
|
|
5293
|
-
const body = redactSecrets(input.body);
|
|
5294
|
-
super(formatApiError(input.operation, input.status, body));
|
|
5295
|
-
this.name = "DeepSeekApiError";
|
|
5296
|
-
this.operation = input.operation;
|
|
5297
|
-
this.status = input.status;
|
|
5298
|
-
this.body = body;
|
|
5299
|
-
this.retryable = input.status === 408 || input.status === 425 || input.status === 429 || input.status >= 500 && input.status <= 599;
|
|
5300
|
-
this.retryAfterMs = input.retryAfterMs;
|
|
5301
|
-
}
|
|
5302
|
-
}
|
|
5303
|
-
async function postJson(endpoint, body, operation, opts) {
|
|
5340
|
+
async function postJson(endpoint, body, operation2, opts) {
|
|
5304
5341
|
const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
|
|
5305
5342
|
const attempts = opts.retry.maxRetries + 1;
|
|
5306
5343
|
let lastError;
|
|
5307
5344
|
for (let attempt = 0;attempt < attempts; attempt++) {
|
|
5308
5345
|
try {
|
|
5309
|
-
return await requestOnce(endpoint, body,
|
|
5346
|
+
return await requestOnce(endpoint, body, operation2, opts, fetchImpl);
|
|
5310
5347
|
} catch (error) {
|
|
5311
5348
|
lastError = error;
|
|
5312
5349
|
if (!(error instanceof DeepSeekApiError) || !error.retryable || attempt === attempts - 1) {
|
|
@@ -5317,7 +5354,7 @@ async function postJson(endpoint, body, operation, opts) {
|
|
|
5317
5354
|
}
|
|
5318
5355
|
throw lastError;
|
|
5319
5356
|
}
|
|
5320
|
-
async function requestOnce(endpoint, body,
|
|
5357
|
+
async function requestOnce(endpoint, body, operation2, opts, fetchImpl) {
|
|
5321
5358
|
return fetchWithTimeout(endpoint, {
|
|
5322
5359
|
method: "POST",
|
|
5323
5360
|
headers: {
|
|
@@ -5325,27 +5362,27 @@ async function requestOnce(endpoint, body, operation, opts, fetchImpl) {
|
|
|
5325
5362
|
"Content-Type": "application/json"
|
|
5326
5363
|
},
|
|
5327
5364
|
body: JSON.stringify(body)
|
|
5328
|
-
}, opts.signal, opts.timeoutMs,
|
|
5365
|
+
}, opts.signal, opts.timeoutMs, operation2, fetchImpl, async (response) => {
|
|
5329
5366
|
if (!response.ok) {
|
|
5330
5367
|
const text2 = await readBoundedText(response, MAX_ERROR_BODY_CHARS);
|
|
5331
5368
|
throw new DeepSeekApiError({
|
|
5332
|
-
operation,
|
|
5369
|
+
operation: operation2,
|
|
5333
5370
|
status: response.status,
|
|
5334
5371
|
body: text2,
|
|
5335
5372
|
retryAfterMs: parseRetryAfter(response.headers.get("retry-after"))
|
|
5336
5373
|
});
|
|
5337
5374
|
}
|
|
5338
|
-
const text = await readResponseText(response, MAX_RESPONSE_BYTES,
|
|
5375
|
+
const text = await readResponseText(response, MAX_RESPONSE_BYTES, operation2);
|
|
5339
5376
|
if (!text.trim())
|
|
5340
|
-
throw new Error(`${
|
|
5377
|
+
throw new Error(`${operation2} returned an empty response body`);
|
|
5341
5378
|
try {
|
|
5342
5379
|
return JSON.parse(text);
|
|
5343
5380
|
} catch {
|
|
5344
|
-
throw new Error(`${
|
|
5381
|
+
throw new Error(`${operation2} returned invalid JSON: ${truncate(redactSecrets(text), 500)}`);
|
|
5345
5382
|
}
|
|
5346
5383
|
});
|
|
5347
5384
|
}
|
|
5348
|
-
async function fetchWithTimeout(endpoint, init, signal, timeoutMs,
|
|
5385
|
+
async function fetchWithTimeout(endpoint, init, signal, timeoutMs, operation2, fetchImpl, handleResponse) {
|
|
5349
5386
|
const controller = new AbortController;
|
|
5350
5387
|
let timedOut = false;
|
|
5351
5388
|
const forwardAbort = () => controller.abort(signal.reason);
|
|
@@ -5362,9 +5399,9 @@ async function fetchWithTimeout(endpoint, init, signal, timeoutMs, operation, fe
|
|
|
5362
5399
|
return await handleResponse(response);
|
|
5363
5400
|
} catch (error) {
|
|
5364
5401
|
if (timedOut)
|
|
5365
|
-
throw new Error(formatTimeoutError(
|
|
5402
|
+
throw new Error(formatTimeoutError(operation2, timeoutMs));
|
|
5366
5403
|
if (signal.aborted)
|
|
5367
|
-
throw abortReason(signal,
|
|
5404
|
+
throw abortReason(signal, operation2);
|
|
5368
5405
|
throw error;
|
|
5369
5406
|
} finally {
|
|
5370
5407
|
if (timer !== undefined)
|
|
@@ -5394,10 +5431,10 @@ function retryDelay(retryAfterMs, baseDelayMs, attempt) {
|
|
|
5394
5431
|
function sleep(ms, signal) {
|
|
5395
5432
|
if (ms <= 0)
|
|
5396
5433
|
return Promise.resolve();
|
|
5397
|
-
return new Promise((
|
|
5434
|
+
return new Promise((resolve3, reject) => {
|
|
5398
5435
|
const timer = setTimeout(() => {
|
|
5399
5436
|
signal.removeEventListener("abort", onAbort);
|
|
5400
|
-
|
|
5437
|
+
resolve3();
|
|
5401
5438
|
}, ms);
|
|
5402
5439
|
const onAbort = () => {
|
|
5403
5440
|
clearTimeout(timer);
|
|
@@ -5411,8 +5448,8 @@ function sleep(ms, signal) {
|
|
|
5411
5448
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
5412
5449
|
});
|
|
5413
5450
|
}
|
|
5414
|
-
function abortReason(signal,
|
|
5415
|
-
return signal.reason instanceof Error ? signal.reason : new Error(`${
|
|
5451
|
+
function abortReason(signal, operation2) {
|
|
5452
|
+
return signal.reason instanceof Error ? signal.reason : new Error(`${operation2} request aborted`);
|
|
5416
5453
|
}
|
|
5417
5454
|
async function readBoundedText(response, maxChars) {
|
|
5418
5455
|
if (!response.body)
|
|
@@ -5440,11 +5477,11 @@ async function readBoundedText(response, maxChars) {
|
|
|
5440
5477
|
}
|
|
5441
5478
|
return truncate(text, limit);
|
|
5442
5479
|
}
|
|
5443
|
-
async function readResponseText(response, maxBytes,
|
|
5480
|
+
async function readResponseText(response, maxBytes, operation2) {
|
|
5444
5481
|
if (!response.body) {
|
|
5445
5482
|
const text2 = await response.text();
|
|
5446
5483
|
if (new TextEncoder().encode(text2).byteLength > maxBytes) {
|
|
5447
|
-
throw new Error(`${
|
|
5484
|
+
throw new Error(`${operation2} response exceeded ${maxBytes} bytes`);
|
|
5448
5485
|
}
|
|
5449
5486
|
return text2;
|
|
5450
5487
|
}
|
|
@@ -5459,7 +5496,7 @@ async function readResponseText(response, maxBytes, operation) {
|
|
|
5459
5496
|
break;
|
|
5460
5497
|
bytes += value.byteLength;
|
|
5461
5498
|
if (bytes > maxBytes) {
|
|
5462
|
-
throw new Error(`${
|
|
5499
|
+
throw new Error(`${operation2} response exceeded ${maxBytes} bytes`);
|
|
5463
5500
|
}
|
|
5464
5501
|
text += decoder.decode(value, { stream: true });
|
|
5465
5502
|
}
|
|
@@ -5472,6 +5509,28 @@ async function readResponseText(response, maxBytes, operation) {
|
|
|
5472
5509
|
}
|
|
5473
5510
|
return text;
|
|
5474
5511
|
}
|
|
5512
|
+
var DeepSeekApiError;
|
|
5513
|
+
var init_transport = __esm(() => {
|
|
5514
|
+
init_constants();
|
|
5515
|
+
init_format2();
|
|
5516
|
+
DeepSeekApiError = class DeepSeekApiError extends Error {
|
|
5517
|
+
operation;
|
|
5518
|
+
status;
|
|
5519
|
+
body;
|
|
5520
|
+
retryable;
|
|
5521
|
+
retryAfterMs;
|
|
5522
|
+
constructor(input) {
|
|
5523
|
+
const body = redactSecrets(input.body);
|
|
5524
|
+
super(formatApiError(input.operation, input.status, body));
|
|
5525
|
+
this.name = "DeepSeekApiError";
|
|
5526
|
+
this.operation = input.operation;
|
|
5527
|
+
this.status = input.status;
|
|
5528
|
+
this.body = body;
|
|
5529
|
+
this.retryable = input.status === 408 || input.status === 425 || input.status === 429 || input.status >= 500 && input.status <= 599;
|
|
5530
|
+
this.retryAfterMs = input.retryAfterMs;
|
|
5531
|
+
}
|
|
5532
|
+
};
|
|
5533
|
+
});
|
|
5475
5534
|
|
|
5476
5535
|
// src/core/client.ts
|
|
5477
5536
|
function effectiveTimeout(configuredMs, perCallMs) {
|
|
@@ -5535,30 +5594,28 @@ function createRetrievalClient(dependencies = {}) {
|
|
|
5535
5594
|
fetchDocument: (url, options, request) => fetchDocument(url, options, bind(request))
|
|
5536
5595
|
};
|
|
5537
5596
|
}
|
|
5538
|
-
var retrievalClient
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5597
|
+
var retrievalClient;
|
|
5598
|
+
var init_client2 = __esm(() => {
|
|
5599
|
+
init_constants();
|
|
5600
|
+
init_domains();
|
|
5601
|
+
init_format2();
|
|
5602
|
+
init_search();
|
|
5603
|
+
init_transport();
|
|
5604
|
+
init_url();
|
|
5605
|
+
init_transport();
|
|
5606
|
+
retrievalClient = createRetrievalClient();
|
|
5607
|
+
});
|
|
5542
5608
|
|
|
5543
5609
|
// src/core/descriptions.ts
|
|
5544
|
-
var FETCH_SERVICE_LIMITS = "DeepSeek does not render JavaScript and cannot reach private networks; PDFs, images, and other binary files are unsupported.";
|
|
5545
|
-
var
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
var SEARCH_TOOL_DESCRIPTION = "Search the web with DeepSeek's in-house search engine and return a short, filtered result " + "list (title, URL, summary). " + `${SEARCH_RANKED_FILTERED} ` + `${SEARCH_EMPTY_IS_NORMAL} ` + `${SEARCH_QUERY_OPERATORS} ` + "To read a full page, pass a result URL to the deepseek_fetch tool.";
|
|
5550
|
-
var FETCH_TOOL_DESCRIPTION = "Fetch one web page as clean Markdown through DeepSeek's Fetch API. " + `${FETCH_SERVICE_LIMITS} ` + `${FETCH_OUTPUT_TRUNCATED}`;
|
|
5551
|
-
var SEARCH_QUERY_PARAMETER = "Search query, 128 characters or fewer including operators (site:, -site:, quoted phrases, lang:).";
|
|
5552
|
-
var FETCH_URL_PARAMETER = "Absolute http:// or https:// URL to fetch. Credentials are rejected.";
|
|
5610
|
+
var FETCH_SERVICE_LIMITS = "DeepSeek does not render JavaScript and cannot reach private networks; PDFs, images, and other binary files are unsupported.", FETCH_OUTPUT_TRUNCATED = "Output is truncated to the configured size.", SEARCH_RANKED_FILTERED = "Results are ranked by relevance and source authority, deduplicated by URL, and capped at the configured maximum.", SEARCH_EMPTY_IS_NORMAL = "An empty result list is normal, not an error.", SEARCH_QUERY_OPERATORS = "Use site:/-site: operators in the query to include or exclude domains; the full query must stay within 128 characters.", SEARCH_TOOL_DESCRIPTION, FETCH_TOOL_DESCRIPTION, SEARCH_QUERY_PARAMETER = "Search query, 128 characters or fewer including operators (site:, -site:, quoted phrases, lang:).", FETCH_URL_PARAMETER = "Absolute http:// or https:// URL to fetch. Credentials are rejected.";
|
|
5611
|
+
var init_descriptions = __esm(() => {
|
|
5612
|
+
SEARCH_TOOL_DESCRIPTION = "Search the web with DeepSeek's in-house search engine and return a short, filtered result " + "list (title, URL, summary). " + `${SEARCH_RANKED_FILTERED} ` + `${SEARCH_EMPTY_IS_NORMAL} ` + `${SEARCH_QUERY_OPERATORS} ` + "To read a full page, pass a result URL to the deepseek_fetch tool.";
|
|
5613
|
+
FETCH_TOOL_DESCRIPTION = "Fetch one web page as clean Markdown through DeepSeek's Fetch API. " + `${FETCH_SERVICE_LIMITS} ` + `${FETCH_OUTPUT_TRUNCATED}`;
|
|
5614
|
+
});
|
|
5553
5615
|
|
|
5554
5616
|
// src/mcp/server.ts
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
query: z.string().min(1).describe(SEARCH_QUERY_PARAMETER)
|
|
5558
|
-
});
|
|
5559
|
-
var FETCH_INPUT = z.object({
|
|
5560
|
-
url: z.string().min(1).describe(FETCH_URL_PARAMETER)
|
|
5561
|
-
});
|
|
5617
|
+
import { McpServer } from "@modelcontextprotocol/server";
|
|
5618
|
+
import * as z2 from "zod/v4";
|
|
5562
5619
|
function createDeepSeekServer(config, env = process.env, client = retrievalClient) {
|
|
5563
5620
|
const server = new McpServer({ name: MCP_SERVER_NAME, version: package_default.version });
|
|
5564
5621
|
if (config.search.enabled) {
|
|
@@ -5619,38 +5676,71 @@ function toErrorResult(error) {
|
|
|
5619
5676
|
const message = error instanceof Error ? error.message : String(error);
|
|
5620
5677
|
return { content: [{ type: "text", text: message }], isError: true };
|
|
5621
5678
|
}
|
|
5679
|
+
var MCP_SERVER_NAME = "deepseek-web-retrieval", SEARCH_INPUT, FETCH_INPUT;
|
|
5680
|
+
var init_server = __esm(() => {
|
|
5681
|
+
init_package();
|
|
5682
|
+
init_client2();
|
|
5683
|
+
init_constants();
|
|
5684
|
+
init_descriptions();
|
|
5685
|
+
init_format2();
|
|
5686
|
+
init_auth2();
|
|
5687
|
+
init_client();
|
|
5688
|
+
SEARCH_INPUT = z2.object({
|
|
5689
|
+
query: z2.string().min(1).describe(SEARCH_QUERY_PARAMETER)
|
|
5690
|
+
});
|
|
5691
|
+
FETCH_INPUT = z2.object({
|
|
5692
|
+
url: z2.string().min(1).describe(FETCH_URL_PARAMETER)
|
|
5693
|
+
});
|
|
5694
|
+
});
|
|
5695
|
+
|
|
5696
|
+
// src/mcp/serve.ts
|
|
5697
|
+
var exports_serve = {};
|
|
5698
|
+
__export(exports_serve, {
|
|
5699
|
+
serveMcp: () => serveMcp
|
|
5700
|
+
});
|
|
5701
|
+
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
5702
|
+
function serveMcp() {
|
|
5703
|
+
const env = process.env;
|
|
5704
|
+
if (!apiKeyFromEnv(env)) {
|
|
5705
|
+
console.error(MISSING_API_KEY_MESSAGE);
|
|
5706
|
+
process.exit(1);
|
|
5707
|
+
}
|
|
5708
|
+
const config = resolveEnvOptions(env);
|
|
5709
|
+
const precheck = servePrecheck(config);
|
|
5710
|
+
if (precheck) {
|
|
5711
|
+
console.error(precheck);
|
|
5712
|
+
process.exit(1);
|
|
5713
|
+
}
|
|
5714
|
+
const handle = serveStdio(() => {
|
|
5715
|
+
const server = createDeepSeekServer(config, env);
|
|
5716
|
+
server.server.oninitialized = () => {
|
|
5717
|
+
const info = server.server.getClientVersion();
|
|
5718
|
+
if (info === undefined)
|
|
5719
|
+
return;
|
|
5720
|
+
console.error(`mcp client: ${info.name} ${info.version ?? "unknown"} — ` + (isJsonReplacingClient(info.name) ? "text-only results (this client replaces content with serialized structuredContent)" : "text + structuredContent results"));
|
|
5721
|
+
};
|
|
5722
|
+
return server;
|
|
5723
|
+
});
|
|
5724
|
+
const tools = [
|
|
5725
|
+
config.search.enabled ? `search (max ${config.search.maxResults} results)` : null,
|
|
5726
|
+
config.fetch.enabled ? `fetch (max ${config.fetch.maxChars} chars)` : null
|
|
5727
|
+
].filter(Boolean).join(", ");
|
|
5728
|
+
console.error(`deepseek-web-retrieval MCP server on stdio (${tools})`);
|
|
5729
|
+
process.on("SIGINT", () => void handle.close());
|
|
5730
|
+
process.on("SIGTERM", () => void handle.close());
|
|
5731
|
+
}
|
|
5732
|
+
var init_serve = __esm(() => {
|
|
5733
|
+
init_auth();
|
|
5734
|
+
init_env();
|
|
5735
|
+
init_auth2();
|
|
5736
|
+
init_client();
|
|
5737
|
+
init_server();
|
|
5738
|
+
});
|
|
5622
5739
|
|
|
5623
5740
|
// src/mcp/cli.ts
|
|
5624
|
-
|
|
5625
|
-
if (subcommand === "init" || subcommand === "uninstall" || subcommand === "list") {
|
|
5741
|
+
if (process.argv.length > 2) {
|
|
5626
5742
|
const { runInstallerCli: runInstallerCli2 } = await Promise.resolve().then(() => (init_cli(), exports_cli));
|
|
5627
5743
|
process.exit(await runInstallerCli2(process.argv.slice(2)));
|
|
5628
5744
|
}
|
|
5629
|
-
var
|
|
5630
|
-
|
|
5631
|
-
console.error(MISSING_API_KEY_MESSAGE);
|
|
5632
|
-
process.exit(1);
|
|
5633
|
-
}
|
|
5634
|
-
var config = resolveEnvOptions(env);
|
|
5635
|
-
var precheck = servePrecheck(config);
|
|
5636
|
-
if (precheck) {
|
|
5637
|
-
console.error(precheck);
|
|
5638
|
-
process.exit(1);
|
|
5639
|
-
}
|
|
5640
|
-
var handle = serveStdio(() => {
|
|
5641
|
-
const server = createDeepSeekServer(config, env);
|
|
5642
|
-
server.server.oninitialized = () => {
|
|
5643
|
-
const info = server.server.getClientVersion();
|
|
5644
|
-
if (info === undefined)
|
|
5645
|
-
return;
|
|
5646
|
-
console.error(`mcp client: ${info.name} ${info.version ?? "unknown"} — ` + (isJsonReplacingClient(info.name) ? "text-only results (this client replaces content with serialized structuredContent)" : "text + structuredContent results"));
|
|
5647
|
-
};
|
|
5648
|
-
return server;
|
|
5649
|
-
});
|
|
5650
|
-
var tools = [
|
|
5651
|
-
config.search.enabled ? `search (max ${config.search.maxResults} results)` : null,
|
|
5652
|
-
config.fetch.enabled ? `fetch (max ${config.fetch.maxChars} chars)` : null
|
|
5653
|
-
].filter(Boolean).join(", ");
|
|
5654
|
-
console.error(`deepseek-web-retrieval MCP server on stdio (${tools})`);
|
|
5655
|
-
process.on("SIGINT", () => void handle.close());
|
|
5656
|
-
process.on("SIGTERM", () => void handle.close());
|
|
5745
|
+
var { serveMcp: serveMcp2 } = await Promise.resolve().then(() => (init_serve(), exports_serve));
|
|
5746
|
+
serveMcp2();
|