@boundless.network/setup 0.1.1 → 0.1.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/dist/app.js +4 -19
- package/dist/ui/table.js +32 -9
- package/package.json +1 -1
package/dist/app.js
CHANGED
|
@@ -19,8 +19,7 @@ import { Frame, Muted, Para, Title } from "./ui/frame.js";
|
|
|
19
19
|
import { MultiSelect, Select } from "./ui/menu.js";
|
|
20
20
|
import { Spinner } from "./ui/spinner.js";
|
|
21
21
|
import { LOGO, LOGO_COLUMNS, LOGO_ROWS } from "./ui/logo.js";
|
|
22
|
-
import {
|
|
23
|
-
import { TextInput } from "./ui/text-input.js";
|
|
22
|
+
import { ModelSelect } from "./ui/table.js";
|
|
24
23
|
import { BAD, BRAND, MUTED, OK, WARN } from "./ui/theme.js";
|
|
25
24
|
const NAV = "↑↓ navigate enter select";
|
|
26
25
|
function message(error) {
|
|
@@ -173,9 +172,7 @@ export function App({ onFinish }) {
|
|
|
173
172
|
setScreen({ kind: "model", role: "primary" });
|
|
174
173
|
}, onError: (error) => fail(error, { kind: "catalog" }), wizard: wizard }));
|
|
175
174
|
case "model":
|
|
176
|
-
return (_jsx(ModelPicker, { catalog: wizard.catalog, harnesses: chosen(),
|
|
177
|
-
case "type-model":
|
|
178
|
-
return (_jsx(TypeModel, { catalog: wizard.catalog, onCancel: () => setScreen({ kind: "model", role: screen.role }), onSubmit: (id) => chooseModel(screen.role, id) }));
|
|
175
|
+
return (_jsx(ModelPicker, { catalog: wizard.catalog, harnesses: chosen(), onSelect: (id) => chooseModel(screen.role, id), role: screen.role }));
|
|
179
176
|
case "review":
|
|
180
177
|
return (_jsx(Review, { harnesses: chosen(), input: planInput(), onCancel: () => exit(), onPlans: (plans) => {
|
|
181
178
|
wizard.plans = plans;
|
|
@@ -312,22 +309,10 @@ function Catalog({ onDone, onError, wizard }) {
|
|
|
312
309
|
}, []);
|
|
313
310
|
return (_jsx(Frame, { hints: "", children: _jsx(Spinner, { label: "Reading the model catalog" }) }));
|
|
314
311
|
}
|
|
315
|
-
function ModelPicker({ catalog, harnesses,
|
|
312
|
+
function ModelPicker({ catalog, harnesses, onSelect, role, }) {
|
|
316
313
|
const lead = harnesses.find((harness) => role === "primary" || harness.backgroundDefault !== null) ?? harnesses[0];
|
|
317
314
|
const recommended = role === "primary" ? lead?.defaultModel : lead?.backgroundDefault;
|
|
318
|
-
|
|
319
|
-
const cheapest = [...catalog].sort((a, b) => a.outputPerMillionTokens - b.outputPerMillionTokens).map((model) => model.id);
|
|
320
|
-
const picks = [recommended, ...cheapest].filter((id) => typeof id === "string" && ids.has(id));
|
|
321
|
-
const options = [...new Set(picks)].slice(0, 4).map((id, index) => ({
|
|
322
|
-
hint: index === 0 ? `recommended for ${lead?.name ?? "you"}` : undefined,
|
|
323
|
-
label: id,
|
|
324
|
-
value: id,
|
|
325
|
-
}));
|
|
326
|
-
return (_jsxs(Frame, { hints: NAV, children: [_jsx(Title, { children: role === "primary" ? "Which model should be the default?" : "Which model for background work?" }), _jsxs(Muted, { center: true, children: [role === "primary" ? "Every configured harness gets this model." : "Cheap, fast tasks (Claude Code haiku slot, OpenCode small_model, omp tiny).", " Prices are USD per 1M tokens from the live catalog."] }), _jsx(ModelTable, { models: catalog }), _jsx(Box, { justifyContent: "center", children: _jsx(Select, { onSelect: (id) => (id === "__other" ? onOther() : onSelect(id)), options: [...options, { label: "Another model from the table", value: "__other" }] }) })] }));
|
|
327
|
-
}
|
|
328
|
-
function TypeModel({ catalog, onCancel, onSubmit }) {
|
|
329
|
-
const [rejected, setRejected] = useState(null);
|
|
330
|
-
return (_jsxs(Frame, { hints: "enter confirm esc back", children: [_jsx(Title, { children: "Type a model ID" }), _jsx(ModelTable, { models: catalog }), _jsx(Box, { justifyContent: "center", children: _jsx(TextInput, { onCancel: onCancel, onSubmit: (id) => (catalog.some((model) => model.id === id) ? onSubmit(id) : setRejected(id)), placeholder: "model id" }) }), rejected ? (_jsx(Box, { justifyContent: "center", marginTop: 1, children: _jsxs(Text, { color: WARN, children: [rejected, " is not served right now."] }) })) : null] }));
|
|
315
|
+
return (_jsxs(Frame, { hints: NAV, children: [_jsx(Title, { children: role === "primary" ? "Which model should be the default?" : "Which model for background work?" }), _jsxs(Muted, { center: true, children: [role === "primary" ? "Every configured harness gets this model." : "Cheap, fast tasks (Claude Code haiku slot, OpenCode small_model, omp tiny).", " Prices are USD per 1M tokens from the live catalog", lead ? `; the recommendation is ${lead.name}'s documented default.` : "."] }), _jsx(ModelSelect, { models: catalog, onSelect: onSelect, recommended: recommended ?? undefined }, role)] }));
|
|
331
316
|
}
|
|
332
317
|
function Review({ harnesses, input, onCancel, onPlans, onProceed, wizard, }) {
|
|
333
318
|
const [plans, setPlans] = useState(null);
|
package/dist/ui/table.js
CHANGED
|
@@ -1,17 +1,40 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Box, Text } from "ink";
|
|
2
|
+
import { Box, Text, useInput } from "ink";
|
|
3
|
+
import { useState } from "react";
|
|
3
4
|
import { usd } from "../lib/catalog.js";
|
|
4
|
-
import { MUTED } from "./theme.js";
|
|
5
|
-
const
|
|
5
|
+
import { BRAND, MUTED } from "./theme.js";
|
|
6
|
+
const HEADER = ["ID", "Input /1M", "Output /1M", "Context", ""];
|
|
7
|
+
const cells = (model, recommended) => [
|
|
6
8
|
model.id,
|
|
7
9
|
usd(model.inputPerMillionTokens),
|
|
8
10
|
usd(model.outputPerMillionTokens),
|
|
9
11
|
model.contextTokens.toLocaleString("en-US"),
|
|
12
|
+
model.id === recommended ? "recommended" : "",
|
|
10
13
|
];
|
|
11
|
-
export function
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
export function ModelSelect({ models, onSelect, recommended, }) {
|
|
15
|
+
const start = Math.max(models.findIndex((model) => model.id === recommended), 0);
|
|
16
|
+
const [index, setIndex] = useState(start);
|
|
17
|
+
useInput((input, key) => {
|
|
18
|
+
if (key.upArrow || input === "k") {
|
|
19
|
+
setIndex((index + models.length - 1) % models.length);
|
|
20
|
+
}
|
|
21
|
+
else if (key.downArrow || input === "j") {
|
|
22
|
+
setIndex((index + 1) % models.length);
|
|
23
|
+
}
|
|
24
|
+
else if (key.return) {
|
|
25
|
+
const chosen = models[index];
|
|
26
|
+
if (chosen) {
|
|
27
|
+
onSelect(chosen.id);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
const rows = models.map((model) => cells(model, recommended));
|
|
32
|
+
const widths = HEADER.map((cell, column) => Math.max(cell.length, ...rows.map((row) => row[column]?.length ?? 0)));
|
|
33
|
+
const line = (row) => row
|
|
34
|
+
.map((cell, column) => (column === 0 || column === 4 ? cell.padEnd(widths[column] ?? 0) : cell.padStart(widths[column] ?? 0)))
|
|
35
|
+
.join(" ");
|
|
36
|
+
return (_jsx(Box, { justifyContent: "center", marginBottom: 1, children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: MUTED, children: ` ${line(HEADER)}` }), rows.map((row, position) => {
|
|
37
|
+
const active = position === index;
|
|
38
|
+
return (_jsxs(Text, { bold: active, color: active ? BRAND : undefined, children: [active ? "▸ " : " ", line(row)] }, row[0]));
|
|
39
|
+
})] }) }));
|
|
17
40
|
}
|
package/package.json
CHANGED