agent-nuvira 3.5.7 → 3.5.10

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 (134) hide show
  1. package/README.md +19 -1
  2. package/dist/agents/agents/package-agent.d.ts +22 -0
  3. package/dist/agents/agents/package-agent.d.ts.map +1 -1
  4. package/dist/agents/agents/package-agent.js +92 -4
  5. package/dist/agents/agents/package-agent.js.map +1 -1
  6. package/dist/agents/release-preflight.d.ts +42 -5
  7. package/dist/agents/release-preflight.d.ts.map +1 -1
  8. package/dist/agents/release-preflight.js +82 -5
  9. package/dist/agents/release-preflight.js.map +1 -1
  10. package/dist/cli/chat.d.ts.map +1 -1
  11. package/dist/cli/chat.js +99 -9
  12. package/dist/cli/chat.js.map +1 -1
  13. package/dist/cli/cli-program.d.ts.map +1 -1
  14. package/dist/cli/cli-program.js +6 -0
  15. package/dist/cli/cli-program.js.map +1 -1
  16. package/dist/cli/code-map.d.ts +51 -0
  17. package/dist/cli/code-map.d.ts.map +1 -1
  18. package/dist/cli/code-map.js +174 -2
  19. package/dist/cli/code-map.js.map +1 -1
  20. package/dist/cli/credentials.d.ts.map +1 -1
  21. package/dist/cli/credentials.js +4 -1
  22. package/dist/cli/credentials.js.map +1 -1
  23. package/dist/cli/execute.js +5 -5
  24. package/dist/cli/execute.js.map +1 -1
  25. package/dist/cli/loop-executor.d.ts.map +1 -1
  26. package/dist/cli/loop-executor.js +76 -13
  27. package/dist/cli/loop-executor.js.map +1 -1
  28. package/dist/cli/motion.d.ts +53 -0
  29. package/dist/cli/motion.d.ts.map +1 -0
  30. package/dist/cli/motion.js +516 -0
  31. package/dist/cli/motion.js.map +1 -0
  32. package/dist/config/process-env.d.ts.map +1 -1
  33. package/dist/config/process-env.js +2 -2
  34. package/dist/config/process-env.js.map +1 -1
  35. package/dist/editing/types.d.ts +23 -1
  36. package/dist/editing/types.d.ts.map +1 -1
  37. package/dist/editing/types.js +51 -7
  38. package/dist/editing/types.js.map +1 -1
  39. package/dist/inference/route-resolver.d.ts +39 -0
  40. package/dist/inference/route-resolver.d.ts.map +1 -1
  41. package/dist/inference/route-resolver.js +51 -2
  42. package/dist/inference/route-resolver.js.map +1 -1
  43. package/dist/inference/thinking-replay.d.ts +86 -0
  44. package/dist/inference/thinking-replay.d.ts.map +1 -0
  45. package/dist/inference/thinking-replay.js +110 -0
  46. package/dist/inference/thinking-replay.js.map +1 -0
  47. package/dist/inference/tools.d.ts +9 -0
  48. package/dist/inference/tools.d.ts.map +1 -1
  49. package/dist/inference/tools.js +12 -1
  50. package/dist/inference/tools.js.map +1 -1
  51. package/dist/learning/assessment-protocol.d.ts +120 -0
  52. package/dist/learning/assessment-protocol.d.ts.map +1 -0
  53. package/dist/learning/assessment-protocol.js +236 -0
  54. package/dist/learning/assessment-protocol.js.map +1 -0
  55. package/dist/learning/assessment-turn-context.d.ts +54 -0
  56. package/dist/learning/assessment-turn-context.d.ts.map +1 -0
  57. package/dist/learning/assessment-turn-context.js +71 -0
  58. package/dist/learning/assessment-turn-context.js.map +1 -0
  59. package/dist/learning/exhaustion-report.d.ts +24 -1
  60. package/dist/learning/exhaustion-report.d.ts.map +1 -1
  61. package/dist/learning/exhaustion-report.js +18 -6
  62. package/dist/learning/exhaustion-report.js.map +1 -1
  63. package/dist/learning/machine-facts.d.ts +7 -0
  64. package/dist/learning/machine-facts.d.ts.map +1 -1
  65. package/dist/learning/machine-facts.js +37 -2
  66. package/dist/learning/machine-facts.js.map +1 -1
  67. package/dist/learning/perf-probe.d.ts +140 -0
  68. package/dist/learning/perf-probe.d.ts.map +1 -0
  69. package/dist/learning/perf-probe.js +316 -0
  70. package/dist/learning/perf-probe.js.map +1 -0
  71. package/dist/learning/self-check-discovery.d.ts +117 -0
  72. package/dist/learning/self-check-discovery.d.ts.map +1 -0
  73. package/dist/learning/self-check-discovery.js +334 -0
  74. package/dist/learning/self-check-discovery.js.map +1 -0
  75. package/dist/skills/bundled-skills-phase3.d.ts.map +1 -1
  76. package/dist/skills/bundled-skills-phase3.js +3 -3
  77. package/dist/skills/bundled-skills-phase3.js.map +1 -1
  78. package/dist/skills/sandbox-executor.d.ts.map +1 -1
  79. package/dist/skills/sandbox-executor.js +115 -34
  80. package/dist/skills/sandbox-executor.js.map +1 -1
  81. package/dist/tools/child-agent-runtime.js +19 -1
  82. package/dist/tools/child-agent-runtime.js.map +1 -1
  83. package/dist/tools/credentials-tool.d.ts.map +1 -1
  84. package/dist/tools/credentials-tool.js +4 -1
  85. package/dist/tools/credentials-tool.js.map +1 -1
  86. package/dist/tools/loop-project-context.d.ts +7 -0
  87. package/dist/tools/loop-project-context.d.ts.map +1 -1
  88. package/dist/tools/loop-project-context.js +44 -0
  89. package/dist/tools/loop-project-context.js.map +1 -1
  90. package/dist/tools/modality/motion-tool.d.ts +28 -1
  91. package/dist/tools/modality/motion-tool.d.ts.map +1 -1
  92. package/dist/tools/modality/motion-tool.js +261 -10
  93. package/dist/tools/modality/motion-tool.js.map +1 -1
  94. package/dist/tools/modality/motion.d.ts +403 -3
  95. package/dist/tools/modality/motion.d.ts.map +1 -1
  96. package/dist/tools/modality/motion.js +1096 -41
  97. package/dist/tools/modality/motion.js.map +1 -1
  98. package/dist/tools/pipeline-tool.d.ts.map +1 -1
  99. package/dist/tools/pipeline-tool.js +19 -1
  100. package/dist/tools/pipeline-tool.js.map +1 -1
  101. package/dist/tools/plan-store.d.ts +90 -6
  102. package/dist/tools/plan-store.d.ts.map +1 -1
  103. package/dist/tools/plan-store.js +140 -13
  104. package/dist/tools/plan-store.js.map +1 -1
  105. package/dist/tools/publish-tool.d.ts.map +1 -1
  106. package/dist/tools/publish-tool.js +9 -0
  107. package/dist/tools/publish-tool.js.map +1 -1
  108. package/dist/tools/registry.d.ts.map +1 -1
  109. package/dist/tools/registry.js +59 -7
  110. package/dist/tools/registry.js.map +1 -1
  111. package/dist/tools/tool-loop.d.ts +17 -0
  112. package/dist/tools/tool-loop.d.ts.map +1 -1
  113. package/dist/tools/tool-loop.js +4 -1
  114. package/dist/tools/tool-loop.js.map +1 -1
  115. package/dist/web-dashboard/chat-console.d.ts.map +1 -1
  116. package/dist/web-dashboard/chat-console.js +11 -1
  117. package/dist/web-dashboard/chat-console.js.map +1 -1
  118. package/dist/web-dashboard/motion-data.d.ts +62 -0
  119. package/dist/web-dashboard/motion-data.d.ts.map +1 -0
  120. package/dist/web-dashboard/motion-data.js +91 -0
  121. package/dist/web-dashboard/motion-data.js.map +1 -0
  122. package/dist/web-dashboard/project-context.js +6 -0
  123. package/dist/web-dashboard/project-context.js.map +1 -1
  124. package/dist/web-dashboard/server.d.ts.map +1 -1
  125. package/dist/web-dashboard/server.js +83 -33
  126. package/dist/web-dashboard/server.js.map +1 -1
  127. package/dist/web-dashboard/src/types.d.ts +31 -0
  128. package/dist/web-dashboard/src/types.d.ts.map +1 -1
  129. package/package.json +1 -1
  130. package/src/web-dashboard/public/assets/{index-CzRU84ET.css → index-CXdBvA0N.css} +1 -1
  131. package/src/web-dashboard/public/assets/{index-V0rIqVbg.js → index-DfjkO16t.js} +81 -81
  132. package/src/web-dashboard/public/assets/index-DfjkO16t.js.map +1 -0
  133. package/src/web-dashboard/public/index.html +2 -2
  134. package/src/web-dashboard/public/assets/index-V0rIqVbg.js.map +0 -1
