dsh-loop-engine-allinone 0.7.2 → 0.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -8,6 +8,29 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
8
 
9
9
  Nothing yet.
10
10
 
11
+ ## [0.7.3]
12
+
13
+ ### Fixed
14
+
15
+ - **ZCode's path probe only worked on the author's machine.** The resolver and the
16
+ probe script both hardcoded `D:\Programs\ZCode\...` (and the probe also
17
+ `D:\Programs
18
+ pm-global`), so on any other host the "well-known location" check
19
+ silently never matched and a user with ZCode installed somewhere normal was told it
20
+ was not installed. Both now derive candidates from the environment:
21
+ `%ZCODE_HOME%` → `%LOCALAPPDATA%\Programs\ZCode` → `%ProgramFiles%\ZCode`, and
22
+ the probe's npm prefixes from the running npm configuration and the standard
23
+ per-machine layouts.
24
+ - A test run's probe output directory (`probe-out/`) was picked up by `git add -A`.
25
+ Removed, and ignored from now on.
26
+
27
+ ### Added
28
+
29
+ - **`ZCODE_HOME` is documented**, with a `zcodeBin` key in the configuration example.
30
+ ZCode ships as a desktop bundle rather than a plain executable, so a manual install
31
+ outside an installer-written root needs one of the two to be found — and the README
32
+ previously mentioned neither, which is why the gap went unnoticed.
33
+
11
34
  ## [0.7.2]
12
35
 
13
36
  ### Changed
package/README.md CHANGED
@@ -130,6 +130,7 @@ Custom settings can be configured under your profile's composition entry:
130
130
  qoderclicnBin: 'D:/tools/qoderclicn.exe'
131
131
  grokBin: 'C:/Users/user/.grok/bin/grok.exe'
132
132
  minimaxcodeBin: 'D:/npm-global/node_modules/@minimax-ai/code/cli.js'
133
+ zcodeBin: 'D:/Programs/ZCode/resources/glm/zcode.cjs'
133
134
 
134
135
  # 2. Region override (optional - MiniMax Code supports 'cn' or 'en')
135
136
  regions:
@@ -149,6 +150,12 @@ Custom settings can be configured under your profile's composition entry:
149
150
  summarizerModel: 'deepseek-flash'
