@ordewell/cli 0.4.11 → 0.4.13
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/main.js +94 -73
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
));
|
|
25
25
|
|
|
26
26
|
// src/main.ts
|
|
27
|
-
var
|
|
27
|
+
var import_core19 = require("@ordewell/core");
|
|
28
28
|
|
|
29
29
|
// src/utils/env.ts
|
|
30
30
|
var import_fs = require("fs");
|
|
@@ -1181,6 +1181,7 @@ function iconFor(status) {
|
|
|
1181
1181
|
}
|
|
1182
1182
|
|
|
1183
1183
|
// src/commands/run.ts
|
|
1184
|
+
var import_core7 = require("@ordewell/core");
|
|
1184
1185
|
function resolveSessionId(subArgs) {
|
|
1185
1186
|
const explicit = flag(subArgs, "--session-id");
|
|
1186
1187
|
if (explicit) return explicit;
|
|
@@ -1221,6 +1222,10 @@ async function followExecution(api, sessionId) {
|
|
|
1221
1222
|
await api.streamExecution(sessionId, (event) => {
|
|
1222
1223
|
if (event.type === "task_started") {
|
|
1223
1224
|
process.stderr.write(`[${event.order}/${event.title}] Started: ${event.runner} / ${event.modelId}
|
|
1225
|
+
`);
|
|
1226
|
+
}
|
|
1227
|
+
if (event.type === "checkpoint") {
|
|
1228
|
+
process.stderr.write(`\xB7 Checkpoint \u2014 ${event.taskTitle}: ${(0, import_core7.truncateCheckpointSummary)(event.summary)}
|
|
1224
1229
|
`);
|
|
1225
1230
|
}
|
|
1226
1231
|
if (event.type === "status_update" && event.tasks) {
|
|
@@ -1261,7 +1266,7 @@ async function handleRun(subArgs) {
|
|
|
1261
1266
|
|
|
1262
1267
|
// src/commands/status.ts
|
|
1263
1268
|
var import_fs4 = require("fs");
|
|
1264
|
-
var
|
|
1269
|
+
var import_core8 = require("@ordewell/core");
|
|
1265
1270
|
async function handleStatus(subArgs, injectedApi) {
|
|
1266
1271
|
const sessionId = flag(subArgs, "--session-id");
|
|
1267
1272
|
const workspace = flag(subArgs, "--workspace") || process.cwd();
|
|
@@ -1332,12 +1337,12 @@ function printOneSession(sessionId, meta, plan) {
|
|
|
1332
1337
|
const icon = iconFor(t.status);
|
|
1333
1338
|
const model = t.assignedModel ? ` (${t.assignedModel.modelLabel})` : "";
|
|
1334
1339
|
const shortId = (t.id ?? "").slice(-8);
|
|
1335
|
-
console.log(` ${(0,
|
|
1340
|
+
console.log(` ${(0, import_core8.taskOrderLabel)(t).padStart(2)}. ${icon} [${shortId}] ${t.title}${model}`);
|
|
1336
1341
|
for (const sub of t.subtasks || []) {
|
|
1337
1342
|
const subIcon = iconFor(sub.status);
|
|
1338
1343
|
const subModel = sub.assignedModel ? ` (${sub.assignedModel.modelLabel})` : "";
|
|
1339
1344
|
const subShortId = (sub.id ?? "").slice(-8);
|
|
1340
|
-
console.log(` ${(0,
|
|
1345
|
+
console.log(` ${(0, import_core8.taskOrderLabel)(sub, t)}. ${subIcon} [${subShortId}] ${sub.title}${subModel}`);
|
|
1341
1346
|
}
|
|
1342
1347
|
}
|
|
1343
1348
|
}
|
|
@@ -1389,10 +1394,10 @@ async function handleWeb(subArgs) {
|
|
|
1389
1394
|
}
|
|
1390
1395
|
|
|
1391
1396
|
// src/commands/models.ts
|
|
1392
|
-
var
|
|
1397
|
+
var import_core10 = require("@ordewell/core");
|
|
1393
1398
|
|
|
1394
1399
|
// src/commands/model.ts
|
|
1395
|
-
var
|
|
1400
|
+
var import_core9 = require("@ordewell/core");
|
|
1396
1401
|
|
|
1397
1402
|
// src/catalog.ts
|
|
1398
1403
|
function normalizeCatalog(result) {
|
|
@@ -1498,7 +1503,7 @@ async function handleModel(subArgs, injectedApi) {
|
|
|
1498
1503
|
if (!modelId) fail(USAGE);
|
|
1499
1504
|
const settings = await api.getSettings();
|
|
1500
1505
|
const provider = typeof settings.aiProvider === "string" ? settings.aiProvider : "";
|
|
1501
|
-
const runner = (0,
|
|
1506
|
+
const runner = (0, import_core9.runnerForProvider)(provider);
|
|
1502
1507
|
if (runner) {
|
|
1503
1508
|
const known = (await fetchCatalog(api)).models.filter((m) => m.runners?.includes(runner));
|
|
1504
1509
|
if (known.length > 0 && !known.some((m) => m.id === modelId)) {
|
|
@@ -1517,7 +1522,7 @@ async function showModels(api) {
|
|
|
1517
1522
|
const [settings, catalog] = await Promise.all([api.getSettings(), fetchCatalog(api)]);
|
|
1518
1523
|
const provider = typeof settings.aiProvider === "string" ? settings.aiProvider : "";
|
|
1519
1524
|
const current = typeof settings.orchestratorModel === "string" ? settings.orchestratorModel : "";
|
|
1520
|
-
const runner = (0,
|
|
1525
|
+
const runner = (0, import_core9.runnerForProvider)(provider);
|
|
1521
1526
|
const options = runner ? catalog.models.filter((m) => m.runners?.includes(runner)) : catalog.orchestratorModels;
|
|
1522
1527
|
console.log(`
|
|
1523
1528
|
Planner model: ${current || "(backend default)"}`);
|
|
@@ -1551,8 +1556,8 @@ async function handleModels(subArgs) {
|
|
|
1551
1556
|
const rest = subArgs.filter((_, i) => i !== setIdx && i !== setIdx + 1);
|
|
1552
1557
|
return handleModel(["set", subArgs[setIdx + 1], ...rest]);
|
|
1553
1558
|
}
|
|
1554
|
-
const config = new
|
|
1555
|
-
const providers = (0,
|
|
1559
|
+
const config = new import_core10.EnvConfig();
|
|
1560
|
+
const providers = (0, import_core10.configuredProviders)(config);
|
|
1556
1561
|
if (providers.length === 0) {
|
|
1557
1562
|
console.error("No providers configured. Set an API key for a provider, e.g.:");
|
|
1558
1563
|
console.error(" OPENROUTER_API_KEY=... (OpenRouter)");
|
|
@@ -1561,19 +1566,19 @@ async function handleModels(subArgs) {
|
|
|
1561
1566
|
console.error(" OPENAI_COMPATIBLE_BASE_URL=... (self-hosted / OpenAI-compatible)");
|
|
1562
1567
|
process.exit(1);
|
|
1563
1568
|
}
|
|
1564
|
-
const { apiKeys, baseUrls } = (0,
|
|
1569
|
+
const { apiKeys, baseUrls } = (0, import_core10.collectProviderCredentials)(config);
|
|
1565
1570
|
let models;
|
|
1566
1571
|
let errors;
|
|
1567
1572
|
try {
|
|
1568
|
-
const result = await (0,
|
|
1569
|
-
models = (0,
|
|
1573
|
+
const result = await (0, import_core10.fetchAllProviderModels)({ apiKeys, baseUrls });
|
|
1574
|
+
models = (0, import_core10.toOrchestratorOptions)(result.models, import_core10.ORCHESTRATOR_SHORTCUTS);
|
|
1570
1575
|
errors = result.errors;
|
|
1571
1576
|
} catch (err) {
|
|
1572
1577
|
console.error(`Failed to fetch models: ${err instanceof Error ? err.message : String(err)}`);
|
|
1573
1578
|
process.exit(1);
|
|
1574
1579
|
return;
|
|
1575
1580
|
}
|
|
1576
|
-
const providerLabel = (p) => (0,
|
|
1581
|
+
const providerLabel = (p) => (0, import_core10.getProviderMeta)(p)?.label ?? p;
|
|
1577
1582
|
console.log(
|
|
1578
1583
|
`
|
|
1579
1584
|
Available models (${models.length}) across ${providers.length} configured provider(s):`
|
|
@@ -1690,9 +1695,9 @@ function handleSetup(subArgs) {
|
|
|
1690
1695
|
}
|
|
1691
1696
|
|
|
1692
1697
|
// src/commands/plugins.ts
|
|
1693
|
-
var
|
|
1698
|
+
var import_core11 = require("@ordewell/core");
|
|
1694
1699
|
function handlePlugins(subArgs) {
|
|
1695
|
-
const registry = new
|
|
1700
|
+
const registry = new import_core11.RunnerRegistry();
|
|
1696
1701
|
registry.loadUserPlugins();
|
|
1697
1702
|
const sub = subArgs[0];
|
|
1698
1703
|
if (sub === "list" || !sub) {
|
|
@@ -1728,7 +1733,7 @@ ${plugins.length} plugin(s):
|
|
|
1728
1733
|
process.exit(1);
|
|
1729
1734
|
}
|
|
1730
1735
|
try {
|
|
1731
|
-
const resolved = (0,
|
|
1736
|
+
const resolved = (0, import_core11.classifyPluginSource)(source);
|
|
1732
1737
|
const manifest = resolved.kind === "git" ? registry.installFromGit(resolved.url) : registry.installFromPath(resolved.path);
|
|
1733
1738
|
console.log(`Installed plugin: ${manifest.name} v${manifest.version}`);
|
|
1734
1739
|
} catch (err) {
|
|
@@ -2123,7 +2128,7 @@ async function handleSessions(subArgs, injectedApi) {
|
|
|
2123
2128
|
}
|
|
2124
2129
|
|
|
2125
2130
|
// src/commands/planner.ts
|
|
2126
|
-
var
|
|
2131
|
+
var import_core12 = require("@ordewell/core");
|
|
2127
2132
|
|
|
2128
2133
|
// src/plannerModelSwitch.ts
|
|
2129
2134
|
function describePlannerSwitch(settings, provider) {
|
|
@@ -2142,7 +2147,7 @@ function rememberedModelFor(settings, provider) {
|
|
|
2142
2147
|
}
|
|
2143
2148
|
|
|
2144
2149
|
// src/commands/planner.ts
|
|
2145
|
-
var KNOWN_PROVIDERS = Object.keys(
|
|
2150
|
+
var KNOWN_PROVIDERS = Object.keys(import_core12.ALL_PROVIDERS);
|
|
2146
2151
|
async function handlePlanner(subArgs, injectedApi) {
|
|
2147
2152
|
const api = await connect(subArgs, injectedApi);
|
|
2148
2153
|
const [wanted] = positionals(subArgs);
|
|
@@ -2157,13 +2162,13 @@ async function handlePlanner(subArgs, injectedApi) {
|
|
|
2157
2162
|
const settings = await persistEnv(api, { AI_PROVIDER: provider });
|
|
2158
2163
|
const recall2 = describePlannerSwitch(settings, provider);
|
|
2159
2164
|
writeEnv({ ORCHESTRATOR_MODEL: recall2.model, ORDEWELL_PLANNER_EFFORT: recall2.effort });
|
|
2160
|
-
const meta =
|
|
2165
|
+
const meta = import_core12.ALL_PROVIDERS[provider];
|
|
2161
2166
|
const catalog = await fetchCatalog(api);
|
|
2162
2167
|
console.log(
|
|
2163
|
-
(0,
|
|
2168
|
+
(0, import_core12.isCliProvider)(provider) ? `Planning with ${meta.label} \u2014 no API key needed, it uses that agent's own subscription.` : `Planner set to ${meta.label}.`
|
|
2164
2169
|
);
|
|
2165
2170
|
console.log(plannerModelLine(recall2));
|
|
2166
|
-
if (!(0,
|
|
2171
|
+
if (!(0, import_core12.isCliProvider)(provider) && !catalog.providers.includes(provider)) {
|
|
2167
2172
|
console.log(` No ${meta.apiKeyEnvVar} configured yet \u2014 set one with \`ordewell key set ${provider} <key>\`.`);
|
|
2168
2173
|
}
|
|
2169
2174
|
}
|
|
@@ -2181,15 +2186,15 @@ async function showPlanners(api) {
|
|
|
2181
2186
|
const [settings, catalog] = await Promise.all([api.getSettings(), fetchCatalog(api)]);
|
|
2182
2187
|
const current = typeof settings.aiProvider === "string" ? settings.aiProvider : "";
|
|
2183
2188
|
console.log("\nCoding agents (no API key \u2014 they use their own subscription)");
|
|
2184
|
-
for (const id of
|
|
2185
|
-
const runner = (0,
|
|
2189
|
+
for (const id of import_core12.CLI_PROVIDERS) {
|
|
2190
|
+
const runner = (0, import_core12.runnerForProvider)(id);
|
|
2186
2191
|
const discovered = runner ? catalog.models.some((m) => m.runners?.includes(runner)) : false;
|
|
2187
|
-
console.log(` ${marker(id === current)} ${id.padEnd(14)} ${
|
|
2192
|
+
console.log(` ${marker(id === current)} ${id.padEnd(14)} ${import_core12.ALL_PROVIDERS[id].label}${discovered ? "" : " (not detected)"}`);
|
|
2188
2193
|
}
|
|
2189
2194
|
console.log("\nAPI providers");
|
|
2190
|
-
for (const id of
|
|
2195
|
+
for (const id of import_core12.PROVIDER_PRIORITY) {
|
|
2191
2196
|
const configured = catalog.providers.includes(id);
|
|
2192
|
-
const meta =
|
|
2197
|
+
const meta = import_core12.ALL_PROVIDERS[id];
|
|
2193
2198
|
console.log(` ${marker(id === current)} ${id.padEnd(14)} ${meta.label}${configured ? "" : ` (no ${meta.apiKeyEnvVar})`}`);
|
|
2194
2199
|
}
|
|
2195
2200
|
console.log(`
|
|
@@ -2206,7 +2211,7 @@ async function handlePlannerEffort(subArgs, injectedApi) {
|
|
|
2206
2211
|
const provider = typeof settings.aiProvider === "string" ? settings.aiProvider : "";
|
|
2207
2212
|
const modelId = typeof settings.orchestratorModel === "string" ? settings.orchestratorModel : "";
|
|
2208
2213
|
const currentEffort = typeof settings.plannerThinkingEffort === "string" ? settings.plannerThinkingEffort : "";
|
|
2209
|
-
const runner = (0,
|
|
2214
|
+
const runner = (0, import_core12.runnerForProvider)(provider);
|
|
2210
2215
|
if (!runner) {
|
|
2211
2216
|
fail(
|
|
2212
2217
|
"Thinking effort applies to a coding-agent planner.",
|
|
@@ -2246,7 +2251,7 @@ async function handlePlannerEffort(subArgs, injectedApi) {
|
|
|
2246
2251
|
}
|
|
2247
2252
|
|
|
2248
2253
|
// src/commands/key.ts
|
|
2249
|
-
var
|
|
2254
|
+
var import_core13 = require("@ordewell/core");
|
|
2250
2255
|
var USAGE4 = "Usage: ordewell key [list | set <provider> <key>]";
|
|
2251
2256
|
async function handleKey(subArgs, injectedApi) {
|
|
2252
2257
|
const [action, provider, ...keyParts] = positionals(subArgs);
|
|
@@ -2257,8 +2262,8 @@ async function handleKey(subArgs, injectedApi) {
|
|
|
2257
2262
|
if (action !== "set") {
|
|
2258
2263
|
const catalog = await fetchCatalog(api);
|
|
2259
2264
|
console.log("\nAPI provider keys\n");
|
|
2260
|
-
for (const id2 of
|
|
2261
|
-
const meta2 =
|
|
2265
|
+
for (const id2 of import_core13.PROVIDER_PRIORITY) {
|
|
2266
|
+
const meta2 = import_core13.ALL_PROVIDERS[id2];
|
|
2262
2267
|
const configured = catalog.providers.includes(id2);
|
|
2263
2268
|
console.log(` ${configured ? "\u2713" : " "} ${id2.padEnd(14)} ${meta2.apiKeyEnvVar.padEnd(28)} ${meta2.label}`);
|
|
2264
2269
|
}
|
|
@@ -2268,7 +2273,7 @@ async function handleKey(subArgs, injectedApi) {
|
|
|
2268
2273
|
}
|
|
2269
2274
|
if (!provider) fail(USAGE4);
|
|
2270
2275
|
const id = provider.toLowerCase();
|
|
2271
|
-
const meta =
|
|
2276
|
+
const meta = import_core13.ALL_PROVIDERS[id];
|
|
2272
2277
|
if (!meta) {
|
|
2273
2278
|
fail(`Unknown provider: ${provider}`, "Run `ordewell key` to see the list.");
|
|
2274
2279
|
}
|
|
@@ -2348,7 +2353,7 @@ async function handleApprove(subArgs, injectedApi) {
|
|
|
2348
2353
|
// src/tui/terminalLauncher.ts
|
|
2349
2354
|
var import_child_process3 = require("child_process");
|
|
2350
2355
|
var import_util = require("util");
|
|
2351
|
-
var
|
|
2356
|
+
var import_core14 = require("@ordewell/core");
|
|
2352
2357
|
var execFileAsync = (0, import_util.promisify)(import_child_process3.execFile);
|
|
2353
2358
|
var defaultExecFile = async (command, args) => {
|
|
2354
2359
|
const { stdout, stderr } = await execFileAsync(command, args);
|
|
@@ -2368,16 +2373,16 @@ var defaultWhich = (bin) => {
|
|
|
2368
2373
|
async function openTaskTerminal(port, planSessionId, taskId, deps = {}) {
|
|
2369
2374
|
const platform = deps.platform ?? process.platform;
|
|
2370
2375
|
const env = deps.env ?? process.env;
|
|
2371
|
-
const hasTmuxImpl = deps.hasTmuxImpl ??
|
|
2376
|
+
const hasTmuxImpl = deps.hasTmuxImpl ?? import_core14.hasTmux;
|
|
2372
2377
|
const execFileImpl = deps.execFileImpl ?? defaultExecFile;
|
|
2373
2378
|
const spawnImpl = deps.spawnImpl ?? defaultSpawn;
|
|
2374
2379
|
const which = deps.which ?? defaultWhich;
|
|
2375
2380
|
if (!hasTmuxImpl()) {
|
|
2376
2381
|
return { ok: false, message: "tmux is not installed \u2014 install it to get a real terminal per task." };
|
|
2377
2382
|
}
|
|
2378
|
-
const session = (0,
|
|
2379
|
-
const socket = (0,
|
|
2380
|
-
const base = (0,
|
|
2383
|
+
const session = (0, import_core14.tmuxSessionName)(port);
|
|
2384
|
+
const socket = (0, import_core14.tmuxSocketName)(port);
|
|
2385
|
+
const base = (0, import_core14.tmuxWindowName)(taskId, planSessionId);
|
|
2381
2386
|
let windows;
|
|
2382
2387
|
try {
|
|
2383
2388
|
const { stdout } = await execFileImpl("tmux", ["-L", socket, "list-windows", "-t", session, "-F", "#{window_name}"]);
|
|
@@ -2671,7 +2676,7 @@ Dependencies \xB7 #${task.order} ${task.title}
|
|
|
2671
2676
|
}
|
|
2672
2677
|
|
|
2673
2678
|
// src/tui/index.ts
|
|
2674
|
-
var
|
|
2679
|
+
var import_core18 = require("@ordewell/core");
|
|
2675
2680
|
|
|
2676
2681
|
// src/tui/ansi.ts
|
|
2677
2682
|
var import_string_width = __toESM(require("string-width"));
|
|
@@ -3196,6 +3201,14 @@ function planRows(state) {
|
|
|
3196
3201
|
function selectedPlanRow(state) {
|
|
3197
3202
|
return planRows(state)[state.selectedTask] ?? null;
|
|
3198
3203
|
}
|
|
3204
|
+
function findTask(tasks, id) {
|
|
3205
|
+
for (const task of tasks) {
|
|
3206
|
+
if (task.id === id) return task;
|
|
3207
|
+
const found = findTask(task.subtasks ?? [], id);
|
|
3208
|
+
if (found) return found;
|
|
3209
|
+
}
|
|
3210
|
+
return void 0;
|
|
3211
|
+
}
|
|
3199
3212
|
function initialState(overrides = {}) {
|
|
3200
3213
|
return {
|
|
3201
3214
|
editor: emptyEditor(),
|
|
@@ -3241,7 +3254,7 @@ function initialState(overrides = {}) {
|
|
|
3241
3254
|
}
|
|
3242
3255
|
|
|
3243
3256
|
// src/tui/layout.ts
|
|
3244
|
-
var
|
|
3257
|
+
var import_core15 = require("@ordewell/core");
|
|
3245
3258
|
var CHROME_ROWS = 4;
|
|
3246
3259
|
function chatInputWrap(state) {
|
|
3247
3260
|
const active = state.focus === "chat" && !state.overlay;
|
|
@@ -3253,7 +3266,7 @@ function footerHints(state) {
|
|
|
3253
3266
|
const planning = state.status === "planning" || state.status === "researching";
|
|
3254
3267
|
const escHint = planning ? "esc stop planning" : null;
|
|
3255
3268
|
if (state.focus === "plan") {
|
|
3256
|
-
if (state.
|
|
3269
|
+
if (state.taskEditor) {
|
|
3257
3270
|
return ["type to edit prompt", "pgup/pgdn scroll", "alt-enter newline", "enter save", "esc cancel"];
|
|
3258
3271
|
}
|
|
3259
3272
|
return [
|
|
@@ -3377,9 +3390,9 @@ function chatScrollMax(state) {
|
|
|
3377
3390
|
}
|
|
3378
3391
|
function plannerSetup(state) {
|
|
3379
3392
|
const provider = state.plannerProvider;
|
|
3380
|
-
const registration =
|
|
3393
|
+
const registration = import_core15.ALL_PROVIDERS[provider];
|
|
3381
3394
|
if (!registration) return { label: "not set", ready: false };
|
|
3382
|
-
const runner = (0,
|
|
3395
|
+
const runner = (0, import_core15.runnerForProvider)(provider);
|
|
3383
3396
|
const ready = runner ? state.runners.some((r) => r.id === runner) : state.configuredProviders.includes(provider);
|
|
3384
3397
|
return { label: registration.label, ready };
|
|
3385
3398
|
}
|
|
@@ -3526,7 +3539,7 @@ function taskLines(state, row, index, cols) {
|
|
|
3526
3539
|
const icon = paint(rawIcon);
|
|
3527
3540
|
const kind = running ? style.yellow("RUN") : task.type === "user" ? style.yellow("MAN") : style.grey(" AI");
|
|
3528
3541
|
const caret = selected ? style.cyan("\u276F") : " ";
|
|
3529
|
-
const orderLabel = parent ? (0,
|
|
3542
|
+
const orderLabel = parent ? (0, import_core15.taskOrderLabel)(task, parent) : String(task.order).padStart(2);
|
|
3530
3543
|
const indent = parent ? " " : "";
|
|
3531
3544
|
const head = `${indent}${caret} ${icon} ${orderLabel} ${kind} `;
|
|
3532
3545
|
const titleRoom = Math.max(1, cols - width(head));
|
|
@@ -3904,9 +3917,9 @@ function frame(title, body, rows, cols) {
|
|
|
3904
3917
|
}
|
|
3905
3918
|
|
|
3906
3919
|
// src/tui/reducer.ts
|
|
3907
|
-
var
|
|
3920
|
+
var import_core16 = require("@ordewell/core");
|
|
3908
3921
|
var import_plan_utils3 = require("@ordewell/core/plan-utils");
|
|
3909
|
-
var KNOWN_PROVIDERS2 = Object.keys(
|
|
3922
|
+
var KNOWN_PROVIDERS2 = Object.keys(import_core16.ALL_PROVIDERS);
|
|
3910
3923
|
var DEFAULT_EFFORT = "__runner_default__";
|
|
3911
3924
|
function step(state, effects = []) {
|
|
3912
3925
|
return { state, effects };
|
|
@@ -3988,7 +4001,7 @@ function reduce(state, action) {
|
|
|
3988
4001
|
case "planUpdated": {
|
|
3989
4002
|
if (stale(state, action.sessionId)) return step(state);
|
|
3990
4003
|
const tasks = normalizeTasks(action.plan);
|
|
3991
|
-
const expandedTaskId =
|
|
4004
|
+
const expandedTaskId = state.expandedTaskId && findTask(tasks, state.expandedTaskId) ? state.expandedTaskId : null;
|
|
3992
4005
|
const next = {
|
|
3993
4006
|
...state,
|
|
3994
4007
|
tasks,
|
|
@@ -4203,11 +4216,11 @@ function modelDetail(m) {
|
|
|
4203
4216
|
function providerErrorHint(state) {
|
|
4204
4217
|
const failed = Object.keys(state.providerErrors ?? {});
|
|
4205
4218
|
if (failed.length === 0) return void 0;
|
|
4206
|
-
const names = failed.map((p) =>
|
|
4219
|
+
const names = failed.map((p) => import_core16.ALL_PROVIDERS[p]?.label ?? p);
|
|
4207
4220
|
return `\u26A0 Unavailable (key or fetch failed): ${names.join(", ")} \u2014 showing working providers only.`;
|
|
4208
4221
|
}
|
|
4209
4222
|
function plannerModelItems(state) {
|
|
4210
|
-
const runner = (0,
|
|
4223
|
+
const runner = (0, import_core16.runnerForProvider)(state.plannerProvider);
|
|
4211
4224
|
if (!runner) return state.orchestratorModels.map((m) => ({ id: m.id, label: m.label, detail: modelDetail(m) }));
|
|
4212
4225
|
const items = state.models.filter((m) => m.runners?.includes(runner)).map((m) => ({
|
|
4213
4226
|
id: m.id,
|
|
@@ -4218,7 +4231,7 @@ function plannerModelItems(state) {
|
|
|
4218
4231
|
return items.length > 0 ? items : [{ id: "", label: `No ${runner} models discovered yet`, detail: "run /refresh", disabled: true }];
|
|
4219
4232
|
}
|
|
4220
4233
|
function plannerEffortItems(state) {
|
|
4221
|
-
const runner = (0,
|
|
4234
|
+
const runner = (0, import_core16.runnerForProvider)(state.plannerProvider);
|
|
4222
4235
|
if (!runner) {
|
|
4223
4236
|
return [{ id: "", label: "Thinking effort applies to a coding-agent planner", detail: "switch with /planner", disabled: true }];
|
|
4224
4237
|
}
|
|
@@ -4292,7 +4305,7 @@ function pickerItemsFor(state, action) {
|
|
|
4292
4305
|
if (action.kind === "set-task-model") {
|
|
4293
4306
|
const task = state.tasks.find((candidate) => candidate.id === action.taskId);
|
|
4294
4307
|
if (!task) return [];
|
|
4295
|
-
|
|
4308
|
+
const items = modelsForTask(state.models, task).map((model) => ({
|
|
4296
4309
|
id: model.id,
|
|
4297
4310
|
label: model.label,
|
|
4298
4311
|
detail: [
|
|
@@ -4301,6 +4314,7 @@ function pickerItemsFor(state, action) {
|
|
|
4301
4314
|
].filter(Boolean).join(" \xB7 "),
|
|
4302
4315
|
selected: model.id === task.assignedModel?.modelId
|
|
4303
4316
|
}));
|
|
4317
|
+
return items.length > 0 ? items : [{ id: "", label: `No ${task.assignedRunner ?? "runner"} models discovered yet`, detail: "run /refresh", disabled: true }];
|
|
4304
4318
|
}
|
|
4305
4319
|
if (action.kind === "set-task-effort") {
|
|
4306
4320
|
const task = state.tasks.find((candidate) => candidate.id === action.taskId);
|
|
@@ -4427,9 +4441,12 @@ function markAction(task) {
|
|
|
4427
4441
|
return task.status === "completed" ? "uncomplete" : "complete";
|
|
4428
4442
|
}
|
|
4429
4443
|
function handlePlanKey(state, key) {
|
|
4430
|
-
const editingTask = state.expandedTaskId ? state.tasks
|
|
4444
|
+
const editingTask = state.expandedTaskId ? findTask(state.tasks, state.expandedTaskId) : void 0;
|
|
4431
4445
|
if (editingTask && state.taskEditor) return handleTaskEditKey(state, editingTask, state.taskEditor, key);
|
|
4432
|
-
if (key.name === "escape")
|
|
4446
|
+
if (key.name === "escape") {
|
|
4447
|
+
if (state.expandedTaskId) return step({ ...state, expandedTaskId: null, planScroll: null });
|
|
4448
|
+
return step({ ...state, focus: "chat" });
|
|
4449
|
+
}
|
|
4433
4450
|
if (key.name === "up") {
|
|
4434
4451
|
return step({ ...state, selectedTask: Math.max(0, state.selectedTask - 1), planScroll: null });
|
|
4435
4452
|
}
|
|
@@ -4446,6 +4463,10 @@ function handlePlanKey(state, key) {
|
|
|
4446
4463
|
if (!row) return step(state);
|
|
4447
4464
|
const task = row.task;
|
|
4448
4465
|
if (key.name === "enter" || key.name === "right") {
|
|
4466
|
+
const hasSubtasks = (task.subtasks?.length ?? 0) > 0;
|
|
4467
|
+
if (hasSubtasks && state.expandedTaskId !== task.id) {
|
|
4468
|
+
return step({ ...state, expandedTaskId: task.id, taskEditor: null, planScroll: null });
|
|
4469
|
+
}
|
|
4449
4470
|
const text = task.prompt ?? task.description ?? task.title;
|
|
4450
4471
|
return step({
|
|
4451
4472
|
...state,
|
|
@@ -4856,7 +4877,7 @@ function newSession(state) {
|
|
|
4856
4877
|
}
|
|
4857
4878
|
function setModel(state, args) {
|
|
4858
4879
|
if (args[0] === "set" && args[1]) {
|
|
4859
|
-
const runner = (0,
|
|
4880
|
+
const runner = (0, import_core16.runnerForProvider)(state.plannerProvider);
|
|
4860
4881
|
const known = runner ? modelsForRunner(state.models, runner) : [];
|
|
4861
4882
|
if (runner && known.length > 0 && !known.some((m) => m.id === args[1])) {
|
|
4862
4883
|
return fail2(state, `${args[1]} was not discovered for ${runner}.`);
|
|
@@ -4878,21 +4899,21 @@ function setModel(state, args) {
|
|
|
4878
4899
|
}
|
|
4879
4900
|
function plannerItems(state) {
|
|
4880
4901
|
const installed = new Set(state.runners.map((r) => r.id));
|
|
4881
|
-
const agents =
|
|
4882
|
-
const runner = (0,
|
|
4902
|
+
const agents = import_core16.CLI_PROVIDERS.map((id) => {
|
|
4903
|
+
const runner = (0, import_core16.runnerForProvider)(id);
|
|
4883
4904
|
const ready = installed.has(runner);
|
|
4884
4905
|
return {
|
|
4885
4906
|
id,
|
|
4886
|
-
label:
|
|
4907
|
+
label: import_core16.ALL_PROVIDERS[id].label,
|
|
4887
4908
|
detail: ready ? "coding agent \xB7 no API key needed" : "CLI not installed or not on PATH",
|
|
4888
4909
|
selected: state.plannerProvider === id,
|
|
4889
4910
|
disabled: !ready
|
|
4890
4911
|
};
|
|
4891
4912
|
});
|
|
4892
|
-
const vendors =
|
|
4913
|
+
const vendors = import_core16.PROVIDER_PRIORITY.filter((id) => state.configuredProviders.includes(id)).map((id) => ({
|
|
4893
4914
|
id,
|
|
4894
|
-
label:
|
|
4895
|
-
detail:
|
|
4915
|
+
label: import_core16.ALL_PROVIDERS[id].label,
|
|
4916
|
+
detail: import_core16.ALL_PROVIDERS[id].apiKeyEnvVar,
|
|
4896
4917
|
selected: state.plannerProvider === id
|
|
4897
4918
|
}));
|
|
4898
4919
|
return vendors.length > 0 ? [...agents, ...vendors] : [...agents, { id: "", label: "No API providers configured", detail: "add a key with /key", disabled: true }];
|
|
@@ -4950,16 +4971,16 @@ function setKey(state, args) {
|
|
|
4950
4971
|
}
|
|
4951
4972
|
return step(state, [{ type: "setApiKey", provider, key: args.slice(2).join(" ") }]);
|
|
4952
4973
|
}
|
|
4953
|
-
const items =
|
|
4974
|
+
const items = import_core16.PROVIDER_PRIORITY.map((id) => ({
|
|
4954
4975
|
id,
|
|
4955
|
-
label:
|
|
4956
|
-
detail:
|
|
4976
|
+
label: import_core16.ALL_PROVIDERS[id].label,
|
|
4977
|
+
detail: import_core16.ALL_PROVIDERS[id].apiKeyEnvVar,
|
|
4957
4978
|
selected: state.configuredProviders.includes(id)
|
|
4958
4979
|
}));
|
|
4959
4980
|
return step({ ...state, overlay: { kind: "picker", picker: picker("API provider key", items, { kind: "set-key" }) } });
|
|
4960
4981
|
}
|
|
4961
4982
|
function keyPrompt(provider) {
|
|
4962
|
-
const meta =
|
|
4983
|
+
const meta = import_core16.ALL_PROVIDERS[provider];
|
|
4963
4984
|
return {
|
|
4964
4985
|
kind: "prompt",
|
|
4965
4986
|
title: `${meta.label} API key`,
|
|
@@ -5317,7 +5338,7 @@ function createApp(deps) {
|
|
|
5317
5338
|
|
|
5318
5339
|
// src/tui/effects.ts
|
|
5319
5340
|
var import_child_process4 = require("child_process");
|
|
5320
|
-
var
|
|
5341
|
+
var import_core17 = require("@ordewell/core");
|
|
5321
5342
|
var import_plan_utils4 = require("@ordewell/core/plan-utils");
|
|
5322
5343
|
var ConversationQueue = class {
|
|
5323
5344
|
tail = Promise.resolve();
|
|
@@ -5484,7 +5505,7 @@ async function perform(effect, deps) {
|
|
|
5484
5505
|
dispatch({ type: "notice", message: `Orchestrator model set to ${effect.modelId}.` });
|
|
5485
5506
|
return;
|
|
5486
5507
|
case "setPlanner": {
|
|
5487
|
-
const meta =
|
|
5508
|
+
const meta = import_core17.ALL_PROVIDERS[effect.provider];
|
|
5488
5509
|
if (!meta) throw new Error(`Unknown planner: ${effect.provider}`);
|
|
5489
5510
|
const env = { AI_PROVIDER: effect.provider };
|
|
5490
5511
|
const settings = await api.updateSettings({ env });
|
|
@@ -5496,7 +5517,7 @@ async function perform(effect, deps) {
|
|
|
5496
5517
|
});
|
|
5497
5518
|
dispatch({
|
|
5498
5519
|
type: "notice",
|
|
5499
|
-
message: `${(0,
|
|
5520
|
+
message: `${(0, import_core17.isCliProvider)(effect.provider) ? `Planning with ${meta.label} \u2014 no API key needed.` : `Planner set to ${meta.label}.`} ${plannerModelNotice(recall2)}`
|
|
5500
5521
|
});
|
|
5501
5522
|
await loadModels(deps);
|
|
5502
5523
|
return;
|
|
@@ -5508,7 +5529,7 @@ async function perform(effect, deps) {
|
|
|
5508
5529
|
dispatch({ type: "notice", message: `Planner effort set to ${effect.effort || "the runner default"}.` });
|
|
5509
5530
|
return;
|
|
5510
5531
|
case "setApiKey": {
|
|
5511
|
-
const meta =
|
|
5532
|
+
const meta = import_core17.ALL_PROVIDERS[effect.provider];
|
|
5512
5533
|
if (!meta) throw new Error(`Unknown provider: ${effect.provider}`);
|
|
5513
5534
|
await api.updateSettings({ env: { [meta.apiKeyEnvVar]: effect.key } });
|
|
5514
5535
|
deps.setEnvVar(meta.apiKeyEnvVar, effect.key);
|
|
@@ -5596,7 +5617,7 @@ function osc52(text) {
|
|
|
5596
5617
|
function copySelection(deps, text) {
|
|
5597
5618
|
if (!text) return;
|
|
5598
5619
|
const lines = text.split("\n").length;
|
|
5599
|
-
const command = (0,
|
|
5620
|
+
const command = (0, import_core17.clipboardCopyCommand)(deps.hasBin);
|
|
5600
5621
|
if (command) {
|
|
5601
5622
|
try {
|
|
5602
5623
|
(deps.pipeToClipboard ?? pipeToClipboardDefault)(command, text);
|
|
@@ -5738,7 +5759,7 @@ function onExecutionEvent(dispatch, event, sessionId) {
|
|
|
5738
5759
|
// The extension shows these in its checkpoint panel; here they are
|
|
5739
5760
|
// transcript lines, which is the TUI's equivalent surface.
|
|
5740
5761
|
case "checkpoint":
|
|
5741
|
-
dispatch({ type: "notice", message:
|
|
5762
|
+
dispatch({ type: "notice", message: `\xB7 Checkpoint \u2014 ${event.taskTitle}: ${(0, import_core17.truncateCheckpointSummary)(event.summary)}` });
|
|
5742
5763
|
return;
|
|
5743
5764
|
case "approval_decided":
|
|
5744
5765
|
dispatch({ type: "notice", message: describeApprovalDecision2(event) });
|
|
@@ -6091,7 +6112,7 @@ async function handleTui(subArgs) {
|
|
|
6091
6112
|
}
|
|
6092
6113
|
const workspace = flag(subArgs, "--workspace") || process.cwd();
|
|
6093
6114
|
try {
|
|
6094
|
-
(0,
|
|
6115
|
+
(0, import_core18.assertWorkspaceExists)(workspace);
|
|
6095
6116
|
} catch {
|
|
6096
6117
|
console.error(
|
|
6097
6118
|
`Workspace "${workspace}" does not exist.
|
|
@@ -6100,7 +6121,7 @@ cd into a directory that exists, or pass --workspace <path> naming one that does
|
|
|
6100
6121
|
);
|
|
6101
6122
|
process.exit(1);
|
|
6102
6123
|
}
|
|
6103
|
-
registerSkillCommands((0,
|
|
6124
|
+
registerSkillCommands((0, import_core18.createSkillsService)(workspace).listSkills());
|
|
6104
6125
|
const explicitPort = flag(subArgs, "--port") || process.env.ORDEWELL_PORT;
|
|
6105
6126
|
const targetPort = explicitPort ? resolvePort(subArgs) : await findFreePort();
|
|
6106
6127
|
const { port, owned: ownedAtLaunch } = await ensureDaemonOwned(targetPort, { detached: false });
|
|
@@ -6119,7 +6140,7 @@ cd into a directory that exists, or pass --workspace <path> naming one that does
|
|
|
6119
6140
|
conversationQueue,
|
|
6120
6141
|
port,
|
|
6121
6142
|
dispatch: (action) => app.dispatch(action),
|
|
6122
|
-
newSessionId: () => (0,
|
|
6143
|
+
newSessionId: () => (0, import_core18.mintSessionId)(),
|
|
6123
6144
|
setEnvVar: (key, value) => {
|
|
6124
6145
|
writeEnvVar(findEnvFile(), key, value);
|
|
6125
6146
|
process.env[key] = value;
|
|
@@ -6225,7 +6246,7 @@ function cliVersion() {
|
|
|
6225
6246
|
|
|
6226
6247
|
// src/main.ts
|
|
6227
6248
|
async function main() {
|
|
6228
|
-
(0,
|
|
6249
|
+
(0, import_core19.migrateOldConfigDir)();
|
|
6229
6250
|
loadEnvFile();
|
|
6230
6251
|
const argv = process.argv.slice(2);
|
|
6231
6252
|
const command = argv[0] ?? (process.stdin.isTTY ? "tui" : "--help");
|
package/package.json
CHANGED