agent-nuvira 3.3.4 → 3.3.5

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 (33) hide show
  1. package/dist/agent-sdk/src/scaffold.d.ts +1 -1
  2. package/dist/agent-sdk/src/scaffold.js +1 -1
  3. package/dist/config/process-env.d.ts +136 -0
  4. package/dist/config/process-env.d.ts.map +1 -0
  5. package/dist/config/process-env.js +217 -0
  6. package/dist/config/process-env.js.map +1 -0
  7. package/dist/learning/model-reachability.d.ts +95 -0
  8. package/dist/learning/model-reachability.d.ts.map +1 -0
  9. package/dist/learning/model-reachability.js +111 -0
  10. package/dist/learning/model-reachability.js.map +1 -0
  11. package/dist/learning/model-registry.d.ts +22 -0
  12. package/dist/learning/model-registry.d.ts.map +1 -1
  13. package/dist/learning/model-registry.js +24 -0
  14. package/dist/learning/model-registry.js.map +1 -1
  15. package/dist/learning/model-verify-job.d.ts +131 -0
  16. package/dist/learning/model-verify-job.d.ts.map +1 -0
  17. package/dist/learning/model-verify-job.js +221 -0
  18. package/dist/learning/model-verify-job.js.map +1 -0
  19. package/dist/web-dashboard/process-env-inventory.d.ts +57 -0
  20. package/dist/web-dashboard/process-env-inventory.d.ts.map +1 -0
  21. package/dist/web-dashboard/process-env-inventory.js +96 -0
  22. package/dist/web-dashboard/process-env-inventory.js.map +1 -0
  23. package/dist/web-dashboard/server.d.ts.map +1 -1
  24. package/dist/web-dashboard/server.js +246 -17
  25. package/dist/web-dashboard/server.js.map +1 -1
  26. package/dist/web-dashboard/src/types.d.ts +65 -0
  27. package/dist/web-dashboard/src/types.d.ts.map +1 -1
  28. package/package.json +1 -1
  29. package/src/web-dashboard/public/assets/{index-XJjj2cBX.css → index-CIJ6FHHZ.css} +1 -1
  30. package/src/web-dashboard/public/assets/{index-YWF9FpwQ.js → index-CsySzR41.js} +82 -82
  31. package/src/web-dashboard/public/assets/index-CsySzR41.js.map +1 -0
  32. package/src/web-dashboard/public/index.html +2 -2
  33. package/src/web-dashboard/public/assets/index-YWF9FpwQ.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-verify-job.js","sourceRoot":"","sources":["../../src/learning/model-verify-job.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * The data behind the dashboard's Process Environment page.
