@ordewell/cli 0.10.9 → 0.10.11

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 (3) hide show
  1. package/README.md +11 -7
  2. package/dist/main.js +99 -305
  3. package/package.json +3 -3
package/README.md CHANGED
@@ -19,17 +19,21 @@ on Windows, run the terminal UI under WSL.
19
19
 
20
20
  Run `ordewell` in your project to open the terminal UI: the conversation on the
21
21
  left, the live plan on the right. The first run lets you pick a planner and runners
22
- with `/planner` (Harness › Model › Effort, saved at the end) and `/runners`, and no API key is needed if you plan with a coding
22
+ with `/planner` (Harness › Model › Effort, each step saved as you go) and `/runners`, and no API key is needed if you plan with a coding
23
23
  agent you already use.
24
24
  The welcome screen says it plainly: nothing runs until you approve the plan (unless autorun is on).
25
25
 
26
26
  `/settings` walks autonomy, supervisor, merge automatically, autorun and parallel
27
- in one panel and saves only what you changed. `/model` and `/planner-effort` set
28
- the planner model and effort on their own. Press `?` in the plan pane for the
29
- full key sheet; the footer shows only the keys that apply to the selected task.
30
-
31
- Every command in the terminal UI is also a subcommand, except `/settings`, whose
32
- settings each have their own:
27
+ in one panel and saves only what you changed. `/planner` walks harness, model and
28
+ effort in one flow, so there is no separate model or effort command. Press `?` in
29
+ the plan pane for the full key sheet; the footer shows only the keys that apply
30
+ to the selected task.
31
+
32
+ Every command in the terminal UI is also a subcommand, except `/settings`: it is
33
+ a panel over headless commands that remain for scripts (`ordewell auto`,
34
+ `supervisor`, `automerge`, `autorun` and `parallel`). `/planner` has its own
35
+ `ordewell planner`, and its model and effort steps are `ordewell model` and
36
+ `ordewell planner-effort`.
33
37
 
34
38
  ```bash
35
39
  export AI_PROVIDER=claude-code # plan with Claude Code, Codex or OpenCode
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_core52 = require("@ordewell/core");
27
+ var import_core51 = require("@ordewell/core");
28
28
 
29
29
  // src/utils/env.ts
30
30
  var import_fs = require("fs");
@@ -129,9 +129,10 @@ function printHelp() {
129
129
  console.log(`
130
130
  Ordewell: task orchestration for coding agents
131
131
 
132
- Run "ordewell" with no arguments for the TUI. Every command below has a TUI
133
- slash command of the same name, where each one opens a picker instead of taking
134
- an id.
132
+ Run "ordewell" with no arguments for the TUI. Where a command has a slash
133
+ command, both take the same name. The headless run-setting and planner-step
134
+ commands marked "(headless)" are set in /settings and /planner in the TUI and
135
+ VS Code.
135
136
 
136
137
  Planning:
137
138
  ordewell Full-screen terminal UI (everything the VS Code extension does)
@@ -172,17 +173,17 @@ Per-task assignment (omit the value to list the options):
172
173
 
173
174
  Planner, models and runners:
174
175
  ordewell planner [<provider>] Choose who plans: an API provider or a coding agent (no API key)
175
- ordewell model [set <id>] Show or set the planner model (applies without a restart)
176
- ordewell planner-effort [lvl] Thinking effort for a coding-agent planner
176
+ ordewell model [set <id>] (headless) Show or set the planner model; /planner covers it in the TUI and VS Code
177
+ ordewell planner-effort [lvl] (headless) Thinking effort for a coding-agent planner; /planner covers it
177
178
  ordewell key [set <p> <key>] Show which providers have a key, or store one
178
179
  ordewell runners [<id> on|off] Enable or disable runners (${runnerIdList()})
179
180
  ordewell allowlist set|clear|show Limit which models a runner may use
180
- ordewell auto [full|guarded] Autonomy level for new plans: Full or Guarded
181
- ordewell supervisor [off|watch|act] Whether the planner watches or acts on your runs (default watch);
182
- also: supervisor retries <n>, supervisor reads <n>
183
- ordewell automerge [on|off] Merge into your branch by itself at merge gates and at the end of a run (default off)
184
- ordewell autorun [on|off] Start each plan the planner submits, without review (default off)
185
- ordewell parallel [<n>] How many AI tasks run at once (default 5; applies to a live run)
181
+ ordewell auto [full|guarded] (headless) Autonomy level for new plans, Full or Guarded; /settings covers it
182
+ ordewell supervisor [off|watch|act] (headless) Whether the planner watches or acts on your runs;
183
+ also: supervisor retries <n>, supervisor reads <n>; /settings covers it
184
+ ordewell automerge [on|off] (headless) Merge at merge gates and at the end of a run; /settings covers it
185
+ ordewell autorun [on|off] (headless) Start each plan the planner submits, without review; /settings covers it
186
+ ordewell parallel [<n>] (headless) How many AI tasks run at once, a live run included; /settings covers it
186
187
  ordewell refresh Re-discover runners and model catalogs
187
188
  ordewell models List every provider's catalog (works without a server)
188
189
 
@@ -2574,7 +2575,7 @@ function runnerCommandLines(block2, cols, detailAll) {
2574
2575
  return [head, ...underHeader(shown.map(style.grey))];
2575
2576
  }
2576
2577
  function compactionLine(block2, cols) {
2577
- const sizes = block2.preTokens !== void 0 && block2.postTokens !== void 0 ? ` \xB7 ${compactCount(block2.preTokens)} \u2192 ${compactCount(block2.postTokens)} tokens` : "";
2578
+ const sizes = block2.preTokens !== void 0 && block2.postTokens !== void 0 ? ` \xB7 ${(0, import_core14.formatTokenCount)(block2.preTokens)} \u2192 ${(0, import_core14.formatTokenCount)(block2.postTokens)} tokens` : "";
2578
2579
  const text = block2.trigger === "auto" && !sizes ? "\u2261 Context compacted by the runner on its own" : `\u2261 Context compacted${sizes}`;
2579
2580
  return style.grey(truncate(text, cols));
2580
2581
  }
@@ -2650,37 +2651,10 @@ function conversationLines(blocks2, cols, detailAll, answering) {
2650
2651
  }
2651
2652
  return lines;
2652
2653
  }
2653
- function compactCount(n) {
2654
- if (n < 1e3) return String(n);
2655
- const [value, unit] = n < 999950 ? [n / 1e3, "k"] : [n / 1e6, "M"];
2656
- return `${value.toFixed(1).replace(/\.0$/, "")}${unit}`;
2657
- }
2658
- function formatCost(currency, amount) {
2659
- const [whole, frac = ""] = amount.toFixed(4).replace(/0+$/, "").split(".");
2660
- const value = `${whole}.${frac.padEnd(2, "0")}`;
2661
- return currency.toLowerCase() === "usd" ? `$${value}` : `${value} ${currency.toUpperCase()}`;
2662
- }
2663
2654
  function tokenLine(blocks2, cols) {
2664
2655
  const usage = blocks2[blocks2.length - 1];
2665
- if (usage?.type !== "usage") return null;
2666
- const parts = usageMeasures(usage.totals);
2667
- if (usage.model && !usage.contextFill) parts.push("ctx unknown");
2668
- if (usage.contextFill) parts.splice(2, 0, `${Math.round(usage.contextFill.usedTokens / usage.contextFill.windowTokens * 100)}% ctx`);
2669
- return parts.length > 0 ? style.grey(truncate(parts.join(" \xB7 "), cols)) : null;
2670
- }
2671
- function usageMeasures(totals) {
2672
- return [
2673
- ...totals.inputTokens !== void 0 ? [`${compactCount(totals.inputTokens)} in`] : [],
2674
- ...totals.outputTokens !== void 0 ? [`${compactCount(totals.outputTokens)} out`] : [],
2675
- ...totals.cachedInputTokens !== void 0 ? [`${compactCount(totals.cachedInputTokens)} cached`] : [],
2676
- ...Object.entries(totals.reportedCost ?? {}).map(([currency, amount]) => formatCost(currency, amount))
2677
- ];
2678
- }
2679
- function taskUsageText(usage) {
2680
- return [
2681
- ...usageMeasures(usage.totals),
2682
- ...usage.attempt !== void 0 ? [usage.contextFill ? `ctx ${Math.round(usage.contextFill.usedTokens / usage.contextFill.windowTokens * 100)}%` : "ctx unknown"] : []
2683
- ].join(" \xB7 ");
2656
+ const text = usage?.type === "usage" ? (0, import_core14.usageText)(usage) : null;
2657
+ return text ? style.grey(truncate(text, cols)) : null;
2684
2658
  }
