@sagentlab/navarch-runtime 0.1.49 → 0.1.50
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 +10 -0
- package/dist/cli.cjs +20 -5
- package/dist/session.cjs +18 -23
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -837,3 +837,13 @@ Each invocation rebuilds from Git blobs at the requested commit, avoiding stale
|
|
|
837
837
|
persistent indexes. Bounds are 2,000 files, 10 MB total source, 500 KB per file,
|
|
838
838
|
100 returned nodes and 300 edges. A later persistent index can optimize large
|
|
839
839
|
repositories without changing the query format.
|
|
840
|
+
|
|
841
|
+
### Pinning a connection model
|
|
842
|
+
|
|
843
|
+
`connect --agent codex --model gpt-6-astra` saves the model alongside the local
|
|
844
|
+
machine identity. `start` and `supervise` reuse that model, including after worker
|
|
845
|
+
restarts. Their optional `--model` flag overrides the saved choice. The pin wins
|
|
846
|
+
over the project's session model for the selected adapter only; switching agent
|
|
847
|
+
types does not reuse another adapter's pin. Reconnect without `--model` to return
|
|
848
|
+
to project-controlled model selection. Older identities without a model keep
|
|
849
|
+
using the control-plane execution policy.
|
package/dist/cli.cjs
CHANGED
|
@@ -76,6 +76,14 @@ function agentFromFlag(flags) {
|
|
|
76
76
|
}
|
|
77
77
|
return value;
|
|
78
78
|
}
|
|
79
|
+
/** Saved pins only apply to the adapter they were selected for. */
|
|
80
|
+
function modelFromFlags(flags, agentType, identity) {
|
|
81
|
+
const model = flags.model ?? (identity?.agent_type === agentType ? identity.model : undefined);
|
|
82
|
+
if (model !== undefined && (!model.trim() || model === "true" || /\s/.test(model))) {
|
|
83
|
+
throw new Error("--model requires a non-empty model reference without whitespace.");
|
|
84
|
+
}
|
|
85
|
+
return model;
|
|
86
|
+
}
|
|
79
87
|
function parseArgs(argv) {
|
|
80
88
|
const [command, ...rest] = argv;
|
|
81
89
|
const flags = {};
|
|
@@ -118,6 +126,7 @@ async function registerCommand(flags) {
|
|
|
118
126
|
.filter(Boolean);
|
|
119
127
|
const ownerZone = flags["owner-zone"] ?? config.ownerZone;
|
|
120
128
|
const agentType = agentFromFlag(flags) ?? config.agentType;
|
|
129
|
+
modelFromFlags(flags, agentType); // Validate before consuming an enrollment token.
|
|
121
130
|
const client = new api_cjs_1.NavarchApiClient({ baseUrl: apiBase });
|
|
122
131
|
const result = await client.registerMachine({
|
|
123
132
|
enrollment_token: enrollmentToken,
|
|
@@ -132,6 +141,7 @@ async function registerCommand(flags) {
|
|
|
132
141
|
name,
|
|
133
142
|
api_base: apiBase,
|
|
134
143
|
agent_type: agentType,
|
|
144
|
+
model: modelFromFlags(flags, agentType),
|
|
135
145
|
});
|
|
136
146
|
// Printed exactly once. Never logged or echoed again after this point.
|
|
137
147
|
console.log("Machine registered.");
|
|
@@ -166,6 +176,7 @@ async function connectCommand(flags) {
|
|
|
166
176
|
.map((s) => s.trim())
|
|
167
177
|
.filter(Boolean);
|
|
168
178
|
const agentType = agentFromFlag(flags) ?? config.agentType;
|
|
179
|
+
modelFromFlags(flags, agentType); // Validate before consuming an enrollment token.
|
|
169
180
|
const client = new api_cjs_1.NavarchApiClient({ baseUrl: apiBase });
|
|
170
181
|
const result = await client.connectMachine({
|
|
171
182
|
enrollment_token: enrollmentToken,
|
|
@@ -180,6 +191,7 @@ async function connectCommand(flags) {
|
|
|
180
191
|
name,
|
|
181
192
|
api_base: apiBase,
|
|
182
193
|
agent_type: agentType,
|
|
194
|
+
model: modelFromFlags(flags, agentType),
|
|
183
195
|
});
|
|
184
196
|
// Printed exactly once. Never logged or echoed again after this point.
|
|
185
197
|
console.log("Machine connected.");
|
|
@@ -195,7 +207,7 @@ async function startCommand(flags) {
|
|
|
195
207
|
// time, and finally the backwards-compatible Claude Code default.
|
|
196
208
|
const agentType = agentFromFlag(flags) ??
|
|
197
209
|
(process.env.NAVARCH_AGENT ? baseConfig.agentType : identity.agent_type ?? baseConfig.agentType);
|
|
198
|
-
const config = { ...baseConfig, agentType };
|
|
210
|
+
const config = { ...baseConfig, agentType, model: modelFromFlags(flags, agentType, identity) };
|
|
199
211
|
const api = new api_cjs_1.NavarchApiClient({ baseUrl: identity.api_base, token: identity.token });
|
|
200
212
|
const capacity = new capacity_cjs_1.CapacityTracker(config.maxSessions);
|
|
201
213
|
const activeSessionIds = new Set();
|
|
@@ -277,6 +289,9 @@ async function superviseCommand(flags) {
|
|
|
277
289
|
const agentType = agentFromFlag(flags) ??
|
|
278
290
|
(process.env.NAVARCH_AGENT ? config.agentType : identity.agent_type ?? config.agentType);
|
|
279
291
|
const workerArgs = ["--agent", agentType];
|
|
292
|
+
const model = modelFromFlags(flags, agentType, identity);
|
|
293
|
+
if (model)
|
|
294
|
+
workerArgs.push("--model", model);
|
|
280
295
|
// Pin the identity for this supervisor's lifetime. Without this snapshot, a
|
|
281
296
|
// replacement worker rereads machine.json after an automatic update and can
|
|
282
297
|
// silently become a different machine if another terminal reused the same
|
|
@@ -332,11 +347,11 @@ function helpText() {
|
|
|
332
347
|
|
|
333
348
|
Usage:
|
|
334
349
|
navarch-runtime register --token <enrollment-token> --name <machine-name> \\
|
|
335
|
-
[--config-dir <path>] [--agent claude-code|codex|gemini|opencode|acp] [--capabilities a,b] [--max-sessions N] [--owner-zone z] [--api-base url]
|
|
350
|
+
[--config-dir <path>] [--agent claude-code|codex|gemini|opencode|acp] [--model <model>] [--capabilities a,b] [--max-sessions N] [--owner-zone z] [--api-base url]
|
|
336
351
|
navarch-runtime connect --token <enrollment-token> --name <machine-name> \\
|
|
337
|
-
[--config-dir <path>] [--agent claude-code|codex|gemini|opencode|acp] [--project <project-id>] [--capabilities a,b] [--max-sessions N] [--api-base url]
|
|
338
|
-
navarch-runtime start [--config-dir <path>] [--agent claude-code|codex|gemini|opencode|acp]
|
|
339
|
-
navarch-runtime supervise [--config-dir <path>] [--agent claude-code|codex|gemini|opencode|acp]
|
|
352
|
+
[--config-dir <path>] [--agent claude-code|codex|gemini|opencode|acp] [--model <model>] [--project <project-id>] [--capabilities a,b] [--max-sessions N] [--api-base url]
|
|
353
|
+
navarch-runtime start [--config-dir <path>] [--agent claude-code|codex|gemini|opencode|acp] [--model <model>]
|
|
354
|
+
navarch-runtime supervise [--config-dir <path>] [--agent claude-code|codex|gemini|opencode|acp] [--model <model>]
|
|
340
355
|
navarch-runtime doctor [--config-dir <path>]
|
|
341
356
|
navarch-runtime code-graph --query <symbol-or-file> [--mode search|callers|callees|impact] [--commit HEAD] [--depth 1..5] [--repo <path>]
|
|
342
357
|
|
package/dist/session.cjs
CHANGED
|
@@ -38,6 +38,21 @@ const COMPLETION_REMEDIATION_RETRIES = 2;
|
|
|
38
38
|
*/
|
|
39
39
|
const DELIVERY_CORRECTION_RETRIES = 1;
|
|
40
40
|
const log = (0, logger_cjs_1.createLogger)("session");
|
|
41
|
+
function resolveSessionExecution(config, claimed) {
|
|
42
|
+
const runtime = claimed.runtime ?? config.agentType;
|
|
43
|
+
const execution = claimed.context_bundle.execution ?? {
|
|
44
|
+
profile: claimed.task.execution_profile ?? "standard",
|
|
45
|
+
model: runtime === "codex" ? "gpt-6-astra"
|
|
46
|
+
: runtime === "gemini" ? "auto"
|
|
47
|
+
: runtime === "opencode" || runtime === "acp" ? "default"
|
|
48
|
+
: "claude-opus-5",
|
|
49
|
+
reasoning_effort: "medium",
|
|
50
|
+
};
|
|
51
|
+
return {
|
|
52
|
+
...execution,
|
|
53
|
+
...(runtime === config.agentType && config.model ? { model: config.model } : {}),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
41
56
|
/**
|
|
42
57
|
* Runs one claimed task end to end (implementation-plan.md WP-07):
|
|
43
58
|
* 1. write the prompt file
|
|
@@ -70,19 +85,9 @@ async function runSession(deps, claimed, sessionId) {
|
|
|
70
85
|
// explicit pre-start signal. Otherwise it waits for expiry and bypasses
|
|
71
86
|
// the repeat/backoff policy entirely.
|
|
72
87
|
const { api, config } = deps;
|
|
73
|
-
const { lease_id: leaseId, task
|
|
88
|
+
const { lease_id: leaseId, task } = claimed;
|
|
74
89
|
const runtime = claimed.runtime ?? config.agentType;
|
|
75
|
-
const execution =
|
|
76
|
-
profile: task.execution_profile ?? "standard",
|
|
77
|
-
model: runtime === "codex"
|
|
78
|
-
? "gpt-6-astra"
|
|
79
|
-
: runtime === "gemini"
|
|
80
|
-
? "auto"
|
|
81
|
-
: runtime === "opencode" || runtime === "acp"
|
|
82
|
-
? "default"
|
|
83
|
-
: "claude-opus-5",
|
|
84
|
-
reasoning_effort: "medium",
|
|
85
|
-
};
|
|
90
|
+
const execution = resolveSessionExecution(config, claimed);
|
|
86
91
|
const crashDetail = describeCompletionError(err).slice(0, 1800);
|
|
87
92
|
const failureSummary = `Session crashed: ${crashDetail}`;
|
|
88
93
|
log.error(`session ${leaseId} threw before adapter start: ${crashDetail}`);
|
|
@@ -110,17 +115,7 @@ async function runClaimedSession(deps, claimed, sessionId, lifecycle) {
|
|
|
110
115
|
const { api, config } = deps;
|
|
111
116
|
const { lease_id: leaseId, task, context_bundle: bundle } = claimed;
|
|
112
117
|
const runtime = claimed.runtime ?? config.agentType;
|
|
113
|
-
const execution =
|
|
114
|
-
profile: task.execution_profile ?? "standard",
|
|
115
|
-
model: runtime === "codex"
|
|
116
|
-
? "gpt-6-astra"
|
|
117
|
-
: runtime === "gemini"
|
|
118
|
-
? "auto"
|
|
119
|
-
: runtime === "opencode" || runtime === "acp"
|
|
120
|
-
? "default"
|
|
121
|
-
: "claude-opus-5",
|
|
122
|
-
reasoning_effort: "medium",
|
|
123
|
-
};
|
|
118
|
+
const execution = resolveSessionExecution(config, claimed);
|
|
124
119
|
// Isolation posture reported on every completion so `sessions` records what
|
|
125
120
|
// a run actually executed under (#660). Derived from config alone, so the
|
|
126
121
|
// pre-start failure paths below can stamp it too. Host mode records
|
package/package.json
CHANGED