150
151
  ```
151
152
 
153
+ **ZCode's install location.** ZCode ships as a desktop bundle rather than a plain
154
+ executable, so it is found by probing an install root: `%ZCODE_HOME%` first, then
155
+ `%LOCALAPPDATA%\Programs\ZCode` and `%ProgramFiles%\ZCode`. A manual install
156
+ anywhere else (`D:\Programs\ZCode`, say) is named either with the `ZCODE_HOME`
157
+ environment variable or with `bins.zcodeBin` — nothing hardcodes a drive letter.
158
+
152
159
  ---
153
160
 
154
161
  ## Usage Guide
package/README.zh.md CHANGED
@@ -124,6 +124,7 @@ dsh plugin --profile web add ./dsh-loop-engine-allinone
124
124
  qoderclicnBin: 'D:/tools/qoderclicn.exe'
125
125
  grokBin: 'C:/Users/username/.grok/bin/grok.exe'
126
126
  minimaxcodeBin: 'D:/npm-global/node_modules/@minimax-ai/code/cli.js'
127
+ zcodeBin: 'D:/Programs/ZCode/resources/glm/zcode.cjs'
127
128
 
128
129
  # 2. 账号区域设置(可选,MiniMax Code 支持 'cn' 或 'en')
129
130
  regions:
package/lib/index.js CHANGED
@@ -92,7 +92,7 @@ var __callDispose = (stack, error, hasError) => {
92
92
  import { existsSync as existsSync8, readFileSync as readFileSync5 } from "node:fs";
93
93
  import { mkdir as mkdir2, readFile as readFile6, rename as rename2, writeFile as writeFile2 } from "node:fs/promises";
94
94
  import { randomUUID as randomUUID3 } from "node:crypto";
95
- import { dirname as dirname7, join as join21 } from "node:path";
95
+ import { dirname as dirname7, join as join22 } from "node:path";
96
96
  import z12 from "@deepseek-ai/schemastery";
97
97
  import { resolveDshHome as resolveDshHome2 } from "@deepseek-ai/dsh-home-paths";
98
98
 
@@ -8669,11 +8669,27 @@ function textRunOutcome(result) {
8669
8669
 
8670
8670
  // src/engine-zcode/process.ts
8671
8671
  import { existsSync as existsSync3 } from "node:fs";
8672
+ import { join as join7 } from "node:path";
8672
8673
  var ZCODE_DISPOSE_GRACE_MS = 3e3;
8673
- function wellKnownZcode() {
8674
- if (process.platform !== "win32") return void 0;
8675
- const candidate = "D:ProgramsZCode\resourcesglmzcode.cjs";
8676
- return existsSync3(candidate) ? candidate : void 0;
8674
+ function zcodeInstallRoots(env = process.env) {
8675
+ const roots = [];
8676
+ if (env.ZCODE_HOME !== void 0 && env.ZCODE_HOME !== "") roots.push(env.ZCODE_HOME);
8677
+ if (env.LOCALAPPDATA !== void 0 && env.LOCALAPPDATA !== "") {
8678
+ roots.push(join7(env.LOCALAPPDATA, "Programs", "ZCode"));
8679
+ }
8680
+ if (process.platform === "win32" && env.ProgramFiles !== void 0 && env.ProgramFiles !== "") {
8681
+ roots.push(join7(env.ProgramFiles, "ZCode"));
8682
+ }
8683
+ return roots;
8684
+ }
8685
+ function zcodeCliCandidates(env = process.env) {
8686
+ return zcodeInstallRoots(env).map((root) => join7(root, "resources", "glm", "zcode.cjs"));
8687
+ }
8688
+ function wellKnownZcode(env = process.env) {
8689
+ for (const candidate of zcodeCliCandidates(env)) {
8690
+ if (existsSync3(candidate)) return candidate;
8691
+ }
8692
+ return void 0;
8677
8693
  }
8678
8694
  function zcodeArgvPrefix(configBin) {
8679
8695
  const pinned = configBin === void 0 || configBin === "" ? wellKnownZcode() : configBin;
@@ -8681,9 +8697,14 @@ function zcodeArgvPrefix(configBin) {
8681
8697
  return /\.(?:c|m)?js$/i.test(pinned) ? [process.execPath, pinned] : [pinned];
8682
8698
  }
8683
8699
  var ZCODE_PROVIDER_CONFIG_ENV = "ZCODE_BUILTIN_PROVIDER_CONFIG_FILE";
8684
- function zcodeBuiltinProviderConfig() {
8685
- const candidate = "D:ProgramsZCode\resourcesconfigproviderzcode-builtin.json";
8686
- return existsSync3(candidate) ? candidate : void 0;
8700
+ function zcodeProviderConfigCandidates(env = process.env) {
8701
+ return zcodeInstallRoots(env).map((root) => join7(root, "resources", "config", "provider", "zcode-builtin.json"));
8702
+ }
8703
+ function zcodeBuiltinProviderConfig(env = process.env) {
8704
+ for (const candidate of zcodeProviderConfigCandidates(env)) {
8705
+ if (existsSync3(candidate)) return candidate;
8706
+ }
8707
+ return void 0;
8687
8708
  }
8688
8709
  function zcodeMode(dangerFullAccess) {
8689
8710
  return dangerFullAccess ? "yolo" : "build";
@@ -8883,16 +8904,16 @@ function mapStreamJsonDocument(document, accept, run) {
8883
8904
  // src/engine-qoderclicn/process.ts
8884
8905
  import { existsSync as existsSync4 } from "node:fs";
8885
8906
  import { homedir as homedir2 } from "node:os";
8886
- import { join as join7 } from "node:path";
8907
+ import { join as join8 } from "node:path";
8887
8908
  var QODERCLICN_DISPOSE_GRACE_MS = 3e3;
8888
8909
  function qoderclicnHomeDir() {
8889
8910
  const envHome = process.env.QODER_HOME;
8890
- return envHome !== void 0 && envHome !== "" ? envHome : join7(homedir2(), ".qoder-cn");
8911
+ return envHome !== void 0 && envHome !== "" ? envHome : join8(homedir2(), ".qoder-cn");
8891
8912
  }
8892
8913
  function qoderclicnBinResolver(configBin) {
8893
8914
  if (configBin !== void 0 && configBin !== "") return configBin;
8894
8915
  const executable = process.platform === "win32" ? "qoderclicn.exe" : "qoderclicn";
8895
- const candidate = join7(qoderclicnHomeDir(), "bin", "qoderclicn", executable);
8916
+ const candidate = join8(qoderclicnHomeDir(), "bin", "qoderclicn", executable);
8896
8917
  return existsSync4(candidate) ? candidate : "qoderclicn";
8897
8918
  }
8898
8919
  function qoderclicnPermissionMode(sandbox, approval) {
@@ -9021,14 +9042,14 @@ import z8 from "@deepseek-ai/schemastery";
9021
9042
 
9022
9043
  // src/engine-hermes/process.ts
9023
9044
  import { existsSync as existsSync5 } from "node:fs";
9024
- import { delimiter, join as join8 } from "node:path";
9045
+ import { delimiter, join as join9 } from "node:path";
9025
9046
  var HERMES_DISPOSE_GRACE_MS = 3e3;
9026
9047
  var HERMES_PROMPT_FLAG = "-z";
9027
9048
  function wellKnownHermes() {
9028
9049
  if (process.platform !== "win32") return void 0;
9029
9050
  const local = process.env.LOCALAPPDATA;
9030
9051
  if (local === void 0 || local === "") return void 0;
9031
- const candidate = join8(local, "hermes", "hermes-agent", "venv", "Scripts", "hermes.exe");
9052
+ const candidate = join9(local, "hermes", "hermes-agent", "venv", "Scripts", "hermes.exe");
9032
9053
  return existsSync5(candidate) ? candidate : void 0;
9033
9054
  }
9034
9055
  function hermesBinResolver(configBin) {
@@ -9126,11 +9147,11 @@ import z9 from "@deepseek-ai/schemastery";
9126
9147
  // src/engine-grok/process.ts
9127
9148
  import { existsSync as existsSync7 } from "node:fs";
9128
9149
  import { homedir as homedir3 } from "node:os";
9129
- import { join as join10 } from "node:path";
9150
+ import { join as join11 } from "node:path";
9130
9151
 
9131
9152
  // src/driver-acp/executable.ts
9132
9153
  import { existsSync as existsSync6 } from "node:fs";
9133
- import { join as join9 } from "node:path";
9154
+ import { join as join10 } from "node:path";
9134
9155
  function execArgvPrefix(bin) {
9135
9156
  if (/\.(?:c|m)?js$/i.test(bin)) return [process.execPath, bin];
9136
9157
  if (/\.(?:cmd|bat)$/i.test(bin)) return [process.env.ComSpec ?? "cmd.exe", "/c", bin];
@@ -9144,7 +9165,7 @@ function resolveOnPath(name2, env = process.env) {
9144
9165
  for (const directory of path.split(separator)) {
9145
9166
  if (directory === "") continue;
9146
9167
  for (const extension of extensions) {
9147
- const candidate = join9(directory, `${name2}${extension}`);
9168
+ const candidate = join10(directory, `${name2}${extension}`);
9148
9169
  if (existsSync6(candidate)) return candidate;
9149
9170
  }
9150
9171
  }
@@ -9155,8 +9176,8 @@ function npmPackageEntry(prefix, pkg, entry) {
9155
9176
  const scope = scoped ? pkg.slice(0, pkg.indexOf("/")) : "";
9156
9177
  const name2 = scoped ? pkg.slice(pkg.indexOf("/") + 1) : pkg;
9157
9178
  if (name2 === "" || scoped && scope === "") return void 0;
9158
- const relative = scoped ? join9("node_modules", scope, name2, entry) : join9("node_modules", name2, entry);
9159
- for (const candidate of [join9(prefix, relative), join9(prefix, "lib", relative)]) {
9179
+ const relative = scoped ? join10("node_modules", scope, name2, entry) : join10("node_modules", name2, entry);
9180
+ for (const candidate of [join10(prefix, relative), join10(prefix, "lib", relative)]) {
9160
9181
  if (existsSync6(candidate)) return candidate;
9161
9182
  }
9162
9183
  return void 0;
@@ -9166,12 +9187,12 @@ function npmPackageEntry(prefix, pkg, entry) {
9166
9187
  var GROK_DISPOSE_GRACE_MS = 3e3;
9167
9188
  function grokHomeDir() {
9168
9189
  const envHome = process.env.GROK_HOME;
9169
- return envHome !== void 0 && envHome !== "" ? envHome : join10(homedir3(), ".grok");
9190
+ return envHome !== void 0 && envHome !== "" ? envHome : join11(homedir3(), ".grok");
9170
9191
  }
9171
9192
  function grokBinResolver(configBin) {
9172
9193
  if (configBin !== void 0 && configBin !== "") return configBin;
9173
9194
  const executable = process.platform === "win32" ? "grok.exe" : "grok";
9174
- const candidate = join10(grokHomeDir(), "bin", executable);
9195
+ const candidate = join11(grokHomeDir(), "bin", executable);
9175
9196
  if (existsSync7(candidate)) return candidate;
9176
9197
  return resolveOnPath("grok") ?? "grok";
9177
9198
  }
@@ -9276,7 +9297,7 @@ import z10 from "@deepseek-ai/schemastery";
9276
9297
 
9277
9298
  // src/engine-minimaxcode/process.ts
9278
9299
  import { homedir as homedir4 } from "node:os";
9279
- import { dirname as dirname3, join as join11 } from "node:path";
9300
+ import { dirname as dirname3, join as join12 } from "node:path";
9280
9301
  var MINIMAXCODE_DISPOSE_GRACE_MS = 3e3;
9281
9302
  var MINIMAXCODE_NPM_PACKAGE = "@minimax-ai/code";
9282
9303
  var MINIMAXCODE_ENTRYPOINT = "cli.js";
@@ -9284,7 +9305,7 @@ function mcodeBinResolver(configBin, env = process.env) {
9284
9305
  if (configBin !== void 0 && configBin !== "") return configBin;
9285
9306
  const prefixes = [
9286
9307
  env.MCODE_INSTALL_ROOT,
9287
- env.APPDATA === void 0 ? void 0 : join11(env.APPDATA, "npm"),
9308
+ env.APPDATA === void 0 ? void 0 : join12(env.APPDATA, "npm"),
9288
9309
  // A standard Windows node install puts the global prefix beside node.exe.
9289
9310
  dirname3(process.execPath),
9290
9311
  dirname3(dirname3(process.execPath)),
@@ -9293,7 +9314,7 @@ function mcodeBinResolver(configBin, env = process.env) {
9293
9314
  // `HOME`, and the whole point of this resolver is to find an install the
9294
9315
  // inherited environment may not describe.
9295
9316
  "/usr/local",
9296
- join11(homedir4(), ".npm-global")
9317
+ join12(homedir4(), ".npm-global")
9297
9318
  ];
9298
9319
  for (const prefix of prefixes) {
9299
9320
  if (prefix === void 0 || prefix === "") continue;
@@ -9593,7 +9614,7 @@ ${block}`);
9593
9614
  // src/preset.ts
