@ran-sh/dsh-crew 0.5.3 → 0.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -93
- package/README.zh.md +73 -93
- package/docs/installation.md +63 -63
- package/package.json +1 -1
- package/src/extension-contract.mjs +7 -5
- package/src/install/install.mjs +18 -6
- package/src/install/windows-startup.mjs +148 -115
- package/src/install/zcode.mjs +366 -316
- package/src/runtime-identity.mjs +1 -1
- package/src/server.mjs +39 -39
- package/src/workflow-runtime.mjs +71 -53
- package/src/workspace-isolation.mjs +43 -7
package/README.md
CHANGED
|
@@ -1,93 +1,76 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
[
|
|
8
|
-
|
|
9
|
-
## Quick start
|
|
10
|
-
|
|
11
|
-
Requirements: Node.js
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
npm install -g @ran-sh/dsh-crew@latest
|
|
15
|
-
dsh-crew install
|
|
16
|
-
dsh-crew integrate
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
dsh-crew
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
dsh-crew
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
node
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
node --test test/*.test.mjs
|
|
80
|
-
pnpm run build:client
|
|
81
|
-
node scripts/setup.mjs uninstall
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
For launchers at `<= 0.3.3`, refresh the launcher first. The old updater cannot discover newer releases and cannot be retroactively fixed:
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
npm install -g @ran-sh/dsh-crew@latest
|
|
88
|
-
dsh-crew update
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
Installation ownership and rollback details: [Installation plan](./docs/installation.md). Architecture contracts: [UI surfaces](./docs/ui-surfaces.md) · [Readiness](./docs/readiness-matrix.md) · [Jobs and information flow](./docs/job-contracts.md).
|
|
92
|
-
|
|
93
|
-
MIT
|
|
1
|
+
# DSH Crew
|
|
2
|
+
|
|
3
|
+
An isolated Crew Harness for Codex Desktop, ZCode, and Claude Code. It
|
|
4
|
+
provides Worker/Reviewer dispatch, model priorities, job tracking, and a
|
|
5
|
+
capability-aware safety gate.
|
|
6
|
+
|
|
7
|
+
[简体中文](./README.zh.md)
|
|
8
|
+
|
|
9
|
+
## Quick start
|
|
10
|
+
|
|
11
|
+
Requirements: Node.js and Git.
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install -g @ran-sh/dsh-crew@latest
|
|
15
|
+
dsh-crew install
|
|
16
|
+
dsh-crew integrate
|
|
17
|
+
dsh-crew status
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Open <http://127.0.0.1:3080> for the daily console. On Windows, installation
|
|
21
|
+
also registers login startup for the two local services.
|
|
22
|
+
|
|
23
|
+
| Surface | Purpose |
|
|
24
|
+
| --- | --- |
|
|
25
|
+
| `3080` | Daily console, Crew settings, integrations, and jobs |
|
|
26
|
+
| `3210` | Isolated Crew Harness, Providers, Harness Models, and low-level settings |
|
|
27
|
+
|
|
28
|
+
In **Settings → DSH Crew**, refresh Harness Models and order the Worker and
|
|
29
|
+
Reviewer model lists. Then ask a host agent:
|
|
30
|
+
|
|
31
|
+
```text
|
|
32
|
+
Use ds-worker to implement this change and run its tests.
|
|
33
|
+
Use ds-reviewer to review the result.
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Codex, ZCode, and Claude use the installed managed integration. The policy
|
|
37
|
+
checks live Crew capabilities before dispatch; if a selected Crew capability
|
|
38
|
+
becomes unavailable, the host pauses for an operator decision instead of
|
|
39
|
+
silently falling back.
|
|
40
|
+
|
|
41
|
+
## Useful commands
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
dsh-crew inspect # live capabilities and readiness
|
|
45
|
+
dsh-crew jobs list # jobs and Result Contracts
|
|
46
|
+
dsh-crew update # update and repair enabled integrations
|
|
47
|
+
dsh-crew uninstall # remove managed files, keep backups/config
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The runtime is isolated under `~/.config/dsh-crew/harness` with `profile: dsh-crew`;
|
|
51
|
+
the official `web` profile receives only the 3080 bridge.
|
|
52
|
+
|
|
53
|
+
## Legacy launcher migration
|
|
54
|
+
|
|
55
|
+
For launchers at `<= 0.3.3`, refresh the launcher first. The old updater cannot discover newer releases and cannot be retroactively fixed:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm install -g @ran-sh/dsh-crew@latest
|
|
59
|
+
dsh-crew update
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Install from source
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
git clone https://github.com/Ran-sh/dsh-crew.git
|
|
66
|
+
cd dsh-crew
|
|
67
|
+
node scripts/setup.mjs install
|
|
68
|
+
node scripts/setup.mjs status
|
|
69
|
+
node scripts/setup.mjs uninstall
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Run tests with `node --test test/*.test.mjs`. See [installation](./docs/installation.md),
|
|
73
|
+
[UI surfaces](./docs/ui-surfaces.md), [readiness](./docs/readiness-matrix.md),
|
|
74
|
+
and [job contracts](./docs/job-contracts.md) for details.
|
|
75
|
+
|
|
76
|
+
MIT
|
package/README.zh.md
CHANGED
|
@@ -1,93 +1,73 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
dsh-crew
|
|
16
|
-
dsh-crew
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
dsh-crew
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
dsh-crew
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
验证与卸载:
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
node --test test/*.test.mjs
|
|
80
|
-
pnpm run build:client
|
|
81
|
-
node scripts/setup.mjs uninstall
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
对于 `<= 0.3.3` 的旧启动器,请先刷新启动器。旧 updater 无法发现更新,也无法被追溯修复:
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
npm install -g @ran-sh/dsh-crew@latest
|
|
88
|
-
dsh-crew update
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
安装归属与回滚细节见[安装方案](./docs/installation.md)。架构合同:[界面分工](./docs/ui-surfaces.md) · [就绪矩阵](./docs/readiness-matrix.md) · [任务与信息流](./docs/job-contracts.md)。
|
|
92
|
-
|
|
93
|
-
MIT
|
|
1
|
+
# DSH Crew
|
|
2
|
+
|
|
3
|
+
为 Codex Desktop、ZCode 和 Claude Code 提供隔离的 Crew Harness,支持
|
|
4
|
+
Worker/Reviewer 调度、模型优先级、任务跟踪和能力感知安全门。
|
|
5
|
+
|
|
6
|
+
[English](./README.md)
|
|
7
|
+
|
|
8
|
+
## 快速开始
|
|
9
|
+
|
|
10
|
+
需要 Node.js 和 Git。
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install -g @ran-sh/dsh-crew@latest
|
|
14
|
+
dsh-crew install
|
|
15
|
+
dsh-crew integrate
|
|
16
|
+
dsh-crew status
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
打开 <http://127.0.0.1:3080> 进入日常控制台。Windows 安装会注册当前用户的
|
|
20
|
+
登录启动项,自动启动两个本地服务。
|
|
21
|
+
|
|
22
|
+
| 界面 | 用途 |
|
|
23
|
+
| --- | --- |
|
|
24
|
+
| `3080` | 日常控制台、Crew 设置、集成状态和任务 |
|
|
25
|
+
| `3210` | 隔离的 Crew Harness、Provider、Harness Models 和底层设置 |
|
|
26
|
+
|
|
27
|
+
进入 **设置 → DSH Crew**,刷新 Harness Models,并分别排列 Worker 与 Reviewer
|
|
28
|
+
的模型顺序。然后直接告诉 Codex、ZCode 或 Claude:
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
使用 ds-worker 实现这个改动并运行测试。
|
|
32
|
+
使用 ds-reviewer 审查结果。
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
集成会先检查 Crew 的实时能力;已选择 Crew 后若能力不可用,会暂停等待操作者
|
|
36
|
+
决定修复 Crew 还是由主代理本地完成,不会静默降级。
|
|
37
|
+
|
|
38
|
+
## 常用命令
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
dsh-crew inspect # 实时能力与就绪度
|
|
42
|
+
dsh-crew jobs list # 任务与 Result Contract
|
|
43
|
+
dsh-crew update # 更新并修复已启用集成
|
|
44
|
+
dsh-crew uninstall # 移除受管文件,保留配置/备份
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
运行时隔离在 `~/.config/dsh-crew/harness`,使用 `profile: dsh-crew`;官方 `web` profile
|
|
48
|
+
只接收 3080 轻量桥接。
|
|
49
|
+
|
|
50
|
+
## 旧启动器迁移
|
|
51
|
+
|
|
52
|
+
对于 `<= 0.3.3` 的旧启动器,请先刷新启动器。旧 updater 无法发现更新,也无法被追溯修复:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npm install -g @ran-sh/dsh-crew@latest
|
|
56
|
+
dsh-crew update
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 从源码安装
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
git clone https://github.com/Ran-sh/dsh-crew.git
|
|
63
|
+
cd dsh-crew
|
|
64
|
+
node scripts/setup.mjs install
|
|
65
|
+
node scripts/setup.mjs status
|
|
66
|
+
node scripts/setup.mjs uninstall
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
测试:`node --test test/*.test.mjs`。更多信息见[安装方案](./docs/installation.md)、
|
|
70
|
+
[界面分工](./docs/ui-surfaces.md)、[就绪矩阵](./docs/readiness-matrix.md)和
|
|
71
|
+
[任务合同](./docs/job-contracts.md)。
|
|
72
|
+
|
|
73
|
+
MIT
|
package/docs/installation.md
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
|
-
# Installation plan
|
|
2
|
-
|
|
3
|
-
DSH Crew uses an explicit installer. Merely installing the npm package does not mutate the host.
|
|
4
|
-
|
|
5
|
-
## Recommended path
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install -g @ran-sh/dsh-crew@latest
|
|
9
|
-
dsh-crew install
|
|
10
|
-
dsh-crew integrate
|
|
11
|
-
dsh-crew status
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
To test GitHub `main` before an npm release:
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
git clone https://github.com/Ran-sh/dsh-crew.git
|
|
18
|
-
cd dsh-crew
|
|
19
|
-
node scripts/setup.mjs install
|
|
20
|
-
node scripts/setup.mjs status
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Managed surfaces
|
|
24
|
-
|
|
25
|
-
| Surface | Installed behavior | Uninstall behavior |
|
|
26
|
-
| --- | --- | --- |
|
|
27
|
-
| Crew runtime | Isolated in `~/.config/dsh-crew/harness`, profile: dsh-crew | Registration removed; config kept unless `--purge` |
|
|
28
|
-
| Codex MCP and roles | Points Worker, Reviewer, and MCP to the installed release | Only DSH Crew entries are removed |
|
|
29
|
-
| Global Codex policy | Managed block inside `~/.codex/AGENTS.md` | Only the managed block is removed |
|
|
30
|
-
| ZCode MCP, agents and commands | Installs `~/.zcode/AGENTS.md`, `agents/{ds-worker,ds-reviewer}.md`, commands and a source-aware `dsh-crew` MCP entry | Only DSH Crew-owned files/entry are removed |
|
|
31
|
-
| Windows login startup | `DSH Crew.vbs`
|
|
32
|
-
| Official 3080 UI | Optional lightweight bridge after `integrate` | `detach` removes the bridge; a backup is kept |
|
|
33
|
-
|
|
34
|
-
The Windows login launcher starts the official UI on 3080 and the isolated Crew backend on 3210. It does not open a browser and does not store credentials.
|
|
35
|
-
|
|
36
|
-
ZCode uses `~/.zcode/cli/config.json` when it already has native MCP servers. If
|
|
37
|
-
that native list is empty, the installer uses `~/.agents/mcp.json`; unrelated
|
|
38
|
-
servers are preserved and a conflicting unowned `dsh-crew` entry fails closed.
|
|
39
|
-
|
|
40
|
-
## Verification
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
dsh-crew status
|
|
44
|
-
dsh-crew inspect
|
|
45
|
-
dsh-crew jobs list
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
Source checkout verification:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
node --test test/*.test.mjs
|
|
52
|
-
pnpm run build:client
|
|
53
|
-
npm pack --dry-run
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## Rollback
|
|
57
|
-
|
|
58
|
-
```bash
|
|
59
|
-
dsh-crew detach
|
|
60
|
-
dsh-crew uninstall
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Use `dsh-crew uninstall --purge` only when configuration and backups should also be deleted.
|
|
1
|
+
# Installation plan
|
|
2
|
+
|
|
3
|
+
DSH Crew uses an explicit installer. Merely installing the npm package does not mutate the host.
|
|
4
|
+
|
|
5
|
+
## Recommended path
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @ran-sh/dsh-crew@latest
|
|
9
|
+
dsh-crew install
|
|
10
|
+
dsh-crew integrate
|
|
11
|
+
dsh-crew status
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
To test GitHub `main` before an npm release:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
git clone https://github.com/Ran-sh/dsh-crew.git
|
|
18
|
+
cd dsh-crew
|
|
19
|
+
node scripts/setup.mjs install
|
|
20
|
+
node scripts/setup.mjs status
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Managed surfaces
|
|
24
|
+
|
|
25
|
+
| Surface | Installed behavior | Uninstall behavior |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| Crew runtime | Isolated in `~/.config/dsh-crew/harness`, profile: dsh-crew | Registration removed; config kept unless `--purge` |
|
|
28
|
+
| Codex MCP and roles | Points Worker, Reviewer, and MCP to the installed release | Only DSH Crew entries are removed |
|
|
29
|
+
| Global Codex policy | Managed block inside `~/.codex/AGENTS.md` | Only the managed block is removed |
|
|
30
|
+
| ZCode MCP, agents and commands | Installs `~/.zcode/AGENTS.md`, `agents/{ds-worker,ds-reviewer}.md`, commands and a source-aware `dsh-crew` MCP entry | Only DSH Crew-owned files/entry are removed |
|
|
31
|
+
| Windows login startup | `DSH Crew.vbs`, `start-dsh-crew.cmd`, and `start-dsh-crew.ps1` | Only DSH Crew-owned files are removed; foreign pre-existing content at those exact paths is preserved or fails closed |
|
|
32
|
+
| Official 3080 UI | Optional lightweight bridge after `integrate` | `detach` removes the bridge; a backup is kept |
|
|
33
|
+
|
|
34
|
+
The Windows login launcher starts the official UI on 3080 and the isolated Crew backend on 3210. It does not open a browser and does not store credentials.
|
|
35
|
+
|
|
36
|
+
ZCode uses `~/.zcode/cli/config.json` when it already has native MCP servers. If
|
|
37
|
+
that native list is empty, the installer uses `~/.agents/mcp.json`; unrelated
|
|
38
|
+
servers are preserved and a conflicting unowned `dsh-crew` entry fails closed.
|
|
39
|
+
|
|
40
|
+
## Verification
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
dsh-crew status
|
|
44
|
+
dsh-crew inspect
|
|
45
|
+
dsh-crew jobs list
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Source checkout verification:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
node --test test/*.test.mjs
|
|
52
|
+
pnpm run build:client
|
|
53
|
+
npm pack --dry-run
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Rollback
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
dsh-crew detach
|
|
60
|
+
dsh-crew uninstall
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Use `dsh-crew uninstall --purge` only when configuration and backups should also be deleted.
|
package/package.json
CHANGED
|
@@ -41,11 +41,13 @@ export function buildExtensionContract({ config = {}, readinessMatrix = {}, work
|
|
|
41
41
|
.map((id) => row(readinessMatrix, id))
|
|
42
42
|
.find((entry) => entry?.status === 'PASS');
|
|
43
43
|
const catalogEvidence = row(readinessMatrix, 'provider_catalog');
|
|
44
|
-
const modelReadiness =
|
|
45
|
-
?
|
|
46
|
-
:
|
|
47
|
-
? component('
|
|
48
|
-
:
|
|
44
|
+
const modelReadiness = catalogEvidence?.status === 'FAIL'
|
|
45
|
+
? readinessFromRow(catalogEvidence)
|
|
46
|
+
: realModelEvidence
|
|
47
|
+
? component('READY', realModelEvidence.reason_code ?? 'MODEL_EXECUTION_PASSED')
|
|
48
|
+
: catalogEvidence?.status === 'PASS' || catalogEvidence?.status === 'SKIP'
|
|
49
|
+
? component('DEGRADED', 'MODEL_CATALOG_ONLY')
|
|
50
|
+
: component('UNAVAILABLE', catalogEvidence?.reason_code ?? 'NO_EVIDENCE');
|
|
49
51
|
const components = {
|
|
50
52
|
harness: readinessFromRow(row(readinessMatrix, 'hub_compatibility')),
|
|
51
53
|
model: modelReadiness,
|
package/src/install/install.mjs
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
// This module keeps all installer exports while replacing only global config
|
|
5
5
|
// read/write semantics with schema-v3 canonical authority.
|
|
6
6
|
|
|
7
|
-
export * from './install-legacy.mjs';
|
|
8
|
-
export * from './windows-startup.mjs';
|
|
9
|
-
export * from './zcode.mjs';
|
|
7
|
+
export * from './install-legacy.mjs';
|
|
8
|
+
export * from './windows-startup.mjs';
|
|
9
|
+
export * from './zcode.mjs';
|
|
10
10
|
|
|
11
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
12
|
-
import { dirname, join } from 'node:path';
|
|
11
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
12
|
+
import { basename, dirname, join } from 'node:path';
|
|
13
13
|
import { homedir } from 'node:os';
|
|
14
14
|
import * as legacy from './install-legacy.mjs';
|
|
15
15
|
import { normalizeModelPriority } from '../model-routing.mjs';
|
|
@@ -58,6 +58,18 @@ function readJson(file, fallback) {
|
|
|
58
58
|
function validObject(value) {
|
|
59
59
|
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
60
60
|
}
|
|
61
|
+
function writeFileAtomic(file, content) {
|
|
62
|
+
const dir = dirname(file);
|
|
63
|
+
mkdirSync(dir, { recursive: true });
|
|
64
|
+
const temp = join(dir, `.${basename(file)}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.dsh-crew.tmp`);
|
|
65
|
+
try {
|
|
66
|
+
writeFileSync(temp, content);
|
|
67
|
+
renameSync(temp, file);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
try { rmSync(temp, { force: true }); } catch {}
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
61
73
|
|
|
62
74
|
function sourceVersion(stored) {
|
|
63
75
|
return Number.isInteger(stored?.config_schema_version) ? stored.config_schema_version : 0;
|
|
@@ -401,7 +413,7 @@ export function writeGlobalConfig(patch, { configFile = GLOBAL_CONFIG_FILE } = {
|
|
|
401
413
|
...normalized,
|
|
402
414
|
config_schema_version: CONFIG_SCHEMA_VERSION,
|
|
403
415
|
});
|
|
404
|
-
|
|
416
|
+
writeFileAtomic(configFile, JSON.stringify(persisted, null, 2) + '\n');
|
|
405
417
|
return attachReadMetadata(normalizeGlobalConfig(persisted), {
|
|
406
418
|
version: CONFIG_SCHEMA_VERSION,
|
|
407
419
|
canonical: true,
|