amicus 4.6.1 → 4.6.2
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/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +86 -0
- package/README.md +2 -2
- package/docs/ROADMAP.md +7 -2
- package/docs/configuration.md +13 -9
- package/docs/council.md +7 -2
- package/docs/troubleshooting.md +49 -20
- package/docs/usage.md +21 -1
- package/electron/setup-ui-aliases.js +2 -2
- package/electron/workspace-ui/index.html +3 -0
- package/electron/workspace-ui/live-model.js +71 -0
- package/electron/workspace-ui/workspace-app.js +2 -2
- package/electron/workspace-ui/workspace-panels.js +9 -10
- package/electron/workspace-ui/workspace-seats.js +117 -0
- package/electron/workspace-ui/workspace-verbs.js +1 -0
- package/electron/workspace-ui/workspace.css +6 -0
- package/package.json +1 -1
- package/schemas/alias-audit.schema.json +6 -1
- package/schemas/council-run.schema.json +14 -0
- package/src/cli-handlers-doctor.js +16 -4
- package/src/cli.js +4 -0
- package/src/council/run-chair.js +49 -3
- package/src/headless.js +119 -9
- package/src/mcp-council-awareness.js +1 -0
- package/src/opencode-client.js +21 -0
- package/src/sidecar/fanout-leg.js +2 -2
- package/src/sidecar/fanout.js +1 -1
- package/src/sidecar/models-probe.js +119 -0
- package/src/sidecar/models.js +81 -6
- package/src/utils/alias-audit.js +52 -1
- package/src/utils/base-url-classify.js +74 -0
- package/src/utils/council-presets.js +6 -2
- package/src/utils/curated-models.js +29 -10
- package/src/utils/doctor-base-url-check.js +41 -0
- package/src/utils/model-fetcher.js +1 -0
- package/src/utils/model-tiers.js +28 -7
- package/src/utils/no-output-backstop.js +48 -0
- package/src/utils/result-schema.js +29 -2
- package/src/workspace/live-normalize.js +1 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module utils/no-output-backstop
|
|
3
|
+
* v4.6.2 PR2 (spec §5, D4): fail a headless leg fast when the model produces
|
|
4
|
+
* ZERO output, reasoning, and tool calls — the "accepted but not serving"
|
|
5
|
+
* class (the v4.6.1 gemini release-gate incident: requests accepted, zero
|
|
6
|
+
* tokens, three suites burned 130s timeouts each to learn nothing).
|
|
7
|
+
*
|
|
8
|
+
* Pure state machine, loop-driven (no timers of its own — the poll loop
|
|
9
|
+
* ticks it): armed at leg start, DISARMED PERMANENTLY by the first
|
|
10
|
+
* `progressed` tick (a 30-90s cold-prefill local model is never affected),
|
|
11
|
+
* fired when the deadline passes with nothing ever observed. `fired` is
|
|
12
|
+
* terminal. `ms <= 0` never arms — 0 is the documented escape hatch, which
|
|
13
|
+
* is why the env resolver uses envNumber (explicit 0 honored) rather than
|
|
14
|
+
* the `Number(env) || default` idiom.
|
|
15
|
+
*
|
|
16
|
+
* PR3's live probe reuses this with a 30s override — ms is an input; only
|
|
17
|
+
* the exported resolver reads the environment.
|
|
18
|
+
*/
|
|
19
|
+
'use strict';
|
|
20
|
+
|
|
21
|
+
const { envNumber } = require('./env-num');
|
|
22
|
+
|
|
23
|
+
const DEFAULT_NO_OUTPUT_BACKSTOP_MS = 120000;
|
|
24
|
+
|
|
25
|
+
/** @param {object} [env] test seam; defaults to process.env */
|
|
26
|
+
function resolveNoOutputBackstopMs(env) {
|
|
27
|
+
return envNumber('AMICUS_NO_OUTPUT_BACKSTOP_MS', DEFAULT_NO_OUTPUT_BACKSTOP_MS, env);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {{ms:number, startedAt:number}} opts
|
|
32
|
+
* @returns {{tick:(progressed:boolean, nowMs:number)=>string, state:()=>string}}
|
|
33
|
+
*/
|
|
34
|
+
function createNoOutputBackstop({ ms, startedAt }) {
|
|
35
|
+
let state = ms > 0 ? 'armed' : 'disarmed';
|
|
36
|
+
const deadline = startedAt + ms;
|
|
37
|
+
return {
|
|
38
|
+
tick(progressed, nowMs) {
|
|
39
|
+
if (state !== 'armed') { return state; }
|
|
40
|
+
if (progressed) { state = 'disarmed'; return state; }
|
|
41
|
+
if (nowMs >= deadline) { state = 'fired'; }
|
|
42
|
+
return state;
|
|
43
|
+
},
|
|
44
|
+
state() { return state; },
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = { resolveNoOutputBackstopMs, createNoOutputBackstop, DEFAULT_NO_OUTPUT_BACKSTOP_MS };
|
|
@@ -192,10 +192,32 @@ function buildCatalogDoc({ models, fetchedAt, refreshed = false, search = null,
|
|
|
192
192
|
* of curated DEFAULT aliases (toGatewayRoutes() vs. the live catalog),
|
|
193
193
|
* distinct from the flat `stale` audit above. Defaults to [] so existing
|
|
194
194
|
* callers that omit it are unaffected.
|
|
195
|
+
* `drifted` (v4.6.2 PR1, 2A) is additive: stored user-config aliases whose
|
|
196
|
+
* target is still catalog-live but behind the current quick-pick family
|
|
197
|
+
* resolution (findDriftedStoredAliases). Defaults to [] so existing callers
|
|
198
|
+
* that omit it are unaffected. Paired with an additive `driftedCount`
|
|
199
|
+
* (drifted.length), mirroring the staleCount/stale and
|
|
200
|
+
* gatewayFindingsCount/gatewayFindings pairs above.
|
|
201
|
+
* `probe` (v4.6.2 PR3, spec §6 D5) is additive: the `--live` opt-in per-alias
|
|
202
|
+
* probe outcomes (probeStoredAliases — served/accepted-but-silent/error), one
|
|
203
|
+
* row per stored alias actually probed. Defaults to [] so every call without
|
|
204
|
+
* --live (i.e. every existing caller) is unaffected. Paired with an additive
|
|
205
|
+
* `probeCount` (probe.length), mirroring the driftedCount/drifted pair above.
|
|
206
|
+
* `probeSkipped` (v4.6.2 PR3 Task 4) is additive: null when the probe ran or
|
|
207
|
+
* `--live` wasn't requested; otherwise a stable reason slug (e.g.
|
|
208
|
+
* 'catalog-unavailable') for the one case this function can see — the
|
|
209
|
+
* `--refresh --check --live` skip (runRefresh returns before this is ever
|
|
210
|
+
* called) is announced by the caller instead, since that path emits a
|
|
211
|
+
* model-catalog doc, not this one.
|
|
195
212
|
* @param {{stale: Array<{alias,model,source,suggestions}>, catalogAvailable: boolean,
|
|
196
|
-
* gatewayFindings?: Array<{alias,gateway,kind,model,expected?}
|
|
213
|
+
* gatewayFindings?: Array<{alias,gateway,kind,model,expected?}>,
|
|
214
|
+
* drifted?: Array<{alias,stored,current}>,
|
|
215
|
+
* probe?: Array<{alias,target,outcome,detail,cost}>,
|
|
216
|
+
* probeSkipped?: string|null}} opts
|
|
197
217
|
*/
|
|
198
|
-
function buildAuditDoc({
|
|
218
|
+
function buildAuditDoc({
|
|
219
|
+
stale, catalogAvailable, gatewayFindings = [], drifted = [], probe = [], probeSkipped = null
|
|
220
|
+
}) {
|
|
199
221
|
return {
|
|
200
222
|
schemaVersion: SCHEMA_VERSION,
|
|
201
223
|
type: 'alias-audit',
|
|
@@ -204,6 +226,11 @@ function buildAuditDoc({ stale, catalogAvailable, gatewayFindings = [] }) {
|
|
|
204
226
|
stale,
|
|
205
227
|
gatewayFindingsCount: gatewayFindings.length,
|
|
206
228
|
gatewayFindings,
|
|
229
|
+
driftedCount: drifted.length,
|
|
230
|
+
drifted,
|
|
231
|
+
probeCount: probe.length,
|
|
232
|
+
probe,
|
|
233
|
+
probeSkipped,
|
|
207
234
|
};
|
|
208
235
|
}
|
|
209
236
|
|
|
@@ -126,6 +126,7 @@ function normalizeLive(doc) {
|
|
|
126
126
|
stageName: active ? active.name : null,
|
|
127
127
|
stages,
|
|
128
128
|
seats: legRowsOf(doc).map(seatOf),
|
|
129
|
+
degrades: Array.isArray(doc.degrades) ? doc.degrades : [],
|
|
129
130
|
// ⚠️ v4.4.1 RN-8 (D1 ruling: delete the promise). `legsTotal`/`legsComplete` used to be
|
|
130
131
|
// mapped here under a comment promising them as "the honest fallback readout if a seat row
|
|
131
132
|
// is ever unavailable" — a UI fallback nobody ever wired. Nothing in electron/workspace-ui/
|