deepseeker-code 1.0.41 → 1.0.43

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.
Files changed (2) hide show
  1. package/dist/cli.mjs +525 -374
  2. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -9,12 +9,88 @@ var __export = (target, all) => {
9
9
  __defProp(target, name, { get: all[name], enumerable: true });
10
10
  };
11
11
 
12
+ // src/updateCheck.ts
13
+ var updateCheck_exports = {};
14
+ __export(updateCheck_exports, {
15
+ getCachedLatestIfNewer: () => getCachedLatestIfNewer,
16
+ readLocalVersion: () => readLocalVersion,
17
+ refreshUpdateCache: () => refreshUpdateCache
18
+ });
19
+ import { readFileSync as readFileSync2, writeFileSync, mkdirSync } from "node:fs";
20
+ import path2 from "node:path";
21
+ import os2 from "os";
22
+ import { fileURLToPath } from "node:url";
23
+ var PKG_NAME, REGISTRY, CACHE_TTL_MS, FETCH_TIMEOUT_MS, cacheFile, readLocalVersion, parseSemver, compareVersion, readCache, writeCache, getCachedLatestIfNewer, refreshUpdateCache;
24
+ var init_updateCheck = __esm({
25
+ "src/updateCheck.ts"() {
26
+ "use strict";
27
+ PKG_NAME = "deepseeker-code";
28
+ REGISTRY = "https://registry.npmjs.org";
29
+ CACHE_TTL_MS = 6 * 60 * 60 * 1e3;
30
+ FETCH_TIMEOUT_MS = 3e3;
31
+ cacheFile = () => path2.join(os2.homedir(), ".deepseeker-code", "update-check.json");
32
+ readLocalVersion = () => {
33
+ try {
34
+ const here = path2.dirname(fileURLToPath(import.meta.url));
35
+ return JSON.parse(readFileSync2(path2.join(here, "..", "package.json"), "utf8")).version ?? "0.0.0";
36
+ } catch {
37
+ return "0.0.0";
38
+ }
39
+ };
40
+ parseSemver = (v) => {
41
+ const m = String(v ?? "").match(/^(\d+)\.(\d+)\.(\d+)/);
42
+ return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : [0, 0, 0];
43
+ };
44
+ compareVersion = (a, b) => {
45
+ const [a1, a2, a3] = parseSemver(a);
46
+ const [b1, b2, b3] = parseSemver(b);
47
+ return a1 - b1 || a2 - b2 || a3 - b3;
48
+ };
49
+ readCache = () => {
50
+ try {
51
+ const obj = JSON.parse(readFileSync2(cacheFile(), "utf8"));
52
+ return typeof obj.latestVersion === "string" && typeof obj.lastCheck === "number" ? obj : null;
53
+ } catch {
54
+ return null;
55
+ }
56
+ };
57
+ writeCache = (latestVersion) => {
58
+ try {
59
+ mkdirSync(path2.dirname(cacheFile()), { recursive: true });
60
+ writeFileSync(cacheFile(), JSON.stringify({ lastCheck: Date.now(), latestVersion }), "utf8");
61
+ } catch {
62
+ }
63
+ };
64
+ getCachedLatestIfNewer = (currentVersion) => {
65
+ const cache = readCache();
66
+ if (!cache) return null;
67
+ return compareVersion(cache.latestVersion, currentVersion) > 0 ? cache.latestVersion : null;
68
+ };
69
+ refreshUpdateCache = () => {
70
+ const cache = readCache();
71
+ if (cache && Date.now() - cache.lastCheck < CACHE_TTL_MS) return;
72
+ void (async () => {
73
+ try {
74
+ const res = await fetch(`${REGISTRY}/${PKG_NAME}/latest`, {
75
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
76
+ });
77
+ if (!res.ok) return;
78
+ const info = await res.json();
79
+ if (info.version) writeCache(info.version);
80
+ } catch {
81
+ }
82
+ })();
83
+ };
84
+ }
85
+ });
86
+
12
87
  // src/strings.ts
13
88
  var VERSION, STRINGS, locale, getLocale, setLocale, S, LOCAL_COMMAND_NAMES;
