agent-gear 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/AGENTS.md +64 -5
  2. package/dist/cloud-host/supervisor.d.ts +92 -0
  3. package/dist/cloud-host/supervisor.d.ts.map +1 -0
  4. package/dist/cloud-host/supervisor.js +216 -0
  5. package/dist/cloud-host/supervisor.js.map +1 -0
  6. package/dist/cloud-host/supervisor.test.d.ts +2 -0
  7. package/dist/cloud-host/supervisor.test.d.ts.map +1 -0
  8. package/dist/cloud-host/supervisor.test.js +296 -0
  9. package/dist/cloud-host/supervisor.test.js.map +1 -0
  10. package/dist/commands/harness.d.ts +17 -0
  11. package/dist/commands/harness.d.ts.map +1 -0
  12. package/dist/commands/harness.js +35 -0
  13. package/dist/commands/harness.js.map +1 -0
  14. package/dist/config.d.ts.map +1 -1
  15. package/dist/config.js +10 -3
  16. package/dist/config.js.map +1 -1
  17. package/dist/harness/env.d.ts +36 -0
  18. package/dist/harness/env.d.ts.map +1 -0
  19. package/dist/harness/env.js +78 -0
  20. package/dist/harness/env.js.map +1 -0
  21. package/dist/harness/env.test.d.ts +2 -0
  22. package/dist/harness/env.test.d.ts.map +1 -0
  23. package/dist/harness/env.test.js +70 -0
  24. package/dist/harness/env.test.js.map +1 -0
  25. package/dist/harness/opencode-cli.d.ts +24 -0
  26. package/dist/harness/opencode-cli.d.ts.map +1 -0
  27. package/dist/harness/opencode-cli.js +74 -0
  28. package/dist/harness/opencode-cli.js.map +1 -0
  29. package/dist/harness/opencode-cli.test.d.ts +2 -0
  30. package/dist/harness/opencode-cli.test.d.ts.map +1 -0
  31. package/dist/harness/opencode-cli.test.js +62 -0
  32. package/dist/harness/opencode-cli.test.js.map +1 -0
  33. package/dist/harness/opencode-config.atomic-failure.test.d.ts +2 -0
  34. package/dist/harness/opencode-config.atomic-failure.test.d.ts.map +1 -0
  35. package/dist/harness/opencode-config.atomic-failure.test.js +35 -0
  36. package/dist/harness/opencode-config.atomic-failure.test.js.map +1 -0
  37. package/dist/harness/opencode-config.d.ts +54 -0
  38. package/dist/harness/opencode-config.d.ts.map +1 -0
  39. package/dist/harness/opencode-config.js +130 -0
  40. package/dist/harness/opencode-config.js.map +1 -0
  41. package/dist/harness/opencode-config.test.d.ts +2 -0
  42. package/dist/harness/opencode-config.test.d.ts.map +1 -0
  43. package/dist/harness/opencode-config.test.js +183 -0
  44. package/dist/harness/opencode-config.test.js.map +1 -0
  45. package/dist/harness/prepare.d.ts +34 -0
  46. package/dist/harness/prepare.d.ts.map +1 -0
  47. package/dist/harness/prepare.js +46 -0
  48. package/dist/harness/prepare.js.map +1 -0
  49. package/dist/harness/prepare.test.d.ts +2 -0
  50. package/dist/harness/prepare.test.d.ts.map +1 -0
  51. package/dist/harness/prepare.test.js +96 -0
  52. package/dist/harness/prepare.test.js.map +1 -0
  53. package/dist/heartbeat.d.ts.map +1 -1
  54. package/dist/heartbeat.js +2 -0
  55. package/dist/heartbeat.js.map +1 -1
  56. package/dist/index.js +21 -0
  57. package/dist/index.js.map +1 -1
  58. package/dist/socketio-client.d.ts +62 -3
  59. package/dist/socketio-client.d.ts.map +1 -1
  60. package/dist/socketio-client.js +155 -16
  61. package/dist/socketio-client.js.map +1 -1
  62. package/dist/socketio-client.test.d.ts +2 -0
  63. package/dist/socketio-client.test.d.ts.map +1 -0
  64. package/dist/socketio-client.test.js +132 -0
  65. package/dist/socketio-client.test.js.map +1 -0
  66. package/dist/workload-executor.d.ts +24 -1
  67. package/dist/workload-executor.d.ts.map +1 -1
  68. package/dist/workload-executor.js +78 -16
  69. package/dist/workload-executor.js.map +1 -1
  70. package/dist/workload-executor.test.js +99 -1
  71. package/dist/workload-executor.test.js.map +1 -1
  72. package/package.json +2 -1
  73. package/src/cloud-host/supervisor.test.ts +367 -0
  74. package/src/cloud-host/supervisor.ts +289 -0
  75. package/src/commands/harness.ts +44 -0
  76. package/src/config.ts +9 -3
  77. package/src/harness/env.test.ts +79 -0
  78. package/src/harness/env.ts +89 -0
  79. package/src/harness/opencode-cli.test.ts +82 -0
  80. package/src/harness/opencode-cli.ts +99 -0
  81. package/src/harness/opencode-config.atomic-failure.test.ts +51 -0
  82. package/src/harness/opencode-config.test.ts +238 -0
  83. package/src/harness/opencode-config.ts +176 -0
  84. package/src/harness/prepare.test.ts +117 -0
  85. package/src/harness/prepare.ts +69 -0
  86. package/src/heartbeat.ts +2 -0
  87. package/src/index.ts +22 -0
  88. package/src/socketio-client.test.ts +155 -0
  89. package/src/socketio-client.ts +204 -18
  90. package/src/workload-executor.test.ts +120 -0
  91. package/src/workload-executor.ts +100 -17
  92. package/tests/commands/harness.test.ts +90 -0
  93. package/tests/socketio-client.test.ts +140 -2