@@ -31,7 +31,7 @@ import { classifyEntries, } from '../learning/cost-classification.js';
31
31
  import { acceptanceSummary, collectLabelledTurns, serializeLabelledTurns, parseCorpusText, detectCorpusFormat, mergeImportedLabels, } from '../learning/acceptance-model.js';
32
32
  import { readDecisions, recallDecisions, reviseDecision } from '../learning/decision-log.js';
33
33
  import { degradedCallsFromTraces } from '../learning/reasoning-trace.js';
34
- import { withStrictModel } from '../inference/route-resolver.js';
34
+ import { strictPinPolicy, withStrictModel } from '../inference/route-resolver.js';
35
35
  import { readRecallHits } from '../context/session-recall.js';
36
36
  import { getRouterPromotion } from '../learning/router-promotion.js';
37
37
  import { AUTH_CLEAR_THRESHOLD } from '../learning/key-hygiene.js';
@@ -57,6 +57,7 @@ import { FRESH_DAYS, FRESHNESS_COPY, REACHABILITY_COPY, classifyFreshness, class
57
57
  import { VERIFY_BACKLOG_DEFAULT_PER_RUN, VERIFY_BACKLOG_MAX_PER_RUN, getVerifyBacklogState, startVerifyBacklogRun, } from '../learning/model-verify-job.js';
58
58
  import { setToolsetEnabled } from '../tools/toolsets.js';
59
59
  import { ArtifactStore } from '../tools/artifact-store.js';
60
+ import { motionRenderFile, motionRenders } from './motion-data.js';
60
61
  import { setSkillEnabled } from '../learning/hub-skill-catalog.js';
61
62
  // I11 — dashboard channel send-test: the same registry/adapters `nuvira gateway
62
63
  // send` uses, so a Channels-tab test message behaves identically to the CLI.
@@ -156,6 +157,43 @@ function artifactFileMime(file, recorded) {
156
157
  };
157
158
  return byExt[ext] ?? 'application/octet-stream';
158
159
  }