2685
2659
  function assignmentFlagText(row) {
2686
2660
  return `${row.assignmentFlag} \u2014 ${row.assignmentConsequence}`;
@@ -2767,8 +2741,8 @@ function printOneSession(sessionId, meta, plan, runnerScope) {
2767
2741
  if (isolation) console.log(`Base: ${handoffBase(isolation.handoff, 8)}`);
2768
2742
  console.log(`Tasks: ${everyTask.length} total | ${count("completed")} done | ${count("failed")} failed | ${count("in_progress")} running | ${count("blocked")} blocked | ${count("skipped")} skipped
2769
2743
  `);
2770
- const usage = (0, import_core15.planUsage)(allTasks);
2771
- if (usage.attempts) console.log(`Tasks total: ${taskUsageText(usage)}`);
2744
+ const total = (0, import_core15.tasksTotalText)(allTasks);
2745
+ if (total) console.log(total);
2772
2746
  const record = servedApprovalRecord(plan);
2773
2747
  const approval = (row, ref) => row.waitsForApproval ? `${row.waitsForApproval}: \`ordewell force-start ${ref}\` approves it, \`ordewell run\` approves all` : null;
2774
2748
  for (const t of allTasks) {
@@ -2782,7 +2756,8 @@ function printOneSession(sessionId, meta, plan, runnerScope) {
2782
2756
  if (row.assignmentFlag) console.log(` \u26A0 ${assignmentFlagText(row)}`);
2783
2757
  if (row.blockedBy) console.log(` ${(0, import_core15.blockedByLabel)(row.blockedBy)}`);
2784
2758
  if (row.status === "skipped") console.log(` ${(0, import_core15.skippedLabel)(row.skipReason)}`);
2785
- if (row.usage) console.log(` ${taskUsageText(row.usage)}`);
2759
+ const usage = row.usage && (0, import_core15.usageText)(row.usage);
2760
+ if (usage) console.log(` ${usage}`);
2786
2761
  for (const sub of t.subtasks || []) {
2787
2762
  const subIcon = iconFor(blocked.has(sub.id) ? "blocked" : sub.status);
2788
2763
  const subModel = sub.assignedModel ? ` (${sub.assignedModel.modelLabel})` : "";
@@ -2794,7 +2769,8 @@ function printOneSession(sessionId, meta, plan, runnerScope) {
2794
2769
  if (subRow.assignmentFlag) console.log(` \u26A0 ${assignmentFlagText(subRow)}`);
2795
2770
  if (subRow.blockedBy) console.log(` ${(0, import_core15.blockedByLabel)(subRow.blockedBy)}`);
2796
2771
  if (subRow.status === "skipped") console.log(` ${(0, import_core15.skippedLabel)(subRow.skipReason)}`);
2797
- if (subRow.usage) console.log(` ${taskUsageText(subRow.usage)}`);
2772
+ const subUsage = subRow.usage && (0, import_core15.usageText)(subRow.usage);
2773
+ if (subUsage) console.log(` ${subUsage}`);
2798
2774
  }
2799
2775
  }
2800
2776
  }
@@ -4697,7 +4673,7 @@ ${namedOf(tasks, task)} is ${task.ops ? "an ops task: it runs in your checkout o
4697
4673
  }
4698
4674
 
4699
4675
  // src/tui/index.ts
4700
- var import_core51 = require("@ordewell/core");
4676
+ var import_core50 = require("@ordewell/core");
4701
4677
 
4702
4678
  // src/tui/slash.ts
4703
4679
  var import_core30 = require("@ordewell/core");
@@ -4730,16 +4706,9 @@ var SLASH_COMMANDS = [
4730
4706
  { name: "task-ops", usage: "/task-ops <id> [on|off]", description: "Choose between an ops task (runs in your checkout once its dependencies are merged) and a change task", category: "tasks" },
4731
4707
  // Models & providers
4732
4708
  { name: "planner", usage: "/planner [<provider>]", description: "Pick the planner: harness, model and effort in one go", category: "models" },
4733
- { name: "model", usage: "/model [set <id>]", description: "Show or set the planner model", category: "models" },
4734
- { name: "planner-effort", usage: "/planner-effort [<level>]", description: "Thinking effort for a coding-agent planner", category: "models" },
4735
4709
  { name: "key", usage: "/key [set <provider> <key>]", description: "Configure API provider keys", category: "models" },
4736
4710
  { name: "allowlist", usage: "/allowlist [set <runner> <ids> | clear <runner>]", description: "Limit which models a runner may use", category: "models" },
4737
4711
  { name: "runners", usage: "/runners [<id> on|off]", description: `Enable or disable runners (${runnerIdList()})`, category: "models" },
4738
- { name: "auto", usage: "/auto [full|guarded]", description: "Autonomy level for new plans: Full or Guarded", category: "models" },
4739
- { 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" },
4740
- { 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" },
4741
- { name: "autorun", usage: "/autorun [on|off]", description: "Start each plan the planner submits, without review", category: "models" },
4742
- { name: "parallel", usage: "/parallel [<n>]", description: "How many AI tasks run at once (applies to a live run)", category: "models" },
4743
4712
  { name: "settings", usage: "/settings", description: "Run settings: autonomy, supervisor, merging, autorun, parallel tasks", category: "models" },
4744
4713
  { name: "refresh", usage: "/refresh", description: "Re-discover runners and model catalogs", category: "models" },
4745
4714
  // Sessions
@@ -4880,8 +4849,7 @@ function refillPicker(state, kinds) {
4880
4849
  const overlay = state.overlay;
4881
4850
  if (overlay?.kind !== "picker" || !kinds.includes(overlay.picker.action.kind)) return state;
4882
4851
  const items = pickerItemsFor(state, overlay.picker.action);
4883
- const hint = overlay.picker.action.kind === "set-model" ? providerErrorHint(state) : overlay.picker.hint;
4884
- return { ...state, overlay: { kind: "picker", picker: { ...overlay.picker, items, hint, index: 0 } } };
4852
+ return { ...state, overlay: { kind: "picker", picker: { ...overlay.picker, items, index: 0 } } };
4885
4853
  }
4886
4854
  function reseedRunnerChoice(before, after) {
4887
4855
  const overlay = after.overlay;
@@ -4895,16 +4863,20 @@ function reseedRunnerChoice(before, after) {
4895
4863
  function modelDetail(m) {
4896
4864
  return [m.provider, m.pricing].filter(Boolean).join(" \xB7 ") || void 0;
4897
4865
  }
4898
- function providerErrorHint(state) {
4899
- const failed = Object.keys(state.providerErrors ?? {});
4900
- if (failed.length === 0) return void 0;
4901
- const names = failed.map((p) => (0, import_core31.getProviderMeta)(p)?.label ?? p);
4902
- return `\u26A0 Unavailable (key or fetch failed): ${names.join(", ")}. Showing working providers only.`;
4903
- }
4904
4866
  function plannerModelItems(state, provider, selectedId) {
4905
4867
  const runner = (0, import_core31.runnerForProvider)(provider);
4906
4868
  if (!runner) {
4907
- return state.orchestratorModels.map((m) => ({ id: m.id, label: m.label, detail: modelDetail(m), selected: m.id === selectedId }));
4869
+ const failed = Object.entries(state.providerErrors ?? {});
4870
+ const unavailable = failed.length === 0 ? [] : [{
4871
+ id: "",
4872
+ label: "Some providers are unavailable",
4873
+ detail: `\u26A0 ${failed.map(([id]) => (0, import_core31.getProviderMeta)(id)?.label ?? id).join(", ")}: key or fetch failed`,
4874
+ disabled: true
4875
+ }];
4876
+ return [
4877
+ ...unavailable,
4878
+ ...state.orchestratorModels.map((m) => ({ id: m.id, label: m.label, detail: modelDetail(m), selected: m.id === selectedId }))
4879
+ ];
4908
4880
  }
4909
4881
  const items = state.models.filter((m) => m.runners?.includes(runner)).map((m) => ({
4910
4882
  id: m.id,
@@ -4927,7 +4899,7 @@ function plannerEffortItems(state, provider, modelId, selectedEffort) {
4927
4899
  }
4928
4900
  const model = plannerHarnessModel(state, provider, modelId);
4929
4901
  if (!model) {
4930
- return [{ id: "", label: "No planner model selected", detail: "pick one with /model", disabled: true }];
4902
+ return [{ id: "", label: "No planner model selected", detail: "pick one with /planner", disabled: true }];
4931
4903
  }
4932
4904
  const variants = model.variants ?? [];
4933
4905
  if (variants.length === 0) {
@@ -4939,12 +4911,6 @@ function plannerEffortItems(state, provider, modelId, selectedEffort) {
4939
4911
  ];
4940
4912
  }
4941
4913
  function pickerItemsFor(state, action) {
4942
- if (action.kind === "set-model") {
4943
- return plannerModelItems(state, state.plannerProvider, state.orchestratorModel);
4944
- }
4945
- if (action.kind === "set-planner-effort") {
4946
- return plannerEffortItems(state, state.plannerProvider, state.orchestratorModel, state.plannerEffort);
4947
- }
4948
4914
  if (action.kind === "rewind") {
4949
4915
  if (state.rewindTargets === null) return [];
4950
4916
  if (state.rewindTargets.length === 0) {
@@ -5373,11 +5339,11 @@ function taskUsageFooter(state, tv, blocks2, cols) {
5373
5339
  const reported = task?.attemptUsage ?? [];
5374
5340
  if (!task || reported.length === 0) return tokenRow(blocks2, cols);
5375
5341
  const onScreen = tv.attempt > 0 ? reported.find((a) => a.attempt === tv.attempt) : reported.at(-1);
5376
- const spend = (0, import_core34.taskUsageSummary)(task);
5377
- const total = taskUsageText({ ...spend, attempt: reported.at(-1)?.attempt ?? 0 });
5378
- if (onScreen === reported.at(-1)) return [style.grey(truncate(total, cols))];
5379
- const own = onScreen ? [style.grey(truncate(`attempt ${onScreen.attempt}: ${taskUsageText({ totals: onScreen.totals, contextFill: (0, import_core34.plannerContextFill)(onScreen), attempt: onScreen.attempt })}`, cols))] : tokenRow(blocks2, cols);
5380
- return [...own, style.grey(truncate(`task total: ${total}`, cols))];
5342
+ const total = (0, import_core34.usageText)((0, import_core34.taskUsageSummary)(task));
5343
+ const totalRow = total ? [style.grey(truncate(onScreen === reported.at(-1) ? total : `task total: ${total}`, cols))] : [];
5344
+ if (onScreen === reported.at(-1)) return totalRow;
5345
+ const own = onScreen ? (0, import_core34.usageText)({ totals: onScreen.totals, contextFill: (0, import_core34.plannerContextFill)(onScreen) }) : null;
5346
+ return [...onScreen ? own ? [style.grey(truncate(`attempt ${onScreen.attempt}: ${own}`, cols))] : [] : tokenRow(blocks2, cols), ...totalRow];
5381
5347
  }
5382
5348
  function chatScrollMax(state) {
5383
5349
  return chatLayout(state, bodyRows(state), chatPaneWidth(state)).maxScroll;
@@ -5533,18 +5499,18 @@ var STATUS_ICON = {
5533
5499
  var inRow = (label) => label.charAt(0).toLowerCase() + label.slice(1);
5534
5500
  function planLayout(state, rows, cols) {
5535
5501
  const done = state.tasks.filter((t) => t.status === "completed").length;
5536
- const totalUsage = (0, import_core34.planUsage)(state.tasks);
5502
+ const totalUsage = (0, import_core34.tasksTotalText)(state.tasks);
5537
5503
  const unmerged = state.runMerge?.handoff.landed.length ?? 0;
5538
5504
  const count = `${done}/${state.tasks.length}`;
5539
5505
  const hints = runHints(state);
5540
5506
  const hint = hints.find((h) => width(`Plan ${count} \xB7 ${h}`) <= cols) ?? hints.at(-1);
5541
5507
  const lines = [
5542
5508
  truncate(`${style.bold(style.brand("Plan"))} ${style.grey(`${count}${hint ? ` \xB7 ${hint}` : ""}`)}`, cols),
5543
- totalUsage.attempts ? style.grey(truncate(`Tasks total: ${taskUsageText(totalUsage)}`, cols)) : ""
5509
+ totalUsage ? style.grey(truncate(totalUsage, cols)) : ""
5544
5510
  ];
5545
5511
  if (unmerged > 0) {
5546
5512
  const landed = style.dim(truncate(`${unmerged} landed task${unmerged === 1 ? "" : "s"} not merged: /handoff merge`, cols));
5547
- if (totalUsage.attempts) lines.push(landed);
5513
+ if (totalUsage) lines.push(landed);
5548
5514
  else lines[1] = landed;
5549
5515
  }
5550
5516
  const firstRowLine = lines.length;
@@ -5721,7 +5687,7 @@ function taskLines(state, planRow, index, cols) {
5721
5687
  lines.push(...taskText("Forced", `Started before the work of ${row.forcedPastGate.join(", ")} was merged into your branch.`, cols, bodyPad));
5722
5688
  }
5723
5689
  if (row.autonomous) {
5724
- lines.push(...taskText("Autonomy", "Runs without permission prompts (Full). Change the level with /auto.", cols, bodyPad));
5690
+ lines.push(...taskText("Autonomy", "Runs without permission prompts (Full). Change the level with /settings.", cols, bodyPad));
5725
5691
  }
5726
5692
  const editableSeed = task.prompt ?? task.description ?? task.title;
5727
5693
  if (task.description && task.description !== task.title && task.description !== editableSeed) {
@@ -6301,10 +6267,10 @@ function frame(title, body, rows, cols) {
6301
6267
  }
6302
6268
 
6303
6269
  // src/tui/reducer.ts
6304
- var import_core49 = require("@ordewell/core");
6270
+ var import_core48 = require("@ordewell/core");
6305
6271
 
6306
6272
  // src/tui/reducers/overlays.ts
6307
- var import_core48 = require("@ordewell/core");
6273
+ var import_core47 = require("@ordewell/core");
6308
6274
 
6309
6275
  // src/tui/reducers/approvals.ts
6310
6276
  var import_core37 = require("@ordewell/core");
@@ -6373,7 +6339,7 @@ function handleApprovalKey(state, overlay, key) {
6373
6339
  }
6374
6340
 
6375
6341
  // src/tui/reducers/commands.ts
6376
- var import_core47 = require("@ordewell/core");
6342
+ var import_core46 = require("@ordewell/core");
6377
6343
 
6378
6344
  // src/tui/reducers/plannerStepper.ts
6379
6345
  var import_core38 = require("@ordewell/core");
@@ -7329,73 +7295,8 @@ function followSession(state, message) {
7329
7295
  return message.type === "approval_settled" ? dropApproval(heard, message.id) : heard;
7330
7296
  }
7331
7297
 
7332
- // src/tui/reducers/runSettings.ts
7333
- var import_core45 = require("@ordewell/core");
7334
- function runSettingsEffect(state, changes) {
7335
- return { type: "setRunSettings", changes, ...state.sessionId ? { sessionId: state.sessionId } : {} };
7336
- }
7337
- function supervisorCommand(state, args) {
7338
- const [arg, value] = args;
7339
- if (arg === void 0) {
7340
- return step(say(state, "system", `${(0, import_core45.supervisorSummary)(state.runSettings)}: /supervisor off|watch|act, /supervisor retries <n>, /supervisor reads <n>.`));
7341
- }
7342
- if (arg === "retries") {
7343
- const n = (0, import_core45.parseCount)(value, 0);
7344
- return n === null ? fail3(state, "Usage: /supervisor retries <whole number, 0 or more>") : step(state, [runSettingsEffect(state, { supervisorRetryLimit: n })]);
7345
- }
7346
- if (arg === "reads") {
7347
- const n = (0, import_core45.parseCount)(value, 1);
7348
- return n === null ? fail3(state, "Usage: /supervisor reads <whole number, 1 or more>") : step(state, [runSettingsEffect(state, { wakeUpReadBudget: n })]);
7349
- }
7350
- if (arg === "act") return confirmSupervisorAct(state);
7351
- if (arg === "off" || arg === "watch") return step(state, [runSettingsEffect(state, { supervisorLevel: arg })]);
7352
- return fail3(state, "Usage: /supervisor [off|watch|act] \xB7 /supervisor retries <n> \xB7 /supervisor reads <n>");
7353
- }
7354
- function automergeCommand(state, arg) {
7355
- if (arg === void 0) {
7356
- return step(say(state, "system", `${(0, import_core45.automergeSummary)(state.runSettings)}: /automerge on|off.`));
7357
- }
7358
- const enabled = (0, import_core45.parseSwitch)(arg);
7359
- if (enabled === null) return fail3(state, "Usage: /automerge [on|off]");
7360
- return step(state, [runSettingsEffect(state, { mergeAtGatesAutomatically: enabled })]);
7361
- }
7362
- function autorunCommand(state, arg) {
7363
- if (arg === void 0) {
7364
- return step(say(state, "system", `${(0, import_core45.autorunSummary)(state.runSettings)}: /autorun on starts each plan the planner submits, without review.`));
7365
- }
7366
- const enabled = (0, import_core45.parseSwitch)(arg);
7367
- if (enabled === null) return fail3(state, "Usage: /autorun [on|off]");
7368
- if (enabled) return confirmAutorun(state);
7369
- return step(state, [runSettingsEffect(state, { autorun: false })]);
7370
- }
7371
- function confirmSupervisorAct(state) {
7372
- return step({
7373
- ...state,
7374
- overlay: {
7375
- kind: "confirm",
7376
- title: "Let the supervisor act?",
7377
- message: "At Act the supervisor runs, stops and retries tasks, answers their requests (never allowing), edits the plan and merges, without asking you.",
7378
- note: `${import_core45.ACT_RISK}
7379
- It applies to this session's run now, and to every later run.`,
7380
- action: { kind: "supervisor-act" }
7381
- }
7382
- });
7383
- }
7384
- function confirmAutorun(state) {
7385
- return step({
7386
- ...state,
7387
- overlay: {
7388
- kind: "confirm",
7389
- title: "Start plans without review?",
7390
- 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.",
7391
- note: import_core45.AUTORUN_RISK,
7392
- action: { kind: "autorun-on" }
7393
- }
7394
- });
7395
- }
7396
-
7397
7298
  // src/tui/reducers/settings.ts
7398
- var import_core46 = require("@ordewell/core");
7299
+ var import_core45 = require("@ordewell/core");
7399
7300
  var SUPERVISOR_DETAIL = {
7400
7301
  off: "The planner speaks only when you write",
7401
7302
  watch: "The planner follows your runs and suggests what to do",
@@ -7420,7 +7321,7 @@ var SETTINGS = {
7420
7321
  {
7421
7322
  id: "guarded",
7422
7323
  label: "Guarded",
7423
- detail: [`New plans run tasks in each runner's safer mode`, (0, import_core46.codexSandboxNotice)(state.modesByRunner)?.line].filter(Boolean).join(" \xB7 "),
7324
+ detail: [`New plans run tasks in each runner's safer mode`, (0, import_core45.codexSandboxNotice)(state.modesByRunner)?.line].filter(Boolean).join(" \xB7 "),
7424
7325
  selected: !state.autonomous
7425
7326
  }
7426
7327
  ]
@@ -7430,7 +7331,7 @@ var SETTINGS = {
7430
7331
  label: "Supervisor",
7431
7332
  items: (state) => ["off", "watch", "act"].map((level) => ({
7432
7333
  id: level,
7433
- label: import_core46.SUPERVISOR_LEVEL_LABEL[level],
7334
+ label: import_core45.SUPERVISOR_LEVEL_LABEL[level],
7434
7335
  detail: SUPERVISOR_DETAIL[level],
7435
7336
  selected: state.runSettings.supervisorLevel === level
7436
7337
  }))
@@ -7484,12 +7385,12 @@ function saveChoices(state, choices) {
7484
7385
  const autonomous = choices.autonomy === "full";
7485
7386
  if (autonomous !== state.autonomous) {
7486
7387
  save2.autonomous = autonomous;
7487
- changed.push(`Autonomy ${(0, import_core46.autonomyLevelLabel)(autonomous)}`);
7388
+ changed.push(`Autonomy ${(0, import_core45.autonomyLevelLabel)(autonomous)}`);
7488
7389
  }
7489
7390
  const level = choices.supervisor;
7490
7391
  if (level !== state.runSettings.supervisorLevel) {
7491
7392
  run.supervisorLevel = level;
7492
- changed.push(`Supervisor ${import_core46.SUPERVISOR_LEVEL_LABEL[level]}`);
7393
+ changed.push(`Supervisor ${import_core45.SUPERVISOR_LEVEL_LABEL[level]}`);
7493
7394
  }
7494
7395
  if (choices.retries !== void 0 && Number(choices.retries) !== state.runSettings.supervisorRetryLimit) {
7495
7396
  run.supervisorRetryLimit = Number(choices.retries);
@@ -7516,7 +7417,7 @@ function saveChoices(state, choices) {
7516
7417
  }
7517
7418
  if (changed.length === 0) return step(state);
7518
7419
  const effect = { ...save2, message: `Settings: ${changed.join(" \xB7 ")}` };
7519
- const risks = [...run.supervisorLevel === "act" ? [import_core46.ACT_RISK] : [], ...run.autorun ? [import_core46.AUTORUN_RISK] : []];
7420
+ const risks = [...run.supervisorLevel === "act" ? [import_core45.ACT_RISK] : [], ...run.autorun ? [import_core45.AUTORUN_RISK] : []];
7520
7421
  if (risks.length === 0) return saveSettings(state, effect);
7521
7422
  return step({
7522
7423
  ...state,
@@ -7567,28 +7468,14 @@ function runCommand(state, { name, args }) {
7567
7468
  state,
7568
7469
  (sessionId) => plannerInFlight(state) ? stopPlanning(state, sessionId) : step(state, [{ type: "stopExecution", sessionId }])
7569
7470
  );
7570
- case "model":
7571
- return setModel(state, args);
7572
7471
  case "planner":
7573
7472
  return setPlanner(state, args);
7574
- case "planner-effort":
7575
- return setPlannerEffort(state, args);
7576
7473
  case "key":
7577
7474
  return setKey(state, args);
7578
7475
  case "allowlist":
7579
7476
  return allowlist(state, args);
7580
7477
  case "runners":
7581
7478
  return runners(state, args);
7582
- case "auto":
7583
- return setAutonomous(state, args[0]);
7584
- case "supervisor":
7585
- return supervisorCommand(state, args);
7586
- case "automerge":
7587
- return automergeCommand(state, args[0]);
7588
- case "autorun":
7589
- return autorunCommand(state, args[0]);
7590
- case "parallel":
7591
- return setMaxParallel(state, args[0]);
7592
7479
  case "settings":
7593
7480
  return openSettings(state);
7594
7481
  case "mouse":
@@ -7709,8 +7596,8 @@ function newSession(state) {
7709
7596
  goal: "",
7710
7597
  taskView: null,
7711
7598
  planApproved: false,
7712
- conversation: import_core47.EMPTY_CONVERSATION,
7713
- turnGate: import_core47.NO_TURN,
7599
+ conversation: import_core46.EMPTY_CONVERSATION,
7600
+ turnGate: import_core46.NO_TURN,
7714
7601
  selectedTask: 0,
7715
7602
  expandedTaskId: null,
7716
7603
  taskEditor: null,
@@ -7721,40 +7608,16 @@ function newSession(state) {
7721
7608
  // Prompts belong to the session that raised them; the old planner is gone
7722
7609
  // and its pending requests deny on their own timeout.
7723
7610
  pendingApprovals: [],
7724
- queuedPrompts: import_core47.EMPTY_HOLD,
7611
+ queuedPrompts: import_core46.EMPTY_HOLD,
7725
7612
  stopArmed: false,
7726
7613
  forceSendPending: null,
7727
7614
  overlay: state.overlay?.kind === "approval" ? null : state.overlay
7728
- }, import_core47.EMPTY_RUN), closeEffects);
7729
- }
7730
- function setModel(state, args) {
7731
- if (args[0] === "set" && args[1]) {
7732
- const runner = (0, import_core47.runnerForProvider)(state.plannerProvider);
7733
- const known = runner ? modelsForRunner(state.models, runner) : [];
7734
- if (runner && known.length > 0 && !known.some((m) => m.id === args[1])) {
7735
- return fail3(state, `${args[1]} was not discovered for ${runner}.`);
7736
- }
7737
- const refusal = known.length === 0 ? vendorModelRefusal(state.plannerProvider, args[1], import_core47.TERMINAL_UI_COMMANDS.pickPlanner) : null;
7738
- if (refusal) return fail3(state, refusal);
7739
- return step(state, [{ type: "setModel", modelId: args[1] }]);
7740
- }
7741
- if (args.length > 0 && args[0] !== "set") return fail3(state, "Usage: /model [set <model-id>]");
7742
- const items = pickerItemsFor(state, { kind: "set-model" });
7743
- return step(
7744
- {
7745
- ...state,
7746
- overlay: {
7747
- kind: "picker",
7748
- picker: picker("Planner model", items, { kind: "set-model" }, { hint: providerErrorHint(state), filterable: true })
7749
- }
7750
- },
7751
- [{ type: "loadModels" }]
7752
- );
7615
+ }, import_core46.EMPTY_RUN), closeEffects);
7753
7616
  }
7754
7617
  function setPlanner(state, args) {
7755
7618
  if (args[0]) {
7756
7619
  const id = args[0].toLowerCase();
7757
- if (!(0, import_core47.isPlannerBackend)(id)) {
7620
+ if (!(0, import_core46.isPlannerBackend)(id)) {
7758
7621
  return fail3(state, `Unknown planner: ${id}. Run /planner with no arguments to see the list.`);
7759
7622
  }
7760
7623
  return step(state, [{ type: "setPlanner", provider: id }]);
@@ -7762,31 +7625,10 @@ function setPlanner(state, args) {
7762
7625
  const opened = openStepper(state, plannerStepper);
7763
7626
  return { ...opened, effects: [...opened.effects, { type: "loadModels" }] };
7764
7627
  }
7765
- function setPlannerEffort(state, args) {
7766
- const items = plannerEffortItems(state, state.plannerProvider, state.orchestratorModel, state.plannerEffort);
7767
- if (args[0]) {
7768
- const wanted = args[0].toLowerCase();
7769
- const match = items.find((i) => !i.disabled && (i.id === wanted || wanted === "default" && i.id === DEFAULT_EFFORT));
7770
- if (!match) {
7771
- const available = items.filter((i) => !i.disabled && i.id !== DEFAULT_EFFORT).map((i) => i.id);
7772
- return fail3(state, available.length > 0 ? `Unknown effort: ${args[0]}. Available: ${available.join(", ")}, default.` : items[0]?.label ?? "No effort levels available.");
7773
- }
7774
- return step(state, [{ type: "setPlannerEffort", effort: match.id === DEFAULT_EFFORT ? "" : match.id }]);
7775
- }
7776
- return step({
7777
- ...state,
7778
- overlay: {
7779
- kind: "picker",
7780
- picker: picker("Planner thinking effort", items, { kind: "set-planner-effort" }, {
7781
- hint: "How hard the planning agent thinks per turn. Higher costs latency and tokens against your subscription."
7782
- })
7783
- }
7784
- });
7785
- }
7786
7628
  function setKey(state, args) {
7787
7629
  if (args[0] === "set" && args[1]) {
7788
7630
  const provider = args[1].toLowerCase();
7789
- if (!(0, import_core47.isApiProvider)(provider)) {
7631
+ if (!(0, import_core46.isApiProvider)(provider)) {
7790
7632
  return fail3(state, `Unknown provider: ${provider}. Run /key with no arguments to see the list.`);
7791
7633
  }
7792
7634
  if (!args[2]) {
@@ -7797,16 +7639,16 @@ function setKey(state, args) {
7797
7639
  }
7798
7640
  return step(state, [{ type: "setApiKey", provider, key: args.slice(2).join(" ") }]);
7799
7641
  }
7800
- const items = import_core47.PROVIDER_PRIORITY.map((id) => ({
7642
+ const items = import_core46.PROVIDER_PRIORITY.map((id) => ({
7801
7643
  id,
7802
- label: (0, import_core47.getProviderMeta)(id).label,
7803
- detail: (0, import_core47.getProviderMeta)(id).apiKeyEnvVar,
7644
+ label: (0, import_core46.getProviderMeta)(id).label,
7645
+ detail: (0, import_core46.getProviderMeta)(id).apiKeyEnvVar,
7804
7646
  selected: state.configuredProviders.includes(id)
7805
7647
  }));
7806
7648
  return step({ ...state, overlay: { kind: "picker", picker: picker("API provider key", items, { kind: "set-key" }) } });
7807
7649
  }
7808
7650
  function keyPrompt(provider) {
7809
- const meta = (0, import_core47.getProviderMeta)(provider);
7651
+ const meta = (0, import_core46.getProviderMeta)(provider);
7810
7652
  return {
7811
7653
  kind: "prompt",
7812
7654
  title: `${meta.label} API key`,
@@ -7881,18 +7723,6 @@ function runners(state, args) {
7881
7723
  })
7882
7724
  } }, [{ type: "loadRunners" }]);
7883
7725
  }
7884
- function setMaxParallel(state, arg) {
7885
- if (!arg) return step(say(state, "system", `Up to ${state.maxParallel} AI task${state.maxParallel === 1 ? "" : "s"} run at once: /parallel <n> changes it.`));
7886
- const limit = (0, import_core47.parseMaxParallel)(arg);
7887
- if (limit === null) return fail3(state, "Usage: /parallel [<number of tasks, 1 or more>]");
7888
- return step({ ...state, maxParallel: limit }, [{ type: "setMaxParallel", limit }]);
7889
- }
7890
- function setAutonomous(state, arg) {
7891
- if (arg === void 0) return step(say(state, "system", `Autonomy level: ${(0, import_core47.autonomyLevelLabel)(state.autonomous)}. /auto full or /auto guarded changes it for new plans.`));
7892
- const enabled = (0, import_core47.parseAutonomyLevel)(arg);
7893
- if (enabled === null) return fail3(state, "Usage: /auto [full|guarded]");
7894
- return step({ ...state, autonomous: enabled }, [{ type: "setAutonomous", enabled }]);
7895
- }
7896
7726
  function setMouseCapture(state, arg) {
7897
7727
  const enabled = resolveToggle(arg, state.mouseCapture);
7898
7728
  if (enabled === null) return fail3(state, "Usage: /mouse [on|off]");
@@ -7983,8 +7813,6 @@ function runConfirm(state, overlay) {
7983
7813
  if (!state.sessionId) return step(closed);
7984
7814
  return step(closed, [taskActionEffect(closed, state.sessionId, overlay.action.taskId, "force-start")]);
7985
7815
  }
7986
- if (overlay.action.kind === "supervisor-act") return step(closed, [runSettingsEffect(closed, { supervisorLevel: "act" })]);
7987
- if (overlay.action.kind === "autorun-on") return step(closed, [runSettingsEffect(closed, { autorun: true })]);
7988
7816
  if (overlay.action.kind === "save-settings") return answerSaveSettings(state, overlay.action, true);
7989
7817
  if (overlay.action.kind === "merge-run" || overlay.action.kind === "discard-run") {
7990
7818
  return confirmedHandoff(state, overlay.action.kind);
@@ -8087,10 +7915,6 @@ function choose2(state, picker2, item) {
8087
7915
  return step(say(state, "error", item.detail ? `${item.label}: ${item.detail}` : `${item.label} is not available.`));
8088
7916
  }
8089
7917
  switch (picker2.action.kind) {
8090
- case "set-model":
8091
- return step(closed, [{ type: "setModel", modelId: item.id }]);
8092
- case "set-planner-effort":
8093
- return step(closed, [{ type: "setPlannerEffort", effort: item.id === DEFAULT_EFFORT ? "" : item.id }]);
8094
7918
  case "load-session":
8095
7919
  return step(closed, [{ type: "loadSession", sessionId: item.id }]);
8096
7920
  case "rewind":
@@ -8098,7 +7922,7 @@ function choose2(state, picker2, item) {
8098
7922
  case "delete-session":
8099
7923
  return step(closed, [{ type: "deleteSession", sessionId: item.id }]);
8100
7924
  case "set-key":
8101
- return (0, import_core48.isApiProvider)(item.id) ? step({ ...state, overlay: keyPrompt(item.id) }) : step(closed);
7925
+ return (0, import_core47.isApiProvider)(item.id) ? step({ ...state, overlay: keyPrompt(item.id) }) : step(closed);
8102
7926
  case "choose-allowlist-runner": {
8103
7927
  const action = { kind: "set-allowlist", runner: item.id };
8104
7928
  const items = pickerItemsFor(state, action);
@@ -8174,7 +7998,7 @@ function reduceAction(state, action) {
8174
7998
  // (`task-1`), so nothing of the last one's — a merge gate, a checkpoint, its
8175
7999
  // tasks — may carry over into this.
8176
8000
  case "sessionStarted":
8177
- return step(withRun({ ...state, sessionId: action.sessionId, goal: action.goal, taskView: null }, import_core49.EMPTY_RUN));
8001
+ return step(withRun({ ...state, sessionId: action.sessionId, goal: action.goal, taskView: null }, import_core48.EMPTY_RUN));
8178
8002
  // A loaded session is a different one: the turn the old one had out, the
8179
8003
  // prompts held behind it and a stop armed against it are not this one's.
8180
8004
  // (`sessionStarted` cannot reset them: `startConversation` dispatches it
@@ -8186,13 +8010,13 @@ function reduceAction(state, action) {
8186
8010
  goal: action.goal,
8187
8011
  taskView: null,
8188
8012
  planner: "idle",
8189
- turnGate: import_core49.NO_TURN,
8013
+ turnGate: import_core48.NO_TURN,
8190
8014
  pendingApprovals: [],
8191
- queuedPrompts: import_core49.EMPTY_HOLD,
8015
+ queuedPrompts: import_core48.EMPTY_HOLD,
8192
8016
  stopArmed: false,
8193
8017
  forceSendPending: null,
8194
8018
  overlay: state.overlay?.kind === "approval" ? null : state.overlay
8195
- }, import_core49.EMPTY_RUN));
8019
+ }, import_core48.EMPTY_RUN));
8196
8020
  // The daemon registers a session only once planning succeeds; when it does
8197
8021
  // not, holding on to the id would send every next message to a session the
8198
8022
  // server never had.
@@ -8202,20 +8026,20 @@ function reduceAction(state, action) {
8202
8026
  sessionId: null,
8203
8027
  goal: "",
8204
8028
  taskView: null,
8205
- turnGate: import_core49.NO_TURN,
8029
+ turnGate: import_core48.NO_TURN,
8206
8030
  pendingApprovals: [],
8207
- queuedPrompts: import_core49.EMPTY_HOLD,
8031
+ queuedPrompts: import_core48.EMPTY_HOLD,
8208
8032
  stopArmed: false,
8209
8033
  forceSendPending: null,
8210
8034
  overlay: state.overlay?.kind === "approval" ? null : state.overlay
8211
- }, import_core49.EMPTY_RUN));
8035
+ }, import_core48.EMPTY_RUN));
8212
8036
  // Deleting the session on screen stops it in the daemon; a view left on it
8213
8037
  // would answer every next message with a session-not-found.
8214
8038
  case "sessionDeleted":
8215
8039
  return action.sessionId === state.sessionId ? newSession(state) : step(state);
8216
8040
  case "chatRestored":
8217
8041
  if (stale(state, action.sessionId)) return step(state);
8218
- return step({ ...state, conversation: (0, import_core49.fromTranscript)(action.history, action.researchLog, action.plannerUsage, action.pendingTurns), scroll: 0 });
8042
+ return step({ ...state, conversation: (0, import_core48.fromTranscript)(action.history, action.researchLog, action.plannerUsage, action.pendingTurns), scroll: 0 });
8219
8043
  case "planRefreshed":
8220
8044
  if (stale(state, action.sessionId)) return step(state);
8221
8045
  return step(showPlan(state, action.plan));
@@ -8268,9 +8092,9 @@ function reduceAction(state, action) {
8268
8092
  taskId: action.taskId,
8269
8093
  order: action.order ?? 0,
8270
8094
  title: action.title,
8271
- runner: action.runner ?? import_core49.DEFAULT_RUNNERS[0]
8095
+ runner: action.runner ?? import_core48.DEFAULT_RUNNERS[0]
8272
8096
  });
8273
- const spoken = say(folded, "system", (0, import_core49.taskStartedNotice)(action.title, action.runner));
8097
+ const spoken = say(folded, "system", (0, import_core48.taskStartedNotice)(action.title, action.runner));
8274
8098
  return step({ ...spoken, status: "executing" });
8275
8099
  }
8276
8100
  case "taskCheckpoint":
@@ -8322,7 +8146,7 @@ function reduceAction(state, action) {
8322
8146
  completed: state.tasks.filter((t) => t.status === "completed").length,
8323
8147
  total: state.tasks.length,
8324
8148
  failed: state.tasks.filter((t) => t.status === "failed").length,
8325
- blocked: (0, import_core49.blockingFailures)(state.tasks).size,
8149
+ blocked: (0, import_core48.blockingFailures)(state.tasks).size,
8326
8150
  skipped: state.tasks.filter((t) => t.status === "skipped").length
8327
8151
  };
8328
8152
  const failures = `${failed > 0 ? ` \xB7 ${failed} failed` : ""}${blocked ? ` \xB7 ${blocked} blocked` : ""}${skipped ? ` \xB7 ${skipped} skipped` : ""}`;
@@ -8365,7 +8189,7 @@ function reduceAction(state, action) {
8365
8189
  providerErrors: action.providerErrors ?? state.providerErrors,
8366
8190
  modesByRunner: action.modesByRunner ?? state.modesByRunner
8367
8191
  },
8368
- ["set-model", "set-task-model", "set-task-effort", "set-task-mode"]
8192
+ ["set-task-model", "set-task-effort", "set-task-mode"]
8369
8193
  )
8370
8194
  ));
8371
8195
  case "sessionsLoaded":
@@ -8385,14 +8209,14 @@ function reduceAction(state, action) {
8385
8209
  taskView: null,
8386
8210
  status: "idle",
8387
8211
  planner: "idle",
8388
- turnGate: import_core49.NO_TURN,
8212
+ turnGate: import_core48.NO_TURN,
8389
8213
  planApproved: false,
8390
8214
  pendingApprovals: [],
8391
- queuedPrompts: import_core49.EMPTY_HOLD,
8215
+ queuedPrompts: import_core48.EMPTY_HOLD,
8392
8216
  stopArmed: false,
8393
8217
  forceSendPending: null,
8394
8218
  overlay: state.overlay?.kind === "approval" ? null : state.overlay
8395
- }, import_core49.EMPTY_RUN));
8219
+ }, import_core48.EMPTY_RUN));
8396
8220
  // The rewound message comes back as a draft to edit and resend, so it lands
8397
8221
  // as if just typed: history is not being browsed, and nothing is parked.
8398
8222
  case "inputPrefilled":
@@ -8568,7 +8392,7 @@ function submit(state) {
8568
8392
  const builtIn = builtInCommand(text);
8569
8393
  if (builtIn) return runCommand(cleared, builtIn);
8570
8394
  if (plannerInFlight(state)) {
8571
- return step({ ...cleared, queuedPrompts: (0, import_core49.holdPrompt)(state.queuedPrompts, text) });
8395
+ return step({ ...cleared, queuedPrompts: (0, import_core48.holdPrompt)(state.queuedPrompts, text) });
8572
8396
  }
8573
8397
  const spoken = say(cleared, "user", text);
8574
8398
  const effect = state.sessionId ? { type: "sendMessage", sessionId: state.sessionId, message: text } : { type: "startConversation", goal: text };
@@ -8643,7 +8467,7 @@ function createApp(deps) {
8643
8467
 
8644
8468
  // src/tui/effects.ts
8645
8469
  var import_child_process3 = require("child_process");
8646
- var import_core50 = require("@ordewell/core");
8470
+ var import_core49 = require("@ordewell/core");
8647
8471
 
8648
8472
  // src/tui/inbound.ts
8649
8473
  var CONVERSATION_TYPES = /* @__PURE__ */ new Set([
@@ -9071,9 +8895,9 @@ function plannerModelNotice(recall2) {
9071
8895
  case "remembered":
9072
8896
  return `Restored ${recall2.model}.`;
9073
8897
  case "catalog-default":
9074
- return `Using its default model, ${recall2.model}. Pick another with /model.`;
8898
+ return `Using its default model, ${recall2.model}. Pick another with /planner.`;
9075
8899
  case "none":
9076
- return "Pick a model with /model.";
8900
+ return "Pick a model with /planner.";
9077
8901
  }
9078
8902
  }
9079
8903
  async function perform(effect, deps) {
@@ -9133,24 +8957,18 @@ async function perform(effect, deps) {
9133
8957
  await refreshPlan(deps, sessionId);
9134
8958
  return;
9135
8959
  }
9136
- 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_core50.markRequestFor)(action) === "uncomplete" ? () => api.markTaskIncomplete(sessionId, taskId) : () => api.markTaskComplete(sessionId, taskId);
8960
+ 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_core49.markRequestFor)(action) === "uncomplete" ? () => api.markTaskIncomplete(sessionId, taskId) : () => api.markTaskComplete(sessionId, taskId);
9137
8961
  await (effect.watch ? withExecutionStream(deps, sessionId, request) : request());
9138
8962
  await refreshPlan(deps, sessionId);
9139
8963
  return;
9140
8964
  }
9141
8965
  case "addTask": {
9142
- const fields = (0, import_core50.newTaskFields)(effect.title);
8966
+ const fields = (0, import_core49.newTaskFields)(effect.title);
9143
8967
  if (!fields) return;
9144
8968
  await api.addTask(effect.sessionId, { ...fields });
9145
8969
  await refreshPlan(deps, effect.sessionId);
9146
8970
  return;
9147
8971
  }
9148
- case "setRunSettings": {
9149
- const settings = await api.updateRunSettings(effect.changes, effect.sessionId);
9150
- dispatch({ type: "settingsLoaded", settings });
9151
- if (effect.sessionId) await refreshPlan(deps, effect.sessionId);
9152
- return;
9153
- }
9154
8972
  case "updateTask":
9155
8973
  await api.updateTask(effect.sessionId, effect.taskId, effect.changes);
9156
8974
  await refreshPlan(deps, effect.sessionId);
@@ -9234,20 +9052,12 @@ async function perform(effect, deps) {
9234
9052
  case "interruptTask":
9235
9053
  await api.interruptTask(effect.sessionId, effect.taskId);
9236
9054
  return;
9237
- case "setModel": {
9238
- const settled = await api.updateSettings({ orchestratorModel: effect.modelId });
9239
- const plannerThinkingEffort = typeof settled.plannerThinkingEffort === "string" ? settled.plannerThinkingEffort : "";
9240
- persistAfterDaemon(deps, { ORCHESTRATOR_MODEL: effect.modelId, ORDEWELL_PLANNER_EFFORT: plannerThinkingEffort });
9241
- dispatch({ type: "settingsLoaded", settings: { orchestratorModel: effect.modelId, plannerThinkingEffort } });
9242
- dispatch({ type: "notice", message: `Planner model set to ${effect.modelId}.` });
9243
- return;
9244
- }
9245
9055
  case "setPlanner": {
9246
- const meta = (0, import_core50.getProviderMeta)(effect.provider);
9056
+ const meta = (0, import_core49.getProviderMeta)(effect.provider);
9247
9057
  if (!meta) throw new Error(`Unknown planner: ${effect.provider}`);
9248
- if ((0, import_core50.isCliProvider)(effect.provider)) {
9058
+ if ((0, import_core49.isCliProvider)(effect.provider)) {
9249
9059
  const installed = ((await api.getRunners()).runners ?? []).map((r) => r.id);
9250
- const refusal = uninstalledPlannerRefusal(effect.provider, installed, import_core50.TERMINAL_UI_COMMANDS.pickPlanner);
9060
+ const refusal = uninstalledPlannerRefusal(effect.provider, installed, import_core49.TERMINAL_UI_COMMANDS.pickPlanner);
9251
9061
  if (refusal) throw new Error(refusal);
9252
9062
  }
9253
9063
  const env = { AI_PROVIDER: effect.provider };
@@ -9260,7 +9070,7 @@ async function perform(effect, deps) {
9260
9070
  });
9261
9071
  dispatch({
9262
9072
  type: "notice",
9263
- message: `${(0, import_core50.isCliProvider)(effect.provider) ? `Planning with ${meta.label}: no API key needed.` : `Planner set to ${meta.label}.`} ${plannerModelNotice(recall2)}`
9073
+ message: `${(0, import_core49.isCliProvider)(effect.provider) ? `Planning with ${meta.label}: no API key needed.` : `Planner set to ${meta.label}.`} ${plannerModelNotice(recall2)}`
9264
9074
  });
9265
9075
  await loadModels(deps);
9266
9076
  return;
@@ -9281,14 +9091,8 @@ async function perform(effect, deps) {
9281
9091
  dispatch({ type: "notice", message: effect.notice });
9282
9092
  return;
9283
9093
  }
9284
- case "setPlannerEffort":
9285
- await api.updateSettings({ env: { ORDEWELL_PLANNER_EFFORT: effect.effort } });
9286
- deps.setEnvVar("ORDEWELL_PLANNER_EFFORT", effect.effort);
9287
- dispatch({ type: "settingsLoaded", settings: { plannerThinkingEffort: effect.effort } });
9288
- dispatch({ type: "notice", message: `Planner effort set to ${effect.effort || "the runner default"}.` });
9289
- return;
9290
9094
  case "setApiKey": {
9291
- const meta = (0, import_core50.isApiProvider)(effect.provider) ? (0, import_core50.getProviderMeta)(effect.provider) : void 0;
9095
+ const meta = (0, import_core49.isApiProvider)(effect.provider) ? (0, import_core49.getProviderMeta)(effect.provider) : void 0;
9292
9096
  if (!meta) throw new Error(`Unknown provider: ${effect.provider}`);
9293
9097
  await api.updateSettings({ env: { [meta.apiKeyEnvVar]: effect.key } });
9294
9098
  deps.setEnvVar(meta.apiKeyEnvVar, effect.key);
@@ -9319,10 +9123,6 @@ async function perform(effect, deps) {
9319
9123
  dispatch({ type: "notice", message: effect.message });
9320
9124
  return;
9321
9125
  }
9322
- case "setMaxParallel":
9323
- await saveMaxParallel(deps, effect.limit);
9324
- dispatch({ type: "notice", message: `Up to ${effect.limit} AI task${effect.limit === 1 ? "" : "s"} now run at once.` });
9325
- return;
9326
9126
  case "saveSettings": {
9327
9127
  if (Object.keys(effect.run).length > 0) {
9328
9128
  const settings = await api.updateRunSettings(effect.run, effect.sessionId);
@@ -9334,12 +9134,6 @@ async function perform(effect, deps) {
9334
9134
  dispatch({ type: "notice", message: overridden ? `${effect.message}: ORDEWELL_AUTONOMOUS_MODE in the environment decides the autonomy level until it is unset.` : effect.message });
9335
9135
  return;
9336
9136
  }
9337
- case "setAutonomous": {
9338
- const { overridden } = deps.saveAutonomy(effect.enabled);
9339
- const level = (0, import_core50.autonomyLevelLabel)(effect.enabled);
9340
- 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.` });
9341
- return;
9342
- }
9343
9137
  case "setMouseCapture":
9344
9138
  deps.setMouseCapture(effect.enabled);
9345
9139
  deps.setEnvVar("ORDEWELL_TUI_MOUSE", String(effect.enabled));
@@ -9512,7 +9306,7 @@ async function saveMaxParallel(deps, limit) {
9512
9306
  function copySelection(deps, text) {
9513
9307
  if (!text) return;
9514
9308
  const lines = text.split("\n").length;
9515
- const command = (0, import_core50.clipboardCopyCommand)(deps.hasBin);
9309
+ const command = (0, import_core49.clipboardCopyCommand)(deps.hasBin);
9516
9310
  if (command) {
9517
9311
  try {
9518
9312
  (deps.pipeToClipboard ?? pipeToClipboardDefault)(command, text);
@@ -9617,7 +9411,7 @@ function turnReplies(plan) {
9617
9411
  const replies = [];
9618
9412
  for (let i = history.length - 1; i >= 0; i--) {
9619
9413
  const entry = history[i];
9620
- if ((0, import_core50.isUserMessage)(entry)) break;
9414
+ if ((0, import_core49.isUserMessage)(entry)) break;
9621
9415
  if (entry.role === "assistant" && entry.kind === void 0) {
9622
9416
  const { content, timestamp, runs } = entry;
9623
9417
  replies.unshift({ content, ...timestamp ? { timestamp } : {}, ...runs ? { runs } : {} });
@@ -9973,7 +9767,7 @@ async function handleTui(subArgs) {
9973
9767
  }
9974
9768
  const workspace = flag(subArgs, "--workspace") || process.cwd();
9975
9769
  try {
9976
- (0, import_core51.assertWorkspaceExists)(workspace);
9770
+ (0, import_core50.assertWorkspaceExists)(workspace);
9977
9771
  } catch {
9978
9772
  console.error(
9979
9773
  `Workspace "${workspace}" does not exist.
@@ -9982,7 +9776,7 @@ cd into a directory that exists, or pass --workspace <path> naming one that does
9982
9776
  );
9983
9777
  process.exit(1);
9984
9778
  }
9985
- const discoveredSkills = (0, import_core51.createSkillsService)(workspace, new import_core51.EnvConfig().workspaceRepos).listSkills();
9779
+ const discoveredSkills = (0, import_core50.createSkillsService)(workspace, new import_core50.EnvConfig().workspaceRepos).listSkills();
9986
9780
  registerSkillCommands(discoveredSkills);
9987
9781
  const taskSkills = discoveredSkills.filter((s) => s.appliesTo === "task").map((s) => ({ name: s.name, description: s.description }));
9988
9782
  const explicitPort = flag(subArgs, "--port") || process.env.ORDEWELL_PORT;
@@ -9992,7 +9786,7 @@ cd into a directory that exists, or pass --workspace <path> naming one that does
9992
9786
  const api = new ApiClient(port, workspace);
9993
9787
  let terminal;
9994
9788
  const mouseCapture = process.env.ORDEWELL_TUI_MOUSE !== "false" && process.env.ORDEWELL_TUI_MOUSE !== "0";
9995
- const settings = new import_core51.SettingsService();
9789
+ const settings = new import_core50.SettingsService();
9996
9790
  const app = createApp({
9997
9791
  // The level the daemon plans with: the saved one, unless the environment overrides it (ADR-0030).
9998
9792
  // The run settings are seeded from the same file because the first frame is
@@ -10014,13 +9808,13 @@ cd into a directory that exists, or pass --workspace <path> naming one that does
10014
9808
  workspace,
10015
9809
  port,
10016
9810
  dispatch: (action) => app.dispatch(action),
10017
- newSessionId: () => (0, import_core51.mintSessionId)(),
9811
+ newSessionId: () => (0, import_core50.mintSessionId)(),
10018
9812
  setEnvVar: (key, value) => {
10019
9813
  writeEnvVar(findEnvFile(), key, value);
10020
9814
  process.env[key] = value;
10021
9815
  },
10022
9816
  saveAutonomy: (enabled) => {
10023
- const settings2 = new import_core51.SettingsService();
9817
+ const settings2 = new import_core50.SettingsService();
10024
9818
  settings2.setAutonomousMode(enabled);
10025
9819
  return { overridden: settings2.autonomousModeOverridden() };
10026
9820
  },
@@ -10137,7 +9931,7 @@ var COMMANDS = {
10137
9931
  // src/main.ts
10138
9932
  var TUI_FLAGS = /* @__PURE__ */ new Set(["--workspace", "--port"]);
10139
9933
  async function main() {
10140
- (0, import_core52.migrateOldConfigDir)();
9934
+ (0, import_core51.migrateOldConfigDir)();
10141
9935
  moveAutonomyToSettings();
10142
9936
  loadEnvFile();
10143
9937
  const argv = process.argv.slice(2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ordewell/cli",
3
- "version": "0.10.9",
3
+ "version": "0.10.11",
4
4
  "description": "Ordewell CLI and TUI — plan, run and verify coding-agent tasks from the terminal.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Alessandro Costanzo Ciano",
@@ -51,8 +51,8 @@
51
51
  "typecheck": "tsc --noEmit"
52
52
  },
53
53
  "dependencies": {
54
- "@ordewell/core": "^0.10.9",
55
- "@ordewell/web": "^0.10.9",
54
+ "@ordewell/core": "^0.10.11",
55
+ "@ordewell/web": "^0.10.11",
56
56
  "string-width": "^7.2.0",
57
57
  "ws": "^8.18.0"
58
58
  },