@@ -0,0 +1,296 @@
1
+ import { describe, it, expect, vi, afterEach } from 'vitest';
2
+ import { mkdtemp, mkdir, rm, stat } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { CLOUD_HOST_MODE_KEYS, DEFAULT_HARNESS_INIT_WAIT_MS, DEFAULT_WORKSPACE, CloudHostEnvError, isCloudHostMode, parseInitWaitMs, readCloudHostEnv, resolveShutdownExitCode, startCloudHostSupervisor, } from './supervisor.js';
5
+ const TMP_BASE = '/tmp/opencode';
6
+ const BASE_ENV = {
7
+ ZAG_HOST_ENDPOINT: 'wss://controller.example.com',
8
+ ZAG_HOST_KEY: 'zag_k_1_host_key_secret',
9
+ ZAG_CONTROLLER_KEY: 'controller-token-secret',
10
+ ZAG_SERVER_ENDPOINT: 'wss://cloud-controller.example.com/worker',
11
+ ZAG_HOST_NAME: 'my-cloud-host',
12
+ ZAG_DEFAULT_WORKSPACE: '/root/workspace',
13
+ };
14
+ function fakeSocket() {
15
+ return { disconnect: vi.fn(), emit: vi.fn() };
16
+ }
17
+ function setup(overrides = {}) {
18
+ const worker = fakeSocket();
19
+ const controller = fakeSocket();
20
+ const connect = vi.fn((endpoint, key, options) => {
21
+ void endpoint;
22
+ void key;
23
+ void options;
24
+ return (connect.mock.calls.length === 1 ? worker : controller);
25
+ });
26
+ const exit = vi.fn();
27
+ const logs = [];
28
+ return {
29
+ worker,
30
+ controller,
31
+ connect,
32
+ exit,
33
+ logs,
34
+ deps: {
35
+ env: overrides.env ?? { ...BASE_ENV },
36
+ connect: connect,
37
+ makeDir: overrides.makeDir ?? (async () => { }),
38
+ exit,
39
+ log: (message) => logs.push(message),
40
+ installSignalHandlers: false,
41
+ },
42
+ };
43
+ }
44
+ describe('cloud host mode detection (T-AG2)', () => {
45
+ it('requires all three cloud-host env variables to be non-empty', () => {
46
+ expect(isCloudHostMode(BASE_ENV)).toBe(true);
47
+ for (const key of CLOUD_HOST_MODE_KEYS) {
48
+ expect(isCloudHostMode({ ...BASE_ENV, [key]: '' })).toBe(false);
49
+ expect(isCloudHostMode({ ...BASE_ENV, [key]: ' ' })).toBe(false);
50
+ expect(isCloudHostMode({ ...BASE_ENV, [key]: undefined })).toBe(false);
51
+ }
52
+ // 本地控制器单连接(无 ZAG_HOST_*)不进入云电脑模式
53
+ expect(isCloudHostMode({
54
+ ZAG_SERVER_ENDPOINT: 'http://localhost:4001',
55
+ ZAG_CONTROLLER_KEY: 'zag_k_1_local',
56
+ })).toBe(false);
57
+ });
58
+ it('parses HARNESS_INIT_WAIT_MS with the 10 minute default', () => {
59
+ expect(parseInitWaitMs(undefined)).toBe(DEFAULT_HARNESS_INIT_WAIT_MS);
60
+ expect(DEFAULT_HARNESS_INIT_WAIT_MS).toBe(600_000);
61
+ expect(parseInitWaitMs('1500')).toBe(1500);
62
+ expect(parseInitWaitMs('0')).toBe(DEFAULT_HARNESS_INIT_WAIT_MS);
63
+ expect(parseInitWaitMs('-1')).toBe(DEFAULT_HARNESS_INIT_WAIT_MS);
64
+ expect(parseInitWaitMs('abc')).toBe(DEFAULT_HARNESS_INIT_WAIT_MS);
65
+ });
66
+ });
67
+ describe('readCloudHostEnv (T-AG7)', () => {
68
+ it('reads required values and applies defaults', () => {
69
+ const env = readCloudHostEnv({
70
+ ZAG_HOST_ENDPOINT: ' wss://controller.example.com ',
71
+ ZAG_HOST_KEY: 'host-key',
72
+ ZAG_CONTROLLER_KEY: 'worker-token',
73
+ ZAG_SERVER_ENDPOINT: 'wss://cc.example.com/worker',
74
+ });
75
+ expect(env).toMatchObject({
76
+ hostEndpoint: 'wss://controller.example.com',
77
+ hostKey: 'host-key',
78
+ controllerKey: 'worker-token',
79
+ serverEndpoint: 'wss://cc.example.com/worker',
80
+ workspace: DEFAULT_WORKSPACE,
81
+ initWaitMs: DEFAULT_HARNESS_INIT_WAIT_MS,
82
+ });
83
+ expect(env.hostName.length).toBeGreaterThan(0);
84
+ });
85
+ it('lists every missing variable by name without leaking values of present ones', () => {
86
+ let error;
87
+ try {
88
+ readCloudHostEnv({
89
+ ZAG_HOST_ENDPOINT: 'wss://controller.example.com',
90
+ ZAG_HOST_KEY: 'super-secret-host-key',
91
+ });
92
+ }
93
+ catch (caught) {
94
+ error = caught;
95
+ }
96
+ expect(error).toBeInstanceOf(CloudHostEnvError);
97
+ const message = error.message;
98
+ expect(message).toContain('ZAG_CONTROLLER_KEY');
99
+ expect(message).toContain('ZAG_SERVER_ENDPOINT');
100
+ expect(message).not.toContain('super-secret-host-key');
101
+ expect(message).not.toContain('wss://controller.example.com');
102
+ });
103
+ });
104
+ describe('startCloudHostSupervisor', () => {
105
+ const dirs = [];
106
+ afterEach(async () => {
107
+ await Promise.all(dirs.splice(0).map((dir) => rm(dir, { recursive: true, force: true })));
108
+ });
109
+ it('T-AG6: creates the default workspace idempotently before connecting', async () => {
110
+ await mkdir(TMP_BASE, { recursive: true });
111
+ const dir = await mkdtemp(join(TMP_BASE, 'supervisor-'));
112
+ dirs.push(dir);
113
+ const workspace = join(dir, 'workspace', 'nested');
114
+ const context = setup({
115
+ env: { ...BASE_ENV, ZAG_DEFAULT_WORKSPACE: workspace },
116
+ makeDir: async (path) => {
117
+ await mkdir(path, { recursive: true });
118
+ },
119
+ });
120
+ const handle = await startCloudHostSupervisor(context.deps);
121
+ await startCloudHostSupervisor(context.deps);
122
+ expect((await stat(workspace)).isDirectory()).toBe(true);
123
+ expect(handle.workspace).toBe(workspace);
124
+ // makeDir 在连接之前完成(connect 的调用发生在其后)
125
+ expect(context.connect).toHaveBeenCalledTimes(2);
126
+ });
127
+ it('T-AG3: connects /worker first with the one-time token and no local MCP server', async () => {
128
+ const context = setup();
129
+ const handle = await startCloudHostSupervisor(context.deps);
130
+ expect(context.connect).toHaveBeenCalledTimes(1);
131
+ const [endpoint, key, options] = context.connect.mock.calls[0];
132
+ expect(endpoint).toBe(BASE_ENV.ZAG_SERVER_ENDPOINT);
133
+ expect(key).toBe(BASE_ENV.ZAG_CONTROLLER_KEY);
134
+ expect(options).toMatchObject({
135
+ serverName: 'my-cloud-host',
136
+ handshakeToken: BASE_ENV.ZAG_CONTROLLER_KEY,
137
+ skipLocalMcpStart: true,
138
+ handleWorkload: true,
139
+ persistConfig: false,
140
+ });
141
+ expect(handle.controllerSocket).toBeNull();
142
+ });
143
+ it('T-AG3b: connects controller-api immediately when initializing is false/absent', async () => {
144
+ const context = setup();
145
+ await startCloudHostSupervisor(context.deps);
146
+ const workerOptions = context.connect.mock.calls[0][2];
147
+ workerOptions.onRegistered?.({ controllerId: 'container-1', initializing: false });
148
+ expect(context.connect).toHaveBeenCalledTimes(2);
149
+ const [endpoint, key, options] = context.connect.mock.calls[1];
150
+ expect(endpoint).toBe(BASE_ENV.ZAG_HOST_ENDPOINT);
151
+ expect(key).toBe(BASE_ENV.ZAG_HOST_KEY);
152
+ expect(options).toMatchObject({
153
+ handshakeToken: BASE_ENV.ZAG_HOST_KEY,
154
+ skipLocalMcpStart: false,
155
+ handleWorkload: false,
156
+ persistConfig: false,
157
+ });
158
+ // 重复 registered(重连)不应重复建连
159
+ workerOptions.onRegistered?.({ controllerId: 'container-1' });
160
+ expect(context.connect).toHaveBeenCalledTimes(2);
161
+ });
162
+ it('T-AG4: waits for the first init workload batch when initializing=true', async () => {
163
+ const context = setup();
164
+ await startCloudHostSupervisor(context.deps);
165
+ const workerOptions = context.connect.mock.calls[0][2];
166
+ workerOptions.onRegistered?.({ controllerId: 'container-1', initializing: true });
167
+ expect(context.connect).toHaveBeenCalledTimes(1);
168
+ // post 批次不触发标准连接
169
+ workerOptions.onWorkloadBatchComplete?.({ phase: 'post', itemCount: 1, status: 'completed' });
170
+ expect(context.connect).toHaveBeenCalledTimes(1);
171
+ workerOptions.onWorkloadBatchComplete?.({ phase: 'init', itemCount: 2, status: 'completed' });
172
+ expect(context.connect).toHaveBeenCalledTimes(2);
173
+ });
174
+ it('T-AG4b: connects after a failed init batch too', async () => {
175
+ const context = setup();
176
+ await startCloudHostSupervisor(context.deps);
177
+ const workerOptions = context.connect.mock.calls[0][2];
178
+ workerOptions.onRegistered?.({ controllerId: 'container-1', initializing: true });
179
+ workerOptions.onWorkloadBatchComplete?.({ phase: 'init', itemCount: 1, status: 'failed', error: 'boom' });
180
+ expect(context.connect).toHaveBeenCalledTimes(2);
181
+ });
182
+ it('T-AG4e: does not treat an interrupted (cancelled) init batch as complete', async () => {
183
+ const context = setup();
184
+ await startCloudHostSupervisor(context.deps);
185
+ const workerOptions = context.connect.mock.calls[0][2];
186
+ workerOptions.onRegistered?.({ controllerId: 'container-1', initializing: true });
187
+ workerOptions.onWorkloadBatchComplete?.({
188
+ phase: 'init',
189
+ itemCount: 1,
190
+ status: 'cancelled',
191
+ cancelled: true,
192
+ failedCount: 0,
193
+ });
194
+ expect(context.connect).toHaveBeenCalledTimes(1);
195
+ // 重连重放后的真实 init 完成才建立标准连接
196
+ workerOptions.onWorkloadBatchComplete?.({
197
+ phase: 'init',
198
+ itemCount: 1,
199
+ status: 'completed',
200
+ cancelled: false,
201
+ failedCount: 0,
202
+ });
203
+ expect(context.connect).toHaveBeenCalledTimes(2);
204
+ });
205
+ it('T-AG4c: connects after the init wait timeout', async () => {
206
+ const context = setup({ env: { ...BASE_ENV, HARNESS_INIT_WAIT_MS: '20' } });
207
+ await startCloudHostSupervisor(context.deps);
208
+ const workerOptions = context.connect.mock.calls[0][2];
209
+ workerOptions.onRegistered?.({ controllerId: 'container-1', initializing: true });
210
+ expect(context.connect).toHaveBeenCalledTimes(1);
211
+ await vi.waitFor(() => {
212
+ expect(context.connect).toHaveBeenCalledTimes(2);
213
+ });
214
+ // 超时后迟到的 initializing registered 不得再次进入等待(不产生幽灵定时器/重复连接)
215
+ workerOptions.onRegistered?.({ controllerId: 'container-1', initializing: true });
216
+ expect(context.connect).toHaveBeenCalledTimes(2);
217
+ expect(context.logs.join('\n')).toContain('timed out');
218
+ });
219
+ it('T-AG4d: connects immediately when the init batch finished before registered', async () => {
220
+ const context = setup();
221
+ await startCloudHostSupervisor(context.deps);
222
+ const workerOptions = context.connect.mock.calls[0][2];
223
+ workerOptions.onWorkloadBatchComplete?.({ phase: 'init', itemCount: 1, status: 'completed' });
224
+ expect(context.connect).toHaveBeenCalledTimes(1);
225
+ workerOptions.onRegistered?.({ controllerId: 'container-1', initializing: true });
226
+ expect(context.connect).toHaveBeenCalledTimes(2);
227
+ });
228
+ it('T-AG17: shutdown from either side closes both sockets and exits 0 without unregister', async () => {
229
+ const context = setup();
230
+ const handle = await startCloudHostSupervisor(context.deps);
231
+ const workerOptions = context.connect.mock.calls[0][2];
232
+ workerOptions.onRegistered?.({ controllerId: 'container-1', initializing: false });
233
+ const controllerOptions = context.connect.mock.calls[1][2];
234
+ workerOptions.onShutdown?.({ reason: 'server requested shutdown' });
235
+ expect(context.worker.disconnect).toHaveBeenCalled();
236
+ expect(context.controller.disconnect).toHaveBeenCalled();
237
+ expect(context.exit).toHaveBeenCalledWith(0);
238
+ expect(context.worker.emit).not.toHaveBeenCalledWith('unregister', expect.anything());
239
+ expect(context.controller.emit).not.toHaveBeenCalledWith('unregister', expect.anything());
240
+ // 另一端 shutdown / 重复 shutdown 幂等
241
+ controllerOptions.onShutdown?.({ reason: 'duplicate' });
242
+ handle.shutdown('SIGTERM');
243
+ expect(context.exit).toHaveBeenCalledTimes(1);
244
+ });
245
+ it('T-AG17b: worker shutdown before the controller connection only closes the worker', async () => {
246
+ const context = setup();
247
+ await startCloudHostSupervisor(context.deps);
248
+ const workerOptions = context.connect.mock.calls[0][2];
249
+ workerOptions.onShutdown?.({ reason: 'server requested shutdown' });
250
+ expect(context.worker.disconnect).toHaveBeenCalled();
251
+ expect(context.controller.disconnect).not.toHaveBeenCalled();
252
+ expect(context.exit).toHaveBeenCalledWith(0);
253
+ });
254
+ it('C-2: failure/version-mismatch shutdown exits non-zero (entrypoint self-heal path)', async () => {
255
+ // socketio-client 的错误事件 reason 前缀
256
+ expect(resolveShutdownExitCode('version_mismatch: agent-gear 版本不兼容')).toBe(1);
257
+ expect(resolveShutdownExitCode('error: REGISTER_FAILED')).toBe(1);
258
+ // 必须工作负载初始化失败(worker shutdown 包装后仍须识别)
259
+ expect(resolveShutdownExitCode('worker shutdown: 必须工作负载「OpenCode(Harness)」初始化失败')).toBe(1);
260
+ expect(resolveShutdownExitCode('required init failed')).toBe(1);
261
+ // 正常路径
262
+ expect(resolveShutdownExitCode('controller-api shutdown: server requested')).toBe(0);
263
+ expect(resolveShutdownExitCode('SIGINT')).toBe(0);
264
+ expect(resolveShutdownExitCode('unregistered')).toBe(0);
265
+ });
266
+ it('C-2: required init failure closes both sockets and exits 1', async () => {
267
+ const context = setup();
268
+ await startCloudHostSupervisor(context.deps);
269
+ const workerOptions = context.connect.mock.calls[0][2];
270
+ workerOptions.onRegistered?.({ controllerId: 'container-1', initializing: false });
271
+ workerOptions.onShutdown?.({ reason: 'worker shutdown: 必须工作负载初始化失败' });
272
+ expect(context.worker.disconnect).toHaveBeenCalled();
273
+ expect(context.controller.disconnect).toHaveBeenCalled();
274
+ expect(context.exit).toHaveBeenCalledWith(1);
275
+ expect(context.worker.emit).not.toHaveBeenCalledWith('unregister', expect.anything());
276
+ // 显式 code 优先(调用方可覆盖)
277
+ const explicit = setup();
278
+ const explicitHandle = await startCloudHostSupervisor(explicit.deps);
279
+ explicitHandle.shutdown('server requested shutdown', 1);
280
+ expect(explicit.exit).toHaveBeenCalledWith(1);
281
+ });
282
+ it('C-2: version_mismatch reason exits 1', async () => {
283
+ const context = setup();
284
+ await startCloudHostSupervisor(context.deps);
285
+ const workerOptions = context.connect.mock.calls[0][2];
286
+ workerOptions.onShutdown?.({ reason: 'version_mismatch: agent-gear 版本不兼容' });
287
+ expect(context.exit).toHaveBeenCalledWith(1);
288
+ });
289
+ it('T-AG7b: rejects with a clear error instead of connecting when cloud-host env is incomplete', async () => {
290
+ const context = setup({ env: { ...BASE_ENV, ZAG_HOST_KEY: '' } });
291
+ await expect(startCloudHostSupervisor(context.deps)).rejects.toBeInstanceOf(CloudHostEnvError);
292
+ expect(context.connect).not.toHaveBeenCalled();
293
+ expect(context.exit).not.toHaveBeenCalled();
294
+ });
295
+ });
296
+ //# sourceMappingURL=supervisor.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supervisor.test.js","sourceRoot":"","sources":["../../src/cloud-host/supervisor.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { Command } from 'commander';
2
+ import { prepareHarness, type PrepareHarnessOptions } from '../harness/prepare.js';
3
+ export interface RegisterHarnessCommandsDeps {
4
+ prepare?: (options?: PrepareHarnessOptions) => Promise<Awaited<ReturnType<typeof prepareHarness>>>;
5
+ }
6
+ /**
7
+ * 注册 `agent-gear harness` 命令组。
8
+ *
9
+ * ```
10
+ * agent-gear harness prepare # 校验 env → opencode --version → 写 opencode.jsonc
11
+ * ```
12
+ *
13
+ * 失败以退出码 1 结束(供 harness 工作负载 `required=true` 触发容器强制注销);
14
+ * 输出/错误均对 `ZAG_MODEL_API_KEY` 等 secret 脱敏。
15
+ */
16
+ export declare function registerHarnessCommands(program: Command, deps?: RegisterHarnessCommandsDeps): Command;
17
+ //# sourceMappingURL=harness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../src/commands/harness.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,EAAwB,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAEzG,MAAM,WAAW,2BAA2B;IAC1C,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,qBAAqB,KAAK,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC;CACpG;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,OAAO,EAChB,IAAI,GAAE,2BAAgC,GACrC,OAAO,CAsBT"}
@@ -0,0 +1,35 @@
1
+ import { collectSecretValues, redactSecrets } from '../workload-executor.js';
2
+ import { formatPrepareSummary, prepareHarness } from '../harness/prepare.js';
3
+ /**
4
+ * 注册 `agent-gear harness` 命令组。
5
+ *
6
+ * ```
7
+ * agent-gear harness prepare # 校验 env → opencode --version → 写 opencode.jsonc
8
+ * ```
9
+ *
10
+ * 失败以退出码 1 结束(供 harness 工作负载 `required=true` 触发容器强制注销);
11
+ * 输出/错误均对 `ZAG_MODEL_API_KEY` 等 secret 脱敏。
12
+ */
13
+ export function registerHarnessCommands(program, deps = {}) {
14
+ const harness = program
15
+ .command('harness')
16
+ .description('Prepare harness runtime (OpenCode) for cloud-host containers');
17
+ harness
18
+ .command('prepare')
19
+ .description('Validate harness env, verify OpenCode CLI and write provider.zag into opencode.jsonc')
20
+ .action(async () => {
21
+ try {
22
+ const result = await (deps.prepare ?? prepareHarness)();
23
+ console.log(formatPrepareSummary(result));
24
+ }
25
+ catch (error) {
26
+ const secrets = collectSecretValues(process.env);
27
+ const message = redactSecrets(error.message, secrets);
28
+ console.error(`harness prepare failed: ${message}`);
29
+ // 非零退出:不直接 process.exit,便于测试断言 exitCode 与已刷新的日志。
30
+ process.exitCode = 1;
31
+ }
32
+ });
33
+ return harness;
34
+ }
35
+ //# sourceMappingURL=harness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.js","sourceRoot":"","sources":["../../src/commands/harness.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAA8B,MAAM,uBAAuB,CAAC;AAMzG;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAAgB,EAChB,OAAoC,EAAE;IAEtC,MAAM,OAAO,GAAG,OAAO;SACpB,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,8DAA8D,CAAC,CAAC;IAE/E,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,sFAAsF,CAAC;SACnG,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,cAAc,CAAC,EAAE,CAAC;YACxD,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACjD,MAAM,OAAO,GAAG,aAAa,CAAE,KAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACjE,OAAO,CAAC,KAAK,CAAC,2BAA2B,OAAO,EAAE,CAAC,CAAC;YACpD,iDAAiD;YACjD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACxB,MAAM,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9B,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9B,WAAW,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACjC;AAED,wBAAgB,UAAU,IAAI,UAAU,CAMvC;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAKlD;AAED,wBAAgB,cAAc,IAAI,IAAI,CAIrC;AAED,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAGrD;AAED,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,SAAS,CAG1D;AAED,wBAAgB,2BAA2B,IAAI,MAAM,GAAG,SAAS,CAGhE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAIjD;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAI3D;AAED,wBAAgB,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAK9D;AAED,wBAAgB,eAAe,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKxE;AAED,wBAAgB,wBAAwB,IAAI,MAAM,GAAG,SAAS,CAG7D;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAI3D;AAED,wBAAgB,0BAA0B,IAAI,IAAI,CAIjD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACxB,MAAM,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9B,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9B,WAAW,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACjC;AAED,wBAAgB,UAAU,IAAI,UAAU,CAMvC;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAWlD;AAED,wBAAgB,cAAc,IAAI,IAAI,CAIrC;AAED,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAGrD;AAED,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,SAAS,CAG1D;AAED,wBAAgB,2BAA2B,IAAI,MAAM,GAAG,SAAS,CAGhE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAIjD;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAI3D;AAED,wBAAgB,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAK9D;AAED,wBAAgB,eAAe,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKxE;AAED,wBAAgB,wBAAwB,IAAI,MAAM,GAAG,SAAS,CAG7D;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAI3D;AAED,wBAAgB,0BAA0B,IAAI,IAAI,CAIjD"}
package/dist/config.js CHANGED
@@ -1,4 +1,4 @@
1
- import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
1
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, chmodSync } from 'fs';
2
2
  import { join } from 'path';