160
+ /**
161
+ * Stream a media file, with byte-range support.
162
+ *
163
+ * A `<video>` that cannot seek cannot be reviewed: the player asks for ranges
164
+ * the moment the user drags the scrubber. Shared by the artifact endpoint and
165
+ * the motion endpoint so a second media route cannot quietly lose that — the
166
+ * same reason the artifact route says it never takes a path from the query.
167
+ */
168
+ function streamMedia(req, res, filePath, type) {
169
+ const size = statSync(filePath).size;
170
+ const range = /^bytes=(\d*)-(\d*)$/.exec(req.headers.range ?? '');
171
+ if (range) {
172
+ const start = range[1] ? Number(range[1]) : 0;
173
+ const end = range[2] ? Math.min(Number(range[2]), size - 1) : size - 1;
174
+ if (start >= size || end < start) {
175
+ res.writeHead(416, { 'Content-Range': `bytes */${size}` });
176
+ res.end();
177
+ return;
178
+ }
179
+ res.writeHead(206, {
180
+ 'Content-Type': type,
181
+ 'Content-Length': String(end - start + 1),
182
+ 'Content-Range': `bytes ${start}-${end}/${size}`,
183
+ 'Accept-Ranges': 'bytes',
184
+ 'Cache-Control': 'no-store',
185
+ });
186
+ createReadStream(filePath, { start, end }).pipe(res);
187
+ return;
188
+ }
189
+ res.writeHead(200, {
190
+ 'Content-Type': type,
191
+ 'Content-Length': String(size),
192
+ 'Accept-Ranges': 'bytes',
193
+ 'Cache-Control': 'no-store',
194
+ });
195
+ createReadStream(filePath).pipe(res);
196
+ }
159
197
  function loadAlwaysWatchQuotaFlag() {
160
198
  try {
161
199
  const configPath = resolveBuffConfigPath();
@@ -3377,6 +3415,25 @@ function handleRequest(req, res) {
3377
3415
  })();
3378
3416
  return;
3379
3417
  }