3
+ *
4
+ * Two values are reported per variable, and keeping them apart is the whole
5
+ * point of this module:
6
+ *
7
+ * - **the file value** — the line in the credential `.env`. This is what the
8
+ * page writes, what persists, and what the NEXT `nuvira` run reads.
9
+ * - **the process value** — what `process.env` holds right now, which is what
10
+ * the RUNNING dashboard would actually obey.
11
+ *
12
+ * They disagree for one reason worth surfacing: `loadEnv()` never overrides a
13
+ * variable that is already in the environment (`Do NOT override existing
14
+ * process.env values — system env vars take priority`). So a value exported in
15
+ * the operator's shell, or a systemd unit's `Environment=`, silently outranks
16
+ * anything written here — for the dashboard AND for every CLI run in that shell.
17
+ * A page that showed only the file would let a user write `NUVIRA_OTEL=0`, watch
18
+ * the row turn off, and still export spans. `shadowed` is that fact, stated.
19
+ *
20
+ * The file is the page's own target, so `state` is computed from it; the process
21
+ * value is reported beside it, never folded in.
22
+ */
23
+ import { type ProcessEnvVarSpec } from '../config/process-env.js';
24
+ /** One row of the page: a curated variable and both of its values. */
25
+ export interface ProcessEnvRow {
26
+ name: string;
27
+ label: string;
28
+ group: ProcessEnvVarSpec['group'];
29
+ kind: ProcessEnvVarSpec['kind'];
30
+ rule?: ProcessEnvVarSpec['rule'];
31
+ acceptsValue?: boolean;
32
+ valueLabel?: string;
33
+ placeholder?: string;
34
+ description: string;
35
+ unsetMeans: string;
36
+ cliEquivalent?: string;
37
+ /**
38
+ * The persisted line, or `null` when there is no line at all. `''` is a real
39
+ * and different state — a line that exists and is blank — so it is not
40
+ * collapsed into `null`.
41
+ */
42
+ fileValue: string | null;
43
+ /** What the running dashboard process sees, or `null` when it is not set. */
44
+ processValue: string | null;
45
+ /** Derived from the FILE value, by the rule its own reader uses. */
46
+ state: 'on' | 'off' | 'set' | 'unset';
47
+ /**
48
+ * True when the process is running with a different value than the file holds,
49
+ * which means a shell/systemd value is outranking this page.
50
+ */
51
+ shadowed: boolean;
52
+ /** Something true about the current combination that a user needs to know. */
53
+ warning?: string;
54
+ }
55
+ /** Build the row set. Never throws — an unreadable `.env` yields every row unset. */
56
+ export declare function readProcessEnvInventory(): ProcessEnvRow[];
57
+ //# sourceMappingURL=process-env-inventory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-env-inventory.d.ts","sourceRoot":"","sources":["../../src/web-dashboard/process-env-inventory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,0BAA0B,CAAC;AAElC,sEAAsE;AACtE,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,6EAA6E;IAC7E,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,oEAAoE;IACpE,KAAK,EAAE,IAAI,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,CAAC;IACtC;;;OAGG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qFAAqF;AACrF,wBAAgB,uBAAuB,IAAI,aAAa,EAAE,CAYzD"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * The data behind the dashboard's Process Environment page.
3
+ *
4
+ * Two values are reported per variable, and keeping them apart is the whole
5
+ * point of this module:
6
+ *
7
+ * - **the file value** — the line in the credential `.env`. This is what the
8
+ * page writes, what persists, and what the NEXT `nuvira` run reads.
9
+ * - **the process value** — what `process.env` holds right now, which is what
10
+ * the RUNNING dashboard would actually obey.
11
+ *
12
+ * They disagree for one reason worth surfacing: `loadEnv()` never overrides a
13
+ * variable that is already in the environment (`Do NOT override existing
14
+ * process.env values — system env vars take priority`). So a value exported in
15
+ * the operator's shell, or a systemd unit's `Environment=`, silently outranks
16
+ * anything written here — for the dashboard AND for every CLI run in that shell.
17
+ * A page that showed only the file would let a user write `NUVIRA_OTEL=0`, watch
18
+ * the row turn off, and still export spans. `shadowed` is that fact, stated.
19
+ *
20
+ * The file is the page's own target, so `state` is computed from it; the process
21
+ * value is reported beside it, never folded in.
22
+ */
23
+ import { loadEnvFile } from '../skills/secret-capture.js';
24
+ import { PROCESS_ENV_VARS, processEnvFlagIsOn, } from '../config/process-env.js';
25
+ /** Build the row set. Never throws — an unreadable `.env` yields every row unset. */
26
+ export function readProcessEnvInventory() {
27
+ let file = {};
28
+ try {
29
+ file = loadEnvFile();
30
+ }
31
+ catch {
32
+ // Best-effort: a broken inventory must not blank the page, and every row
33
+ // still renders as "unset" rather than as absent.
34
+ }
35
+ const rows = PROCESS_ENV_VARS.map((spec) => toRow(spec, file));
36
+ addOtelWarning(rows, file);
37
+ return rows;
38
+ }
39
+ function toRow(spec, file) {
40
+ const fileValue = Object.prototype.hasOwnProperty.call(file, spec.name) ? file[spec.name] : null;
41
+ const rawEnv = process.env[spec.name];
42
+ const processValue = rawEnv === undefined ? null : rawEnv;
43
+ const state = fileValue === null
44
+ ? 'unset'
45
+ : spec.kind === 'text'
46
+ ? 'set'
47
+ : processEnvFlagIsOn(spec.rule, fileValue)
48
+ ? 'on'
49
+ : 'off';
50
+ return {
51
+ name: spec.name,
52
+ label: spec.label,
53
+ group: spec.group,
54
+ kind: spec.kind,
55
+ rule: spec.rule,
56
+ acceptsValue: spec.acceptsValue,
57
+ valueLabel: spec.valueLabel,
58
+ placeholder: spec.placeholder,
59
+ description: spec.description,
60
+ unsetMeans: spec.unsetMeans,
61
+ cliEquivalent: spec.cliEquivalent,
62
+ fileValue,
63
+ processValue,
64
+ state,
65
+ // A blank stored line and an unset variable are different rows but the same
66
+ // effective silence, so only a real disagreement counts as shadowed.
67
+ shadowed: processValue !== null && processValue !== fileValue,
68
+ };
69
+ }
70
+ /**
71
+ * Say out loud that enabling export without an endpoint exports nothing.
72
+ *
73
+ * MEASURED against the OTLP resolution in `otel.ts`: with no
74
+ * `OTEL_EXPORTER_OTLP_ENDPOINT` and no `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`,
75
+ * `otelEndpoint()` returns null — the spans are built and then dropped. That is
76
+ * a run paying for a tracer and shipping nothing, and the page can see it.
77
+ *
78
+ * Both endpoint names are read straight from the file map: they are standard
79
+ * OpenTelemetry names rather than ours, so they are deliberately NOT on the
80
+ * allowlist and this module never writes them.
81
+ */
82
+ function addOtelWarning(rows, file) {
83
+ const otel = rows.find((r) => r.name === 'NUVIRA_OTEL');
84
+ if (!otel)
85
+ return;
86
+ const effective = otel.processValue ?? otel.fileValue;
87
+ if (!processEnvFlagIsOn('truthy', effective))
88
+ return;
89
+ const endpoint = (name) => (process.env[name] ?? (Object.prototype.hasOwnProperty.call(file, name) ? file[name] : '')).trim();
90
+ if (!endpoint('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT') && !endpoint('OTEL_EXPORTER_OTLP_ENDPOINT')) {
91
+ otel.warning =
92
+ 'Export is on but no OTLP endpoint is set, so spans are built and then dropped. ' +
93
+ 'Set OTEL_EXPORTER_OTLP_ENDPOINT to actually ship them.';
94
+ }
95
+ }
96
+ //# sourceMappingURL=process-env-inventory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-env-inventory.js","sourceRoot":"","sources":["../../src/web-dashboard/process-env-inventory.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/web-dashboard/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/web-dashboard/server.ts"],"names":[],"mappings":"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"}
@@ -43,6 +43,9 @@ import { clearModelListCache } from '../inference/model-validator.js';
43
43
  import { probeProviderList } from '../inference/model-probe.js';
