dsh-loop-engine-allinone 0.7.0 → 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 +62 -0
- package/README.md +57 -26
- package/README.zh.md +43 -23
- package/lib/index.js +86 -56
- package/lib/types/engine-zcode/process.d.ts +35 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,68 @@ 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
|
+
|
|
34
|
+
## [0.7.2]
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- **Installation leads with `--profile web` again.** 0.7.1 made `<your-profile>` the
|
|
39
|
+
primary spelling, on the reasoning that `web` is one of several shipped templates.
|
|
40
|
+
That is true but the wrong shape for an install section: `dsh web` is the harness
|
|
41
|
+
CLI's own documented example (`dsh web` = `dsh --profile web`), and every published
|
|
42
|
+
plugin says `dsh plugin --profile web add ...` — dsh-market included. Forcing a
|
|
43
|
+
placeholder substitution before the first command is friction with no payoff for the
|
|
44
|
+
majority.
|
|
45
|
+
|
|
46
|
+
The non-`web` case is now a caveat section instead: `desktop`, `headless`, and
|
|
47
|
+
self-named profiles get both steps, plus the silent failure that follows from doing
|
|
48
|
+
only the first one. npm / GitHub / local-clone remain the three sources.
|
|
49
|
+
|
|
50
|
+
## [0.7.1]
|
|
51
|
+
|
|
52
|
+
### Fixed
|
|
53
|
+
|
|
54
|
+
- **Installation no longer assumes a `web` profile.** `web` is one of several shipped
|
|
55
|
+
templates; the Desktop app boots `desktop`, a CI deployment boots `headless`, and
|
|
56
|
+
many people run a profile they named themselves. The instructions now say
|
|
57
|
+
`<your-profile>` and give the three real sources: npm, GitHub, and a local clone for
|
|
58
|
+
plugin development.
|
|
59
|
+
- **A wrong `profile:` is now diagnosable.** The field defaults to `web`, so forgetting
|
|
60
|
+
it writes the managed block into another profile's patch file while the profile that
|
|
61
|
+
actually boots never reads it — the plugin mounts, the base `agent-loop` row is never
|
|
62
|
+
disabled, and no hosted engine is reachable, with **nothing logged**. The harness
|
|
63
|
+
gives a plugin no way to ask which profile is running, so `apply` now checks whether
|
|
64
|
+
the target directory holds a profile's `package.json` and warns with the field to set.
|
|
65
|
+
It is a warning, not a failure: a first boot may legitimately precede the profile's
|
|
66
|
+
own files.
|
|
67
|
+
|
|
68
|
+
### Documented
|
|
69
|
+
|
|
70
|
+
- The engine picker appears in whichever profile renders a web UI, not specifically in
|
|
71
|
+
`web`.
|
|
72
|
+
|
|
11
73
|
## [0.7.0]
|
|
12
74
|
|
|
13
75
|
### Added
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
**dsh-loop-engine-allinone** is an all-in-one agent loop engine switcher for **[DeepSeek Harness](https://github.com/deepseek-ai)** (`dsh`). It enables per-session engine switching across **10 hosted engines** (Claude Code, Codex, Pi, Kimi Code, Antigravity, ZCode, Qoder CN, Hermes Agent, Grok Build, MiniMax Code) alongside the built-in `in-process` loop.
|
|
9
9
|
|
|
10
|
-
> `dsh` is the harness CLI. `dsh
|
|
10
|
+
> `dsh` is the harness CLI. `dsh --profile <name>` boots one of its **profiles**, and the engine picker plus this plugin's settings page appear in whichever profile renders a web UI (the shipped `web` template is one; the Desktop app uses `desktop`).
|
|
11
11
|
|
|
12
12
|
Sessions are fully independent: run Codex in one chat while another runs Kimi Code or Antigravity simultaneously. Handover between two hosted engines happens seamlessly in place; switching to or from the native `in-process` engine performs an in-browser reload without restarting the backend process. All without modifying the DeepSeek Harness core codebase.
|
|
13
13
|
|
|
@@ -33,40 +33,64 @@ Sessions are fully independent: run Codex in one chat while another runs Kimi Co
|
|
|
33
33
|
## Installation
|
|
34
34
|
|
|
35
35
|
```sh
|
|
36
|
-
# From npm (recommended)
|
|
37
36
|
dsh plugin --profile web add dsh-loop-engine-allinone
|
|
38
37
|
```
|
|
39
38
|
|
|
40
|
-
|
|
39
|
+
Restart `dsh web`, then open **Settings → Loop engine**.
|
|
40
|
+
|
|
41
|
+
### From GitHub instead of npm
|
|
41
42
|
|
|
42
43
|
```sh
|
|
43
|
-
dsh web
|
|
44
|
+
dsh plugin --profile web add yaliklinty/dsh-loop-engine-allinone
|
|
44
45
|
```
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
`headless` deployment, a renamed profile) means naming that profile instead:
|
|
48
|
-
`dsh plugin --profile desktop add dsh-loop-engine-allinone`, **and** setting
|
|
49
|
-
`profile: desktop` in the composition entry — see the notes below, because
|
|
50
|
-
forgetting the second half is the one mistake that leaves the plugin mounted but
|
|
51
|
-
unable to run any engine.
|
|
52
|
-
|
|
53
|
-
### Installation Notes
|
|
54
|
-
|
|
55
|
-
- **Profile Configuration**: The installer automatically injects a managed configuration block into your profile's `cordis.patch.yml`. All other custom configuration in that file is preserved.
|
|
56
|
-
- **Non-web Profiles**: When installing into non-web profiles (such as `desktop` or headless), explicitly specify `profile: <name>` in the composition entry:
|
|
57
|
-
```yaml
|
|
58
|
-
- id: loop-engine
|
|
59
|
-
config:
|
|
60
|
-
profile: desktop
|
|
61
|
-
```
|
|
62
|
-
*(Without this, configuration defaults to `web` and the plugin will not attach to custom profiles.)*
|
|
63
|
-
- **Uninstallation**: Run `dsh plugin --profile web remove dsh-loop-engine-allinone`, then remove the managed `loop-engine` block from `cordis.patch.yml`.
|
|
64
|
-
- **pnpm 10+**: If dependency build scripts are blocked (`ERR_PNPM_IGNORED_BUILDS` mentioning `esbuild`, `@google/genai`, etc.), run `pnpm approve-builds`.
|
|
65
|
-
- **Harness from Source**: If launching the harness directly from a source checkout, bridge peer dependencies using `file:` shims as described in [docs/source-checkout.md](docs/source-checkout.md).
|
|
47
|
+
### From a local clone
|
|
66
48
|
|
|
67
|
-
|
|
49
|
+
Only when you are working on the plugin itself:
|
|
68
50
|
|
|
69
|
-
|
|
51
|
+
```sh
|
|
52
|
+
git clone https://github.com/yaliklinty/dsh-loop-engine-allinone.git
|
|
53
|
+
dsh plugin --profile web add ./dsh-loop-engine-allinone
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Not on the `web` profile?
|
|
57
|
+
|
|
58
|
+
`web` is the profile the harness's own CLI documents (`dsh web` is short for
|
|
59
|
+
`dsh --profile web`), so it is the right default. But the Desktop app boots
|
|
60
|
+
`desktop`, a CI deployment may boot `headless`, and you may have made your own. In
|
|
61
|
+
that case:
|
|
62
|
+
|
|
63
|
+
1. install with that profile's name — `dsh plugin --profile desktop add
|
|
64
|
+
dsh-loop-engine-allinone`;
|
|
65
|
+
2. **and** set the same name in the composition entry:
|
|
66
|
+
|
|
67
|
+
```yaml
|
|
68
|
+
- id: loop-engine
|
|
69
|
+
config:
|
|
70
|
+
profile: desktop
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Step 2 is the one that bites. The field defaults to `web`, so omitting it makes the
|
|
74
|
+
plugin write its managed block into `profiles/web/cordis.patch.yml` while the profile
|
|
75
|
+
you actually boot never reads it: the plugin mounts, but the base `agent-loop` row is
|
|
76
|
+
never disabled, the router cannot take the agent-factory slot, and **no hosted engine
|
|
77
|
+
is reachable** — with nothing logged. This release also warns when it detects that
|
|
78
|
+
shape, naming the field to set.
|
|
79
|
+
|
|
80
|
+
### Installation notes
|
|
81
|
+
|
|
82
|
+
- The installer rewrites one managed block in the profile's `cordis.patch.yml`; every
|
|
83
|
+
other byte you wrote there is preserved, so upgrading needs no hand edit.
|
|
84
|
+
- **Uninstall**: `dsh plugin --profile web remove dsh-loop-engine-allinone`, **then
|
|
85
|
+
delete the managed `loop-engine` block** from that profile's `cordis.patch.yml`. The
|
|
86
|
+
block outlives the plugin, and while it is present the profile has no agent factory,
|
|
87
|
+
so no session can be created.
|
|
88
|
+
- **pnpm 10+** may block dependency build scripts (`ERR_PNPM_IGNORED_BUILDS` naming
|
|
89
|
+
`esbuild`, `@google/genai`, `protobufjs`). Run `pnpm approve-builds`, or add an
|
|
90
|
+
`allowBuilds` entry, and retry — only the installing project can grant this.
|
|
91
|
+
- **Harness from source**: bridge the profile's harness peers with `file:` shims, or
|
|
92
|
+
session resume fails with `agent-presets: refusing to compose an unscoped context`.
|
|
93
|
+
Steps in [docs/source-checkout.md](docs/source-checkout.md).
|
|
70
94
|
|
|
71
95
|
## Supported Engines
|
|
72
96
|
|
|
@@ -106,6 +130,7 @@ Custom settings can be configured under your profile's composition entry:
|
|
|
106
130
|
qoderclicnBin: 'D:/tools/qoderclicn.exe'
|
|
107
131
|
grokBin: 'C:/Users/user/.grok/bin/grok.exe'
|
|
108
132
|
minimaxcodeBin: 'D:/npm-global/node_modules/@minimax-ai/code/cli.js'
|
|
133
|
+
zcodeBin: 'D:/Programs/ZCode/resources/glm/zcode.cjs'
|
|
109
134
|
|
|
110
135
|
# 2. Region override (optional - MiniMax Code supports 'cn' or 'en')
|
|
111
136
|
regions:
|
|
@@ -125,6 +150,12 @@ Custom settings can be configured under your profile's composition entry:
|
|
|
125
150
|
summarizerModel: 'deepseek-flash'
|
|
126
151
|
```
|
|
127
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
|
+
|
|
128
159
|
---
|
|
129
160
|
|
|
130
161
|
## Usage Guide
|
package/README.zh.md
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
**dsh-loop-engine-allinone** 是专为 [DeepSeek Harness](https://github.com/deepseek-ai)(`dsh`)打造的 Agent 循环引擎全功能切换插件。支持**按会话独立切换** 10 家主流外部引擎与 Harness 原生 `in-process` 循环。
|
|
9
9
|
|
|
10
|
+
> `dsh` 是 harness 的命令行程序;`dsh --profile <名字>` 启动它的某个 **profile**。引擎选择器与本插件的设置页出现在**任何渲染 web UI 的 profile** 里(随附的 `web` 模板是其中之一,桌面版用的是 `desktop`)。
|
|
11
|
+
|
|
10
12
|
各会话完全隔离互不干扰:一个窗口运行 Codex,另一个窗口可同时运行 Kimi Code 或 Antigravity。托管引擎之间支持**无缝原地热换**;切换至原生 `in-process` 时会自动刷新页面重新挂载(无需重启 `dsh web` 后端进程)。**全程无需修改 DeepSeek Harness 主仓库源码**。
|
|
11
13
|
|
|
12
14
|
> **Fork 说明**:本项目基于 [`kuun993/dsh-loop-engine`](https://github.com/kuun993/dsh-loop-engine) 进行深度重构与扩展。
|
|
@@ -30,42 +32,59 @@
|
|
|
30
32
|
|
|
31
33
|
## 安装说明
|
|
32
34
|
|
|
33
|
-
通过 `dsh plugin` 命令行直接安装:
|
|
34
|
-
|
|
35
35
|
```sh
|
|
36
|
-
# 从 npm 安装(推荐)
|
|
37
36
|
dsh plugin --profile web add dsh-loop-engine-allinone
|
|
38
37
|
```
|
|
39
38
|
|
|
40
|
-
|
|
39
|
+
重启 `dsh web`,打开 **Settings → Loop engine**。
|
|
40
|
+
|
|
41
|
+
### 想从 GitHub 装而不是 npm
|
|
41
42
|
|
|
42
43
|
```sh
|
|
43
|
-
dsh web
|
|
44
|
+
dsh plugin --profile web add yaliklinty/dsh-loop-engine-allinone
|
|
44
45
|
```
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
### 从本地克隆安装
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
要把 `--profile web` 换成对应名字,**并且**在组合条目里写 `profile: <名字>`。
|
|
50
|
-
只做前一半是本插件最容易犯的错:插件挂上了,却一个引擎都跑不起来。详见下方安装须知。
|
|
49
|
+
只在开发插件本身时才需要:
|
|
51
50
|
|
|
52
|
-
|
|
51
|
+
```sh
|
|
52
|
+
git clone https://github.com/yaliklinty/dsh-loop-engine-allinone.git
|
|
53
|
+
dsh plugin --profile web add ./dsh-loop-engine-allinone
|
|
54
|
+
```
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
- **非 Web Profile 部署**:若安装至桌面版 `desktop` 或 headless 等自定义 profile,需在配置中显式指定 `profile: <name>`:
|
|
56
|
-
```yaml
|
|
57
|
-
- id: loop-engine
|
|
58
|
-
config:
|
|
59
|
-
profile: desktop
|
|
60
|
-
```
|
|
61
|
-
*(若未指定,插件默认挂载到 `web` profile,导致自定义 profile 无法生效。)*
|
|
62
|
-
- **卸载插件**:执行 `dsh plugin --profile web remove dsh-loop-engine-allinone`,并手动清理 `cordis.patch.yml` 中残留的 `loop-engine` 受管块。
|
|
63
|
-
- **pnpm 10+ 构建拦截**:若遇到 `ERR_PNPM_IGNORED_BUILDS`(提示 `esbuild`、`@google/genai` 等构建被忽略),执行 `pnpm approve-builds` 允许即可。
|
|
64
|
-
- **源码模式运行 Harness**:若通过源码启动 Harness,需按照 [docs/source-checkout.md](docs/source-checkout.md) 说明配置 `file:` shim 桥接依赖包。
|
|
56
|
+
### 不是 `web` profile?
|
|
65
57
|
|
|
66
|
-
|
|
58
|
+
`web` 是 harness 自己的 CLI 文档里用的那个 profile(`dsh web` 就是 `dsh --profile web`
|
|
59
|
+
的简写),所以它是正确的默认值。但桌面版启动的是 `desktop`,CI 部署可能用 `headless`,
|
|
60
|
+
你也可能自己建过一个。这种情况下:
|
|
67
61
|
|
|
68
|
-
|
|
62
|
+
1. 用那个 profile 的名字安装 —— `dsh plugin --profile desktop add dsh-loop-engine-allinone`;
|
|
63
|
+
2. **并且**在组合条目里写上同一个名字:
|
|
64
|
+
|
|
65
|
+
```yaml
|
|
66
|
+
- id: loop-engine
|
|
67
|
+
config:
|
|
68
|
+
profile: desktop
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**第 2 步才是会咬人的地方。** 该字段默认是 `web`,漏写会让插件把受管块写进
|
|
72
|
+
`profiles/web/cordis.patch.yml`,而你实际启动的 profile 永远读不到它:插件挂上了,
|
|
73
|
+
但基础 `agent-loop` 行没被禁,路由器拿不到 agent factory 槽位,**任何托管引擎都不可达**
|
|
74
|
+
——而且不报错。本版本会在检测到这种情形时告警,并指出该设哪个字段。
|
|
75
|
+
|
|
76
|
+
### 安装注意事项
|
|
77
|
+
|
|
78
|
+
- 安装会重写该 profile `cordis.patch.yml` 里的一段受管块;你写的其它内容逐字节保留,升级不需要手工改。
|
|
79
|
+
- **卸载**:`dsh plugin --profile web remove dsh-loop-engine-allinone`,**然后手动删掉**
|
|
80
|
+
该 profile `cordis.patch.yml` 里的 `loop-engine` 受管块。块会比插件活得久,而它还在时
|
|
81
|
+
profile 里没有任何 agent factory,会话一条也建不出来。
|
|
82
|
+
- **pnpm 10+** 可能拦下依赖的 build script(`ERR_PNPM_IGNORED_BUILDS`,列出 `esbuild`、
|
|
83
|
+
`@google/genai`、`protobufjs`)。执行 `pnpm approve-builds`,或加一条 `allowBuilds`,然后重试
|
|
84
|
+
——只有安装方能授予这个权限。
|
|
85
|
+
- **用源码启动 harness** 时,要用 `file:` shim 把 profile 的 harness peer 包桥接到 checkout 源码,
|
|
86
|
+
否则恢复会话会报 `agent-presets: refusing to compose an unscoped context`。
|
|
87
|
+
步骤见 [docs/source-checkout.md](docs/source-checkout.md)。
|
|
69
88
|
|
|
70
89
|
## 支持引擎一览
|
|
71
90
|
|
|
@@ -105,6 +124,7 @@ dsh web
|
|
|
105
124
|
qoderclicnBin: 'D:/tools/qoderclicn.exe'
|
|
106
125
|
grokBin: 'C:/Users/username/.grok/bin/grok.exe'
|
|
107
126
|
minimaxcodeBin: 'D:/npm-global/node_modules/@minimax-ai/code/cli.js'
|
|
127
|
+
zcodeBin: 'D:/Programs/ZCode/resources/glm/zcode.cjs'
|
|
108
128
|
|
|
109
129
|
# 2. 账号区域设置(可选,MiniMax Code 支持 'cn' 或 'en')
|
|
110
130
|
regions:
|
package/lib/index.js
CHANGED
|
@@ -89,10 +89,10 @@ var __callDispose = (stack, error, hasError) => {
|
|
|
89
89
|
};
|
|
90
90
|
|
|
91
91
|
// src/index.ts
|
|
92
|
-
import { readFileSync as readFileSync5 } from "node:fs";
|
|
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
|
|
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
|
|
8674
|
-
|
|
8675
|
-
|
|
8676
|
-
|
|
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
|
|
8685
|
-
|
|
8686
|
-
|
|
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
|
|
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 :
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
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 ?
|
|
9159
|
-
for (const candidate of [
|
|
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 :
|
|
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 =
|
|
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
|
|
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 :
|
|
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
|
-
|
|
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
|
|
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 =
|
|
9797
|
-
const compositionChanged = await writeIfDifferent(
|
|
9798
|
-
const metadataChanged = await writeIfDifferent(
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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(
|
|
10285
|
+
await collectSkillsDir(join15(projectRoot, ".claude", "skills"), CLAUDE_CODE_RANK, candidates);
|
|
10265
10286
|
await collectClaudeMd(projectRoot, candidates);
|
|
10266
10287
|
}
|
|
10267
|
-
await collectSkillsDir(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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(
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 =
|
|
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: () =>
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
11442
|
+
return join22(
|
|
11422
11443
|
resolveDshHome2(),
|
|
11423
11444
|
"profiles",
|
|
11424
11445
|
config.profile ?? "web",
|
|
@@ -11476,9 +11497,18 @@ function readPatchFileSync(path) {
|
|
|
11476
11497
|
throw error;
|
|
11477
11498
|
}
|
|
11478
11499
|
}
|
|
11500
|
+
function warnIfProfileLooksWrong(ctx, config, patchPath) {
|
|
11501
|
+
const profileDir = dirname7(patchPath);
|
|
11502
|
+
if (existsSync8(join22(profileDir, "package.json"))) return;
|
|
11503
|
+
const named = config.profile ?? "web";
|
|
11504
|
+
ctx.logger.warn(
|
|
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.`
|
|
11506
|
+
);
|
|
11507
|
+
}
|
|
11479
11508
|
function apply(ctx, config) {
|
|
11480
11509
|
const summarizer = resolveSummarizerTarget(config);
|
|
11481
11510
|
const patchPath = resolvePatchPath(config);
|
|
11511
|
+
warnIfProfileLooksWrong(ctx, config, patchPath);
|
|
11482
11512
|
const patchText = readPatchFileSync(patchPath);
|
|
11483
11513
|
const legacyEngine = legacyBlockEngineOf(patchText);
|
|
11484
11514
|
const needsWrite = hasLegacyManagedBlock(patchText) || !hasManagedBlock(patchText);
|
|
@@ -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
|
-
/**
|
|
67
|
-
|
|
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.
|
|
4
|
+
"version": "0.7.3",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
7
7
|
},
|