@ordewell/cli 0.10.1 → 0.10.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.
Files changed (2) hide show
  1. package/dist/main.js +580 -468
  2. package/package.json +5 -3
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 import_core46 = require("@ordewell/core");
27
+ var import_core49 = require("@ordewell/core");
28
28
 
29
29
  // src/utils/env.ts
30
30
  var import_fs = require("fs");
@@ -107,6 +107,23 @@ function moveAutonomyToSettings() {
107
107
  }
108
108
  }
109
109
 
110
+ // src/runnerNames.ts
111
+ var import_core2 = require("@ordewell/core");
112
+ function manifests() {
113
+ return new import_core2.RunnerRegistry().list().map((entry) => entry.manifest);
114
+ }
115
+ function runnerIdList() {
116
+ return manifests().map((m) => m.name).join(", ");
117
+ }
118
+ function runnerIdChoice() {
119
+ return manifests().map((m) => m.name).join("|");
120
+ }
121
+ function runnerNamesOr() {
122
+ const names = manifests().map((m) => m.displayName);
123
+ if (names.length < 2) return names.join("");
124
+ return `${names.slice(0, -1).join(", ")} or ${names[names.length - 1]}`;
125
+ }
126
+
110
127
  // src/help.ts
111
128
  function printHelp() {
112
129
  console.log(`
@@ -157,7 +174,7 @@ Planner, models and runners:
157
174
  ordewell model [set <id>] Show or set the planner model (applies without a restart)
158
175
  ordewell planner-effort [lvl] Thinking effort for a coding-agent planner
159
176
  ordewell key [set <p> <key>] Show which providers have a key, or store one
160
- ordewell runners [<id> on|off] Enable or disable runners (claude-code, opencode, codex)
177
+ ordewell runners [<id> on|off] Enable or disable runners (${runnerIdList()})
161
178
  ordewell allowlist set|clear|show Limit which models a runner may use
162
179
  ordewell auto [full|guarded] Autonomy level for new plans: Full or Guarded
163
180
  ordewell supervisor [off|watch|act] Whether the planner watches or acts on your runs (default watch);
@@ -236,13 +253,13 @@ Quick Start:
236
253
  then run: ordewell plan --goal "Your task description"
237
254
 
238
255
  No API key? Plan with a coding agent you already pay for:
239
- AI_PROVIDER=claude-code ordewell plan --goal "Your task description"
256
+ AI_PROVIDER=<runner> ordewell plan --goal "Your task description"
240
257
 
241
258
  Environment:
242
259
  OPENROUTER_API_KEY OpenRouter API key (recommended)
243
260
  GEMINI_API_KEY Google Gemini API key (alternative)
244
261
  AI_PROVIDER openrouter, google \u2014 auto-detected from keys
245
- claude-code, codex, opencode \u2014 plan with that CLI,
262
+ ${runnerIdList()} \u2014 plan with that CLI,
246
263
  no API key (uses its own subscription)
247
264
  ORDEWELL_PLANNER_EFFORT Thinking effort for a coding-agent planner
248
265
  ORCHESTRATOR_MODEL Default: deepseek/deepseek-v4-flash
@@ -275,9 +292,9 @@ var import_os = require("os");
275
292
  var import_path2 = require("path");
276
293
  var import_http = __toESM(require("http"));
277
294
  var import_net = require("net");
278
- var import_core2 = require("@ordewell/core");
295
+ var import_core3 = require("@ordewell/core");
279
296
  var DEFAULT_PORT = 3742;
280
- var CONFIG_DIR = (0, import_core2.globalDataDir)();
297
+ var CONFIG_DIR = (0, import_core3.globalDataDir)();
281
298
  var LEGACY_PID_FILE = (0, import_path2.join)(CONFIG_DIR, "server.pid");
282
299
  var OLD_CONFIG_DIR = (0, import_path2.join)((0, import_os.homedir)(), ".config", "ordewell");
283
300
  function pidFileFor(port) {
@@ -317,12 +334,12 @@ function getWebServerPath() {
317
334
  );
318
335
  }
319
336
  async function isDaemonRunning(port = DEFAULT_PORT) {
320
- const token = (0, import_core2.readDaemonToken)(port);
337
+ const token = (0, import_core3.readDaemonToken)(port);
321
338
  try {
322
339
  const res = await httpGet(
323
340
  `http://127.0.0.1:${port}/api/workspaces`,
324
341
  2e3,
325
- token ? { Authorization: (0, import_core2.bearerHeaderValue)(token) } : {}
342
+ token ? { Authorization: (0, import_core3.bearerHeaderValue)(token) } : {}
326
343
  );
327
344
  return res.status === 200 || res.status === 401;
328
345
  } catch {
@@ -378,7 +395,7 @@ async function stopDaemon(port = DEFAULT_PORT) {
378
395
  const pid = parseInt(pidStr, 10);
379
396
  if (!pid || isNaN(pid)) {
380
397
  (0, import_fs2.unlinkSync)(pidFile);
381
- (0, import_core2.clearDaemonToken)(port);
398
+ (0, import_core3.clearDaemonToken)(port);
382
399
  return false;
383
400
  }
384
401
  process.kill(pid, "SIGTERM");
@@ -391,7 +408,7 @@ async function stopDaemon(port = DEFAULT_PORT) {
391
408
  (0, import_fs2.unlinkSync)(pidFile);
392
409
  } catch {
393
410
  }
394
- (0, import_core2.clearDaemonToken)(port);
411
+ (0, import_core3.clearDaemonToken)(port);
395
412
  console.log("Server was not running (stale PID removed).");
396
413
  return true;
397
414
  }
@@ -444,7 +461,7 @@ function resolvePort(args = []) {
444
461
  // src/apiClient.ts
445
462
  var import_http2 = __toESM(require("http"));
446
463
  var import_ws = __toESM(require("ws"));
447
- var import_core3 = require("@ordewell/core");
464
+ var import_core4 = require("@ordewell/core");
448
465
  var DEFAULT_HTTP_TIMEOUT_MS = 15 * 60 * 1e3;
449
466
  var DaemonError = class extends Error {
450
467
  constructor(message, status, code) {
@@ -488,7 +505,7 @@ var ApiClient = class _ApiClient {
488
505
  * A missing file is not an error here — the daemon's own 401 names the path.
489
506
  */
490
507
  token() {
491
- return (0, import_core3.readDaemonToken)(this.port);
508
+ return (0, import_core4.readDaemonToken)(this.port);
492
509
  }
493
510
  /**
494
511
  * A daemon holds only the sessions adopted since it started, so after a
@@ -524,7 +541,7 @@ var ApiClient = class _ApiClient {
524
541
  method,
525
542
  headers: {
526
543
  ...body ? { "Content-Type": "application/json" } : {},
527
- ...token ? { Authorization: (0, import_core3.bearerHeaderValue)(token) } : {}
544
+ ...token ? { Authorization: (0, import_core4.bearerHeaderValue)(token) } : {}
528
545
  },
529
546
  // Planner research on a real repository regularly exceeds two minutes.
530
547
  // The benchmark harness uses the same 15-minute default explicitly;
@@ -554,7 +571,7 @@ var ApiClient = class _ApiClient {
554
571
  req.end();
555
572
  });
556
573
  }
557
- async generatePlan(goal, runners2, workspace, sessionId = (0, import_core3.mintSessionId)()) {
574
+ async generatePlan(goal, runners2, workspace, sessionId = (0, import_core4.mintSessionId)()) {
558
575
  const { plan, models, modelsByRunner, notes } = await this.call("POST", `/api/plans/${sessionId}/generate`, "Plan generation failed", {
559
576
  goal,
560
577
  runners: runners2 || void 0,
@@ -789,7 +806,7 @@ var ApiClient = class _ApiClient {
789
806
  const token = this.token();
790
807
  const socket = new import_ws.default(
791
808
  `ws://127.0.0.1:${this.port}/ws/session/${sessionId}`,
792
- token ? (0, import_core3.tokenSubprotocols)(token) : void 0
809
+ token ? (0, import_core4.tokenSubprotocols)(token) : void 0
793
810
  );
794
811
  socket.on("unexpected-response", (_req, res) => {
795
812
  const chunks = [];
@@ -1012,15 +1029,15 @@ function positionals(args) {
1012
1029
  }
1013
1030
 
1014
1031
  // src/utils/tasks.ts
1015
- var import_core4 = require("@ordewell/core");
1032
+ var import_core5 = require("@ordewell/core");
1016
1033
  function allTasksOf(plan) {
1017
1034
  const tasks = plan?.pendingTasks || plan?.tasks || [];
1018
1035
  const executionLog = plan?.executionLog || [];
1019
- return (0, import_core4.rejoinPlanTree)(tasks, executionLog);
1036
+ return (0, import_core5.rejoinPlanTree)(tasks, executionLog);
1020
1037
  }
1021
1038
  function resolveTaskId(plan, identifier) {
1022
1039
  const allTasks = allTasksOf(plan);
1023
- const byRef = (0, import_core4.resolveTaskRef)(allTasks, identifier);
1040
+ const byRef = (0, import_core5.resolveTaskRef)(allTasks, identifier);
1024
1041
  if (byRef) return byRef.id;
1025
1042
  const prefixMatches = allTasks.filter((t) => typeof t.id === "string" && t.id.startsWith(identifier));
1026
1043
  if (prefixMatches.length === 1) return prefixMatches[0].id;
@@ -1030,13 +1047,13 @@ function resolveTaskId(plan, identifier) {
1030
1047
  // src/utils/session.ts
1031
1048
  var import_fs3 = require("fs");
1032
1049
  var import_path3 = require("path");
1033
- var import_core5 = require("@ordewell/core");
1050
+ var import_core6 = require("@ordewell/core");
1034
1051
  var LAST_SESSION_FILENAME = "last-session.json";
1035
1052
  function lastSessionFile(workspace) {
1036
- return (0, import_path3.join)((0, import_core5.getStateDir)(workspace), LAST_SESSION_FILENAME);
1053
+ return (0, import_path3.join)((0, import_core6.getStateDir)(workspace), LAST_SESSION_FILENAME);
1037
1054
  }
1038
1055
  function saveLastSession(sessionId, goal, runners2, workspace) {
1039
- const dir = (0, import_core5.getStateDir)(workspace);
1056
+ const dir = (0, import_core6.getStateDir)(workspace);
1040
1057
  if (!(0, import_fs3.existsSync)(dir)) (0, import_fs3.mkdirSync)(dir, { recursive: true });
1041
1058
  (0, import_fs3.writeFileSync)(
1042
1059
  lastSessionFile(workspace),
@@ -1058,14 +1075,14 @@ function expandSessionId(id, workspace) {
1058
1075
  if (id.startsWith(SESSION_PREFIX)) return id;
1059
1076
  let files;
1060
1077
  try {
1061
- files = (0, import_fs3.readdirSync)((0, import_path3.join)((0, import_core5.getStateDir)(workspace), "sessions")).filter((f) => f.endsWith(".json"));
1078
+ files = (0, import_fs3.readdirSync)((0, import_path3.join)((0, import_core6.getStateDir)(workspace), "sessions")).filter((f) => f.endsWith(".json"));
1062
1079
  } catch {
1063
1080
  return id;
1064
1081
  }
1065
1082
  const matches = /* @__PURE__ */ new Set();
1066
1083
  for (const file of files) {
1067
1084
  try {
1068
- const full = JSON.parse((0, import_fs3.readFileSync)((0, import_path3.join)((0, import_core5.getStateDir)(workspace), "sessions", file), "utf8"))?.meta?.id;
1085
+ const full = JSON.parse((0, import_fs3.readFileSync)((0, import_path3.join)((0, import_core6.getStateDir)(workspace), "sessions", file), "utf8"))?.meta?.id;
1069
1086
  if (typeof full === "string" && (full.endsWith(id) || full.slice(SESSION_PREFIX.length).startsWith(id))) matches.add(full);
1070
1087
  } catch {
1071
1088
  }
@@ -1136,7 +1153,7 @@ ${describeApproval(event)}
1136
1153
  }
1137
1154
 
1138
1155
  // src/commands/researchLog.ts
1139
- var import_core6 = require("@ordewell/core");
1156
+ var import_core7 = require("@ordewell/core");
1140
1157
  var OUTCOME_MARK = {
1141
1158
  success: "\u2713",
1142
1159
  failure: "\u2717",
@@ -1148,7 +1165,7 @@ var RESULT_CHARS = 160;
1148
1165
  var VERBOSE_RESULT_CHARS = 600;
1149
1166
  var THINKING_CHARS = 300;
1150
1167
  function summarize(tool, args, toolLabel) {
1151
- const { name, keyArg } = (0, import_core6.toolHeadline)(tool, args, toolLabel);
1168
+ const { name, keyArg } = (0, import_core7.toolHeadline)(tool, args, toolLabel);
1152
1169
  return `${name}(${keyArg})`;
1153
1170
  }
1154
1171
  function oneLine(text, max) {
@@ -1198,7 +1215,7 @@ function createStepLog(options = {}) {
1198
1215
  }
1199
1216
 
1200
1217
  // src/commands/plan.ts
1201
- var import_core7 = require("@ordewell/core");
1218
+ var import_core8 = require("@ordewell/core");
1202
1219
  function planTasks(plan) {
1203
1220
  return plan ? allTasksOf(plan) : [];
1204
1221
  }
@@ -1282,11 +1299,11 @@ Plan: ${tasks.length} task${tasks.length === 1 ? "" : "s"} (${aiCount} AI, ${man
1282
1299
  for (const t of tasks) {
1283
1300
  const typeIcon = t.type === "user" ? "[MAN]" : t.ops ? "[OPS]" : "[ AI]";
1284
1301
  const deps = t.dependencies?.length ? ` \u2190 ${t.dependencies.join(", ")}` : "";
1285
- console.log(` ${(0, import_core7.taskOrderLabel)(t).padStart(2)}. ${typeIcon} ${t.title}${modelSuffix(t)}${deps}`);
1302
+ console.log(` ${(0, import_core8.taskOrderLabel)(t).padStart(2)}. ${typeIcon} ${t.title}${modelSuffix(t)}${deps}`);
1286
1303
  for (const sub of t.subtasks || []) {
1287
1304
  const subTypeIcon = sub.type === "user" ? "[MAN]" : "[ AI]";
1288
1305
  const subDeps = sub.dependencies?.length ? ` \u2190 ${sub.dependencies.join(", ")}` : "";
1289
- console.log(` ${(0, import_core7.taskOrderLabel)(sub, t)}. ${subTypeIcon} ${sub.title}${modelSuffix(sub)}${subDeps}`);
1306
+ console.log(` ${(0, import_core8.taskOrderLabel)(sub, t)}. ${subTypeIcon} ${sub.title}${modelSuffix(sub)}${subDeps}`);
1290
1307
  }
1291
1308
  }
1292
1309
  if (manCount > 0) {
@@ -1336,7 +1353,7 @@ async function handlePlan(subArgs, deps = {}) {
1336
1353
  runners2 = runnerFlags;
1337
1354
  }
1338
1355
  console.error(`Generating plan for: "${goal}"...`);
1339
- const sessionId = (0, import_core7.mintSessionId)();
1356
+ const sessionId = (0, import_core8.mintSessionId)();
1340
1357
  const isTty = !!process.stderr.isTTY;
1341
1358
  let lastLineLength = 0;
1342
1359
  const stepLog = createStepLog({ verbose });
@@ -1442,7 +1459,7 @@ ${note}`);
1442
1459
  }
1443
1460
 
1444
1461
  // src/isolation.ts
1445
- var import_core8 = require("@ordewell/core");
1462
+ var import_core9 = require("@ordewell/core");
1446
1463
  var STATE_OF = {
1447
1464
  active: "active",
1448
1465
  merged: "integrated",
@@ -1526,9 +1543,9 @@ function repairedLanded(handoff) {
1526
1543
  function repairedNotice(handoff) {
1527
1544
  const repaired = repairedLanded(handoff);
1528
1545
  if (repaired.length === 0) return "";
1529
- const named = repaired.map((t) => `${t.title} (${(0, import_core8.capConflictFiles)(t.repairedFiles)})`);
1530
- const list = named.length === 1 ? named[0] : `${named.slice(0, -1).join(", ")} and ${named[named.length - 1]}`;
1531
- return ` ${list} landed through ${repaired.length === 1 ? "a conflict repair" : "conflict repairs"}.`;
1546
+ const named = repaired.map((t) => `${t.title} (${(0, import_core9.capConflictFiles)(t.repairedFiles)})`);
1547
+ const list2 = named.length === 1 ? named[0] : `${named.slice(0, -1).join(", ")} and ${named[named.length - 1]}`;
1548
+ return ` ${list2} landed through ${repaired.length === 1 ? "a conflict repair" : "conflict repairs"}.`;
1532
1549
  }
1533
1550
  function repoResultLines(handoff) {
1534
1551
  return handoff.repos.map(({ path, landed }) => {
@@ -1541,14 +1558,14 @@ function mergeOutcome(result, branch, group, repaired = []) {
1541
1558
  if (!group && result.outcome === "conflict") {
1542
1559
  return { ok, message: `Merging ${branch} conflicted, so it was aborted \u2014 your tree is as it was. Merge it with git and resolve the conflict there.` };
1543
1560
  }
1544
- const { message } = (0, import_core8.describeMergeResult)(result, branch, group, repaired);
1561
+ const { message } = (0, import_core9.describeMergeResult)(result, branch, group, repaired);
1545
1562
  return { ok, message: ok || !group ? message : `${message} Each repository's ${branch} is a plain branch you can merge by hand.` };
1546
1563
  }
1547
1564
 
1548
1565
  // src/utils/output.ts
1549
- var import_core9 = require("@ordewell/core");
1566
+ var import_core10 = require("@ordewell/core");
1550
1567
  function iconFor(status) {
1551
- switch ((0, import_core9.taskStatusKind)({ status })) {
1568
+ switch ((0, import_core10.taskStatusKind)({ status })) {
1552
1569
  case "done":
1553
1570
  return "\x1B[32m\u2713\x1B[0m";
1554
1571
  case "running":
@@ -1568,7 +1585,7 @@ function iconFor(status) {
1568
1585
  }
1569
1586
 
1570
1587
  // src/commands/run.ts
1571
- var import_core10 = require("@ordewell/core");
1588
+ var import_core11 = require("@ordewell/core");
1572
1589
 
1573
1590
  // src/commands/shared.ts
1574
1591
  var import_readline2 = require("readline");
@@ -1727,11 +1744,11 @@ async function followExecution(api, sessionId, start, onBlocked) {
1727
1744
  });
1728
1745
  const stream = api.streamExecution(sessionId, (event) => {
1729
1746
  if (event.type === "task_started") {
1730
- process.stderr.write(`\xB7 ${(0, import_core10.taskStartedNotice)(event.title, event.runner)}
1747
+ process.stderr.write(`\xB7 ${(0, import_core11.taskStartedNotice)(event.title, event.runner)}
1731
1748
  `);
1732
1749
  }
1733
1750
  if (event.type === "checkpoint") {
1734
- process.stderr.write(`\xB7 Checkpoint \u2014 ${event.taskTitle}: ${(0, import_core10.truncateCheckpointSummary)(event.summary)} \u2014 \`ordewell checkpoint <id> approve|reject [reason]\` answers it
1751
+ process.stderr.write(`\xB7 Checkpoint \u2014 ${event.taskTitle}: ${(0, import_core11.truncateCheckpointSummary)(event.summary)} \u2014 \`ordewell checkpoint <id> approve|reject [reason]\` answers it
1735
1752
  `);
1736
1753
  }
1737
1754
  if (event.type === "status_update" && event.tasks) {
@@ -1812,7 +1829,7 @@ async function handleRun(subArgs, injectedApi) {
1812
1829
  }
1813
1830
 
1814
1831
  // src/tui/blocks.ts
1815
- var import_core11 = require("@ordewell/core");
1832
+ var import_core13 = require("@ordewell/core");
1816
1833
 
1817
1834
  // src/tui/ansi.ts
1818
1835
  var import_string_width = __toESM(require("string-width"));
@@ -2027,94 +2044,191 @@ var style = {
2027
2044
  };
2028
2045
 
2029
2046
  // src/tui/markdown.ts
2047
+ var import_core12 = require("@ordewell/core");
2030
2048
  function renderMarkdown(source, cols) {
2031
- const lines = source.replace(/\r/g, "").replace(/^\n+|\n+$/g, "").split("\n");
2049
+ return blocks((0, import_core12.markdownTokens)(source), { room: Math.max(1, cols), base: [] });
2050
+ }
2051
+ function closeOf(tokens, open) {
2052
+ const { level } = tokens[open];
2053
+ for (let i = open + 1; i < tokens.length; i += 1) {
2054
+ if (tokens[i].nesting === -1 && tokens[i].level === level) return i;
2055
+ }
2056
+ return tokens.length - 1;
2057
+ }
2058
+ function lastLine(tokens) {
2059
+ let last = null;
2060
+ for (const token of tokens) {
2061
+ if (token.nesting === 0 && token.map && (last === null || token.map[1] > last)) last = token.map[1];
2062
+ }
2063
+ return last ?? tokens[0]?.map?.[1] ?? null;
2064
+ }
2065
+ function blocks(tokens, ctx) {
2032
2066
  const out = [];
2033
- let inCodeBlock = false;
2034
- for (let i = 0; i < lines.length; i += 1) {
2035
- const line = lines[i];
2036
- if (/^\s*```/.test(line)) {
2037
- inCodeBlock = !inCodeBlock;
2038
- continue;
2039
- }
2040
- if (inCodeBlock) {
2041
- out.push(...wrap(style.grey(` ${line}`), cols));
2042
- continue;
2043
- }
2044
- const table = tableAt(lines, i);
2045
- if (table) {
2046
- out.push(...renderTable(table.headers, table.rows, cols));
2047
- i = table.end;
2048
- continue;
2049
- }
2050
- const heading = line.match(/^\s{0,3}(#{1,6})\s+(.+?)\s*#*\s*$/);
2051
- if (heading) {
2052
- const paint = heading[1].length <= 2 ? (text) => style.bold(style.brand(text)) : style.bold;
2053
- out.push(...wrap(paint(inline(heading[2])), cols));
2054
- continue;
2055
- }
2056
- if (/^\s{0,3}(?:[-*_]\s*){3,}$/.test(line)) {
2057
- out.push(style.grey("\u2500".repeat(Math.max(1, cols))));
2058
- continue;
2059
- }
2060
- const bullet = line.match(/^(\s*)[-*+]\s+(.+)$/);
2061
- if (bullet) {
2062
- out.push(...wrap(`${bullet[1]}\u2022 ${inline(bullet[2])}`, cols));
2063
- continue;
2064
- }
2065
- const quote = line.match(/^\s*>\s?(.*)$/);
2066
- if (quote) {
2067
- out.push(...wrap(style.grey(`\u2502 ${inline(quote[1])}`), cols));
2068
- continue;
2069
- }
2070
- out.push(...wrap(inline(line), cols));
2067
+ let previousEnd = null;
2068
+ for (let i = 0; i < tokens.length; i += 1) {
2069
+ const token = tokens[i];
2070
+ if (token.nesting === -1) continue;
2071
+ const end = token.nesting === 1 ? closeOf(tokens, i) : i;
2072
+ const children = tokens.slice(i + 1, end);
2073
+ const lines = block(token, children, ctx);
2074
+ const last = lastLine([token, ...children]);
2075
+ i = end;
2076
+ if (lines === null) continue;
2077
+ const start = token.map?.[0] ?? null;
2078
+ if (previousEnd !== null && start !== null && start > previousEnd && out.length > 0) out.push("");
2079
+ previousEnd = last ?? previousEnd;
2080
+ out.push(...lines);
2071
2081
  }
2072
2082
  return out;
2073
2083
  }
2074
- function tableAt(lines, start) {
2075
- if (!lines[start]?.includes("|") || !isTableRule(lines[start + 1] ?? "")) return null;
2076
- const headers = tableCells(lines[start]);
2077
- if (headers.length < 2) return null;
2078
- const rows = [];
2079
- let end = start + 1;
2080
- for (let i = start + 2; i < lines.length && lines[i].includes("|"); i += 1) {
2081
- const cells2 = tableCells(lines[i]);
2082
- if (cells2.length !== headers.length) break;
2083
- rows.push(cells2);
2084
- end = i;
2084
+ function block(token, children, ctx) {
2085
+ switch (token.type) {
2086
+ case "paragraph_open":
2087
+ return wrap(inline(children[0]?.children ?? [], ctx.base, "\n"), ctx.room);
2088
+ case "heading_open": {
2089
+ const level = Number(token.tag.slice(1));
2090
+ const base = level <= 2 ? [style.bold, style.brand] : [style.bold];
2091
+ return wrap(inline(children[0]?.children ?? [], [...ctx.base, ...base], "\n"), ctx.room);
2092
+ }
2093
+ case "fence":
2094
+ case "code_block":
2095
+ return token.content.replace(/\n$/, "").split("\n").flatMap((line) => wrap(` ${line}`, ctx.room)).map(style.grey);
2096
+ case "hr":
2097
+ return [style.grey("\u2500".repeat(ctx.room))];
2098
+ case "blockquote_open": {
2099
+ const inner = blocks(children, { room: Math.max(1, ctx.room - 2), base: [...ctx.base, style.grey] });
2100
+ return inner.map((line) => `${style.grey("\u2502")} ${line}`);
2101
+ }
2102
+ case "bullet_list_open":
2103
+ return list(children, ctx, () => "\u2022");
2104
+ case "ordered_list_open": {
2105
+ const start = Number(token.attrs?.find(([name]) => name === "start")?.[1] ?? 1);
2106
+ let n = start - 1;
2107
+ return list(children, ctx, (item) => {
2108
+ n += 1;
2109
+ return `${item.info || n}${item.markup || "."}`;
2110
+ });
2111
+ }
2112
+ case "table_open":
2113
+ return table(children, ctx);
2114
+ default:
2115
+ return null;
2085
2116
  }
2086
- return { headers, rows, end };
2087
2117
  }
2088
- function isTableRule(line) {
2089
- const cells2 = tableCells(line);
2090
- return cells2.length >= 2 && cells2.every((cell) => /^:?-{3,}:?$/.test(cell));
2118
+ function list(items, ctx, marker2) {
2119
+ const out = [];
2120
+ let previousEnd = null;
2121
+ for (let i = 0; i < items.length; i += 1) {
2122
+ const item = items[i];
2123
+ if (item.type !== "list_item_open") continue;
2124
+ const end = closeOf(items, i);
2125
+ const mark = marker2(item);
2126
+ const hang = " ".repeat(width(mark) + 1);
2127
+ const content = items.slice(i + 1, end);
2128
+ const inner = blocks(content, { ...ctx, room: Math.max(1, ctx.room - hang.length) });
2129
+ i = end;
2130
+ const start = item.map?.[0] ?? null;
2131
+ if (previousEnd !== null && start !== null && start > previousEnd) out.push("");
2132
+ previousEnd = lastLine(content) ?? previousEnd;
2133
+ (inner.length > 0 ? inner : [""]).forEach((line, row) => out.push(row === 0 ? `${mark} ${line}` : line && `${hang}${line}`));
2134
+ }
2135
+ return out;
2091
2136
  }
2092
- function tableCells(line) {
2093
- return line.trim().replace(/^\||\|$/g, "").split("|").map((cell) => cell.trim());
2137
+ function inline(tokens, base, lineBreak) {
2138
+ const active = [...base];
2139
+ const paint = (text) => text.split(" ").map((word) => word ? active.reduce((acc, apply) => apply(acc), word) : word).join(" ");
2140
+ let out = "";
2141
+ let href = null;
2142
+ let linkText = "";
2143
+ const emit = (text) => {
2144
+ out += paint(text);
2145
+ if (href !== null) linkText += text;
2146
+ };
2147
+ for (const token of tokens) {
2148
+ switch (token.type) {
2149
+ case "text":
2150
+ case "image":
2151
+ emit(token.content);
2152
+ break;
2153
+ case "code_inline":
2154
+ active.push(style.brand);
2155
+ emit(token.content);
2156
+ active.pop();
2157
+ break;
2158
+ case "softbreak":
2159
+ case "hardbreak":
2160
+ out += lineBreak;
2161
+ break;
2162
+ case "strong_open":
2163
+ active.push(style.bold);
2164
+ break;
2165
+ case "em_open":
2166
+ active.push(style.italic);
2167
+ break;
2168
+ case "s_open":
2169
+ active.push(style.dim);
2170
+ break;
2171
+ case "link_open":
2172
+ href = token.attrs?.find(([name]) => name === "href")?.[1] ?? null;
2173
+ linkText = "";
2174
+ if (href !== null) active.push(style.underline);
2175
+ break;
2176
+ case "link_close":
2177
+ if (href !== null) {
2178
+ active.pop();
2179
+ if (linkText !== href) out += paint(" ") + style.grey(`(${href})`);
2180
+ }
2181
+ href = null;
2182
+ break;
2183
+ case "strong_close":
2184
+ case "em_close":
2185
+ case "s_close":
2186
+ active.pop();
2187
+ break;
2188
+ default:
2189
+ if (token.content) emit(token.content);
2190
+ }
2191
+ }
2192
+ return out;
2193
+ }
2194
+ function table(tokens, ctx) {
2195
+ const headers = [];
2196
+ const rows = [];
2197
+ let inHead = false;
2198
+ let row = null;
2199
+ for (const token of tokens) {
2200
+ if (token.type === "thead_open") inHead = true;
2201
+ else if (token.type === "thead_close") inHead = false;
2202
+ else if (token.type === "tr_open") row = [];
2203
+ else if (token.type === "tr_close" && row) {
2204
+ if (inHead) headers.push(...row);
2205
+ else rows.push(row);
2206
+ row = null;
2207
+ } else if (token.type === "inline" && row) {
2208
+ row.push(inline(token.children ?? [], inHead ? [style.bold] : [], " "));
2209
+ }
2210
+ }
2211
+ return renderTable(headers, rows, ctx.room);
2094
2212
  }
2095
2213
  function renderTable(headers, rows, cols) {
2096
2214
  const separator = " \u2502 ";
2097
2215
  const separatorWidth = width(separator);
2098
2216
  const available = Math.max(headers.length, cols - separatorWidth * (headers.length - 1));
2099
2217
  const natural = headers.map(
2100
- (header, column) => Math.max(width(inline(header)), ...rows.map((row) => width(inline(row[column] ?? ""))))
2218
+ (header, column) => Math.max(width(header), ...rows.map((row) => width(row[column] ?? "")))
2101
2219
  );
2102
2220
  const columnWidths = fitTableColumns(natural, available);
2103
- if (columnWidths.some((size) => size < 4)) return renderStackedTable(headers, rows, cols);
2104
- const renderRow = (cells2, paint = (text) => text) => {
2105
- const wrapped = cells2.map((cell, index) => wrap(inline(cell), columnWidths[index]));
2221
+ if (columnWidths.some((size, index) => size < Math.min(4, natural[index]))) return renderRecords(headers, rows, cols);
2222
+ const renderRow = (cells2) => {
2223
+ const wrapped = headers.map((_, index) => wrap(cells2[index] ?? "", columnWidths[index]));
2106
2224
  const height = Math.max(...wrapped.map((cell) => cell.length));
2107
2225
  return Array.from(
2108
2226
  { length: height },
2109
- (_, line) => wrapped.map((cell, column) => pad(paint(cell[line] ?? ""), columnWidths[column])).join(separator)
2227
+ (_, line) => wrapped.map((cell, column) => pad(cell[line] ?? "", columnWidths[column])).join(separator)
2110
2228
  );
2111
2229
  };
2112
2230
  const rule = columnWidths.map((size) => style.grey("\u2500".repeat(size))).join(style.grey("\u2500\u253C\u2500"));
2113
- return [
2114
- ...renderRow(headers, style.bold),
2115
- rule,
2116
- ...rows.flatMap((row) => renderRow(row))
2117
- ];
2231
+ return [...renderRow(headers), rule, ...rows.flatMap(renderRow)];
2118
2232
  }
2119
2233
  function fitTableColumns(natural, available) {
2120
2234
  const widths = [...natural];
@@ -2127,15 +2241,12 @@ function fitTableColumns(natural, available) {
2127
2241
  }
2128
2242
  return widths;
2129
2243
  }
2130
- function renderStackedTable(headers, rows, cols) {
2244
+ function renderRecords(headers, rows, cols) {
2131
2245
  return rows.flatMap((row, rowIndex) => [
2132
- ...rowIndex === 0 ? [] : [""],
2133
- ...row.flatMap((cell, column) => wrap(`${style.bold(inline(headers[column]))}: ${inline(cell)}`, cols))
2246
+ ...rowIndex === 0 ? [] : [style.grey("\u2500".repeat(cols))],
2247
+ ...headers.flatMap((header, column) => wrap(`${header}: ${row[column] ?? ""}`, cols))
2134
2248
  ]);
2135
2249
  }
2136
- function inline(text) {
2137
- return text.replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/\[([^\]]+)\]\(([^\s)]+)(?:\s+[^)]*)?\)/g, "$1 ($2)").replace(/\*\*([^*]+)\*\*/g, (_, bold) => style.bold(bold)).replace(/__([^_]+)__/g, (_, bold) => style.bold(bold)).replace(/(^|[^\w])\*([^*]+)\*(?![\w*])/g, (_, prefix, italic) => `${prefix}${style.italic(italic)}`).replace(/(^|[^\w])_([^_]+)_(?![\w_])/g, (_, prefix, italic) => `${prefix}${style.italic(italic)}`).replace(/`([^`]+)`/g, (_, code) => style.brand(code));
2138
- }
2139
2250
 
2140
2251
  // src/tui/blocks.ts
2141
2252
  function countOf(n, noun) {
@@ -2168,25 +2279,25 @@ var ROLE_CONTINUATION = {
2168
2279
  error: style.red,
2169
2280
  wake_up: style.yellow
2170
2281
  };
2171
- function messageLines(block, cols) {
2172
- const text = sanitize(block.text);
2282
+ function messageLines(block2, cols) {
2283
+ const text = sanitize(block2.text);
2173
2284
  const room = Math.max(1, cols - 2);
2174
- const wrapped = block.role === "planner" || block.role === "agent" || block.role === "supervisor" ? renderMarkdown(text, room) : block.skills ? skillPaintedLines(text, block.skills, room) : wrap(text, room);
2175
- const rest = ROLE_CONTINUATION[block.role] ?? ((t) => t);
2176
- const rows = wrapped.map((line, i) => i === 0 ? ROLE_PREFIX[block.role](line) : rest(` ${line}`));
2177
- if (block.role === "user" && block.forced) {
2285
+ const wrapped = block2.role === "planner" || block2.role === "agent" || block2.role === "supervisor" ? renderMarkdown(text, room) : block2.skills ? skillPaintedLines(text, block2.skills, room) : wrap(text, room);
2286
+ const rest = ROLE_CONTINUATION[block2.role] ?? ((t) => t);
2287
+ const rows = wrapped.map((line, i) => i === 0 ? ROLE_PREFIX[block2.role](line) : rest(` ${line}`));
2288
+ if (block2.role === "user" && block2.forced) {
2178
2289
  const note = style.grey(" \xB7 sent now");
2179
2290
  if (width(rows[0]) + width(note) <= cols) rows[0] += note;
2180
2291
  else rows.push(` ${note}`);
2181
2292
  }
2182
- return block.role === "user" ? onBand(rows, cols) : rows;
2293
+ return block2.role === "user" ? onBand(rows, cols) : rows;
2183
2294
  }
2184
2295
  function onBand(rows, cols) {
2185
2296
  const band = ["", ...rows, ""];
2186
2297
  return style.enabled ? band.map((row) => style.band(pad(row, cols))) : band;
2187
2298
  }
2188
2299
  function skillPaintedLines(text, skills, room) {
2189
- const tokens = (0, import_core11.loadedSkillTokens)(text, skills);
2300
+ const tokens = (0, import_core13.loadedSkillTokens)(text, skills);
2190
2301
  return wrapLines(text, room).map(({ line, start }) => {
2191
2302
  let painted = "";
2192
2303
  let at = 0;
@@ -2200,19 +2311,19 @@ function skillPaintedLines(text, skills, room) {
2200
2311
  return painted + line.slice(at);
2201
2312
  });
2202
2313
  }
2203
- function skillLoadLine(block, cols) {
2204
- const head = block.attaches ? `\u25CF /${sanitize(block.name)} will be attached to fitting tasks \xB7 ` : block.invokedBy === "planner" ? `\u25CF ${sanitize(block.name)} skill loaded by planner \xB7 ` : `\u25CF /${sanitize(block.name)} skill loaded \xB7 `;
2205
- const line = truncate(`${head}${truncatePath(sanitize(block.path), Math.max(1, cols - width(head)))}`, cols);
2314
+ function skillLoadLine(block2, cols) {
2315
+ const head = block2.attaches ? `\u25CF /${sanitize(block2.name)} will be attached to fitting tasks \xB7 ` : block2.invokedBy === "planner" ? `\u25CF ${sanitize(block2.name)} skill loaded by planner \xB7 ` : `\u25CF /${sanitize(block2.name)} skill loaded \xB7 `;
2316
+ const line = truncate(`${head}${truncatePath(sanitize(block2.path), Math.max(1, cols - width(head)))}`, cols);
2206
2317
  return `${style.green("\u25CF")}${style.grey(line.slice(1))}`;
2207
2318
  }
2208
- function thinkingLines(block, cols, detailAll) {
2209
- const text = sanitize(block.text).trim();
2319
+ function thinkingLines(block2, cols, detailAll) {
2320
+ const text = sanitize(block2.text).trim();
2210
2321
  const head = `\u2234 Thinking (${countOf(text ? text.split(/\s+/).length : 0, "word")})`;
2211
2322
  if (detailAll) {
2212
2323
  const body = text ? wrap(text, Math.max(1, cols - 2)).map((line) => style.grey(` ${line}`)) : [];
2213
2324
  return [style.grey(truncate(head, cols)), ...body];
2214
2325
  }
2215
- const latest = block.streaming ? (text.split("\n").at(-1) ?? "").trim() : "";
2326
+ const latest = block2.streaming ? (text.split("\n").at(-1) ?? "").trim() : "";
2216
2327
  const room = cols - width(`${head} \xB7 `);
2217
2328
  if (!latest || room < 2) return [style.grey(truncate(head, cols))];
2218
2329
  const shown = width(latest) > room ? `\u2026${tailOf(latest, room - 1)}` : latest;
@@ -2224,21 +2335,21 @@ var PREVIEW_LINES = 3;
2224
2335
  function underHeader(lines) {
2225
2336
  return lines.map((line, i) => `${i === 0 ? style.grey(OUTPUT_HEAD) : OUTPUT_INDENT}${line}`);
2226
2337
  }
2227
- function unsettledOutcome(block) {
2228
- switch (block.status) {
2338
+ function unsettledOutcome(block2) {
2339
+ switch (block2.status) {
2229
2340
  case "error":
2230
2341
  return { label: "Error", paint: style.red };
2231
2342
  case "denied":
2232
- return { label: block.outcome === "refused" ? "Refused" : "Denied", paint: style.yellow };
2343
+ return { label: block2.outcome === "refused" ? "Refused" : "Denied", paint: style.yellow };
2233
2344
  case "interrupted":
2234
2345
  return { label: "Interrupted", paint: style.grey };
2235
2346
  default:
2236
2347
  return null;
2237
2348
  }
2238
2349
  }
2239
- function commandMark(block) {
2240
- if (block.status === "pending") return style.grey("\u25CB");
2241
- return (unsettledOutcome(block)?.paint ?? style.green)("\u25CF");
2350
+ function commandMark(block2) {
2351
+ if (block2.status === "pending") return style.grey("\u25CB");
2352
+ return (unsettledOutcome(block2)?.paint ?? style.green)("\u25CF");
2242
2353
  }
2243
2354
  var PATH_LIKE = /^(?![a-z][a-z0-9+.-]*:\/\/)\S*\/\S*$/i;
2244
2355
  function truncatePath(path, max) {
@@ -2251,17 +2362,17 @@ function truncatePath(path, max) {
2251
2362
  const slash = tail.search(/[\\/]/);
2252
2363
  return `\u2026${slash > 0 ? tail.slice(slash) : tail}`;
2253
2364
  }
2254
- function commandHeader(block, cols, detailAll) {
2255
- const name = sanitize(block.headline.name);
2256
- const keyArg = sanitize(block.headline.keyArg);
2365
+ function commandHeader(block2, cols, detailAll) {
2366
+ const name = sanitize(block2.headline.name);
2367
+ const keyArg = sanitize(block2.headline.keyArg);
2257
2368
  if (detailAll) {
2258
- return wrap(`${name}(${keyArg})`, Math.max(1, cols - 2)).map((line, i) => i === 0 ? `${commandMark(block)} ${line}` : ` ${line}`);
2369
+ return wrap(`${name}(${keyArg})`, Math.max(1, cols - 2)).map((line, i) => i === 0 ? `${commandMark(block2)} ${line}` : ` ${line}`);
2259
2370
  }
2260
2371
  const open = `\u25CF ${name}(`;
2261
2372
  const room = cols - width(open) - 1;
2262
2373
  const cut = PATH_LIKE.test(keyArg) ? truncatePath(keyArg, room) : truncate(keyArg, room);
2263
2374
  const text = room > 1 ? `${open}${cut})` : truncate(`${open}${keyArg})`, cols);
2264
- return [`${commandMark(block)}${text.slice(1)}`];
2375
+ return [`${commandMark(block2)}${text.slice(1)}`];
2265
2376
  }
2266
2377
  function argumentLines(args) {
2267
2378
  if (!args.trim()) return [];
@@ -2277,21 +2388,21 @@ function argumentLines(args) {
2277
2388
  return [`${key}: ${first}`, ...rest];
2278
2389
  });
2279
2390
  }
2280
- function resultLines(block, room, detailAll) {
2281
- if (block.status === "pending") return [style.grey("Running\u2026")];
2391
+ function resultLines(block2, room, detailAll) {
2392
+ if (block2.status === "pending") return [style.grey("Running\u2026")];
2282
2393
  const fit2 = (line) => detailAll ? wrap(line, room) : [truncate(line, room)];
2283
- const outcome = unsettledOutcome(block);
2394
+ const outcome = unsettledOutcome(block2);
2284
2395
  if (outcome) {
2285
- const [reason, ...rest] = (0, import_core11.outputLines)(block.output).map(sanitize);
2396
+ const [reason, ...rest] = (0, import_core13.outputLines)(block2.output).map(sanitize);
2286
2397
  const status = fit2(reason ? `${outcome.label}: ${reason}` : outcome.label).map(outcome.paint);
2287
2398
  return detailAll ? [...status, ...rest.flatMap(fit2).map(style.grey)] : status;
2288
2399
  }
2289
2400
  if (detailAll) {
2290
- const lines2 = (0, import_core11.outputLines)(block.output).map(sanitize);
2401
+ const lines2 = (0, import_core13.outputLines)(block2.output).map(sanitize);
2291
2402
  const note = lines2.length > PREVIEW_LINES ? ["\u2026 (ctrl+o to collapse)"] : [];
2292
2403
  return lines2.length > 0 ? [...lines2.flatMap(fit2), ...note].map(style.grey) : [style.grey("(no output)")];
2293
2404
  }
2294
- const { lines, hiddenLineCount } = (0, import_core11.outputPreview)(block.output, PREVIEW_LINES);
2405
+ const { lines, hiddenLineCount } = (0, import_core13.outputPreview)(block2.output, PREVIEW_LINES);
2295
2406
  if (lines.length === 0) return [style.grey("(no output)")];
2296
2407
  const more = hiddenLineCount > 0 ? [`\u2026 +${countOf(hiddenLineCount, "line")} (ctrl+o to expand)`] : [];
2297
2408
  return [...lines.map(sanitize), ...more].map((line) => style.grey(truncate(line, room)));
@@ -2304,8 +2415,8 @@ var DIFF_PAINT = {
2304
2415
  gap: style.grey
2305
2416
  };
2306
2417
  var DIFF_SIGN = { added: "+", removed: "-", context: " ", gap: "" };
2307
- function diffLines(block, diff, room, detailAll) {
2308
- const rows = (0, import_core11.diffRows)(block.output);
2418
+ function diffLines(block2, diff, room, detailAll) {
2419
+ const rows = (0, import_core13.diffRows)(block2.output);
2309
2420
  const gutter = Math.max(0, ...rows.map((row) => String(row.line ?? "").length));
2310
2421
  const draw = (row) => {
2311
2422
  const text = row.kind === "gap" ? `${" ".repeat(gutter)} \u22EE` : `${String(row.line ?? "").padStart(gutter)} ${DIFF_SIGN[row.kind]} ${sanitize(row.text)}`;
@@ -2314,14 +2425,14 @@ function diffLines(block, diff, room, detailAll) {
2314
2425
  const shown = detailAll ? rows : rows.slice(0, DIFF_PREVIEW_ROWS);
2315
2426
  const hidden = rows.length - shown.length;
2316
2427
  const more = hidden > 0 ? [style.grey(`\u2026 +${countOf(hidden, "line")} (ctrl+o to expand)`)] : [];
2317
- return [(0, import_core11.diffSummary)(diff), ...shown.flatMap(draw), ...more];
2428
+ return [(0, import_core13.diffSummary)(diff), ...shown.flatMap(draw), ...more];
2318
2429
  }
2319
- function toolLines(block, cols, detailAll) {
2430
+ function toolLines(block2, cols, detailAll) {
2320
2431
  const room = Math.max(1, cols - OUTPUT_INDENT.length);
2321
- const diff = block.diff && block.status === "ok" ? block.diff : null;
2322
- const args = detailAll && !diff ? argumentLines(block.args).flatMap((line) => wrap(line, room)).map((line) => OUTPUT_INDENT + style.grey(line)) : [];
2323
- const result = diff ? diffLines(block, diff, room, detailAll) : resultLines(block, room, detailAll);
2324
- return [...commandHeader(block, cols, detailAll), ...args, ...underHeader(result)];
2432
+ const diff = block2.diff && block2.status === "ok" ? block2.diff : null;
2433
+ const args = detailAll && !diff ? argumentLines(block2.args).flatMap((line) => wrap(line, room)).map((line) => OUTPUT_INDENT + style.grey(line)) : [];
2434
+ const result = diff ? diffLines(block2, diff, room, detailAll) : resultLines(block2, room, detailAll);
2435
+ return [...commandHeader(block2, cols, detailAll), ...args, ...underHeader(result)];
2325
2436
  }
2326
2437
  var SUBAGENT_PAINT = {
2327
2438
  running: style.yellow,
@@ -2330,24 +2441,24 @@ var SUBAGENT_PAINT = {
2330
2441
  stopped: style.grey
2331
2442
  };
2332
2443
  var CHILD_INDENT = " ";
2333
- function subagentHeader(block, cols) {
2334
- const brief = firstLine(block.brief);
2335
- const steps = block.children.filter((c) => c.type === "tool").length;
2336
- const status = block.status === "running" && steps > 0 ? `running \xB7 ${countOf(steps, "step")}` : block.status;
2444
+ function subagentHeader(block2, cols) {
2445
+ const brief = firstLine(block2.brief);
2446
+ const steps = block2.children.filter((c) => c.type === "tool").length;
2447
+ const status = block2.status === "running" && steps > 0 ? `running \xB7 ${countOf(steps, "step")}` : block2.status;
2337
2448
  const head = brief ? " Agent: " : " Agent";
2338
2449
  const briefRoom = cols - width(`\u25C6${head} ${status}`);
2339
2450
  if (briefRoom < 4) return truncate(`\u25C6${head}${brief} ${status}`, cols);
2340
- const named = `${style.brand("\u25C6")}${head}${truncate(brief, briefRoom)} ${SUBAGENT_PAINT[block.status](status)}`;
2341
- const digest = firstLine(block.digest);
2451
+ const named = `${style.brand("\u25C6")}${head}${truncate(brief, briefRoom)} ${SUBAGENT_PAINT[block2.status](status)}`;
2452
+ const digest = firstLine(block2.digest);
2342
2453
  const digestRoom = cols - width(named) - width(" \xB7 ");
2343
2454
  return digest && digestRoom >= 4 ? `${named}${style.grey(` \xB7 ${truncate(digest, digestRoom)}`)}` : named;
2344
2455
  }
2345
- function subagentLines(block, cols, detailAll) {
2346
- const header = subagentHeader(block, cols);
2456
+ function subagentLines(block2, cols, detailAll) {
2457
+ const header = subagentHeader(block2, cols);
2347
2458
  if (!detailAll) return [header];
2348
2459
  const childCols = Math.max(1, cols - CHILD_INDENT.length);
2349
- const children = block.children.flatMap((child) => blockLines(child, childCols, true).map((line) => CHILD_INDENT + line));
2350
- const digest = sanitize(block.digest).trim();
2460
+ const children = block2.children.flatMap((child) => blockLines(child, childCols, true).map((line) => CHILD_INDENT + line));
2461
+ const digest = sanitize(block2.digest).trim();
2351
2462
  const handedBack = digest ? underHeader(wrap(digest, Math.max(1, cols - OUTPUT_INDENT.length)).map(style.grey)) : [];
2352
2463
  return [header, ...children, ...handedBack];
2353
2464
  }
@@ -2372,15 +2483,15 @@ var DECIDED_BY = {
2372
2483
  budget: "web-read budget",
2373
2484
  unsupported: "not usable on this runner version"
2374
2485
  };
2375
- function approvalLine(block, cols) {
2376
- const policy = block.decidedBy && block.decidedBy !== "asked" ? DECIDED_BY[block.decidedBy] : void 0;
2377
- const [mark, status, paint] = block.status === "pending" ? ["?", "Waiting for you", style.yellow] : block.status === "granted" ? ["\u2713", policy ? `Auto-approved (${policy})` : block.forTask ? "Approved for this task" : "Approved", style.green] : block.status === "withdrawn" ? ["\xB7", "Withdrawn", style.grey] : ["\u2298", policy ? `Auto-denied (${policy})` : "Denied", style.yellow];
2378
- const note = block.note ? ` \u2014 \u201C${firstLine(block.note)}\u201D` : "";
2379
- const line = `${mark} ${status} \xB7 ${APPROVAL_KIND[block.kind]}: ${firstLine(block.subject)}${note}`;
2486
+ function approvalLine(block2, cols) {
2487
+ const policy = block2.decidedBy && block2.decidedBy !== "asked" ? DECIDED_BY[block2.decidedBy] : void 0;
2488
+ const [mark, status, paint] = block2.status === "pending" ? ["?", "Waiting for you", style.yellow] : block2.status === "granted" ? ["\u2713", policy ? `Auto-approved (${policy})` : block2.forTask ? "Approved for this task" : "Approved", style.green] : block2.status === "withdrawn" ? ["\xB7", "Withdrawn", style.grey] : ["\u2298", policy ? `Auto-denied (${policy})` : "Denied", style.yellow];
2489
+ const note = block2.note ? ` \u2014 \u201C${firstLine(block2.note)}\u201D` : "";
2490
+ const line = `${mark} ${status} \xB7 ${APPROVAL_KIND[block2.kind]}: ${firstLine(block2.subject)}${note}`;
2380
2491
  return `${paint(mark)}${truncate(line, cols).slice(mark.length)}`;
2381
2492
  }
2382
- function approvalKeysLine(block, cols) {
2383
- const keys = ["ctrl-y allow", ...block.allowForTask ? ["ctrl-t allow for task"] : [], "ctrl-g deny (composer text is the note)"];
2493
+ function approvalKeysLine(block2, cols) {
2494
+ const keys = ["ctrl-y allow", ...block2.allowForTask ? ["ctrl-t allow for task"] : [], "ctrl-g deny (composer text is the note)"];
2384
2495
  return style.grey(truncate(` ${keys.join(" \xB7 ")}`, cols));
2385
2496
  }
2386
2497
  function checkpointCardLines(order, question, cols, approvalFirst) {
@@ -2413,22 +2524,22 @@ var COMMAND_PAINT = {
2413
2524
  failed: style.red,
2414
2525
  stopped: style.grey
2415
2526
  };
2416
- function runnerCommandLines(block, cols, detailAll) {
2417
- const typed = sanitize(`/${block.name}${block.args ? ` ${block.args}` : ""}`);
2418
- const status = ` ${block.status}`;
2419
- const head = `${style.accent("\u276F")} ${truncate(typed, Math.max(1, cols - 2 - width(status)))}${COMMAND_PAINT[block.status](status)}`;
2527
+ function runnerCommandLines(block2, cols, detailAll) {
2528
+ const typed = sanitize(`/${block2.name}${block2.args ? ` ${block2.args}` : ""}`);
2529
+ const status = ` ${block2.status}`;
2530
+ const head = `${style.accent("\u276F")} ${truncate(typed, Math.max(1, cols - 2 - width(status)))}${COMMAND_PAINT[block2.status](status)}`;
2420
2531
  const room = Math.max(1, cols - OUTPUT_INDENT.length);
2421
- const printed = (0, import_core11.outputLines)(block.output).map(sanitize);
2532
+ const printed = (0, import_core13.outputLines)(block2.output).map(sanitize);
2422
2533
  const shown = detailAll ? printed.flatMap((line) => wrap(line, room)) : printed.slice(0, PREVIEW_LINES).map((line) => truncate(line, room));
2423
2534
  return [head, ...underHeader(shown.map(style.grey))];
2424
2535
  }
2425
- function compactionLine(block, cols) {
2426
- const sizes = block.preTokens !== void 0 && block.postTokens !== void 0 ? ` \xB7 ${compactCount(block.preTokens)} \u2192 ${compactCount(block.postTokens)} tokens` : "";
2427
- const text = block.trigger === "auto" && !sizes ? "\u2261 Context compacted by the runner on its own" : `\u2261 Context compacted${sizes}`;
2536
+ function compactionLine(block2, cols) {
2537
+ const sizes = block2.preTokens !== void 0 && block2.postTokens !== void 0 ? ` \xB7 ${compactCount(block2.preTokens)} \u2192 ${compactCount(block2.postTokens)} tokens` : "";
2538
+ const text = block2.trigger === "auto" && !sizes ? "\u2261 Context compacted by the runner on its own" : `\u2261 Context compacted${sizes}`;
2428
2539
  return style.grey(truncate(text, cols));
2429
2540
  }
2430
- function runnerLoadedLines(block, cols, detailAll) {
2431
- const of = (kind) => block.commands.filter((c) => c.kind === kind).map((c) => `/${sanitize(c.name)}`);
2541
+ function runnerLoadedLines(block2, cols, detailAll) {
2542
+ const of = (kind) => block2.commands.filter((c) => c.kind === kind).map((c) => `/${sanitize(c.name)}`);
2432
2543
  const skills = of("skill");
2433
2544
  const commands = of("command");
2434
2545
  const builtins = of("builtin");
@@ -2436,66 +2547,66 @@ function runnerLoadedLines(block, cols, detailAll) {
2436
2547
  countOf(skills.length, "skill"),
2437
2548
  countOf(commands.length, "command"),
2438
2549
  countOf(builtins.length, "built-in command"),
2439
- countOf(block.mcpServers.length, "MCP server")
2550
+ countOf(block2.mcpServers.length, "MCP server")
2440
2551
  ];
2441
2552
  const head = truncate(`\u25CF Runner loaded ${counts.join(", ")}`, cols);
2442
2553
  const lines = [`${style.green("\u25CF")}${style.grey(head.slice(1))}`];
2443
2554
  if (!detailAll) return lines;
2444
2555
  const room = Math.max(1, cols - OUTPUT_INDENT.length);
2445
- const list = (label, names) => names.length > 0 ? wrap(`${label}: ${names.join(" ")}`, room) : [];
2446
- const servers = block.mcpServers.map((m) => `${sanitize(m.name)}${m.status ? ` (${sanitize(m.status)})` : ""}`);
2556
+ const list2 = (label, names) => names.length > 0 ? wrap(`${label}: ${names.join(" ")}`, room) : [];
2557
+ const servers = block2.mcpServers.map((m) => `${sanitize(m.name)}${m.status ? ` (${sanitize(m.status)})` : ""}`);
2447
2558
  return [
2448
2559
  ...lines,
2449
- ...[...list("skills", skills), ...list("commands", commands), ...list("built-in", builtins), ...servers.length > 0 ? wrap(`MCP servers: ${servers.join(", ")}`, room) : []].map((line) => OUTPUT_INDENT + style.grey(line))
2560
+ ...[...list2("skills", skills), ...list2("commands", commands), ...list2("built-in", builtins), ...servers.length > 0 ? wrap(`MCP servers: ${servers.join(", ")}`, room) : []].map((line) => OUTPUT_INDENT + style.grey(line))
2450
2561
  ];
2451
2562
  }
2452
- function planLine(block, cols) {
2453
- const count = block.taskCount === void 0 ? "" : ` (${countOf(block.taskCount, "task")})`;
2454
- const text = block.status === "building" ? "Building plan\u2026" : `Plan ${block.status}${count}`;
2563
+ function planLine(block2, cols) {
2564
+ const count = block2.taskCount === void 0 ? "" : ` (${countOf(block2.taskCount, "task")})`;
2565
+ const text = block2.status === "building" ? "Building plan\u2026" : `Plan ${block2.status}${count}`;
2455
2566
  return `${style.brand("\u25C7")}${truncate(`\u25C7 ${text}`, cols).slice(1)}`;
2456
2567
  }
2457
- function blockLines(block, cols, detailAll) {
2458
- switch (block.type) {
2568
+ function blockLines(block2, cols, detailAll) {
2569
+ switch (block2.type) {
2459
2570
  case "message":
2460
- return messageLines(block, cols);
2571
+ return messageLines(block2, cols);
2461
2572
  case "thinking":
2462
- return thinkingLines(block, cols, detailAll);
2573
+ return thinkingLines(block2, cols, detailAll);
2463
2574
  case "tool":
2464
- return toolLines(block, cols, detailAll);
2575
+ return toolLines(block2, cols, detailAll);
2465
2576
  case "subagent":
2466
- return subagentLines(block, cols, detailAll);
2577
+ return subagentLines(block2, cols, detailAll);
2467
2578
  case "approval":
2468
- return [approvalLine(block, cols)];
2579
+ return [approvalLine(block2, cols)];
2469
2580
  case "plan":
2470
- return [planLine(block, cols)];
2581
+ return [planLine(block2, cols)];
2471
2582
  case "skill_load":
2472
- return [skillLoadLine(block, cols)];
2583
+ return [skillLoadLine(block2, cols)];
2473
2584
  case "command":
2474
- return runnerCommandLines(block, cols, detailAll);
2585
+ return runnerCommandLines(block2, cols, detailAll);
2475
2586
  case "compaction":
2476
- return [compactionLine(block, cols)];
2587
+ return [compactionLine(block2, cols)];
2477
2588
  case "runner_loaded":
2478
- return runnerLoadedLines(block, cols, detailAll);
2589
+ return runnerLoadedLines(block2, cols, detailAll);
2479
2590
  // Pinned under the pane rather than drawn in it — see `tokenLine`.
2480
2591
  case "usage":
2481
2592
  return [];
2482
2593
  }
2483
2594
  }
2484
2595
  var drawnBlocks = /* @__PURE__ */ new WeakMap();
2485
- function drawn(block, cols, detailAll) {
2486
- const cached = drawnBlocks.get(block);
2596
+ function drawn(block2, cols, detailAll) {
2597
+ const cached = drawnBlocks.get(block2);
2487
2598
  if (cached && cached.cols === cols && cached.detailAll === detailAll) return cached.lines;
2488
- const lines = blockLines(block, cols, detailAll);
2489
- drawnBlocks.set(block, { cols, detailAll, lines });
2599
+ const lines = blockLines(block2, cols, detailAll);
2600
+ drawnBlocks.set(block2, { cols, detailAll, lines });
2490
2601
  return lines;
2491
2602
  }
2492
- function conversationLines(blocks, cols, detailAll, answering) {
2603
+ function conversationLines(blocks2, cols, detailAll, answering) {
2493
2604
  const lines = [];
2494
- for (const [i, block] of blocks.entries()) {
2495
- if (block.type === "usage") continue;
2496
- lines.push(...drawn(block, cols, detailAll));
2497
- if (block === answering) lines.push(approvalKeysLine(block, cols));
2498
- if (blocks[i + 1]?.type !== "skill_load") lines.push("");
2605
+ for (const [i, block2] of blocks2.entries()) {
2606
+ if (block2.type === "usage") continue;
2607
+ lines.push(...drawn(block2, cols, detailAll));
2608
+ if (block2 === answering) lines.push(approvalKeysLine(block2, cols));
2609
+ if (blocks2[i + 1]?.type !== "skill_load") lines.push("");
2499
2610
  }
2500
2611
  return lines;
2501
2612
  }
@@ -2509,8 +2620,8 @@ function formatCost(currency, amount) {
2509
2620
  const value = `${whole}.${frac.padEnd(2, "0")}`;
2510
2621
  return currency.toLowerCase() === "usd" ? `$${value}` : `${value} ${currency.toUpperCase()}`;
2511
2622
  }
2512
- function tokenLine(blocks, cols) {
2513
- const usage = blocks[blocks.length - 1];
2623
+ function tokenLine(blocks2, cols) {
2624
+ const usage = blocks2[blocks2.length - 1];
2514
2625
  if (usage?.type !== "usage") return null;
2515
2626
  const parts = usageMeasures(usage.totals, false);
2516
2627
  if (usage.model && !usage.contextFill) parts.push("ctx unknown");
@@ -2536,7 +2647,7 @@ function taskUsageText(usage) {
2536
2647
 
2537
2648
  // src/commands/status.ts
2538
2649
  var import_fs4 = require("fs");
2539
- var import_core12 = require("@ordewell/core");
2650
+ var import_core14 = require("@ordewell/core");
2540
2651
  async function handleStatus(subArgs, injectedApi) {
2541
2652
  const sessionId = flag(subArgs, "--session-id");
2542
2653
  const workspace = flag(subArgs, "--workspace") || process.cwd();
@@ -2591,8 +2702,8 @@ function emitJson(payload, outputPath) {
2591
2702
  }
2592
2703
  function printOneSession(sessionId, meta, plan) {
2593
2704
  const allTasks = allTasksOf(plan);
2594
- const everyTask = (0, import_core12.flattenTasks)(allTasks);
2595
- const blocked = (0, import_core12.blockingFailures)(everyTask.map((t) => ({ ...t, subtasks: [], dependencies: t.dependencies ?? [] })));
2705
+ const everyTask = (0, import_core14.flattenTasks)(allTasks);
2706
+ const blocked = (0, import_core14.blockingFailures)(everyTask.map((t) => ({ ...t, subtasks: [], dependencies: t.dependencies ?? [] })));
2596
2707
  const count = (status) => everyTask.filter((t) => t.status === status || status === "blocked" && blocked.has(t.id)).length;
2597
2708
  console.log(`Session: ${sessionId}`);
2598
2709
  console.log(`Goal: ${meta.goal}`);
@@ -2600,25 +2711,25 @@ function printOneSession(sessionId, meta, plan) {
2600
2711
  console.log(`Phase: ${plan?.phase || "unknown"} | Created: ${meta.createdAt}`);
2601
2712
  console.log(`Tasks: ${everyTask.length} total | ${count("completed")} done | ${count("failed")} failed | ${count("in_progress")} running | ${count("blocked")} blocked | ${count("skipped")} skipped
2602
2713
  `);
2603
- const usage = (0, import_core12.planUsage)(allTasks);
2714
+ const usage = (0, import_core14.planUsage)(allTasks);
2604
2715
  if (usage.attempts) console.log(`Tasks total: ${taskUsageText(usage)}`);
2605
2716
  for (const t of allTasks) {
2606
2717
  const icon = iconFor(blocked.has(t.id) ? "blocked" : t.status);
2607
2718
  const model = t.assignedModel ? ` (${t.assignedModel.modelLabel})` : "";
2608
2719
  const shortId = (t.id ?? "").slice(-8);
2609
- console.log(` ${(0, import_core12.taskOrderLabel)(t).padStart(2)}. ${icon} [${shortId}] ${t.title}${model}`);
2610
- const row = (0, import_core12.taskRowView)({ ...t, dependencies: t.dependencies ?? [] }, { tasks: allTasks });
2611
- if (row.blockedBy) console.log(` ${(0, import_core12.blockedByLabel)(row.blockedBy)}`);
2612
- if (row.status === "skipped") console.log(` ${(0, import_core12.skippedLabel)(row.skipReason)}`);
2720
+ console.log(` ${(0, import_core14.taskOrderLabel)(t).padStart(2)}. ${icon} [${shortId}] ${t.title}${model}`);
2721
+ const row = (0, import_core14.taskRowView)({ ...t, dependencies: t.dependencies ?? [] }, { tasks: allTasks });
2722
+ if (row.blockedBy) console.log(` ${(0, import_core14.blockedByLabel)(row.blockedBy)}`);
2723
+ if (row.status === "skipped") console.log(` ${(0, import_core14.skippedLabel)(row.skipReason)}`);
2613
2724
  if (row.usage) console.log(` ${taskUsageText(row.usage)}`);
2614
2725
  for (const sub of t.subtasks || []) {
2615
2726
  const subIcon = iconFor(blocked.has(sub.id) ? "blocked" : sub.status);
2616
2727
  const subModel = sub.assignedModel ? ` (${sub.assignedModel.modelLabel})` : "";
2617
2728
  const subShortId = (sub.id ?? "").slice(-8);
2618
- console.log(` ${(0, import_core12.taskOrderLabel)(sub, t)}. ${subIcon} [${subShortId}] ${sub.title}${subModel}`);
2619
- const subRow = (0, import_core12.taskRowView)({ ...sub, dependencies: sub.dependencies ?? [] }, { parent: t, tasks: allTasks });
2620
- if (subRow.blockedBy) console.log(` ${(0, import_core12.blockedByLabel)(subRow.blockedBy)}`);
2621
- if (subRow.status === "skipped") console.log(` ${(0, import_core12.skippedLabel)(subRow.skipReason)}`);
2729
+ console.log(` ${(0, import_core14.taskOrderLabel)(sub, t)}. ${subIcon} [${subShortId}] ${sub.title}${subModel}`);
2730
+ const subRow = (0, import_core14.taskRowView)({ ...sub, dependencies: sub.dependencies ?? [] }, { parent: t, tasks: allTasks });
2731
+ if (subRow.blockedBy) console.log(` ${(0, import_core14.blockedByLabel)(subRow.blockedBy)}`);
2732
+ if (subRow.status === "skipped") console.log(` ${(0, import_core14.skippedLabel)(subRow.skipReason)}`);
2622
2733
  if (subRow.usage) console.log(` ${taskUsageText(subRow.usage)}`);
2623
2734
  }
2624
2735
  }
@@ -2671,10 +2782,10 @@ async function handleWeb(subArgs) {
2671
2782
  }
2672
2783
 
2673
2784
  // src/commands/models.ts
2674
- var import_core14 = require("@ordewell/core");
2785
+ var import_core16 = require("@ordewell/core");
2675
2786
 
2676
2787
  // src/commands/model.ts
2677
- var import_core13 = require("@ordewell/core");
2788
+ var import_core15 = require("@ordewell/core");
2678
2789
  var USAGE = "Usage: ordewell model [show | set <model-id>]";
2679
2790
  async function handleModel(subArgs, injectedApi) {
2680
2791
  const [action, modelId] = positionals(subArgs);
@@ -2689,7 +2800,7 @@ async function handleModel(subArgs, injectedApi) {
2689
2800
  if (!modelId) fail(USAGE);
2690
2801
  const settings = await api.getSettings();
2691
2802
  const provider = typeof settings.aiProvider === "string" ? settings.aiProvider : "";
2692
- const runner = (0, import_core13.runnerForProvider)(provider);
2803
+ const runner = (0, import_core15.runnerForProvider)(provider);
2693
2804
  if (runner) {
2694
2805
  const known = (await fetchCatalog(api)).models.filter((m) => m.runners?.includes(runner));
2695
2806
  if (known.length > 0 && !known.some((m) => m.id === modelId)) {
@@ -2712,7 +2823,7 @@ async function showModels(api) {
2712
2823
  const [settings, catalog] = await Promise.all([api.getSettings(), fetchCatalog(api)]);
2713
2824
  const provider = typeof settings.aiProvider === "string" ? settings.aiProvider : "";
2714
2825
  const current = typeof settings.orchestratorModel === "string" ? settings.orchestratorModel : "";
2715
- const runner = (0, import_core13.runnerForProvider)(provider);
2826
+ const runner = (0, import_core15.runnerForProvider)(provider);
2716
2827
  const options = runner ? catalog.models.filter((m) => m.runners?.includes(runner)) : catalog.orchestratorModels;
2717
2828
  console.log(`
2718
2829
  Planner model: ${current || "(backend default)"}`);
@@ -2746,8 +2857,8 @@ async function handleModels(subArgs) {
2746
2857
  const rest = subArgs.filter((_, i) => i !== setIdx && i !== setIdx + 1);
2747
2858
  return handleModel(["set", subArgs[setIdx + 1], ...rest]);
2748
2859
  }
2749
- const config = new import_core14.EnvConfig();
2750
- const providers = (0, import_core14.configuredProviders)(config);
2860
+ const config = new import_core16.EnvConfig();
2861
+ const providers = (0, import_core16.configuredProviders)(config);
2751
2862
  if (providers.length === 0) {
2752
2863
  console.error("No providers configured. Set an API key for a provider, e.g.:");
2753
2864
  console.error(" OPENROUTER_API_KEY=... (OpenRouter)");
@@ -2756,19 +2867,19 @@ async function handleModels(subArgs) {
2756
2867
  console.error(" OPENAI_COMPATIBLE_BASE_URL=... (self-hosted / OpenAI-compatible)");
2757
2868
  process.exit(1);
2758
2869
  }
2759
- const { apiKeys, baseUrls } = (0, import_core14.collectProviderCredentials)(config);
2870
+ const { apiKeys, baseUrls } = (0, import_core16.collectProviderCredentials)(config);
2760
2871
  let models;
2761
2872
  let errors;
2762
2873
  try {
2763
- const result = await (0, import_core14.fetchAllProviderModels)({ apiKeys, baseUrls });
2764
- models = (0, import_core14.toOrchestratorOptions)(result.models, import_core14.ORCHESTRATOR_SHORTCUTS);
2874
+ const result = await (0, import_core16.fetchAllProviderModels)({ apiKeys, baseUrls });
2875
+ models = (0, import_core16.toOrchestratorOptions)(result.models, import_core16.ORCHESTRATOR_SHORTCUTS);
2765
2876
  errors = result.errors;
2766
2877
  } catch (err) {
2767
2878
  console.error(`Failed to fetch models: ${err instanceof Error ? err.message : String(err)}`);
2768
2879
  process.exit(1);
2769
2880
  return;
2770
2881
  }
2771
- const providerLabel = (p) => (0, import_core14.getProviderMeta)(p)?.label ?? p;
2882
+ const providerLabel = (p) => (0, import_core16.getProviderMeta)(p)?.label ?? p;
2772
2883
  console.log(
2773
2884
  `
2774
2885
  Available models (${models.length}) across ${providers.length} configured provider(s):`
@@ -2808,7 +2919,7 @@ ${providerLabel(provider)}`);
2808
2919
 
2809
2920
  // src/commands/setup.ts
2810
2921
  var import_fs6 = require("fs");
2811
- var import_core15 = require("@ordewell/core");
2922
+ var import_core17 = require("@ordewell/core");
2812
2923
  function handleSetup(subArgs) {
2813
2924
  const modelIdx = subArgs.indexOf("--model");
2814
2925
  const chosenModel = modelIdx !== -1 ? subArgs[modelIdx + 1] : null;
@@ -2853,7 +2964,7 @@ function handleSetup(subArgs) {
2853
2964
 
2854
2965
  # Or plan with a coding agent you already have installed \u2014 no API key needed,
2855
2966
  # it uses that agent's own subscription. Set the model to one of its own.
2856
- # AI_PROVIDER=claude-code|codex|opencode
2967
+ # AI_PROVIDER=${runnerIdChoice()}
2857
2968
  # ORCHESTRATOR_MODEL=haiku
2858
2969
  # ORDEWELL_PLANNER_EFFORT=low
2859
2970
 
@@ -2880,13 +2991,13 @@ function handleSetup(subArgs) {
2880
2991
  # STEPFUN_API_KEY=...
2881
2992
  # SILICONFLOW_API_KEY=...
2882
2993
  `;
2883
- (0, import_core15.writePrivateFile)(envFile, content);
2994
+ (0, import_core17.writePrivateFile)(envFile, content);
2884
2995
  console.log(`Wrote: ${envFile}`);
2885
2996
  console.log("Review and edit the file, then run: ordewell tui");
2886
2997
  }
2887
2998
 
2888
2999
  // src/commands/skills.ts
2889
- var import_core16 = require("@ordewell/core");
3000
+ var import_core18 = require("@ordewell/core");
2890
3001
  var import_path5 = require("path");
2891
3002
  function invocation(skill) {
2892
3003
  if (skill.userInvocable && skill.modelInvocable) return "both";
@@ -2899,22 +3010,22 @@ function handleSkills(subArgs) {
2899
3010
  fail("Usage: ordewell skills [--workspace /path] [--json]");
2900
3011
  }
2901
3012
  const workspace = (0, import_path5.resolve)(flag(subArgs, "--workspace") || process.cwd());
2902
- const catalog = (0, import_core16.createSkillsService)(workspace, new import_core16.EnvConfig().workspaceRepos).readCatalog();
3013
+ const catalog = (0, import_core18.createSkillsService)(workspace, new import_core18.EnvConfig().workspaceRepos).readCatalog();
2903
3014
  const skills = catalog.skills.map((skill) => ({
2904
3015
  name: skill.name,
2905
3016
  scope: skill.source,
2906
3017
  appliesTo: skill.appliesTo,
2907
3018
  invocation: invocation(skill),
2908
- path: (0, import_core16.abbreviateHome)(skill.path)
3019
+ path: (0, import_core18.abbreviateHome)(skill.path)
2909
3020
  }));
2910
3021
  const shadowed = catalog.shadowed.map(({ skill, shadowedBy }) => ({
2911
3022
  name: skill.name,
2912
- path: (0, import_core16.abbreviateHome)(skill.path),
2913
- shadowedBy: { scope: shadowedBy.source, path: (0, import_core16.abbreviateHome)(shadowedBy.path) }
3023
+ path: (0, import_core18.abbreviateHome)(skill.path),
3024
+ shadowedBy: { scope: shadowedBy.source, path: (0, import_core18.abbreviateHome)(shadowedBy.path) }
2914
3025
  }));
2915
3026
  const invalid = catalog.invalid.map((skill) => ({
2916
3027
  name: skill.name,
2917
- path: (0, import_core16.abbreviateHome)(skill.path),
3028
+ path: (0, import_core18.abbreviateHome)(skill.path),
2918
3029
  reason: skill.reason
2919
3030
  }));
2920
3031
  if (hasFlag(subArgs, "--json")) {
@@ -3029,7 +3140,7 @@ async function handleShow(args, api) {
3029
3140
  }
3030
3141
 
3031
3142
  // src/commands/task-control.ts
3032
- var import_core17 = require("@ordewell/core");
3143
+ var import_core19 = require("@ordewell/core");
3033
3144
  var PAST_TENSE = {
3034
3145
  run: "Task started.",
3035
3146
  "force-start": "Task force-started.",
@@ -3072,7 +3183,7 @@ async function confirmPastGate(subArgs, api, sessionId, taskId, confirm2) {
3072
3183
  if (hasFlag(subArgs, "--yes")) return;
3073
3184
  const unmerged = await api.getMergeGate(sessionId, taskId).catch(() => []);
3074
3185
  if (unmerged.length === 0) return;
3075
- const question = `${(0, import_core17.pastGateConfirmation)(unmerged.map((d) => (0, import_core17.titledTaskRef)(d)))} Start it anyway?`;
3186
+ const question = `${(0, import_core19.pastGateConfirmation)(unmerged.map((d) => (0, import_core19.titledTaskRef)(d)))} Start it anyway?`;
3076
3187
  if (!await confirm2(question)) fail("Not started \u2014 nothing was changed. Pass --yes to start it without a prompt.");
3077
3188
  }
3078
3189
  function makeHandler(action, command = action) {
@@ -3385,24 +3496,24 @@ async function handleRewind(subArgs, injectedApi) {
3385
3496
  }
3386
3497
 
3387
3498
  // src/tui/transcript.ts
3388
- var import_core18 = require("@ordewell/core");
3499
+ var import_core20 = require("@ordewell/core");
3389
3500
  function show(state, { view: conversation, gate: turnGate }) {
3390
3501
  const gated = turnGate === state.turnGate ? state : { ...state, turnGate };
3391
3502
  if (conversation === state.conversation) return gated;
3392
3503
  return { ...gated, conversation };
3393
3504
  }
3394
3505
  function fold(state, input) {
3395
- return show(state, { view: (0, import_core18.reduceConversation)(state.conversation, input), gate: state.turnGate });
3506
+ return show(state, { view: (0, import_core20.reduceConversation)(state.conversation, input), gate: state.turnGate });
3396
3507
  }
3397
3508
  function say(state, role, text) {
3398
3509
  const said = fold(state, { type: "local_entry", role, text });
3399
3510
  return said.conversation.nextId > state.conversation.nextId ? { ...said, scroll: 0 } : said;
3400
3511
  }
3401
3512
  function hear(state, message) {
3402
- return show(state, (0, import_core18.followTurn)(state.conversation, state.turnGate, message));
3513
+ return show(state, (0, import_core20.followTurn)(state.conversation, state.turnGate, message));
3403
3514
  }
3404
3515
  function cutTurn(state) {
3405
- return show(state, (0, import_core18.stopTurn)(state.conversation, state.turnGate));
3516
+ return show(state, (0, import_core20.stopTurn)(state.conversation, state.turnGate));
3406
3517
  }
3407
3518
  function wiped(view) {
3408
3519
  return { ...view, blocks: view.blocks.filter((b) => b.type === "usage") };
@@ -3651,7 +3762,7 @@ async function handleHandoff(subArgs, injectedApi, confirm2 = askYesNo) {
3651
3762
  }
3652
3763
 
3653
3764
  // src/commands/planner.ts
3654
- var import_core19 = require("@ordewell/core");
3765
+ var import_core21 = require("@ordewell/core");
3655
3766
 
3656
3767
  // src/plannerModelSwitch.ts
3657
3768
  function plannerSwitchRecall(settings) {
@@ -3661,7 +3772,6 @@ function plannerSwitchRecall(settings) {
3661
3772
  }
3662
3773
 
3663
3774
  // src/commands/planner.ts
3664
- var isAiProvider = (id) => Object.hasOwn(import_core19.ALL_PROVIDERS, id);
3665
3775
  async function handlePlanner(subArgs, injectedApi) {
3666
3776
  const api = await connect(subArgs, injectedApi);
3667
3777
  const [wanted] = positionals(subArgs);
@@ -3670,19 +3780,19 @@ async function handlePlanner(subArgs, injectedApi) {
3670
3780
  return;
3671
3781
  }
3672
3782
  const provider = wanted.toLowerCase();
3673
- if (!isAiProvider(provider)) {
3783
+ const meta = (0, import_core21.getProviderMeta)(provider);
3784
+ if (!meta) {
3674
3785
  fail(`Unknown planner: ${provider}`, "Run `ordewell planner` with no arguments to see the list.");
3675
3786
  }
3676
3787
  const settings = await persistEnv(api, { AI_PROVIDER: provider });
3677
3788
  const recall2 = plannerSwitchRecall(settings);
3678
3789
  writeEnv({ ORCHESTRATOR_MODEL: recall2.model, ORDEWELL_PLANNER_EFFORT: recall2.effort });
3679
- const meta = import_core19.ALL_PROVIDERS[provider];
3680
3790
  const catalog = await fetchCatalog(api);
3681
3791
  console.log(
3682
- (0, import_core19.isCliProvider)(provider) ? `Planning with ${meta.label} \u2014 no API key needed, it uses that agent's own subscription.` : `Planner set to ${meta.label}.`
3792
+ (0, import_core21.isCliProvider)(provider) ? `Planning with ${meta.label} \u2014 no API key needed, it uses that agent's own subscription.` : `Planner set to ${meta.label}.`
3683
3793
  );
3684
3794
  console.log(plannerModelLine(recall2));
3685
- if (!(0, import_core19.isCliProvider)(provider) && !catalog.providers.includes(provider)) {
3795
+ if ((0, import_core21.isApiProvider)(provider) && !catalog.providers.includes(provider)) {
3686
3796
  console.log(` No ${meta.apiKeyEnvVar} configured yet \u2014 set one with \`ordewell key set ${provider} <key>\`.`);
3687
3797
  }
3688
3798
  }
@@ -3700,15 +3810,15 @@ async function showPlanners(api) {
3700
3810
  const [settings, catalog] = await Promise.all([api.getSettings(), fetchCatalog(api)]);
3701
3811
  const current = typeof settings.aiProvider === "string" ? settings.aiProvider : "";
3702
3812
  console.log("\nCoding agents (no API key \u2014 they use their own subscription)");
3703
- for (const id of import_core19.CLI_PROVIDERS) {
3704
- const runner = (0, import_core19.runnerForProvider)(id);
3813
+ for (const id of import_core21.CLI_PROVIDERS) {
3814
+ const runner = (0, import_core21.runnerForProvider)(id);
3705
3815
  const discovered = runner ? catalog.models.some((m) => m.runners?.includes(runner)) : false;
3706
- console.log(` ${marker(id === current)} ${id.padEnd(14)} ${import_core19.ALL_PROVIDERS[id].label}${discovered ? "" : " (not detected)"}`);
3816
+ console.log(` ${marker(id === current)} ${id.padEnd(14)} ${(0, import_core21.getProviderMeta)(id)?.label ?? id}${discovered ? "" : " (not detected)"}`);
3707
3817
  }
3708
3818
  console.log("\nAPI providers");
3709
- for (const id of import_core19.PROVIDER_PRIORITY) {
3819
+ for (const id of import_core21.PROVIDER_PRIORITY) {
3710
3820
  const configured = catalog.providers.includes(id);
3711
- const meta = import_core19.ALL_PROVIDERS[id];
3821
+ const meta = (0, import_core21.getProviderMeta)(id);
3712
3822
  console.log(` ${marker(id === current)} ${id.padEnd(14)} ${meta.label}${configured ? "" : ` (no ${meta.apiKeyEnvVar})`}`);
3713
3823
  }
3714
3824
  console.log(`
@@ -3725,11 +3835,11 @@ async function handlePlannerEffort(subArgs, injectedApi) {
3725
3835
  const provider = typeof settings.aiProvider === "string" ? settings.aiProvider : "";
3726
3836
  const modelId = typeof settings.orchestratorModel === "string" ? settings.orchestratorModel : "";
3727
3837
  const currentEffort = typeof settings.plannerThinkingEffort === "string" ? settings.plannerThinkingEffort : "";
3728
- const runner = isAiProvider(provider) ? (0, import_core19.runnerForProvider)(provider) : null;
3838
+ const runner = (0, import_core21.runnerForProvider)(provider);
3729
3839
  if (!runner) {
3730
3840
  fail(
3731
3841
  "Thinking effort applies to a coding-agent planner.",
3732
- "Switch with: ordewell planner claude-code|codex|opencode"
3842
+ `Switch with: ordewell planner ${runnerIdChoice()}`
3733
3843
  );
3734
3844
  }
3735
3845
  const model = catalog.models.find((m) => m.id === modelId && m.runners?.includes(runner));
@@ -3765,7 +3875,7 @@ async function handlePlannerEffort(subArgs, injectedApi) {
3765
3875
  }
3766
3876
 
3767
3877
  // src/commands/parallel.ts
3768
- var import_core20 = require("@ordewell/core");
3878
+ var import_core22 = require("@ordewell/core");
3769
3879
  var USAGE5 = "Usage: ordewell parallel [<number of tasks, 1 or more>]";
3770
3880
  async function handleParallel(subArgs, injectedApi) {
3771
3881
  const [wanted] = positionals(subArgs);
@@ -3775,14 +3885,14 @@ async function handleParallel(subArgs, injectedApi) {
3775
3885
  console.log(`Up to ${String(settings.maxParallel ?? "?")} AI tasks run at once. Change with: ordewell parallel <n>`);
3776
3886
  return;
3777
3887
  }
3778
- const limit = (0, import_core20.parseMaxParallel)(wanted);
3888
+ const limit = (0, import_core22.parseMaxParallel)(wanted);
3779
3889
  if (limit === null) fail(`"${wanted}" is not a number of tasks (1 or more).`, USAGE5);
3780
3890
  await persistEnv(api, { ORDEWELL_MAX_PARALLEL: String(limit) });
3781
3891
  console.log(`Up to ${limit} AI task${limit === 1 ? "" : "s"} now run at once.`);
3782
3892
  }
3783
3893
 
3784
3894
  // src/commands/runSettings.ts
3785
- var import_core21 = require("@ordewell/core");
3895
+ var import_core23 = require("@ordewell/core");
3786
3896
  var SUPERVISOR_USAGE = "Usage: ordewell supervisor [off|watch|act] \xB7 ordewell supervisor retries <n> \xB7 ordewell supervisor reads <n>";
3787
3897
  var AUTOMERGE_USAGE = "Usage: ordewell automerge [on|off]";
3788
3898
  var AUTORUN_USAGE = "Usage: ordewell autorun [on|off]";
@@ -3793,28 +3903,28 @@ async function handleSupervisor(subArgs, injectedApi) {
3793
3903
  const [arg, value] = positionals(subArgs);
3794
3904
  let changes = null;
3795
3905
  if (arg === "off" || arg === "watch" || arg === "act") changes = { supervisorLevel: arg };
3796
- else if (arg === "retries") changes = maybe((0, import_core21.parseCount)(value, 0), (n) => ({ supervisorRetryLimit: n }));
3797
- else if (arg === "reads") changes = maybe((0, import_core21.parseCount)(value, 1), (n) => ({ wakeUpReadBudget: n }));
3906
+ else if (arg === "retries") changes = maybe((0, import_core23.parseCount)(value, 0), (n) => ({ supervisorRetryLimit: n }));
3907
+ else if (arg === "reads") changes = maybe((0, import_core23.parseCount)(value, 1), (n) => ({ wakeUpReadBudget: n }));
3798
3908
  if (arg !== void 0 && changes === null) fail(SUPERVISOR_USAGE);
3799
3909
  const api = await connect(subArgs, injectedApi);
3800
3910
  if (!changes) {
3801
- console.log((0, import_core21.supervisorSummary)((await api.getSettings()).run));
3911
+ console.log((0, import_core23.supervisorSummary)((await api.getSettings()).run));
3802
3912
  console.log(` ${SUPERVISOR_USAGE}`);
3803
3913
  return;
3804
3914
  }
3805
3915
  await save(api, changes);
3806
- if (changes.supervisorLevel) console.log(`Supervisor: ${import_core21.SUPERVISOR_LEVEL_LABEL[changes.supervisorLevel]}, from each session's next run.`);
3807
- if (changes.supervisorLevel === "act") console.log(import_core21.ACT_RISK);
3916
+ if (changes.supervisorLevel) console.log(`Supervisor: ${import_core23.SUPERVISOR_LEVEL_LABEL[changes.supervisorLevel]}, from each session's next run.`);
3917
+ if (changes.supervisorLevel === "act") console.log(import_core23.ACT_RISK);
3808
3918
  if (changes.supervisorRetryLimit !== void 0) console.log(`Supervisor retry limit: ${changes.supervisorRetryLimit} per task.`);
3809
3919
  if (changes.wakeUpReadBudget !== void 0) console.log(`Wake-up read budget: ${changes.wakeUpReadBudget} reads.`);
3810
3920
  }
3811
3921
  async function handleAutomerge(subArgs, injectedApi) {
3812
3922
  const [arg] = positionals(subArgs);
3813
- const enabled = arg === void 0 ? null : (0, import_core21.parseSwitch)(arg);
3923
+ const enabled = arg === void 0 ? null : (0, import_core23.parseSwitch)(arg);
3814
3924
  if (arg !== void 0 && enabled === null) fail(AUTOMERGE_USAGE);
3815
3925
  const api = await connect(subArgs, injectedApi);
3816
3926
  if (enabled === null) {
3817
- console.log((0, import_core21.automergeSummary)((await api.getSettings()).run));
3927
+ console.log((0, import_core23.automergeSummary)((await api.getSettings()).run));
3818
3928
  console.log(` ${AUTOMERGE_USAGE}`);
3819
3929
  return;
3820
3930
  }
@@ -3823,24 +3933,24 @@ async function handleAutomerge(subArgs, injectedApi) {
3823
3933
  }
3824
3934
  async function handleAutorun(subArgs, injectedApi) {
3825
3935
  const [arg] = positionals(subArgs);
3826
- const enabled = arg === void 0 ? null : (0, import_core21.parseSwitch)(arg);
3936
+ const enabled = arg === void 0 ? null : (0, import_core23.parseSwitch)(arg);
3827
3937
  if (arg !== void 0 && enabled === null) fail(AUTORUN_USAGE);
3828
3938
  const api = await connect(subArgs, injectedApi);
3829
3939
  if (enabled === null) {
3830
- console.log((0, import_core21.autorunSummary)((await api.getSettings()).run));
3940
+ console.log((0, import_core23.autorunSummary)((await api.getSettings()).run));
3831
3941
  console.log(` ${AUTORUN_USAGE}`);
3832
3942
  return;
3833
3943
  }
3834
3944
  await save(api, { autorun: enabled });
3835
3945
  console.log(`Autorun: ${enabled ? "on \u2014 each plan the planner submits starts at once" : "off \u2014 plans wait for your review"}.`);
3836
- if (enabled) console.log(import_core21.AUTORUN_RISK);
3946
+ if (enabled) console.log(import_core23.AUTORUN_RISK);
3837
3947
  }
3838
3948
  function maybe(n, wrap2) {
3839
3949
  return n === null ? null : wrap2(n);
3840
3950
  }
3841
3951
 
3842
3952
  // src/commands/key.ts
3843
- var import_core22 = require("@ordewell/core");
3953
+ var import_core24 = require("@ordewell/core");
3844
3954
  var USAGE6 = "Usage: ordewell key [list | set <provider> <key>]";
3845
3955
  async function handleKey(subArgs, injectedApi) {
3846
3956
  const [action, provider, ...keyParts] = positionals(subArgs);
@@ -3851,8 +3961,8 @@ async function handleKey(subArgs, injectedApi) {
3851
3961
  if (action !== "set") {
3852
3962
  const catalog = await fetchCatalog(api);
3853
3963
  console.log("\nAPI provider keys\n");
3854
- for (const id2 of import_core22.PROVIDER_PRIORITY) {
3855
- const meta2 = import_core22.ALL_PROVIDERS[id2];
3964
+ for (const id2 of import_core24.PROVIDER_PRIORITY) {
3965
+ const meta2 = (0, import_core24.getProviderMeta)(id2);
3856
3966
  const configured = catalog.providers.includes(id2);
3857
3967
  console.log(` ${configured ? "\u2713" : " "} ${id2.padEnd(14)} ${meta2.apiKeyEnvVar.padEnd(28)} ${meta2.label}`);
3858
3968
  }
@@ -3862,10 +3972,10 @@ async function handleKey(subArgs, injectedApi) {
3862
3972
  }
3863
3973
  if (!provider) fail(USAGE6);
3864
3974
  const id = provider.toLowerCase();
3865
- const meta = import_core22.ALL_PROVIDERS[id];
3866
- if (!meta) {
3975
+ if (!(0, import_core24.isApiProvider)(id)) {
3867
3976
  fail(`Unknown provider: ${provider}`, "Run `ordewell key` to see the list.");
3868
3977
  }
3978
+ const meta = (0, import_core24.getProviderMeta)(id);
3869
3979
  const key = keyParts.join(" ").trim();
3870
3980
  if (!key) fail(`Usage: ordewell key set ${id} <key>`);
3871
3981
  await persistEnv(api, { [meta.apiKeyEnvVar]: key });
@@ -3873,7 +3983,7 @@ async function handleKey(subArgs, injectedApi) {
3873
3983
  }
3874
3984
 
3875
3985
  // src/commands/runners.ts
3876
- var import_core23 = require("@ordewell/core");
3986
+ var import_core25 = require("@ordewell/core");
3877
3987
  var USAGE7 = "Usage: ordewell runners [<runner-id> on|off]";
3878
3988
  async function handleRunners(subArgs, injectedApi) {
3879
3989
  const [runner, toggle] = positionals(subArgs);
@@ -3884,7 +3994,7 @@ async function handleRunners(subArgs, injectedApi) {
3884
3994
  for (const r of state2.runners) {
3885
3995
  console.log(` ${r.enabled ? "\u2713" : " "} ${r.id.padEnd(14)} ${r.name}${r.enabled ? "" : " (disabled)"}`);
3886
3996
  }
3887
- const notice = (0, import_core23.codexSandboxNotice)((await fetchCatalog(api).catch(() => null))?.modesByRunner);
3997
+ const notice = (0, import_core25.codexSandboxNotice)((await fetchCatalog(api).catch(() => null))?.modesByRunner);
3888
3998
  if (notice) console.log(`
3889
3999
  ${notice.line}
3890
4000
  ${notice.docs}`);
@@ -3905,17 +4015,17 @@ async function handleRunners(subArgs, injectedApi) {
3905
4015
  var AUTO_USAGE = "Usage: ordewell auto [full|guarded]";
3906
4016
  function handleAuto(subArgs) {
3907
4017
  const [arg] = positionals(subArgs);
3908
- const settings = new import_core23.SettingsService();
4018
+ const settings = new import_core25.SettingsService();
3909
4019
  const current = settings.autonomousMode();
3910
4020
  if (!arg) {
3911
- console.log(`Autonomy level: ${(0, import_core23.autonomyLevelLabel)(current)}`);
4021
+ console.log(`Autonomy level: ${(0, import_core25.autonomyLevelLabel)(current)}`);
3912
4022
  console.log(` ${AUTO_USAGE}`);
3913
4023
  return;
3914
4024
  }
3915
- const enabled = (0, import_core23.parseAutonomyLevel)(arg);
4025
+ const enabled = (0, import_core25.parseAutonomyLevel)(arg);
3916
4026
  if (enabled === null) fail(AUTO_USAGE);
3917
4027
  settings.setAutonomousMode(enabled);
3918
- console.log(settings.autonomousModeOverridden() ? `${(0, import_core23.autonomyLevelLabel)(enabled)} is saved, but ORDEWELL_AUTONOMOUS_MODE in the environment decides the level until it is unset.` : `Autonomy level: ${(0, import_core23.autonomyLevelLabel)(enabled)} for new plans.`);
4028
+ console.log(settings.autonomousModeOverridden() ? `${(0, import_core25.autonomyLevelLabel)(enabled)} is saved, but ORDEWELL_AUTONOMOUS_MODE in the environment decides the level until it is unset.` : `Autonomy level: ${(0, import_core25.autonomyLevelLabel)(enabled)} for new plans.`);
3919
4029
  }
3920
4030
  async function handleRefresh(subArgs, injectedApi) {
3921
4031
  const api = await connect(subArgs, injectedApi);
@@ -3945,7 +4055,7 @@ async function handleApprove(subArgs, injectedApi) {
3945
4055
  }
3946
4056
 
3947
4057
  // src/commands/task-assign.ts
3948
- var import_core25 = require("@ordewell/core");
4058
+ var import_core27 = require("@ordewell/core");
3949
4059
  var import_plan_utils = require("@ordewell/core/plan-utils");
3950
4060
 
3951
4061
  // src/tui/taskAssignment.ts
@@ -3985,7 +4095,7 @@ function modesForTask(modesByRunner, task) {
3985
4095
  }
3986
4096
 
3987
4097
  // src/tui/state.ts
3988
- var import_core24 = require("@ordewell/core");
4098
+ var import_core26 = require("@ordewell/core");
3989
4099
 
3990
4100
  // src/tui/editor.ts
3991
4101
  function emptyEditor() {
@@ -4143,7 +4253,7 @@ function queuedTarget(tv) {
4143
4253
  for (let i = queued.length - 1; i >= 0; i--) if (!queued[i].forced) return i;
4144
4254
  return -1;
4145
4255
  }
4146
- var anyTaskRunning = (state) => state.tasks.some(import_core24.isTaskRunning);
4256
+ var anyTaskRunning = (state) => state.tasks.some(import_core26.isTaskRunning);
4147
4257
  var plannerInFlight = (state) => state.planner !== "idle";
4148
4258
  var planPaneOpen = (state) => state.focus === "plan" && !state.overlay && (!!state.taskEditor || !!state.expandedTaskId);
4149
4259
  function planRows(state) {
@@ -4163,8 +4273,8 @@ function selectedPlanRow(state) {
4163
4273
  }
4164
4274
  function runnerCommands(tv) {
4165
4275
  for (let i = tv.view.blocks.length - 1; i >= 0; i--) {
4166
- const block = tv.view.blocks[i];
4167
- if (block.type === "runner_loaded") return block.commands;
4276
+ const block2 = tv.view.blocks[i];
4277
+ if (block2.type === "runner_loaded") return block2.commands;
4168
4278
  }
4169
4279
  return [];
4170
4280
  }
@@ -4189,10 +4299,10 @@ function findTask(tasks, id) {
4189
4299
  return void 0;
4190
4300
  }
4191
4301
  function refFor(state, task) {
4192
- return (0, import_core24.taskRefOf)(state.tasks, task.id) ?? (0, import_core24.taskRef)(task);
4302
+ return (0, import_core26.taskRefOf)(state.tasks, task.id) ?? (0, import_core26.taskRef)(task);
4193
4303
  }
4194
4304
  function titledRefFor(state, task) {
4195
- return (0, import_core24.titledTaskRefOf)(state.tasks, task.id) ?? (0, import_core24.titledTaskRef)(task);
4305
+ return (0, import_core26.titledTaskRefOf)(state.tasks, task.id) ?? (0, import_core26.titledTaskRef)(task);
4196
4306
  }
4197
4307
  function asRunTasks(tasks) {
4198
4308
  return tasks.map((task) => ({ ...task, subtasks: asRunTasks(task.subtasks ?? []) }));
@@ -4200,7 +4310,7 @@ function asRunTasks(tasks) {
4200
4310
  function seedRun(overrides) {
4201
4311
  if (overrides.run) return overrides.run;
4202
4312
  return {
4203
- ...import_core24.EMPTY_RUN,
4313
+ ...import_core26.EMPTY_RUN,
4204
4314
  tasks: asRunTasks(overrides.tasks ?? []),
4205
4315
  handoff: overrides.handoff ?? null,
4206
4316
  runMerge: overrides.runMerge ? { waitingAtGate: overrides.runMerge.waitingAtGate, paused: overrides.runMerge.paused, repos: overrides.runMerge.handoff.repos, landed: overrides.runMerge.handoff.landed } : null
@@ -4209,9 +4319,9 @@ function seedRun(overrides) {
4209
4319
  function initialState(overrides = {}) {
4210
4320
  return {
4211
4321
  editor: emptyEditor(),
4212
- conversation: import_core24.EMPTY_CONVERSATION,
4322
+ conversation: import_core26.EMPTY_CONVERSATION,
4213
4323
  taskView: null,
4214
- turnGate: import_core24.NO_TURN,
4324
+ turnGate: import_core26.NO_TURN,
4215
4325
  detailAll: false,
4216
4326
  status: "idle",
4217
4327
  planner: "idle",
@@ -4237,11 +4347,11 @@ function initialState(overrides = {}) {
4237
4347
  plannerProvider: "",
4238
4348
  plannerEffort: "",
4239
4349
  plannerModels: {},
4240
- maxParallel: import_core24.DEFAULT_MAX_PARALLEL,
4350
+ maxParallel: import_core26.DEFAULT_MAX_PARALLEL,
4241
4351
  configuredProviders: [],
4242
4352
  allowlist: {},
4243
4353
  autonomous: true,
4244
- runSettings: { ...import_core24.RUN_SETTINGS_DEFAULTS },
4354
+ runSettings: { ...import_core26.RUN_SETTINGS_DEFAULTS },
4245
4355
  runAutoMerge: null,
4246
4356
  runSupervisor: null,
4247
4357
  mouseCapture: true,
@@ -4251,7 +4361,7 @@ function initialState(overrides = {}) {
4251
4361
  runMerge: null,
4252
4362
  overlay: null,
4253
4363
  pendingApprovals: [],
4254
- queuedPrompts: import_core24.EMPTY_HOLD,
4364
+ queuedPrompts: import_core26.EMPTY_HOLD,
4255
4365
  stopArmed: false,
4256
4366
  stopArmToken: 0,
4257
4367
  stopRequested: false,
@@ -4385,7 +4495,7 @@ Mode \xB7 ${namedOf(tasks, task)}${task.assignedRunner ? ` (${task.assignedRunne
4385
4495
  for (const m of modes) {
4386
4496
  console.log(` ${m.id === task.taskMode ? "*" : " "} ${m.id.padEnd(14)} ${m.label}${m.unavailable ? " \u2014 unavailable on this host" : m.description ? ` \u2014 ${m.description}` : ""}`);
4387
4497
  }
4388
- const notice = (0, import_core25.codexSandboxNotice)(catalog.modesByRunner);
4498
+ const notice = (0, import_core27.codexSandboxNotice)(catalog.modesByRunner);
4389
4499
  if (notice) console.log(`
4390
4500
  ${notice.line}
4391
4501
  ${notice.docs}`);
@@ -4434,7 +4544,7 @@ var SKILLS_USAGE = "Usage: ordewell task-skills <task-id-or-order> [<name> [<nam
4434
4544
  async function handleTaskSkills(subArgs, injectedApi) {
4435
4545
  await withTask(subArgs, SKILLS_USAGE, injectedApi, async (api, sessionId, task, tasks, value) => {
4436
4546
  if (task.type !== "ai") fail("Manual tasks do not run an executor, so they take no skills.");
4437
- const catalog = (0, import_core25.createSkillsService)(flag(subArgs, "--workspace") || process.cwd(), new import_core25.EnvConfig().workspaceRepos).listSkills().filter((s) => s.appliesTo === "task");
4547
+ const catalog = (0, import_core27.createSkillsService)(flag(subArgs, "--workspace") || process.cwd(), new import_core27.EnvConfig().workspaceRepos).listSkills().filter((s) => s.appliesTo === "task");
4438
4548
  if (!value) {
4439
4549
  console.log(`
4440
4550
  Skills \xB7 ${namedOf(tasks, task)}
@@ -4479,10 +4589,10 @@ ${namedOf(tasks, task)} is ${task.ops ? "an ops task: it runs in your checkout o
4479
4589
  }
4480
4590
 
4481
4591
  // src/tui/index.ts
4482
- var import_core45 = require("@ordewell/core");
4592
+ var import_core48 = require("@ordewell/core");
4483
4593
 
4484
4594
  // src/tui/slash.ts
4485
- var import_core26 = require("@ordewell/core");
4595
+ var import_core28 = require("@ordewell/core");
4486
4596
  var SLASH_COMMANDS = [
4487
4597
  // Planning. There is deliberately no `/plan`: typing the goal *is* the way to
4488
4598
  // start planning, and an alias for it only shadowed `/planner` on completion.
@@ -4515,7 +4625,7 @@ var SLASH_COMMANDS = [
4515
4625
  { name: "planner-effort", usage: "/planner-effort [<level>]", description: "Thinking effort for a coding-agent planner", category: "models" },
4516
4626
  { name: "key", usage: "/key [set <provider> <key>]", description: "Configure API provider keys", category: "models" },
4517
4627
  { name: "allowlist", usage: "/allowlist [set <runner> <ids> | clear <runner>]", description: "Limit which models a runner may use", category: "models" },
4518
- { name: "runners", usage: "/runners [<id> on|off]", description: "Enable or disable runners (claude-code, opencode, codex)", category: "models" },
4628
+ { name: "runners", usage: "/runners [<id> on|off]", description: `Enable or disable runners (${runnerIdList()})`, category: "models" },
4519
4629
  { name: "auto", usage: "/auto [full|guarded]", description: "Autonomy level for new plans: Full or Guarded", category: "models" },
4520
4630
  { name: "supervisor", usage: "/supervisor [off|watch|act] \xB7 retries <n> \xB7 reads <n>", description: "Whether the planner watches or acts on your runs, now and from then on", category: "models" },
4521
4631
  { name: "automerge", usage: "/automerge [on|off]", description: "Merge into your branch by itself at merge gates and at the end of a run", category: "models" },
@@ -4601,7 +4711,7 @@ function parseRunnerCommand(text) {
4601
4711
  return match ? { name: match[1], args: (match[2] ?? "").trim() } : null;
4602
4712
  }
4603
4713
  function runnerCommandFor(commands, name) {
4604
- return (0, import_core26.findRunnerCommand)(commands, name) ?? (0, import_core26.findRunnerCommand)(commands, name.toLowerCase());
4714
+ return (0, import_core28.findRunnerCommand)(commands, name) ?? (0, import_core28.findRunnerCommand)(commands, name.toLowerCase());
4605
4715
  }
4606
4716
  function composerCompletions(token, runner) {
4607
4717
  if (runner) return token.start === 0 ? runner.filter((c) => c.name.toLowerCase().startsWith(token.name)).map((c) => c.name) : [];
@@ -4648,10 +4758,10 @@ function chatEditorRoomFor(state, active) {
4648
4758
  }
4649
4759
 
4650
4760
  // src/tui/layout.ts
4651
- var import_core29 = require("@ordewell/core");
4761
+ var import_core31 = require("@ordewell/core");
4652
4762
 
4653
4763
  // src/tui/reducers/pickers.ts
4654
- var import_core27 = require("@ordewell/core");
4764
+ var import_core29 = require("@ordewell/core");
4655
4765
  var import_plan_utils2 = require("@ordewell/core/plan-utils");
4656
4766
  var DEFAULT_EFFORT = "__runner_default__";
4657
4767
  function picker(title, items, action, extra = {}) {
@@ -4670,11 +4780,11 @@ function modelDetail(m) {
4670
4780
  function providerErrorHint(state) {
4671
4781
  const failed = Object.keys(state.providerErrors ?? {});
4672
4782
  if (failed.length === 0) return void 0;
4673
- const names = failed.map((p) => import_core27.ALL_PROVIDERS[p]?.label ?? p);
4783
+ const names = failed.map((p) => (0, import_core29.getProviderMeta)(p)?.label ?? p);
4674
4784
  return `\u26A0 Unavailable (key or fetch failed): ${names.join(", ")} \u2014 showing working providers only.`;
4675
4785
  }
4676
4786
  function plannerModelItems(state, provider, selectedId) {
4677
- const runner = (0, import_core27.runnerForProvider)(provider);
4787
+ const runner = (0, import_core29.runnerForProvider)(provider);
4678
4788
  if (!runner) {
4679
4789
  return state.orchestratorModels.map((m) => ({ id: m.id, label: m.label, detail: modelDetail(m), selected: m.id === selectedId }));
4680
4790
  }
@@ -4690,11 +4800,11 @@ function plannerModelItems(state, provider, selectedId) {
4690
4800
  return items.length > 0 ? items : [{ id: "", label: `No ${runner} models discovered yet`, detail: "run /refresh", disabled: true }];
4691
4801
  }
4692
4802
  function plannerHarnessModel(state, provider, modelId) {
4693
- const runner = (0, import_core27.runnerForProvider)(provider);
4803
+ const runner = (0, import_core29.runnerForProvider)(provider);
4694
4804
  return runner ? state.models.find((m) => m.id === modelId && m.runners?.includes(runner)) : void 0;
4695
4805
  }
4696
4806
  function plannerEffortItems(state, provider, modelId, selectedEffort) {
4697
- if (!(0, import_core27.runnerForProvider)(provider)) {
4807
+ if (!(0, import_core29.runnerForProvider)(provider)) {
4698
4808
  return [{ id: "", label: "Thinking effort applies to a coding-agent planner", detail: "switch with /planner", disabled: true }];
4699
4809
  }
4700
4810
  const model = plannerHarnessModel(state, provider, modelId);
@@ -4812,11 +4922,11 @@ function pickerItemsFor(state, action) {
4812
4922
  function plannerItems(state) {
4813
4923
  const installed = new Set(state.runners.map((r) => r.id));
4814
4924
  const usability = {};
4815
- for (const id of import_core27.CLI_PROVIDERS) {
4816
- const runner = (0, import_core27.runnerForProvider)(id);
4925
+ for (const id of import_core29.CLI_PROVIDERS) {
4926
+ const runner = (0, import_core29.runnerForProvider)(id);
4817
4927
  usability[runner] = installed.has(runner) ? { usable: true } : { usable: false, reason: "CLI not installed or not on PATH" };
4818
4928
  }
4819
- const entries = (0, import_core27.plannerBackendEntries)(usability, state.configuredProviders);
4929
+ const entries = (0, import_core29.plannerBackendEntries)(usability, state.configuredProviders);
4820
4930
  const items = entries.map((entry) => ({
4821
4931
  id: entry.id,
4822
4932
  label: entry.label,
@@ -4841,7 +4951,7 @@ function cliVersion() {
4841
4951
  }
4842
4952
 
4843
4953
  // src/tui/planKeys.ts
4844
- var import_core28 = require("@ordewell/core");
4954
+ var import_core30 = require("@ordewell/core");
4845
4955
  var PLAN_KEYS = {
4846
4956
  move: { keys: "up / down", meaning: "move between tasks", group: "Navigation" },
4847
4957
  scroll: { keys: "pgup / pgdn", meaning: "scroll the plan", group: "Navigation" },
@@ -4868,7 +4978,7 @@ var PLAN_KEYS = {
4868
4978
  meaning: "cancel the task's runner, or keep a task paused on a usage limit from resuming on its own",
4869
4979
  group: "Run",
4870
4980
  // `c` cancels the resume while the task has one; it has no runner to cancel then.
4871
- hint: (task) => task && (0, import_core28.resumeLabel)(task) ? "c don't resume" : "c cancel"
4981
+ hint: (task) => task && (0, import_core30.resumeLabel)(task) ? "c don't resume" : "c cancel"
4872
4982
  },
4873
4983
  resume: { keys: "r", meaning: "resume a task paused on a usage limit now, once the limit has reset", group: "Run", hint: "r resume now" },
4874
4984
  resolve: { keys: "x", meaning: "resolve a merge conflict", group: "Run", hint: "x resolve conflict" },
@@ -4878,7 +4988,7 @@ var PLAN_KEYS = {
4878
4988
  meaning: "mark the task done, or take it back",
4879
4989
  group: "Status",
4880
4990
  // `m` toggles, so the hint names the direction it will go for this task.
4881
- hint: (task) => task && (0, import_core28.markAction)(task) === "uncomplete" ? "m undone" : "m done"
4991
+ hint: (task) => task && (0, import_core30.markAction)(task) === "uncomplete" ? "m undone" : "m done"
4882
4992
  },
4883
4993
  skip: { keys: "s", meaning: "skip the task: none of its work lands, and what depends on it goes ahead", group: "Status", hint: "s skip" },
4884
4994
  remove: { keys: "d", meaning: "remove the task", group: "Status" },
@@ -4905,7 +5015,7 @@ function hintOf(id, task) {
4905
5015
  }
4906
5016
  function taskKeyIds(task, runActive) {
4907
5017
  if (!task) return ["add"];
4908
- const row = (0, import_core28.taskRowView)(task);
5018
+ const row = (0, import_core30.taskRowView)(task);
4909
5019
  if (row.conflict) return ["resolve", "log"];
4910
5020
  if (row.actions.includes("resume-now") || row.resumes) {
4911
5021
  return [...row.actions.includes("resume-now") ? ["resume"] : [], ...row.resumes ? ["cancel"] : [], "skip", "log"];
@@ -4933,7 +5043,7 @@ function planFooterHints(task, runActive) {
4933
5043
  }
4934
5044
 
4935
5045
  // src/tui/layout.ts
4936
- var import_core30 = require("@ordewell/core");
5046
+ var import_core32 = require("@ordewell/core");
4937
5047
  var CHROME_ROWS = 1;
4938
5048
  function chatInputWrap(state) {
4939
5049
  const active = state.focus === "chat" && !state.overlay;
@@ -4959,7 +5069,7 @@ function footerHints(state) {
4959
5069
  }
4960
5070
  return [...escHint ? [escHint] : [], ...planFooterHints(selected, state.status === "executing")];
4961
5071
  }
4962
- const detailHint = (0, import_core30.hasHiddenDetail)(state.taskView ? state.taskView.view.blocks : state.conversation.blocks) ? [state.detailAll ? "ctrl-o collapse all" : "ctrl-o expand all"] : [];
5072
+ const detailHint = (0, import_core32.hasHiddenDetail)(state.taskView ? state.taskView.view.blocks : state.conversation.blocks) ? [state.detailAll ? "ctrl-o collapse all" : "ctrl-o expand all"] : [];
4963
5073
  return [
4964
5074
  "/help",
4965
5075
  ...checkpointHints,
@@ -5018,12 +5128,12 @@ function queuedTaskBubble(message, target, sends, cols) {
5018
5128
  }
5019
5129
  function taskActivity(task, working) {
5020
5130
  if (task?.status === "completed" || task?.status === "failed") return task.status;
5021
- const approvals = (0, import_core30.approvalLabel)(task?.awaitingApproval);
5131
+ const approvals = (0, import_core32.approvalLabel)(task?.awaitingApproval);
5022
5132
  if (approvals) return inRow(approvals);
5023
5133
  if (working) return "working";
5024
5134
  if (task?.status === "awaiting_user") {
5025
- const resumes = (0, import_core30.resumeLabel)(task);
5026
- return [inRow((0, import_core30.awaitingLabel)(task) ?? "Waiting for your input"), resumes ? inRow(resumes) : ""].filter(Boolean).join(" \xB7 ");
5135
+ const resumes = (0, import_core32.resumeLabel)(task);
5136
+ return [inRow((0, import_core32.awaitingLabel)(task) ?? "Waiting for your input"), resumes ? inRow(resumes) : ""].filter(Boolean).join(" \xB7 ");
5027
5137
  }
5028
5138
  return task?.status ?? "";
5029
5139
  }
@@ -5036,7 +5146,7 @@ function taskHeaderLines(state, tv, cols) {
5036
5146
  taskActivity(task, tv.view.working)
5037
5147
  ].filter(Boolean);
5038
5148
  const approval = waitingApproval(tv);
5039
- const hint = approval ? ["ctrl-y allow", ...approval.allowForTask ? ["ctrl-t allow for task"] : [], "ctrl-g deny (composer text is the note)"] : waitingCheckpoint(task) ? ["enter reply", "ctrl-y approve", "ctrl-g reject", "ctrl-x stop runner"] : task && (0, import_core30.resumeLabel)(task) ? ["ctrl-x don't resume"] : [...runnerStoppable(state) ? ["ctrl-x stop runner"] : [], "ctrl-r remove queued", "ctrl-s send now"];
5149
+ const hint = approval ? ["ctrl-y allow", ...approval.allowForTask ? ["ctrl-t allow for task"] : [], "ctrl-g deny (composer text is the note)"] : waitingCheckpoint(task) ? ["enter reply", "ctrl-y approve", "ctrl-g reject", "ctrl-x stop runner"] : task && (0, import_core32.resumeLabel)(task) ? ["ctrl-x don't resume"] : [...runnerStoppable(state) ? ["ctrl-x stop runner"] : [], "ctrl-r remove queued", "ctrl-s send now"];
5040
5150
  if (approval && waitingCheckpoint(task)) hint.push("then the checkpoint");
5041
5151
  const index = tv.attempts.indexOf(tv.attempt);
5042
5152
  if (tv.attempts.length > 1) hint.push(`alt\u2190/\u2192 attempt ${index >= 0 ? index + 1 : 1}/${tv.attempts.length}`);
@@ -5066,9 +5176,9 @@ function chatActivity(state) {
5066
5176
  const own = findTask(state.tasks, tv.taskId);
5067
5177
  const task = state.tasks.find((t) => t.subtasks?.some((s) => s.id === tv.taskId)) ?? own;
5068
5178
  if (!task) return null;
5069
- if ((0, import_core24.isTaskRunning)(task) || own && (0, import_core24.isTaskRunning)(own)) return { label: "Working\u2026", busy: true };
5179
+ if ((0, import_core26.isTaskRunning)(task) || own && (0, import_core26.isTaskRunning)(own)) return { label: "Working\u2026", busy: true };
5070
5180
  const at = task.status === "awaiting_user" && task.awaitingReason === "usage-limit" && task.resumeAt ? new Date(task.resumeAt) : null;
5071
- if (at && !Number.isNaN(at.getTime())) return { label: `paused \xB7 resumes ${(0, import_core30.resumeTime)(at)}`, busy: false };
5181
+ if (at && !Number.isNaN(at.getTime())) return { label: `paused \xB7 resumes ${(0, import_core32.resumeTime)(at)}`, busy: false };
5072
5182
  return null;
5073
5183
  }
5074
5184
  function runHints(state) {
@@ -5097,41 +5207,41 @@ function bodyRows(state) {
5097
5207
  return Math.max(0, state.rows - CHROME_ROWS - composerRows(state) - footer);
5098
5208
  }
5099
5209
  var chatBodyMemo = null;
5100
- function chatBodyLines(blocks, cols, detailAll, answering) {
5210
+ function chatBodyLines(blocks2, cols, detailAll, answering) {
5101
5211
  const memo = chatBodyMemo;
5102
- if (memo && memo.blocks === blocks && memo.cols === cols && memo.detailAll === detailAll) return memo.lines;
5103
- const lines = conversationLines(blocks, cols, detailAll, answering);
5104
- chatBodyMemo = { blocks, cols, detailAll, lines };
5212
+ if (memo && memo.blocks === blocks2 && memo.cols === cols && memo.detailAll === detailAll) return memo.lines;
5213
+ const lines = conversationLines(blocks2, cols, detailAll, answering);
5214
+ chatBodyMemo = { blocks: blocks2, cols, detailAll, lines };
5105
5215
  return lines;
5106
5216
  }
5107
5217
  function chatLayout(state, rows, cols) {
5108
5218
  const tv = state.taskView;
5109
- const blocks = tv ? tv.view.blocks : state.conversation.blocks;
5219
+ const blocks2 = tv ? tv.view.blocks : state.conversation.blocks;
5110
5220
  const welcome = !tv && state.tasks.length === 0;
5111
5221
  const checkpoint = tv ? waitingCheckpoint(findTask(state.tasks, tv.taskId)) : void 0;
5112
5222
  const card = tv && checkpoint ? checkpointCardLines(findTask(state.tasks, tv.taskId)?.order ?? 0, checkpoint, cols, waitingApproval(tv) !== void 0) : [];
5113
- const answering = chatBodyLines(blocks, cols, state.detailAll, tv ? waitingApproval(tv) : void 0);
5223
+ const answering = chatBodyLines(blocks2, cols, state.detailAll, tv ? waitingApproval(tv) : void 0);
5114
5224
  const body = card.length > 0 ? [...answering, ...card] : answering;
5115
5225
  const transcript = !welcome ? body : body.length === 0 ? welcomeLines(state, rows, cols) : [...welcomeLines(state, rows, cols), "", ...body];
5116
5226
  const bubbles = tv ? taskQueuedRows(state, cols) : queuedPromptRows(state, cols);
5117
5227
  const content = [...transcript, ...bubbles.length > 0 ? ["", ...bubbles] : []];
5118
5228
  const taskHeader = tv ? taskHeaderLines(state, tv, cols) : [];
5119
- const usage = rows <= 1 ? [] : tv ? taskUsageFooter(state, tv, blocks, cols) : tokenRow(blocks, cols);
5229
+ const usage = rows <= 1 ? [] : tv ? taskUsageFooter(state, tv, blocks2, cols) : tokenRow(blocks2, cols);
5120
5230
  const footer = usage.slice(0, Math.max(1, rows - taskHeader.length - 1));
5121
5231
  const space = Math.max(0, rows - taskHeader.length - footer.length);
5122
5232
  return { lines: content, header: taskHeader, footer, anchor: content.length > space ? "bottom" : "top", maxScroll: Math.max(0, content.length - space) };
5123
5233
  }
5124
- var tokenRow = (blocks, cols) => {
5125
- const line = tokenLine(blocks, cols);
5234
+ var tokenRow = (blocks2, cols) => {
5235
+ const line = tokenLine(blocks2, cols);
5126
5236
  return line ? [line] : [];
5127
5237
  };
5128
- function taskUsageFooter(state, tv, blocks, cols) {
5238
+ function taskUsageFooter(state, tv, blocks2, cols) {
5129
5239
  const task = findTask(state.tasks, tv.taskId);
5130
5240
  const reported = task?.attemptUsage ?? [];
5131
5241
  const onScreen = tv.attempt > 0 ? reported.find((a) => a.attempt === tv.attempt) : reported.at(-1);
5132
- if (!task || !onScreen) return tokenRow(blocks, cols);
5133
- const usage = (0, import_core30.taskRowView)({ ...task, attemptUsage: [onScreen] }).usage;
5134
- if (!usage) return tokenRow(blocks, cols);
5242
+ if (!task || !onScreen) return tokenRow(blocks2, cols);
5243
+ const usage = (0, import_core32.taskRowView)({ ...task, attemptUsage: [onScreen] }).usage;
5244
+ if (!usage) return tokenRow(blocks2, cols);
5135
5245
  const models = usage.byModel ?? [];
5136
5246
  return [
5137
5247
  style.grey(truncate(taskUsageText(usage), cols)),
@@ -5143,17 +5253,17 @@ function chatScrollMax(state) {
5143
5253
  }
5144
5254
  function plannerSetup(state) {
5145
5255
  const provider = state.plannerProvider;
5146
- const registration = import_core30.ALL_PROVIDERS[provider];
5256
+ const registration = (0, import_core32.getProviderMeta)(provider);
5147
5257
  if (!registration) return { label: "not set", ready: false };
5148
- const runner = (0, import_core30.runnerForProvider)(provider);
5149
- const ready = runner ? state.runners.some((r) => r.id === runner) : state.configuredProviders.includes(provider);
5258
+ const runner = (0, import_core32.runnerForProvider)(provider);
5259
+ const ready = runner ? state.runners.some((r) => r.id === runner) : (0, import_core32.isApiProvider)(provider) && state.configuredProviders.includes(provider);
5150
5260
  return { label: registration.label, ready };
5151
5261
  }
5152
5262
  var SETUP_KEY_COLS = 10;
5153
5263
  var SETUP_VALUE_COLS = 32;
5154
5264
  function runSettingsValue(state) {
5155
5265
  const { supervisorLevel, mergeAtGatesAutomatically, autorun } = state.runSettings;
5156
- const level = `supervisor ${import_core29.SUPERVISOR_LEVEL_LABEL[supervisorLevel]}`;
5266
+ const level = `supervisor ${import_core31.SUPERVISOR_LEVEL_LABEL[supervisorLevel]}`;
5157
5267
  return [
5158
5268
  supervisorLevel === "act" ? style.yellow(level) : level,
5159
5269
  `auto-merge ${mergeAtGatesAutomatically ? "on" : "off"}`,
@@ -5254,7 +5364,7 @@ function welcomeLines(state, rows, cols) {
5254
5364
  ];
5255
5365
  const notice = canPlan ? [] : [
5256
5366
  ...wrap(
5257
- style.yellow("Ordewell needs one coding agent installed (Claude Code, Codex, OpenCode) \u2014 or an API key from a provider such as OpenRouter, added with /key."),
5367
+ style.yellow(`Ordewell needs one coding agent installed (${runnerNamesOr()}) \u2014 or an API key from a provider such as OpenRouter, added with /key.`),
5258
5368
  Math.max(1, cols - 1)
5259
5369
  ),
5260
5370
  ""
@@ -5288,7 +5398,7 @@ var STATUS_ICON = {
5288
5398
  var inRow = (label) => label.charAt(0).toLowerCase() + label.slice(1);
5289
5399
  function planLayout(state, rows, cols) {
5290
5400
  const done = state.tasks.filter((t) => t.status === "completed").length;
5291
- const totalUsage = (0, import_core30.planUsage)(state.tasks);
5401
+ const totalUsage = (0, import_core32.planUsage)(state.tasks);
5292
5402
  const unmerged = state.runMerge?.handoff.landed.length ?? 0;
5293
5403
  const count = `${done}/${state.tasks.length}`;
5294
5404
  const hints = runHints(state);
@@ -5366,7 +5476,7 @@ function planScrollExtent(state) {
5366
5476
  }
5367
5477
  function taskLines(state, planRow, index, cols) {
5368
5478
  const { task, parent } = planRow;
5369
- const row = (0, import_core30.taskRowView)(task, { parent, tasks: state.tasks, modes: modesForTask(state.modesByRunner, task) });
5479
+ const row = (0, import_core32.taskRowView)(task, { parent, tasks: state.tasks, modes: modesForTask(state.modesByRunner, task) });
5370
5480
  const selected = state.focus === "plan" && index === state.selectedTask;
5371
5481
  const expanded = state.expandedTaskId === task.id;
5372
5482
  const rawIcon = row.status === "running" ? SPINNER[state.spinnerFrame % SPINNER.length] : STATUS_ICON[row.status];
@@ -5417,10 +5527,10 @@ function taskLines(state, planRow, index, cols) {
5417
5527
  lines.push(style.yellow(truncate(`${bodyPad}\u23F8 waits for Merge all \u2014 ${row.mergeGate.join(", ")} not merged into your branch yet`, cols)));
5418
5528
  }
5419
5529
  if (row.blockedBy) {
5420
- lines.push(style.red(truncate(`${bodyPad}\u2298 ${inRow((0, import_core30.blockedByLabel)(row.blockedBy))} \u2014 runs once ${row.blockedBy.length === 1 ? "it is retried and passes" : "they are retried and pass"}`, cols)));
5530
+ lines.push(style.red(truncate(`${bodyPad}\u2298 ${inRow((0, import_core32.blockedByLabel)(row.blockedBy))} \u2014 runs once ${row.blockedBy.length === 1 ? "it is retried and passes" : "they are retried and pass"}`, cols)));
5421
5531
  }
5422
5532
  if (row.status === "skipped") {
5423
- lines.push(style.grey(truncate(`${bodyPad}\xBB ${inRow((0, import_core30.skippedLabel)(row.skipReason))} \u2014 nothing of it landed; m done lands its kept work`, cols)));
5533
+ lines.push(style.grey(truncate(`${bodyPad}\xBB ${inRow((0, import_core32.skippedLabel)(row.skipReason))} \u2014 nothing of it landed; m done lands its kept work`, cols)));
5424
5534
  }
5425
5535
  const resumable = row.actions.includes("resume-now");
5426
5536
  if (row.resumes) {
@@ -5555,8 +5665,8 @@ function helpScrollMax(state) {
5555
5665
  }
5556
5666
 
5557
5667
  // src/tui/render.ts
5558
- var import_core31 = require("@ordewell/core");
5559
- var import_core32 = require("@ordewell/core");
5668
+ var import_core33 = require("@ordewell/core");
5669
+ var import_core34 = require("@ordewell/core");
5560
5670
  function render(state) {
5561
5671
  const { rows, cols } = state;
5562
5672
  const rowsForBody = bodyRows(state);
@@ -5655,8 +5765,8 @@ function runSettingsBadge(state) {
5655
5765
  const { supervisorLevel, mergeAtGatesAutomatically, autorun } = state.runSettings;
5656
5766
  const paint = (text, warn) => warn ? style.yellow(text) : style.grey(text);
5657
5767
  const run = state.status === "executing" ? state.runSupervisor : null;
5658
- const actual = run?.unsupervised ? "unsupervised" : run && run.level !== supervisorLevel ? import_core32.SUPERVISOR_LEVEL_LABEL[run.level] : null;
5659
- const level = `supervisor ${import_core32.SUPERVISOR_LEVEL_LABEL[supervisorLevel]}${actual ? ` \u2192 ${actual}` : ""}`;
5768
+ const actual = run?.unsupervised ? "unsupervised" : run && run.level !== supervisorLevel ? import_core34.SUPERVISOR_LEVEL_LABEL[run.level] : null;
5769
+ const level = `supervisor ${import_core34.SUPERVISOR_LEVEL_LABEL[supervisorLevel]}${actual ? ` \u2192 ${actual}` : ""}`;
5660
5770
  return [
5661
5771
  paint(level, supervisorLevel === "act"),
5662
5772
  ...mergeAtGatesAutomatically ? [style.grey("auto-merge")] : [],
@@ -5853,8 +5963,8 @@ function renderHandoff(state, overlay, rows, cols) {
5853
5963
  return frame(`Diff \u2014 ${handoffBranch(handoff)}`, [...shown, "", style.grey(`${more}enter or esc goes back`)], rows, cols);
5854
5964
  }
5855
5965
  const landed = handoff.landed.length === 0 ? [style.grey("Nothing landed on it.")] : handoff.landed.map((task) => {
5856
- const repaired = task.repairedFiles?.length ? style.yellow(` \u2014 repaired (${(0, import_core31.capConflictFiles)(task.repairedFiles)})`) : "";
5857
- return ` ${style.green("\u2713")} ${(0, import_core31.titledTaskRefOf)(state.tasks, task.taskId) ?? (0, import_core31.titledTaskRef)(task)}${repaired}`;
5966
+ const repaired = task.repairedFiles?.length ? style.yellow(` \u2014 repaired (${(0, import_core33.capConflictFiles)(task.repairedFiles)})`) : "";
5967
+ return ` ${style.green("\u2713")} ${(0, import_core33.titledTaskRefOf)(state.tasks, task.taskId) ?? (0, import_core33.titledTaskRef)(task)}${repaired}`;
5858
5968
  });
5859
5969
  const actions = handoffActions(handoff).map((action, index) => {
5860
5970
  const active = index === overlay.index;
@@ -5902,8 +6012,8 @@ function renderPicker(picker2, rows, cols) {
5902
6012
  ...picker2.filterable ? [["type", "to filter"]] : []
5903
6013
  ]);
5904
6014
  const room = Math.max(1, rows - head.length - 3);
5905
- const list = items.length === 0 ? [style.grey(picker2.filter ? "Nothing matches that filter." : "Nothing to show yet\u2026")] : pickerRows({ items, index: picker2.index, numbered: !picker2.filterable, chosen: picker2.multi ? picker2.chosen : void 0 }, room, inner);
5906
- return frame(picker2.title, [...head, ...list, "", footer], rows, cols);
6015
+ const list2 = items.length === 0 ? [style.grey(picker2.filter ? "Nothing matches that filter." : "Nothing to show yet\u2026")] : pickerRows({ items, index: picker2.index, numbered: !picker2.filterable, chosen: picker2.multi ? picker2.chosen : void 0 }, room, inner);
6016
+ return frame(picker2.title, [...head, ...list2, "", footer], rows, cols);
5907
6017
  }
5908
6018
  function renderStepper(stepper, rows, cols) {
5909
6019
  const { definition, trail } = stepper;
@@ -5934,13 +6044,13 @@ function renderStepper(stepper, rows, cols) {
5934
6044
  cancel
5935
6045
  ]);
5936
6046
  const room = Math.max(1, rows - head.length - 3);
5937
- const list = items.length === 0 ? [style.grey(stepper.filter ? "Nothing matches that filter." : "Nothing to show yet\u2026")] : pickerRows({ items, index: stepper.index, numbered: !active.filterable }, room, inner);
5938
- return frame(definition.title, [...head, ...list, "", footer], rows, cols);
6047
+ const list2 = items.length === 0 ? [style.grey(stepper.filter ? "Nothing matches that filter." : "Nothing to show yet\u2026")] : pickerRows({ items, index: stepper.index, numbered: !active.filterable }, room, inner);
6048
+ return frame(definition.title, [...head, ...list2, "", footer], rows, cols);
5939
6049
  }
5940
6050
  var DETAIL_GAP = 2;
5941
- function pickerRows(list, room, inner) {
5942
- const { items, numbered, chosen } = list;
5943
- const index = Math.max(0, Math.min(list.index, items.length - 1));
6051
+ function pickerRows(list2, room, inner) {
6052
+ const { items, numbered, chosen } = list2;
6053
+ const index = Math.max(0, Math.min(list2.index, items.length - 1));
5944
6054
  const digits = String(items.length).length;
5945
6055
  const prefixWidth = 2 + (numbered ? digits + 2 : 0) + (chosen ? 4 : 0);
5946
6056
  const rowWidth = Math.max(1, inner - prefixWidth);
@@ -5949,7 +6059,7 @@ function pickerRows(list, room, inner) {
5949
6059
  const labelWidth = items.some((item) => item.detail) ? Math.min(widest, Math.max(8, rowWidth - DETAIL_GAP - Math.max(16, Math.floor(rowWidth / 3)))) : Math.min(widest, rowWidth);
5950
6060
  const detailWidth = Math.max(1, rowWidth - labelWidth - DETAIL_GAP);
5951
6061
  const detailIndent = " ".repeat(prefixWidth + labelWidth + DETAIL_GAP);
5952
- const block = (item, i) => {
6062
+ const block2 = (item, i) => {
5953
6063
  const active = i === index;
5954
6064
  const current = isCurrent(item);
5955
6065
  const number = numbered ? `${String(i + 1).padStart(digits)}. ` : "";
@@ -5966,29 +6076,29 @@ function pickerRows(list, room, inner) {
5966
6076
  ];
5967
6077
  return active ? lines.map((line) => style.highlight(pad(line, inner))) : lines;
5968
6078
  };
5969
- const blocks = items.map(block);
5970
- if (blocks.reduce((n, b) => n + b.length, 0) <= room) return blocks.flat();
6079
+ const blocks2 = items.map(block2);
6080
+ if (blocks2.reduce((n, b) => n + b.length, 0) <= room) return blocks2.flat();
5971
6081
  const fit2 = Math.max(1, room - 2);
5972
6082
  let lo = index;
5973
6083
  let hi = index;
5974
- let used = blocks[index].length;
6084
+ let used = blocks2[index].length;
5975
6085
  for (let grew = true; grew; ) {
5976
6086
  grew = false;
5977
- if (hi + 1 < blocks.length && used + blocks[hi + 1].length <= fit2) {
6087
+ if (hi + 1 < blocks2.length && used + blocks2[hi + 1].length <= fit2) {
5978
6088
  hi += 1;
5979
- used += blocks[hi].length;
6089
+ used += blocks2[hi].length;
5980
6090
  grew = true;
5981
6091
  }
5982
- if (lo > 0 && used + blocks[lo - 1].length <= fit2) {
6092
+ if (lo > 0 && used + blocks2[lo - 1].length <= fit2) {
5983
6093
  lo -= 1;
5984
- used += blocks[lo].length;
6094
+ used += blocks2[lo].length;
5985
6095
  grew = true;
5986
6096
  }
5987
6097
  }
5988
6098
  return [
5989
6099
  ...lo > 0 ? [style.grey(` \u2191 \u2026 +${lo} more`)] : [],
5990
- ...blocks.slice(lo, hi + 1).flat().slice(0, fit2),
5991
- ...hi < blocks.length - 1 ? [style.grey(` \u2193 \u2026 +${blocks.length - 1 - hi} more`)] : []
6100
+ ...blocks2.slice(lo, hi + 1).flat().slice(0, fit2),
6101
+ ...hi < blocks2.length - 1 ? [style.grey(` \u2193 \u2026 +${blocks2.length - 1 - hi} more`)] : []
5992
6102
  ];
5993
6103
  }
5994
6104
  function keyHints(hints) {
@@ -6028,7 +6138,10 @@ function frame(title, body, rows, cols) {
6028
6138
  }
6029
6139
 
6030
6140
  // src/tui/reducer.ts
6031
- var import_core43 = require("@ordewell/core");
6141
+ var import_core46 = require("@ordewell/core");
6142
+
6143
+ // src/tui/reducers/overlays.ts
6144
+ var import_core45 = require("@ordewell/core");
6032
6145
 
6033
6146
  // src/tui/reducers/shared.ts
6034
6147
  function step(state, effects = []) {
@@ -6087,10 +6200,10 @@ function handleApprovalKey(state, overlay, key) {
6087
6200
  }
6088
6201
 
6089
6202
  // src/tui/reducers/commands.ts
6090
- var import_core42 = require("@ordewell/core");
6203
+ var import_core44 = require("@ordewell/core");
6091
6204
 
6092
6205
  // src/tui/reducers/plannerStepper.ts
6093
- var import_core33 = require("@ordewell/core");
6206
+ var import_core35 = require("@ordewell/core");
6094
6207
  var offered = (items) => new Set(items.filter((i) => !i.disabled).map((i) => i.id));
6095
6208
  function preferredModel(state, provider) {
6096
6209
  const listed = offered(plannerModelItems(state, provider, ""));
@@ -6138,7 +6251,7 @@ var plannerStepper = {
6138
6251
  const model = plannerModelItems(state, provider, "").find((m) => m.id === modelId);
6139
6252
  const level = plannerEffortItems(state, provider, modelId, "").find((e) => e.id === effort);
6140
6253
  const parts = [
6141
- import_core33.ALL_PROVIDERS[provider]?.label ?? provider,
6254
+ (0, import_core35.getProviderMeta)(provider)?.label ?? provider,
6142
6255
  model?.label ?? modelId,
6143
6256
  ...effort ? [effortLabel(level?.label ?? effort)] : []
6144
6257
  ];
@@ -6153,10 +6266,10 @@ var plannerStepper = {
6153
6266
  };
6154
6267
 
6155
6268
  // src/tui/reducers/stepper.ts
6156
- var import_core34 = require("@ordewell/core");
6269
+ var import_core36 = require("@ordewell/core");
6157
6270
  function openStepper(state, definition) {
6158
6271
  const { choices, lists } = settle(state, definition, {});
6159
- const first = lists.findIndex((list) => list !== null);
6272
+ const first = lists.findIndex((list2) => list2 !== null);
6160
6273
  if (first === -1) return definition.save(state, choices);
6161
6274
  return step({ ...state, overlay: { kind: "stepper", stepper: show2(state, definition, choices, first) } });
6162
6275
  }
@@ -6176,11 +6289,11 @@ function handleStepperKey(state, stepper, key) {
6176
6289
  const reopen = (next) => step({ ...state, overlay: { kind: "stepper", stepper: next } });
6177
6290
  const { definition, current, entry, choices } = stepper;
6178
6291
  const def = definition.steps[current];
6179
- const typed = def.number && entry ? (0, import_core34.parseCount)(entry.text, def.number.min) : null;
6292
+ const typed = def.number && entry ? (0, import_core36.parseCount)(entry.text, def.number.min) : null;
6180
6293
  const { lists } = settle(state, definition, choices);
6181
6294
  const items = matchingItems(stepper.items, stepper.filter);
6182
6295
  const before = lastIndexBefore(lists, current);
6183
- const after = lists.findIndex((list, i) => i > current && list !== null);
6296
+ const after = lists.findIndex((list2, i) => i > current && list2 !== null);
6184
6297
  if (key.name === "escape") return step({ ...state, overlay: null });
6185
6298
  if (key.name === "tab" || key.name === "right") return after === -1 ? reopen(stepper) : reopen(show2(state, definition, choices, after));
6186
6299
  if (key.name === "shift-tab" || key.name === "left") return before === -1 ? reopen(stepper) : reopen(show2(state, definition, choices, before));
@@ -6226,14 +6339,14 @@ function choose(state, stepper, value) {
6226
6339
  const saved = definition.save(open, choices);
6227
6340
  if (saved.state.overlay !== open.overlay) return saved;
6228
6341
  const { lists } = settle(saved.state, definition, choices);
6229
- const next = !definition.advanceOnEnter ? current : lists.findIndex((list, i) => i > current && list !== null);
6342
+ const next = !definition.advanceOnEnter ? current : lists.findIndex((list2, i) => i > current && list2 !== null);
6230
6343
  if (next === -1 || lists[next] === null) return { ...saved, state: { ...saved.state, overlay: null } };
6231
6344
  return { ...saved, state: { ...saved.state, overlay: { kind: "stepper", stepper: show2(saved.state, definition, choices, next) } } };
6232
6345
  }
6233
6346
  function reopenStepper(state, stepper) {
6234
6347
  const { definition, current } = stepper;
6235
6348
  const { lists } = settle(state, definition, {});
6236
- const at = lists[current] !== null ? current : lists.findIndex((list) => list !== null);
6349
+ const at = lists[current] !== null ? current : lists.findIndex((list2) => list2 !== null);
6237
6350
  if (at === -1) return { ...state, overlay: null };
6238
6351
  return { ...state, overlay: { kind: "stepper", stepper: show2(state, definition, {}, at) } };
6239
6352
  }
@@ -6242,7 +6355,7 @@ function settle(state, definition, wanted) {
6242
6355
  const lists = definition.steps.map((def) => {
6243
6356
  if (def.skip?.(state, { ...choices })) return null;
6244
6357
  if (def.number) {
6245
- choices[def.id] = String((0, import_core34.parseCount)(wanted[def.id], def.number.min) ?? def.number.current(state, { ...choices }));
6358
+ choices[def.id] = String((0, import_core36.parseCount)(wanted[def.id], def.number.min) ?? def.number.current(state, { ...choices }));
6246
6359
  return [];
6247
6360
  }
6248
6361
  const items = def.items(state, { ...choices });
@@ -6256,10 +6369,10 @@ function settle(state, definition, wanted) {
6256
6369
  function show2(state, definition, wanted, current) {
6257
6370
  const { choices, lists } = settle(state, definition, wanted);
6258
6371
  const items = lists[current] ?? [];
6259
- const trail = lists.flatMap((list, i) => {
6260
- if (list === null) return [];
6372
+ const trail = lists.flatMap((list2, i) => {
6373
+ if (list2 === null) return [];
6261
6374
  const def2 = definition.steps[i];
6262
- const value = i >= current ? void 0 : def2.number ? choices[def2.id] : list.find((item) => item.id === choices[def2.id])?.label;
6375
+ const value = i >= current ? void 0 : def2.number ? choices[def2.id] : list2.find((item) => item.id === choices[def2.id])?.label;
6263
6376
  return [{ label: def2.label, active: i === current, ...value !== void 0 ? { value } : {} }];
6264
6377
  });
6265
6378
  const def = definition.steps[current];
@@ -6281,7 +6394,7 @@ function lastIndexBefore(lists, index) {
6281
6394
  }
6282
6395
 
6283
6396
  // src/tui/reducers/planPane.ts
6284
- var import_core37 = require("@ordewell/core");
6397
+ var import_core39 = require("@ordewell/core");
6285
6398
 
6286
6399
  // src/tui/reducers/pointer.ts
6287
6400
  var WHEEL_NOTCH = 3;
@@ -6359,13 +6472,13 @@ function handleMouseSelect(state, key) {
6359
6472
  }
6360
6473
 
6361
6474
  // src/tui/reducers/taskView.ts
6362
- var import_core35 = require("@ordewell/core");
6475
+ var import_core37 = require("@ordewell/core");
6363
6476
  function openTaskView(state, sessionId, taskId) {
6364
6477
  const task = findTask(state.tasks, taskId);
6365
6478
  if (!task) return step(say(state, "system", `No task ${taskId} in this plan.`));
6366
6479
  const taskView = {
6367
6480
  taskId,
6368
- view: import_core35.EMPTY_TASK_LOG,
6481
+ view: import_core37.EMPTY_TASK_LOG,
6369
6482
  attempts: [],
6370
6483
  attempt: 0,
6371
6484
  pending: [],
@@ -6395,13 +6508,13 @@ function applyLive(tv, attempt, events) {
6395
6508
  }
6396
6509
  next = {
6397
6510
  ...next,
6398
- view: import_core35.EMPTY_TASK_LOG,
6511
+ view: import_core37.EMPTY_TASK_LOG,
6399
6512
  attempt,
6400
6513
  attempts: next.attempts.includes(attempt) ? next.attempts : [...next.attempts, attempt]
6401
6514
  };
6402
6515
  }
6403
6516
  if (attempt < next.attempt) return next;
6404
- return clampQueueIndex({ ...next, view: events.reduce(import_core35.reduceTaskLog, next.view) });
6517
+ return clampQueueIndex({ ...next, view: events.reduce(import_core37.reduceTaskLog, next.view) });
6405
6518
  }
6406
6519
  function taskLogAbandoned(state) {
6407
6520
  const tv = state.taskView;
@@ -6422,14 +6535,14 @@ function announceApprovals(state, action) {
6422
6535
  if (state.taskView?.taskId === action.taskId) return state;
6423
6536
  const task = findTask(state.tasks, action.taskId);
6424
6537
  const way = task ? `tab to the plan, select task ${task.order} and press enter (or /open ${task.order})` : "tab to the plan, select it and press enter";
6425
- const spoken = action.events.reduce((s, event) => event.type === "approval_requested" && !event.decided ? say(s, "system", `Task ${task?.order ?? "?"} waits for approval: ${(0, import_core35.runnerToolSubject)(event.tool, event.args)} \u2014 ${way}, then ctrl-y allows or ctrl-g denies`) : s, state);
6538
+ const spoken = action.events.reduce((s, event) => event.type === "approval_requested" && !event.decided ? say(s, "system", `Task ${task?.order ?? "?"} waits for approval: ${(0, import_core37.runnerToolSubject)(event.tool, event.args)} \u2014 ${way}, then ctrl-y allows or ctrl-g denies`) : s, state);
6426
6539
  return spoken !== state ? { ...spoken, scroll: state.scroll } : spoken;
6427
6540
  }
6428
6541
  function announceCheckpoint(state, action) {
6429
6542
  const task = findTask(state.tasks, action.taskId) ?? state.tasks.find((t) => t.title === action.title);
6430
6543
  const label = task ? `Task ${task.order}` : action.title;
6431
6544
  const where = task ? `tab to the plan, select task ${task.order} and press enter (or /open ${task.order}) to answer` : "tab to the plan, select it and press enter to answer";
6432
- const spoken = say(state, "system", `${label} asks: ${(0, import_core35.truncateCheckpointSummary)(action.summary)} \u2014 ${where}`);
6545
+ const spoken = say(state, "system", `${label} asks: ${(0, import_core37.truncateCheckpointSummary)(action.summary)} \u2014 ${where}`);
6433
6546
  return { ...spoken, scroll: state.scroll };
6434
6547
  }
6435
6548
  function taskLogLoaded(state, action) {
@@ -6437,7 +6550,7 @@ function taskLogLoaded(state, action) {
6437
6550
  if (!tv || tv.taskId !== action.taskId) return state;
6438
6551
  const loaded = action.attempt >= 1 ? {
6439
6552
  ...tv,
6440
- view: (0, import_core35.replayTaskLog)(action.events),
6553
+ view: (0, import_core37.replayTaskLog)(action.events),
6441
6554
  attempts: action.attempts ?? tv.attempts,
6442
6555
  attempt: action.attempt
6443
6556
  } : { ...tv, attempts: action.attempts ?? tv.attempts };
@@ -6511,7 +6624,7 @@ function handleTaskViewKey(state, key) {
6511
6624
  if (key.name === "ctrl-s") return sendNow(state, tv, state.sessionId);
6512
6625
  if (key.name === "ctrl-x") {
6513
6626
  const task = findTask(state.tasks, tv.taskId);
6514
- if (task && (0, import_core35.resumeLabel)(task)) return step(state, [{ type: "taskAction", sessionId: state.sessionId, taskId: tv.taskId, action: "cancel-resume" }]);
6627
+ if (task && (0, import_core37.resumeLabel)(task)) return step(state, [{ type: "taskAction", sessionId: state.sessionId, taskId: tv.taskId, action: "cancel-resume" }]);
6515
6628
  return step(state, [{ type: "interruptTask", sessionId: state.sessionId, taskId: tv.taskId }]);
6516
6629
  }
6517
6630
  if (key.name === "ctrl-y") return answerWaiting(state, tv, state.sessionId, "allow");
@@ -6529,7 +6642,7 @@ function handleTaskViewKey(state, key) {
6529
6642
  }
6530
6643
 
6531
6644
  // src/tui/reducers/taskEdits.ts
6532
- var import_core36 = require("@ordewell/core");
6645
+ var import_core38 = require("@ordewell/core");
6533
6646
  var import_plan_utils3 = require("@ordewell/core/plan-utils");
6534
6647
  function openTaskRunnerPicker(state, task) {
6535
6648
  if (task.type !== "ai") return fail3(state, "Manual tasks do not run on an executor, so they have no runner.");
@@ -6640,7 +6753,7 @@ function openTaskModePicker(state, task) {
6640
6753
  overlay: {
6641
6754
  kind: "picker",
6642
6755
  picker: picker(`Mode \xB7 ${refFor(state, task)}`, pickerItemsFor(state, action), action, {
6643
- hint: [`Modes declared by ${task.assignedRunner}.`, (0, import_core36.codexSandboxNotice)(state.modesByRunner)?.line].filter(Boolean).join(" ")
6756
+ hint: [`Modes declared by ${task.assignedRunner}.`, (0, import_core38.codexSandboxNotice)(state.modesByRunner)?.line].filter(Boolean).join(" ")
6644
6757
  })
6645
6758
  }
6646
6759
  }
@@ -6868,11 +6981,11 @@ function handlePlanKey(state, key) {
6868
6981
  if (!state.sessionId || key.name !== "char") return step(state);
6869
6982
  if (key.char === "E") return step(state, [{ type: "execute", sessionId: state.sessionId }]);
6870
6983
  if (key.char === "S") return step(state, [{ type: "stopExecution", sessionId: state.sessionId }]);
6871
- const shortcut = key.char === "c" && (0, import_core37.resumeLabel)(task) ? "cancel-resume" : PLAN_SHORTCUTS[key.char ?? ""];
6984
+ const shortcut = key.char === "c" && (0, import_core39.resumeLabel)(task) ? "cancel-resume" : PLAN_SHORTCUTS[key.char ?? ""];
6872
6985
  if (key.char === "r") {
6873
- return (0, import_core37.taskRowActions)(task).includes("resume-now") ? step(state, [taskActionEffect(state, state.sessionId, task.id, "resume-now")]) : step(state);
6986
+ return (0, import_core39.taskRowActions)(task).includes("resume-now") ? step(state, [taskActionEffect(state, state.sessionId, task.id, "resume-now")]) : step(state);
6874
6987
  }
6875
- const action = key.char === "m" ? (0, import_core37.markAction)(task) : shortcut;
6988
+ const action = key.char === "m" ? (0, import_core39.markAction)(task) : shortcut;
6876
6989
  if (action === "force-start" && task.mergeGate?.length) return confirmForceStartPastGate(state, task);
6877
6990
  if (action) {
6878
6991
  return step(state, [taskActionEffect(state, state.sessionId, task.id, action)]);
@@ -6912,9 +7025,9 @@ function commitTaskEdit(state, task, editor) {
6912
7025
  }
6913
7026
 
6914
7027
  // src/tui/reducers/turnQueue.ts
6915
- var import_core38 = require("@ordewell/core");
7028
+ var import_core40 = require("@ordewell/core");
6916
7029
  function drainQueue(state, settled) {
6917
- const next = (0, import_core38.drainNext)(state.queuedPrompts);
7030
+ const next = (0, import_core40.drainNext)(state.queuedPrompts);
6918
7031
  const ended = disarmStop({ ...settled, stopRequested: false, forceSendPending: null });
6919
7032
  if (!next) return step(ended);
6920
7033
  const spoken = say(ended, "user", next.text);
@@ -6929,7 +7042,7 @@ function restoreForced(state) {
6929
7042
  if (!forced) return state;
6930
7043
  const cleared = { ...state, forceSendPending: null };
6931
7044
  if (forced.queueIndex === void 0) {
6932
- const text = (0, import_core38.aheadOfDraft)(forced.text, state.editor.text);
7045
+ const text = (0, import_core40.aheadOfDraft)(forced.text, state.editor.text);
6933
7046
  return { ...cleared, editor: { ...state.editor, text, cursor: text.length } };
6934
7047
  }
6935
7048
  const queued = [...state.queuedPrompts];
@@ -6945,14 +7058,14 @@ function stopPlanning(state, sessionId) {
6945
7058
  return step(queueToEditor(cutTurn({ ...dismissed, stopArmed: false, stopRequested: true, forceSendPending: null })), [{ type: "cancelPlanning", sessionId }]);
6946
7059
  }
6947
7060
  function queueToEditor(state) {
6948
- const all = (0, import_core38.unsendAll)(state.queuedPrompts);
7061
+ const all = (0, import_core40.unsendAll)(state.queuedPrompts);
6949
7062
  if (!all) return state;
6950
7063
  return { ...state, queuedPrompts: all.rest, editor: { ...state.editor, text: all.text, cursor: all.text.length } };
6951
7064
  }
6952
7065
  function unsendLatest(state) {
6953
- const latest = (0, import_core38.unsendLatest)(state.queuedPrompts);
7066
+ const latest = (0, import_core40.unsendLatest)(state.queuedPrompts);
6954
7067
  if (!latest) return step(state);
6955
- const text = (0, import_core38.aheadOfDraft)(latest.text, state.editor.text);
7068
+ const text = (0, import_core40.aheadOfDraft)(latest.text, state.editor.text);
6956
7069
  return step({
6957
7070
  ...state,
6958
7071
  queuedPrompts: latest.rest,
@@ -6968,7 +7081,7 @@ function forceSendPlanner(state) {
6968
7081
  { type: "forceSendPlannerMessage", sessionId: state.sessionId, message: text }
6969
7082
  ]);
6970
7083
  }
6971
- const latest = (0, import_core38.unsendLatest)(state.queuedPrompts);
7084
+ const latest = (0, import_core40.unsendLatest)(state.queuedPrompts);
6972
7085
  if (!latest) return step(say(state, "system", "Nothing to send now: type a message, or queue one with enter."));
6973
7086
  const forced = { text: latest.text, queueIndex: latest.rest.length };
6974
7087
  return step({ ...state, queuedPrompts: latest.rest, stopRequested: false, forceSendPending: forced }, [
@@ -6984,7 +7097,7 @@ function plannerEscape(state) {
6984
7097
  }
6985
7098
 
6986
7099
  // src/tui/reducers/incoming.ts
6987
- var import_core39 = require("@ordewell/core");
7100
+ var import_core41 = require("@ordewell/core");
6988
7101
  var planText = (value, fallback = "") => sanitize(String(value ?? fallback));
6989
7102
  var planLabel = (value, fallback = "") => planText(value, fallback).replace(/\n+/g, " ");
6990
7103
  var asRecord = (value) => typeof value === "object" && value !== null ? value : {};
@@ -7023,7 +7136,7 @@ function runTaskToView(t) {
7023
7136
  ...Array.isArray(model.availableVariants) ? { availableVariants: model.availableVariants.map((variant) => planLabel(variant)) } : {}
7024
7137
  } : void 0,
7025
7138
  isolation: t.isolation,
7026
- awaitingReason: t.status === "awaiting_user" && (0, import_core39.isAwaitingReason)(t.awaitingReason) ? t.awaitingReason : void 0,
7139
+ awaitingReason: t.status === "awaiting_user" && (0, import_core41.isAwaitingReason)(t.awaitingReason) ? t.awaitingReason : void 0,
7027
7140
  ...t.status === "awaiting_user" && t.awaitingReason === "usage-limit" && typeof t.resumeAt === "string" ? { resumeAt: t.resumeAt } : {},
7028
7141
  ...t.status === "skipped" && typeof t.skipReason === "string" ? { skipReason: sanitize(t.skipReason) } : {},
7029
7142
  checkpoint: typeof t.checkpoint === "string" ? sanitize(t.checkpoint) : void 0,
@@ -7042,7 +7155,7 @@ function supervisorOfRun(runSettings) {
7042
7155
  const unsupervised = typeof runSettings.unsupervised === "string" ? runSettings.unsupervised : void 0;
7043
7156
  return {
7044
7157
  runSupervisor: {
7045
- level: (0, import_core39.isSupervisorLevel)(runSettings.supervisorLevel) ? runSettings.supervisorLevel : "off",
7158
+ level: (0, import_core41.isSupervisorLevel)(runSettings.supervisorLevel) ? runSettings.supervisorLevel : "off",
7046
7159
  ...unsupervised ? { unsupervised } : {}
7047
7160
  }
7048
7161
  };
@@ -7059,7 +7172,7 @@ function withRun(state, run) {
7059
7172
  };
7060
7173
  }
7061
7174
  function foldRun(state, input) {
7062
- const run = (0, import_core39.reduceRun)(state.run, input);
7175
+ const run = (0, import_core41.reduceRun)(state.run, input);
7063
7176
  return run === state.run ? state : withRun(state, run);
7064
7177
  }
7065
7178
  function mapRunTasks(tasks, map) {
@@ -7107,21 +7220,21 @@ function followSession(state, message) {
7107
7220
  }
7108
7221
 
7109
7222
  // src/tui/reducers/runSettings.ts
7110
- var import_core40 = require("@ordewell/core");
7223
+ var import_core42 = require("@ordewell/core");
7111
7224
  function runSettingsEffect(state, changes) {
7112
7225
  return { type: "setRunSettings", changes, ...state.sessionId ? { sessionId: state.sessionId } : {} };
7113
7226
  }
7114
7227
  function supervisorCommand(state, args) {
7115
7228
  const [arg, value] = args;
7116
7229
  if (arg === void 0) {
7117
- return step(say(state, "system", `${(0, import_core40.supervisorSummary)(state.runSettings)} \u2014 /supervisor off|watch|act, /supervisor retries <n>, /supervisor reads <n>.`));
7230
+ return step(say(state, "system", `${(0, import_core42.supervisorSummary)(state.runSettings)} \u2014 /supervisor off|watch|act, /supervisor retries <n>, /supervisor reads <n>.`));
7118
7231
  }
7119
7232
  if (arg === "retries") {
7120
- const n = (0, import_core40.parseCount)(value, 0);
7233
+ const n = (0, import_core42.parseCount)(value, 0);
7121
7234
  return n === null ? fail3(state, "Usage: /supervisor retries <whole number, 0 or more>") : step(state, [runSettingsEffect(state, { supervisorRetryLimit: n })]);
7122
7235
  }
7123
7236
  if (arg === "reads") {
7124
- const n = (0, import_core40.parseCount)(value, 1);
7237
+ const n = (0, import_core42.parseCount)(value, 1);
7125
7238
  return n === null ? fail3(state, "Usage: /supervisor reads <whole number, 1 or more>") : step(state, [runSettingsEffect(state, { wakeUpReadBudget: n })]);
7126
7239
  }
7127
7240
  if (arg === "act") return confirmSupervisorAct(state);
@@ -7130,17 +7243,17 @@ function supervisorCommand(state, args) {
7130
7243
  }
7131
7244
  function automergeCommand(state, arg) {
7132
7245
  if (arg === void 0) {
7133
- return step(say(state, "system", `${(0, import_core40.automergeSummary)(state.runSettings)} \u2014 /automerge on|off.`));
7246
+ return step(say(state, "system", `${(0, import_core42.automergeSummary)(state.runSettings)} \u2014 /automerge on|off.`));
7134
7247
  }
7135
- const enabled = (0, import_core40.parseSwitch)(arg);
7248
+ const enabled = (0, import_core42.parseSwitch)(arg);
7136
7249
  if (enabled === null) return fail3(state, "Usage: /automerge [on|off]");
7137
7250
  return step(state, [runSettingsEffect(state, { mergeAtGatesAutomatically: enabled })]);
7138
7251
  }
7139
7252
  function autorunCommand(state, arg) {
7140
7253
  if (arg === void 0) {
7141
- return step(say(state, "system", `${(0, import_core40.autorunSummary)(state.runSettings)} \u2014 /autorun on starts each plan the planner submits, without review.`));
7254
+ return step(say(state, "system", `${(0, import_core42.autorunSummary)(state.runSettings)} \u2014 /autorun on starts each plan the planner submits, without review.`));
7142
7255
  }
7143
- const enabled = (0, import_core40.parseSwitch)(arg);
7256
+ const enabled = (0, import_core42.parseSwitch)(arg);
7144
7257
  if (enabled === null) return fail3(state, "Usage: /autorun [on|off]");
7145
7258
  if (enabled) return confirmAutorun(state);
7146
7259
  return step(state, [runSettingsEffect(state, { autorun: false })]);
@@ -7152,7 +7265,7 @@ function confirmSupervisorAct(state) {
7152
7265
  kind: "confirm",
7153
7266
  title: "Let the supervisor act?",
7154
7267
  message: "At Act the supervisor runs, stops and retries tasks, answers their requests (never allowing), edits the plan and merges, without asking you.",
7155
- note: `${import_core40.ACT_RISK}
7268
+ note: `${import_core42.ACT_RISK}
7156
7269
  It applies to this session's run now, and to every later run.`,
7157
7270
  action: { kind: "supervisor-act" }
7158
7271
  }
@@ -7165,14 +7278,14 @@ function confirmAutorun(state) {
7165
7278
  kind: "confirm",
7166
7279
  title: "Start plans without review?",
7167
7280
  message: "With autorun on, each plan the planner submits starts at once, as if you had pressed Execute. The planner still asks when something is unclear.",
7168
- note: import_core40.AUTORUN_RISK,
7281
+ note: import_core42.AUTORUN_RISK,
7169
7282
  action: { kind: "autorun-on" }
7170
7283
  }
7171
7284
  });
7172
7285
  }
7173
7286
 
7174
7287
  // src/tui/reducers/settings.ts
7175
- var import_core41 = require("@ordewell/core");
7288
+ var import_core43 = require("@ordewell/core");
7176
7289
  var SUPERVISOR_DETAIL = {
7177
7290
  off: "The planner speaks only when you write",
7178
7291
  watch: "The planner follows your runs and suggests what to do",
@@ -7197,7 +7310,7 @@ var SETTINGS = {
7197
7310
  {
7198
7311
  id: "guarded",
7199
7312
  label: "Guarded",
7200
- detail: [`New plans run tasks in each runner's safer mode`, (0, import_core41.codexSandboxNotice)(state.modesByRunner)?.line].filter(Boolean).join(" \xB7 "),
7313
+ detail: [`New plans run tasks in each runner's safer mode`, (0, import_core43.codexSandboxNotice)(state.modesByRunner)?.line].filter(Boolean).join(" \xB7 "),
7201
7314
  selected: !state.autonomous
7202
7315
  }
7203
7316
  ]
@@ -7207,7 +7320,7 @@ var SETTINGS = {
7207
7320
  label: "Supervisor",
7208
7321
  items: (state) => ["off", "watch", "act"].map((level) => ({
7209
7322
  id: level,
7210
- label: import_core41.SUPERVISOR_LEVEL_LABEL[level],
7323
+ label: import_core43.SUPERVISOR_LEVEL_LABEL[level],
7211
7324
  detail: SUPERVISOR_DETAIL[level],
7212
7325
  selected: state.runSettings.supervisorLevel === level
7213
7326
  }))
@@ -7261,12 +7374,12 @@ function saveChoices(state, choices) {
7261
7374
  const autonomous = choices.autonomy === "full";
7262
7375
  if (autonomous !== state.autonomous) {
7263
7376
  save2.autonomous = autonomous;
7264
- changed.push(`Autonomy ${(0, import_core41.autonomyLevelLabel)(autonomous)}`);
7377
+ changed.push(`Autonomy ${(0, import_core43.autonomyLevelLabel)(autonomous)}`);
7265
7378
  }
7266
7379
  const level = choices.supervisor;
7267
7380
  if (level !== state.runSettings.supervisorLevel) {
7268
7381
  run.supervisorLevel = level;
7269
- changed.push(`Supervisor ${import_core41.SUPERVISOR_LEVEL_LABEL[level]}`);
7382
+ changed.push(`Supervisor ${import_core43.SUPERVISOR_LEVEL_LABEL[level]}`);
7270
7383
  }
7271
7384
  if (choices.retries !== void 0 && Number(choices.retries) !== state.runSettings.supervisorRetryLimit) {
7272
7385
  run.supervisorRetryLimit = Number(choices.retries);
@@ -7293,7 +7406,7 @@ function saveChoices(state, choices) {
7293
7406
  }
7294
7407
  if (changed.length === 0) return step(state);
7295
7408
  const effect = { ...save2, message: `Settings: ${changed.join(" \xB7 ")}` };
7296
- const risks = [...run.supervisorLevel === "act" ? [import_core41.ACT_RISK] : [], ...run.autorun ? [import_core41.AUTORUN_RISK] : []];
7409
+ const risks = [...run.supervisorLevel === "act" ? [import_core43.ACT_RISK] : [], ...run.autorun ? [import_core43.AUTORUN_RISK] : []];
7297
7410
  if (risks.length === 0) return saveSettings(state, effect);
7298
7411
  return step({
7299
7412
  ...state,
@@ -7322,7 +7435,6 @@ function saveSettings(state, effect) {
7322
7435
  }
7323
7436
 
7324
7437
  // src/tui/reducers/commands.ts
7325
- var KNOWN_PROVIDERS = Object.keys(import_core42.ALL_PROVIDERS);
7326
7438
  var unknownCommand = (state, name) => fail3(state, `Unknown command: /${name} \u2014 type /help to see what's available.`);
7327
7439
  function runCommand(state, { name, args }) {
7328
7440
  if (!findCommand(name)) return unknownCommand(state, name);
@@ -7485,8 +7597,8 @@ function newSession(state) {
7485
7597
  goal: "",
7486
7598
  taskView: null,
7487
7599
  planApproved: false,
7488
- conversation: import_core42.EMPTY_CONVERSATION,
7489
- turnGate: import_core42.NO_TURN,
7600
+ conversation: import_core44.EMPTY_CONVERSATION,
7601
+ turnGate: import_core44.NO_TURN,
7490
7602
  selectedTask: 0,
7491
7603
  expandedTaskId: null,
7492
7604
  taskEditor: null,
@@ -7497,15 +7609,15 @@ function newSession(state) {
7497
7609
  // Prompts belong to the session that raised them; the old planner is gone
7498
7610
  // and its pending requests deny on their own timeout.
7499
7611
  pendingApprovals: [],
7500
- queuedPrompts: import_core42.EMPTY_HOLD,
7612
+ queuedPrompts: import_core44.EMPTY_HOLD,
7501
7613
  stopArmed: false,
7502
7614
  forceSendPending: null,
7503
7615
  overlay: state.overlay?.kind === "approval" ? null : state.overlay
7504
- }, import_core42.EMPTY_RUN), closeEffects);
7616
+ }, import_core44.EMPTY_RUN), closeEffects);
7505
7617
  }
7506
7618
  function setModel(state, args) {
7507
7619
  if (args[0] === "set" && args[1]) {
7508
- const runner = (0, import_core42.runnerForProvider)(state.plannerProvider);
7620
+ const runner = (0, import_core44.runnerForProvider)(state.plannerProvider);
7509
7621
  const known = runner ? modelsForRunner(state.models, runner) : [];
7510
7622
  if (runner && known.length > 0 && !known.some((m) => m.id === args[1])) {
7511
7623
  return fail3(state, `${args[1]} was not discovered for ${runner}.`);
@@ -7528,7 +7640,7 @@ function setModel(state, args) {
7528
7640
  function setPlanner(state, args) {
7529
7641
  if (args[0]) {
7530
7642
  const id = args[0].toLowerCase();
7531
- if (!KNOWN_PROVIDERS.includes(id)) {
7643
+ if (!(0, import_core44.isPlannerBackend)(id)) {
7532
7644
  return fail3(state, `Unknown planner: ${id}. Run /planner with no arguments to see the list.`);
7533
7645
  }
7534
7646
  return step(state, [{ type: "setPlanner", provider: id }]);
@@ -7560,7 +7672,7 @@ function setPlannerEffort(state, args) {
7560
7672
  function setKey(state, args) {
7561
7673
  if (args[0] === "set" && args[1]) {
7562
7674
  const provider = args[1].toLowerCase();
7563
- if (!KNOWN_PROVIDERS.includes(provider)) {
7675
+ if (!(0, import_core44.isApiProvider)(provider)) {
7564
7676
  return fail3(state, `Unknown provider: ${provider}. Run /key with no arguments to see the list.`);
7565
7677
  }
7566
7678
  if (!args[2]) {
@@ -7571,16 +7683,16 @@ function setKey(state, args) {
7571
7683
  }
7572
7684
  return step(state, [{ type: "setApiKey", provider, key: args.slice(2).join(" ") }]);
7573
7685
  }
7574
- const items = import_core42.PROVIDER_PRIORITY.map((id) => ({
7686
+ const items = import_core44.PROVIDER_PRIORITY.map((id) => ({
7575
7687
  id,
7576
- label: import_core42.ALL_PROVIDERS[id].label,
7577
- detail: import_core42.ALL_PROVIDERS[id].apiKeyEnvVar,
7688
+ label: (0, import_core44.getProviderMeta)(id).label,
7689
+ detail: (0, import_core44.getProviderMeta)(id).apiKeyEnvVar,
7578
7690
  selected: state.configuredProviders.includes(id)
7579
7691
  }));
7580
7692
  return step({ ...state, overlay: { kind: "picker", picker: picker("API provider key", items, { kind: "set-key" }) } });
7581
7693
  }
7582
7694
  function keyPrompt(provider) {
7583
- const meta = import_core42.ALL_PROVIDERS[provider];
7695
+ const meta = (0, import_core44.getProviderMeta)(provider);
7584
7696
  return {
7585
7697
  kind: "prompt",
7586
7698
  title: `${meta.label} API key`,
@@ -7657,13 +7769,13 @@ function runners(state, args) {
7657
7769
  }
7658
7770
  function setMaxParallel(state, arg) {
7659
7771
  if (!arg) return step(say(state, "system", `Up to ${state.maxParallel} AI task${state.maxParallel === 1 ? "" : "s"} run at once \u2014 /parallel <n> changes it.`));
7660
- const limit = (0, import_core42.parseMaxParallel)(arg);
7772
+ const limit = (0, import_core44.parseMaxParallel)(arg);
7661
7773
  if (limit === null) return fail3(state, "Usage: /parallel [<number of tasks, 1 or more>]");
7662
7774
  return step({ ...state, maxParallel: limit }, [{ type: "setMaxParallel", limit }]);
7663
7775
  }
7664
7776
  function setAutonomous(state, arg) {
7665
- if (arg === void 0) return step(say(state, "system", `Autonomy level: ${(0, import_core42.autonomyLevelLabel)(state.autonomous)} \u2014 /auto full or /auto guarded changes it for new plans.`));
7666
- const enabled = (0, import_core42.parseAutonomyLevel)(arg);
7777
+ if (arg === void 0) return step(say(state, "system", `Autonomy level: ${(0, import_core44.autonomyLevelLabel)(state.autonomous)} \u2014 /auto full or /auto guarded changes it for new plans.`));
7778
+ const enabled = (0, import_core44.parseAutonomyLevel)(arg);
7667
7779
  if (enabled === null) return fail3(state, "Usage: /auto [full|guarded]");
7668
7780
  return step({ ...state, autonomous: enabled }, [{ type: "setAutonomous", enabled }]);
7669
7781
  }
@@ -7872,7 +7984,7 @@ function choose2(state, picker2, item) {
7872
7984
  case "delete-session":
7873
7985
  return step(closed, [{ type: "deleteSession", sessionId: item.id }]);
7874
7986
  case "set-key":
7875
- return step({ ...state, overlay: keyPrompt(item.id) });
7987
+ return (0, import_core45.isApiProvider)(item.id) ? step({ ...state, overlay: keyPrompt(item.id) }) : step(closed);
7876
7988
  case "choose-allowlist-runner": {
7877
7989
  const action = { kind: "set-allowlist", runner: item.id };
7878
7990
  const items = pickerItemsFor(state, action);
@@ -7948,7 +8060,7 @@ function reduceAction(state, action) {
7948
8060
  // (`task-1`), so nothing of the last one's — a merge gate, a checkpoint, its
7949
8061
  // tasks — may carry over into this.
7950
8062
  case "sessionStarted":
7951
- return step(withRun({ ...state, sessionId: action.sessionId, goal: action.goal, taskView: null }, import_core43.EMPTY_RUN));
8063
+ return step(withRun({ ...state, sessionId: action.sessionId, goal: action.goal, taskView: null }, import_core46.EMPTY_RUN));
7952
8064
  // The daemon registers a session only once planning succeeds; when it does
7953
8065
  // not, holding on to the id would send every next message to a session the
7954
8066
  // server never had.
@@ -7959,18 +8071,18 @@ function reduceAction(state, action) {
7959
8071
  goal: "",
7960
8072
  taskView: null,
7961
8073
  pendingApprovals: [],
7962
- queuedPrompts: import_core43.EMPTY_HOLD,
8074
+ queuedPrompts: import_core46.EMPTY_HOLD,
7963
8075
  stopArmed: false,
7964
8076
  forceSendPending: null,
7965
8077
  overlay: state.overlay?.kind === "approval" ? null : state.overlay
7966
- }, import_core43.EMPTY_RUN));
8078
+ }, import_core46.EMPTY_RUN));
7967
8079
  // Deleting the session on screen stops it in the daemon; a view left on it
7968
8080
  // would answer every next message with a session-not-found.
7969
8081
  case "sessionDeleted":
7970
8082
  return action.sessionId === state.sessionId ? newSession(state) : step(state);
7971
8083
  case "chatRestored":
7972
8084
  if (stale(state, action.sessionId)) return step(state);
7973
- return step({ ...state, conversation: (0, import_core43.fromTranscript)(action.history, action.researchLog, action.plannerUsage, action.pendingTurns), scroll: 0 });
8085
+ return step({ ...state, conversation: (0, import_core46.fromTranscript)(action.history, action.researchLog, action.plannerUsage, action.pendingTurns), scroll: 0 });
7974
8086
  case "planUpdated": {
7975
8087
  if (stale(state, action.sessionId)) return step(state);
7976
8088
  const settled = { ...showPlan(state, action.plan), planner: "idle" };
@@ -8010,15 +8122,15 @@ function reduceAction(state, action) {
8010
8122
  case "taskStarted": {
8011
8123
  if (stale(state, action.sessionId)) return step(state);
8012
8124
  const existing = findTask(state.tasks, action.taskId);
8013
- if (existing && (0, import_core24.isTaskRunning)(existing)) return step(state);
8125
+ if (existing && (0, import_core26.isTaskRunning)(existing)) return step(state);
8014
8126
  const folded = foldRun(state, {
8015
8127
  type: "task_started",
8016
8128
  taskId: action.taskId,
8017
8129
  order: action.order ?? 0,
8018
8130
  title: action.title,
8019
- runner: action.runner ?? "claude-code"
8131
+ runner: action.runner ?? import_core46.DEFAULT_RUNNERS[0]
8020
8132
  });
8021
- const spoken = say(folded, "system", (0, import_core43.taskStartedNotice)(action.title, action.runner));
8133
+ const spoken = say(folded, "system", (0, import_core46.taskStartedNotice)(action.title, action.runner));
8022
8134
  return step({ ...spoken, status: "executing" });
8023
8135
  }
8024
8136
  case "taskCheckpoint":
@@ -8064,7 +8176,7 @@ function reduceAction(state, action) {
8064
8176
  completed: state.tasks.filter((t) => t.status === "completed").length,
8065
8177
  total: state.tasks.length,
8066
8178
  failed: state.tasks.filter((t) => t.status === "failed").length,
8067
- blocked: (0, import_core43.blockingFailures)(state.tasks).size,
8179
+ blocked: (0, import_core46.blockingFailures)(state.tasks).size,
8068
8180
  skipped: state.tasks.filter((t) => t.status === "skipped").length
8069
8181
  };
8070
8182
  const failures = `${failed > 0 ? ` \xB7 ${failed} failed` : ""}${blocked ? ` \xB7 ${blocked} blocked` : ""}${skipped ? ` \xB7 ${skipped} skipped` : ""}`;
@@ -8128,11 +8240,11 @@ function reduceAction(state, action) {
8128
8240
  planner: "idle",
8129
8241
  planApproved: false,
8130
8242
  pendingApprovals: [],
8131
- queuedPrompts: import_core43.EMPTY_HOLD,
8243
+ queuedPrompts: import_core46.EMPTY_HOLD,
8132
8244
  stopArmed: false,
8133
8245
  forceSendPending: null,
8134
8246
  overlay: state.overlay?.kind === "approval" ? null : state.overlay
8135
- }, import_core43.EMPTY_RUN));
8247
+ }, import_core46.EMPTY_RUN));
8136
8248
  // The rewound message comes back as a draft to edit and resend, so it lands
8137
8249
  // as if just typed: history is not being browsed, and nothing is parked.
8138
8250
  case "inputPrefilled":
@@ -8204,7 +8316,7 @@ function showPlan(state, plan) {
8204
8316
  });
8205
8317
  }
8206
8318
  function runStatus(state, tasks) {
8207
- if (tasks.some(import_core24.isTaskRunning)) return "executing";
8319
+ if (tasks.some(import_core26.isTaskRunning)) return "executing";
8208
8320
  if (tasks.some((t) => t.status === "awaiting_user") || state.runMerge?.paused) return "executing";
8209
8321
  return "idle";
8210
8322
  }
@@ -8296,7 +8408,7 @@ function submit(state) {
8296
8408
  const builtIn = builtInCommand(text);
8297
8409
  if (builtIn) return runCommand(cleared, builtIn);
8298
8410
  if (plannerInFlight(state)) {
8299
- return step({ ...cleared, queuedPrompts: (0, import_core43.holdPrompt)(state.queuedPrompts, text) });
8411
+ return step({ ...cleared, queuedPrompts: (0, import_core46.holdPrompt)(state.queuedPrompts, text) });
8300
8412
  }
8301
8413
  const spoken = say(cleared, "user", text);
8302
8414
  const effect = state.sessionId ? { type: "sendMessage", sessionId: state.sessionId, message: text } : { type: "startConversation", goal: text };
@@ -8371,7 +8483,7 @@ function createApp(deps) {
8371
8483
 
8372
8484
  // src/tui/effects.ts
8373
8485
  var import_child_process3 = require("child_process");
8374
- var import_core44 = require("@ordewell/core");
8486
+ var import_core47 = require("@ordewell/core");
8375
8487
 
8376
8488
  // src/tui/inbound.ts
8377
8489
  var CONVERSATION_TYPES = /* @__PURE__ */ new Set([
@@ -8780,13 +8892,13 @@ async function perform(effect, deps) {
8780
8892
  await refreshPlan(deps, sessionId);
8781
8893
  return;
8782
8894
  }
8783
- const request = action === "cancel" || action === "retry" || action === "force-start" ? () => api.taskControl(sessionId, taskId, action) : action === "resume-now" ? () => api.resumeNow(sessionId, taskId) : action === "skip" ? () => api.skipTask(sessionId, taskId) : (0, import_core44.markRequestFor)(action) === "uncomplete" ? () => api.markTaskIncomplete(sessionId, taskId) : () => api.markTaskComplete(sessionId, taskId);
8895
+ const request = action === "cancel" || action === "retry" || action === "force-start" ? () => api.taskControl(sessionId, taskId, action) : action === "resume-now" ? () => api.resumeNow(sessionId, taskId) : action === "skip" ? () => api.skipTask(sessionId, taskId) : (0, import_core47.markRequestFor)(action) === "uncomplete" ? () => api.markTaskIncomplete(sessionId, taskId) : () => api.markTaskComplete(sessionId, taskId);
8784
8896
  await (effect.watch ? withExecutionStream(deps, sessionId, request) : request());
8785
8897
  await refreshPlan(deps, sessionId);
8786
8898
  return;
8787
8899
  }
8788
8900
  case "addTask": {
8789
- const fields = (0, import_core44.newTaskFields)(effect.title);
8901
+ const fields = (0, import_core47.newTaskFields)(effect.title);
8790
8902
  if (!fields) return;
8791
8903
  await api.addTask(effect.sessionId, { ...fields });
8792
8904
  await refreshPlan(deps, effect.sessionId);
@@ -8894,7 +9006,7 @@ async function perform(effect, deps) {
8894
9006
  return;
8895
9007
  }
8896
9008
  case "setPlanner": {
8897
- const meta = import_core44.ALL_PROVIDERS[effect.provider];
9009
+ const meta = (0, import_core47.getProviderMeta)(effect.provider);
8898
9010
  if (!meta) throw new Error(`Unknown planner: ${effect.provider}`);
8899
9011
  const env = { AI_PROVIDER: effect.provider };
8900
9012
  const settings = await api.updateSettings({ env });
@@ -8906,7 +9018,7 @@ async function perform(effect, deps) {
8906
9018
  });
8907
9019
  dispatch({
8908
9020
  type: "notice",
8909
- message: `${(0, import_core44.isCliProvider)(effect.provider) ? `Planning with ${meta.label} \u2014 no API key needed.` : `Planner set to ${meta.label}.`} ${plannerModelNotice(recall2)}`
9021
+ message: `${(0, import_core47.isCliProvider)(effect.provider) ? `Planning with ${meta.label} \u2014 no API key needed.` : `Planner set to ${meta.label}.`} ${plannerModelNotice(recall2)}`
8910
9022
  });
8911
9023
  await loadModels(deps);
8912
9024
  return;
@@ -8934,7 +9046,7 @@ async function perform(effect, deps) {
8934
9046
  dispatch({ type: "notice", message: `Planner effort set to ${effect.effort || "the runner default"}.` });
8935
9047
  return;
8936
9048
  case "setApiKey": {
8937
- const meta = import_core44.ALL_PROVIDERS[effect.provider];
9049
+ const meta = (0, import_core47.isApiProvider)(effect.provider) ? (0, import_core47.getProviderMeta)(effect.provider) : void 0;
8938
9050
  if (!meta) throw new Error(`Unknown provider: ${effect.provider}`);
8939
9051
  await api.updateSettings({ env: { [meta.apiKeyEnvVar]: effect.key } });
8940
9052
  deps.setEnvVar(meta.apiKeyEnvVar, effect.key);
@@ -8982,7 +9094,7 @@ async function perform(effect, deps) {
8982
9094
  }
8983
9095
  case "setAutonomous": {
8984
9096
  const { overridden } = deps.saveAutonomy(effect.enabled);
8985
- const level = (0, import_core44.autonomyLevelLabel)(effect.enabled);
9097
+ const level = (0, import_core47.autonomyLevelLabel)(effect.enabled);
8986
9098
  dispatch({ type: "notice", message: overridden ? `${level} is saved, but ORDEWELL_AUTONOMOUS_MODE in the environment decides the level until it is unset.` : `Autonomy level: ${level} for new plans.` });
8987
9099
  return;
8988
9100
  }
@@ -9146,7 +9258,7 @@ async function saveMaxParallel(deps, limit) {
9146
9258
  function copySelection(deps, text) {
9147
9259
  if (!text) return;
9148
9260
  const lines = text.split("\n").length;
9149
- const command = (0, import_core44.clipboardCopyCommand)(deps.hasBin);
9261
+ const command = (0, import_core47.clipboardCopyCommand)(deps.hasBin);
9150
9262
  if (command) {
9151
9263
  try {
9152
9264
  (deps.pipeToClipboard ?? pipeToClipboardDefault)(command, text);
@@ -9251,7 +9363,7 @@ function lastAssistantMessage(plan) {
9251
9363
  const history = plan?.conversationHistory ?? [];
9252
9364
  for (let i = history.length - 1; i >= 0; i--) {
9253
9365
  const entry = history[i];
9254
- if ((0, import_core44.isUserMessage)(entry)) return null;
9366
+ if ((0, import_core47.isUserMessage)(entry)) return null;
9255
9367
  if (entry.role === "assistant" && entry.kind === void 0) {
9256
9368
  const { content, timestamp } = entry;
9257
9369
  return { content, ...timestamp ? { timestamp } : {} };
@@ -9273,14 +9385,14 @@ async function loadModels(deps) {
9273
9385
  }
9274
9386
  async function loadSessions(deps) {
9275
9387
  const sessions = await deps.api.getSessions(deps.workspace);
9276
- const list = sessions.map((s) => ({
9388
+ const list2 = sessions.map((s) => ({
9277
9389
  id: String(s.id),
9278
9390
  goal: String(s.goal ?? ""),
9279
9391
  taskCount: Number(s.taskCount ?? 0),
9280
9392
  status: String(s.status ?? ""),
9281
9393
  createdAt: String(s.createdAt ?? "")
9282
9394
  }));
9283
- deps.dispatch({ type: "sessionsLoaded", sessions: list });
9395
+ deps.dispatch({ type: "sessionsLoaded", sessions: list2 });
9284
9396
  }
9285
9397
  async function loadRunners(deps) {
9286
9398
  const state = await deps.api.getRunners();
@@ -9606,7 +9718,7 @@ async function handleTui(subArgs) {
9606
9718
  }
9607
9719
  const workspace = flag(subArgs, "--workspace") || process.cwd();
9608
9720
  try {
9609
- (0, import_core45.assertWorkspaceExists)(workspace);
9721
+ (0, import_core48.assertWorkspaceExists)(workspace);
9610
9722
  } catch {
9611
9723
  console.error(
9612
9724
  `Workspace "${workspace}" does not exist.
@@ -9615,7 +9727,7 @@ cd into a directory that exists, or pass --workspace <path> naming one that does
9615
9727
  );
9616
9728
  process.exit(1);
9617
9729
  }
9618
- const discoveredSkills = (0, import_core45.createSkillsService)(workspace, new import_core45.EnvConfig().workspaceRepos).listSkills();
9730
+ const discoveredSkills = (0, import_core48.createSkillsService)(workspace, new import_core48.EnvConfig().workspaceRepos).listSkills();
9619
9731
  registerSkillCommands(discoveredSkills);
9620
9732
  const taskSkills = discoveredSkills.filter((s) => s.appliesTo === "task").map((s) => ({ name: s.name, description: s.description }));
9621
9733
  const explicitPort = flag(subArgs, "--port") || process.env.ORDEWELL_PORT;
@@ -9627,20 +9739,20 @@ cd into a directory that exists, or pass --workspace <path> naming one that does
9627
9739
  const mouseCapture = process.env.ORDEWELL_TUI_MOUSE !== "false" && process.env.ORDEWELL_TUI_MOUSE !== "0";
9628
9740
  const app = createApp({
9629
9741
  // The level the daemon plans with: the saved one, unless the environment overrides it (ADR-0030).
9630
- initial: { workspace, autonomous: new import_core45.SettingsService().autonomousMode(), mouseCapture, taskSkills },
9742
+ initial: { workspace, autonomous: new import_core48.SettingsService().autonomousMode(), mouseCapture, taskSkills },
9631
9743
  draw: (frame2) => terminal?.draw(frame2),
9632
9744
  perform: (effect) => runEffect(effect, {
9633
9745
  api,
9634
9746
  workspace,
9635
9747
  port,
9636
9748
  dispatch: (action) => app.dispatch(action),
9637
- newSessionId: () => (0, import_core45.mintSessionId)(),
9749
+ newSessionId: () => (0, import_core48.mintSessionId)(),
9638
9750
  setEnvVar: (key, value) => {
9639
9751
  writeEnvVar(findEnvFile(), key, value);
9640
9752
  process.env[key] = value;
9641
9753
  },
9642
9754
  saveAutonomy: (enabled) => {
9643
- const settings = new import_core45.SettingsService();
9755
+ const settings = new import_core48.SettingsService();
9644
9756
  settings.setAutonomousMode(enabled);
9645
9757
  return { overridden: settings.autonomousModeOverridden() };
9646
9758
  },
@@ -9754,7 +9866,7 @@ var COMMANDS = {
9754
9866
  // src/main.ts
9755
9867
  var TUI_FLAGS = /* @__PURE__ */ new Set(["--workspace", "--port"]);
9756
9868
  async function main() {
9757
- (0, import_core46.migrateOldConfigDir)();
9869
+ (0, import_core49.migrateOldConfigDir)();
9758
9870
  moveAutonomyToSettings();
9759
9871
  loadEnvFile();
9760
9872
  const argv = process.argv.slice(2);