44
44
  import { CATALOG_PROVIDER_IDS, getCatalogProvider } from '../inference/provider-catalog.js';
45
45
  import { readHubData } from './hub-data.js';
46
+ import { isCuratedProcessEnvVar, normalizeProcessEnvValue, } from '../config/process-env.js';
47
+ import { FRESH_DAYS, FRESHNESS_COPY, REACHABILITY_COPY, classifyFreshness, classifyReachability, } from '../learning/model-reachability.js';
48
+ import { VERIFY_BACKLOG_DEFAULT_PER_RUN, VERIFY_BACKLOG_MAX_PER_RUN, getVerifyBacklogState, startVerifyBacklogRun, } from '../learning/model-verify-job.js';
46
49
  import { setToolsetEnabled } from '../tools/toolsets.js';
47
50
  import { setSkillEnabled } from '../learning/hub-skill-catalog.js';
48
51
  // I11 — dashboard channel send-test: the same registry/adapters `nuvira gateway
@@ -2766,6 +2769,32 @@ function writeJson(res, status, data) {
2766
2769
  res.writeHead(status, { 'Content-Type': 'application/json' });
2767
2770
  res.end(JSON.stringify(data));
2768
2771
  }
2772
+ /**
2773
+ * Turn a refused process-environment value into something a user can act on.
2774
+ *
2775
+ * UI copy on purpose: the validator sends a stable machine reason, and the
2776
+ * message is composed here. The two that matter most are the ones a user would
2777
+ * otherwise read as success — a name off the allowlist (the endpoint is curated,
2778
+ * and saying so is friendlier than a bare 400) and a value that is not a flag
2779
+ * (`NUVIRA_STRICT_MODEL=true` reads as OFF, so accepting it would store a
2780
+ * setting that does not do what the page says it does).
2781
+ */
2782
+ function describeProcessEnvRefusal(name, reason) {
2783
+ switch (reason) {
2784
+ case 'unknown-name':
2785
+ return `${name || 'That name'} is not one of the curated process switches. Skill secrets live on the Environment page, and provider credentials in provider setup.`;
2786
+ case 'empty':
2787
+ return `${name} cannot be set to an empty value — use Unset to remove it from the env file.`;
2788
+ case 'multiline':
2789
+ return `${name} was not saved: a value may not contain a newline, or it would add a second variable to the env file.`;
2790
+ case 'too-long':
2791
+ return `${name} was not saved: the value is too long (limit 512 characters).`;
2792
+ case 'not-a-flag':
2793
+ return `${name} was not saved: it is a switch, so its value must be on (1, true, yes, on) or off (0, false, off, no).`;
2794
+ default:
2795
+ return `${name} was not saved.`;
2796
+ }
2797
+ }
2769
2798
  // ─── Request Handler ────────────────────────────────────────────────────────