9594
9615
  import { mkdir, readFile as readFile2, rename, writeFile } from "node:fs/promises";
9595
9616
  import { randomUUID } from "node:crypto";
9596
- import { dirname as dirname4, join as join12 } from "node:path";
9617
+ import { dirname as dirname4, join as join13 } from "node:path";
9597
9618
  var USER_PRESET_DIR = ".agent-presets";
9598
9619
  var COMPOSITION_FILE = "agent.cordis.yml";
9599
9620
  var METADATA_FILE = "preset.yml";
@@ -9793,9 +9814,9 @@ async function ensureEnginePresets(dshHome, source, target) {
9793
9814
  ${applySummarizerTarget(stripPresetRows(composition), target)}`;
9794
9815
  let changed = false;
9795
9816
  for (const engine of HOSTED_ENGINE_IDS) {
9796
- const dir = join12(dshHome, USER_PRESET_DIR, enginePresetId(engine));
9797
- const compositionChanged = await writeIfDifferent(join12(dir, COMPOSITION_FILE), stripped);
9798
- const metadataChanged = await writeIfDifferent(join12(dir, METADATA_FILE), managedMetadata(engine));
9817
+ const dir = join13(dshHome, USER_PRESET_DIR, enginePresetId(engine));
9818
+ const compositionChanged = await writeIfDifferent(join13(dir, COMPOSITION_FILE), stripped);
9819
+ const metadataChanged = await writeIfDifferent(join13(dir, METADATA_FILE), managedMetadata(engine));
9799
9820
  changed = changed || compositionChanged || metadataChanged;
9800
9821
  }
9801
9822
  return changed;
@@ -10051,7 +10072,7 @@ function usableSelection(answered) {
10051
10072
  // src/commands.ts
10052
10073
  import { readdirSync, readFileSync as readFileSync3 } from "node:fs";
10053
10074
  import { homedir as homedir5 } from "node:os";
10054
- import { join as join13 } from "node:path";
10075
+ import { join as join14 } from "node:path";
10055
10076
  import { createUserMessage as createUserMessage6 } from "@deepseek-ai/dsh-llm";
10056
10077
  var COMMAND_NAME = /^[a-z][a-z0-9_-]*$/;
10057
10078
  function forwardClaudeCodeCommand(name2) {
@@ -10085,7 +10106,7 @@ function discoverUserSlashCommands() {
10085
10106
  if (!entry.endsWith(".md")) continue;
10086
10107
  const name2 = entry.slice(0, -".md".length);
10087
10108
  if (!COMMAND_NAME.test(name2) || seen.has(name2)) continue;
10088
- const path = join13(userCommandsDir(), entry);
10109
+ const path = join14(userCommandsDir(), entry);
10089
10110
  let raw;
10090
10111
  try {
10091
10112
  raw = readFileSync3(path, "utf8");
@@ -10100,7 +10121,7 @@ function discoverUserSlashCommands() {
10100
10121
  return definitions;
10101
10122
  }
10102
10123
  function userCommandsDir() {
10103
- return join13(homedir5(), ".claude", "commands");
10124
+ return join14(homedir5(), ".claude", "commands");
10104
10125
  }
10105
10126
  function commandDescription(raw) {
10106
10127
  const trimmed = raw.trim();
@@ -10151,7 +10172,7 @@ var KIMI_COMMANDS = [
10151
10172
  // src/skills.ts
10152
10173
  import { readFile as readFile3, readdir, stat } from "node:fs/promises";
10153
10174
  import { homedir as homedir6 } from "node:os";
10154
- import { join as join14, resolve } from "node:path";
10175
+ import { join as join15, resolve } from "node:path";
10155
10176
  var SKILL_NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
10156
10177
  var PROVIDER_NAME = "claude-code";
10157
10178
  var CLAUDE_CODE_RANK = 150;
@@ -10261,10 +10282,10 @@ var ClaudeCodeSkillProvider = class {
10261
10282
  const cwd = options.cwd;
10262
10283
  if (cwd !== void 0) {
10263
10284
  const projectRoot = await findProjectRoot(resolve(cwd));
10264
- await collectSkillsDir(join14(projectRoot, ".claude", "skills"), CLAUDE_CODE_RANK, candidates);
10285
+ await collectSkillsDir(join15(projectRoot, ".claude", "skills"), CLAUDE_CODE_RANK, candidates);
10265
10286
  await collectClaudeMd(projectRoot, candidates);
10266
10287
  }
10267
- await collectSkillsDir(join14(homedir6(), ".claude", "skills"), CLAUDE_CODE_USER_RANK, candidates);
10288
+ await collectSkillsDir(join15(homedir6(), ".claude", "skills"), CLAUDE_CODE_USER_RANK, candidates);
10268
10289
  if (this.control.signal.aborted) return [];
10269
10290
  return candidates;
10270
10291
  }
@@ -10298,11 +10319,11 @@ async function collectSkillsDir(skillsDir, rank, candidates) {
10298
10319
  return;
10299
10320
  }
10300
10321
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
10301
- const entryPath = join14(skillsDir, entry.name);
10322
+ const entryPath = join15(skillsDir, entry.name);
10302
10323
  const info = await stat(entryPath).catch(() => void 0);
10303
10324
  if (info === void 0) continue;
10304
10325
  if (info.isDirectory()) {
10305
- const path = join14(entryPath, "SKILL.md");
10326
+ const path = join15(entryPath, "SKILL.md");
10306
10327
  const skill2 = await tryParseSkill(path);
10307
10328
  if (skill2 === void 0) continue;
10308
10329
  candidates.push(toCandidate(skill2, path, rank, entryPath));
@@ -10315,7 +10336,7 @@ async function collectSkillsDir(skillsDir, rank, candidates) {
10315
10336
  }
10316
10337
  }
10317
10338
  async function collectClaudeMd(projectRoot, candidates) {
10318
- const claudeMd = join14(projectRoot, "CLAUDE.md");
10339
+ const claudeMd = join15(projectRoot, "CLAUDE.md");
10319
10340
  try {
10320
10341
  const info = await stat(claudeMd);
10321
10342
  if (!info.isFile()) return;
@@ -10352,7 +10373,7 @@ async function findProjectRoot(cwd) {
10352
10373
  let current = cwd;
10353
10374
  while (true) {
10354
10375
  try {
10355
- await stat(join14(current, ".git"));
10376
+ await stat(join15(current, ".git"));
10356
10377
  return current;
10357
10378
  } catch {
10358
10379
  }
@@ -10364,15 +10385,15 @@ async function findProjectRoot(cwd) {
10364
10385
 
10365
10386
  // src/engine-codex/skills.ts
10366
10387
  import { homedir as homedir7 } from "node:os";
10367
- import { join as join17 } from "node:path";
10388
+ import { join as join18 } from "node:path";
10368
10389
 
10369
10390
  // src/driver-core/agents-md-skill-provider.ts
10370
10391
  import { readdir as readdir2, readFile as readFile5, stat as stat3 } from "node:fs/promises";
10371
- import { dirname as dirname5, join as join16 } from "node:path";
10392
+ import { dirname as dirname5, join as join17 } from "node:path";
10372
10393
 
10373
10394
  // src/driver-core/context-files.ts
10374
10395
  import { readFile as readFile4, stat as stat2 } from "node:fs/promises";
10375
- import { join as join15, resolve as resolve2 } from "node:path";
10396
+ import { join as join16, resolve as resolve2 } from "node:path";
10376
10397
  async function projectAncestors(cwd) {
10377
10398
  const root = await findProjectRoot(resolve2(cwd));
10378
10399
  const dirs = [];
@@ -10393,11 +10414,11 @@ async function collectProjectContextFiles(cwd, policy) {
10393
10414
  }
10394
10415
  async function dirContextFile(dir, policy) {
10395
10416
  if (policy.override !== void 0) {
10396
- const override = join15(dir, policy.override);
10417
+ const override = join16(dir, policy.override);
10397
10418
  if (await pathExists(override)) return override;
10398
10419
  }
10399
10420
  for (const name2 of policy.primary) {
10400
- const candidate = join15(dir, name2);
10421
+ const candidate = join16(dir, name2);
10401
10422
  if (await pathExists(candidate)) return candidate;
10402
10423
  }
10403
10424
  return void 0;
@@ -10457,18 +10478,18 @@ var AgentsMdSkillProvider = class {
10457
10478
  if (this.spec.skills !== void 0) {
10458
10479
  const catalog = this.spec.skills;
10459
10480
  for (const dir of await projectAncestors(cwd)) {
10460
- await this.collectSkillsDir(join16(dir, ...catalog.project), catalog.projectRank, candidates);
10481
+ await this.collectSkillsDir(join17(dir, ...catalog.project), catalog.projectRank, candidates);
10461
10482
  }
10462
10483
  }
10463
10484
  }
10464
10485
  const userDir = this.spec.userDir();
10465
10486
  const userContext = this.spec.userContext;
10466
10487
  if (userContext !== void 0) {
10467
- const userFile = join16(userDir, userContext.file);
10488
+ const userFile = join17(userDir, userContext.file);
10468
10489
  if (await fileNonEmpty(userFile)) candidates.push(this.agentsCandidate([userFile], userContext.rank));
10469
10490
  }
10470
10491
  if (this.spec.skills !== void 0) {
10471
- await this.collectSkillsDir(join16(userDir, this.spec.skills.userDir), this.spec.skills.userRank, candidates);
10492
+ await this.collectSkillsDir(join17(userDir, this.spec.skills.userDir), this.spec.skills.userRank, candidates);
10472
10493
  }
10473
10494
  if (this.control.signal.aborted) return [];
10474
10495
  return candidates;
@@ -10528,11 +10549,11 @@ var AgentsMdSkillProvider = class {
10528
10549
  return;
10529
10550
  }
10530
10551
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
10531
- const entryPath = join16(skillsDir, entry.name);
10552
+ const entryPath = join17(skillsDir, entry.name);
10532
10553
  const info = await stat3(entryPath).catch(() => void 0);
10533
10554
  if (info === void 0) continue;
10534
10555
  if (info.isDirectory()) {
10535
- const path = join16(entryPath, "SKILL.md");
10556
+ const path = join17(entryPath, "SKILL.md");
10536
10557
  const parsed2 = await this.tryParse(path);
10537
10558
  if (parsed2 === void 0) continue;
10538
10559
  candidates.push(this.skillCandidate(parsed2, path, rank, entryPath));
@@ -10578,7 +10599,7 @@ var CODEX_SPEC = {
10578
10599
  name: "codex",
10579
10600
  agentsMdDescription: "Codex project/user instructions (AGENTS.md)",
10580
10601
  contextPolicy: CODEX_CONTEXT_POLICY,
10581
- userDir: () => join17(homedir7(), ".codex"),
10602
+ userDir: () => join18(homedir7(), ".codex"),
10582
10603
  projectRank: CODEX_PROJECT_RANK,
10583
10604
  userContext: { file: "AGENTS.md", rank: CODEX_USER_RANK }
10584
10605
  };
@@ -10590,7 +10611,7 @@ var CodexSkillProvider = class extends AgentsMdSkillProvider {
10590
10611
 
10591
10612
  // src/engine-pi/skills.ts
10592
10613
  import { homedir as homedir8 } from "node:os";
10593
- import { join as join18, resolve as resolve3 } from "node:path";
10614
+ import { join as join19, resolve as resolve3 } from "node:path";
10594
10615
  var PI_AGENTS_PROJECT_RANK = 140;
10595
10616
  var PI_SKILL_PROJECT_RANK = 150;
10596
10617
  var PI_AGENTS_USER_RANK = 160;
@@ -10602,7 +10623,7 @@ var PI_CONTEXT_POLICY = {
10602
10623
  function piAgentDir2() {
10603
10624
  const override = process.env.PI_CODING_AGENT_DIR;
10604
10625
  if (override !== void 0 && override.length > 0) return resolve3(override);
10605
- return join18(homedir8(), ".pi", "agent");
10626
+ return join19(homedir8(), ".pi", "agent");
10606
10627
  }
10607
10628
  var PI_SPEC = {
10608
10629
  name: "pi",
@@ -10626,7 +10647,7 @@ var PiSkillProvider = class extends AgentsMdSkillProvider {
10626
10647
 
10627
10648
  // src/engine-kimi/skills.ts
10628
10649
  import { homedir as homedir9 } from "node:os";
10629
- import { join as join19, resolve as resolve4 } from "node:path";
10650
+ import { join as join20, resolve as resolve4 } from "node:path";
10630
10651
  var KIMI_AGENTS_PROJECT_RANK = 140;
10631
10652
  var KIMI_SKILL_PROJECT_RANK = 150;
10632
10653
  var KIMI_SKILL_USER_RANK = 160;
@@ -10636,7 +10657,7 @@ var KIMI_CONTEXT_POLICY = {
10636
10657
  function kimiAgentDir() {
10637
10658
  const override = process.env.KIMI_CODE_HOME;
10638
10659
  if (override !== void 0 && override.length > 0) return resolve4(override);
10639
- return join19(homedir9(), ".kimi-code");
10660
+ return join20(homedir9(), ".kimi-code");
10640
10661
  }
10641
10662
  var KIMI_SPEC = {
10642
10663
  name: "kimi",
@@ -11257,13 +11278,13 @@ function handoverOf(handle) {
11257
11278
  // src/session-engine-store.ts
11258
11279
  import { mkdirSync as mkdirSync2, readFileSync as readFileSync4, renameSync, writeFileSync as writeFileSync2 } from "node:fs";
11259
11280
  import { randomUUID as randomUUID2 } from "node:crypto";
11260
- import { dirname as dirname6, join as join20 } from "node:path";
11281
+ import { dirname as dirname6, join as join21 } from "node:path";
11261
11282
  import { resolveDshHome } from "@deepseek-ai/dsh-home-paths";
11262
11283
  var ENGINE_RECORD_DIR = ".loop-engine";
11263
11284
  var ENGINE_RECORD_FILE = "engines.json";
11264
11285
  var ENGINE_RECORD_VERSION = 1;
11265
11286
  function resolveEngineRecordPath() {
11266
- return join20(resolveDshHome(), ENGINE_RECORD_DIR, ENGINE_RECORD_FILE);
11287
+ return join21(resolveDshHome(), ENGINE_RECORD_DIR, ENGINE_RECORD_FILE);
11267
11288
  }
11268
11289
  function isMissing(error) {
11269
11290
  return error?.code === "ENOENT";
@@ -11418,7 +11439,7 @@ var Config11 = z12.object({
11418
11439
  });
11419
11440
  function resolvePatchPath(config) {
11420
11441
  if (config.patchPath !== void 0 && config.patchPath !== "") return config.patchPath;
11421
- return join21(
11442
+ return join22(
11422
11443
  resolveDshHome2(),
11423
11444
  "profiles",
11424
11445
  config.profile ?? "web",
@@ -11478,7 +11499,7 @@ function readPatchFileSync(path) {
11478
11499
  }
11479
11500
  function warnIfProfileLooksWrong(ctx, config, patchPath) {
11480
11501
  const profileDir = dirname7(patchPath);
11481
- if (existsSync8(join21(profileDir, "package.json"))) return;
11502
+ if (existsSync8(join22(profileDir, "package.json"))) return;
11482
11503
  const named = config.profile ?? "web";
11483
11504
  ctx.logger.warn(
11484
11505
  `loop-engine: profile "${named}" has no package.json beside "${patchPath}". If you boot a different profile, set \`profile: <that-name>\` in this plugin's composition entry - otherwise its managed block is written here, the profile you actually boot never reads it, and no hosted engine will be reachable.`
@@ -42,6 +42,29 @@ export declare const ZCODE_DISPOSE_GRACE_MS = 3000;
42
42
  export declare const ZCODE_MODES: readonly ["build", "edit", "plan", "yolo"];
43
43
  /** One ZCode permission mode. */
44
44
  export type ZcodeMode = (typeof ZCODE_MODES)[number];
45
+ /**
46
+ * The install roots a ZCode desktop build may sit under, most specific first.
47
+ *
48
+ * One list, used by both the CLI lookup and the provider-catalog lookup, so the two
49
+ * can never disagree about where an install is. No drive letter is assumed: the fork
50
+ * was written against one machine's `D:\Programs\ZCode`, and `%ZCODE_HOME%` is how an
51
+ * operator names a manual install like that one.
52
+ * @param env - the environment to read the roots from.
53
+ * @returns candidate roots.
54
+ */
55
+ export declare function zcodeInstallRoots(env?: NodeJS.ProcessEnv): readonly string[];
56
+ /**
57
+ * Every place a ZCode desktop install may keep its bundled CLI, in probe order.
58
+ *
59
+ * Derived from the environment rather than hardcoded: the fork was written against
60
+ * one machine's `D:\Programs\ZCode`, and shipping that literal meant the probe
61
+ * never matched anywhere else. `%LOCALAPPDATA%\Programs` is where the installer puts
62
+ * a per-user app, `%ProgramFiles%` where an all-users install goes, and
63
+ * `%ZCODE_HOME%` is the app's own override.
64
+ * @param env - the environment to read install roots from.
65
+ * @returns candidate paths for the bundled CLI, most specific first.
66
+ */
67
+ export declare function zcodeCliCandidates(env?: NodeJS.ProcessEnv): readonly string[];
45
68
  /**
46
69
  * Resolve the argv prefix that launches ZCode.
47
70
  *
@@ -63,8 +86,18 @@ export declare function zcodeArgvPrefix(configBin?: string): string[];
63
86
  * only when the deployment has not — an explicit deployment value always wins.
64
87
  */
65
88
  export declare const ZCODE_PROVIDER_CONFIG_ENV = "ZCODE_BUILTIN_PROVIDER_CONFIG_FILE";
66
- /** The bundled provider catalog inside the desktop app, when it exists. */
67
- export declare function zcodeBuiltinProviderConfig(): string | undefined;
89
+ /**
90
+ * Every place a ZCode install may keep the provider catalog its bundle needs.
91
+ * @param env - the environment to read install roots from.
92
+ * @returns candidate paths, most specific first.
93
+ */
94
+ export declare function zcodeProviderConfigCandidates(env?: NodeJS.ProcessEnv): readonly string[];
95
+ /**
96
+ * The bundled provider catalog inside the desktop app, when it exists.
97
+ * @param env - the environment to probe.
98
+ * @returns the catalog path, or undefined when no install was found.
99
+ */
100
+ export declare function zcodeBuiltinProviderConfig(env?: NodeJS.ProcessEnv): string | undefined;
68
101
  /**
69
102
  * Map the session's dsh knobs onto ZCode's `--mode`.
70
103
  *
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-loop-engine-allinone",
3
3
  "description": "Web-switchable agent loop engine selection for the DeepSeek Harness - out-of-tree plugin with a data-driven engine registry and a pluggable driver layer. Ten engines: Claude Code / Codex / Pi / Kimi Code / Antigravity / ZCode / Qoder CN / Hermes / Grok Build / MiniMax Code. All-in-one fork of kuun993/dsh-loop-engine.",
4
- "version": "0.7.2",
4
+ "version": "0.7.3",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
7
7
  },