14
89
  var init_strings = __esm({
15
90
  "src/strings.ts"() {
16
91
  "use strict";
17
- VERSION = "v1.0.0";
92
+ init_updateCheck();
93
+ VERSION = `v${readLocalVersion()}`;
18
94
  STRINGS = {
19
95
  zh: {
20
96
  brand: "DeepSeeker-Code",
@@ -317,15 +393,15 @@ __export(config_exports, {
317
393
  appConfig: () => appConfig,
318
394
  configSources: () => configSources
319
395
  });
320
- import path2 from "path";
321
- import os2 from "os";
322
- import { readFileSync as readFileSync2 } from "fs";
396
+ import path3 from "path";
397
+ import os3 from "os";
398
+ import { readFileSync as readFileSync3 } from "fs";
323
399
  import { createHash } from "crypto";
324
400
  var _DataDir, appConfig, ENV_SOURCES, configSources, ENGINE_OVERRIDE_VALIDATORS, ENGINE_OVERRIDE_KEYS, applyEngineOverrides;
325
401
  var init_config = __esm({
326
402
  "../core/src/config/index.ts"() {
327
403
  "use strict";
328
- _DataDir = process.env.DEEPSEEKER_CODE_DATA_DIR ? path2.resolve(process.env.DEEPSEEKER_CODE_DATA_DIR) : path2.join(os2.homedir(), ".deepseeker-code");
404
+ _DataDir = process.env.DEEPSEEKER_CODE_DATA_DIR ? path3.resolve(process.env.DEEPSEEKER_CODE_DATA_DIR) : path3.join(os3.homedir(), ".deepseeker-code");
329
405
  appConfig = {
330
406
  dataDir: _DataDir,
331
407
  maxReasoningRounds: 3,
@@ -352,8 +428,8 @@ var init_config = __esm({
352
428
  if (/^[a-z]:/i.test(cwd)) {
353
429
  cwd = cwd.charAt(0).toUpperCase() + cwd.slice(1);
354
430
  }
355
- const currentFolder = path2.basename(cwd);
356
- const parentFolder = path2.basename(path2.dirname(cwd));
431
+ const currentFolder = path3.basename(cwd);
432
+ const parentFolder = path3.basename(path3.dirname(cwd));
357
433
  const hash = createHash("sha256").update(cwd).digest("hex").slice(0, 8);
358
434
  return `${parentFolder}-${currentFolder}-${hash}`;
359
435
  })(),
@@ -451,15 +527,15 @@ var init_config = __esm({
451
527
  ENGINE_OVERRIDE_KEYS = Object.keys(ENGINE_OVERRIDE_VALIDATORS);
452
528
  applyEngineOverrides = (cfg) => {
453
529
  const paths = [
454
- { scope: "settings.global", configPath: path2.join(cfg.dataDir, "settings.json") },
530
+ { scope: "settings.global", configPath: path3.join(cfg.dataDir, "settings.json") },
455
531
  // 全局用户级
456
- { scope: "settings.project", configPath: path2.join(process.cwd(), ".deepseeker-code", "settings.json") }
532
+ { scope: "settings.project", configPath: path3.join(process.cwd(), ".deepseeker-code", "settings.json") }
457
533
  // 项目级(覆盖全局)
458
534
  ];
459
535
  for (const { scope, configPath } of paths) {
460
536
  let raw;
461
537
  try {
462
- raw = readFileSync2(configPath, "utf-8");
538
+ raw = readFileSync3(configPath, "utf-8");
463
539
  } catch {
464
540
  continue;
465
541
  }
@@ -493,7 +569,7 @@ import { randomUUID } from "node:crypto";
493
569
  import fs from "fs/promises";
494
570
  import { execFile } from "node:child_process";
495
571
  import { promisify } from "node:util";
496
- var getFileName, createUUID, SAFE_SESSION_ID_RE, isSafeSessionId, assertSafeSessionId, readJSONFile, atomicWriteJSON, createSemaphore, injectMarkedBlock, decodeProcessOutput, execFileSmart;
572
+ var getFileName, createUUID, SAFE_SESSION_ID_RE, isSafeSessionId, assertSafeSessionId, detectTextLocale, readJSONFile, atomicWriteJSON, createSemaphore, injectMarkedBlock, decodeProcessOutput, execFileSmart;
497
573
  var init_common = __esm({
498
574
  "../core/src/common/index.ts"() {
499
575
  "use strict";
@@ -516,6 +592,15 @@ var init_common = __esm({
516
592
  throw new Error(`\u{1F6D1} [SECURITY] \u975E\u6CD5 ${label}: ${JSON.stringify(sessionId.slice(0, 48))}\uFF08\u4EC5\u5141\u8BB8\u5B57\u6BCD/\u6570\u5B57/\u4E0B\u5212\u7EBF/\u8FDE\u5B57\u7B26\uFF09`);
517
593
  }
518
594
  };
595
+ detectTextLocale = (text) => {
596
+ const stripped = (text || "").replace(/```[\s\S]*?```/g, " ").replace(/`[^`]*`/g, " ").replace(/\s+/g, " ");
597
+ const cjk = (stripped.match(/[㐀-䶿一-鿿]/g) || []).length;
598
+ const latin = (stripped.match(/[A-Za-z]/g) || []).length;
599
+ if (cjk === 0 && latin === 0) return null;
600
+ if (cjk === 0) return "en";
601
+ if (latin === 0) return "zh";
602
+ return cjk / (cjk + latin) >= 0.2 ? "zh" : "en";
603
+ };
519
604
  readJSONFile = async (file, fallback = null) => {
520
605
  try {
521
606
  const raw = await fs.readFile(file, "utf-8");
@@ -596,7 +681,7 @@ ${body}`) return;
596
681
  });
597
682
 
598
683
  // src/prefs.ts
599
- import path3 from "path";
684
+ import path4 from "path";
600
685
  import fs2 from "fs/promises";
601
686
  var PREFS_FILE, readPrefs, readLocale, writePrefs, writeLocale;
602
687
  var init_prefs = __esm({
@@ -604,7 +689,7 @@ var init_prefs = __esm({
604
689
  "use strict";
605
690
  init_config();
606
691
  init_common();
607
- PREFS_FILE = path3.join(appConfig.dataDir, "prefs.json");
692
+ PREFS_FILE = path4.join(appConfig.dataDir, "prefs.json");
608
693
  readPrefs = async () => {
609
694
  const p = await readJSONFile(PREFS_FILE);
610
695
  return p && typeof p === "object" ? p : {};
@@ -625,7 +710,7 @@ var init_prefs = __esm({
625
710
  });
626
711
 
627
712
  // ../core/src/trust/index.ts
628
- import path4 from "path";
713
+ import path5 from "path";
629
714
  import fs3 from "fs/promises";
630
715
  var TRUSTED_FILE, normalizeDir, readTrustedDirs, isTrustedDir, trustDir, untrustDir;
631
716
  var init_trust = __esm({
@@ -633,9 +718,9 @@ var init_trust = __esm({
633
718
  "use strict";
634
719
  init_config();
635
720
  init_common();
636
- TRUSTED_FILE = path4.join(appConfig.dataDir, "trusted_dirs.json");
721
+ TRUSTED_FILE = path5.join(appConfig.dataDir, "trusted_dirs.json");
637
722
  normalizeDir = (dir) => {
638
- let d = path4.resolve(dir).replace(/\\/g, "/");
723
+ let d = path5.resolve(dir).replace(/\\/g, "/");
639
724
  if (/^[a-z]:/i.test(d)) d = d.charAt(0).toUpperCase() + d.slice(1);
640
725
  return d;
641
726
  };
@@ -978,7 +1063,7 @@ var init_replay = __esm({
978
1063
  });
979
1064
 
980
1065
  // ../core/src/llm/model.ts
981
- import { readFileSync as readFileSync3 } from "fs";
1066
+ import { readFileSync as readFileSync4 } from "fs";
982
1067
  var resolveInitialProvider, activeProvider, chatWithModelWithSummary, classifyToolRisk;
983
1068
  var init_model = __esm({
984
1069
  "../core/src/llm/model.ts"() {
@@ -993,7 +1078,7 @@ var init_model = __esm({
993
1078
  }
994
1079
  let raw;
995
1080
  try {
996
- raw = JSON.parse(readFileSync3(scriptPath, "utf-8"));
1081
+ raw = JSON.parse(readFileSync4(scriptPath, "utf-8"));
997
1082
  } catch (e) {
998
1083
  throw new Error(`\u56DE\u653E\u5267\u672C\u52A0\u8F7D\u5931\u8D25\uFF08${scriptPath}\uFF09: ${e?.message ?? e}`);
999
1084
  }
@@ -1113,7 +1198,7 @@ __export(store_exports, {
1113
1198
  writeStore: () => writeStore
1114
1199
  });
1115
1200
  import fs4 from "fs/promises";
1116
- import path5 from "path";
1201
+ import path6 from "path";
1117
1202
  async function getRollingState(sessionId) {
1118
1203
  const store = await readStore(sessionId);
1119
1204
  if (!store) {
@@ -1160,16 +1245,16 @@ var init_store = __esm({
1160
1245
  getSessionsDirPath = (mainSessionId) => {
1161
1246
  assertSafeSessionId(mainSessionId);
1162
1247
  const fileName = getFileName(mainSessionId);
1163
- return path5.join(appConfig.dataDir, "sessions", appConfig.userWorkspaceDir, fileName);
1248
+ return path6.join(appConfig.dataDir, "sessions", appConfig.userWorkspaceDir, fileName);
1164
1249
  };
1165
- getWorkspaceSessionsDir = () => path5.join(appConfig.dataDir, "sessions", appConfig.userWorkspaceDir);
1250
+ getWorkspaceSessionsDir = () => path6.join(appConfig.dataDir, "sessions", appConfig.userWorkspaceDir);
1166
1251
  getStatePath = (sessionId) => {
1167
1252
  assertSafeSessionId(sessionId);
1168
- return path5.join(getSessionsDirPath(sessionId), `${sessionId}.state.json`);
1253
+ return path6.join(getSessionsDirPath(sessionId), `${sessionId}.state.json`);
1169
1254
  };
1170
1255
  getTranscriptPath = (sessionId) => {
1171
1256
  assertSafeSessionId(sessionId);
1172
- return path5.join(getSessionsDirPath(sessionId), `${sessionId}.jsonl`);
1257
+ return path6.join(getSessionsDirPath(sessionId), `${sessionId}.jsonl`);
1173
1258
  };
1174
1259
  ensureSessionsDir = async (sessionId) => {
1175
1260
  await fs4.mkdir(getSessionsDirPath(sessionId), { recursive: true });
@@ -1179,7 +1264,7 @@ var init_store = __esm({
1179
1264
  migrateLegacyFiles = async (sessionId) => {
1180
1265
  assertSafeSessionId(sessionId);
1181
1266
  const dir = getSessionsDirPath(sessionId);
1182
- const legacy = path5.join(dir, `${sessionId}.json`);
1267
+ const legacy = path6.join(dir, `${sessionId}.json`);
1183
1268
  const transcriptPath = getTranscriptPath(sessionId);
1184
1269
  const statePath = getStatePath(sessionId);
1185
1270
  let legacyText;
@@ -1304,7 +1389,7 @@ var init_store = __esm({
1304
1389
  if (!entry.isDirectory()) continue;
1305
1390
  const sessionId = entry.name;
1306
1391
  if (!isSafeSessionId(sessionId)) continue;
1307
- const dirPath = path5.join(root, sessionId);
1392
+ const dirPath = path6.join(root, sessionId);
1308
1393
  const state = await readJSONFile(getStatePath(sessionId));
1309
1394
  let messageCount = 0;
1310
1395
  let preview = "";
@@ -1481,7 +1566,7 @@ var init_types = __esm({
1481
1566
 
1482
1567
  // ../core/src/hooks/shellExecutor.ts
1483
1568
  import { spawn } from "child_process";
1484
- import path6 from "path";
1569
+ import path7 from "path";
1485
1570
  var MAX_OUTPUT, DEFAULT_TIMEOUT_MS, HARD_TIMEOUT_CAP_MS, ENV_WHITELIST, truncate, MAX_STDIN_FIELD, capFieldStrings, extractFilePath, executeHookCommand;
1486
1571
  var init_shellExecutor = __esm({
1487
1572
  "../core/src/hooks/shellExecutor.ts"() {
@@ -1527,7 +1612,7 @@ var init_shellExecutor = __esm({
1527
1612
  if (typeof rel !== "string" || !rel.trim()) return void 0;
1528
1613
  const base = typeof p.cwd === "string" && p.cwd || process.env.WORKSPACE_ROOT || process.cwd();
1529
1614
  try {
1530
- return path6.resolve(base, rel);
1615
+ return path7.resolve(base, rel);
1531
1616
  } catch {
1532
1617
  return void 0;
1533
1618
  }
@@ -1732,7 +1817,7 @@ var init_hooks = __esm({
1732
1817
  });
1733
1818
 
1734
1819
  // ../core/src/agent/truncate.ts
1735
- import path7 from "path";
1820
+ import path8 from "path";
1736
1821
  function stripAnsi(text) {
1737
1822
  return text.replace(ANSI_ESCAPE, "");
1738
1823
  }
@@ -1771,10 +1856,10 @@ var init_truncate = __esm({
1771
1856
  if (!text) return text;
1772
1857
  const roots = /* @__PURE__ */ new Set();
1773
1858
  try {
1774
- roots.add(path7.resolve(appConfig.userWorkspaceDir));
1859
+ roots.add(path8.resolve(appConfig.userWorkspaceDir));
1775
1860
  for (const r of getFileAccessRoots()) {
1776
1861
  try {
1777
- roots.add(path7.resolve(r));
1862
+ roots.add(path8.resolve(r));
1778
1863
  } catch {
1779
1864
  }
1780
1865
  }
@@ -2041,7 +2126,7 @@ ${line}` : line;
2041
2126
 
2042
2127
  // ../core/src/tool/permissions.ts
2043
2128
  import fs6 from "fs/promises";
2044
- import path8 from "path";
2129
+ import path9 from "path";
2045
2130
  var PRIMARY_ARG, rules2, trustedProject, globCache, globToRegex, DANGER_COMMAND_TOOLS, compileRule, readPermissionConfig, toolNameMatches, ruleMatches, initPermissions, checkPermission, listPermissionRules, buildScopedAllowRule, resolveSettingsPath, addPermissionRule;
2046
2131
  var init_permissions = __esm({
2047
2132
  "../core/src/tool/permissions.ts"() {
@@ -2103,9 +2188,9 @@ var init_permissions = __esm({
2103
2188
  readPermissionConfig = async (includeProject) => {
2104
2189
  const merged = { allow: [], deny: [], ask: [] };
2105
2190
  const paths = [
2106
- path8.join(appConfig.dataDir, "settings.json"),
2191
+ path9.join(appConfig.dataDir, "settings.json"),
2107
2192
  // 全局用户级
2108
- ...includeProject ? [path8.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
2193
+ ...includeProject ? [path9.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
2109
2194
  // 项目级(叠加);未信任时省略
2110
2195
  ];
2111
2196
  for (const configPath of paths) {
@@ -2196,7 +2281,7 @@ var init_permissions = __esm({
2196
2281
  }
2197
2282
  return `${toolName}(${val})`;
2198
2283
  };
2199
- resolveSettingsPath = (scope) => scope === "global" ? path8.join(appConfig.dataDir, "settings.json") : path8.join(process.cwd(), ".deepseeker-code", "settings.json");
2284
+ resolveSettingsPath = (scope) => scope === "global" ? path9.join(appConfig.dataDir, "settings.json") : path9.join(process.cwd(), ".deepseeker-code", "settings.json");
2200
2285
  addPermissionRule = async (scope, kind, ruleStr) => {
2201
2286
  if (scope === "project" && !trustedProject) return false;
2202
2287
  const compiled = compileRule(ruleStr, `runtime:addPermissionRule(${scope})`, kind);
@@ -2208,7 +2293,7 @@ var init_permissions = __esm({
2208
2293
  const arr = Array.isArray(cfg.permissions[kind]) ? cfg.permissions[kind] : cfg.permissions[kind] = [];
2209
2294
  if (!arr.includes(ruleStr)) {
2210
2295
  arr.push(ruleStr);
2211
- await fs6.mkdir(path8.dirname(file), { recursive: true });
2296
+ await fs6.mkdir(path9.dirname(file), { recursive: true });
2212
2297
  await atomicWriteJSON(file, cfg);
2213
2298
  }
2214
2299
  if (!rules2[kind].some((r) => r.raw === compiled.raw)) rules2[kind].push(compiled);
@@ -2248,7 +2333,7 @@ var init_sessionRegistry = __esm({
2248
2333
  // ../core/src/tool/guard.ts
2249
2334
  import fs7 from "fs/promises";
2250
2335
  import fsSync from "fs";
2251
- import path9 from "path";
2336
+ import path10 from "path";
2252
2337
  import ignore from "ignore";
2253
2338
  import { AsyncLocalStorage } from "node:async_hooks";
2254
2339
  var WORKSPACE_ROOT, workspaceAls, getActiveWorkspaceRoot, runWithWorkspaceRoot, runWithSessionContext, BUILTIN_IGNORE_RULES, ignoreCache, ignoreBuilding, allowedRootsReal, getAllowedWorkspaceRoots, getContainingRoot, allowedBoundaryRoots, resolveSafePath, resolveReadablePath, assertWithinWorkspace, PROTECTED_WRITE_DIRS, COMMAND_ENV_DENYLIST, SENSITIVE_ENV_PATTERN, scrubCommandEnv, isProtectedWrite, scanIgnoreFilesRecursive, buildIgnoreEngine, getIgnoreForBase, initializeWorkspaceIgnore, checkIsPathIgnored, requestApproval;
@@ -2304,8 +2389,8 @@ var init_guard = __esm({
2304
2389
  getContainingRoot = (absPath) => {
2305
2390
  let best;
2306
2391
  for (const r of allowedBoundaryRoots()) {
2307
- const rel = path9.relative(r, absPath);
2308
- if (!rel.startsWith("..") && !path9.isAbsolute(rel)) {
2392
+ const rel = path10.relative(r, absPath);
2393
+ if (!rel.startsWith("..") && !path10.isAbsolute(rel)) {
2309
2394
  if (!best || r.length > best.length) best = r;
2310
2395
  }
2311
2396
  }
@@ -2322,16 +2407,16 @@ var init_guard = __esm({
2322
2407
  };
2323
2408
  resolveSafePath = (rel, base) => {
2324
2409
  const root = base ?? getActiveWorkspaceRoot();
2325
- const candidateAbsPath = path9.resolve(root, rel);
2410
+ const candidateAbsPath = path10.resolve(root, rel);
2326
2411
  let truePhysicalPath = candidateAbsPath;
2327
2412
  try {
2328
2413
  if (fsSync.existsSync(candidateAbsPath)) {
2329
2414
  truePhysicalPath = fsSync.realpathSync(candidateAbsPath);
2330
2415
  } else {
2331
- const parentDir = path9.dirname(candidateAbsPath);
2416
+ const parentDir = path10.dirname(candidateAbsPath);
2332
2417
  if (fsSync.existsSync(parentDir)) {
2333
2418
  const trueParentDir = fsSync.realpathSync(parentDir);
2334
- truePhysicalPath = path9.join(trueParentDir, path9.basename(candidateAbsPath));
2419
+ truePhysicalPath = path10.join(trueParentDir, path10.basename(candidateAbsPath));
2335
2420
  }
2336
2421
  }
2337
2422
  } catch (e) {
@@ -2345,8 +2430,8 @@ var init_guard = __esm({
2345
2430
  }
2346
2431
  })() : allowedBoundaryRoots();
2347
2432
  const escaped = boundaryRoots.every((r) => {
2348
- const rel0 = path9.relative(r, truePhysicalPath);
2349
- return rel0.startsWith("..") || path9.isAbsolute(rel0);
2433
+ const rel0 = path10.relative(r, truePhysicalPath);
2434
+ return rel0.startsWith("..") || path10.isAbsolute(rel0);
2350
2435
  });
2351
2436
  if (escaped) {
2352
2437
  throw new Error(`\u{1F6D1} [SECURITY ALERT] \u68C0\u6D4B\u5230\u6076\u610F\u7684\u7269\u7406\u8DEF\u5F84\u8DE8\u754C\u9003\u9038\uFF01\u62D2\u7EDD\u8BBF\u95EE\uFF1A${rel}`);
@@ -2355,12 +2440,12 @@ var init_guard = __esm({
2355
2440
  };
2356
2441
  resolveReadablePath = (rel) => {
2357
2442
  const root = getActiveWorkspaceRoot();
2358
- const absPath = path9.resolve(root, rel);
2443
+ const absPath = path10.resolve(root, rel);
2359
2444
  if (!fsSync.existsSync(absPath)) {
2360
- const rootName = path9.basename(root);
2445
+ const rootName = path10.basename(root);
2361
2446
  const firstSeg = rel.split(/[\\/]/)[0];
2362
2447
  if (rootName && firstSeg === rootName) {
2363
- const alt = path9.resolve(root, rel.slice(firstSeg.length + 1));
2448
+ const alt = path10.resolve(root, rel.slice(firstSeg.length + 1));
2364
2449
  if (fsSync.existsSync(alt)) return alt;
2365
2450
  }
2366
2451
  }
@@ -2373,9 +2458,9 @@ var init_guard = __esm({
2373
2458
  if (fsSync.existsSync(absPath)) {
2374
2459
  truePhysicalPath = fsSync.realpathSync(absPath);
2375
2460
  } else {
2376
- const parentDir = path9.dirname(absPath);
2461
+ const parentDir = path10.dirname(absPath);
2377
2462
  if (fsSync.existsSync(parentDir)) {
2378
- truePhysicalPath = path9.join(fsSync.realpathSync(parentDir), path9.basename(absPath));
2463
+ truePhysicalPath = path10.join(fsSync.realpathSync(parentDir), path10.basename(absPath));
2379
2464
  }
2380
2465
  }
2381
2466
  } catch (e) {
@@ -2389,8 +2474,8 @@ var init_guard = __esm({
2389
2474
  }
2390
2475
  })() : allowedBoundaryRoots();
2391
2476
  const escaped = boundaryRoots.every((r) => {
2392
- const rel0 = path9.relative(r, truePhysicalPath);
2393
- return rel0.startsWith("..") || path9.isAbsolute(rel0);
2477
+ const rel0 = path10.relative(r, truePhysicalPath);
2478
+ return rel0.startsWith("..") || path10.isAbsolute(rel0);
2394
2479
  });
2395
2480
  if (escaped) {
2396
2481
  throw new Error(`\u{1F6D1} [SECURITY ALERT] \u4E8C\u6B21\u56F4\u680F\u590D\u68C0\u53D1\u73B0\u8D8A\u754C\uFF08\u7591\u4F3C TOCTOU \u8F6F\u94FE\u63A5\u9003\u9038\uFF09\uFF1A${absPath}`);
@@ -2417,7 +2502,7 @@ var init_guard = __esm({
2417
2502
  if (!relOrAbs) return false;
2418
2503
  try {
2419
2504
  const base = cwd || process.env.WORKSPACE_ROOT || process.cwd();
2420
- const abs = path9.isAbsolute(relOrAbs) ? relOrAbs : path9.resolve(base, relOrAbs);
2505
+ const abs = path10.isAbsolute(relOrAbs) ? relOrAbs : path10.resolve(base, relOrAbs);
2421
2506
  const lower = abs.replace(/\\/g, "/").toLowerCase();
2422
2507
  return PROTECTED_WRITE_DIRS.some((d) => {
2423
2508
  const seg = ("/" + d).toLowerCase();
@@ -2432,9 +2517,9 @@ var init_guard = __esm({
2432
2517
  const entries = await fs7.readdir(dirPath, { withFileTypes: true });
2433
2518
  for (const entry of entries) {
2434
2519
  if (entry.isFile() && (entry.name === ".gitignore" || entry.name === ".agentignore")) {
2435
- const fullPath = path9.join(dirPath, entry.name);
2520
+ const fullPath = path10.join(dirPath, entry.name);
2436
2521
  const content = await fs7.readFile(fullPath, "utf-8");
2437
- const relDir = path9.relative(base, dirPath).replace(/\\/g, "/");
2522
+ const relDir = path10.relative(base, dirPath).replace(/\\/g, "/");
2438
2523
  const rules3 = content.split(/\r?\n/).map((line) => {
2439
2524
  const trimmed = line.trim();
2440
2525
  if (!trimmed || trimmed.startsWith("#")) return "";
@@ -2445,7 +2530,7 @@ var init_guard = __esm({
2445
2530
  }
2446
2531
  for (const entry of entries) {
2447
2532
  if (entry.isDirectory() && entry.name !== "node_modules" && entry.name !== ".git") {
2448
- await scanIgnoreFilesRecursive(path9.join(dirPath, entry.name), base, engine);
2533
+ await scanIgnoreFilesRecursive(path10.join(dirPath, entry.name), base, engine);
2449
2534
  }
2450
2535
  }
2451
2536
  } catch {
@@ -2516,7 +2601,7 @@ var init_guard = __esm({
2516
2601
  // ../core/src/tool/registry/background.ts
2517
2602
  import { spawn as spawn2, execFileSync } from "child_process";
2518
2603
  import fsSync2 from "fs";
2519
- import path10 from "path";
2604
+ import path11 from "path";
2520
2605
  function appendOutput(task, chunk) {
2521
2606
  task.outputBuffer += chunk;
2522
2607
  if (task.outputBuffer.length > MAX_BUFFER_CHARS) {
@@ -2541,7 +2626,7 @@ async function killTree(proc) {
2541
2626
  }
2542
2627
  }
2543
2628
  async function killBackgroundTasksUnder(dirPath) {
2544
- const norm = (p) => path10.resolve(p).replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
2629
+ const norm = (p) => path11.resolve(p).replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
2545
2630
  const target = norm(dirPath);
2546
2631
  let killed = 0;
2547
2632
  for (const task of registry.values()) {
@@ -2586,9 +2671,9 @@ var init_background = __esm({
2586
2671
  if (envShell && envShell.toLowerCase() !== "cmd") candidates.push(envShell);
2587
2672
  const gitExe = whereLines("git")[0];
2588
2673
  if (gitExe) {
2589
- const dir = path10.dirname(gitExe);
2590
- const root = path10.dirname(dir);
2591
- candidates.push(path10.join(root, "bin", "bash.exe"), path10.join(dir, "bash.exe"), path10.join(path10.dirname(root), "bin", "bash.exe"));
2674
+ const dir = path11.dirname(gitExe);
2675
+ const root = path11.dirname(dir);
2676
+ candidates.push(path11.join(root, "bin", "bash.exe"), path11.join(dir, "bash.exe"), path11.join(path11.dirname(root), "bin", "bash.exe"));
2592
2677
  }
2593
2678
  const bashHits = whereLines("bash").filter((p) => !/\\System32\\/i.test(p)).sort((a, b) => Number(/\\Git\\/i.test(b)) - Number(/\\Git\\/i.test(a)));
2594
2679
  candidates.push(...bashHits);
@@ -2729,12 +2814,13 @@ task_id: ${taskId}
2729
2814
  type: "function",
2730
2815
  function: {
2731
2816
  name: "get_background_output",
2732
- description: "\u67E5\u770B\u6307\u5B9A\u540E\u53F0\u4EFB\u52A1\u7684\u6700\u8FD1\u8F93\u51FA\u65E5\u5FD7\u4E0E\u8FD0\u884C\u72B6\u6001\uFF08running/exited/killed + \u9000\u51FA\u7801\uFF09\u3002\u7EAF\u8BFB\uFF0C\u514D\u5BA1\u6279\u3002\u7528\u4E8E\u786E\u8BA4 dev server \u662F\u5426\u542F\u52A8\u6210\u529F\u3001\u67E5\u770B\u62A5\u9519\u7B49\u3002",
2817
+ description: "\u67E5\u770B\u6307\u5B9A\u540E\u53F0\u4EFB\u52A1\u7684\u6700\u8FD1\u8F93\u51FA\u65E5\u5FD7\u4E0E\u8FD0\u884C\u72B6\u6001\uFF08running/exited/killed + \u9000\u51FA\u7801\uFF09\u3002\u7EAF\u8BFB\uFF0C\u514D\u5BA1\u6279\u3002\u7528\u4E8E\u786E\u8BA4 dev server \u662F\u5426\u542F\u52A8\u6210\u529F\u3001\u67E5\u770B\u62A5\u9519\u7B49\u3002\u7B49\u957F\u4EFB\u52A1\uFF08\u6784\u5EFA/\u6D4B\u8BD5\uFF09\u8DD1\u5B8C\uFF1A\u5E26 wait_seconds \u963B\u585E\u7B49\u5F85\u4EFB\u52A1\u9000\u51FA\u540E\u518D\u8FD4\u56DE\uFF08\u4ECD\u5728\u8DD1\u5219\u7B49\u5230\u8D85\u65F6\u8FD4\u56DE\u5F53\u524D\u72B6\u6001\uFF09\u2014\u2014\u7528\u5B83\u7B49\uFF0C\u4E0D\u8981\u4E0D\u5E26 wait \u53CD\u590D\u8F6E\u8BE2\u67E5\u8BE2\u3002",
2733
2818
  parameters: {
2734
2819
  type: "object",
2735
2820
  properties: {
2736
2821
  task_id: { type: "string", description: "run_in_background \u8FD4\u56DE\u7684 task_id" },
2737
- tail_lines: { type: "number", description: "\u53EA\u8FD4\u56DE\u6700\u540E N \u884C\u65E5\u5FD7\uFF08\u9ED8\u8BA4 50\uFF0C\u907F\u514D\u4E00\u6B21\u704C\u5165\u8FC7\u591A\uFF09" }
2822
+ tail_lines: { type: "number", description: "\u53EA\u8FD4\u56DE\u6700\u540E N \u884C\u65E5\u5FD7\uFF08\u9ED8\u8BA4 50\uFF0C\u907F\u514D\u4E00\u6B21\u704C\u5165\u8FC7\u591A\uFF09" },
2823
+ wait_seconds: { type: "number", description: "\u963B\u585E\u7B49\u5F85\u4EFB\u52A1\u9000\u51FA\uFF08\u6216\u5230\u8FBE\u6B64\u65F6\u957F\uFF09\u540E\u518D\u8FD4\u56DE\uFF0C\u4E0A\u9650 120 \u79D2\uFF1B\u4EFB\u52A1\u5DF2\u5728\u8DD1\u4E14\u9700\u8981\u7B49\u7ED3\u679C\u65F6\u4F7F\u7528\uFF0C\u4E0D\u9700\u8981\u7B49\u5C31\u7701\u7565" }
2738
2824
  },
2739
2825
  required: ["task_id"]
2740
2826
  },
@@ -2745,6 +2831,13 @@ task_id: ${taskId}
2745
2831
  if (!task || task.sessionId !== ctx?.sessionId) {
2746
2832
  return `\u274C [\u67E5\u8BE2\u5931\u8D25]\uFF1A\u672A\u627E\u5230 task_id=${args.task_id}\uFF08\u53EF\u80FD\u5DF2\u968F\u670D\u52A1\u91CD\u542F\u4E22\u5931\uFF0C\u6216\u4E0D\u5C5E\u4E8E\u5F53\u524D\u4F1A\u8BDD\uFF09\u3002`;
2747
2833
  }
2834
+ const waitMs = Math.min(Math.max(0, args.wait_seconds ?? 0), 120) * 1e3;
2835
+ if (waitMs > 0 && task.status === "running") {
2836
+ const deadline = Date.now() + waitMs;
2837
+ while (task.status === "running" && Date.now() < deadline && !ctx?.abortSignal?.aborted) {
2838
+ await new Promise((r) => setTimeout(r, 500));
2839
+ }
2840
+ }
2748
2841
  const tail = Math.max(1, args.tail_lines ?? 50);
2749
2842
  const allLines = task.outputBuffer.split("\n");
2750
2843
  const tailText = allLines.slice(-tail).join("\n").trim();
@@ -3331,13 +3424,13 @@ ${capped || JSON.stringify(result)}`;
3331
3424
 
3332
3425
  // ../core/src/tool/mcp/loader.ts
3333
3426
  import fs8 from "fs/promises";
3334
- import path11 from "path";
3427
+ import path12 from "path";
3335
3428
  import { homedir } from "os";
3336
3429
  function sanitize(s) {
3337
3430
  return s.replace(/[^a-zA-Z0-9_]/g, "_");
3338
3431
  }
3339
3432
  async function readMcpConfig() {
3340
- const configPath = process.env.MCP_CONFIG || path11.join(appConfig.dataDir, "mcp.json");
3433
+ const configPath = process.env.MCP_CONFIG || path12.join(appConfig.dataDir, "mcp.json");
3341
3434
  let raw;
3342
3435
  try {
3343
3436
  raw = await fs8.readFile(configPath, "utf-8");
@@ -3807,26 +3900,31 @@ var init_repeatBreaker = __esm({
3807
3900
  const recentSignatures = [];
3808
3901
  const recentPollTargets = [];
3809
3902
  const POLL_TARGET_KEYS = { get_background_output: ["task_id"] };
3903
+ const parseArgs2 = (tc) => {
3904
+ try {
3905
+ return JSON.parse(tc?.function?.arguments || "{}") ?? {};
3906
+ } catch {
3907
+ return {};
3908
+ }
3909
+ };
3810
3910
  const pollTarget = (tc) => {
3811
3911
  const name = tc?.function?.name;
3812
3912
  const keys = name ? POLL_TARGET_KEYS[name] : void 0;
3813
3913
  if (!keys) return null;
3814
- let args = {};
3815
- try {
3816
- args = JSON.parse(tc?.function?.arguments || "{}");
3817
- } catch {
3818
- }
3914
+ const args = parseArgs2(tc);
3819
3915
  const picked = {};
3820
3916
  for (const k of keys) if (k in args) picked[k] = args[k];
3821
3917
  return `${name}:${JSON.stringify(picked)}`;
3822
3918
  };
3919
+ const isWaitPoll = (tc) => tc?.function?.name === "get_background_output" && Number(parseArgs2(tc).wait_seconds ?? 0) > 0;
3823
3920
  const check = (toolCalls, round, lastContent) => {
3824
- const sig = toolCalls.map((t) => `${t.function.name}:${t.function.arguments}`).join("|");
3921
+ const effCalls = toolCalls.filter((t) => !isWaitPoll(t));
3922
+ const sig = effCalls.map((t) => `${t.function.name}:${t.function.arguments}`).join("|");
3825
3923
  const tooName = toolCalls.map((t) => `${t.function.name}`).join("|");
3826
3924
  recentSignatures.push(sig);
3827
3925
  if (recentSignatures.length > 6) recentSignatures.shift();
3828
3926
  const last3 = recentSignatures.slice(-3);
3829
- if (last3.length === 3 && last3.every((s) => s === last3[0])) {
3927
+ if (sig && last3.length === 3 && last3.every((s) => s === sig)) {
3830
3928
  const text = (lastContent || "") + "\n\uFF08\u68C0\u6D4B\u5230\u91CD\u590D\u5DE5\u5177\u8C03\u7528\uFF0C\u5DF2\u505C\u6B62\uFF09";
3831
3929
  events({
3832
3930
  sessionId,
@@ -3845,31 +3943,28 @@ var init_repeatBreaker = __esm({
3845
3943
  });
3846
3944
  return { tripped: true, kind: "full", text, toolName: tooName };
3847
3945
  }
3848
- const pollTargets = toolCalls.map(pollTarget).filter(Boolean);
3849
- if (pollTargets.length) {
3850
- const pollSig = pollTargets.join("|");
3851
- recentPollTargets.push(pollSig);
3852
- if (recentPollTargets.length > 8) recentPollTargets.shift();
3853
- const last4 = recentPollTargets.slice(-4);
3854
- if (last4.length === 4 && last4.every((s) => s === last4[0])) {
3855
- const text = (lastContent || "") + "\n\uFF08\u68C0\u6D4B\u5230\u540E\u53F0\u4EFB\u52A1\u8F6E\u8BE2\u6B7B\u5FAA\u73AF\uFF08\u53CD\u590D\u67E5\u8BE2\u540C\u4E00\u4EFB\u52A1\uFF09\uFF0C\u5DF2\u505C\u6B62\uFF09";
3856
- events({
3857
- sessionId,
3858
- eventType: "tool.repeat_break",
3859
- metadata: {
3860
- depth,
3861
- decisionSource: llmDecisionSource,
3862
- durationMs: performance.now() - startTime,
3863
- round,
3864
- toolName: tooName,
3865
- toolSource: "builtin",
3866
- ok: false,
3867
- attempt: round
3868
- },
3869
- payload: { output: text }
3870
- });
3871
- return { tripped: true, kind: "names", text, toolName: tooName };
3872
- }
3946
+ const pollSig = effCalls.map(pollTarget).filter(Boolean).join("|");
3947
+ recentPollTargets.push(pollSig);
3948
+ if (recentPollTargets.length > 8) recentPollTargets.shift();
3949
+ const last4 = recentPollTargets.slice(-4);
3950
+ if (pollSig && last4.length === 4 && last4.every((s) => s === pollSig)) {
3951
+ const text = (lastContent || "") + "\n\uFF08\u68C0\u6D4B\u5230\u540E\u53F0\u4EFB\u52A1\u8F6E\u8BE2\u6B7B\u5FAA\u73AF\uFF08\u53CD\u590D\u67E5\u8BE2\u540C\u4E00\u4EFB\u52A1\uFF09\uFF0C\u5DF2\u505C\u6B62\uFF09";
3952
+ events({
3953
+ sessionId,
3954
+ eventType: "tool.repeat_break",
3955
+ metadata: {
3956
+ depth,
3957
+ decisionSource: llmDecisionSource,
3958
+ durationMs: performance.now() - startTime,
3959
+ round,
3960
+ toolName: tooName,
3961
+ toolSource: "builtin",
3962
+ ok: false,
3963
+ attempt: round
3964
+ },
3965
+ payload: { output: text }
3966
+ });
3967
+ return { tripped: true, kind: "names", text, toolName: tooName };
3873
3968
  }
3874
3969
  events({
3875
3970
  sessionId,
@@ -4112,7 +4207,7 @@ ${AGENT_USAGE_HINT}`);
4112
4207
 
4113
4208
  // ../core/src/projectGuide/loader.ts
4114
4209
  import fs10 from "fs/promises";
4115
- import path12 from "path";
4210
+ import path13 from "path";
4116
4211
  var CANDIDATES, MAX_GUIDE_BYTES, cached, initProjectGuide, getProjectGuide;
4117
4212
  var init_loader2 = __esm({
4118
4213
  "../core/src/projectGuide/loader.ts"() {
@@ -4129,7 +4224,7 @@ var init_loader2 = __esm({
4129
4224
  try {
4130
4225
  for (const name of CANDIDATES) {
4131
4226
  try {
4132
- const raw = await fs10.readFile(path12.join(WORKSPACE_ROOT, name), "utf-8");
4227
+ const raw = await fs10.readFile(path13.join(WORKSPACE_ROOT, name), "utf-8");
4133
4228
  const body = raw.length > MAX_GUIDE_BYTES ? raw.slice(0, MAX_GUIDE_BYTES) + `
4134
4229
 
4135
4230
  \u2026[\u9879\u76EE\u6307\u5F15\u8D85 ${MAX_GUIDE_BYTES} \u5B57\u8282\u5DF2\u622A\u65AD\uFF0C\u5B8C\u6574\u5185\u5BB9\u53EF\u8C03\u7528 read_project_guide \u83B7\u53D6]` : raw;
@@ -4287,10 +4382,23 @@ var init_systemInjections = __esm({
4287
4382
  function: { name: t.function.name, description: t.function.description, parameters: t.function.parameters }
4288
4383
  }));
4289
4384
  ensureSummarySlot(message);
4290
- if (locale2) {
4291
- const hint = locale2 === "zh" ? "\u8BF7\u59CB\u7EC8\u7528\u4E2D\u6587\u56DE\u590D\u7528\u6237\u3002" : "Always reply to the user in English.";
4292
- injectMarkedBlock(message, "\u27E6DSC:LOCALE\u27E7", hint);
4293
- }
4385
+ const LOCALE_HINTS = {
4386
+ zh: "\u59CB\u7EC8\u7528\u4E2D\u6587\u8F93\u51FA\u6240\u6709\u9762\u5411\u7528\u6237\u7684\u5185\u5BB9\uFF1A\u4F60\u7684\u56DE\u590D\u3001\u4E2D\u95F4\u53D9\u8FF0\u3001todo \u4EFB\u52A1\u9879\u6807\u9898\u3001\u901A\u8FC7 exit_plan_mode \u63D0\u4EA4\u7684\u65B9\u6848\u6587\u672C\u3001\u4EE3\u7801\u6CE8\u91CA\u4E0E\u63D0\u4EA4\u4FE1\u606F\u3002\u4EE3\u7801\u6807\u8BC6\u7B26\u4FDD\u6301\u539F\u6837\uFF1B\u5DE5\u5177\u7ED3\u679C\u4E0E\u7CFB\u7EDF\u6307\u4EE4\u53EF\u80FD\u5939\u6742\u5176\u4ED6\u8BED\u8A00\u2014\u2014\u5FC5\u8981\u65F6\u7167\u5F15\u539F\u6587\uFF0C\u4F46\u4F60\u81EA\u5DF1\u7684\u53D9\u8FF0\u4E0E\u89E3\u91CA\u4E00\u5F8B\u7528\u4E2D\u6587\u3002",
4387
+ en: "Always produce ALL user-facing output in English: your replies, interim narration, todo item titles, the plan text you submit via exit_plan_mode, code comments, and commit messages. Keep code identifiers as-is; tool results and system instructions may arrive in Chinese \u2014 quote them verbatim where needed, but your own narration and explanations must stay in English."
4388
+ };
4389
+ const lastUserText = (() => {
4390
+ for (let i = message.length - 1; i >= 0; i--) {
4391
+ const m = message[i];
4392
+ if (m?.role !== "user") continue;
4393
+ const c = m.content;
4394
+ if (typeof c === "string") return c;
4395
+ if (Array.isArray(c)) return c.filter((p) => typeof p?.text === "string").map((p) => p.text).join(" ");
4396
+ return "";
4397
+ }
4398
+ return "";
4399
+ })();
4400
+ const effLocale = detectTextLocale(lastUserText) ?? locale2;
4401
+ if (effLocale) injectMarkedBlock(message, "\u27E6DSC:LOCALE\u27E7", LOCALE_HINTS[effLocale]);
4294
4402
  injectOutputStyle(message, outputStyle);
4295
4403
  injectSkillCatalog(message);
4296
4404
  injectAgentCatalog(message);
@@ -4313,13 +4421,14 @@ var init_agent = __esm({
4313
4421
  type: "function",
4314
4422
  function: {
4315
4423
  name: "spawn_agent",
4316
- description: "\u521B\u5EFA\u4E00\u4E2A\u62E5\u6709\u72EC\u7ACB\u6267\u884C\u73AF\u5883\u7684\u5B50 agent \u5904\u7406\u9694\u79BB\u7684\u7279\u5B9A\u5B50\u4EFB\u52A1\uFF0C\u5B50\u4EFB\u52A1\u5B8C\u6210\u540E\u81EA\u52A8\u6C47\u603B\u6539\u52A8\u70B9\u4E0E\u7ED3\u8BBA\u8FD4\u56DE\u3002\u53EF\u901A\u8FC7 name \u6307\u5B9A\u58F0\u660E\u5F0F\u5B50 Agent\uFF08\u89C1\u7CFB\u7EDF\u63D0\u793A\u8BCD\u3010\u53EF\u7528\u5B50 Agent \u76EE\u5F55\u3011\uFF09\u4EE5\u5957\u7528\u5176\u4E13\u957F\u7CFB\u7EDF\u8BCD/\u5DE5\u5177\u767D\u540D\u5355/model\uFF1B\u4E0D\u4F20 name \u8D70\u9ED8\u8BA4\u901A\u7528\u5B50 agent\u3002",
4424
+ description: "\u521B\u5EFA\u4E00\u4E2A\u62E5\u6709\u72EC\u7ACB\u6267\u884C\u73AF\u5883\u7684\u5B50 agent \u5904\u7406\u9694\u79BB\u7684\u7279\u5B9A\u5B50\u4EFB\u52A1\uFF0C\u5B50\u4EFB\u52A1\u5B8C\u6210\u540E\u81EA\u52A8\u6C47\u603B\u6539\u52A8\u70B9\u4E0E\u7ED3\u8BBA\u8FD4\u56DE\u3002\u53EF\u901A\u8FC7 name \u6307\u5B9A\u58F0\u660E\u5F0F\u5B50 Agent\uFF08\u89C1\u7CFB\u7EDF\u63D0\u793A\u8BCD\u3010\u53EF\u7528\u5B50 Agent \u76EE\u5F55\u3011\uFF09\u4EE5\u5957\u7528\u5176\u4E13\u957F\u7CFB\u7EDF\u8BCD/\u5DE5\u5177\u767D\u540D\u5355/model\uFF1B\u4E0D\u4F20 name \u8D70\u9ED8\u8BA4\u901A\u7528\u5B50 agent\u3002\u652F\u6301\u7EED\u8DD1\uFF1A\u4F20 resume_session_id\uFF08\u6B64\u524D\u8FD4\u56DE\u7684 agent_id\uFF09\u590D\u7528\u8BE5\u5B50 Agent \u7684\u5B8C\u6574\u5386\u53F2\u8BB0\u5FC6\uFF0C\u9002\u5408\u8FFD\u95EE\u3001\u7EE7\u7EED\u672A\u5B8C\u6210\u7684\u4EFB\u52A1\u3002",
4317
4425
  parameters: {
4318
4426
  type: "object",
4319
4427
  properties: {
4320
- task: { type: "string", description: "\u4EA4\u7ED9\u5B50 agent \u7684\u5177\u4F53\u5FAE\u89C2\u4EFB\u52A1\u63CF\u8FF0\uFF08\u5982 '\u7F16\u5199 Button \u7EC4\u4EF6\u7684\u5355\u5143\u6D4B\u8BD5'\uFF09" },
4428
+ task: { type: "string", description: "\u4EA4\u7ED9\u5B50 agent \u7684\u5177\u4F53\u5FAE\u89C2\u4EFB\u52A1\u63CF\u8FF0\uFF08\u5982 '\u7F16\u5199 Button \u7EC4\u4EF6\u7684\u5355\u5143\u6D4B\u8BD5'\uFF09\uFF1B\u7EED\u8DD1\u65F6\u4E3A\u65B0\u6307\u4EE4\uFF08\u5982 '\u7EE7\u7EED\u5B8C\u6210\u5269\u4F59\u7528\u4F8B'\uFF09" },
4321
4429
  name: { type: "string", description: "\u58F0\u660E\u5F0F\u5B50 Agent \u540D\u79F0\uFF08\u987B\u4E0E\u7CFB\u7EDF\u63D0\u793A\u8BCD\u4E2D\u3010\u53EF\u7528\u5B50 Agent \u76EE\u5F55\u3011\u4E00\u81F4\uFF09\u3002\u63D0\u4F9B\u65F6\u6309\u5176\u58F0\u660E\u52A0\u8F7D\u7CFB\u7EDF\u8BCD/\u5DE5\u5177\u767D\u540D\u5355/model\uFF1B\u4E0D\u63D0\u4F9B\u5219\u8D70\u9ED8\u8BA4\u901A\u7528\u5B50 agent\u3002" },
4322
- role: { type: "string", description: "\u5B50 agent \u7684\u89D2\u8272/\u4E13\u957F\uFF08\u53EF\u9009\uFF0C\u5982 '\u6D4B\u8BD5\u4E13\u5BB6'\u3001'\u91CD\u6784\u5148\u950B'\uFF09\u3002\u58F0\u660E\u5F0F agent \u81EA\u5E26 role \u65F6\u4F5C\u8865\u5145\u3002" }
4430
+ role: { type: "string", description: "\u5B50 agent \u7684\u89D2\u8272/\u4E13\u957F\uFF08\u53EF\u9009\uFF0C\u5982 '\u6D4B\u8BD5\u4E13\u5BB6'\u3001'\u91CD\u6784\u5148\u950B'\uFF09\u3002\u58F0\u660E\u5F0F agent \u81EA\u5E26 role \u65F6\u4F5C\u8865\u5145\u3002" },
4431
+ resume_session_id: { type: "string", description: "\u7EED\u8DD1\u65E2\u6709\u5B50 Agent\uFF1A\u4F20\u6B64\u524D spawn_agent \u8FD4\u56DE\u7684 agent_id\uFF0C\u5176\u78C1\u76D8\u4E0A\u7684\u5386\u53F2\u4E0E\u8BB0\u5FC6\u5C06\u5B8C\u6574\u6062\u590D\u3002\u6CE8\u610F\uFF1A\u5B50 Agent \u72B6\u6001\u4E0D\u968F\u4E3B\u4F1A\u8BDD fork \u56DE\u6EDA\u2014\u2014fork \u53EA\u5206\u53C9\u5BF9\u8BDD\uFF0C\u7EED\u8DD1\u62FF\u5230\u7684\u662F\u5B50\u4F1A\u8BDD\u78C1\u76D8\u6700\u65B0\u72B6\u6001\u3002\u7F3A\u7701\u5219\u65B0\u5EFA\u5B50 Agent\u3002" }
4323
4432
  },
4324
4433
  required: ["task"]
4325
4434
  },
@@ -4327,10 +4436,17 @@ var init_agent = __esm({
4327
4436
  isSync: true,
4328
4437
  async execute(args, ctx) {
4329
4438
  if (!ctx) return "\u274C [\u6D3E\u751F\u5931\u8D25]\uFF1Aspawn_agent \u7F3A\u5C11\u5FC5\u987B\u7684\u667A\u80FD\u4F53\u8FD0\u884C\u4E0A\u4E0B\u6587\u3002";
4330
- const res = await runSubagent(args, ctx, getGlobalTools);
4439
+ const res = await runSubagent(
4440
+ { task: args.task, name: args.name, role: args.role, resumeSessionId: args.resume_session_id },
4441
+ ctx,
4442
+ getGlobalTools
4443
+ );
4331
4444
  if (!res.ok) return res.output;
4332
4445
  return [
4333
- `\u{1F389} [\u5B50 Agent \u6267\u884C\u5B8C\u6BD5] \u6D3E\u751F\u5B50\u4EFB\u52A1\u6C47\u62A5\u5982\u4E0B\uFF1A
4446
+ `\u{1F389} [\u5B50 Agent \u6267\u884C\u5B8C\u6BD5${args.resume_session_id ? "\xB7\u7EED\u8DD1" : ""}] \u6D3E\u751F\u5B50\u4EFB\u52A1\u6C47\u62A5\u5982\u4E0B\uFF1A
4447
+ `,
4448
+ `\u{1F194} agent_id: ${res.sessionId}
4449
+ \uFF08\u9700\u8981\u7EE7\u7EED\u8BE5\u5B50 Agent \u7684\u4EFB\u52A1\u6216\u8FFD\u95EE\u65F6\uFF0C\u8C03\u7528 spawn_agent \u4F20 resume_session_id=${res.sessionId}\uFF0C\u5176\u5386\u53F2\u8BB0\u5FC6\u5B8C\u6574\u4FDD\u7559\uFF09
4334
4450
  `,
4335
4451
  `==================================================
4336
4452
  `,
@@ -4349,8 +4465,8 @@ var init_agent = __esm({
4349
4465
  });
4350
4466
 
4351
4467
  // ../core/src/tool/worktree/manager.ts
4352
- import path13 from "path";
4353
- import os3 from "os";
4468
+ import path14 from "path";
4469
+ import os4 from "os";
4354
4470
  import fs11 from "fs";
4355
4471
  var runMainGit, worktreeRootDir, worktreeDir, isNotARepoError, createWorktree, harvestDiff, runInWorktree, removeWorktree, sweepOrphanedWorktrees, disposeAllSessionWorktrees;
4356
4472
  var init_manager = __esm({
@@ -4362,8 +4478,8 @@ var init_manager = __esm({
4362
4478
  init_background();
4363
4479
  init_sessionRegistry();
4364
4480
  runMainGit = (args, maxBuffer = 1024 * 1024 * 5) => execFileSmart("git", args, { cwd: WORKSPACE_ROOT, maxBuffer });
4365
- worktreeRootDir = () => path13.join(os3.tmpdir(), "deepseeker-code-worktrees", appConfig.userWorkspaceDir);
4366
- worktreeDir = (sessionId, stepId) => path13.join(worktreeRootDir(), sessionId, stepId);
4481
+ worktreeRootDir = () => path14.join(os4.tmpdir(), "deepseeker-code-worktrees", appConfig.userWorkspaceDir);
4482
+ worktreeDir = (sessionId, stepId) => path14.join(worktreeRootDir(), sessionId, stepId);
4367
4483
  isNotARepoError = (e) => {
4368
4484
  const text = `${e?.message || ""} ${e?.stderr || ""}`.toLowerCase();
4369
4485
  return text.includes("not a git repository");
@@ -4374,7 +4490,7 @@ var init_manager = __esm({
4374
4490
  const wtPath = worktreeDir(sessionId, stepId);
4375
4491
  const shortId = sessionId.replace(/[^A-Za-z0-9-]/g, "").slice(0, 8) || "x";
4376
4492
  const branch = `dsc-wt-${shortId}-${stepId}`;
4377
- await fs11.promises.mkdir(path13.dirname(wtPath), { recursive: true });
4493
+ await fs11.promises.mkdir(path14.dirname(wtPath), { recursive: true });
4378
4494
  try {
4379
4495
  await runMainGit(["worktree", "add", "-b", branch, wtPath, "HEAD"]);
4380
4496
  } catch (e) {
@@ -4450,7 +4566,7 @@ var init_manager = __esm({
4450
4566
  }
4451
4567
  let swept = 0;
4452
4568
  for (const sessionIdDir of entries) {
4453
- const sessionPath = path13.join(root, sessionIdDir);
4569
+ const sessionPath = path14.join(root, sessionIdDir);
4454
4570
  let stepDirs;
4455
4571
  try {
4456
4572
  stepDirs = await fs11.promises.readdir(sessionPath);
@@ -4458,7 +4574,7 @@ var init_manager = __esm({
4458
4574
  continue;
4459
4575
  }
4460
4576
  for (const stepDir of stepDirs) {
4461
- const wtPath = path13.join(sessionPath, stepDir);
4577
+ const wtPath = path14.join(sessionPath, stepDir);
4462
4578
  try {
4463
4579
  await runMainGit(["worktree", "remove", "--force", wtPath]);
4464
4580
  } catch {
@@ -4739,7 +4855,7 @@ var init_workflow = __esm({
4739
4855
 
4740
4856
  // ../core/src/tool/tsHost.ts
4741
4857
  import fsSync3 from "fs";
4742
- import path14 from "path";
4858
+ import path15 from "path";
4743
4859
  var _ts, _tsTried, getTs, buildDefaultOptions, findTsConfigBounded, resolveTsConfig, createProjectHost, lsCache, getLanguageService, realpathNative, posToLineCol, lineColToPos;
4744
4860
  var init_tsHost = __esm({
4745
4861
  "../core/src/tool/tsHost.ts"() {
@@ -4772,16 +4888,16 @@ var init_tsHost = __esm({
4772
4888
  strict: false
4773
4889
  });
4774
4890
  findTsConfigBounded = (ts, absPath) => {
4775
- const root = path14.resolve(getContainingRoot(absPath));
4776
- let dir = path14.dirname(absPath);
4891
+ const root = path15.resolve(getContainingRoot(absPath));
4892
+ let dir = path15.dirname(absPath);
4777
4893
  while (true) {
4778
- const candidate = path14.join(dir, "tsconfig.json");
4894
+ const candidate = path15.join(dir, "tsconfig.json");
4779
4895
  try {
4780
4896
  if (fsSync3.existsSync(candidate)) return candidate;
4781
4897
  } catch {
4782
4898
  }
4783
- if (path14.resolve(dir) === root) break;
4784
- const parent = path14.dirname(dir);
4899
+ if (path15.resolve(dir) === root) break;
4900
+ const parent = path15.dirname(dir);
4785
4901
  if (parent === dir) break;
4786
4902
  dir = parent;
4787
4903
  }
@@ -4792,7 +4908,7 @@ var init_tsHost = __esm({
4792
4908
  if (!tsConfigPath) {
4793
4909
  return { options: buildDefaultOptions(ts), fileNames: [], projectRoot: getContainingRoot(absPath) };
4794
4910
  }
4795
- const basePath = path14.dirname(tsConfigPath);
4911
+ const basePath = path15.dirname(tsConfigPath);
4796
4912
  const raw = ts.readConfigFile(tsConfigPath, ts.sys.readFile);
4797
4913
  if (raw.error) return { options: buildDefaultOptions(ts), fileNames: [], projectRoot: basePath };
4798
4914
  const parsed = ts.parseJsonConfigFileContent(raw.config, ts.sys, basePath);
@@ -4803,7 +4919,7 @@ var init_tsHost = __esm({
4803
4919
  const roots = /* @__PURE__ */ new Set();
4804
4920
  const caseSensitive = ts.sys.useCaseSensitiveFileNames;
4805
4921
  const canonical = (f) => caseSensitive ? f : f.toLowerCase();
4806
- const keyOf = (f) => canonical(path14.resolve(f)).replace(/\\/g, "/");
4922
+ const keyOf = (f) => canonical(path15.resolve(f)).replace(/\\/g, "/");
4807
4923
  rootFileNames.forEach((f) => roots.add(keyOf(f)));
4808
4924
  const fresh = (fileName) => {
4809
4925
  const key = keyOf(fileName);
@@ -4892,7 +5008,7 @@ var init_tsHost = __esm({
4892
5008
 
4893
5009
  // ../core/src/tool/registry/fs.ts
4894
5010
  import fs12 from "fs/promises";
4895
- import path15 from "path";
5011
+ import path16 from "path";
4896
5012
  import { createReadStream } from "fs";
4897
5013
  import * as readline from "readline";
4898
5014
  var isSensitiveReadTarget, stripReadFileLineNumbers, maskSecretsInContent, makeTmpPath, ATOMIC_TMP_RE, sweepStaleAtomicTmp, assertReadable, stripEdgeBlankLines, matchLineBlockWith, diagnoseOldStr, reindentToBase, alignIndentsByAnchor, applyOneEditToContent, fsTools;
@@ -4953,7 +5069,7 @@ var init_fs = __esm({
4953
5069
  return;
4954
5070
  }
4955
5071
  for (const e of entries) {
4956
- const full = path15.join(dir, e.name);
5072
+ const full = path16.join(dir, e.name);
4957
5073
  if (e.isDirectory()) {
4958
5074
  if (!skipDirs.has(e.name)) await walk(full);
4959
5075
  continue;
@@ -5227,8 +5343,8 @@ ${formattedCode}${hasMore ? `
5227
5343
  const entries = await fs12.readdir(currentPath, { withFileTypes: true });
5228
5344
  const validEntries = entries.filter((entry) => {
5229
5345
  if (entry.isSymbolicLink()) return false;
5230
- const fullPath = path15.join(currentPath, entry.name);
5231
- const relPath = path15.relative(getActiveWorkspaceRoot(), fullPath).replace(/\\/g, "/");
5346
+ const fullPath = path16.join(currentPath, entry.name);
5347
+ const relPath = path16.relative(getActiveWorkspaceRoot(), fullPath).replace(/\\/g, "/");
5232
5348
  return !checkIsPathIgnored(entry.isDirectory() ? `${relPath}/` : relPath);
5233
5349
  });
5234
5350
  let output = "";
@@ -5247,7 +5363,7 @@ ${formattedCode}${hasMore ? `
5247
5363
  `;
5248
5364
  if (entry.isDirectory()) {
5249
5365
  const nextPrefix = prefix + (isLast ? " " : "\u2502 ");
5250
- const fullPath = path15.join(currentPath, entry.name);
5366
+ const fullPath = path16.join(currentPath, entry.name);
5251
5367
  const subTree = await buildTreeText(fullPath, currentDepth + 1, nextPrefix);
5252
5368
  output += subTree;
5253
5369
  }
@@ -5361,7 +5477,7 @@ ${summaries.join("\n")}`;
5361
5477
  }
5362
5478
  const content = args.content ?? "";
5363
5479
  assertWithinWorkspace(absPath);
5364
- await fs12.mkdir(path15.dirname(absPath), { recursive: true });
5480
+ await fs12.mkdir(path16.dirname(absPath), { recursive: true });
5365
5481
  tmpPath = makeTmpPath(absPath);
5366
5482
  await fs12.writeFile(tmpPath, content, "utf-8");
5367
5483
  await fs12.rename(tmpPath, absPath);
@@ -5400,7 +5516,7 @@ ${summaries.join("\n")}`;
5400
5516
  }
5401
5517
  let rel = "";
5402
5518
  try {
5403
- rel = path15.relative(getActiveWorkspaceRoot(), resolveSafePath(cleanPath));
5519
+ rel = path16.relative(getActiveWorkspaceRoot(), resolveSafePath(cleanPath));
5404
5520
  } catch {
5405
5521
  }
5406
5522
  if (rel === "" || rel === "src") {
@@ -5421,8 +5537,8 @@ ${summaries.join("\n")}`;
5421
5537
  return `\u274C [\u5B89\u5168\u7194\u65AD]\uFF1A\u7981\u6B62\u901A\u8FC7\u672C\u5DE5\u5177\u76F4\u63A5\u6467\u6BC1\u9879\u76EE\u6839\u76EE\u5F55\u6216\u4F20\u5165\u7A7A\u8DEF\u5F84\uFF01`;
5422
5538
  }
5423
5539
  const absPath = resolveSafePath(cleanPath);
5424
- const rel = path15.relative(getActiveWorkspaceRoot(), absPath);
5425
- if (!rel || rel === "" || rel === "src" || rel.startsWith("..") || path15.isAbsolute(rel)) {
5540
+ const rel = path16.relative(getActiveWorkspaceRoot(), absPath);
5541
+ if (!rel || rel === "" || rel === "src" || rel.startsWith("..") || path16.isAbsolute(rel)) {
5426
5542
  return `\u274C [\u5B89\u5168\u7194\u65AD]\uFF1A\u62D2\u7EDD\u9500\u6BC1\u5DE5\u4F5C\u533A\u6839\u76EE\u5F55 / src \u6E90\u7801\u6839 / \u8D8A\u754C\u8DEF\u5F84 [${cleanPath}]\uFF01`;
5427
5543
  }
5428
5544
  let stat;
@@ -5467,7 +5583,7 @@ ${summaries.join("\n")}`;
5467
5583
  try {
5468
5584
  const absPath = resolveSafePath(args.path);
5469
5585
  assertWithinWorkspace(absPath);
5470
- await fs12.mkdir(path15.dirname(absPath), { recursive: true });
5586
+ await fs12.mkdir(path16.dirname(absPath), { recursive: true });
5471
5587
  tmpPath = makeTmpPath(absPath);
5472
5588
  await fs12.writeFile(tmpPath, args.content, "utf-8");
5473
5589
  await fs12.rename(tmpPath, absPath);
@@ -5601,7 +5717,7 @@ ${summaries.join("\n")}`;
5601
5717
  }
5602
5718
  assertWithinWorkspace(srcAbs);
5603
5719
  assertWithinWorkspace(dstAbs);
5604
- await fs12.mkdir(path15.dirname(dstAbs), { recursive: true });
5720
+ await fs12.mkdir(path16.dirname(dstAbs), { recursive: true });
5605
5721
  await fs12.rename(srcAbs, dstAbs);
5606
5722
  return `\u2705 [\u79FB\u52A8\u6210\u529F]\uFF1A[${args.source}] \u2192 [${args.destination}]\u3002`;
5607
5723
  } catch (error) {
@@ -5616,7 +5732,7 @@ ${summaries.join("\n")}`;
5616
5732
 
5617
5733
  // ../core/src/tool/registry/search.ts
5618
5734
  import { rgPath } from "vscode-ripgrep";
5619
- import path16 from "path";
5735
+ import path17 from "path";
5620
5736
  import fs13 from "fs/promises";
5621
5737
  function escapeRegExp(string) {
5622
5738
  return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -5659,10 +5775,10 @@ var init_search = __esm({
5659
5775
  const resolveSearchRoot = () => {
5660
5776
  if (!args.path) return ctx?.cwd ?? getActiveWorkspaceRoot();
5661
5777
  const p = args.path.trim();
5662
- const looksLikeBareName = !path16.isAbsolute(p) && !p.includes("/") && !p.includes("\\");
5778
+ const looksLikeBareName = !path17.isAbsolute(p) && !p.includes("/") && !p.includes("\\");
5663
5779
  if (looksLikeBareName) {
5664
5780
  const hit = getAllowedWorkspaceRoots().find((r) => {
5665
- const bn = path16.basename(r);
5781
+ const bn = path17.basename(r);
5666
5782
  return bn === p || bn.toLowerCase() === p.toLowerCase();
5667
5783
  });
5668
5784
  if (hit) return hit;
@@ -5751,7 +5867,7 @@ var init_search = __esm({
5751
5867
  const GUIDE_CANDIDATES = ["CLAUDE.md", "AGENTS.md", "AGENT.md"];
5752
5868
  for (const name of GUIDE_CANDIDATES) {
5753
5869
  try {
5754
- const content = await fs13.readFile(path16.join(getActiveWorkspaceRoot(), name), "utf-8");
5870
+ const content = await fs13.readFile(path17.join(getActiveWorkspaceRoot(), name), "utf-8");
5755
5871
  return `[Project Guide via ${name}]
5756
5872
 
5757
5873
  ${content}`;
@@ -5984,7 +6100,7 @@ ${tail}`,
5984
6100
 
5985
6101
  // ../core/src/tool/registry/glob.ts
5986
6102
  import fs14 from "fs/promises";
5987
- import path17 from "path";
6103
+ import path18 from "path";
5988
6104
  var findMatchingBrace, splitTopLevel, globToRegex2, globTools;
5989
6105
  var init_glob = __esm({
5990
6106
  "../core/src/tool/registry/glob.ts"() {
@@ -6090,16 +6206,16 @@ var init_glob = __esm({
6090
6206
  if (scannedCount > MAX_SCAN_LIMIT) return;
6091
6207
  const entries = await fs14.readdir(dir, { withFileTypes: true });
6092
6208
  const validEntries = entries.filter((e) => {
6093
- const full = path17.join(dir, e.name);
6094
- const rel = path17.relative(activeRoot, full).replace(/\\/g, "/");
6209
+ const full = path18.join(dir, e.name);
6210
+ const rel = path18.relative(activeRoot, full).replace(/\\/g, "/");
6095
6211
  return !checkIsPathIgnored(e.isDirectory() ? `${rel}/` : rel);
6096
6212
  });
6097
6213
  for (const e of validEntries) {
6098
6214
  scannedCount++;
6099
6215
  if (scannedCount > MAX_SCAN_LIMIT) break;
6100
6216
  if (e.isSymbolicLink()) continue;
6101
- const full = path17.join(dir, e.name);
6102
- const rel = path17.relative(activeRoot, full).replace(/\\/g, "/");
6217
+ const full = path18.join(dir, e.name);
6218
+ const rel = path18.relative(activeRoot, full).replace(/\\/g, "/");
6103
6219
  if (e.isDirectory()) {
6104
6220
  if (cleanPattern.endsWith("/") && re.test(`${rel}/`)) {
6105
6221
  hits.push(`${rel}/`);
@@ -6316,7 +6432,7 @@ ${summary}`;
6316
6432
 
6317
6433
  // ../core/src/tool/registry/inspect_dependencies.ts
6318
6434
  import * as fs15 from "fs/promises";
6319
- import * as path18 from "path";
6435
+ import * as path19 from "path";
6320
6436
  var dependencyTools;
6321
6437
  var init_inspect_dependencies = __esm({
6322
6438
  "../core/src/tool/registry/inspect_dependencies.ts"() {
@@ -6337,7 +6453,7 @@ var init_inspect_dependencies = __esm({
6337
6453
  isSync: true,
6338
6454
  async execute() {
6339
6455
  try {
6340
- const pjsPath = path18.join(getActiveWorkspaceRoot(), "package.json");
6456
+ const pjsPath = path19.join(getActiveWorkspaceRoot(), "package.json");
6341
6457
  const raw = await fs15.readFile(pjsPath, "utf-8");
6342
6458
  const pjs = JSON.parse(raw);
6343
6459
  const result = {
@@ -6639,13 +6755,13 @@ async function safeFetchFollow(startUrl, baseHeaders, signals, allowPrivate = fa
6639
6755
  return res;
6640
6756
  }
6641
6757
  }
6642
- var FETCH_TIMEOUT_MS, SEARCH_TIMEOUT_MS, DEFAULT_MAX_CHARS, USER_AGENT, BROWSER_UA, TAVILY_ENDPOINT, formatHostBlockMessage, MAX_REDIRECTS, pinnedSsrfDispatcher, pinnedMetadataGuardDispatcher, readBodyCapped, webTools;
6758
+ var FETCH_TIMEOUT_MS2, SEARCH_TIMEOUT_MS, DEFAULT_MAX_CHARS, USER_AGENT, BROWSER_UA, TAVILY_ENDPOINT, formatHostBlockMessage, MAX_REDIRECTS, pinnedSsrfDispatcher, pinnedMetadataGuardDispatcher, readBodyCapped, webTools;
6643
6759
  var init_web = __esm({
6644
6760
  "../core/src/tool/registry/web.ts"() {
6645
6761
  "use strict";
6646
6762
  init_type();
6647
6763
  init_config();
6648
- FETCH_TIMEOUT_MS = 15e3;
6764
+ FETCH_TIMEOUT_MS2 = 15e3;
6649
6765
  SEARCH_TIMEOUT_MS = 2e4;
6650
6766
  DEFAULT_MAX_CHARS = 16e3;
6651
6767
  USER_AGENT = "DeepSeeker-Code-Agent/1.0 (+web_fetch tool)";
@@ -6775,7 +6891,7 @@ var init_web = __esm({
6775
6891
  if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
6776
6892
  return `\u274C [\u5B89\u5168\u7194\u65AD]\uFF1A\u4EC5\u5141\u8BB8 http/https \u534F\u8BAE\uFF0C\u62D2\u7EDD ${parsed.protocol}`;
6777
6893
  }
6778
- const signals = [AbortSignal.timeout(FETCH_TIMEOUT_MS)];
6894
+ const signals = [AbortSignal.timeout(FETCH_TIMEOUT_MS2)];
6779
6895
  if (ctx?.abortSignal) signals.push(ctx.abortSignal);
6780
6896
  try {
6781
6897
  const res = await safeFetchFollow(parsed.href, {
@@ -6812,7 +6928,7 @@ var init_web = __esm({
6812
6928
  ${body}${truncNote}`;
6813
6929
  } catch (error) {
6814
6930
  if (error?.name === "TimeoutError") {
6815
- return `\u274C [\u6293\u53D6\u8D85\u65F6]\uFF1A${FETCH_TIMEOUT_MS / 1e3}s \u5185\u672A\u54CD\u5E94\uFF1A${parsed.href}`;
6931
+ return `\u274C [\u6293\u53D6\u8D85\u65F6]\uFF1A${FETCH_TIMEOUT_MS2 / 1e3}s \u5185\u672A\u54CD\u5E94\uFF1A${parsed.href}`;
6816
6932
  }
6817
6933
  if (error?.name === "AbortError") {
6818
6934
  return `\u23F9\uFE0F [\u5DF2\u4E2D\u6B62]\uFF1A\u7528\u6237\u4E2D\u65AD\u4E86\u6293\u53D6\uFF1A${parsed.href}`;
@@ -6981,7 +7097,7 @@ var init_http = __esm({
6981
7097
 
6982
7098
  // ../core/src/tool/registry/typescript.ts
6983
7099
  import fs16 from "fs/promises";
6984
- import path19 from "path";
7100
+ import path20 from "path";
6985
7101
  var MAX_FILE_BYTES, toDisplayPath, precheck, MAX_DIAG_ENTRIES, MAX_DIAG_FILES, diagnoseOneFile, typescriptTools;
6986
7102
  var init_typescript = __esm({
6987
7103
  "../core/src/tool/registry/typescript.ts"() {
@@ -6992,8 +7108,8 @@ var init_typescript = __esm({
6992
7108
  init_fs();
6993
7109
  MAX_FILE_BYTES = 1024 * 1024;
6994
7110
  toDisplayPath = (wsRoot, abs) => {
6995
- const rel = path19.relative(wsRoot, abs);
6996
- if (rel && !rel.startsWith("..") && !path19.isAbsolute(rel)) return rel.replace(/\\/g, "/");
7111
+ const rel = path20.relative(wsRoot, abs);
7112
+ if (rel && !rel.startsWith("..") && !path20.isAbsolute(rel)) return rel.replace(/\\/g, "/");
6997
7113
  return abs.replace(/\\/g, "/").split("/").slice(-3).join("/");
6998
7114
  };
6999
7115
  precheck = async (displayPath, absPath) => {
@@ -7252,7 +7368,7 @@ var init_todo = __esm({
7252
7368
 
7253
7369
  // ../core/src/observability/traceCalculate.ts
7254
7370
  import fs17 from "fs/promises";
7255
- import path20 from "path";
7371
+ import path21 from "path";
7256
7372
  var getDirBytes, getTodayDateString;
7257
7373
  var init_traceCalculate = __esm({
7258
7374
  "../core/src/observability/traceCalculate.ts"() {
@@ -7269,7 +7385,7 @@ var init_traceCalculate = __esm({
7269
7385
  continue;
7270
7386
  }
7271
7387
  for (const e of entries) {
7272
- const p = path20.join(cur, e.name);
7388
+ const p = path21.join(cur, e.name);
7273
7389
  if (e.isDirectory()) {
7274
7390
  stack.push(p);
7275
7391
  } else {
@@ -7293,7 +7409,7 @@ var init_traceCalculate = __esm({
7293
7409
  });
7294
7410
 
7295
7411
  // ../core/src/tool/undo/store.ts
7296
- import path21 from "path";
7412
+ import path22 from "path";
7297
7413
  import fs18 from "fs/promises";
7298
7414
  var getUndoRootPath, getUndoClockPath, getUndoDirPath, getUndoBackupRoot, ensureUndoDir, getUndoIndexPath;
7299
7415
  var init_store2 = __esm({
@@ -7302,14 +7418,14 @@ var init_store2 = __esm({
7302
7418
  init_config();
7303
7419
  init_common();
7304
7420
  init_traceCalculate();
7305
- getUndoRootPath = () => path21.join(appConfig.dataDir, "undo");
7306
- getUndoClockPath = () => path21.join(getUndoRootPath(), "undo-cleanup-clock.json");
7421
+ getUndoRootPath = () => path22.join(appConfig.dataDir, "undo");
7422
+ getUndoClockPath = () => path22.join(getUndoRootPath(), "undo-cleanup-clock.json");
7307
7423
  getUndoDirPath = (mainSessionId) => {
7308
7424
  const rootId = getFileName(mainSessionId);
7309
7425
  assertSafeSessionId(rootId, "undoSessionId");
7310
- return path21.join(getUndoRootPath(), appConfig.userWorkspaceDir, rootId);
7426
+ return path22.join(getUndoRootPath(), appConfig.userWorkspaceDir, rootId);
7311
7427
  };
7312
- getUndoBackupRoot = (mainSessionId) => path21.join(getUndoDirPath(mainSessionId), "backups");
7428
+ getUndoBackupRoot = (mainSessionId) => path22.join(getUndoDirPath(mainSessionId), "backups");
7313
7429
  ensureUndoDir = async (mainSessionId) => {
7314
7430
  await fs18.mkdir(getUndoDirPath(mainSessionId), { recursive: true, mode: 448 });
7315
7431
  };
@@ -7321,14 +7437,14 @@ var init_store2 = __esm({
7321
7437
  const files = await fs18.readdir(dir);
7322
7438
  const existedFile = files.find((f) => f.endsWith(`__${rootId}.jsonl`));
7323
7439
  const fileName = existedFile ?? `undo-${getTodayDateString()}__${rootId}.jsonl`;
7324
- return path21.join(dir, fileName);
7440
+ return path22.join(dir, fileName);
7325
7441
  };
7326
7442
  }
7327
7443
  });
7328
7444
 
7329
7445
  // ../core/src/tool/undo/index.ts
7330
7446
  import fs19 from "fs/promises";
7331
- import path22 from "path";
7447
+ import path23 from "path";
7332
7448
  var undoLocks, withUndoLock, appendUndoRecord, readUndoIndex, markRestored;
7333
7449
  var init_undo = __esm({
7334
7450
  "../core/src/tool/undo/index.ts"() {
@@ -7378,7 +7494,7 @@ var init_undo = __esm({
7378
7494
  for (const f of files) {
7379
7495
  if (!f.startsWith("undo-") || !f.endsWith(".jsonl")) continue;
7380
7496
  try {
7381
- const raw = await fs19.readFile(path22.join(dir, f), "utf-8");
7497
+ const raw = await fs19.readFile(path23.join(dir, f), "utf-8");
7382
7498
  for (const line of raw.split("\n")) {
7383
7499
  const trimmed = line.trim();
7384
7500
  if (!trimmed) continue;
@@ -7409,7 +7525,7 @@ var init_undo = __esm({
7409
7525
  }
7410
7526
  for (const f of files) {
7411
7527
  if (!f.startsWith("undo-") || !f.endsWith(".jsonl")) continue;
7412
- const fp = path22.join(dir, f);
7528
+ const fp = path23.join(dir, f);
7413
7529
  let raw;
7414
7530
  try {
7415
7531
  raw = await fs19.readFile(fp, "utf-8");
@@ -7447,7 +7563,7 @@ var init_undo = __esm({
7447
7563
 
7448
7564
  // ../core/src/tool/undo/cleanup.ts
7449
7565
  import fs20 from "fs/promises";
7450
- import path23 from "path";
7566
+ import path24 from "path";
7451
7567
  async function maybeCleanupAfterUndoAppend(_sessionId) {
7452
7568
  if (cleanupInProgress) return;
7453
7569
  cleanupInProgress = true;
@@ -7473,7 +7589,7 @@ async function maybeCleanupAfterUndoAppend(_sessionId) {
7473
7589
  lastSizeCleanupAt = now;
7474
7590
  diskLastCleanupAt = now;
7475
7591
  const clockPath = getUndoClockPath();
7476
- await fs20.mkdir(path23.dirname(clockPath), { recursive: true });
7592
+ await fs20.mkdir(path24.dirname(clockPath), { recursive: true });
7477
7593
  await fs20.writeFile(clockPath, JSON.stringify({ lastCleanupAt: now, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), "utf-8");
7478
7594
  if (deleted > 0) console.log(`\u2728 [Undo\u8FD0\u7EF4] \u5171\u9500\u6BC1 ${deleted} \u4E2A undo \u8D44\u4EA7\uFF08\u7D22\u5F15 + \u5B64\u513F\u5185\u5BB9\uFF09\uFF0C\u78C1\u76D8\u6C34\u4F4D\u56DE\u843D\u3002`);
7479
7595
  } catch (e) {
@@ -7498,12 +7614,12 @@ async function cleanupOldUndoFiles() {
7498
7614
  const re = /^undo-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
7499
7615
  let deleted = 0;
7500
7616
  for (const rp of relativePaths) {
7501
- const fileName = path23.basename(rp);
7617
+ const fileName = path24.basename(rp);
7502
7618
  const m = fileName.match(re);
7503
7619
  if (!m) continue;
7504
7620
  const fileBornDay = /* @__PURE__ */ new Date(`${m[1]}T00:00:00`);
7505
7621
  if (fileBornDay >= cutoff) continue;
7506
- const fullPath = path23.join(dir, rp);
7622
+ const fullPath = path24.join(dir, rp);
7507
7623
  try {
7508
7624
  const st = await fs20.stat(fullPath);
7509
7625
  if (now - st.mtimeMs < ACTIVE_GRACE_MS) continue;
@@ -7525,10 +7641,10 @@ async function evictOldestForSize(targetBytes) {
7525
7641
  const re = /^undo-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
7526
7642
  const candidates = [];
7527
7643
  for (const rp of relativePaths) {
7528
- if (!re.test(path23.basename(rp))) continue;
7644
+ if (!re.test(path24.basename(rp))) continue;
7529
7645
  try {
7530
- const st = await fs20.stat(path23.join(dir, rp));
7531
- candidates.push({ mtime: st.mtimeMs, fullPath: path23.join(dir, rp), size: st.size });
7646
+ const st = await fs20.stat(path24.join(dir, rp));
7647
+ candidates.push({ mtime: st.mtimeMs, fullPath: path24.join(dir, rp), size: st.size });
7532
7648
  } catch {
7533
7649
  }
7534
7650
  }
@@ -7557,7 +7673,7 @@ async function gcOrphanBackups() {
7557
7673
  return 0;
7558
7674
  }
7559
7675
  for (const ws of workspaces) {
7560
- const wsDir = path23.join(root, ws);
7676
+ const wsDir = path24.join(root, ws);
7561
7677
  let stWs;
7562
7678
  try {
7563
7679
  stWs = await fs20.stat(wsDir);
@@ -7572,7 +7688,7 @@ async function gcOrphanBackups() {
7572
7688
  continue;
7573
7689
  }
7574
7690
  for (const sess of sessions2) {
7575
- const sessDir = path23.join(wsDir, sess);
7691
+ const sessDir = path24.join(wsDir, sess);
7576
7692
  const liveIds = /* @__PURE__ */ new Set();
7577
7693
  let files;
7578
7694
  try {
@@ -7583,7 +7699,7 @@ async function gcOrphanBackups() {
7583
7699
  for (const f of files) {
7584
7700
  if (!f.startsWith("undo-") || !f.endsWith(".jsonl")) continue;
7585
7701
  try {
7586
- const raw = await fs20.readFile(path23.join(sessDir, f), "utf-8");
7702
+ const raw = await fs20.readFile(path24.join(sessDir, f), "utf-8");
7587
7703
  for (const line of raw.split("\n")) {
7588
7704
  const t = line.trim();
7589
7705
  if (!t) continue;
@@ -7596,7 +7712,7 @@ async function gcOrphanBackups() {
7596
7712
  } catch {
7597
7713
  }
7598
7714
  }
7599
- const backupsDir = path23.join(sessDir, "backups");
7715
+ const backupsDir = path24.join(sessDir, "backups");
7600
7716
  let undoDirs;
7601
7717
  try {
7602
7718
  undoDirs = await fs20.readdir(backupsDir);
@@ -7606,7 +7722,7 @@ async function gcOrphanBackups() {
7606
7722
  for (const ud of undoDirs) {
7607
7723
  if (liveIds.has(ud)) continue;
7608
7724
  try {
7609
- await fs20.rm(path23.join(backupsDir, ud), { recursive: true, force: true });
7725
+ await fs20.rm(path24.join(backupsDir, ud), { recursive: true, force: true });
7610
7726
  deleted += 1;
7611
7727
  } catch {
7612
7728
  }
@@ -7649,7 +7765,7 @@ var init_cleanup = __esm({
7649
7765
  return 0;
7650
7766
  }
7651
7767
  for (const e of entries) {
7652
- const full = path23.join(dir, e.name);
7768
+ const full = path24.join(dir, e.name);
7653
7769
  if (e.isDirectory()) {
7654
7770
  total += await getDirBytesRecursive(full);
7655
7771
  } else if (e.isFile()) {
@@ -7666,7 +7782,7 @@ var init_cleanup = __esm({
7666
7782
 
7667
7783
  // ../core/src/tool/undo/backup.ts
7668
7784
  import fs21 from "fs/promises";
7669
- import path24 from "path";
7785
+ import path25 from "path";
7670
7786
  import crypto from "crypto";
7671
7787
  async function beforeMutationBackup(toolName, args, toolCallId, sessionId) {
7672
7788
  if (appConfig.undoEnabled === false) return null;
@@ -7681,7 +7797,7 @@ async function beforeMutationBackup(toolName, args, toolCallId, sessionId) {
7681
7797
  }
7682
7798
  await ensureUndoDir(sessionId);
7683
7799
  const undoId = createUUID();
7684
- const undoDir = path24.join(getUndoBackupRoot(sessionId), undoId);
7800
+ const undoDir = path25.join(getUndoBackupRoot(sessionId), undoId);
7685
7801
  const now = /* @__PURE__ */ new Date();
7686
7802
  const common = {
7687
7803
  undoId,
@@ -7731,7 +7847,7 @@ async function backupFileOverwrite(common, undoDir, args) {
7731
7847
  }
7732
7848
  const content = await fs21.readFile(absPath);
7733
7849
  await fs21.mkdir(undoDir, { recursive: true, mode: 448 });
7734
- const contentPath = path24.join(undoDir, "content");
7850
+ const contentPath = path25.join(undoDir, "content");
7735
7851
  await fs21.writeFile(contentPath, content, { mode: 384 });
7736
7852
  return {
7737
7853
  ...common,
@@ -7768,7 +7884,7 @@ async function backupDelete(common, undoDir, relativePath) {
7768
7884
  throw new Error(`\u76EE\u5F55 [${relativePath}] \u5185\u542B\u654F\u611F\u6587\u4EF6 ${sensitiveInTree.length} \u4E2A\uFF08\u5982 ${sensitiveInTree[0]}\uFF09\uFF0C\u6309\u7B56\u7565(undoBackupSensitive=deny)\u62D2\u7EDD\u5907\u4EFD\uFF0C\u5199\u5165\u5DF2\u963B\u65AD`);
7769
7885
  }
7770
7886
  }
7771
- const treeDest = path24.join(undoDir, "tree");
7887
+ const treeDest = path25.join(undoDir, "tree");
7772
7888
  const sensitiveSet = new Set(sensitiveInTree);
7773
7889
  await fs21.cp(absPath, treeDest, {
7774
7890
  recursive: true,
@@ -7776,7 +7892,7 @@ async function backupDelete(common, undoDir, relativePath) {
7776
7892
  preserveTimestamps: true,
7777
7893
  filter: (src) => {
7778
7894
  if (src === absPath) return true;
7779
- const relWithin = path24.relative(absPath, src).replace(/\\/g, "/");
7895
+ const relWithin = path25.relative(absPath, src).replace(/\\/g, "/");
7780
7896
  return !sensitiveSet.has(relWithin);
7781
7897
  }
7782
7898
  });
@@ -7793,7 +7909,7 @@ async function backupDelete(common, undoDir, relativePath) {
7793
7909
  throw new Error(`\u6587\u4EF6 [${relativePath}] \u4F53\u79EF\u7EA6 ${st.size} \u5B57\u8282\u8D85\u8FC7\u5355\u6B21\u5907\u4EFD\u4E0A\u9650 ${maxPerOp}\uFF0C\u5199\u5165\u5DF2\u963B\u65AD\uFF08\u9632\u5185\u5B58\u62D6\u57AE\uFF1B\u53EF\u8C03 undoMaxBytesPerOp\uFF09`);
7794
7910
  }
7795
7911
  const content = await fs21.readFile(absPath);
7796
- const contentPath = path24.join(undoDir, "content");
7912
+ const contentPath = path25.join(undoDir, "content");
7797
7913
  await fs21.writeFile(contentPath, content, { mode: 384 });
7798
7914
  return {
7799
7915
  ...common,
@@ -7845,8 +7961,8 @@ var init_backup = __esm({
7845
7961
  }
7846
7962
  entries.sort((a, b) => a.name.localeCompare(b.name));
7847
7963
  for (const e of entries) {
7848
- const full = path24.join(d, e.name);
7849
- const rel = path24.relative(dir, full).replace(/\\/g, "/");
7964
+ const full = path25.join(d, e.name);
7965
+ const rel = path25.relative(dir, full).replace(/\\/g, "/");
7850
7966
  if (e.isDirectory()) {
7851
7967
  h.update(`D ${rel}
7852
7968
  `);
@@ -7872,7 +7988,7 @@ var init_backup = __esm({
7872
7988
  return 0;
7873
7989
  }
7874
7990
  for (const e of entries) {
7875
- const full = path24.join(dir, e.name);
7991
+ const full = path25.join(dir, e.name);
7876
7992
  if (e.isDirectory()) total += await getDirTreeBytes(full);
7877
7993
  else if (e.isFile()) {
7878
7994
  try {
@@ -7893,11 +8009,11 @@ var init_backup = __esm({
7893
8009
  return;
7894
8010
  }
7895
8011
  for (const e of entries) {
7896
- const full = path24.join(d, e.name);
8012
+ const full = path25.join(d, e.name);
7897
8013
  if (e.isDirectory()) {
7898
8014
  await walk(full);
7899
8015
  } else if (e.isFile()) {
7900
- const relWithin = path24.relative(dir, full).replace(/\\/g, "/");
8016
+ const relWithin = path25.relative(dir, full).replace(/\\/g, "/");
7901
8017
  if (isSensitivePath(`${wsRelDir}/${relWithin}`)) found.push(relWithin);
7902
8018
  }
7903
8019
  }
@@ -7910,7 +8026,7 @@ var init_backup = __esm({
7910
8026
 
7911
8027
  // ../core/src/tool/undo/restore.ts
7912
8028
  import fs22 from "fs/promises";
7913
- import path25 from "path";
8029
+ import path26 from "path";
7914
8030
  import crypto2 from "crypto";
7915
8031
  async function doRestore(target, sessionId) {
7916
8032
  if (target.backupKind === "directory_tree") {
@@ -7968,16 +8084,16 @@ async function ensureReverseBackup(target, sessionId) {
7968
8084
  }
7969
8085
  }
7970
8086
  const reverseId = createUUID();
7971
- const reverseDir = path25.join(getUndoBackupRoot(sessionId), reverseId);
8087
+ const reverseDir = path26.join(getUndoBackupRoot(sessionId), reverseId);
7972
8088
  await fs22.mkdir(reverseDir, { recursive: true, mode: 448 });
7973
8089
  assertWithinWorkspace(absPath);
7974
8090
  const st = await fs22.stat(absPath);
7975
8091
  if (st.isDirectory()) {
7976
- const dest2 = path25.join(reverseDir, "tree");
8092
+ const dest2 = path26.join(reverseDir, "tree");
7977
8093
  await fs22.cp(absPath, dest2, { recursive: true, force: true, preserveTimestamps: true });
7978
8094
  return { reverseId, backupKind: "directory_tree", backupPath: dest2 };
7979
8095
  }
7980
- const dest = path25.join(reverseDir, "content");
8096
+ const dest = path26.join(reverseDir, "content");
7981
8097
  await fs22.writeFile(dest, await fs22.readFile(absPath));
7982
8098
  return { reverseId, backupKind: "file_content", backupPath: dest };
7983
8099
  }
@@ -7990,15 +8106,15 @@ async function dispatchRestore(r) {
7990
8106
  return `\u5DF2\u5220\u9664\u65B0\u5EFA\u6587\u4EF6 [${r.relativePath}]`;
7991
8107
  }
7992
8108
  case "file_content": {
7993
- await fs22.mkdir(path25.dirname(absPath), { recursive: true });
7994
- const backupAbs = path25.join(getUndoBackupRoot(r.sessionId), r.undoId, "content");
8109
+ await fs22.mkdir(path26.dirname(absPath), { recursive: true });
8110
+ const backupAbs = path26.join(getUndoBackupRoot(r.sessionId), r.undoId, "content");
7995
8111
  const content = await fs22.readFile(backupAbs);
7996
8112
  await fs22.writeFile(absPath, content);
7997
8113
  return `\u5DF2\u6062\u590D [${r.relativePath}] \u81F3\u5907\u4EFD\u524D\u5185\u5BB9\uFF08${r.fileSizeBefore ?? content.byteLength} \u5B57\u8282\uFF09`;
7998
8114
  }
7999
8115
  case "directory_tree": {
8000
- await fs22.mkdir(path25.dirname(absPath), { recursive: true });
8001
- const src = path25.join(getUndoBackupRoot(r.sessionId), r.undoId, "tree");
8116
+ await fs22.mkdir(path26.dirname(absPath), { recursive: true });
8117
+ const src = path26.join(getUndoBackupRoot(r.sessionId), r.undoId, "tree");
8002
8118
  await fs22.cp(src, absPath, { recursive: true, force: true, preserveTimestamps: true });
8003
8119
  return `\u5DF2\u6062\u590D\u76EE\u5F55\u6811 [${r.relativePath}]\uFF08\u7EA6 ${r.fileSizeBefore ?? 0} \u5B57\u8282\uFF09`;
8004
8120
  }
@@ -8482,7 +8598,7 @@ var init_frontmatter = __esm({
8482
8598
 
8483
8599
  // ../core/src/memory/loader.ts
8484
8600
  import fs24 from "fs/promises";
8485
- import path26 from "path";
8601
+ import path27 from "path";
8486
8602
  var GLOBAL_MEMORY_DIR, SOURCES, VALID_TYPES, parseMemoryAt, loadMemories, initMemories;
8487
8603
  var init_loader3 = __esm({
8488
8604
  "../core/src/memory/loader.ts"() {
@@ -8491,10 +8607,10 @@ var init_loader3 = __esm({
8491
8607
  init_frontmatter();
8492
8608
  init_registry6();
8493
8609
  init_registry2();
8494
- GLOBAL_MEMORY_DIR = path26.join(appConfig.dataDir, "memory");
8610
+ GLOBAL_MEMORY_DIR = path27.join(appConfig.dataDir, "memory");
8495
8611
  SOURCES = [
8496
8612
  { dir: GLOBAL_MEMORY_DIR, source: "global" },
8497
- { dir: path26.join(process.cwd(), ".deepseeker-code", "memory"), source: "project" }
8613
+ { dir: path27.join(process.cwd(), ".deepseeker-code", "memory"), source: "project" }
8498
8614
  ];
8499
8615
  VALID_TYPES = ["user", "feedback", "project", "reference"];
8500
8616
  parseMemoryAt = async (file, _dir, source) => {
@@ -8534,7 +8650,7 @@ var init_loader3 = __esm({
8534
8650
  clearMemories();
8535
8651
  const picked = await scanSources(
8536
8652
  filterSources(SOURCES, includeProject),
8537
- (e, dir) => e.isFile() && e.name.endsWith(".md") ? path26.join(dir, e.name) : void 0,
8653
+ (e, dir) => e.isFile() && e.name.endsWith(".md") ? path27.join(dir, e.name) : void 0,
8538
8654
  parseMemoryAt
8539
8655
  );
8540
8656
  for (const { item } of picked) registerMemory(item);
@@ -8553,7 +8669,7 @@ var init_loader3 = __esm({
8553
8669
 
8554
8670
  // ../core/src/tool/registry/memory.ts
8555
8671
  import fs25 from "fs/promises";
8556
- import path27 from "path";
8672
+ import path28 from "path";
8557
8673
  var MAX_BODY_BYTES, NAME_RE, VALID_TYPES2, memoryFilePath, sanitizeLine, buildMemoryMd, writeAndRegister, memoryTools;
8558
8674
  var init_memory = __esm({
8559
8675
  "../core/src/tool/registry/memory.ts"() {
@@ -8565,7 +8681,7 @@ var init_memory = __esm({
8565
8681
  MAX_BODY_BYTES = 64 * 1024;
8566
8682
  NAME_RE = /^[a-z0-9-]+$/;
8567
8683
  VALID_TYPES2 = ["user", "feedback", "project", "reference"];
8568
- memoryFilePath = (name, project) => project ? path27.join(process.cwd(), ".deepseeker-code", "memory", `${name}.md`) : path27.join(GLOBAL_MEMORY_DIR, `${name}.md`);
8684
+ memoryFilePath = (name, project) => project ? path28.join(process.cwd(), ".deepseeker-code", "memory", `${name}.md`) : path28.join(GLOBAL_MEMORY_DIR, `${name}.md`);
8569
8685
  sanitizeLine = (s) => String(s ?? "").replace(/[\r\n]+/g, " ").trim();
8570
8686
  buildMemoryMd = (name, description, type, body) => `---
8571
8687
  name: ${name}
@@ -8577,7 +8693,7 @@ ${body.trim()}
8577
8693
  `;
8578
8694
  writeAndRegister = async (name, description, type, body, project) => {
8579
8695
  const file = memoryFilePath(name, project);
8580
- await fs25.mkdir(path27.dirname(file), { recursive: true });
8696
+ await fs25.mkdir(path28.dirname(file), { recursive: true });
8581
8697
  const tmp = makeTmpPath(file);
8582
8698
  await fs25.writeFile(tmp, buildMemoryMd(name, description, type, body), "utf-8");
8583
8699
  await fs25.rename(tmp, file);
@@ -9117,7 +9233,7 @@ var init_backgroundTool = __esm({
9117
9233
  });
9118
9234
 
9119
9235
  // ../core/src/tool/autoPermission.ts
9120
- import path28 from "path";
9236
+ import path29 from "path";
9121
9237
  var AUTO_SCOPE, AUTO_DEFAULT_EXTRA, AUTO_AGGRESSIVE_EXTRA, isMcpTool, BUILTIN_AUTO_DENY, matchBuiltinDeny, COMMAND_DENY, matchCommandDeny, hasShellMetachars, READONLY_HEADS, hasWriteModifier, SENSITIVE_FILE_ARG_RE, hasSensitiveFileArg, isReadOnlyCommand, isWithinWorkspace, runAutoCheck;
9122
9238
  var init_autoPermission = __esm({
9123
9239
  "../core/src/tool/autoPermission.ts"() {
@@ -9252,9 +9368,9 @@ var init_autoPermission = __esm({
9252
9368
  isWithinWorkspace = (p, cwd) => {
9253
9369
  if (!p || !cwd) return false;
9254
9370
  try {
9255
- const abs = path28.isAbsolute(p) ? p : path28.resolve(cwd, p);
9256
- const rel = path28.relative(cwd, abs);
9257
- return rel === "" || !rel.startsWith("..") && !path28.isAbsolute(rel);
9371
+ const abs = path29.isAbsolute(p) ? p : path29.resolve(cwd, p);
9372
+ const rel = path29.relative(cwd, abs);
9373
+ return rel === "" || !rel.startsWith("..") && !path29.isAbsolute(rel);
9258
9374
  } catch {
9259
9375
  return false;
9260
9376
  }
@@ -9902,6 +10018,7 @@ var init_agentNudges = __esm({
9902
10018
  createNudgeScheduler = (opts = {}) => {
9903
10019
  const firstPrompt = opts.firstPrompt ?? "";
9904
10020
  const planMode = !!opts.planMode;
10021
+ const noEarlyFinal = !!opts.noEarlyFinal;
9905
10022
  let phantomRetries = 0;
9906
10023
  let phantomPending = null;
9907
10024
  let earlyFinalNudges = 0;
@@ -9964,7 +10081,7 @@ ${TOOL_DIGEST_TEXT}` };
9964
10081
  ${PHANTOM_TEXT}` };
9965
10082
  return true;
9966
10083
  }
9967
- if (text !== "" && round <= EARLY_FINAL_TURN_THRESHOLD && earlyFinalNudges < EARLY_FINAL_MAX && !looksComplete(finalText)) {
10084
+ if (!noEarlyFinal && text !== "" && round <= EARLY_FINAL_TURN_THRESHOLD && earlyFinalNudges < EARLY_FINAL_MAX && !looksComplete(finalText)) {
9968
10085
  earlyFinalNudges++;
9969
10086
  earlyFinalPending = { role: "system", content: `${EARLY_FINAL_FENCE}
9970
10087
  ${EARLY_FINAL_TEXT(round)}` };
@@ -10049,7 +10166,7 @@ async function* runAgent(message, options) {
10049
10166
  const m = message.find((x) => x?.role === "user");
10050
10167
  return typeof m?.content === "string" ? m.content : "";
10051
10168
  })();
10052
- const nudges = createNudgeScheduler({ firstPrompt, planMode: !!options.planMode });
10169
+ const nudges = createNudgeScheduler({ firstPrompt, planMode: !!options.planMode, noEarlyFinal: !!options.noEarlyFinal });
10053
10170
  const userDecisionSource = depth > 0 ? "spawn_agent" : "user";
10054
10171
  const llmDecisionSource = depth > 0 ? "llm_spawn_agent" : "llm";
10055
10172
  const startTime = performance.now();
@@ -10178,7 +10295,6 @@ async function* runAgent(message, options) {
10178
10295
  if (assistantMessage.content) {
10179
10296
  lastContent = assistantMessage.content;
10180
10297
  }
10181
- const tcCount = assistantMessage.tool_calls?.length ?? 0;
10182
10298
  if (!assistantMessage.tool_calls || assistantMessage.tool_calls.length === 0) {
10183
10299
  await appendEvent(sessionId, { dscEvent: "round.end", runId, round, usage: infResult.usage });
10184
10300
  const finalText = (typeof assistantMessage.content === "string" ? assistantMessage.content : "") || "";
@@ -10423,8 +10539,61 @@ var init_content = __esm({
10423
10539
  }
10424
10540
  });
10425
10541
 
10542
+ // ../core/src/session/lineage.ts
10543
+ import fs27 from "node:fs";
10544
+ var parentOfSubsession, stringAncestorsOf, readForkedFromSync, lineageClosureOf, ownerCanApprove;
10545
+ var init_lineage = __esm({
10546
+ "../core/src/session/lineage.ts"() {
10547
+ "use strict";
10548
+ init_store();
10549
+ parentOfSubsession = (sessionId) => {
10550
+ const i = sessionId.lastIndexOf("__sub__");
10551
+ return i > 0 ? sessionId.slice(0, i) : void 0;
10552
+ };
10553
+ stringAncestorsOf = (sessionId) => {
10554
+ const out = [sessionId];
10555
+ let cur = sessionId;
10556
+ for (; ; ) {
10557
+ const p = parentOfSubsession(cur);
10558
+ if (p === void 0) break;
10559
+ out.push(p);
10560
+ cur = p;
10561
+ }
10562
+ return out;
10563
+ };
10564
+ readForkedFromSync = (sessionId) => {
10565
+ try {
10566
+ const raw = fs27.readFileSync(getStatePath(sessionId), "utf-8");
10567
+ const v = JSON.parse(raw)?.forkedFrom;
10568
+ return typeof v === "string" && v.length > 0 ? v : void 0;
10569
+ } catch {
10570
+ return void 0;
10571
+ }
10572
+ };
10573
+ lineageClosureOf = (sessionId) => {
10574
+ const closure = /* @__PURE__ */ new Set();
10575
+ const expand = (id) => {
10576
+ if (closure.has(id)) return;
10577
+ const ancestors = stringAncestorsOf(id);
10578
+ for (const a of ancestors) closure.add(a);
10579
+ const root = ancestors[ancestors.length - 1];
10580
+ const from = readForkedFromSync(root);
10581
+ if (from && !closure.has(from)) expand(from);
10582
+ };
10583
+ expand(sessionId);
10584
+ return closure;
10585
+ };
10586
+ ownerCanApprove = (entrySessionId, approverSessionId) => {
10587
+ if (entrySessionId === approverSessionId) return true;
10588
+ if (!entrySessionId.includes("__sub__")) return false;
10589
+ const closure = lineageClosureOf(approverSessionId);
10590
+ return stringAncestorsOf(entrySessionId).some((a, i) => i > 0 && closure.has(a));
10591
+ };
10592
+ }
10593
+ });
10594
+
10426
10595
  // ../core/src/agent/subagent.ts
10427
- var SUBAGENT_DENYLIST, runSubagent;
10596
+ var SUBAGENT_DENYLIST, activeSubagents, RESUME_NOTE, runSubagent;
10428
10597
  var init_subagent = __esm({
10429
10598
  "../core/src/agent/subagent.ts"() {
10430
10599
  "use strict";
@@ -10435,9 +10604,18 @@ var init_subagent = __esm({
10435
10604
  init_type();
10436
10605
  init_registry4();
10437
10606
  init_hooks();
10607
+ init_lineage();
10438
10608
  SUBAGENT_DENYLIST = /* @__PURE__ */ new Set(["run_command", "delete_path"]);
10609
+ activeSubagents = /* @__PURE__ */ new Set();
10610
+ RESUME_NOTE = [
10611
+ `
10612
+ # \u3010\u7EED\u8DD1\u8BF4\u660E\u3011`,
10613
+ `\u4F60\u6B64\u524D\u7684\u5DE5\u4F5C\u5386\u53F2\u5DF2\u5B8C\u6574\u6062\u590D\u5230\u672C\u6B21\u4E0A\u4E0B\u6587\uFF08\u78C1\u76D8\u6700\u65B0\u72B6\u6001\uFF0C\u53EF\u80FD\u6BD4\u4F60\u4E0A\u6B21\u8BB0\u5FC6\u66F4\u65B0\uFF09\u3002`,
10614
+ `\u8BF7\u5148\u5BF9\u7167\u5386\u53F2\u7B80\u8981\u56DE\u987E\u5DF2\u5B8C\u6210 / \u672A\u5B8C\u6210\u90E8\u5206\uFF0C\u518D\u7EE7\u7EED\u6267\u884C\u65B0\u4EFB\u52A1\uFF1B\u6700\u7EC8\u6C47\u62A5\u4E5F\u8BF7\u5148\u6982\u8FF0\u6B64\u524D\u8FDB\u5C55\u3002`
10615
+ ].join("\n");
10439
10616
  runSubagent = async (spec, ctx, getGlobalTools) => {
10440
- const { task, name, role } = spec;
10617
+ const { task, name, role, resumeSessionId } = spec;
10618
+ const resuming = typeof resumeSessionId === "string" && resumeSessionId.length > 0;
10441
10619
  if (ctx.depth >= MAX_AGENT_DEPTH) {
10442
10620
  return {
10443
10621
  ok: false,
@@ -10445,7 +10623,39 @@ var init_subagent = __esm({
10445
10623
  sessionId: ""
10446
10624
  };
10447
10625
  }
10448
- const subSessionId = `${ctx.sessionId}__sub__${createUUID()}`;
10626
+ if (resuming) {
10627
+ const target = resumeSessionId;
10628
+ if (!target.includes("__sub__")) {
10629
+ return {
10630
+ ok: false,
10631
+ output: `\u274C [\u7EED\u8DD1\u5931\u8D25]\uFF1A${target} \u4E0D\u662F\u5B50 Agent \u4F1A\u8BDD ID\uFF08\u5E94\u5F62\u5982 <\u4F1A\u8BDD>__sub__<uuid>\uFF0C\u6765\u81EA\u6B64\u524D spawn_agent \u8FD4\u56DE\u7684 agent_id\uFF09\u3002`,
10632
+ sessionId: ""
10633
+ };
10634
+ }
10635
+ if (!ownerCanApprove(target, ctx.sessionId)) {
10636
+ return {
10637
+ ok: false,
10638
+ output: `\u274C [\u7EED\u8DD1\u5931\u8D25]\uFF1A\u5B50\u4F1A\u8BDD ${target} \u4E0D\u5C5E\u4E8E\u5F53\u524D\u4F1A\u8BDD\uFF08\u53CA\u5176 fork \u8840\u7F18\uFF09\uFF0C\u7981\u6B62\u8DE8\u4F1A\u8BDD\u590D\u6D3B\u3002\u8BF7\u6838\u5BF9 agent_id \u6216\u6539\u7528\u65B0\u5EFA\u6D3E\u751F\u3002`,
10639
+ sessionId: ""
10640
+ };
10641
+ }
10642
+ if (activeSubagents.has(target)) {
10643
+ return {
10644
+ ok: false,
10645
+ output: `\u274C [\u7EED\u8DD1\u5931\u8D25]\uFF1A\u5B50 Agent ${target} \u6B63\u5728\u6267\u884C\u4E2D\uFF0C\u7981\u6B62\u5E76\u53D1\u7EED\u8DD1\u540C\u4E00\u5B50\u4F1A\u8BDD\uFF08\u4F1A\u4EA4\u53C9\u5199\u574F\u8F6C\u5F55\uFF09\u3002\u8BF7\u7B49\u5F85\u5176\u5B8C\u6210\u540E\u518D\u8BD5\u3002`,
10646
+ sessionId: ""
10647
+ };
10648
+ }
10649
+ const existing = await readTranscriptLines(target);
10650
+ if (existing.length === 0) {
10651
+ return {
10652
+ ok: false,
10653
+ output: `\u274C [\u7EED\u8DD1\u5931\u8D25]\uFF1A\u5B50\u4F1A\u8BDD ${target} \u7684\u8F6C\u5F55\u4E0D\u5B58\u5728\u6216\u4E3A\u7A7A\uFF0C\u65E0\u6CD5\u7EED\u8DD1\u3002\u8BF7\u6539\u7528\u65B0\u5EFA\u6D3E\u751F\u3002`,
10654
+ sessionId: ""
10655
+ };
10656
+ }
10657
+ }
10658
+ const subSessionId = resuming ? resumeSessionId : `${ctx.sessionId}__sub__${createUUID()}`;
10449
10659
  const parentSystemPrompt = ctx.parentSystemPrompt || "";
10450
10660
  const manifest = name ? getAgent(name) : void 0;
10451
10661
  if (name && !manifest) {
@@ -10455,7 +10665,7 @@ var init_subagent = __esm({
10455
10665
  sessionId: ""
10456
10666
  };
10457
10667
  }
10458
- const subSystem = manifest ? [
10668
+ const subSystem = (manifest ? [
10459
10669
  `# \u5B50 Agent \u8EAB\u4EFD\uFF1A${manifest.name}`,
10460
10670
  manifest.body,
10461
10671
  `
@@ -10478,11 +10688,12 @@ var init_subagent = __esm({
10478
10688
  `
10479
10689
  # \u3010\u7EE7\u627F\u7684\u5168\u5C40\u4EE3\u7801\u89C4\u8303\u3011`,
10480
10690
  parentSystemPrompt
10481
- ].join("\n");
10691
+ ].join("\n")) + (resuming ? RESUME_NOTE : "");
10482
10692
  const allTools = getGlobalTools();
10483
10693
  const wantsMcp = manifest?.tools.some((t) => t === "mcp_call" || t === "mcp_list_tools" || t.startsWith("mcp__")) ?? false;
10484
10694
  const toolSchemas = manifest && manifest.tools.length > 0 ? allTools.filter((t) => manifest.tools.includes(t.function.name) || wantsMcp && (t.function.name === "mcp_call" || t.function.name === "mcp_list_tools")) : allTools.filter((t) => !SUBAGENT_DENYLIST.has(t.function.name));
10485
- console.log(`\u{1F423} \u6D3E\u751F\u5B50 Agent [\u6DF1\u5EA6: ${ctx.depth + 1}/${MAX_AGENT_DEPTH}]${manifest ? ` \u58F0\u660E\u5F0F=${manifest.name}` : ""} \u4EFB\u52A1: "${task.slice(0, 50)}..."`);
10695
+ console.log(`${resuming ? "\u{1F501} \u7EED\u8DD1" : "\u{1F423} \u6D3E\u751F"}\u5B50 Agent [\u6DF1\u5EA6: ${ctx.depth + 1}/${MAX_AGENT_DEPTH}][${subSessionId}]${manifest ? ` \u58F0\u660E\u5F0F=${manifest.name}` : ""} \u4EFB\u52A1: "${task.slice(0, 50)}..."`);
10696
+ activeSubagents.add(subSessionId);
10486
10697
  try {
10487
10698
  const subMessages = await buildContextMessages(subSessionId, { role: "user", content: task }, subSystem);
10488
10699
  await appendMessage({ sessionId: subSessionId, role: "user", content: task });
@@ -10506,6 +10717,8 @@ var init_subagent = __esm({
10506
10717
  // ★ 同步透传宿主审批钩子,子 agent 高危工具仍走同一审批通道
10507
10718
  permissionMode: ctx.permissionMode,
10508
10719
  // ★ P1-6 透传:子 agent 工作区文件编辑也走 auto 分类器
10720
+ noEarlyFinal: true,
10721
+ // ★ 子 agent final 是交付父级的汇报,EARLY_FINAL 误推一轮纯浪费;父可经续跑纠错
10509
10722
  model: manifest?.model
10510
10723
  // ★ per-agent 模型覆盖;undefined 时 model.ts 回退全局 MODEL_NAME
10511
10724
  };
@@ -10539,14 +10752,16 @@ var init_subagent = __esm({
10539
10752
  return result ?? { ok: false, output: `\u274C [\u6D3E\u751F\u6267\u884C\u5931\u8D25]: \u672A\u77E5\u9519\u8BEF`, sessionId: subSessionId, manifestName: manifest?.name };
10540
10753
  } catch (error) {
10541
10754
  return { ok: false, output: `\u274C [\u6D3E\u751F\u6267\u884C\u5931\u8D25]: ${error.message}`, sessionId: subSessionId, manifestName: manifest?.name };
10755
+ } finally {
10756
+ activeSubagents.delete(subSessionId);
10542
10757
  }
10543
10758
  };
10544
10759
  }
10545
10760
  });
10546
10761
 
10547
10762
  // ../core/src/hooks/loader.ts
10548
- import fs27 from "fs/promises";
10549
- import path29 from "path";
10763
+ import fs28 from "fs/promises";
10764
+ import path30 from "path";
10550
10765
  var readHooksConfig, appendValidated, validateRule, parseStdoutDecision, parseAgentDecision, compileRule2, loadHooks, initHooks;
10551
10766
  var init_loader4 = __esm({
10552
10767
  "../core/src/hooks/loader.ts"() {
@@ -10561,15 +10776,15 @@ var init_loader4 = __esm({
10561
10776
  readHooksConfig = async (includeProject) => {
10562
10777
  const merged = {};
10563
10778
  const paths = [
10564
- path29.join(appConfig.dataDir, "settings.json"),
10779
+ path30.join(appConfig.dataDir, "settings.json"),
10565
10780
  // 全局用户级
10566
- ...includeProject ? [path29.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
10781
+ ...includeProject ? [path30.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
10567
10782
  // 项目级(叠加);未信任时省略
10568
10783
  ];
10569
10784
  for (const configPath of paths) {
10570
10785
  let raw;
10571
10786
  try {
10572
- raw = await fs27.readFile(configPath, "utf-8");
10787
+ raw = await fs28.readFile(configPath, "utf-8");
10573
10788
  } catch {
10574
10789
  continue;
10575
10790
  }
@@ -10899,9 +11114,9 @@ ${m.context}`;
10899
11114
  });
10900
11115
 
10901
11116
  // ../core/src/skills/loader.ts
10902
- import fs28 from "fs/promises";
10903
- import path30 from "path";
10904
- import { fileURLToPath } from "url";
11117
+ import fs29 from "fs/promises";
11118
+ import path31 from "path";
11119
+ import { fileURLToPath as fileURLToPath2 } from "url";
10905
11120
  var BUILTIN_DIR, SOURCES2, MAX_SKILL_BODY_BYTES, splitList, parseSkillAt, loadSkills, initSkills;
10906
11121
  var init_loader5 = __esm({
10907
11122
  "../core/src/skills/loader.ts"() {
@@ -10911,18 +11126,18 @@ var init_loader5 = __esm({
10911
11126
  init_registry3();
10912
11127
  init_skill();
10913
11128
  init_registry2();
10914
- BUILTIN_DIR = path30.join(path30.dirname(fileURLToPath(import.meta.url)), "builtin");
11129
+ BUILTIN_DIR = path31.join(path31.dirname(fileURLToPath2(import.meta.url)), "builtin");
10915
11130
  SOURCES2 = [
10916
11131
  { dir: BUILTIN_DIR, source: "builtin" },
10917
- { dir: path30.join(appConfig.dataDir, "skills"), source: "global" },
10918
- { dir: path30.join(process.cwd(), ".deepseeker-code", "skills"), source: "project" }
11132
+ { dir: path31.join(appConfig.dataDir, "skills"), source: "global" },
11133
+ { dir: path31.join(process.cwd(), ".deepseeker-code", "skills"), source: "project" }
10919
11134
  ];
10920
11135
  MAX_SKILL_BODY_BYTES = 64 * 1024;
10921
11136
  splitList = (raw) => (raw ?? "").split(",").map((s) => s.trim()).filter(Boolean);
10922
11137
  parseSkillAt = async (skillFile, dir, source) => {
10923
11138
  let raw;
10924
11139
  try {
10925
- raw = await fs28.readFile(skillFile, "utf-8");
11140
+ raw = await fs29.readFile(skillFile, "utf-8");
10926
11141
  } catch {
10927
11142
  return null;
10928
11143
  }
@@ -10961,7 +11176,7 @@ var init_loader5 = __esm({
10961
11176
  loadSkills = async (includeProject) => {
10962
11177
  const picked = await scanSources(
10963
11178
  filterSources(SOURCES2, includeProject),
10964
- (e, dir) => e.isDirectory() ? path30.join(dir, e.name, "SKILL.md") : void 0,
11179
+ (e, dir) => e.isDirectory() ? path31.join(dir, e.name, "SKILL.md") : void 0,
10965
11180
  parseSkillAt
10966
11181
  );
10967
11182
  for (const { item } of picked) registerSkill(item);
@@ -10992,9 +11207,9 @@ var init_loader5 = __esm({
10992
11207
  });
10993
11208
 
10994
11209
  // ../core/src/agents/loader.ts
10995
- import fs29 from "fs/promises";
10996
- import path31 from "path";
10997
- import { fileURLToPath as fileURLToPath2 } from "url";
11210
+ import fs30 from "fs/promises";
11211
+ import path32 from "path";
11212
+ import { fileURLToPath as fileURLToPath3 } from "url";
10998
11213
  var BUILTIN_DIR2, SOURCES3, parseAgentAt, initAgents;
10999
11214
  var init_loader6 = __esm({
11000
11215
  "../core/src/agents/loader.ts"() {
@@ -11003,16 +11218,16 @@ var init_loader6 = __esm({
11003
11218
  init_frontmatter();
11004
11219
  init_registry4();
11005
11220
  init_registry2();
11006
- BUILTIN_DIR2 = path31.join(path31.dirname(fileURLToPath2(import.meta.url)), "builtin");
11221
+ BUILTIN_DIR2 = path32.join(path32.dirname(fileURLToPath3(import.meta.url)), "builtin");
11007
11222
  SOURCES3 = [
11008
11223
  { dir: BUILTIN_DIR2, source: "builtin" },
11009
- { dir: path31.join(appConfig.dataDir, "agents"), source: "global" },
11010
- { dir: path31.join(process.cwd(), ".deepseeker-code", "agents"), source: "project" }
11224
+ { dir: path32.join(appConfig.dataDir, "agents"), source: "global" },
11225
+ { dir: path32.join(process.cwd(), ".deepseeker-code", "agents"), source: "project" }
11011
11226
  ];
11012
11227
  parseAgentAt = async (file, dir, source) => {
11013
11228
  let raw;
11014
11229
  try {
11015
- raw = await fs29.readFile(file, "utf-8");
11230
+ raw = await fs30.readFile(file, "utf-8");
11016
11231
  } catch {
11017
11232
  return null;
11018
11233
  }
@@ -11047,7 +11262,7 @@ var init_loader6 = __esm({
11047
11262
  const known = new Set(into.map((t) => t.function.name));
11048
11263
  const picked = await scanSources(
11049
11264
  filterSources(SOURCES3, includeProject),
11050
- (e, dir) => e.isFile() && e.name.endsWith(".agent.md") ? path31.join(dir, e.name) : void 0,
11265
+ (e, dir) => e.isFile() && e.name.endsWith(".agent.md") ? path32.join(dir, e.name) : void 0,
11051
11266
  parseAgentAt
11052
11267
  );
11053
11268
  for (const { item: m, file, source } of picked) {
@@ -11084,9 +11299,9 @@ var init_registry7 = __esm({
11084
11299
  });
11085
11300
 
11086
11301
  // ../core/src/commands/loader.ts
11087
- import fs30 from "fs/promises";
11088
- import path32 from "path";
11089
- import { fileURLToPath as fileURLToPath3 } from "url";
11302
+ import fs31 from "fs/promises";
11303
+ import path33 from "path";
11304
+ import { fileURLToPath as fileURLToPath4 } from "url";
11090
11305
  var BUILTIN_DIR3, SOURCES4, MAX_COMMAND_BODY_BYTES, parseCommandAt, loadCommands, initCommands;
11091
11306
  var init_loader7 = __esm({
11092
11307
  "../core/src/commands/loader.ts"() {
@@ -11095,17 +11310,17 @@ var init_loader7 = __esm({
11095
11310
  init_frontmatter();
11096
11311
  init_registry7();
11097
11312
  init_registry2();
11098
- BUILTIN_DIR3 = path32.join(path32.dirname(fileURLToPath3(import.meta.url)), "builtin");
11313
+ BUILTIN_DIR3 = path33.join(path33.dirname(fileURLToPath4(import.meta.url)), "builtin");
11099
11314
  SOURCES4 = [
11100
11315
  { dir: BUILTIN_DIR3, source: "builtin" },
11101
- { dir: path32.join(appConfig.dataDir, "commands"), source: "global" },
11102
- { dir: path32.join(process.cwd(), ".deepseeker-code", "commands"), source: "project" }
11316
+ { dir: path33.join(appConfig.dataDir, "commands"), source: "global" },
11317
+ { dir: path33.join(process.cwd(), ".deepseeker-code", "commands"), source: "project" }
11103
11318
  ];
11104
11319
  MAX_COMMAND_BODY_BYTES = 64 * 1024;
11105
11320
  parseCommandAt = async (file, _dir, source) => {
11106
11321
  let raw;
11107
11322
  try {
11108
- raw = await fs30.readFile(file, "utf-8");
11323
+ raw = await fs31.readFile(file, "utf-8");
11109
11324
  } catch {
11110
11325
  return null;
11111
11326
  }
@@ -11116,7 +11331,7 @@ var init_loader7 = __esm({
11116
11331
  }
11117
11332
  const name = parsed.frontmatter.name;
11118
11333
  const description = parsed.frontmatter.description;
11119
- const fallbackName = path32.basename(file, ".md");
11334
+ const fallbackName = path33.basename(file, ".md");
11120
11335
  const finalName = name || fallbackName;
11121
11336
  if (!description) {
11122
11337
  console.warn(`\u26A0\uFE0F [commands] \u7F3A\u5C11 description\uFF08${file}\uFF09\uFF0C\u5DF2\u8DF3\u8FC7`);
@@ -11142,7 +11357,7 @@ var init_loader7 = __esm({
11142
11357
  loadCommands = async (includeProject) => {
11143
11358
  const picked = await scanSources(
11144
11359
  filterSources(SOURCES4, includeProject),
11145
- (e, dir) => e.isFile() && e.name.endsWith(".md") ? path32.join(dir, e.name) : void 0,
11360
+ (e, dir) => e.isFile() && e.name.endsWith(".md") ? path33.join(dir, e.name) : void 0,
11146
11361
  parseCommandAt
11147
11362
  );
11148
11363
  for (const { item } of picked) registerCommand(item);
@@ -11160,9 +11375,9 @@ var init_loader7 = __esm({
11160
11375
  });
11161
11376
 
11162
11377
  // ../core/src/outputStyles/loader.ts
11163
- import fs31 from "fs/promises";
11164
- import path33 from "path";
11165
- import { fileURLToPath as fileURLToPath4 } from "url";
11378
+ import fs32 from "fs/promises";
11379
+ import path34 from "path";
11380
+ import { fileURLToPath as fileURLToPath5 } from "url";
11166
11381
  var BUILTIN_DIR4, MAX_STYLE_BODY_BYTES, SOURCES5, parseStyleAt, loadOutputStyles, initOutputStyles;
11167
11382
  var init_loader8 = __esm({
11168
11383
  "../core/src/outputStyles/loader.ts"() {
@@ -11171,17 +11386,17 @@ var init_loader8 = __esm({
11171
11386
  init_frontmatter();
11172
11387
  init_registry5();
11173
11388
  init_registry2();
11174
- BUILTIN_DIR4 = path33.join(path33.dirname(fileURLToPath4(import.meta.url)), "builtin");
11389
+ BUILTIN_DIR4 = path34.join(path34.dirname(fileURLToPath5(import.meta.url)), "builtin");
11175
11390
  MAX_STYLE_BODY_BYTES = 64 * 1024;
11176
11391
  SOURCES5 = [
11177
11392
  { dir: BUILTIN_DIR4, source: "builtin" },
11178
- { dir: path33.join(appConfig.dataDir, "output-styles"), source: "global" },
11179
- { dir: path33.join(process.cwd(), ".deepseeker-code", "output-styles"), source: "project" }
11393
+ { dir: path34.join(appConfig.dataDir, "output-styles"), source: "global" },
11394
+ { dir: path34.join(process.cwd(), ".deepseeker-code", "output-styles"), source: "project" }
11180
11395
  ];
11181
11396
  parseStyleAt = async (file, _dir, source) => {
11182
11397
  let raw;
11183
11398
  try {
11184
- raw = await fs31.readFile(file, "utf-8");
11399
+ raw = await fs32.readFile(file, "utf-8");
11185
11400
  } catch {
11186
11401
  return null;
11187
11402
  }
@@ -11213,7 +11428,7 @@ var init_loader8 = __esm({
11213
11428
  loadOutputStyles = async (includeProject) => {
11214
11429
  const picked = await scanSources(
11215
11430
  filterSources(SOURCES5, includeProject),
11216
- (e, dir) => e.isFile() && e.name.endsWith(".md") ? path33.join(dir, e.name) : void 0,
11431
+ (e, dir) => e.isFile() && e.name.endsWith(".md") ? path34.join(dir, e.name) : void 0,
11217
11432
  parseStyleAt
11218
11433
  );
11219
11434
  for (const { item } of picked) registerOutputStyle(item);
@@ -11294,8 +11509,8 @@ var init_bootstrap = __esm({
11294
11509
  });
11295
11510
 
11296
11511
  // ../core/src/statusLine/config.ts
11297
- import fs32 from "fs/promises";
11298
- import path34 from "path";
11512
+ import fs33 from "fs/promises";
11513
+ import path35 from "path";
11299
11514
  var parseBlock, readStatusLineConfig;
11300
11515
  var init_config2 = __esm({
11301
11516
  "../core/src/statusLine/config.ts"() {
@@ -11311,16 +11526,16 @@ var init_config2 = __esm({
11311
11526
  };
11312
11527
  readStatusLineConfig = async (includeProject) => {
11313
11528
  const paths = [
11314
- path34.join(appConfig.dataDir, "settings.json"),
11529
+ path35.join(appConfig.dataDir, "settings.json"),
11315
11530
  // 全局用户级
11316
- ...includeProject ? [path34.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
11531
+ ...includeProject ? [path35.join(process.cwd(), ".deepseeker-code", "settings.json")] : []
11317
11532
  // 项目级(覆盖);未信任时省略
11318
11533
  ];
11319
11534
  let result = null;
11320
11535
  for (const configPath of paths) {
11321
11536
  let raw;
11322
11537
  try {
11323
- raw = await fs32.readFile(configPath, "utf-8");
11538
+ raw = await fs33.readFile(configPath, "utf-8");
11324
11539
  } catch {
11325
11540
  continue;
11326
11541
  }
@@ -11340,9 +11555,9 @@ var init_config2 = __esm({
11340
11555
 
11341
11556
  // ../core/src/statusLine/runner.ts
11342
11557
  import { spawn as spawn5 } from "child_process";
11343
- import fs33 from "fs";
11344
- import path35 from "path";
11345
- import { fileURLToPath as fileURLToPath5 } from "url";
11558
+ import fs34 from "fs";
11559
+ import path36 from "path";
11560
+ import { fileURLToPath as fileURLToPath6 } from "url";
11346
11561
  var STATUSLINE_TIMEOUT_MS, cachedVersion, runStatusLine;
11347
11562
  var init_runner = __esm({
11348
11563
  "../core/src/statusLine/runner.ts"() {
@@ -11350,16 +11565,16 @@ var init_runner = __esm({
11350
11565
  init_guard();
11351
11566
  STATUSLINE_TIMEOUT_MS = 3e3;
11352
11567
  try {
11353
- const here = path35.dirname(fileURLToPath5(import.meta.url));
11568
+ const here = path36.dirname(fileURLToPath6(import.meta.url));
11354
11569
  const candidates = [
11355
- path35.join(here, "../../../package.json"),
11570
+ path36.join(here, "../../../package.json"),
11356
11571
  // src/core/package.json
11357
- path35.join(here, "../../../../package.json")
11572
+ path36.join(here, "../../../../package.json")
11358
11573
  // 仓库根 package.json
11359
11574
  ];
11360
11575
  for (const p of candidates) {
11361
11576
  try {
11362
- const pkg = JSON.parse(fs33.readFileSync(p, "utf-8"));
11577
+ const pkg = JSON.parse(fs34.readFileSync(p, "utf-8"));
11363
11578
  if (typeof pkg.version === "string" && pkg.version) {
11364
11579
  cachedVersion = pkg.version;
11365
11580
  break;
@@ -11418,8 +11633,8 @@ var init_createModel = __esm({
11418
11633
  });
11419
11634
 
11420
11635
  // ../core/src/observability/store.ts
11421
- import path36 from "path";
11422
- import fs34 from "fs/promises";
11636
+ import path37 from "path";
11637
+ import fs35 from "fs/promises";
11423
11638
  var getTraceDirPath, getTracePath, tracePathCache, ensuredTraceDirs, ensureTraceDir, getGlobalClockPath, getTraceStorePath;
11424
11639
  var init_store3 = __esm({
11425
11640
  "../core/src/observability/store.ts"() {
@@ -11429,21 +11644,21 @@ var init_store3 = __esm({
11429
11644
  init_common();
11430
11645
  getTraceDirPath = (mainTraceId) => {
11431
11646
  assertSafeSessionId(mainTraceId, "traceId");
11432
- return path36.join(appConfig.dataDir, "trace", appConfig.userWorkspaceDir, getFileName(mainTraceId));
11647
+ return path37.join(appConfig.dataDir, "trace", appConfig.userWorkspaceDir, getFileName(mainTraceId));
11433
11648
  };
11434
11649
  getTracePath = () => {
11435
- return path36.join(appConfig.dataDir, "trace");
11650
+ return path37.join(appConfig.dataDir, "trace");
11436
11651
  };
11437
11652
  tracePathCache = /* @__PURE__ */ new Map();
11438
11653
  ensuredTraceDirs = /* @__PURE__ */ new Set();
11439
11654
  ensureTraceDir = async (mainTraceId) => {
11440
11655
  const dir = getTraceDirPath(mainTraceId);
11441
11656
  if (ensuredTraceDirs.has(dir)) return;
11442
- await fs34.mkdir(dir, { recursive: true });
11657
+ await fs35.mkdir(dir, { recursive: true });
11443
11658
  ensuredTraceDirs.add(dir);
11444
11659
  };
11445
11660
  getGlobalClockPath = () => {
11446
- return path36.join(getTracePath(), "trace-cleanup-clock.json");
11661
+ return path37.join(getTracePath(), "trace-cleanup-clock.json");
11447
11662
  };
11448
11663
  getTraceStorePath = async (mainTraceId) => {
11449
11664
  assertSafeSessionId(mainTraceId, "traceId");
@@ -11452,7 +11667,7 @@ var init_store3 = __esm({
11452
11667
  if (cached2) return cached2;
11453
11668
  await ensureTraceDir(rootId);
11454
11669
  const dir = getTraceDirPath(rootId);
11455
- const files = await fs34.readdir(dir);
11670
+ const files = await fs35.readdir(dir);
11456
11671
  const existedFile = files.find((f) => f.endsWith(`__${rootId}.jsonl`));
11457
11672
  let fileName = "";
11458
11673
  if (existedFile) {
@@ -11461,7 +11676,7 @@ var init_store3 = __esm({
11461
11676
  const todayStr = getTodayDateString();
11462
11677
  fileName = `trace-${todayStr}__${rootId}.jsonl`;
11463
11678
  }
11464
- const resolved = path36.join(dir, fileName);
11679
+ const resolved = path37.join(dir, fileName);
11465
11680
  tracePathCache.set(rootId, resolved);
11466
11681
  return resolved;
11467
11682
  };
@@ -11469,8 +11684,8 @@ var init_store3 = __esm({
11469
11684
  });
11470
11685
 
11471
11686
  // ../core/src/observability/trace.ts
11472
- import fs35 from "fs/promises";
11473
- import path37 from "path";
11687
+ import fs36 from "fs/promises";
11688
+ import path38 from "path";
11474
11689
  async function emitTrace(base) {
11475
11690
  const event = {
11476
11691
  sessionId: base.sessionId,
@@ -11492,7 +11707,7 @@ async function emitTrace(base) {
11492
11707
  async function appendTraceEvent(event) {
11493
11708
  const p = await getTraceStorePath(event.sessionId);
11494
11709
  const line = JSON.stringify(event) + "\n";
11495
- await fs35.appendFile(p, line, "utf-8");
11710
+ await fs36.appendFile(p, line, "utf-8");
11496
11711
  if (workspaceTraceBytes < 0) {
11497
11712
  workspaceTraceBytes = await getDirBytes(getTracePath());
11498
11713
  }
@@ -11524,8 +11739,8 @@ async function maybeCleanupAfterAppend(sessionId) {
11524
11739
  lastSizeCleanupAt2 = now;
11525
11740
  diskLastCleanupAt2 = now;
11526
11741
  const clockPath = getGlobalClockPath();
11527
- await fs35.mkdir(path37.dirname(clockPath), { recursive: true });
11528
- await fs35.writeFile(clockPath, JSON.stringify({ lastCleanupAt: now, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), "utf-8");
11742
+ await fs36.mkdir(path38.dirname(clockPath), { recursive: true });
11743
+ await fs36.writeFile(clockPath, JSON.stringify({ lastCleanupAt: now, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), "utf-8");
11529
11744
  if (deletedCount > 0) {
11530
11745
  console.log(`\u2728 [Trace\u8FD0\u7EF4] \u5171\u9500\u6BC1 ${deletedCount} \u4E2A\u4F1A\u8BDD\u65E5\u5FD7\uFF08\u8F6F\u89C4\u5219\u8FC7\u671F\u6E05\u7406 + \u5BB9\u91CF\u786C\u9A71\u9010\uFF09\uFF0C\u78C1\u76D8\u6C34\u4F4D\u56DE\u843D\u3002`);
11531
11746
  }
@@ -11545,22 +11760,22 @@ async function cleanupOldTraceFiles() {
11545
11760
  let deleted = 0;
11546
11761
  let relativePaths;
11547
11762
  try {
11548
- relativePaths = await fs35.readdir(dir, { recursive: true });
11763
+ relativePaths = await fs36.readdir(dir, { recursive: true });
11549
11764
  } catch {
11550
11765
  return 0;
11551
11766
  }
11552
11767
  const re = /^trace-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
11553
11768
  for (const relativePath of relativePaths) {
11554
- const fileName = path37.basename(relativePath);
11769
+ const fileName = path38.basename(relativePath);
11555
11770
  const m = fileName.match(re);
11556
11771
  if (!m) continue;
11557
11772
  const fileBornDay = /* @__PURE__ */ new Date(`${m[1]}T00:00:00`);
11558
11773
  if (fileBornDay >= cutoff) continue;
11559
- const fullPath = path37.join(dir, relativePath);
11774
+ const fullPath = path38.join(dir, relativePath);
11560
11775
  try {
11561
- const st = await fs35.stat(fullPath);
11776
+ const st = await fs36.stat(fullPath);
11562
11777
  if (now - st.mtimeMs < ACTIVE_GRACE_MS2) continue;
11563
- await fs35.unlink(fullPath);
11778
+ await fs36.unlink(fullPath);
11564
11779
  deleted += 1;
11565
11780
  } catch {
11566
11781
  }
@@ -11571,18 +11786,18 @@ async function evictOldestForSize2(targetBytes) {
11571
11786
  const dir = getTracePath();
11572
11787
  let relativePaths;
11573
11788
  try {
11574
- relativePaths = await fs35.readdir(dir, { recursive: true });
11789
+ relativePaths = await fs36.readdir(dir, { recursive: true });
11575
11790
  } catch {
11576
11791
  return 0;
11577
11792
  }
11578
11793
  const re = /^trace-(\d{4}-\d{2}-\d{2})__([\w-]+)\.jsonl$/;
11579
11794
  const candidates = [];
11580
11795
  for (const relativePath of relativePaths) {
11581
- const fileName = path37.basename(relativePath);
11796
+ const fileName = path38.basename(relativePath);
11582
11797
  if (!re.test(fileName)) continue;
11583
11798
  try {
11584
- const st = await fs35.stat(path37.join(dir, relativePath));
11585
- candidates.push({ mtime: st.mtimeMs, fullPath: path37.join(dir, relativePath), size: st.size });
11799
+ const st = await fs36.stat(path38.join(dir, relativePath));
11800
+ candidates.push({ mtime: st.mtimeMs, fullPath: path38.join(dir, relativePath), size: st.size });
11586
11801
  } catch {
11587
11802
  }
11588
11803
  }
@@ -11592,7 +11807,7 @@ async function evictOldestForSize2(targetBytes) {
11592
11807
  for (const c of candidates) {
11593
11808
  if (totalBytes <= targetBytes) break;
11594
11809
  try {
11595
- await fs35.unlink(c.fullPath);
11810
+ await fs36.unlink(c.fullPath);
11596
11811
  totalBytes -= c.size;
11597
11812
  deleted += 1;
11598
11813
  } catch {
@@ -11624,7 +11839,7 @@ var init_trace = __esm({
11624
11839
  if (clockLoaded2) return;
11625
11840
  clockLoaded2 = true;
11626
11841
  try {
11627
- const rawClock = await fs35.readFile(getGlobalClockPath(), "utf-8");
11842
+ const rawClock = await fs36.readFile(getGlobalClockPath(), "utf-8");
11628
11843
  diskLastCleanupAt2 = JSON.parse(rawClock).lastCleanupAt || 0;
11629
11844
  } catch {
11630
11845
  diskLastCleanupAt2 = 0;
@@ -11643,6 +11858,7 @@ var pendingLocks, waitForUserApproval, resolveUserApprovalLock;
11643
11858
  var init_approvalGate = __esm({
11644
11859
  "../core/src/tool/approvalGate.ts"() {
11645
11860
  "use strict";
11861
+ init_lineage();
11646
11862
  pendingLocks = /* @__PURE__ */ new Map();
11647
11863
  waitForUserApproval = async (sessionId, toolsId, signal) => {
11648
11864
  if (signal?.aborted) return "deny";
@@ -11670,7 +11886,7 @@ var init_approvalGate = __esm({
11670
11886
  resolveUserApprovalLock = (sessionId, toolsId, decision) => {
11671
11887
  const entry = pendingLocks.get(toolsId);
11672
11888
  if (!entry) return false;
11673
- const isOwner = entry.sessionId === sessionId || entry.sessionId.startsWith(`${sessionId}__sub__`);
11889
+ const isOwner = ownerCanApprove(entry.sessionId, sessionId);
11674
11890
  if (!isOwner) return false;
11675
11891
  entry.resolver(decision);
11676
11892
  pendingLocks.delete(toolsId);
@@ -11769,8 +11985,8 @@ ${PLAN_MODE_AUTO_ENTER_HINT}
11769
11985
  });
11770
11986
 
11771
11987
  // ../core/src/serve/chatProcessing.ts
11772
- import path38 from "path";
11773
- import fs36 from "fs";
11988
+ import path39 from "path";
11989
+ import fs37 from "fs";
11774
11990
  var handleUnifiedChat;
11775
11991
  var init_chatProcessing = __esm({
11776
11992
  "../core/src/serve/chatProcessing.ts"() {
@@ -11824,17 +12040,17 @@ ${inject}`;
11824
12040
  if (roots.length > 1) {
11825
12041
  let activeReal = getActiveWorkspaceRoot();
11826
12042
  try {
11827
- activeReal = fs36.realpathSync(activeReal);
12043
+ activeReal = fs37.realpathSync(activeReal);
11828
12044
  } catch {
11829
12045
  }
11830
- const lines = roots.map((r) => `- ${path38.basename(r) || r}: ${r}${r === activeReal ? "\uFF08\u9ED8\u8BA4\u6839\uFF1A\u76F8\u5BF9\u8DEF\u5F84/\u547D\u4EE4\u57FA\u51C6\uFF09" : "\uFF08\u53EF\u76F4\u63A5\u8BFB\u5199\uFF09"}`);
12046
+ const lines = roots.map((r) => `- ${path39.basename(r) || r}: ${r}${r === activeReal ? "\uFF08\u9ED8\u8BA4\u6839\uFF1A\u76F8\u5BF9\u8DEF\u5F84/\u547D\u4EE4\u57FA\u51C6\uFF09" : "\uFF08\u53EF\u76F4\u63A5\u8BFB\u5199\uFF09"}`);
11831
12047
  sysPrompt = sysPrompt + `
11832
12048
 
11833
12049
  \u3010\u5DE5\u4F5C\u533A\uFF08\u591A\u9879\u76EE\uFF09\u3011
11834
12050
  \u65E0\u9700\u5207\u6362\u9879\u76EE\uFF0C\u4EE5\u4E0B\u6240\u6709\u6839\u90FD\u53EF\u76F4\u63A5\u7528\u7EDD\u5BF9\u8DEF\u5F84\u8BBF\u95EE\uFF1B\u8DE8\u9879\u76EE\u7528\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u9ED8\u8BA4\u6839\u7684 ../<\u5144\u5F1F\u76EE\u5F55>:
11835
12051
  ${lines.join("\n")}
11836
- \u2605 \u8DEF\u5F84\u951A\u5B9A\u94C1\u5F8B\uFF1A\u5DE5\u5177\u7F3A\u7701\u53EA\u4F5C\u7528\u4E8E\u9ED8\u8BA4\u6839\uFF08${path38.basename(activeReal) || activeReal} = IDE \u5934\u90E8\u6240\u793A\u6839\uFF09\u3002\u5F53\u7528\u6237\u5728\u5BF9\u8BDD\u4E2D\u6307\u660E\u4E86\u67D0\u4E2A\u9879\u76EE\uFF08\u5982\u300C\u5728 A \u9879\u76EE\u300D\u300C\u6539\u524D\u7AEF\u7684 xxx\u300D\u300C\u641C\u540E\u7AEF\u300D\uFF09\uFF0C\u8BE5\u8F6E\u6240\u6709\u5E26 path \u53C2\u6570\u7684\u5DE5\u5177\u8C03\u7528\uFF08read_file / edit_file / search_grep / glob / list_dir / read_xlsx / read_docx \u7B49\uFF09\u5FC5\u987B\u628A\u5BF9\u5E94\u9879\u76EE\u6839\u4F5C\u4E3A path \u4F20\u5165\uFF08\u7EDD\u5BF9\u8DEF\u5F84\u3001../<\u5144\u5F1F\u76EE\u5F55>\u3001\u6216\u9879\u76EE\u76EE\u5F55\u540D\uFF09\uFF0C\u5426\u5219\u53EA\u4F1A\u8BFB\u5199/\u641C\u7D22\u9ED8\u8BA4\u6839\uFF0C\u4E0E\u7528\u6237\u610F\u56FE\u4E0D\u7B26\u3002
11837
- \u6CE8\u610F\uFF1A\u9879\u76EE\u7EA7\u914D\u7F6E\uFF08.deepseeker-code/\uFF09\u4EC5\u5728\u9ED8\u8BA4\u6839 ${path38.basename(activeReal) || activeReal} \u751F\u6548\u3002`;
12052
+ \u2605 \u8DEF\u5F84\u951A\u5B9A\u94C1\u5F8B\uFF1A\u5DE5\u5177\u7F3A\u7701\u53EA\u4F5C\u7528\u4E8E\u9ED8\u8BA4\u6839\uFF08${path39.basename(activeReal) || activeReal} = IDE \u5934\u90E8\u6240\u793A\u6839\uFF09\u3002\u5F53\u7528\u6237\u5728\u5BF9\u8BDD\u4E2D\u6307\u660E\u4E86\u67D0\u4E2A\u9879\u76EE\uFF08\u5982\u300C\u5728 A \u9879\u76EE\u300D\u300C\u6539\u524D\u7AEF\u7684 xxx\u300D\u300C\u641C\u540E\u7AEF\u300D\uFF09\uFF0C\u8BE5\u8F6E\u6240\u6709\u5E26 path \u53C2\u6570\u7684\u5DE5\u5177\u8C03\u7528\uFF08read_file / edit_file / search_grep / glob / list_dir / read_xlsx / read_docx \u7B49\uFF09\u5FC5\u987B\u628A\u5BF9\u5E94\u9879\u76EE\u6839\u4F5C\u4E3A path \u4F20\u5165\uFF08\u7EDD\u5BF9\u8DEF\u5F84\u3001../<\u5144\u5F1F\u76EE\u5F55>\u3001\u6216\u9879\u76EE\u76EE\u5F55\u540D\uFF09\uFF0C\u5426\u5219\u53EA\u4F1A\u8BFB\u5199/\u641C\u7D22\u9ED8\u8BA4\u6839\uFF0C\u4E0E\u7528\u6237\u610F\u56FE\u4E0D\u7B26\u3002
12053
+ \u6CE8\u610F\uFF1A\u9879\u76EE\u7EA7\u914D\u7F6E\uFF08.deepseeker-code/\uFF09\u4EC5\u5728\u9ED8\u8BA4\u6839 ${path39.basename(activeReal) || activeReal} \u751F\u6548\u3002`;
11838
12054
  }
11839
12055
  let replyText = "";
11840
12056
  try {
@@ -11921,7 +12137,7 @@ ${lines.join("\n")}
11921
12137
  });
11922
12138
 
11923
12139
  // ../core/src/session/fork.ts
11924
- import fs37 from "fs/promises";
12140
+ import fs38 from "fs/promises";
11925
12141
  var listForkAnchors, derivePrefix, forkSession;
11926
12142
  var init_fork = __esm({
11927
12143
  "../core/src/session/fork.ts"() {
@@ -11993,7 +12209,7 @@ var init_fork = __esm({
11993
12209
  const prefix = derivePrefix(lines, upToLineId);
11994
12210
  const newId = createUUID();
11995
12211
  await ensureSessionsDir(newId);
11996
- const rawText = await fs37.readFile(getTranscriptPath(sourceId), "utf-8");
12212
+ const rawText = await fs38.readFile(getTranscriptPath(sourceId), "utf-8");
11997
12213
  const kept = [];
11998
12214
  let good = 0;
11999
12215
  for (const s of rawText.split("\n")) {
@@ -12009,7 +12225,7 @@ var init_fork = __esm({
12009
12225
  }
12010
12226
  let payload = kept.join("\n");
12011
12227
  if (payload.length > 0 && !payload.endsWith("\n")) payload += "\n";
12012
- await fs37.writeFile(getTranscriptPath(newId), payload, "utf-8");
12228
+ await fs38.writeFile(getTranscriptPath(newId), payload, "utf-8");
12013
12229
  const srcState = await readStore(sourceId);
12014
12230
  const srcRolling = await getRollingState(sourceId);
12015
12231
  const legacy = !lines.some(isEventLine);
@@ -12025,6 +12241,9 @@ var init_fork = __esm({
12025
12241
  rollingSummary,
12026
12242
  consecutiveFailures: 0,
12027
12243
  title: `${srcTitle}(\u5206\u53C9)`.slice(0, 200),
12244
+ // ★ fork 血缘元数据:新 ID 是纯 UUID(字符串上无痕),血缘回溯全靠此字段
12245
+ // (session/lineage.ts 消费:审批网关归属 / 子 Agent 续跑归属)。
12246
+ forkedFrom: sourceId,
12028
12247
  // ★ 校准数据透传:fork 首轮压缩判定不从 1.4 重来(纯收益,语义同源会话续接)
12029
12248
  calibRatio: srcRolling.calibRatio,
12030
12249
  lastRealPromptTokens: srcRolling.lastRealPromptTokens,
@@ -13703,7 +13922,7 @@ var init_TopPanel = __esm({
13703
13922
  });
13704
13923
 
13705
13924
  // src/inspect.ts
13706
- import fs38 from "fs";
13925
+ import fs39 from "fs";
13707
13926
  var CWD, fmt, readTrace, inspectUsage, inspectContext, inspectPermissions, inspectMcp, inspectHooks, inspectDebug;
13708
13927
  var init_inspect = __esm({
13709
13928
  "src/inspect.ts"() {
@@ -13721,7 +13940,7 @@ var init_inspect = __esm({
13721
13940
  if (!sessionId) return [];
13722
13941
  try {
13723
13942
  const p = await getTraceStorePath(sessionId);
13724
- const text = await fs38.promises.readFile(p, "utf8");
13943
+ const text = await fs39.promises.readFile(p, "utf8");
13725
13944
  const out = [];
13726
13945
  for (const line of text.split("\n")) {
13727
13946
  if (!line.trim()) continue;
@@ -14412,81 +14631,6 @@ ${listText}`);
14412
14631
  }
14413
14632
  });
14414
14633
 
14415
- // src/updateCheck.ts
14416
- var updateCheck_exports = {};
14417
- __export(updateCheck_exports, {
14418
- getCachedLatestIfNewer: () => getCachedLatestIfNewer,
14419
- readLocalVersion: () => readLocalVersion,
14420
- refreshUpdateCache: () => refreshUpdateCache
14421
- });
14422
- import { readFileSync as readFileSync4, writeFileSync, mkdirSync } from "node:fs";
14423
- import path39 from "node:path";
14424
- import os4 from "os";
14425
- import { fileURLToPath as fileURLToPath6 } from "node:url";
14426
- var PKG_NAME, REGISTRY, CACHE_TTL_MS, FETCH_TIMEOUT_MS2, cacheFile, readLocalVersion, parseSemver, compareVersion, readCache, writeCache, getCachedLatestIfNewer, refreshUpdateCache;
14427
- var init_updateCheck = __esm({
14428
- "src/updateCheck.ts"() {
14429
- "use strict";
14430
- PKG_NAME = "deepseeker-code";
14431
- REGISTRY = "https://registry.npmjs.org";
14432
- CACHE_TTL_MS = 6 * 60 * 60 * 1e3;
14433
- FETCH_TIMEOUT_MS2 = 3e3;
14434
- cacheFile = () => path39.join(os4.homedir(), ".deepseeker-code", "update-check.json");
14435
- readLocalVersion = () => {
14436
- try {
14437
- const here = path39.dirname(fileURLToPath6(import.meta.url));
14438
- return JSON.parse(readFileSync4(path39.join(here, "..", "package.json"), "utf8")).version ?? "0.0.0";
14439
- } catch {
14440
- return "0.0.0";
14441
- }
14442
- };
14443
- parseSemver = (v) => {
14444
- const m = String(v ?? "").match(/^(\d+)\.(\d+)\.(\d+)/);
14445
- return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : [0, 0, 0];
14446
- };
14447
- compareVersion = (a, b) => {
14448
- const [a1, a2, a3] = parseSemver(a);
14449
- const [b1, b2, b3] = parseSemver(b);
14450
- return a1 - b1 || a2 - b2 || a3 - b3;
14451
- };
14452
- readCache = () => {
14453
- try {
14454
- const obj = JSON.parse(readFileSync4(cacheFile(), "utf8"));
14455
- return typeof obj.latestVersion === "string" && typeof obj.lastCheck === "number" ? obj : null;
14456
- } catch {
14457
- return null;
14458
- }
14459
- };
14460
- writeCache = (latestVersion) => {
14461
- try {
14462
- mkdirSync(path39.dirname(cacheFile()), { recursive: true });
14463
- writeFileSync(cacheFile(), JSON.stringify({ lastCheck: Date.now(), latestVersion }), "utf8");
14464
- } catch {
14465
- }
14466
- };
14467
- getCachedLatestIfNewer = (currentVersion) => {
14468
- const cache = readCache();
14469
- if (!cache) return null;
14470
- return compareVersion(cache.latestVersion, currentVersion) > 0 ? cache.latestVersion : null;
14471
- };
14472
- refreshUpdateCache = () => {
14473
- const cache = readCache();
14474
- if (cache && Date.now() - cache.lastCheck < CACHE_TTL_MS) return;
14475
- void (async () => {
14476
- try {
14477
- const res = await fetch(`${REGISTRY}/${PKG_NAME}/latest`, {
14478
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS2)
14479
- });
14480
- if (!res.ok) return;
14481
- const info = await res.json();
14482
- if (info.version) writeCache(info.version);
14483
- } catch {
14484
- }
14485
- })();
14486
- };
14487
- }
14488
- });
14489
-
14490
14634
  // src/preload-config.ts
14491
14635
  import { readFileSync } from "node:fs";
14492
14636
  import path from "node:path";
@@ -14534,6 +14678,7 @@ applyConfigToEnv(loadConfigFile());
14534
14678
  // src/main.tsx
14535
14679
  init_strings();
14536
14680
  init_prefs();
14681
+ init_updateCheck();
14537
14682
  init_trust();
14538
14683
  import { render } from "ink";
14539
14684
  import os5 from "os";
@@ -14550,6 +14695,7 @@ var parseArgs = (argv) => {
14550
14695
  else if (a === "--continue" || a === "-c") out.continue = true;
14551
14696
  else if (a === "--trust") out.trust = true;
14552
14697
  else if (a === "--no-update-check") out.noUpdateCheck = true;
14698
+ else if (a === "--version" || a === "-v") out.version = true;
14553
14699
  }
14554
14700
  return out;
14555
14701
  };
@@ -14610,6 +14756,11 @@ var main = async () => {
14610
14756
  console.debug = silence;
14611
14757
  console.warn = silence;
14612
14758
  const args = parseArgs(process.argv.slice(2));
14759
+ if (args.version) {
14760
+ process.stdout.write(`deepseeker-code v${readLocalVersion()}
14761
+ `);
14762
+ process.exit(0);
14763
+ }
14613
14764
  if (!process.env.DEEP_SEEK_API_KEY) {
14614
14765
  console.error(S.noApiKey("DEEP_SEEK_API_KEY"));
14615
14766
  process.exit(1);