2770
2799
  function handleRequest(req, res) {
2771
2800
  const url = new URL(req.url || '/', `http://${req.headers.host || HOST}`);
@@ -3531,6 +3560,140 @@ function handleRequest(req, res) {
3531
3560
  })();
3532
3561
  return;
3533
3562
  }
3563
+ // ── Process environment — the curated switches, not a general env editor ─
3564
+ //
3565
+ // `/env` edits SKILL secrets: any well-formed NAME a skill might declare. The
3566
+ // switches that change how a RUN behaves (isolation, resume, the debug log,
3567
+ // OTLP export, tool hooks) are a different thing, and the useful thing to
3568
+ // expose is not "write a variable" but "here is what this switch is currently
3569
+ // set to, what unset means, and whether something outranks it".
3570
+ //
3571
+ // The allowlist is enforced HERE rather than in the UI, so a hand-made request
3572
+ // cannot use this endpoint to append an arbitrary name to the credential
3573
+ // `.env` — the page is curated because the server is. Reads need a session;
3574
+ // writing needs routing.operate (admin or operator), matching every other
3575
+ // route that mutates persisted configuration.
3576
+ if (pathname === '/api/process-env' && req.method === 'GET') {
3577
+ void (async () => {
3578
+ const session = adminSessions.validate(bearerToken(req));
3579
+ if (!session) {
3580
+ writeJson(res, 401, { ok: false, error: 'Not authenticated — log in first.' });
3581
+ return;
3582
+ }
3583
+ try {
3584
+ const { readProcessEnvInventory } = await import('./process-env-inventory.js');
3585
+ writeJson(res, 200, { ok: true, vars: readProcessEnvInventory() });
3586
+ }
3587
+ catch (err) {
3588
+ writeJson(res, 500, { ok: false, error: err instanceof Error ? err.message : String(err) });
3589
+ }
3590
+ })();
3591
+ return;
3592
+ }
3593
+ if (pathname === '/api/process-env' && req.method === 'POST') {
3594
+ void (async () => {
3595
+ const session = adminSessions.validate(bearerToken(req));
3596
+ if (!session) {
3597
+ writeJson(res, 401, { ok: false, error: 'Not authenticated — log in first.' });
3598
+ return;
3599
+ }
3600
+ if (!roleCan(session.role, 'routing.operate')) {
3601
+ writeJson(res, 403, {
3602
+ ok: false,
3603
+ error: `Access denied — role '${session.role}' cannot change the process environment (requires admin or operator).`,
3604
+ });
3605
+ return;
3606
+ }
3607
+ const body = await readJsonBody(req);
3608
+ const name = typeof body?.name === 'string' ? body.name.trim() : '';
3609
+ const rawValue = typeof body?.value === 'string' ? body.value : '';
3610
+ const normalized = normalizeProcessEnvValue(name, rawValue);
3611
+ if (!normalized.ok) {
3612
+ writeJson(res, 400, { ok: false, error: describeProcessEnvRefusal(name, normalized.reason), reason: normalized.reason });
3613
+ return;
3614
+ }
3615
+ try {
3616
+ const { saveEnvValue } = await import('../skills/secret-capture.js');
3617
+ const written = saveEnvValue(name, normalized.value);
3618
+ if (!written.success) {
3619
+ writeJson(res, 400, { ok: false, error: `${name} could not be written to the env file (${written.reason ?? 'write-failed'}).` });
3620
+ return;
3621
+ }
3622
+ // Apply to THIS process, so the dashboard's own turns obey the switch
3623
+ // without a restart. It is also why the row stops reading as shadowed:
3624
+ // the process now holds the value that was just written to the file.
3625
+ try {
3626
+ const { applyEnvToProcess } = await import('../gateway/platform-config.js');
3627
+ applyEnvToProcess({ [name]: normalized.value });
3628
+ }
3629
+ catch {
3630
+ /* best-effort */
3631
+ }
3632
+ const { readProcessEnvInventory } = await import('./process-env-inventory.js');
3633
+ writeJson(res, 200, {
3634
+ ok: true,
3635
+ saved: { name, value: normalized.value },
3636
+ row: readProcessEnvInventory().find((r) => r.name === name),
3637
+ });
3638
+ }
3639
+ catch (err) {
3640
+ writeJson(res, 500, { ok: false, error: err instanceof Error ? err.message : String(err) });
3641
+ }
3642
+ })();
3643
+ return;
3644
+ }
3645
+ if (pathname === '/api/process-env/delete' && req.method === 'POST') {
3646
+ void (async () => {
3647
+ const session = adminSessions.validate(bearerToken(req));
3648
+ if (!session) {
3649
+ writeJson(res, 401, { ok: false, error: 'Not authenticated — log in first.' });
3650
+ return;
3651
+ }
3652
+ if (!roleCan(session.role, 'routing.operate')) {
3653
+ writeJson(res, 403, {
3654
+ ok: false,
3655
+ error: `Access denied — role '${session.role}' cannot change the process environment (requires admin or operator).`,
3656
+ });
3657
+ return;
3658
+ }
3659
+ const body = await readJsonBody(req);
3660
+ const name = typeof body?.name === 'string' ? body.name.trim() : '';
3661
+ // The same allowlist the write path uses: deleting an arbitrary name from
3662
+ // the credential file would be a write wearing a different verb.
3663
+ if (!isCuratedProcessEnvVar(name)) {
3664
+ writeJson(res, 400, { ok: false, error: describeProcessEnvRefusal(name, 'unknown-name'), reason: 'unknown-name' });
3665
+ return;
3666
+ }
3667
+ try {
3668
+ const { deleteEnvValue } = await import('../skills/secret-capture.js');
3669
+ const result = deleteEnvValue(name);
3670
+ if (!result.success) {
3671
+ writeJson(res, 400, { ok: false, error: result.reason ?? 'delete failed' });
3672
+ return;
3673
+ }
3674
+ // Drop it from this process too. "Unset" has to mean unset for the run
3675
+ // that is about to happen, or the row would read as unset while the
3676
+ // dashboard kept obeying the value it just removed.
3677
+ try {
3678
+ const { applyEnvToProcess } = await import('../gateway/platform-config.js');
3679
+ applyEnvToProcess({}, [name]);
3680
+ }
3681
+ catch {
3682
+ /* best-effort */
3683
+ }
3684
+ const { readProcessEnvInventory } = await import('./process-env-inventory.js');
3685
+ writeJson(res, 200, {
3686
+ ok: true,
3687
+ removed: result.removed,
3688
+ row: readProcessEnvInventory().find((r) => r.name === name),
3689
+ });
3690
+ }
3691
+ catch (err) {
3692
+ writeJson(res, 500, { ok: false, error: err instanceof Error ? err.message : String(err) });
3693
+ }
3694
+ })();
3695
+ return;
3696
+ }
3534
3697
  // ── Agent Hub channel send-test (I11) — admin-gated gateway send ────────