3418
+ // ── Motion — the renders this workspace has made. Discoverability, not
3419
+ // rendering: the page plays back what a chat turn (or `nuvira motion render`)
3420
+ // produced, because an artifact nobody can find is an artifact nobody has.
3421
+ if (pathname === '/api/motion') {
3422
+ writeJson(res, 200, motionRenders());
3423
+ return;
3424
+ }
3425
+ // The bytes for ONE render. The id is resolved through OUR OWN manifest store
3426
+ // (`motionRenderFile`), never a path from the query string, so this endpoint
3427
+ // cannot be asked for an arbitrary file.
3428
+ if (pathname === '/api/motion-file') {
3429
+ const file = motionRenderFile(url.searchParams.get('id') ?? '');
3430
+ if (!file) {
3431
+ writeJson(res, 404, { ok: false, error: 'No such motion render.' });
3432
+ return;
3433
+ }
3434
+ streamMedia(req, res, file.path, file.mime);
3435
+ return;
3436
+ }
3380
3437
  // ── An artifact's BYTES — how the Artifacts tab shows a rendered video rather
3381
3438
  // than a filename. The path is looked up in OUR OWN artifact store by (session,
3382
3439
  // artifact id) and is never taken from the query string, so a caller cannot ask
@@ -3391,36 +3448,7 @@ function handleRequest(req, res) {
3391
3448
  writeJson(res, 404, { ok: false, error: 'No such artifact file.' });
3392
3449
  return;
3393
3450
  }
3394
- const size = statSync(artifact.path).size;
3395
- const type = artifactFileMime(artifact.path, artifact.mime);
3396
- // Range support, because a <video> that cannot seek cannot be reviewed: a
3397
- // player asks for byte ranges the moment the user drags the scrubber.
3398
- const range = /^bytes=(\d*)-(\d*)$/.exec(req.headers.range ?? '');
3399
- if (range) {
3400
- const start = range[1] ? Number(range[1]) : 0;
3401
- const end = range[2] ? Math.min(Number(range[2]), size - 1) : size - 1;
3402
- if (start >= size || end < start) {
3403
- res.writeHead(416, { 'Content-Range': `bytes */${size}` });
3404
- res.end();
3405
- return;
3406
- }
3407
- res.writeHead(206, {
3408
- 'Content-Type': type,
3409
- 'Content-Length': String(end - start + 1),
3410
- 'Content-Range': `bytes ${start}-${end}/${size}`,
3411
- 'Accept-Ranges': 'bytes',
3412
- 'Cache-Control': 'no-store',
3413
- });
3414
- createReadStream(artifact.path, { start, end }).pipe(res);
3415
- return;
3416
- }
3417
- res.writeHead(200, {
3418
- 'Content-Type': type,
3419
- 'Content-Length': String(size),
3420
- 'Accept-Ranges': 'bytes',
3421
- 'Cache-Control': 'no-store',
3422
- });
3423
- createReadStream(artifact.path).pipe(res);
3451
+ streamMedia(req, res, artifact.path, artifactFileMime(artifact.path, artifact.mime));
3424
3452
  return;
