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
package/dist/cli/chat.js
CHANGED
|
@@ -5,7 +5,7 @@ import { Command } from 'commander';
|
|
|
5
5
|
import inquirer from 'inquirer';
|
|
6
6
|
import { BaseCommand } from './commands.js';
|
|
7
7
|
import { resolveProvider } from './router.js';
|
|
8
|
-
import { resolveRoute, strictModelMode, strictPinRefusal } from '../inference/route-resolver.js';
|
|
8
|
+
import { resolveRoute, strictModelMode, strictPinPolicy, strictPinRefusal, withStrictModel } from '../inference/route-resolver.js';
|
|
9
9
|
import { showModelPicker } from './model-picker.js';
|
|
10
10
|
import { ContextParser } from '../context/parser.js';
|
|
11
11
|
import { getCache } from '../context/cache.js';
|
|
@@ -32,6 +32,7 @@ import { UnusableModelResponseError } from '../learning/response-usability.js';
|
|
|
32
32
|
import { resolveThreadBudgetChars } from '../learning/context-budget.js';
|
|
33
33
|
import { getAutoRouter, isAgentAutoRoute, isAutoModel, isAutoProvider, governanceVerdict, adminBudgetVerdict, isAgenticTask } from '../learning/auto-router.js';
|
|
34
34
|
import { continuationSoftwareText } from '../learning/continuation-intent.js';
|
|
35
|
+
import { buildAssessmentTurnContext } from '../learning/assessment-turn-context.js';
|
|
35
36
|
import { TaskModelContinuity, taskSignature } from '../learning/task-model-continuity.js';
|
|
36
37
|
import { describeFailureKind, renderExhaustionReport, } from '../learning/exhaustion-report.js';
|
|
37
38
|
import { estimateTokens } from '../learning/cost-tracker.js';
|
|
@@ -1305,13 +1306,29 @@ export class ChatCommand extends BaseCommand {
|
|
|
1305
1306
|
.option('--keep-worktree', 'Keep the isolated worktree after the turn instead of removing it')
|
|
1306
1307
|
.option('--resume [id]', 'Replay the recorded steps of this ask whose input is unchanged instead of paying for them again (defaults to the record for this goal + directory; also asked for by NUVIRA_RESUME=1)')
|
|
1307
1308
|
.addHelpText('after', '\nModel routing:\n' +
|
|
1308
|
-
' Pinning -p/--provider (and -m/--model)
|
|
1309
|
-
'
|
|
1310
|
-
'
|
|
1311
|
-
'
|
|
1312
|
-
'
|
|
1309
|
+
' Pinning -p/--provider (and -m/--model) HOLDS: the named model is the only one\n' +
|
|
1310
|
+
' that serves the turn, and a pin that cannot answer fails with a message\n' +
|
|
1311
|
+
' naming the pair instead of quietly substituting another model. To allow the\n' +
|
|
1312
|
+
' repair-and-announce behaviour instead (fall over to an available model and\n' +
|
|
1313
|
+
' report which one answered), set NUVIRA_STRICT_MODEL=0.\n')
|
|
1313
1314
|
.action(async (prompt, options) => {
|
|
1314
|
-
|
|
1315
|
+
const opts = options || {};
|
|
1316
|
+
// ── ASK 1 — A NAMED PAIR HOLDS FOR THE WHOLE TURN ──────────────────
|
|
1317
|
+
//
|
|
1318
|
+
// `--provider`/`--model` name a model; they are not a hint. The `auto`
|
|
1319
|
+
// sentinels are the opposite of a pin and are excluded. When a pair IS
|
|
1320
|
+
// named, the pin's policy (see `strictPinPolicy`) is scoped over the whole
|
|
1321
|
+
// turn — the one-shot answer, its picked followups and every REPL message —
|
|
1322
|
+
// so route resolution, the loop engine's candidate walk and chat's own
|
|
1323
|
+
// pinned-fallback path all read the same answer instead of each deciding
|
|
1324
|
+
// for itself whether substituting is acceptable. `NUVIRA_STRICT_MODEL=0`
|
|
1325
|
+
// is the explicit opt-out and keeps the old repair-and-announce behaviour.
|
|
1326
|
+
const namedPair = Boolean(opts.provider && !isAutoProvider(opts.provider)) || Boolean(opts.model && !isAutoModel(opts.model));
|
|
1327
|
+
if (namedPair && strictPinPolicy(true)) {
|
|
1328
|
+
await withStrictModel(true, () => this.execute(prompt, opts));
|
|
1329
|
+
return;
|
|
1330
|
+
}
|
|
1331
|
+
await this.execute(prompt, opts);
|
|
1315
1332
|
});
|
|
1316
1333
|
return command;
|
|
1317
1334
|
}
|
|
@@ -1845,10 +1862,46 @@ export class ChatCommand extends BaseCommand {
|
|
|
1845
1862
|
* about one directory.
|
|
1846
1863
|
*/
|
|
1847
1864
|
const turnScope = ctxOverrides?.projectPath || process.cwd();
|
|
1865
|
+
// ── ASSESSMENT TURN — one detector, three consumers ────────────────────
|
|
1866
|
+
//
|
|
1867
|
+
// The evidence protocol and everything it carries (the project's own
|
|
1868
|
+
// discovered checks, the performance probes) comes from the SHARED assembler,
|
|
1869
|
+
// which is also what `loop-executor.ts` and `pipeline-tool.ts` call — so
|
|
1870
|
+
// `nuvira execute` and a gateway-run audit get the same rules as this surface
|
|
1871
|
+
// instead of an unadorned ask. See `learning/assessment-turn-context.ts`.
|
|
1872
|
+
//
|
|
1873
|
+
// The symbol map in the ambient project context (which a findings turn repays
|
|
1874
|
+
// and a change turn does not) and the response-cache bypass below read the SAME
|
|
1875
|
+
// boolean, so they can never disagree about whether the turn is an assessment.
|
|
1876
|
+
// Computed here because the cache check is the first thing that needs it.
|
|
1877
|
+
//
|
|
1878
|
+
// Deterministic and NARROW: the assembler tests the goal BEFORE it touches the
|
|
1879
|
+
// filesystem, so a change request returns '' and does no discovery work — its
|
|
1880
|
+
// turn is byte-identical to one from a build without any of this.
|
|
1881
|
+
const assessmentContext = buildAssessmentTurnContext(message, turnScope);
|
|
1882
|
+
const assessmentBlock = assessmentContext.block;
|
|
1883
|
+
const assessmentTurn = assessmentContext.isAssessment;
|
|
1848
1884
|
// Cache check first (same as the legacy path).
|
|
1849
1885
|
const cache = getCache();
|
|
1850
1886
|
const cacheModel = this.cacheModelFor(session);
|
|
1851
|
-
|
|
1887
|
+
// ASSESSMENT TURNS DO NOT REPLAY A CACHED ANSWER.
|
|
1888
|
+
//
|
|
1889
|
+
// A cached answer is a statement about the tree AS IT WAS when the entry was
|
|
1890
|
+
// written, and an assessment is a statement about the tree NOW — so the key
|
|
1891
|
+
// (prompt + model + provider + workspace) is exactly the four things that stay
|
|
1892
|
+
// equal when the code has changed underneath. Observed on 2026-10-16: after a
|
|
1893
|
+
// patched build was installed, the same audit prompt in the same directory
|
|
1894
|
+
// returned `cache.hit {chars:5744}` — the PRE-patch report, identical down to a
|
|
1895
|
+
// mid-sentence truncation, replayed as if it were a fresh look at the tree.
|
|
1896
|
+
//
|
|
1897
|
+
// The cost is one real turn where a replay used to be instant, and it is only
|
|
1898
|
+
// paid by assessment turns: a change request, a question, a repeat of anything
|
|
1899
|
+
// else keeps its cache hit. Truth over speed, in the one place the two can
|
|
1900
|
+
// disagree about the same input.
|
|
1901
|
+
if (cacheEnabled && assessmentTurn) {
|
|
1902
|
+
debugLog?.event('cache.bypass', { reason: 'assessment turn — the tree may have changed', scope: turnScope });
|
|
1903
|
+
}
|
|
1904
|
+
if (cacheEnabled && !assessmentTurn) {
|
|
1852
1905
|
try {
|
|
1853
1906
|
// #30 — read the entry WITH its recorded activity, not just the text: a
|
|
1854
1907
|
// replay that dropped `toolCalls` rendered no tool cards on the dashboard
|
|
@@ -2078,7 +2131,7 @@ export class ChatCommand extends BaseCommand {
|
|
|
2078
2131
|
let ambientProjectContext;
|
|
2079
2132
|
if (!ctxOverrides?.projectContext) {
|
|
2080
2133
|
try {
|
|
2081
|
-
const built = await buildLoopProjectContext(turnCwd);
|
|
2134
|
+
const built = await buildLoopProjectContext(turnCwd, { symbolMap: assessmentTurn });
|
|
2082
2135
|
if (built)
|
|
2083
2136
|
ambientProjectContext = built;
|
|
2084
2137
|
}
|
|
@@ -2144,6 +2197,8 @@ export class ChatCommand extends BaseCommand {
|
|
|
2144
2197
|
// conversation stays contiguous, and it is a USER-TURN message rather than
|
|
2145
2198
|
// system text, so the system prompt stays byte-stable and cacheable.
|
|
2146
2199
|
...(knowledgeBlock ? [{ role: 'user', content: knowledgeBlock }] : []),
|
|
2200
|
+
// The assessment protocol for this ask, when the ask IS an assessment.
|
|
2201
|
+
...(assessmentBlock ? [{ role: 'user', content: assessmentBlock }] : []),
|
|
2147
2202
|
// P4 — the recalled project context (prior sessions + facts) rides in
|
|
2148
2203
|
// next, so the model starts from what this project was last doing.
|
|
2149
2204
|
...(ctxOverrides?.recallContext
|
|
@@ -2398,6 +2453,10 @@ export class ChatCommand extends BaseCommand {
|
|
|
2398
2453
|
// Machine facts are FACTS about the host, not a recommendation, so they
|
|
2399
2454
|
// drop LAST among the optional blocks (higher priority = kept longer).
|
|
2400
2455
|
{ name: 'machine-facts', chars: machineBlock.length, dropPriority: 15 },
|
|
2456
|
+
// The assessment protocol governs how THIS turn's findings may be
|
|
2457
|
+
// claimed, so it outranks every other optional block and is dropped only
|
|
2458
|
+
// after the machine facts.
|
|
2459
|
+
{ name: 'assessment-protocol', chars: assessmentBlock.length, dropPriority: 18 },
|
|
2401
2460
|
{ name: 'working-state', chars: workingStateBlock.length, dropPriority: 25 },
|
|
2402
2461
|
{ name: 'decisions', chars: ctxOverrides?.decisionContext?.length ?? 0, dropPriority: 28 },
|
|
2403
2462
|
{ name: 'recall', chars: ctxOverrides?.recallContext?.length ?? 0, dropPriority: 30 },
|
|
@@ -2421,6 +2480,16 @@ export class ChatCommand extends BaseCommand {
|
|
|
2421
2480
|
(trimmed.has('skill-hint') ? '' : skillHint),
|
|
2422
2481
|
};
|
|
2423
2482
|
}
|
|
2483
|
+
// Applied rather than merely reported (as the two system blocks above are):
|
|
2484
|
+
// a protocol the budget says to drop must not still be in the thread, or the
|
|
2485
|
+
// report and the wire disagree. Matched by exact content so no other
|
|
2486
|
+
// user-turn block is ever touched.
|
|
2487
|
+
if (trimmed.has('assessment-protocol') && assessmentBlock) {
|
|
2488
|
+
for (let i = thread.length - 1; i >= 1; i--) {
|
|
2489
|
+
if (thread[i].role === 'user' && thread[i].content === assessmentBlock)
|
|
2490
|
+
thread.splice(i, 1);
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2424
2493
|
if (report.level !== 'ok') {
|
|
2425
2494
|
recordTraceEvent(chatTraceId, {
|
|
2426
2495
|
kind: 'decision',
|
|
@@ -2671,6 +2740,9 @@ export class ChatCommand extends BaseCommand {
|
|
|
2671
2740
|
// and is now additionally gated on the model having the context for it.
|
|
2672
2741
|
toolExposure: harness.exposure,
|
|
2673
2742
|
maxParallelReads: harness.maxParallelReads,
|
|
2743
|
+
// An assessment turn has no edits to verify, so the loop's self-review
|
|
2744
|
+
// gate would never fire for it — see `selfReviewWhenUnchanged`.
|
|
2745
|
+
...(assessmentTurn ? { selfReviewWhenUnchanged: true } : {}),
|
|
2674
2746
|
// WS3 — the turn span the loop hangs each tool call under.
|
|
2675
2747
|
otel: otelSpan,
|
|
2676
2748
|
// WS4 — the label a tool hook reports this call under.
|
|
@@ -2890,6 +2962,15 @@ export class ChatCommand extends BaseCommand {
|
|
|
2890
2962
|
// respects the quality bar they set instead of inviting a downgrade
|
|
2891
2963
|
// (see ExhaustionInput.pinnedModel).
|
|
2892
2964
|
...(session.model && session.model !== 'default' ? { pinnedModel: session.model } : {}),
|
|
2965
|
+
// ...and whether that pin is HELD, which decides whether the report
|
|
2966
|
+
// may promise an automatic next attempt at all. A held pin is the
|
|
2967
|
+
// default for a named pair, so this is the common case, and telling
|
|
2968
|
+
// the user to wait for a switch the pin forbids was the measured bug
|
|
2969
|
+
// (see ExhaustionInput.pinnedHeld). Read from the same predicate
|
|
2970
|
+
// routing obeys, in this turn's own scope.
|
|
2971
|
+
...(session.model && session.model !== 'default' && strictModelMode()
|
|
2972
|
+
? { pinnedHeld: true }
|
|
2973
|
+
: {}),
|
|
2893
2974
|
// The underlying line is kept as the REASON, so a specific,
|
|
2894
2975
|
// actionable cause is never buried by the report.
|
|
2895
2976
|
...(result.generationFailed && result.content.trim() ? { cause: result.content } : {}),
|
|
@@ -3074,6 +3155,15 @@ export class ChatCommand extends BaseCommand {
|
|
|
3074
3155
|
if (turnCarriesHonestyFlag(result)) {
|
|
3075
3156
|
debugLog?.event('cache.skip', { reason: 'honesty-flag', scope: turnScope });
|
|
3076
3157
|
}
|
|
3158
|
+
else if (assessmentTurn) {
|
|
3159
|
+
// Same rule as the honesty flag above, for the same reason: an
|
|
3160
|
+
// assessment is a claim about the tree at THIS moment, so storing it
|
|
3161
|
+
// lets a later read of that entry — another surface, or a path without
|
|
3162
|
+
// this detector — replay it as a fresh look at code that may have
|
|
3163
|
+
// changed underneath it. The turn is not replayed and not stored; it is
|
|
3164
|
+
// re-derived.
|
|
3165
|
+
debugLog?.event('cache.skip', { reason: 'assessment turn — tree-scoped claim', scope: turnScope });
|
|
3166
|
+
}
|
|
3077
3167
|
else {
|
|
3078
3168
|
// Keyed by the model that ACTUALLY answered (tryGenerate records it
|
|
3079
3169
|
// on success), so a weak model's reply is never replayed as a strong
|