3535
3698
  // Mirrors `nuvira gateway send <target> <text>`: resolve the target (alias or
3536
3699
  // platform:channelId) through the SAME ChannelDirectory, then send through
@@ -4318,25 +4481,34 @@ function handleRequest(req, res) {
4318
4481
  const registryData = readJSON(join(MEMORY_DIR, 'model-registry.json'));
4319
4482
  const now = Date.now();
4320
4483
  const entries = Object.values(registryData?.entries ?? {});
4321
- const STALE_DAYS = 7;
4322
- const REMOVED_DAYS = 30;
4323
- let freshCount = 0;
4324
- let staleCount = 0;
4325
- let removedCount = 0;
4484
+ // Two classifications per entry, deliberately separate — see
4485
+ // `model-reachability.ts` for why: "is the provider still listing it"
4486
+ // (probe age) and "would the router use it" (verification) are different
4487
+ // questions, and this endpoint previously answered both with one rule
4488
+ // while the panel's badges answered with another.
4489
+ const counts = {
4490
+ routable: 0,
4491
+ parked: 0,
4492
+ 'proof-expired': 0,
4493
+ 'proven-dead': 0,
4494
+ 'never-verified': 0,
4495
+ };
4496
+ const freshnessCounts = {
4497
+ fresh: 0,
4498
+ stale: 0,
4499
+ 'likely-removed': 0,
4500
+ };
4326
4501
  const timelineEntries = entries.map((e) => {
4327
- const daysSinceProbe = e.lastProbedAt ? (now - e.lastProbedAt) / (24 * 60 * 60 * 1000) : Infinity;
4328
- const isStale = daysSinceProbe > STALE_DAYS;
4329
- const isRemoved = daysSinceProbe > REMOVED_DAYS && e.errorRate > 0.5;
4330
- if (isRemoved)
4331
- removedCount++;
4332
- else if (isStale)
4333
- staleCount++;
4334
- else
4335
- freshCount++;
4502
+ const reachability = classifyReachability(e, now);
4503
+ const freshness = classifyFreshness(e.lastProbedAt, e.errorRate, now);
4504
+ counts[reachability] += 1;
4505
+ freshnessCounts[freshness] += 1;
4336
4506
  return {
4337
4507
  provider: e.provider,
4338
4508
  model: e.model,
4339
4509
  status: e.status,
4510
+ reachability,
4511
+ freshness,
4340
4512
  lastVerifiedAt: e.lastVerifiedAt || 0,
4341
4513
  lastProbedAt: e.lastProbedAt || 0,
4342
4514
  lastUsedAt: e.lastUsedAt || 0,
@@ -4344,6 +4516,10 @@ function handleRequest(req, res) {
4344
4516
  latencyMs: e.latencyMs,
4345
4517
  contextWindowTokens: e.contextWindowTokens,
4346
4518
  firstSeenAt: e.firstSeenAt || e.lastProbedAt || 0,
4519
+ /** How stale this model's PROOF is — the number `isUsable()` gates on. */
4520
+ daysSinceVerify: e.lastVerifiedAt
4521
+ ? (now - e.lastVerifiedAt) / (24 * 60 * 60 * 1000)
4522
+ : null,
4347
4523
  };
4348
4524
  });
4349
4525
  res.writeHead(200, { 'Content-Type': 'application/json' });
@@ -4351,9 +4527,15 @@ function handleRequest(req, res) {
4351
4527
  entries: timelineEntries,
4352
4528
  lastUpdated: now,
4353
4529
  totalModels: entries.length,
4354
- freshCount,
4355
- staleCount,
4356
- removedCount,
4530
+ counts,
4531
+ freshnessCounts,
4532
+ // The wording travels WITH the data, so the panel cannot drift from the
4533
+ // classifier that produced the state. `reachability-copy` is one small
4534
+ // map, not a per-row string, and it keeps the root learning modules out
4535
+ // of the browser bundle (they are server-side only).
4536
+ reachabilityCopy: REACHABILITY_COPY,
4537
+ freshnessCopy: FRESHNESS_COPY,
4538
+ freshDays: FRESH_DAYS,
4357
4539
  }));
