@harness-nexus/cli 0.1.0-alpha.1 → 0.1.0-alpha.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/dist/daemon/acp/adapters.d.ts.map +1 -1
- package/dist/daemon/acp/adapters.js +9 -3
- package/dist/daemon/acp/adapters.js.map +1 -1
- package/dist/daemon/acp/agent-connection.d.ts +30 -1
- package/dist/daemon/acp/agent-connection.d.ts.map +1 -1
- package/dist/daemon/acp/agent-connection.js +59 -6
- package/dist/daemon/acp/agent-connection.js.map +1 -1
- package/dist/daemon/chat.d.ts +9 -1
- package/dist/daemon/chat.d.ts.map +1 -1
- package/dist/daemon/chat.js +642 -37
- package/dist/daemon/chat.js.map +1 -1
- package/dist/daemon/client.d.ts +10 -2
- package/dist/daemon/client.d.ts.map +1 -1
- package/dist/daemon/client.js +99 -23
- package/dist/daemon/client.js.map +1 -1
- package/dist/daemon/config-view.d.ts +42 -0
- package/dist/daemon/config-view.d.ts.map +1 -0
- package/dist/daemon/config-view.js +159 -0
- package/dist/daemon/config-view.js.map +1 -0
- package/dist/daemon/dsh-sessions.d.ts +161 -0
- package/dist/daemon/dsh-sessions.d.ts.map +1 -0
- package/dist/daemon/dsh-sessions.js +674 -0
- package/dist/daemon/dsh-sessions.js.map +1 -0
- package/dist/daemon/dsh-tap/index.mjs +99 -0
- package/dist/daemon/dsh-tap-listener.d.ts +62 -0
- package/dist/daemon/dsh-tap-listener.d.ts.map +1 -0
- package/dist/daemon/dsh-tap-listener.js +196 -0
- package/dist/daemon/dsh-tap-listener.js.map +1 -0
- package/dist/daemon/jobs.d.ts +8 -5
- package/dist/daemon/jobs.d.ts.map +1 -1
- package/dist/daemon/jobs.js +28 -8
- package/dist/daemon/jobs.js.map +1 -1
- package/dist/daemon/runtime-config.d.ts +34 -0
- package/dist/daemon/runtime-config.d.ts.map +1 -0
- package/dist/daemon/runtime-config.js +343 -0
- package/dist/daemon/runtime-config.js.map +1 -0
- package/dist/daemon/runtime.d.ts +49 -0
- package/dist/daemon/runtime.d.ts.map +1 -0
- package/dist/daemon/runtime.js +218 -0
- package/dist/daemon/runtime.js.map +1 -0
- package/dist/daemon/sessions.d.ts +21 -0
- package/dist/daemon/sessions.d.ts.map +1 -0
- package/dist/daemon/sessions.js +125 -0
- package/dist/daemon/sessions.js.map +1 -0
- package/dist/daemon/workspace.d.ts +3 -0
- package/dist/daemon/workspace.d.ts.map +1 -0
- package/dist/daemon/workspace.js +27 -0
- package/dist/daemon/workspace.js.map +1 -0
- package/dist/install/adapters/deepseek.d.ts +4 -0
- package/dist/install/adapters/deepseek.d.ts.map +1 -1
- package/dist/install/adapters/deepseek.js +4 -2
- package/dist/install/adapters/deepseek.js.map +1 -1
- package/dist/inventory/common.d.ts +2 -0
- package/dist/inventory/common.d.ts.map +1 -1
- package/dist/inventory/common.js.map +1 -1
- package/dist/inventory/runtime.d.ts +40 -0
- package/dist/inventory/runtime.d.ts.map +1 -0
- package/dist/inventory/runtime.js +114 -0
- package/dist/inventory/runtime.js.map +1 -0
- package/dist/inventory/scanners/claude-code.d.ts +2 -0
- package/dist/inventory/scanners/claude-code.d.ts.map +1 -1
- package/dist/inventory/scanners/claude-code.js +103 -39
- package/dist/inventory/scanners/claude-code.js.map +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { chmodSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { harnessJobPayloadSchema, harnessResultDataSchema, } from '@harness-nexus/shared';
|
|
5
|
+
import { HarnessNexusClient } from '@harness-nexus/sdk';
|
|
6
|
+
import { beginMarker, endMarker, DSH_PATCH_FILENAME } from '../install/adapters/deepseek.js';
|
|
7
|
+
import { mergeTomlSection } from '../install/adapters/codex.js';
|
|
8
|
+
import { dshNodeWarning } from './runtime.js';
|
|
9
|
+
/**
|
|
10
|
+
* Provider-config apply (Phase 9 W3) — the daemon half of
|
|
11
|
+
* docs/design/phase-9-harness-runtime.md §4.3.
|
|
12
|
+
*
|
|
13
|
+
* `apply-config` harness jobs fetch the resolved `{spec, secret}` bundle with
|
|
14
|
+
* the machine PAT (execution-time resolution: a requeued job after a spec or
|
|
15
|
+
* credential edit applies the CURRENT value) and write each harness's NATIVE
|
|
16
|
+
* slots. All writes are merge-preserving and idempotent (re-apply = upgrade);
|
|
17
|
+
* every touched file ends 0600. Ground truth per target:
|
|
18
|
+
*
|
|
19
|
+
* - claude-code: `~/.claude/settings.json` — `env.ANTHROPIC_BASE_URL` (only
|
|
20
|
+
* while the spec sets one; a later unset REMOVES ours), `env.ANTHROPIC_AUTH_TOKEN`
|
|
21
|
+
* (the key), top-level `model` (base URL alone doesn't switch the model).
|
|
22
|
+
* - codex: `~/.codex/config.toml` — root keys `model` + `model_provider`, and
|
|
23
|
+
* the `[model_providers.harness_nexus]` block with `requires_openai_auth =
|
|
24
|
+
* true` (the built-in provider's own shape — auth comes from auth.json, no
|
|
25
|
+
* env var). `~/.codex/auth.json` — apikey mode with the key as
|
|
26
|
+
* `OPENAI_API_KEY`. `wire_api` is NOT set: current codex removed `chat`, so
|
|
27
|
+
* every route speaks Responses — gateways must be Responses-compatible.
|
|
28
|
+
* - deepseek: the SETTINGS layer (`~/.dsh/settings.yaml`, namespace
|
|
29
|
+
* `llm-pi-ai` with the provider route + `agent-default-model` selecting
|
|
30
|
+
* it). NOT loader-entry inserts in `cordis.patch.yml` — the dsh
|
|
31
|
+
* composition already mounts both plugins, and a second insert
|
|
32
|
+
* double-registers them ("configurable provider … already declared" /
|
|
33
|
+
* "service agentDefaultModel has been registered") and crashes
|
|
34
|
+
* `--profile acp`. A legacy W3 patch region is retired by the same apply.
|
|
35
|
+
* The key goes to `~/.dsh/.env` under `HARNESS_NEXUS_API_KEY` — dsh's own
|
|
36
|
+
* user-env credential layer, read on EVERY launch (user shells included).
|
|
37
|
+
*/
|
|
38
|
+
/** dsh resolves this name through process env > ~/.dsh/.credentials.yaml > ./.env > ~/.dsh/.env. */
|
|
39
|
+
const DSH_API_KEY_ENV = 'HARNESS_NEXUS_API_KEY';
|
|
40
|
+
/** codex provider id — also the `model_provider` root key value. */
|
|
41
|
+
const CODEX_PROVIDER_ID = 'harness_nexus';
|
|
42
|
+
const PROVIDER_REGION = 'provider';
|
|
43
|
+
function readJson(file) {
|
|
44
|
+
let raw = '{}';
|
|
45
|
+
try {
|
|
46
|
+
raw = readFileSync(file, 'utf8');
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
if (e.code !== 'ENOENT') {
|
|
50
|
+
throw new Error(`cannot read ${file}: ${e instanceof Error ? e.message : String(e)}`);
|
|
51
|
+
}
|
|
52
|
+
return {}; // absent file — nothing to merge
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const parsed = JSON.parse(raw);
|
|
56
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
57
|
+
throw new Error('not a JSON object');
|
|
58
|
+
}
|
|
59
|
+
return parsed;
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
throw new Error(`${file} is not valid JSON (${e instanceof Error ? e.message : String(e)}) — fix or remove it and re-apply`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function writeSecretFile(file, content) {
|
|
66
|
+
mkdirSync(join(file, '..'), { recursive: true });
|
|
67
|
+
writeFileSync(file, content, 'utf8');
|
|
68
|
+
chmodSync(file, 0o600);
|
|
69
|
+
return file;
|
|
70
|
+
}
|
|
71
|
+
/** Display path (`~/.codex/config.toml`) for job result data — never leaks the home dir. */
|
|
72
|
+
const display = (homeDir, file) => `~${file.startsWith(homeDir) ? file.slice(homeDir.length) : file}`;
|
|
73
|
+
// ---- claude-code ----
|
|
74
|
+
function applyClaudeConfig(spec, secret, homeDir) {
|
|
75
|
+
const dir = join(homeDir, '.claude');
|
|
76
|
+
const file = join(dir, 'settings.json');
|
|
77
|
+
const settings = readJson(file);
|
|
78
|
+
const env = {
|
|
79
|
+
...(settings.env ?? {}),
|
|
80
|
+
ANTHROPIC_AUTH_TOKEN: secret,
|
|
81
|
+
};
|
|
82
|
+
if (spec.baseUrl !== undefined)
|
|
83
|
+
env.ANTHROPIC_BASE_URL = spec.baseUrl;
|
|
84
|
+
else
|
|
85
|
+
delete env.ANTHROPIC_BASE_URL; // the platform owns the route — unset means revert to default
|
|
86
|
+
writeSecretFile(file, `${JSON.stringify({ ...settings, env, model: spec.model }, null, 2)}\n`);
|
|
87
|
+
return [display(homeDir, file)];
|
|
88
|
+
}
|
|
89
|
+
// ---- codex ----
|
|
90
|
+
/**
|
|
91
|
+
* Set TOP-LEVEL `key = "value"` pairs in a TOML document, preserving every
|
|
92
|
+
* other byte. Only the region before the first `[section]` header is ours to
|
|
93
|
+
* edit (a `model` inside a section belongs to that section); missing keys are
|
|
94
|
+
* appended to that region. JSON string escaping is valid TOML basic-string
|
|
95
|
+
* escaping.
|
|
96
|
+
*/
|
|
97
|
+
export function mergeTomlRootKeys(existing, values) {
|
|
98
|
+
const headerRe = /^\s*\[/;
|
|
99
|
+
const lines = existing.split('\n');
|
|
100
|
+
const firstHeader = lines.findIndex((l) => headerRe.test(l));
|
|
101
|
+
const topEnd = firstHeader === -1 ? lines.length : firstHeader;
|
|
102
|
+
const top = lines.slice(0, topEnd);
|
|
103
|
+
const rest = lines.slice(topEnd);
|
|
104
|
+
const remaining = new Map(Object.entries(values));
|
|
105
|
+
const rewritten = [];
|
|
106
|
+
for (const line of top) {
|
|
107
|
+
const key = /^(\s*[A-Za-z0-9_-]+)\s*=/.exec(line)?.[1]?.trim();
|
|
108
|
+
const hit = key !== undefined ? remaining.get(key) : undefined;
|
|
109
|
+
if (key !== undefined && hit !== undefined) {
|
|
110
|
+
rewritten.push(`${key} = ${JSON.stringify(hit)}`);
|
|
111
|
+
remaining.delete(key);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
rewritten.push(line);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Append missing keys at the end of the top-level region (before trailing
|
|
118
|
+
// blank lines so a header below keeps its spacing).
|
|
119
|
+
let insertAt = rewritten.length;
|
|
120
|
+
while (insertAt > 0 && rewritten[insertAt - 1].trim() === '')
|
|
121
|
+
insertAt--;
|
|
122
|
+
rewritten.splice(insertAt, 0, ...[...remaining.entries()].map(([k, v]) => `${k} = ${JSON.stringify(v)}`));
|
|
123
|
+
const out = [...rewritten, ...rest].join('\n').replace(/\s+$/, '');
|
|
124
|
+
return `${out}${out.length > 0 ? '\n' : ''}`;
|
|
125
|
+
}
|
|
126
|
+
function applyCodexConfig(spec, secret, homeDir) {
|
|
127
|
+
const dir = join(homeDir, '.codex');
|
|
128
|
+
const cfgPath = join(dir, 'config.toml');
|
|
129
|
+
let cfg = '';
|
|
130
|
+
try {
|
|
131
|
+
cfg = readFileSync(cfgPath, 'utf8');
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
cfg = ''; // absent file — fresh document
|
|
135
|
+
}
|
|
136
|
+
const sectionBody = [
|
|
137
|
+
`name = ${JSON.stringify(spec.providerLabel)}`,
|
|
138
|
+
...(spec.baseUrl !== undefined ? [`base_url = ${JSON.stringify(spec.baseUrl)}`] : []),
|
|
139
|
+
'requires_openai_auth = true',
|
|
140
|
+
].join('\n');
|
|
141
|
+
cfg = mergeTomlSection(mergeTomlRootKeys(cfg, { model: spec.model, model_provider: CODEX_PROVIDER_ID }), `model_providers.${CODEX_PROVIDER_ID}`, sectionBody);
|
|
142
|
+
writeSecretFile(cfgPath, cfg);
|
|
143
|
+
const authPath = join(dir, 'auth.json');
|
|
144
|
+
const auth = readJson(authPath);
|
|
145
|
+
writeSecretFile(authPath, `${JSON.stringify({ ...auth, auth_mode: 'apikey', OPENAI_API_KEY: secret }, null, 2)}\n`);
|
|
146
|
+
return [display(homeDir, cfgPath), display(homeDir, authPath)];
|
|
147
|
+
}
|
|
148
|
+
// ---- deepseek ----
|
|
149
|
+
/** Replace (or append) one `KEY=VALUE` line in a dotenv document, preserving the rest. */
|
|
150
|
+
export function mergeEnvLine(existing, key, value) {
|
|
151
|
+
const re = new RegExp(`^${key}=.*$`, 'm');
|
|
152
|
+
const line = `${key}=${value}`;
|
|
153
|
+
const base = re.test(existing)
|
|
154
|
+
? existing.replace(re, line)
|
|
155
|
+
: existing.replace(/\s+$/, '') + (existing.trim().length > 0 ? '\n' : '') + line;
|
|
156
|
+
return `${base.replace(/\s+$/, '')}\n`;
|
|
157
|
+
}
|
|
158
|
+
const DSH_API_MAP = {
|
|
159
|
+
// pi-ai KnownApi values (verified against the installed catalog types).
|
|
160
|
+
'anthropic-messages': 'anthropic-messages',
|
|
161
|
+
openai: 'openai-completions',
|
|
162
|
+
};
|
|
163
|
+
/** Settings namespaces our managed region owns (verified against the plugins). */
|
|
164
|
+
const DSH_LLM_NS = 'llm-pi-ai';
|
|
165
|
+
const DSH_DEFAULT_MODEL_NS = 'agent-default-model';
|
|
166
|
+
const SETTINGS_BEGIN = '# BEGIN harness-nexus (managed) — rewritten by hnx; keep edits outside the markers';
|
|
167
|
+
const SETTINGS_END = '# END harness-nexus (managed)';
|
|
168
|
+
/**
|
|
169
|
+
* Strip a marked block (full-line comment markers) from a document. Returns
|
|
170
|
+
* the remainder with collapsed surrounding blank lines. A base that is JUST
|
|
171
|
+
* an empty placeholder (`[]` / `{}`) is treated as empty — appending entries
|
|
172
|
+
* after it would produce two YAML documents (a boot-time parse error).
|
|
173
|
+
*/
|
|
174
|
+
export function stripMarkedBlock(existing, begin, end) {
|
|
175
|
+
const b = existing.indexOf(begin);
|
|
176
|
+
let doc = existing;
|
|
177
|
+
if (b !== -1) {
|
|
178
|
+
const e = existing.indexOf(end, b);
|
|
179
|
+
if (e !== -1) {
|
|
180
|
+
const before = existing.slice(0, b);
|
|
181
|
+
const after = existing.slice(e + end.length).replace(/^\n+/, '');
|
|
182
|
+
doc = `${before.replace(/\s+$/, '')}${before.trim().length > 0 ? '\n\n' : ''}${after}`;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const trimmed = doc.trim();
|
|
186
|
+
return trimmed === '[]' || trimmed === '{}' ? '' : doc;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Manage the dsh provider route across its THREE native slots:
|
|
190
|
+
*
|
|
191
|
+
* 1. `~/.dsh/settings.yaml` (`dsh-settings-file`) — the `llm-pi-ai` namespace
|
|
192
|
+
* (the provider route; dormant until a section appears) and
|
|
193
|
+
* `agent-default-model` (the default selection). The general channel for
|
|
194
|
+
* already-mounted plugins; a hand-managed namespace section is refused
|
|
195
|
+
* (duplicate keys brick boot).
|
|
196
|
+
* 2. `~/.dsh/cordis.patch.yml` — an id-targeted CONFIG OVERRIDE of the `acp`
|
|
197
|
+
* entry: the dsh-acp-app composition pins `provider: deepseek-official`
|
|
198
|
+
* on the acp plugin itself, and a plugin's explicit config beats the
|
|
199
|
+
* settings default for its sessions — without this override CHAT keeps
|
|
200
|
+
* hitting the old route. (The W3 build INSERTED duplicate plugins here,
|
|
201
|
+
* which double-registered and crashed `--profile acp`; inserts are gone,
|
|
202
|
+
* and the same apply retires any legacy region.)
|
|
203
|
+
* 3. `~/.dsh/.env` — the key under `HARNESS_NEXUS_API_KEY`, dsh's user-env
|
|
204
|
+
* credential layer (read on every launch, user shells included).
|
|
205
|
+
*/
|
|
206
|
+
function applyDshConfig(spec, secret, homeDir) {
|
|
207
|
+
const dir = join(homeDir, '.dsh');
|
|
208
|
+
const files = [];
|
|
209
|
+
const patchPath = join(dir, DSH_PATCH_FILENAME);
|
|
210
|
+
// 1. The settings document.
|
|
211
|
+
const settingsPath = join(dir, 'settings.yaml');
|
|
212
|
+
let doc = '';
|
|
213
|
+
try {
|
|
214
|
+
doc = readFileSync(settingsPath, 'utf8');
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
doc = ''; // absent document — fresh store
|
|
218
|
+
}
|
|
219
|
+
const base = stripMarkedBlock(doc, SETTINGS_BEGIN, SETTINGS_END);
|
|
220
|
+
for (const ns of [DSH_LLM_NS, DSH_DEFAULT_MODEL_NS]) {
|
|
221
|
+
if (new RegExp(`^${ns}:`, 'm').test(base)) {
|
|
222
|
+
throw new Error(`~/.dsh/settings.yaml already has a hand-managed "${ns}" section — hnx will not overwrite it; ` +
|
|
223
|
+
'remove or rename that section and re-apply');
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
const yq = JSON.stringify; // JSON quoting is valid YAML 1.2 double-quoting
|
|
227
|
+
const region = [
|
|
228
|
+
SETTINGS_BEGIN,
|
|
229
|
+
`${DSH_LLM_NS}:`,
|
|
230
|
+
` providers:`,
|
|
231
|
+
` harness-nexus:`,
|
|
232
|
+
` displayName: ${yq(spec.providerLabel)}`,
|
|
233
|
+
` api: ${DSH_API_MAP[spec.api]}`,
|
|
234
|
+
` baseURL: ${yq(spec.baseUrl)}`,
|
|
235
|
+
` apiKeyEnv: ${DSH_API_KEY_ENV}`,
|
|
236
|
+
` models:`,
|
|
237
|
+
` - id: ${yq(spec.model)}`,
|
|
238
|
+
`${DSH_DEFAULT_MODEL_NS}:`,
|
|
239
|
+
` provider: harness-nexus`,
|
|
240
|
+
` model: ${yq(spec.model)}`,
|
|
241
|
+
SETTINGS_END,
|
|
242
|
+
].join('\n');
|
|
243
|
+
const nextDoc = `${base.replace(/\s+$/, '')}${base.trim().length > 0 ? '\n\n' : ''}${region}\n`;
|
|
244
|
+
writeSecretFile(settingsPath, nextDoc);
|
|
245
|
+
files.push(display(homeDir, settingsPath));
|
|
246
|
+
// 3. The ACP app pins its OWN provider in the dsh-acp-app composition
|
|
247
|
+
// (`- id: acp … config: {provider: deepseek-official…}`), and a plugin's
|
|
248
|
+
// explicit config beats the settings-layer default for its sessions —
|
|
249
|
+
// chat would keep hitting the old route. The patch layer's id-targeted
|
|
250
|
+
// CONFIG OVERRIDE (its documented purpose) reroutes it; an insert would
|
|
251
|
+
// double-register, an override does not.
|
|
252
|
+
let patchDoc = '';
|
|
253
|
+
try {
|
|
254
|
+
patchDoc = readFileSync(patchPath, 'utf8');
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
patchDoc = '[]\n'; // absent file — a fresh empty entry list
|
|
258
|
+
}
|
|
259
|
+
const patchBase = stripMarkedBlock(patchDoc, beginMarker(PROVIDER_REGION), endMarker(PROVIDER_REGION));
|
|
260
|
+
if (/^- id: acp$/m.test(patchBase)) {
|
|
261
|
+
throw new Error('~/.dsh/cordis.patch.yml already overrides the "acp" entry by hand — hnx will not touch it; ' +
|
|
262
|
+
'remove that override and re-apply');
|
|
263
|
+
}
|
|
264
|
+
const patchRegion = [
|
|
265
|
+
`${beginMarker(PROVIDER_REGION)} — rewritten by hnx; keep edits outside the markers`,
|
|
266
|
+
`- id: acp`,
|
|
267
|
+
` config:`,
|
|
268
|
+
` provider: harness-nexus`,
|
|
269
|
+
` model: ${yq(spec.model)}`,
|
|
270
|
+
endMarker(PROVIDER_REGION),
|
|
271
|
+
].join('\n');
|
|
272
|
+
const patchNext = `${patchBase.replace(/\s+$/, '')}${patchBase.trim().length > 0 ? '\n\n' : ''}${patchRegion}\n`;
|
|
273
|
+
writeSecretFile(patchPath, patchNext);
|
|
274
|
+
files.push(display(homeDir, patchPath));
|
|
275
|
+
// 4. The key itself — dsh's user-env credential layer.
|
|
276
|
+
const envPath = join(dir, '.env');
|
|
277
|
+
let envDoc = '';
|
|
278
|
+
try {
|
|
279
|
+
envDoc = readFileSync(envPath, 'utf8');
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
envDoc = '';
|
|
283
|
+
}
|
|
284
|
+
writeSecretFile(envPath, mergeEnvLine(envDoc, DSH_API_KEY_ENV, secret));
|
|
285
|
+
files.push(display(homeDir, envPath));
|
|
286
|
+
return files;
|
|
287
|
+
}
|
|
288
|
+
/** The per-target native writer — pure file surgery, no I/O beyond the harness homes. */
|
|
289
|
+
export function applyRuntimeConfig(target, spec, secret, homeDir) {
|
|
290
|
+
switch (target) {
|
|
291
|
+
case 'claude-code':
|
|
292
|
+
return { files: applyClaudeConfig(spec, secret, homeDir) };
|
|
293
|
+
case 'codex':
|
|
294
|
+
return { files: applyCodexConfig(spec, secret, homeDir) };
|
|
295
|
+
case 'deepseek':
|
|
296
|
+
if (spec.baseUrl === undefined) {
|
|
297
|
+
// The route gate rejects this server-side; the daemon double-checks so
|
|
298
|
+
// a stale queued job fails honestly instead of writing a broken row.
|
|
299
|
+
throw new Error('deepseek provider routes require a baseUrl');
|
|
300
|
+
}
|
|
301
|
+
return { files: applyDshConfig(spec, secret, homeDir) };
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* The `apply-config` harness job executor: fetch the resolved bundle with the
|
|
306
|
+
* machine PAT (REST — the secret never rides the job), write the native slots,
|
|
307
|
+
* settle via `job:result`. No runtime re-probe (config files aren't in the
|
|
308
|
+
* snapshot); the redacted read-back viewer is W4.
|
|
309
|
+
*/
|
|
310
|
+
export async function runApplyConfigJob(socket, opts, job, homeDir = homedir()) {
|
|
311
|
+
const parsed = harnessJobPayloadSchema.safeParse(job.payload);
|
|
312
|
+
if (!parsed.success || parsed.data.action !== 'apply-config') {
|
|
313
|
+
socket.emit('job:result', { jobId: job.id, ok: false, error: 'harness payload invalid' });
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
const target = parsed.data.target;
|
|
317
|
+
const progress = (phase, message) => {
|
|
318
|
+
socket.emit('job:progress', { jobId: job.id, phase, ...(message ? { message } : {}) });
|
|
319
|
+
};
|
|
320
|
+
progress('resolve', `fetching provider config for ${target}`);
|
|
321
|
+
try {
|
|
322
|
+
const client = new HarnessNexusClient({ baseUrl: opts.server, token: opts.token });
|
|
323
|
+
const bundle = await client.getRuntimeConfigBundle(target);
|
|
324
|
+
progress('apply', `writing ${target} config`);
|
|
325
|
+
const { files } = applyRuntimeConfig(target, bundle.spec, bundle.secret, homeDir);
|
|
326
|
+
const nodeWarning = target === 'deepseek' ? dshNodeWarning() : null;
|
|
327
|
+
const data = harnessResultDataSchema.parse({
|
|
328
|
+
target,
|
|
329
|
+
action: 'apply-config',
|
|
330
|
+
files,
|
|
331
|
+
...(nodeWarning !== null ? { warning: nodeWarning } : {}),
|
|
332
|
+
});
|
|
333
|
+
socket.emit('job:result', { jobId: job.id, ok: true, data });
|
|
334
|
+
}
|
|
335
|
+
catch (e) {
|
|
336
|
+
socket.emit('job:result', {
|
|
337
|
+
jobId: job.id,
|
|
338
|
+
ok: false,
|
|
339
|
+
error: e instanceof Error ? e.message : String(e),
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
//# sourceMappingURL=runtime-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-config.js","sourceRoot":"","sources":["../../src/daemon/runtime-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Socket } from 'socket.io-client';
|
|
2
|
+
import { type JobView } from '@harness-nexus/shared';
|
|
3
|
+
/**
|
|
4
|
+
* Harness-runtime job executor (Phase 9 W2). docs/design/phase-9-harness-runtime.md §4.2.
|
|
5
|
+
*
|
|
6
|
+
* `install` / `upgrade` / `pin` map to the per-target command table — npm is
|
|
7
|
+
* the universal channel (every daemon host runs Node ≥20); the ONE native
|
|
8
|
+
* path is a claude-code upgrade on an already-native install (`claude
|
|
9
|
+
* update`, which knows how to self-replace). Managed claude-code machines get
|
|
10
|
+
* `DISABLE_AUTOUPDATER` merged into settings.json so our jobs are the only
|
|
11
|
+
* version movers. A successful job re-probes the runtime and auto-reports the
|
|
12
|
+
* target's inventory (one scan feeds the Agent card + detected-instance sync).
|
|
13
|
+
*
|
|
14
|
+
* Tests drive this with a fake `npm` shim on PATH (design §10) — no network.
|
|
15
|
+
*/
|
|
16
|
+
/** npm package per runtime target (single source for install/pin/upgrade). */
|
|
17
|
+
export declare const HARNESS_PACKAGES: Record<string, string>;
|
|
18
|
+
/**
|
|
19
|
+
* The resolved installer invocation for a harness payload. `apply-config` is
|
|
20
|
+
* not an installer — the daemon routes it to the config executor before this
|
|
21
|
+
* table; reaching it here (misrouted dispatch) refuses honestly.
|
|
22
|
+
*/
|
|
23
|
+
export declare function harnessCommand(payload: {
|
|
24
|
+
action: 'install' | 'upgrade' | 'pin' | 'apply-config';
|
|
25
|
+
target: string;
|
|
26
|
+
version?: string | undefined;
|
|
27
|
+
}, currentInstallMethod: 'npm' | 'native' | 'brew' | 'unknown' | undefined): {
|
|
28
|
+
command: string;
|
|
29
|
+
args: string[];
|
|
30
|
+
} | {
|
|
31
|
+
error: string;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Merge `env.DISABLE_AUTOUPDATER = '1'` into ~/.claude/settings.json —
|
|
35
|
+
* merge-preserving (unknown/user keys survive). Never throws into the job
|
|
36
|
+
* path: an unreadable settings file is reported, not fatal.
|
|
37
|
+
*/
|
|
38
|
+
export declare function disableClaudeAutoUpdater(homeDir: string): string | null;
|
|
39
|
+
/** dsh ≥0.1.2's plugin tree needs Node APIs absent from 20.x (zlib zstd, Promise.withResolvers). */
|
|
40
|
+
export declare function dshNodeWarning(): string | null;
|
|
41
|
+
export interface HarnessJobOptions {
|
|
42
|
+
/** Per-command timeout (default 10 min — npm on a slow link is slow). */
|
|
43
|
+
timeoutMs?: number;
|
|
44
|
+
/** Spawn env override (tests inject a fake npm via PATH). Default: process.env. */
|
|
45
|
+
env?: NodeJS.ProcessEnv;
|
|
46
|
+
homeDir?: string;
|
|
47
|
+
}
|
|
48
|
+
export declare function runHarnessJob(socket: Socket, job: JobView, opts?: HarnessJobOptions): Promise<void>;
|
|
49
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/daemon/runtime.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAGL,KAAK,OAAO,EAEb,MAAM,uBAAuB,CAAC;AAK/B;;;;;;;;;;;;GAYG;AAEH,8EAA8E;AAC9E,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAInD,CAAC;AAcF;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE;IACP,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,KAAK,GAAG,cAAc,CAAC;IACvD,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B,EACD,oBAAoB,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GACtE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAyBzD;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsBvE;AAED,oGAAoG;AACpG,wBAAgB,cAAc,IAAI,MAAM,GAAG,IAAI,CAO9C;AAED,MAAM,WAAW,iBAAiB;IAChC,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAID,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,OAAO,EACZ,IAAI,GAAE,iBAAsB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAsHf"}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { chmodSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { harnessJobPayloadSchema, harnessResultDataSchema, } from '@harness-nexus/shared';
|
|
6
|
+
import { probeRuntime } from '../inventory/runtime.js';
|
|
7
|
+
import { scanTarget, scannerFor } from '../inventory/scan.js';
|
|
8
|
+
import { emptySnapshot } from './client.js';
|
|
9
|
+
/**
|
|
10
|
+
* Harness-runtime job executor (Phase 9 W2). docs/design/phase-9-harness-runtime.md §4.2.
|
|
11
|
+
*
|
|
12
|
+
* `install` / `upgrade` / `pin` map to the per-target command table — npm is
|
|
13
|
+
* the universal channel (every daemon host runs Node ≥20); the ONE native
|
|
14
|
+
* path is a claude-code upgrade on an already-native install (`claude
|
|
15
|
+
* update`, which knows how to self-replace). Managed claude-code machines get
|
|
16
|
+
* `DISABLE_AUTOUPDATER` merged into settings.json so our jobs are the only
|
|
17
|
+
* version movers. A successful job re-probes the runtime and auto-reports the
|
|
18
|
+
* target's inventory (one scan feeds the Agent card + detected-instance sync).
|
|
19
|
+
*
|
|
20
|
+
* Tests drive this with a fake `npm` shim on PATH (design §10) — no network.
|
|
21
|
+
*/
|
|
22
|
+
/** npm package per runtime target (single source for install/pin/upgrade). */
|
|
23
|
+
export const HARNESS_PACKAGES = {
|
|
24
|
+
'claude-code': '@anthropic-ai/claude-code',
|
|
25
|
+
codex: '@openai/codex',
|
|
26
|
+
deepseek: '@deepseek-ai/dsh',
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* The dist-tag a version-less install/upgrade tracks. claude-code follows
|
|
30
|
+
* `stable` (a ~week-old channel with regressions skipped — the managed-install
|
|
31
|
+
* default per the Phase 9 research; `latest`/`next` exist but move faster than
|
|
32
|
+
* a managed fleet should).
|
|
33
|
+
*/
|
|
34
|
+
const CHANNEL_TAG = {
|
|
35
|
+
'claude-code': 'stable',
|
|
36
|
+
codex: 'latest',
|
|
37
|
+
deepseek: 'latest',
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* The resolved installer invocation for a harness payload. `apply-config` is
|
|
41
|
+
* not an installer — the daemon routes it to the config executor before this
|
|
42
|
+
* table; reaching it here (misrouted dispatch) refuses honestly.
|
|
43
|
+
*/
|
|
44
|
+
export function harnessCommand(payload, currentInstallMethod) {
|
|
45
|
+
const pkg = HARNESS_PACKAGES[payload.target];
|
|
46
|
+
if (!pkg)
|
|
47
|
+
return { error: `no harness package for target '${payload.target}'` };
|
|
48
|
+
if (payload.action === 'apply-config') {
|
|
49
|
+
return { error: 'apply-config is executed by the config writer, not the installer table' };
|
|
50
|
+
}
|
|
51
|
+
// The one non-npm path: upgrading a NATIVE claude-code install — the native
|
|
52
|
+
// launcher self-updates; npm -g over it would shadow, not upgrade.
|
|
53
|
+
if (payload.target === 'claude-code' &&
|
|
54
|
+
payload.action === 'upgrade' &&
|
|
55
|
+
currentInstallMethod === 'native' &&
|
|
56
|
+
payload.version === undefined) {
|
|
57
|
+
return { command: 'claude', args: ['update'] };
|
|
58
|
+
}
|
|
59
|
+
if (payload.target === 'claude-code' && currentInstallMethod === 'native' && payload.version) {
|
|
60
|
+
return {
|
|
61
|
+
error: 'claude-code is natively installed and cannot be pinned remotely — run the native installer on the machine, or reinstall it via npm first',
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
const tag = CHANNEL_TAG[payload.target] ?? 'latest';
|
|
65
|
+
const spec = payload.version !== undefined ? `${pkg}@${payload.version}` : `${pkg}@${tag}`;
|
|
66
|
+
return { command: 'npm', args: ['install', '-g', spec] };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Merge `env.DISABLE_AUTOUPDATER = '1'` into ~/.claude/settings.json —
|
|
70
|
+
* merge-preserving (unknown/user keys survive). Never throws into the job
|
|
71
|
+
* path: an unreadable settings file is reported, not fatal.
|
|
72
|
+
*/
|
|
73
|
+
export function disableClaudeAutoUpdater(homeDir) {
|
|
74
|
+
const dir = join(homeDir, '.claude');
|
|
75
|
+
const file = join(dir, 'settings.json');
|
|
76
|
+
let settings = {};
|
|
77
|
+
try {
|
|
78
|
+
settings = JSON.parse(readFileSync(file, 'utf8'));
|
|
79
|
+
if (typeof settings !== 'object' || settings === null || Array.isArray(settings)) {
|
|
80
|
+
return `settings.json is not a JSON object — left untouched`;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
if (e.code !== 'ENOENT') {
|
|
85
|
+
return `settings.json unreadable (${e instanceof Error ? e.message : String(e)}) — left untouched`;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const env = {
|
|
89
|
+
...(settings.env ?? {}),
|
|
90
|
+
DISABLE_AUTOUPDATER: '1',
|
|
91
|
+
};
|
|
92
|
+
mkdirSync(dir, { recursive: true });
|
|
93
|
+
writeFileSync(file, `${JSON.stringify({ ...settings, env }, null, 2)}\n`, 'utf8');
|
|
94
|
+
chmodSync(file, 0o600);
|
|
95
|
+
return null; // ok
|
|
96
|
+
}
|
|
97
|
+
/** dsh ≥0.1.2's plugin tree needs Node APIs absent from 20.x (zlib zstd, Promise.withResolvers). */
|
|
98
|
+
export function dshNodeWarning() {
|
|
99
|
+
const [major, minor] = process.versions.node.split('.').map(Number);
|
|
100
|
+
if (major === undefined)
|
|
101
|
+
return null;
|
|
102
|
+
const ok = major > 22 || (major === 22 && (minor ?? 0) >= 15);
|
|
103
|
+
return ok
|
|
104
|
+
? null
|
|
105
|
+
: `deepseek's ACP profile needs Node >=22.15 (this daemon runs ${process.versions.node}) — chat sessions will fail until Node is upgraded`;
|
|
106
|
+
}
|
|
107
|
+
const TAIL_BYTES = 4096;
|
|
108
|
+
export async function runHarnessJob(socket, job, opts = {}) {
|
|
109
|
+
const parsed = harnessJobPayloadSchema.safeParse(job.payload);
|
|
110
|
+
if (!parsed.success) {
|
|
111
|
+
socket.emit('job:result', { jobId: job.id, ok: false, error: 'harness payload invalid' });
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const payload = parsed.data;
|
|
115
|
+
// The daemon's real home (tests inject a fixture). Defaulting here (not
|
|
116
|
+
// gating on `homeDir !== undefined`) is a W3 fix: W2 daemons skipped the
|
|
117
|
+
// autoupdater write in production because the executor was called without
|
|
118
|
+
// opts — `os.homedir()` honors the daemon's HOME, which is what the smoke
|
|
119
|
+
// rig always relied on anyway.
|
|
120
|
+
const homeDir = opts.homeDir ?? homedir();
|
|
121
|
+
const probeOpts = {};
|
|
122
|
+
if (opts.env?.PATH !== undefined)
|
|
123
|
+
probeOpts.pathEnv = opts.env.PATH;
|
|
124
|
+
if (homeDir !== undefined)
|
|
125
|
+
probeOpts.homeDir = homeDir;
|
|
126
|
+
const progress = (phase, message) => {
|
|
127
|
+
socket.emit('job:progress', { jobId: job.id, phase, ...(message ? { message } : {}) });
|
|
128
|
+
};
|
|
129
|
+
const result = (ok, extra) => {
|
|
130
|
+
socket.emit('job:result', { jobId: job.id, ok, ...extra });
|
|
131
|
+
};
|
|
132
|
+
progress('resolve', `${payload.action} ${payload.target}${payload.version ? `@${payload.version}` : ''}`);
|
|
133
|
+
// Current install method decides the claude-code upgrade path.
|
|
134
|
+
const current = payload.action === 'upgrade' ? await probeRuntime(payload.target, probeOpts) : null;
|
|
135
|
+
const cmd = harnessCommand(payload, current?.installed ? current.installMethod : undefined);
|
|
136
|
+
if ('error' in cmd) {
|
|
137
|
+
result(false, { error: cmd.error });
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
progress('install', `${cmd.command} ${cmd.args.join(' ')}`.slice(0, 512));
|
|
141
|
+
const spawnOutcome = await new Promise((resolve) => {
|
|
142
|
+
let tail = '';
|
|
143
|
+
let lastEmit = 0;
|
|
144
|
+
const append = (chunk) => {
|
|
145
|
+
tail = (tail + chunk.toString()).slice(-TAIL_BYTES);
|
|
146
|
+
const now = Date.now();
|
|
147
|
+
if (now - lastEmit >= 1200) {
|
|
148
|
+
lastEmit = now;
|
|
149
|
+
const line = tail
|
|
150
|
+
.split('\n')
|
|
151
|
+
.filter((l) => l.trim().length > 0)
|
|
152
|
+
.pop() ?? '';
|
|
153
|
+
if (line.length > 0)
|
|
154
|
+
progress('install', line.slice(0, 512));
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
let child;
|
|
158
|
+
try {
|
|
159
|
+
// Inherit the daemon's environment: proxied machines must pass
|
|
160
|
+
// HTTP(S)_PROXY / npm_config_registry through to the installer.
|
|
161
|
+
child = spawn(cmd.command, cmd.args, { env: opts.env ?? process.env });
|
|
162
|
+
}
|
|
163
|
+
catch (e) {
|
|
164
|
+
resolve({ ok: false, tail: e instanceof Error ? e.message : String(e) });
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const timer = setTimeout(() => {
|
|
168
|
+
child.kill('SIGTERM');
|
|
169
|
+
setTimeout(() => child.kill('SIGKILL'), 2000).unref?.();
|
|
170
|
+
resolve({ ok: false, tail: `${tail}\n timed out after ${opts.timeoutMs ?? 600000}ms` });
|
|
171
|
+
}, opts.timeoutMs ?? 600000);
|
|
172
|
+
child.stdout?.on('data', append);
|
|
173
|
+
child.stderr?.on('data', append);
|
|
174
|
+
child.on('error', (e) => {
|
|
175
|
+
clearTimeout(timer);
|
|
176
|
+
resolve({ ok: false, tail: `${tail}\n${e.message}` });
|
|
177
|
+
});
|
|
178
|
+
child.on('close', (code) => {
|
|
179
|
+
clearTimeout(timer);
|
|
180
|
+
resolve({ ok: code === 0, tail });
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
if (!spawnOutcome.ok) {
|
|
184
|
+
const trimmed = spawnOutcome.tail.trim().split('\n').slice(-8).join('\n').slice(0, 900);
|
|
185
|
+
result(false, { error: `${cmd.command} ${cmd.args.join(' ')} failed:\n${trimmed}` });
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
// Managed claude-code: our jobs become the only version mover.
|
|
189
|
+
let warning = null;
|
|
190
|
+
if (payload.target === 'claude-code') {
|
|
191
|
+
warning = disableClaudeAutoUpdater(homeDir);
|
|
192
|
+
}
|
|
193
|
+
if (warning === null && payload.target === 'deepseek') {
|
|
194
|
+
warning = dshNodeWarning();
|
|
195
|
+
}
|
|
196
|
+
// Re-probe so the job RESULT reports what actually landed, then auto-report
|
|
197
|
+
// the target's inventory (runtime arm feeds the Agent card + detected sync).
|
|
198
|
+
progress('verify', 'probing runtime');
|
|
199
|
+
const runtime = await probeRuntime(payload.target, probeOpts);
|
|
200
|
+
const snapshot = scannerFor(payload.target)
|
|
201
|
+
? scanTarget(payload.target, homeDir)
|
|
202
|
+
: emptySnapshot(payload.target);
|
|
203
|
+
socket.emit('inventory:report', { runtimes: [runtime], snapshot });
|
|
204
|
+
const data = harnessResultDataSchema.parse({
|
|
205
|
+
target: payload.target,
|
|
206
|
+
action: payload.action,
|
|
207
|
+
...(runtime.installed
|
|
208
|
+
? {
|
|
209
|
+
version: runtime.version,
|
|
210
|
+
binPath: runtime.binPath,
|
|
211
|
+
installMethod: runtime.installMethod,
|
|
212
|
+
}
|
|
213
|
+
: {}),
|
|
214
|
+
...(warning !== null ? { warning } : {}),
|
|
215
|
+
});
|
|
216
|
+
result(true, { data });
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/daemon/runtime.ts"],"names":[],"mappings":"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"}
|