@sagentlab/navarch-runtime 0.1.26 → 0.1.28

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 CHANGED
@@ -420,8 +420,10 @@ overrides (`codex exec --model ... -c model_reasoning_effort=...`,
420
420
  `claude -p --model ... --effort ...`, `gemini --model ...`, or `opencode run
421
421
  --model ... --variant ...`) and records the effective model, profile, and
422
422
  effort on completion. Gemini currently uses its `auto` model default and does
423
- not expose a reasoning-effort flag. OpenCode accepts `default` to preserve the
424
- authenticated account's selection, or any `provider/model` reference.
423
+ not expose a reasoning-effort flag. OpenCode accepts any `provider/model`
424
+ reference (the platform default is `opencode/x-preview-f-free`, Ox Alpha Free
425
+ (Unlimited) on OpenCode Zen), or `default` to preserve the authenticated
426
+ account's selection.
425
427
  Machine-wide extra arguments still configure other CLI behavior; dispatched
426
428
  model policy wins.
427
429
 
package/dist/session.cjs CHANGED
@@ -46,6 +46,55 @@ const log = (0, logger_cjs_1.createLogger)("session");
46
46
  * isolation instead; see runtime/README.md.
47
47
  */
48
48
  async function runSession(deps, claimed, sessionId) {
49
+ const lifecycle = { enteredMainSessionTry: false };
50
+ try {
51
+ return await runClaimedSession(deps, claimed, sessionId, lifecycle);
52
+ }
53
+ catch (err) {
54
+ if (lifecycle.enteredMainSessionTry)
55
+ throw err;
56
+ // Initialization before the main worktree/adapter try (prompt creation,
57
+ // broker access, MCP/guard setup) must still release the lease with the
58
+ // explicit pre-start signal. Otherwise it waits for expiry and bypasses
59
+ // the repeat/backoff policy entirely.
60
+ const { api, config } = deps;
61
+ const { lease_id: leaseId, task, context_bundle: bundle } = claimed;
62
+ const runtime = claimed.runtime ?? config.agentType;
63
+ const execution = bundle.execution ?? {
64
+ profile: task.execution_profile ?? "standard",
65
+ model: runtime === "codex"
66
+ ? "gpt-5.6-sol"
67
+ : runtime === "gemini"
68
+ ? "auto"
69
+ : runtime === "opencode"
70
+ ? "default"
71
+ : "best",
72
+ reasoning_effort: "medium",
73
+ };
74
+ const crashDetail = describeCompletionError(err).slice(0, 1800);
75
+ const failureSummary = `Session crashed: ${crashDetail}`;
76
+ log.error(`session ${leaseId} threw before adapter start: ${crashDetail}`);
77
+ await api
78
+ .completeLease(leaseId, {
79
+ status: "failed",
80
+ report: verificationFailureReport(task.task_type, failureSummary),
81
+ failure_summary: failureSummary,
82
+ failed_before_start: true,
83
+ evidence_urls: [],
84
+ cost: { tokens_in: 0, tokens_out: 0, cost_usd: 0 },
85
+ exit_status: "crashed",
86
+ agent_type: runtime,
87
+ model: execution.model,
88
+ execution_profile: execution.profile,
89
+ reasoning_effort: execution.reasoning_effort,
90
+ })
91
+ .catch((completeErr) => log.warn(`complete() after initialization crash also failed: ${String(completeErr)}`));
92
+ await node_fs_1.promises
93
+ .rm(node_path_1.default.join(config.workspaceRoot, "sessions", sessionId), { recursive: true, force: true })
94
+ .catch(() => undefined);
95
+ }
96
+ }
97
+ async function runClaimedSession(deps, claimed, sessionId, lifecycle) {
49
98
  const { api, config } = deps;
50
99
  const { lease_id: leaseId, task, context_bundle: bundle } = claimed;
51
100
  const runtime = claimed.runtime ?? config.agentType;
@@ -111,6 +160,7 @@ async function runSession(deps, claimed, sessionId) {
111
160
  status: "failed",
112
161
  report: verificationFailureReport(task.task_type, failureSummary),
113
162
  failure_summary: failureSummary,
163
+ failed_before_start: true,
114
164
  evidence_urls: [],
115
165
  cost: { tokens_in: 0, tokens_out: 0, cost_usd: 0 },
116
166
  exit_status: "crashed",
@@ -175,16 +225,15 @@ async function runSession(deps, claimed, sessionId) {
175
225
  heartbeatInFlight = request;
176
226
  return request;
177
227
  };
178
- const heartbeatTimer = setInterval(() => void pollLease(), config.leaseHeartbeatIntervalMs);
179
228
  const dockerAvailable = config.sandboxMode === "docker" && (await (0, sandbox_cjs_1.isDockerAvailable)());
180
229
  if (config.sandboxMode === "docker" && !dockerAvailable) {
181
- clearInterval(heartbeatTimer);
182
230
  log.warn("Docker requested but not available on this machine — failing the task instead of crashing.");
183
231
  await api
184
232
  .completeLease(leaseId, {
185
233
  status: "failed",
186
234
  report: verificationFailureReport(task.task_type, "Docker sandbox unavailable on this machine."),
187
235
  failure_summary: "Docker sandbox unavailable on this machine.",
236
+ failed_before_start: true,
188
237
  evidence_urls: [],
189
238
  cost: { tokens_in: 0, tokens_out: 0, cost_usd: 0 },
190
239
  exit_status: "crashed",
@@ -277,6 +326,9 @@ async function runSession(deps, claimed, sessionId) {
277
326
  // Kept outside the try so the crash path can report the telemetry this
278
327
  // session actually produced instead of zeroing it.
279
328
  let lastCompletion = null;
329
+ let adapterStarted = false;
330
+ const heartbeatTimer = setInterval(() => void pollLease(), config.leaseHeartbeatIntervalMs);
331
+ lifecycle.enteredMainSessionTry = true;
280
332
  try {
281
333
  await gitWorktree.prepare();
282
334
  if (sandbox) {
@@ -307,6 +359,7 @@ async function runSession(deps, claimed, sessionId) {
307
359
  : promptText);
308
360
  nextPrompt = null;
309
361
  await node_fs_1.promises.writeFile(node_path_1.default.join(workDir, "prompt.md"), runPrompt, "utf8");
362
+ adapterStarted = true;
310
363
  const turnResult = await adapter.run({
311
364
  prompt: runPrompt,
312
365
  mcpConfigPath,
@@ -498,6 +551,7 @@ async function runSession(deps, claimed, sessionId) {
498
551
  ? `${lastCompletion.report}\n\n---\n\n${failureSummary}`
499
552
  : failureSummary),
500
553
  failure_summary: failureSummary,
554
+ failed_before_start: !adapterStarted,
501
555
  evidence_urls: lastCompletion?.evidence_urls ?? [],
502
556
  cost: lastCompletion?.cost ?? { tokens_in: 0, tokens_out: 0, cost_usd: 0 },
503
557
  ...(lastCompletion?.transcript_url
@@ -571,6 +625,10 @@ const REMEDIABLE_REJECTION_CODES = new Set([
571
625
  // the file usually already exists in the worktree, so the remediation turn
572
626
  // only has to call register_artifact and PUT the upload.
573
627
  "artifact_required",
628
+ // A registered render whose duration misses the brief's target_duration:
629
+ // the source assets are still in the worktree, so a remediation turn can
630
+ // re-cut to length, re-register the artifact, and retry on the same lease.
631
+ "duration_mismatch",
574
632
  "pr_not_ready",
575
633
  "review_attestation_required",
576
634
  "review_attestation_invalid",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sagentlab/navarch-runtime",
3
- "version": "0.1.26",
3
+ "version": "0.1.28",
4
4
  "description": "Navarch machine-side session manager: claims delivery tasks and runs them through Claude Code, Codex, Gemini, or OpenCode.",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",