3
3
  import { homedir } from 'os';
4
4
  import { parse, stringify } from 'smol-toml';
@@ -13,9 +13,16 @@ export function readConfig() {
13
13
  }
14
14
  export function writeConfig(data) {
15
15
  if (!existsSync(CONFIG_DIR)) {
16
- mkdirSync(CONFIG_DIR, { recursive: true });
16
+ mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
17
+ }
18
+ // 配置含 Key/resumeToken:仅属主可读写(避免 world-readable 凭据落盘)。
19
+ writeFileSync(CONFIG_FILE, stringify(data), { encoding: 'utf-8', mode: 0o600 });
20
+ try {
21
+ chmodSync(CONFIG_FILE, 0o600);
22
+ }
23
+ catch {
24
+ // 某些平台/文件系统不支持 chmod:不阻断配置写入(已在 Windows 等平台降级)
17
25
  }
18
- writeFileSync(CONFIG_FILE, stringify(data), 'utf-8');
19
26
  }
20
27
  export function clearConfigKey() {
21
28
  const config = readConfig();
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * harness(OpenCode 云电脑)初始化环境校验。
3
+ *
4
+ * 只读取 `harness prepare` 需要的变量;缺失/非法时一次性列出**变量名**,
5
+ * 绝不回显其它 env 的值(尤其 `ZAG_MODEL_API_KEY` 等 secret)。
6
+ */
7
+ /** harness prepare 需要的环境(已归一)。 */
8
+ export interface HarnessEnv {
9
+ /** 模型网关地址(`ZAG_MODEL_BASE_URL`)。 */
10
+ modelBaseUrl: string;
11
+ /** 运行专用模型 Key(`ZAG_MODEL_API_KEY`,禁止打印)。 */
12
+ modelApiKey: string;
13
+ /** 可用模型 ID 列表(`ZAG_MODEL_IDS`,JSON 数组字符串,去空去重)。 */
14
+ modelIds: string[];
15
+ /** 默认工作区(`ZAG_DEFAULT_WORKSPACE`)。 */
16
+ defaultWorkspace: string;
17
+ }
18
+ /** env 校验失败(消息不含任何变量值)。 */
19
+ export declare class HarnessEnvError extends Error {
20
+ constructor(message: string);
21
+ }
22
+ /**
23
+ * 解析 `ZAG_MODEL_IDS`:必须是字符串 JSON 数组;元素 trim 后去空、去重(保持原顺序)。
24
+ *
25
+ * - `[]` 合法(T-AG11:空数组仍写 `models:{}`);
26
+ * - 非数组/非法 JSON/含非字符串元素 → 明确报错(不输出原始值)。
27
+ */
28
+ export declare function parseModelIds(raw: string): string[];
29
+ /**
30
+ * 读取并校验 harness env。
31
+ *
32
+ * 必需:`ZAG_MODEL_BASE_URL` / `ZAG_MODEL_API_KEY` / `ZAG_MODEL_IDS` / `ZAG_DEFAULT_WORKSPACE`
33
+ * (云电脑 Job env 与 `workload:run.env` 均由 agent-api 注入,缺失说明编排不正确)。
34
+ */
35
+ export declare function readHarnessEnv(env?: NodeJS.ProcessEnv): HarnessEnv;
36
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/harness/env.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,kCAAkC;AAClC,MAAM,WAAW,UAAU;IACzB,oCAAoC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,sCAAsC;IACtC,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,2BAA2B;AAC3B,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAMD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAsBnD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,UAAU,CAqB/E"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * harness(OpenCode 云电脑)初始化环境校验。
3
+ *
4
+ * 只读取 `harness prepare` 需要的变量;缺失/非法时一次性列出**变量名**,
5
+ * 绝不回显其它 env 的值(尤其 `ZAG_MODEL_API_KEY` 等 secret)。
6
+ */
7
+ /** env 校验失败(消息不含任何变量值)。 */
8
+ export class HarnessEnvError extends Error {
9
+ constructor(message) {
10
+ super(message);
11
+ this.name = 'HarnessEnvError';
12
+ }
13
+ }
14
+ function nonEmpty(value) {
15
+ return typeof value === 'string' ? value.trim() : '';
16
+ }
17
+ /**
18
+ * 解析 `ZAG_MODEL_IDS`:必须是字符串 JSON 数组;元素 trim 后去空、去重(保持原顺序)。
19
+ *
20
+ * - `[]` 合法(T-AG11:空数组仍写 `models:{}`);
21
+ * - 非数组/非法 JSON/含非字符串元素 → 明确报错(不输出原始值)。
22
+ */
23
+ export function parseModelIds(raw) {
24
+ let parsed;
25
+ try {
26
+ parsed = JSON.parse(raw);
27
+ }
28
+ catch {
29
+ throw new HarnessEnvError('ZAG_MODEL_IDS must be a JSON array of strings (invalid JSON)');
30
+ }
31
+ if (!Array.isArray(parsed)) {
32
+ throw new HarnessEnvError('ZAG_MODEL_IDS must be a JSON array of strings');
33
+ }
34
+ if (!parsed.every((item) => typeof item === 'string')) {
35
+ throw new HarnessEnvError('ZAG_MODEL_IDS must be a JSON array of strings (non-string element)');
36
+ }
37
+ const unique = [];
38
+ const seen = new Set();
39
+ for (const item of parsed) {
40
+ const value = item.trim();
41
+ if (!value || seen.has(value))
42
+ continue;
43
+ seen.add(value);
44
+ unique.push(value);
45
+ }
46
+ return unique;
47
+ }
48
+ /**
49
+ * 读取并校验 harness env。
50
+ *
51
+ * 必需:`ZAG_MODEL_BASE_URL` / `ZAG_MODEL_API_KEY` / `ZAG_MODEL_IDS` / `ZAG_DEFAULT_WORKSPACE`
52
+ * (云电脑 Job env 与 `workload:run.env` 均由 agent-api 注入,缺失说明编排不正确)。
53
+ */
54
+ export function readHarnessEnv(env = process.env) {
55
+ const missing = [];
56
+ const modelBaseUrl = nonEmpty(env.ZAG_MODEL_BASE_URL);
57
+ if (!modelBaseUrl)
58
+ missing.push('ZAG_MODEL_BASE_URL');
59
+ const modelApiKey = nonEmpty(env.ZAG_MODEL_API_KEY);
60
+ if (!modelApiKey)
61
+ missing.push('ZAG_MODEL_API_KEY');
62
+ const rawModelIds = nonEmpty(env.ZAG_MODEL_IDS);
63
+ if (!rawModelIds)
64
+ missing.push('ZAG_MODEL_IDS');
65
+ const defaultWorkspace = nonEmpty(env.ZAG_DEFAULT_WORKSPACE);
66
+ if (!defaultWorkspace)
67
+ missing.push('ZAG_DEFAULT_WORKSPACE');
68
+ if (missing.length > 0) {
69
+ throw new HarnessEnvError(`missing required environment variable(s): ${missing.join(', ')}`);
70
+ }
71
+ return {
72
+ modelBaseUrl,
73
+ modelApiKey,
74
+ modelIds: parseModelIds(rawModelIds),
75
+ defaultWorkspace,
76
+ };
77
+ }
78
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/harness/env.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAcH,2BAA2B;AAC3B,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,SAAS,QAAQ,CAAC,KAAyB;IACzC,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,eAAe,CAAC,8DAA8D,CAAC,CAAC;IAC5F,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,eAAe,CAAC,+CAA+C,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,eAAe,CAAC,oEAAoE,CAAC,CAAC;IAClG,CAAC;IACD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,MAAkB,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1B,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,SAAS;QACxC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,MAAyB,OAAO,CAAC,GAAG;IACjE,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACtD,IAAI,CAAC,YAAY;QAAE,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACtD,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACpD,IAAI,CAAC,WAAW;QAAE,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IACpD,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAChD,IAAI,CAAC,WAAW;QAAE,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAChD,MAAM,gBAAgB,GAAG,QAAQ,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;IAC7D,IAAI,CAAC,gBAAgB;QAAE,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IAE7D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,eAAe,CAAC,6CAA6C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,OAAO;QACL,YAAY;QACZ,WAAW;QACX,QAAQ,EAAE,aAAa,CAAC,WAAW,CAAC;QACpC,gBAAgB;KACjB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=env.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.test.d.ts","sourceRoot":"","sources":["../../src/harness/env.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,70 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { HarnessEnvError, parseModelIds, readHarnessEnv } from './env.js';
3
+ const VALID_ENV = {
4
+ ZAG_MODEL_BASE_URL: 'http://admin-api:8002/v1',
5
+ ZAG_MODEL_API_KEY: 'zag_sk_super_secret',
6
+ ZAG_MODEL_IDS: '["model-a","model-b"]',
7
+ ZAG_DEFAULT_WORKSPACE: '/root/workspace',
8
+ };
9
+ describe('readHarnessEnv (T-AG7/T-AG11)', () => {
10
+ it('reads a valid harness env', () => {
11
+ expect(readHarnessEnv(VALID_ENV)).toEqual({
12
+ modelBaseUrl: 'http://admin-api:8002/v1',
13
+ modelApiKey: 'zag_sk_super_secret',
14
+ modelIds: ['model-a', 'model-b'],
15
+ defaultWorkspace: '/root/workspace',
16
+ });
17
+ });
18
+ it('lists all missing variables by name and never leaks secret values', () => {
19
+ let error;
20
+ try {
21
+ readHarnessEnv({ ZAG_MODEL_API_KEY: 'zag_sk_super_secret' });
22
+ }
23
+ catch (caught) {
24
+ error = caught;
25
+ }
26
+ expect(error).toBeInstanceOf(HarnessEnvError);
27
+ const message = error.message;
28
+ expect(message).toContain('ZAG_MODEL_BASE_URL');
29
+ expect(message).toContain('ZAG_MODEL_IDS');
30
+ expect(message).toContain('ZAG_DEFAULT_WORKSPACE');
31
+ expect(message).not.toContain('ZAG_MODEL_API_KEY');
32
+ expect(message).not.toContain('zag_sk_super_secret');
33
+ });
34
+ it('trims values', () => {
35
+ const env = readHarnessEnv({
36
+ ...VALID_ENV,
37
+ ZAG_MODEL_BASE_URL: ' http://admin-api:8002/v1 ',
38
+ });
39
+ expect(env.modelBaseUrl).toBe('http://admin-api:8002/v1');
40
+ });
41
+ it('rejects a missing default workspace', () => {
42
+ expect(() => readHarnessEnv({ ...VALID_ENV, ZAG_DEFAULT_WORKSPACE: '' })).toThrowError(/ZAG_DEFAULT_WORKSPACE/);
43
+ });
44
+ });
45
+ describe('parseModelIds (T-AG11)', () => {
46
+ it('dedupes and drops empty/whitespace entries while preserving order', () => {
47
+ expect(parseModelIds('["b"," a ","b",""," ","c","a"]')).toEqual(['b', 'a', 'c']);
48
+ });
49
+ it('accepts an empty array', () => {
50
+ expect(parseModelIds('[]')).toEqual([]);
51
+ });
52
+ it('rejects invalid JSON without echoing the raw value', () => {
53
+ let error;
54
+ try {
55
+ parseModelIds('not-json');
56
+ }
57
+ catch (caught) {
58
+ error = caught;
59
+ }
60
+ expect(error).toBeInstanceOf(HarnessEnvError);
61
+ expect(error.message).toContain('ZAG_MODEL_IDS');
62
+ expect(error.message).not.toContain('not-json');
63
+ });
64
+ it('rejects non-array and non-string elements', () => {
65
+ expect(() => parseModelIds('{"a":1}')).toThrowError(/JSON array of strings/);
66
+ expect(() => parseModelIds('["a",1]')).toThrowError(/non-string element/);
67
+ expect(() => parseModelIds('null')).toThrowError(/JSON array of strings/);
68
+ });
69
+ });
70
+ //# sourceMappingURL=env.test.js.map