tickmarkr 1.84.0 → 1.86.0
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 +4 -2
- package/dist/adapters/catalog-remote.d.ts +64 -0
- package/dist/adapters/catalog-remote.js +287 -0
- package/dist/adapters/catalog.d.ts +96 -0
- package/dist/adapters/catalog.js +176 -0
- package/dist/adapters/claude-code.d.ts +1 -0
- package/dist/adapters/claude-code.js +59 -1
- package/dist/adapters/fake.js +42 -4
- package/dist/adapters/model-lints.d.ts +25 -5
- package/dist/adapters/model-lints.js +184 -50
- package/dist/adapters/model-windows.d.ts +31 -0
- package/dist/adapters/model-windows.js +69 -0
- package/dist/adapters/prompt.d.ts +5 -1
- package/dist/adapters/prompt.js +13 -4
- package/dist/adapters/registry.d.ts +25 -26
- package/dist/adapters/registry.js +173 -110
- package/dist/adapters/types.d.ts +3 -0
- package/dist/adapters/types.js +36 -3
- package/dist/brand.d.ts +5 -1
- package/dist/brand.js +18 -2
- package/dist/cli/commands/doctor.d.ts +3 -0
- package/dist/cli/commands/doctor.js +43 -21
- package/dist/cli/commands/fleet.d.ts +7 -0
- package/dist/cli/commands/fleet.js +94 -74
- package/dist/cli/commands/init.js +118 -5
- package/dist/cli/commands/status.js +202 -46
- package/dist/compile/collateral.d.ts +86 -2
- package/dist/compile/collateral.js +294 -3
- package/dist/compile/gsd.d.ts +2 -1
- package/dist/compile/gsd.js +68 -2
- package/dist/compile/native.d.ts +14 -0
- package/dist/compile/native.js +161 -12
- package/dist/config/config.d.ts +82 -5
- package/dist/config/config.js +253 -66
- package/dist/config/fleet-overlay.d.ts +25 -20
- package/dist/config/fleet-overlay.js +195 -77
- package/dist/config/fleet-why.d.ts +23 -0
- package/dist/config/fleet-why.js +42 -0
- package/dist/drivers/herdr.d.ts +21 -3
- package/dist/drivers/herdr.js +344 -110
- package/dist/gates/acceptance.js +7 -2
- package/dist/gates/baseline.d.ts +1 -0
- package/dist/gates/baseline.js +91 -13
- package/dist/gates/llm.d.ts +0 -1
- package/dist/gates/llm.js +5 -30
- package/dist/gates/review.d.ts +9 -1
- package/dist/gates/review.js +105 -10
- package/dist/gates/run-gates.d.ts +9 -0
- package/dist/gates/run-gates.js +285 -41
- package/dist/gates/verdict-cause.d.ts +4 -0
- package/dist/gates/verdict-cause.js +63 -0
- package/dist/graph/schema.d.ts +6 -0
- package/dist/graph/schema.js +8 -5
- package/dist/route/router.d.ts +0 -5
- package/dist/route/router.js +16 -20
- package/dist/run/consult.d.ts +6 -0
- package/dist/run/consult.js +35 -25
- package/dist/run/daemon.d.ts +48 -2
- package/dist/run/daemon.js +1488 -330
- package/dist/run/journal.d.ts +56 -3
- package/dist/run/journal.js +358 -4
- package/dist/run/stall.d.ts +35 -1
- package/dist/run/stall.js +118 -8
- package/dist/tui/cockpit/capture.d.ts +12 -0
- package/dist/tui/cockpit/capture.js +37 -1
- package/dist/tui/cockpit/components.d.ts +2 -0
- package/dist/tui/cockpit/components.js +8 -8
- package/dist/tui/cockpit/derive.d.ts +29 -2
- package/dist/tui/cockpit/derive.js +219 -23
- package/dist/tui/cockpit/run-cockpit.js +128 -27
- package/dist/tui/cockpit/theme.d.ts +32 -26
- package/dist/tui/cockpit/theme.js +11 -5
- package/dist/tui/ink/components.d.ts +0 -15
- package/dist/tui/ink/components.js +0 -17
- package/dist/tui/ink/fleet-app.d.ts +4 -1
- package/dist/tui/ink/fleet-app.js +134 -13
- package/fixtures/sample.native.md +1 -1
- package/package.json +1 -1
- package/skills/tickmarkr-overseer/SKILL.md +354 -34
- package/skills/tickmarkr-overseer/scripts/watch-artifacts.sh +70 -0
- package/skills/tickmarkr-overseer/scripts/watch-panes.sh +1 -1
- package/dist/tui/ink/studio-app.d.ts +0 -59
- package/dist/tui/ink/studio-app.js +0 -320
- package/dist/tui/save.d.ts +0 -38
- package/dist/tui/save.js +0 -96
- package/dist/tui/staging.d.ts +0 -29
- package/dist/tui/staging.js +0 -78
|
@@ -7,19 +7,25 @@ export type ColourValue = {
|
|
|
7
7
|
export declare const LOGO_RAMP: readonly [84, 78, 41, 35];
|
|
8
8
|
/** Near-black panel fill against which every data shade must remain legible. */
|
|
9
9
|
export declare const COCKPIT_SURFACE: "#1a1a19";
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Bright-to-deep, single-hue data ink. Depth communicates magnitude, never tile identity.
|
|
12
|
+
* Anchored on xterm 114 (#87d787) — operator-chosen 2026-08-03 — with the hue (OKLab 144.2°)
|
|
13
|
+
* held constant down the ramp; steps descend in even OKLab lightness (0.094) and were searched
|
|
14
|
+
* and verified through guardDataRamp below. hex is the rendered ink (truecolor terminals);
|
|
15
|
+
* xterm is the nearest-distinct 256-colour fallback, documentation not render source.
|
|
16
|
+
*/
|
|
11
17
|
export declare const COCKPIT_DATA_RAMP: readonly [{
|
|
12
|
-
readonly xterm:
|
|
13
|
-
readonly hex: "#
|
|
18
|
+
readonly xterm: 114;
|
|
19
|
+
readonly hex: "#87d787";
|
|
14
20
|
}, {
|
|
15
|
-
readonly xterm:
|
|
16
|
-
readonly hex: "#
|
|
21
|
+
readonly xterm: 71;
|
|
22
|
+
readonly hex: "#5bbc5e";
|
|
17
23
|
}, {
|
|
18
|
-
readonly xterm:
|
|
19
|
-
readonly hex: "#
|
|
24
|
+
readonly xterm: 65;
|
|
25
|
+
readonly hex: "#4f9a51";
|
|
20
26
|
}, {
|
|
21
27
|
readonly xterm: 29;
|
|
22
|
-
readonly hex: "#
|
|
28
|
+
readonly hex: "#437944";
|
|
23
29
|
}];
|
|
24
30
|
/** Documented near-misses retained as guard fixtures, not special cases in the guard. */
|
|
25
31
|
export declare const EXCLUDED_DATA_SHADES: {
|
|
@@ -38,17 +44,17 @@ export declare const EXCLUDED_DATA_SHADES: {
|
|
|
38
44
|
*/
|
|
39
45
|
export declare const COCKPIT_INKS: {
|
|
40
46
|
readonly dataRamp: readonly [{
|
|
41
|
-
readonly xterm:
|
|
42
|
-
readonly hex: "#
|
|
47
|
+
readonly xterm: 114;
|
|
48
|
+
readonly hex: "#87d787";
|
|
43
49
|
}, {
|
|
44
|
-
readonly xterm:
|
|
45
|
-
readonly hex: "#
|
|
50
|
+
readonly xterm: 71;
|
|
51
|
+
readonly hex: "#5bbc5e";
|
|
46
52
|
}, {
|
|
47
|
-
readonly xterm:
|
|
48
|
-
readonly hex: "#
|
|
53
|
+
readonly xterm: 65;
|
|
54
|
+
readonly hex: "#4f9a51";
|
|
49
55
|
}, {
|
|
50
56
|
readonly xterm: 29;
|
|
51
|
-
readonly hex: "#
|
|
57
|
+
readonly hex: "#437944";
|
|
52
58
|
}];
|
|
53
59
|
readonly warning: {
|
|
54
60
|
readonly xterm: 214;
|
|
@@ -65,17 +71,17 @@ export declare const COCKPIT_INKS: {
|
|
|
65
71
|
};
|
|
66
72
|
/** Every drawable cockpit ink; the panel surface and text emphasis are not inks. */
|
|
67
73
|
export declare const COCKPIT_INK_VOCABULARY: readonly [{
|
|
68
|
-
readonly xterm:
|
|
69
|
-
readonly hex: "#
|
|
74
|
+
readonly xterm: 114;
|
|
75
|
+
readonly hex: "#87d787";
|
|
70
76
|
}, {
|
|
71
|
-
readonly xterm:
|
|
72
|
-
readonly hex: "#
|
|
77
|
+
readonly xterm: 71;
|
|
78
|
+
readonly hex: "#5bbc5e";
|
|
73
79
|
}, {
|
|
74
|
-
readonly xterm:
|
|
75
|
-
readonly hex: "#
|
|
80
|
+
readonly xterm: 65;
|
|
81
|
+
readonly hex: "#4f9a51";
|
|
76
82
|
}, {
|
|
77
83
|
readonly xterm: 29;
|
|
78
|
-
readonly hex: "#
|
|
84
|
+
readonly hex: "#437944";
|
|
79
85
|
}, {
|
|
80
86
|
readonly xterm: 214;
|
|
81
87
|
readonly hex: "#ffaf00";
|
|
@@ -105,16 +111,16 @@ export declare const TEXT_EMPHASIS_TOKENS: {
|
|
|
105
111
|
/** Deliberate 16-colour choices. Renderers select this map; they do not infer one. */
|
|
106
112
|
export declare const REDUCED_COLOUR_MAPPING: {
|
|
107
113
|
readonly dataRamp: readonly [{
|
|
108
|
-
readonly from: "#
|
|
114
|
+
readonly from: "#87d787";
|
|
109
115
|
readonly to: "bright-green";
|
|
110
116
|
}, {
|
|
111
|
-
readonly from: "#
|
|
117
|
+
readonly from: "#5bbc5e";
|
|
112
118
|
readonly to: "green";
|
|
113
119
|
}, {
|
|
114
|
-
readonly from: "#
|
|
120
|
+
readonly from: "#4f9a51";
|
|
115
121
|
readonly to: "green";
|
|
116
122
|
}, {
|
|
117
|
-
readonly from: "#
|
|
123
|
+
readonly from: "#437944";
|
|
118
124
|
readonly to: "dim-green";
|
|
119
125
|
}];
|
|
120
126
|
readonly warning: {
|
|
@@ -3,12 +3,18 @@ import { BRAND_RAMP, GLYPHS } from "../../brand.js";
|
|
|
3
3
|
export const LOGO_RAMP = BRAND_RAMP;
|
|
4
4
|
/** Near-black panel fill against which every data shade must remain legible. */
|
|
5
5
|
export const COCKPIT_SURFACE = "#1a1a19";
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Bright-to-deep, single-hue data ink. Depth communicates magnitude, never tile identity.
|
|
8
|
+
* Anchored on xterm 114 (#87d787) — operator-chosen 2026-08-03 — with the hue (OKLab 144.2°)
|
|
9
|
+
* held constant down the ramp; steps descend in even OKLab lightness (0.094) and were searched
|
|
10
|
+
* and verified through guardDataRamp below. hex is the rendered ink (truecolor terminals);
|
|
11
|
+
* xterm is the nearest-distinct 256-colour fallback, documentation not render source.
|
|
12
|
+
*/
|
|
7
13
|
export const COCKPIT_DATA_RAMP = [
|
|
8
|
-
{ xterm:
|
|
9
|
-
{ xterm:
|
|
10
|
-
{ xterm:
|
|
11
|
-
{ xterm: 29, hex: "#
|
|
14
|
+
{ xterm: 114, hex: "#87d787" },
|
|
15
|
+
{ xterm: 71, hex: "#5bbc5e" },
|
|
16
|
+
{ xterm: 65, hex: "#4f9a51" },
|
|
17
|
+
{ xterm: 29, hex: "#437944" },
|
|
12
18
|
];
|
|
13
19
|
/** Documented near-misses retained as guard fixtures, not special cases in the guard. */
|
|
14
20
|
export const EXCLUDED_DATA_SHADES = {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
|
-
import { type SaveTarget } from "../save.js";
|
|
3
2
|
export type FleetListRow = {
|
|
4
3
|
id: string;
|
|
5
4
|
content: ReactNode;
|
|
@@ -22,17 +21,3 @@ export declare function FleetReviewScreen({ title, legend, diff, }: {
|
|
|
22
21
|
legend: string;
|
|
23
22
|
diff: string;
|
|
24
23
|
}): import("react").JSX.Element;
|
|
25
|
-
export type DiffConfirmationProps = {
|
|
26
|
-
target: SaveTarget;
|
|
27
|
-
targetPath: string;
|
|
28
|
-
diff: string;
|
|
29
|
-
liveRun: boolean;
|
|
30
|
-
};
|
|
31
|
-
export declare function DiffConfirmationScreen(props: DiffConfirmationProps): import("react").JSX.Element;
|
|
32
|
-
export declare function StudioScreen({ tabs, active, lines, status, children, }: {
|
|
33
|
-
tabs: string[];
|
|
34
|
-
active: number;
|
|
35
|
-
lines: string[];
|
|
36
|
-
status?: string;
|
|
37
|
-
children?: ReactNode;
|
|
38
|
-
}): import("react").JSX.Element;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
3
|
import { GLYPHS } from "../../brand.js";
|
|
4
|
-
import { RELOAD_GUARD_NOTICE } from "../save.js";
|
|
5
4
|
function keyedLines(lines) {
|
|
6
5
|
const occurrences = new Map();
|
|
7
6
|
return lines.map((text) => {
|
|
@@ -24,19 +23,3 @@ export function FleetListScreen({ title, legend, rows, cursor, details = [], })
|
|
|
24
23
|
export function FleetReviewScreen({ title, legend, diff, }) {
|
|
25
24
|
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: title }), _jsx(Text, { dimColor: true, children: legend }), _jsx(Text, { children: diff })] }));
|
|
26
25
|
}
|
|
27
|
-
export function DiffConfirmationScreen(props) {
|
|
28
|
-
return _jsx(TextLines, { lines: [
|
|
29
|
-
`Save overlay — ${props.targetPath} (${props.target === "repo" ? "repository" : "global"} target)`,
|
|
30
|
-
"t toggle target · y confirm · n/esc cancel",
|
|
31
|
-
...(props.liveRun ? [RELOAD_GUARD_NOTICE] : []),
|
|
32
|
-
"─ diff ─",
|
|
33
|
-
props.diff || "(no overlay changes)",
|
|
34
|
-
] });
|
|
35
|
-
}
|
|
36
|
-
export function StudioScreen({ tabs, active, lines, status = "no staged changes", children, }) {
|
|
37
|
-
const tabBar = [
|
|
38
|
-
"tickmarkr ui ──",
|
|
39
|
-
...tabs.map((label, index) => `[${index + 1}]${index === active ? "*" : ""}${label}`),
|
|
40
|
-
].join(" ");
|
|
41
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: tabBar }), children ?? _jsx(TextLines, { lines: lines }), _jsx(Text, { dimColor: true, children: status })] }));
|
|
42
|
-
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AuthHealth, type WorkerAdapter } from "../../adapters/types.js";
|
|
2
2
|
import type { MapEntry, RoutingMode, Tier } from "../../config/config.js";
|
|
3
3
|
import { type Shape } from "../../graph/schema.js";
|
|
4
4
|
export type FleetSteeringKey = "review" | "consult";
|
|
@@ -40,6 +40,7 @@ type AgentCli = {
|
|
|
40
40
|
};
|
|
41
41
|
export type FleetModelGroup = {
|
|
42
42
|
adapter: string;
|
|
43
|
+
vendor?: string;
|
|
43
44
|
rows: Array<{
|
|
44
45
|
model: string;
|
|
45
46
|
tier?: Tier;
|
|
@@ -51,6 +52,8 @@ export type FleetClassification = {
|
|
|
51
52
|
model: string;
|
|
52
53
|
tier: Tier;
|
|
53
54
|
note: string;
|
|
55
|
+
vendor?: string;
|
|
56
|
+
channel?: "sub" | "api";
|
|
54
57
|
};
|
|
55
58
|
export type FleetModeOption = {
|
|
56
59
|
id: RoutingMode;
|
|
@@ -3,10 +3,13 @@ import { emitKeypressEvents } from "node:readline";
|
|
|
3
3
|
import { PassThrough } from "node:stream";
|
|
4
4
|
import { render, Text, useApp, useInput } from "ink";
|
|
5
5
|
import { useRef, useState } from "react";
|
|
6
|
+
import { MODEL_ID_RE } from "../../adapters/types.js";
|
|
7
|
+
import { fleetFirstTouchProvenance } from "../../config/fleet-overlay.js";
|
|
6
8
|
import { TIERS } from "../../graph/schema.js";
|
|
7
9
|
import { FleetListScreen, FleetReviewScreen, ToggleMark } from "./components.js";
|
|
8
10
|
const STEERING_KEYS = ["review", "consult"];
|
|
9
11
|
const escape = String.fromCharCode(27);
|
|
12
|
+
const CHANNELS = ["sub", "api"];
|
|
10
13
|
const inkBookkeepingWrites = new Set(["", `${escape}[?25l`, `${escape}[?25h`, `${escape}[?2026h`, `${escape}[?2026l`]);
|
|
11
14
|
function inkOutput(output) {
|
|
12
15
|
if (typeof output.on === "function" && typeof output.off === "function")
|
|
@@ -117,6 +120,11 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
|
|
|
117
120
|
const [modelGroup, setModelGroup] = useState(0);
|
|
118
121
|
const modelCursorRef = useRef(0);
|
|
119
122
|
const [modelCursor, setModelCursor] = useState(0);
|
|
123
|
+
const modelIdRef = useRef("");
|
|
124
|
+
const [modelId, setModelId] = useState("");
|
|
125
|
+
const channelCursorRef = useRef(0);
|
|
126
|
+
const [channelCursor, setChannelCursor] = useState(0);
|
|
127
|
+
const channelByAdapterRef = useRef({});
|
|
120
128
|
const tierCursorRef = useRef(0);
|
|
121
129
|
const [tierCursor, setTierCursor] = useState(0);
|
|
122
130
|
const pendingClassificationRef = useRef(null);
|
|
@@ -160,15 +168,30 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
|
|
|
160
168
|
const group = enabledModelGroups()[modelGroupRef.current];
|
|
161
169
|
if (!group)
|
|
162
170
|
return [];
|
|
163
|
-
|
|
171
|
+
const rows = group.rows.map((row) => {
|
|
164
172
|
const staged = classificationsRef.current.find((classification) => classification.adapter === group.adapter && classification.model === row.model);
|
|
165
173
|
return staged ? { ...row, tier: staged.tier } : row;
|
|
166
174
|
});
|
|
175
|
+
const known = new Set(rows.map((row) => row.model));
|
|
176
|
+
for (const staged of classificationsRef.current) {
|
|
177
|
+
if (staged.adapter === group.adapter && !known.has(staged.model)) {
|
|
178
|
+
rows.push({ model: staged.model, tier: staged.tier });
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return rows;
|
|
167
182
|
};
|
|
168
183
|
const editorState = () => ({
|
|
169
184
|
denyAdapters: [...(denyRef.current ?? [])].sort(),
|
|
170
185
|
denyModels: [...(denyModelsRef.current ?? [])].sort(),
|
|
171
|
-
classifications: classificationsRef.current
|
|
186
|
+
classifications: classificationsRef.current.map((classification) => classification.vendor && classification.channel
|
|
187
|
+
? {
|
|
188
|
+
...classification,
|
|
189
|
+
note: fleetFirstTouchProvenance(classification.note, {
|
|
190
|
+
vendor: classification.vendor,
|
|
191
|
+
channel: classification.channel,
|
|
192
|
+
}),
|
|
193
|
+
}
|
|
194
|
+
: classification),
|
|
172
195
|
selectedMode: selectedModeRef.current,
|
|
173
196
|
map: stagedMap(),
|
|
174
197
|
steering: structuredClone(steeringRef.current),
|
|
@@ -186,6 +209,38 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
|
|
|
186
209
|
screenRef.current = next;
|
|
187
210
|
setScreen(next);
|
|
188
211
|
};
|
|
212
|
+
const beginClassification = (group, model) => {
|
|
213
|
+
tierCursorRef.current = 0;
|
|
214
|
+
setTierCursor(0);
|
|
215
|
+
const firstTouch = !group.rows.some((row) => row.tier !== undefined);
|
|
216
|
+
const pending = {
|
|
217
|
+
adapter: group.adapter,
|
|
218
|
+
model,
|
|
219
|
+
tier: TIERS[0],
|
|
220
|
+
};
|
|
221
|
+
if (!firstTouch) {
|
|
222
|
+
pendingClassificationRef.current = pending;
|
|
223
|
+
showScreen("tiers");
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (!group.vendor) {
|
|
227
|
+
setNotice(`fleet: ${group.adapter} has no vendor declaration — classification cannot be saved`);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
pending.vendor = group.vendor;
|
|
231
|
+
const answered = channelByAdapterRef.current[group.adapter];
|
|
232
|
+
if (answered) {
|
|
233
|
+
pending.channel = answered;
|
|
234
|
+
pendingClassificationRef.current = pending;
|
|
235
|
+
showScreen("tiers");
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
pendingClassificationRef.current = pending;
|
|
239
|
+
channelCursorRef.current = 0;
|
|
240
|
+
setChannelCursor(0);
|
|
241
|
+
setNotice("");
|
|
242
|
+
showScreen("channel");
|
|
243
|
+
};
|
|
189
244
|
useInput((input, key) => {
|
|
190
245
|
if (doneRef.current)
|
|
191
246
|
return;
|
|
@@ -197,7 +252,13 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
|
|
|
197
252
|
showScreen("steering");
|
|
198
253
|
return;
|
|
199
254
|
}
|
|
200
|
-
if (key.escape
|
|
255
|
+
if (key.escape && screenRef.current === "add-model") {
|
|
256
|
+
setNotice("");
|
|
257
|
+
showScreen("models");
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
const typing = screenRef.current === "provenance" || screenRef.current === "add-model";
|
|
261
|
+
if (key.escape || (!typing && input === "q") || (key.ctrl && input === "c")) {
|
|
201
262
|
finish({ kind: "quit" });
|
|
202
263
|
return;
|
|
203
264
|
}
|
|
@@ -276,14 +337,14 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
|
|
|
276
337
|
setNotice("fleet: tier reassignment on classified models is not supported in v1 — edit config directly");
|
|
277
338
|
return;
|
|
278
339
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
showScreen("
|
|
340
|
+
beginClassification(group, row.model);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
if (input === "n" && group) {
|
|
344
|
+
modelIdRef.current = "";
|
|
345
|
+
setModelId("");
|
|
346
|
+
setNotice("");
|
|
347
|
+
showScreen("add-model");
|
|
287
348
|
return;
|
|
288
349
|
}
|
|
289
350
|
if (key.return) {
|
|
@@ -300,6 +361,57 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
|
|
|
300
361
|
}
|
|
301
362
|
return;
|
|
302
363
|
}
|
|
364
|
+
if (screenRef.current === "add-model") {
|
|
365
|
+
if (key.return) {
|
|
366
|
+
const group = enabledModelGroups()[modelGroupRef.current];
|
|
367
|
+
const candidate = modelIdRef.current;
|
|
368
|
+
if (!MODEL_ID_RE.test(candidate)) {
|
|
369
|
+
setNotice(`fleet: model id must match ${MODEL_ID_RE.source}`);
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
if (currentModelRows().some((row) => row.model === candidate)) {
|
|
373
|
+
setNotice(`fleet: ${candidate} is already listed for ${group?.adapter ?? "this adapter"}`);
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
if (group)
|
|
377
|
+
beginClassification(group, candidate);
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
if (key.backspace || key.delete) {
|
|
381
|
+
const next = modelIdRef.current.slice(0, -1);
|
|
382
|
+
modelIdRef.current = next;
|
|
383
|
+
setModelId(next);
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
if (input && !key.ctrl && !key.meta) {
|
|
387
|
+
const next = modelIdRef.current + input;
|
|
388
|
+
modelIdRef.current = next;
|
|
389
|
+
setModelId(next);
|
|
390
|
+
setNotice("");
|
|
391
|
+
}
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
if (screenRef.current === "channel") {
|
|
395
|
+
if (key.downArrow || input === "j") {
|
|
396
|
+
const next = Math.min(channelCursorRef.current + 1, CHANNELS.length - 1);
|
|
397
|
+
channelCursorRef.current = next;
|
|
398
|
+
setChannelCursor(next);
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
if (key.upArrow || input === "k") {
|
|
402
|
+
const next = Math.max(channelCursorRef.current - 1, 0);
|
|
403
|
+
channelCursorRef.current = next;
|
|
404
|
+
setChannelCursor(next);
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
if (key.return && pendingClassificationRef.current) {
|
|
408
|
+
const channel = CHANNELS[channelCursorRef.current];
|
|
409
|
+
channelByAdapterRef.current[pendingClassificationRef.current.adapter] = channel;
|
|
410
|
+
pendingClassificationRef.current.channel = channel;
|
|
411
|
+
showScreen("tiers");
|
|
412
|
+
}
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
303
415
|
if (screenRef.current === "tiers") {
|
|
304
416
|
if (key.downArrow || input === "j") {
|
|
305
417
|
const next = Math.min(tierCursorRef.current + 1, TIERS.length - 1);
|
|
@@ -596,8 +708,12 @@ export function FleetApp({ ageMs, agents, initialDenyAdapters, initialDenyModels
|
|
|
596
708
|
content: row.tier ? (_jsxs(_Fragment, { children: [_jsx(ToggleMark, { active: !denied }), _jsx(Text, { children: ` ${row.model} ${row.tier} ${denied ? "denied" : "allowed"}` })] })) : _jsx(Text, { children: `( ) ${row.model} ??? unclassified${row.detectedAt ? ` (${row.detectedAt})` : ""}` }),
|
|
597
709
|
};
|
|
598
710
|
});
|
|
599
|
-
return (_jsx(FleetListScreen, { title: `step 3/6 · models · ${group?.adapter ?? ""}`, legend: "\u2191\u2193/jk move \u00B7 space toggle \u00B7 t tier \u00B7 enter next \u00B7 esc/q quit", rows: rows, cursor: modelCursor, details: notice ? [notice] : [] }));
|
|
711
|
+
return (_jsx(FleetListScreen, { title: `step 3/6 · models · ${group?.adapter ?? ""}`, legend: "\u2191\u2193/jk move \u00B7 space toggle \u00B7 t tier \u00B7 n add model \u00B7 enter next \u00B7 esc/q quit", rows: rows, cursor: modelCursor, details: notice ? [notice] : [] }));
|
|
600
712
|
}
|
|
713
|
+
if (screen === "add-model")
|
|
714
|
+
return (_jsx(FleetListScreen, { title: `add model · ${group?.adapter ?? ""}`, legend: "type model id \u00B7 enter classify \u00B7 esc cancel", rows: [{ id: "model", content: _jsx(Text, { children: modelId || "model id (required):" }) }], cursor: 0, details: notice ? [notice] : [] }));
|
|
715
|
+
if (screen === "channel")
|
|
716
|
+
return (_jsx(FleetListScreen, { title: `channel · ${pendingClassificationRef.current?.adapter ?? ""}`, legend: "\u2191\u2193/jk move \u00B7 enter select \u00B7 esc/q quit", rows: CHANNELS.map((channel) => ({ id: channel, content: _jsx(Text, { children: channel }) })), cursor: channelCursor }));
|
|
601
717
|
if (screen === "tiers") {
|
|
602
718
|
return (_jsx(FleetListScreen, { title: `pick · tier · ${pendingClassificationRef.current?.adapter}:${pendingClassificationRef.current?.model}`, legend: "\u2191\u2193/jk move \u00B7 enter select \u00B7 esc/q quit", rows: TIERS.map((tier) => ({ id: tier, content: _jsx(Text, { children: tier }) })), cursor: tierCursor }));
|
|
603
719
|
}
|
|
@@ -651,9 +767,14 @@ export async function runFleetInkEditor({ ageMs, adapters, health, initialDenyAd
|
|
|
651
767
|
authed: state.authed,
|
|
652
768
|
}];
|
|
653
769
|
});
|
|
770
|
+
const vendors = new Map(adapters.map((adapter) => [adapter.id, adapter.vendor]));
|
|
771
|
+
const declaredModelGroups = modelGroups.map((group) => ({
|
|
772
|
+
...group,
|
|
773
|
+
vendor: group.vendor ?? vendors.get(group.adapter),
|
|
774
|
+
}));
|
|
654
775
|
const bridgedInput = inkInput(input, initialInput);
|
|
655
776
|
const legacyOutput = typeof output.on !== "function" || typeof output.off !== "function";
|
|
656
|
-
const app = render(_jsx(FleetApp, { ageMs: ageMs, agents: agents, initialDenyAdapters: initialDenyAdapters, initialDenyModels: initialDenyModels, modelGroups:
|
|
777
|
+
const app = render(_jsx(FleetApp, { ageMs: ageMs, agents: agents, initialDenyAdapters: initialDenyAdapters, initialDenyModels: initialDenyModels, modelGroups: declaredModelGroups, initialMode: initialMode, modeOptions: modeOptions, initialMap: initialMap, modePreview: modePreview, shapeRows: shapeRows, candidatesForShape: candidatesForShape, preferOptionsForShape: preferOptionsForShape, initialSteering: initialSteering, steeringOptionsFor: steeringOptionsFor, reviewOverlay: reviewOverlay, reloadGuard: reloadGuard }), {
|
|
657
778
|
// FleetIO's injected stream predates Ink and did not require ref/unref.
|
|
658
779
|
// Real terminal streams pass through unchanged; the compatibility facade
|
|
659
780
|
// adds only those lifecycle methods and leaves input decoding to Ink.
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
- shape: implement
|
|
7
7
|
- deps: none
|
|
8
8
|
- files: src/compile/native.ts, src/compile/index.ts
|
|
9
|
-
- context: docs/
|
|
9
|
+
- context: docs/codebase/ARCHITECTURE.md, src/graph/schema.ts
|
|
10
10
|
- complexity: 8
|
|
11
11
|
- humanGate: true
|
|
12
12
|
- pin: claude-code opus
|