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.
- package/README.md +19 -1
- package/dist/agents/agents/package-agent.d.ts +22 -0
- package/dist/agents/agents/package-agent.d.ts.map +1 -1
- package/dist/agents/agents/package-agent.js +92 -4
- package/dist/agents/agents/package-agent.js.map +1 -1
- package/dist/agents/release-preflight.d.ts +42 -5
- package/dist/agents/release-preflight.d.ts.map +1 -1
- package/dist/agents/release-preflight.js +82 -5
- package/dist/agents/release-preflight.js.map +1 -1
- package/dist/cli/chat.d.ts.map +1 -1
- package/dist/cli/chat.js +99 -9
- package/dist/cli/chat.js.map +1 -1
- package/dist/cli/cli-program.d.ts.map +1 -1
- package/dist/cli/cli-program.js +6 -0
- package/dist/cli/cli-program.js.map +1 -1
- package/dist/cli/code-map.d.ts +51 -0
- package/dist/cli/code-map.d.ts.map +1 -1
- package/dist/cli/code-map.js +174 -2
- package/dist/cli/code-map.js.map +1 -1
- package/dist/cli/credentials.d.ts.map +1 -1
- package/dist/cli/credentials.js +4 -1
- package/dist/cli/credentials.js.map +1 -1
- package/dist/cli/execute.js +5 -5
- package/dist/cli/execute.js.map +1 -1
- package/dist/cli/loop-executor.d.ts.map +1 -1
- package/dist/cli/loop-executor.js +76 -13
- package/dist/cli/loop-executor.js.map +1 -1
- package/dist/cli/motion.d.ts +53 -0
- package/dist/cli/motion.d.ts.map +1 -0
- package/dist/cli/motion.js +516 -0
- package/dist/cli/motion.js.map +1 -0
- package/dist/config/process-env.d.ts.map +1 -1
- package/dist/config/process-env.js +2 -2
- package/dist/config/process-env.js.map +1 -1
- package/dist/editing/types.d.ts +23 -1
- package/dist/editing/types.d.ts.map +1 -1
- package/dist/editing/types.js +51 -7
- package/dist/editing/types.js.map +1 -1
- package/dist/inference/route-resolver.d.ts +39 -0
- package/dist/inference/route-resolver.d.ts.map +1 -1
- package/dist/inference/route-resolver.js +51 -2
- package/dist/inference/route-resolver.js.map +1 -1
- package/dist/inference/thinking-replay.d.ts +86 -0
- package/dist/inference/thinking-replay.d.ts.map +1 -0
- package/dist/inference/thinking-replay.js +110 -0
- package/dist/inference/thinking-replay.js.map +1 -0
- package/dist/inference/tools.d.ts +9 -0
- package/dist/inference/tools.d.ts.map +1 -1
- package/dist/inference/tools.js +12 -1
- package/dist/inference/tools.js.map +1 -1
- package/dist/learning/assessment-protocol.d.ts +120 -0
- package/dist/learning/assessment-protocol.d.ts.map +1 -0
- package/dist/learning/assessment-protocol.js +236 -0
- package/dist/learning/assessment-protocol.js.map +1 -0
- package/dist/learning/assessment-turn-context.d.ts +54 -0
- package/dist/learning/assessment-turn-context.d.ts.map +1 -0
- package/dist/learning/assessment-turn-context.js +71 -0
- package/dist/learning/assessment-turn-context.js.map +1 -0
- package/dist/learning/exhaustion-report.d.ts +24 -1
- package/dist/learning/exhaustion-report.d.ts.map +1 -1
- package/dist/learning/exhaustion-report.js +18 -6
- package/dist/learning/exhaustion-report.js.map +1 -1
- package/dist/learning/machine-facts.d.ts +7 -0
- package/dist/learning/machine-facts.d.ts.map +1 -1
- package/dist/learning/machine-facts.js +37 -2
- package/dist/learning/machine-facts.js.map +1 -1
- package/dist/learning/perf-probe.d.ts +140 -0
- package/dist/learning/perf-probe.d.ts.map +1 -0
- package/dist/learning/perf-probe.js +316 -0
- package/dist/learning/perf-probe.js.map +1 -0
- package/dist/learning/self-check-discovery.d.ts +117 -0
- package/dist/learning/self-check-discovery.d.ts.map +1 -0
- package/dist/learning/self-check-discovery.js +334 -0
- package/dist/learning/self-check-discovery.js.map +1 -0
- package/dist/skills/bundled-skills-phase3.d.ts.map +1 -1
- package/dist/skills/bundled-skills-phase3.js +3 -3
- package/dist/skills/bundled-skills-phase3.js.map +1 -1
- package/dist/skills/sandbox-executor.d.ts.map +1 -1
- package/dist/skills/sandbox-executor.js +115 -34
- package/dist/skills/sandbox-executor.js.map +1 -1
- package/dist/tools/child-agent-runtime.js +19 -1
- package/dist/tools/child-agent-runtime.js.map +1 -1
- package/dist/tools/credentials-tool.d.ts.map +1 -1
- package/dist/tools/credentials-tool.js +4 -1
- package/dist/tools/credentials-tool.js.map +1 -1
- package/dist/tools/loop-project-context.d.ts +7 -0
- package/dist/tools/loop-project-context.d.ts.map +1 -1
- package/dist/tools/loop-project-context.js +44 -0
- package/dist/tools/loop-project-context.js.map +1 -1
- package/dist/tools/modality/motion-tool.d.ts +28 -1
- package/dist/tools/modality/motion-tool.d.ts.map +1 -1
- package/dist/tools/modality/motion-tool.js +261 -10
- package/dist/tools/modality/motion-tool.js.map +1 -1
- package/dist/tools/modality/motion.d.ts +403 -3
- package/dist/tools/modality/motion.d.ts.map +1 -1
- package/dist/tools/modality/motion.js +1096 -41
- package/dist/tools/modality/motion.js.map +1 -1
- package/dist/tools/pipeline-tool.d.ts.map +1 -1
- package/dist/tools/pipeline-tool.js +19 -1
- package/dist/tools/pipeline-tool.js.map +1 -1
- package/dist/tools/plan-store.d.ts +90 -6
- package/dist/tools/plan-store.d.ts.map +1 -1
- package/dist/tools/plan-store.js +140 -13
- package/dist/tools/plan-store.js.map +1 -1
- package/dist/tools/publish-tool.d.ts.map +1 -1
- package/dist/tools/publish-tool.js +9 -0
- package/dist/tools/publish-tool.js.map +1 -1
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +59 -7
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/tool-loop.d.ts +17 -0
- package/dist/tools/tool-loop.d.ts.map +1 -1
- package/dist/tools/tool-loop.js +4 -1
- package/dist/tools/tool-loop.js.map +1 -1
- package/dist/web-dashboard/chat-console.d.ts.map +1 -1
- package/dist/web-dashboard/chat-console.js +11 -1
- package/dist/web-dashboard/chat-console.js.map +1 -1
- package/dist/web-dashboard/motion-data.d.ts +62 -0
- package/dist/web-dashboard/motion-data.d.ts.map +1 -0
- package/dist/web-dashboard/motion-data.js +91 -0
- package/dist/web-dashboard/motion-data.js.map +1 -0
- package/dist/web-dashboard/project-context.js +6 -0
- package/dist/web-dashboard/project-context.js.map +1 -1
- package/dist/web-dashboard/server.d.ts.map +1 -1
- package/dist/web-dashboard/server.js +83 -33
- package/dist/web-dashboard/server.js.map +1 -1
- package/dist/web-dashboard/src/types.d.ts +31 -0
- package/dist/web-dashboard/src/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/web-dashboard/public/assets/{index-CzRU84ET.css → index-CXdBvA0N.css} +1 -1
- package/src/web-dashboard/public/assets/{index-V0rIqVbg.js → index-DfjkO16t.js} +81 -81
- package/src/web-dashboard/public/assets/index-DfjkO16t.js.map +1 -0
- package/src/web-dashboard/public/index.html +2 -2
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|