3425
3453
  }
3426
3454
  if (pathname === '/api/benchmarks') {
@@ -7654,7 +7682,24 @@ function handleRequest(req, res) {
7654
7682
  // only" switch). Scoped to the turn with AsyncLocalStorage rather than a
7655
7683
  // process env write, because two sessions can run concurrently and a
7656
7684
  // global mutation would leak one user's pin into the other's turn.
7657
- const strict = body?.strict === true;
7685
+ //
7686
+ // READ AS A TRI-STATE (2026-10-16) — same three cases, same reasoning, as
7687
+ // `worktree`/`resume` below. `true` holds the pin; `false` is this turn's
7688
+ // EXPLICIT permission to substitute; ABSENT defers to the pin's own policy,
7689
+ // where a request that NAMED a provider+model HOLDS (the pair `pinOf`
7690
+ // records) and an Auto turn has no pair to hold.
7691
+ //
7692
+ // Collapsing absent into `false` — the previous `body?.strict === true` —
7693
+ // was wrong on both sides. A pinned API request that never mentioned the
7694
+ // flag was substituted by default, i.e. a pin read as a preference, which
7695
+ // is the contract `strictPinPolicy` exists to end. And because the scope
7696
+ // set here OUTRANKS the environment inside `withStrictModel`, a dashboard
7697
+ // deployment running with `NUVIRA_STRICT_MODEL=1` was silently un-strict
7698
+ // for every chat turn that left the flag out — the operator's own switch,
7699
+ // quietly ignored.
7700
+ const strict = typeof body?.strict === 'boolean'
7701
+ ? body.strict
7702
+ : strictPinPolicy(typeof provider === 'string' && typeof model === 'string');
7658
7703
  // WS5 (#27) — per-turn isolation and resume, from the GUI.
7659
7704
  //
7660
7705
  // Read as a strict TRI-state, because the three cases are genuinely
@@ -7908,7 +7953,12 @@ function handleRequest(req, res) {
7908
7953
  `your pinned ${requested} is ${pinnedClass} class, and this turn ran on ${served} (${servedClass} class).`;
7909
7954
  }
7910
7955
  else if (substituted) {
7911
- routingNotice = `Auto routing took over: this turn ran on ${served} because your pinned ${requested} was not available. To work with ${requested} only, enable strict model mode.`;
7956
+ // Reachable now only when the turn EXPLICITLY allowed a substitute
7957
+ // (`strict: false`, the chat's lock switched off) or the deployment set
7958
+ // `NUVIRA_STRICT_MODEL=0`, because a named pair holds by default. So the
7959
+ // instruction names the two controls that actually release it, instead
7960
+ // of telling the user to enable something that is already the default.
7961
+ routingNotice = `Auto routing took over: this turn ran on ${served} because your pinned ${requested} was not available. To work with ${requested} only, hold the pin: turn the chat's lock back on, or set NUVIRA_STRICT_MODEL=1.`;
7912
7962
  }
7913
7963
  else if (result.generationFailed === true) {
7914
7964
  // The turn ran on the pair the user pinned and stopped there. Saying