4358
4540
  }
4359
4541
  catch (err) {
@@ -4362,6 +4544,53 @@ function handleRequest(req, res) {
4362
4544
  }
4363
4545
  return;
4364
4546
  }
4547
+ // ── Timeline action: "verify next N" the never-verified backlog ──────────
4548
+ // READ is open, like `/api/model-timeline` above: it carries model ids, counts
4549
+ // and prose, no credentials, and it renders on a page that is already readable
4550
+ // without a session. The WRITE below is where the gate belongs — a spot-check
4551
+ // is a real generation against the user's provider quota.
4552
+ if (pathname === '/api/models/verify-next' && req.method === 'GET') {
4553
+ writeJson(res, 200, {
4554
+ ...getVerifyBacklogState(),
4555
+ defaultCount: VERIFY_BACKLOG_DEFAULT_PER_RUN,
4556
+ maxCount: VERIFY_BACKLOG_MAX_PER_RUN,
4557
+ });
4558
+ return;
4559
+ }
4560
+ // POST /api/models/verify-next — start probing the next N never-verified ids.
4561
+ // Returns as soon as the run is PLANNED; the probes continue in the background
4562
+ // and the panel watches them through the GET above. A run that is refused
4563
+ // (already running, or an empty backlog) is reported with `ok: false` plus the
4564
+ // reason, so "nothing left to do" never has to be inferred from a zero count.
4565
+ if (pathname === '/api/models/verify-next' && req.method === 'POST') {
4566
+ void (async () => {
4567
+ const session = adminSessions.validate(bearerToken(req));
4568
+ if (!session) {
4569
+ writeJson(res, 401, { ok: false, error: 'Not authenticated — log in first.' });
4570
+ return;
4571
+ }
4572
+ if (!roleCan(session.role, 'routing.operate')) {
4573
+ writeJson(res, 403, {
4574
+ ok: false,
4575
+ error: `Access denied — role '${session.role}' cannot spend provider quota on model verification.`,
4576
+ });
4577
+ return;
4578
+ }
4579
+ const body = await readJsonBody(req);
4580
+ const requested = typeof body?.count === 'number' ? body.count : VERIFY_BACKLOG_DEFAULT_PER_RUN;
4581
+ const result = startVerifyBacklogRun(new ConfigManager(), requested);
4582
+ writeJson(res, 200, {
4583
+ ok: result.started,
4584
+ started: result.started,
4585
+ error: result.error,
4586
+ refusal: result.state.refusal,
4587
+ state: result.state,
4588
+ defaultCount: VERIFY_BACKLOG_DEFAULT_PER_RUN,
4589
+ maxCount: VERIFY_BACKLOG_MAX_PER_RUN,
4590
+ });
4591
+ })();
4592
+ return;
4593
+ }
4365
4594
  if (pathname === '/api/requests') {
4366
4595
  res.writeHead(200, { 'Content-Type': 'application/json' });
4367
4596
  res.end(JSON.stringify(readRequestsData()));