@ordewell/cli 0.10.10 → 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.
- package/README.md +11 -7
- package/dist/main.js +82 -263
- 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
|
|
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. `/
|
|
28
|
-
|
|
29
|
-
full key sheet; the footer shows only the keys that apply
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
|
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.
|
|
133
|
-
|
|
134
|
-
|
|
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
|
|
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
|
|
181
|
-
ordewell supervisor [off|watch|act] Whether the planner watches or acts on your runs
|
|
182
|
-
also: supervisor retries <n>, supervisor reads <n
|
|
183
|
-
ordewell automerge [on|off] Merge
|
|
184
|
-
ordewell autorun [on|off] Start each plan the planner submits, without review
|
|
185
|
-
ordewell parallel [<n>] How many AI tasks run at once
|
|
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
|
|
|
@@ -4672,7 +4673,7 @@ ${namedOf(tasks, task)} is ${task.ops ? "an ops task: it runs in your checkout o
|
|
|
4672
4673
|
}
|
|
4673
4674
|
|
|
4674
4675
|
// src/tui/index.ts
|
|
4675
|
-
var
|
|
4676
|
+
var import_core50 = require("@ordewell/core");
|
|
4676
4677
|
|
|
4677
4678
|
// src/tui/slash.ts
|
|
4678
4679
|
var import_core30 = require("@ordewell/core");
|
|
@@ -4705,16 +4706,9 @@ var SLASH_COMMANDS = [
|
|
|
4705
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" },
|
|
4706
4707
|
// Models & providers
|
|
4707
4708
|
{ name: "planner", usage: "/planner [<provider>]", description: "Pick the planner: harness, model and effort in one go", category: "models" },
|
|
4708
|
-
{ name: "model", usage: "/model [set <id>]", description: "Show or set the planner model", category: "models" },
|
|
4709
|
-
{ name: "planner-effort", usage: "/planner-effort [<level>]", description: "Thinking effort for a coding-agent planner", category: "models" },
|
|
4710
4709
|
{ name: "key", usage: "/key [set <provider> <key>]", description: "Configure API provider keys", category: "models" },
|
|
4711
4710
|
{ name: "allowlist", usage: "/allowlist [set <runner> <ids> | clear <runner>]", description: "Limit which models a runner may use", category: "models" },
|
|
4712
4711
|
{ name: "runners", usage: "/runners [<id> on|off]", description: `Enable or disable runners (${runnerIdList()})`, category: "models" },
|
|
4713
|
-
{ name: "auto", usage: "/auto [full|guarded]", description: "Autonomy level for new plans: Full or Guarded", category: "models" },
|
|
4714
|
-
{ 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" },
|
|
4715
|
-
{ 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" },
|
|
4716
|
-
{ name: "autorun", usage: "/autorun [on|off]", description: "Start each plan the planner submits, without review", category: "models" },
|
|
4717
|
-
{ name: "parallel", usage: "/parallel [<n>]", description: "How many AI tasks run at once (applies to a live run)", category: "models" },
|
|
4718
4712
|
{ name: "settings", usage: "/settings", description: "Run settings: autonomy, supervisor, merging, autorun, parallel tasks", category: "models" },
|
|
4719
4713
|
{ name: "refresh", usage: "/refresh", description: "Re-discover runners and model catalogs", category: "models" },
|
|
4720
4714
|
// Sessions
|
|
@@ -4855,8 +4849,7 @@ function refillPicker(state, kinds) {
|
|
|
4855
4849
|
const overlay = state.overlay;
|
|
4856
4850
|
if (overlay?.kind !== "picker" || !kinds.includes(overlay.picker.action.kind)) return state;
|
|
4857
4851
|
const items = pickerItemsFor(state, overlay.picker.action);
|
|
4858
|
-
|
|
4859
|
-
return { ...state, overlay: { kind: "picker", picker: { ...overlay.picker, items, hint, index: 0 } } };
|
|
4852
|
+
return { ...state, overlay: { kind: "picker", picker: { ...overlay.picker, items, index: 0 } } };
|
|
4860
4853
|
}
|
|
4861
4854
|
function reseedRunnerChoice(before, after) {
|
|
4862
4855
|
const overlay = after.overlay;
|
|
@@ -4870,16 +4863,20 @@ function reseedRunnerChoice(before, after) {
|
|
|
4870
4863
|
function modelDetail(m) {
|
|
4871
4864
|
return [m.provider, m.pricing].filter(Boolean).join(" \xB7 ") || void 0;
|
|
4872
4865
|
}
|
|
4873
|
-
function providerErrorHint(state) {
|
|
4874
|
-
const failed = Object.keys(state.providerErrors ?? {});
|
|
4875
|
-
if (failed.length === 0) return void 0;
|
|
4876
|
-
const names = failed.map((p) => (0, import_core31.getProviderMeta)(p)?.label ?? p);
|
|
4877
|
-
return `\u26A0 Unavailable (key or fetch failed): ${names.join(", ")}. Showing working providers only.`;
|
|
4878
|
-
}
|
|
4879
4866
|
function plannerModelItems(state, provider, selectedId) {
|
|
4880
4867
|
const runner = (0, import_core31.runnerForProvider)(provider);
|
|
4881
4868
|
if (!runner) {
|
|
4882
|
-
|
|
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
|
+
];
|
|
4883
4880
|
}
|
|
4884
4881
|
const items = state.models.filter((m) => m.runners?.includes(runner)).map((m) => ({
|
|
4885
4882
|
id: m.id,
|
|
@@ -4902,7 +4899,7 @@ function plannerEffortItems(state, provider, modelId, selectedEffort) {
|
|
|
4902
4899
|
}
|
|
4903
4900
|
const model = plannerHarnessModel(state, provider, modelId);
|
|
4904
4901
|
if (!model) {
|
|
4905
|
-
return [{ id: "", label: "No planner model selected", detail: "pick one with /
|
|
4902
|
+
return [{ id: "", label: "No planner model selected", detail: "pick one with /planner", disabled: true }];
|
|
4906
4903
|
}
|
|
4907
4904
|
const variants = model.variants ?? [];
|
|
4908
4905
|
if (variants.length === 0) {
|
|
@@ -4914,12 +4911,6 @@ function plannerEffortItems(state, provider, modelId, selectedEffort) {
|
|
|
4914
4911
|
];
|
|
4915
4912
|
}
|
|
4916
4913
|
function pickerItemsFor(state, action) {
|
|
4917
|
-
if (action.kind === "set-model") {
|
|
4918
|
-
return plannerModelItems(state, state.plannerProvider, state.orchestratorModel);
|
|
4919
|
-
}
|
|
4920
|
-
if (action.kind === "set-planner-effort") {
|
|
4921
|
-
return plannerEffortItems(state, state.plannerProvider, state.orchestratorModel, state.plannerEffort);
|
|
4922
|
-
}
|
|
4923
4914
|
if (action.kind === "rewind") {
|
|
4924
4915
|
if (state.rewindTargets === null) return [];
|
|
4925
4916
|
if (state.rewindTargets.length === 0) {
|
|
@@ -5696,7 +5687,7 @@ function taskLines(state, planRow, index, cols) {
|
|
|
5696
5687
|
lines.push(...taskText("Forced", `Started before the work of ${row.forcedPastGate.join(", ")} was merged into your branch.`, cols, bodyPad));
|
|
5697
5688
|
}
|
|
5698
5689
|
if (row.autonomous) {
|
|
5699
|
-
lines.push(...taskText("Autonomy", "Runs without permission prompts (Full). Change the level with /
|
|
5690
|
+
lines.push(...taskText("Autonomy", "Runs without permission prompts (Full). Change the level with /settings.", cols, bodyPad));
|
|
5700
5691
|
}
|
|
5701
5692
|
const editableSeed = task.prompt ?? task.description ?? task.title;
|
|
5702
5693
|
if (task.description && task.description !== task.title && task.description !== editableSeed) {
|
|
@@ -6276,10 +6267,10 @@ function frame(title, body, rows, cols) {
|
|
|
6276
6267
|
}
|
|
6277
6268
|
|
|
6278
6269
|
// src/tui/reducer.ts
|
|
6279
|
-
var
|
|
6270
|
+
var import_core48 = require("@ordewell/core");
|
|
6280
6271
|
|
|
6281
6272
|
// src/tui/reducers/overlays.ts
|
|
6282
|
-
var
|
|
6273
|
+
var import_core47 = require("@ordewell/core");
|
|
6283
6274
|
|
|
6284
6275
|
// src/tui/reducers/approvals.ts
|
|
6285
6276
|
var import_core37 = require("@ordewell/core");
|
|
@@ -6348,7 +6339,7 @@ function handleApprovalKey(state, overlay, key) {
|
|
|
6348
6339
|
}
|
|
6349
6340
|
|
|
6350
6341
|
// src/tui/reducers/commands.ts
|
|
6351
|
-
var
|
|
6342
|
+
var import_core46 = require("@ordewell/core");
|
|
6352
6343
|
|
|
6353
6344
|
// src/tui/reducers/plannerStepper.ts
|
|
6354
6345
|
var import_core38 = require("@ordewell/core");
|
|
@@ -7304,73 +7295,8 @@ function followSession(state, message) {
|
|
|
7304
7295
|
return message.type === "approval_settled" ? dropApproval(heard, message.id) : heard;
|
|
7305
7296
|
}
|
|
7306
7297
|
|
|
7307
|
-
// src/tui/reducers/runSettings.ts
|
|
7308
|
-
var import_core45 = require("@ordewell/core");
|
|
7309
|
-
function runSettingsEffect(state, changes) {
|
|
7310
|
-
return { type: "setRunSettings", changes, ...state.sessionId ? { sessionId: state.sessionId } : {} };
|
|
7311
|
-
}
|
|
7312
|
-
function supervisorCommand(state, args) {
|
|
7313
|
-
const [arg, value] = args;
|
|
7314
|
-
if (arg === void 0) {
|
|
7315
|
-
return step(say(state, "system", `${(0, import_core45.supervisorSummary)(state.runSettings)}: /supervisor off|watch|act, /supervisor retries <n>, /supervisor reads <n>.`));
|
|
7316
|
-
}
|
|
7317
|
-
if (arg === "retries") {
|
|
7318
|
-
const n = (0, import_core45.parseCount)(value, 0);
|
|
7319
|
-
return n === null ? fail3(state, "Usage: /supervisor retries <whole number, 0 or more>") : step(state, [runSettingsEffect(state, { supervisorRetryLimit: n })]);
|
|
7320
|
-
}
|
|
7321
|
-
if (arg === "reads") {
|
|
7322
|
-
const n = (0, import_core45.parseCount)(value, 1);
|
|
7323
|
-
return n === null ? fail3(state, "Usage: /supervisor reads <whole number, 1 or more>") : step(state, [runSettingsEffect(state, { wakeUpReadBudget: n })]);
|
|
7324
|
-
}
|
|
7325
|
-
if (arg === "act") return confirmSupervisorAct(state);
|
|
7326
|
-
if (arg === "off" || arg === "watch") return step(state, [runSettingsEffect(state, { supervisorLevel: arg })]);
|
|
7327
|
-
return fail3(state, "Usage: /supervisor [off|watch|act] \xB7 /supervisor retries <n> \xB7 /supervisor reads <n>");
|
|
7328
|
-
}
|
|
7329
|
-
function automergeCommand(state, arg) {
|
|
7330
|
-
if (arg === void 0) {
|
|
7331
|
-
return step(say(state, "system", `${(0, import_core45.automergeSummary)(state.runSettings)}: /automerge on|off.`));
|
|
7332
|
-
}
|
|
7333
|
-
const enabled = (0, import_core45.parseSwitch)(arg);
|
|
7334
|
-
if (enabled === null) return fail3(state, "Usage: /automerge [on|off]");
|
|
7335
|
-
return step(state, [runSettingsEffect(state, { mergeAtGatesAutomatically: enabled })]);
|
|
7336
|
-
}
|
|
7337
|
-
function autorunCommand(state, arg) {
|
|
7338
|
-
if (arg === void 0) {
|
|
7339
|
-
return step(say(state, "system", `${(0, import_core45.autorunSummary)(state.runSettings)}: /autorun on starts each plan the planner submits, without review.`));
|
|
7340
|
-
}
|
|
7341
|
-
const enabled = (0, import_core45.parseSwitch)(arg);
|
|
7342
|
-
if (enabled === null) return fail3(state, "Usage: /autorun [on|off]");
|
|
7343
|
-
if (enabled) return confirmAutorun(state);
|
|
7344
|
-
return step(state, [runSettingsEffect(state, { autorun: false })]);
|
|
7345
|
-
}
|
|
7346
|
-
function confirmSupervisorAct(state) {
|
|
7347
|
-
return step({
|
|
7348
|
-
...state,
|
|
7349
|
-
overlay: {
|
|
7350
|
-
kind: "confirm",
|
|
7351
|
-
title: "Let the supervisor act?",
|
|
7352
|
-
message: "At Act the supervisor runs, stops and retries tasks, answers their requests (never allowing), edits the plan and merges, without asking you.",
|
|
7353
|
-
note: `${import_core45.ACT_RISK}
|
|
7354
|
-
It applies to this session's run now, and to every later run.`,
|
|
7355
|
-
action: { kind: "supervisor-act" }
|
|
7356
|
-
}
|
|
7357
|
-
});
|
|
7358
|
-
}
|
|
7359
|
-
function confirmAutorun(state) {
|
|
7360
|
-
return step({
|
|
7361
|
-
...state,
|
|
7362
|
-
overlay: {
|
|
7363
|
-
kind: "confirm",
|
|
7364
|
-
title: "Start plans without review?",
|
|
7365
|
-
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.",
|
|
7366
|
-
note: import_core45.AUTORUN_RISK,
|
|
7367
|
-
action: { kind: "autorun-on" }
|
|
7368
|
-
}
|
|
7369
|
-
});
|
|
7370
|
-
}
|
|
7371
|
-
|
|
7372
7298
|
// src/tui/reducers/settings.ts
|
|
7373
|
-
var
|
|
7299
|
+
var import_core45 = require("@ordewell/core");
|
|
7374
7300
|
var SUPERVISOR_DETAIL = {
|
|
7375
7301
|
off: "The planner speaks only when you write",
|
|
7376
7302
|
watch: "The planner follows your runs and suggests what to do",
|
|
@@ -7395,7 +7321,7 @@ var SETTINGS = {
|
|
|
7395
7321
|
{
|
|
7396
7322
|
id: "guarded",
|
|
7397
7323
|
label: "Guarded",
|
|
7398
|
-
detail: [`New plans run tasks in each runner's safer mode`, (0,
|
|
7324
|
+
detail: [`New plans run tasks in each runner's safer mode`, (0, import_core45.codexSandboxNotice)(state.modesByRunner)?.line].filter(Boolean).join(" \xB7 "),
|
|
7399
7325
|
selected: !state.autonomous
|
|
7400
7326
|
}
|
|
7401
7327
|
]
|
|
@@ -7405,7 +7331,7 @@ var SETTINGS = {
|
|
|
7405
7331
|
label: "Supervisor",
|
|
7406
7332
|
items: (state) => ["off", "watch", "act"].map((level) => ({
|
|
7407
7333
|
id: level,
|
|
7408
|
-
label:
|
|
7334
|
+
label: import_core45.SUPERVISOR_LEVEL_LABEL[level],
|
|
7409
7335
|
detail: SUPERVISOR_DETAIL[level],
|
|
7410
7336
|
selected: state.runSettings.supervisorLevel === level
|
|
7411
7337
|
}))
|
|
@@ -7459,12 +7385,12 @@ function saveChoices(state, choices) {
|
|
|
7459
7385
|
const autonomous = choices.autonomy === "full";
|
|
7460
7386
|
if (autonomous !== state.autonomous) {
|
|
7461
7387
|
save2.autonomous = autonomous;
|
|
7462
|
-
changed.push(`Autonomy ${(0,
|
|
7388
|
+
changed.push(`Autonomy ${(0, import_core45.autonomyLevelLabel)(autonomous)}`);
|
|
7463
7389
|
}
|
|
7464
7390
|
const level = choices.supervisor;
|
|
7465
7391
|
if (level !== state.runSettings.supervisorLevel) {
|
|
7466
7392
|
run.supervisorLevel = level;
|
|
7467
|
-
changed.push(`Supervisor ${
|
|
7393
|
+
changed.push(`Supervisor ${import_core45.SUPERVISOR_LEVEL_LABEL[level]}`);
|
|
7468
7394
|
}
|
|
7469
7395
|
if (choices.retries !== void 0 && Number(choices.retries) !== state.runSettings.supervisorRetryLimit) {
|
|
7470
7396
|
run.supervisorRetryLimit = Number(choices.retries);
|
|
@@ -7491,7 +7417,7 @@ function saveChoices(state, choices) {
|
|
|
7491
7417
|
}
|
|
7492
7418
|
if (changed.length === 0) return step(state);
|
|
7493
7419
|
const effect = { ...save2, message: `Settings: ${changed.join(" \xB7 ")}` };
|
|
7494
|
-
const risks = [...run.supervisorLevel === "act" ? [
|
|
7420
|
+
const risks = [...run.supervisorLevel === "act" ? [import_core45.ACT_RISK] : [], ...run.autorun ? [import_core45.AUTORUN_RISK] : []];
|
|
7495
7421
|
if (risks.length === 0) return saveSettings(state, effect);
|
|
7496
7422
|
return step({
|
|
7497
7423
|
...state,
|
|
@@ -7542,28 +7468,14 @@ function runCommand(state, { name, args }) {
|
|
|
7542
7468
|
state,
|
|
7543
7469
|
(sessionId) => plannerInFlight(state) ? stopPlanning(state, sessionId) : step(state, [{ type: "stopExecution", sessionId }])
|
|
7544
7470
|
);
|
|
7545
|
-
case "model":
|
|
7546
|
-
return setModel(state, args);
|
|
7547
7471
|
case "planner":
|
|
7548
7472
|
return setPlanner(state, args);
|
|
7549
|
-
case "planner-effort":
|
|
7550
|
-
return setPlannerEffort(state, args);
|
|
7551
7473
|
case "key":
|
|
7552
7474
|
return setKey(state, args);
|
|
7553
7475
|
case "allowlist":
|
|
7554
7476
|
return allowlist(state, args);
|
|
7555
7477
|
case "runners":
|
|
7556
7478
|
return runners(state, args);
|
|
7557
|
-
case "auto":
|
|
7558
|
-
return setAutonomous(state, args[0]);
|
|
7559
|
-
case "supervisor":
|
|
7560
|
-
return supervisorCommand(state, args);
|
|
7561
|
-
case "automerge":
|
|
7562
|
-
return automergeCommand(state, args[0]);
|
|
7563
|
-
case "autorun":
|
|
7564
|
-
return autorunCommand(state, args[0]);
|
|
7565
|
-
case "parallel":
|
|
7566
|
-
return setMaxParallel(state, args[0]);
|
|
7567
7479
|
case "settings":
|
|
7568
7480
|
return openSettings(state);
|
|
7569
7481
|
case "mouse":
|
|
@@ -7684,8 +7596,8 @@ function newSession(state) {
|
|
|
7684
7596
|
goal: "",
|
|
7685
7597
|
taskView: null,
|
|
7686
7598
|
planApproved: false,
|
|
7687
|
-
conversation:
|
|
7688
|
-
turnGate:
|
|
7599
|
+
conversation: import_core46.EMPTY_CONVERSATION,
|
|
7600
|
+
turnGate: import_core46.NO_TURN,
|
|
7689
7601
|
selectedTask: 0,
|
|
7690
7602
|
expandedTaskId: null,
|
|
7691
7603
|
taskEditor: null,
|
|
@@ -7696,40 +7608,16 @@ function newSession(state) {
|
|
|
7696
7608
|
// Prompts belong to the session that raised them; the old planner is gone
|
|
7697
7609
|
// and its pending requests deny on their own timeout.
|
|
7698
7610
|
pendingApprovals: [],
|
|
7699
|
-
queuedPrompts:
|
|
7611
|
+
queuedPrompts: import_core46.EMPTY_HOLD,
|
|
7700
7612
|
stopArmed: false,
|
|
7701
7613
|
forceSendPending: null,
|
|
7702
7614
|
overlay: state.overlay?.kind === "approval" ? null : state.overlay
|
|
7703
|
-
},
|
|
7704
|
-
}
|
|
7705
|
-
function setModel(state, args) {
|
|
7706
|
-
if (args[0] === "set" && args[1]) {
|
|
7707
|
-
const runner = (0, import_core47.runnerForProvider)(state.plannerProvider);
|
|
7708
|
-
const known = runner ? modelsForRunner(state.models, runner) : [];
|
|
7709
|
-
if (runner && known.length > 0 && !known.some((m) => m.id === args[1])) {
|
|
7710
|
-
return fail3(state, `${args[1]} was not discovered for ${runner}.`);
|
|
7711
|
-
}
|
|
7712
|
-
const refusal = known.length === 0 ? vendorModelRefusal(state.plannerProvider, args[1], import_core47.TERMINAL_UI_COMMANDS.pickPlanner) : null;
|
|
7713
|
-
if (refusal) return fail3(state, refusal);
|
|
7714
|
-
return step(state, [{ type: "setModel", modelId: args[1] }]);
|
|
7715
|
-
}
|
|
7716
|
-
if (args.length > 0 && args[0] !== "set") return fail3(state, "Usage: /model [set <model-id>]");
|
|
7717
|
-
const items = pickerItemsFor(state, { kind: "set-model" });
|
|
7718
|
-
return step(
|
|
7719
|
-
{
|
|
7720
|
-
...state,
|
|
7721
|
-
overlay: {
|
|
7722
|
-
kind: "picker",
|
|
7723
|
-
picker: picker("Planner model", items, { kind: "set-model" }, { hint: providerErrorHint(state), filterable: true })
|
|
7724
|
-
}
|
|
7725
|
-
},
|
|
7726
|
-
[{ type: "loadModels" }]
|
|
7727
|
-
);
|
|
7615
|
+
}, import_core46.EMPTY_RUN), closeEffects);
|
|
7728
7616
|
}
|
|
7729
7617
|
function setPlanner(state, args) {
|
|
7730
7618
|
if (args[0]) {
|
|
7731
7619
|
const id = args[0].toLowerCase();
|
|
7732
|
-
if (!(0,
|
|
7620
|
+
if (!(0, import_core46.isPlannerBackend)(id)) {
|
|
7733
7621
|
return fail3(state, `Unknown planner: ${id}. Run /planner with no arguments to see the list.`);
|
|
7734
7622
|
}
|
|
7735
7623
|
return step(state, [{ type: "setPlanner", provider: id }]);
|
|
@@ -7737,31 +7625,10 @@ function setPlanner(state, args) {
|
|
|
7737
7625
|
const opened = openStepper(state, plannerStepper);
|
|
7738
7626
|
return { ...opened, effects: [...opened.effects, { type: "loadModels" }] };
|
|
7739
7627
|
}
|
|
7740
|
-
function setPlannerEffort(state, args) {
|
|
7741
|
-
const items = plannerEffortItems(state, state.plannerProvider, state.orchestratorModel, state.plannerEffort);
|
|
7742
|
-
if (args[0]) {
|
|
7743
|
-
const wanted = args[0].toLowerCase();
|
|
7744
|
-
const match = items.find((i) => !i.disabled && (i.id === wanted || wanted === "default" && i.id === DEFAULT_EFFORT));
|
|
7745
|
-
if (!match) {
|
|
7746
|
-
const available = items.filter((i) => !i.disabled && i.id !== DEFAULT_EFFORT).map((i) => i.id);
|
|
7747
|
-
return fail3(state, available.length > 0 ? `Unknown effort: ${args[0]}. Available: ${available.join(", ")}, default.` : items[0]?.label ?? "No effort levels available.");
|
|
7748
|
-
}
|
|
7749
|
-
return step(state, [{ type: "setPlannerEffort", effort: match.id === DEFAULT_EFFORT ? "" : match.id }]);
|
|
7750
|
-
}
|
|
7751
|
-
return step({
|
|
7752
|
-
...state,
|
|
7753
|
-
overlay: {
|
|
7754
|
-
kind: "picker",
|
|
7755
|
-
picker: picker("Planner thinking effort", items, { kind: "set-planner-effort" }, {
|
|
7756
|
-
hint: "How hard the planning agent thinks per turn. Higher costs latency and tokens against your subscription."
|
|
7757
|
-
})
|
|
7758
|
-
}
|
|
7759
|
-
});
|
|
7760
|
-
}
|
|
7761
7628
|
function setKey(state, args) {
|
|
7762
7629
|
if (args[0] === "set" && args[1]) {
|
|
7763
7630
|
const provider = args[1].toLowerCase();
|
|
7764
|
-
if (!(0,
|
|
7631
|
+
if (!(0, import_core46.isApiProvider)(provider)) {
|
|
7765
7632
|
return fail3(state, `Unknown provider: ${provider}. Run /key with no arguments to see the list.`);
|
|
7766
7633
|
}
|
|
7767
7634
|
if (!args[2]) {
|
|
@@ -7772,16 +7639,16 @@ function setKey(state, args) {
|
|
|
7772
7639
|
}
|
|
7773
7640
|
return step(state, [{ type: "setApiKey", provider, key: args.slice(2).join(" ") }]);
|
|
7774
7641
|
}
|
|
7775
|
-
const items =
|
|
7642
|
+
const items = import_core46.PROVIDER_PRIORITY.map((id) => ({
|
|
7776
7643
|
id,
|
|
7777
|
-
label: (0,
|
|
7778
|
-
detail: (0,
|
|
7644
|
+
label: (0, import_core46.getProviderMeta)(id).label,
|
|
7645
|
+
detail: (0, import_core46.getProviderMeta)(id).apiKeyEnvVar,
|
|
7779
7646
|
selected: state.configuredProviders.includes(id)
|
|
7780
7647
|
}));
|
|
7781
7648
|
return step({ ...state, overlay: { kind: "picker", picker: picker("API provider key", items, { kind: "set-key" }) } });
|
|
7782
7649
|
}
|
|
7783
7650
|
function keyPrompt(provider) {
|
|
7784
|
-
const meta = (0,
|
|
7651
|
+
const meta = (0, import_core46.getProviderMeta)(provider);
|
|
7785
7652
|
return {
|
|
7786
7653
|
kind: "prompt",
|
|
7787
7654
|
title: `${meta.label} API key`,
|
|
@@ -7856,18 +7723,6 @@ function runners(state, args) {
|
|
|
7856
7723
|
})
|
|
7857
7724
|
} }, [{ type: "loadRunners" }]);
|
|
7858
7725
|
}
|
|
7859
|
-
function setMaxParallel(state, arg) {
|
|
7860
|
-
if (!arg) return step(say(state, "system", `Up to ${state.maxParallel} AI task${state.maxParallel === 1 ? "" : "s"} run at once: /parallel <n> changes it.`));
|
|
7861
|
-
const limit = (0, import_core47.parseMaxParallel)(arg);
|
|
7862
|
-
if (limit === null) return fail3(state, "Usage: /parallel [<number of tasks, 1 or more>]");
|
|
7863
|
-
return step({ ...state, maxParallel: limit }, [{ type: "setMaxParallel", limit }]);
|
|
7864
|
-
}
|
|
7865
|
-
function setAutonomous(state, arg) {
|
|
7866
|
-
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.`));
|
|
7867
|
-
const enabled = (0, import_core47.parseAutonomyLevel)(arg);
|
|
7868
|
-
if (enabled === null) return fail3(state, "Usage: /auto [full|guarded]");
|
|
7869
|
-
return step({ ...state, autonomous: enabled }, [{ type: "setAutonomous", enabled }]);
|
|
7870
|
-
}
|
|
7871
7726
|
function setMouseCapture(state, arg) {
|
|
7872
7727
|
const enabled = resolveToggle(arg, state.mouseCapture);
|
|
7873
7728
|
if (enabled === null) return fail3(state, "Usage: /mouse [on|off]");
|
|
@@ -7958,8 +7813,6 @@ function runConfirm(state, overlay) {
|
|
|
7958
7813
|
if (!state.sessionId) return step(closed);
|
|
7959
7814
|
return step(closed, [taskActionEffect(closed, state.sessionId, overlay.action.taskId, "force-start")]);
|
|
7960
7815
|
}
|
|
7961
|
-
if (overlay.action.kind === "supervisor-act") return step(closed, [runSettingsEffect(closed, { supervisorLevel: "act" })]);
|
|
7962
|
-
if (overlay.action.kind === "autorun-on") return step(closed, [runSettingsEffect(closed, { autorun: true })]);
|
|
7963
7816
|
if (overlay.action.kind === "save-settings") return answerSaveSettings(state, overlay.action, true);
|
|
7964
7817
|
if (overlay.action.kind === "merge-run" || overlay.action.kind === "discard-run") {
|
|
7965
7818
|
return confirmedHandoff(state, overlay.action.kind);
|
|
@@ -8062,10 +7915,6 @@ function choose2(state, picker2, item) {
|
|
|
8062
7915
|
return step(say(state, "error", item.detail ? `${item.label}: ${item.detail}` : `${item.label} is not available.`));
|
|
8063
7916
|
}
|
|
8064
7917
|
switch (picker2.action.kind) {
|
|
8065
|
-
case "set-model":
|
|
8066
|
-
return step(closed, [{ type: "setModel", modelId: item.id }]);
|
|
8067
|
-
case "set-planner-effort":
|
|
8068
|
-
return step(closed, [{ type: "setPlannerEffort", effort: item.id === DEFAULT_EFFORT ? "" : item.id }]);
|
|
8069
7918
|
case "load-session":
|
|
8070
7919
|
return step(closed, [{ type: "loadSession", sessionId: item.id }]);
|
|
8071
7920
|
case "rewind":
|
|
@@ -8073,7 +7922,7 @@ function choose2(state, picker2, item) {
|
|
|
8073
7922
|
case "delete-session":
|
|
8074
7923
|
return step(closed, [{ type: "deleteSession", sessionId: item.id }]);
|
|
8075
7924
|
case "set-key":
|
|
8076
|
-
return (0,
|
|
7925
|
+
return (0, import_core47.isApiProvider)(item.id) ? step({ ...state, overlay: keyPrompt(item.id) }) : step(closed);
|
|
8077
7926
|
case "choose-allowlist-runner": {
|
|
8078
7927
|
const action = { kind: "set-allowlist", runner: item.id };
|
|
8079
7928
|
const items = pickerItemsFor(state, action);
|
|
@@ -8149,7 +7998,7 @@ function reduceAction(state, action) {
|
|
|
8149
7998
|
// (`task-1`), so nothing of the last one's — a merge gate, a checkpoint, its
|
|
8150
7999
|
// tasks — may carry over into this.
|
|
8151
8000
|
case "sessionStarted":
|
|
8152
|
-
return step(withRun({ ...state, sessionId: action.sessionId, goal: action.goal, taskView: null },
|
|
8001
|
+
return step(withRun({ ...state, sessionId: action.sessionId, goal: action.goal, taskView: null }, import_core48.EMPTY_RUN));
|
|
8153
8002
|
// A loaded session is a different one: the turn the old one had out, the
|
|
8154
8003
|
// prompts held behind it and a stop armed against it are not this one's.
|
|
8155
8004
|
// (`sessionStarted` cannot reset them: `startConversation` dispatches it
|
|
@@ -8161,13 +8010,13 @@ function reduceAction(state, action) {
|
|
|
8161
8010
|
goal: action.goal,
|
|
8162
8011
|
taskView: null,
|
|
8163
8012
|
planner: "idle",
|
|
8164
|
-
turnGate:
|
|
8013
|
+
turnGate: import_core48.NO_TURN,
|
|
8165
8014
|
pendingApprovals: [],
|
|
8166
|
-
queuedPrompts:
|
|
8015
|
+
queuedPrompts: import_core48.EMPTY_HOLD,
|
|
8167
8016
|
stopArmed: false,
|
|
8168
8017
|
forceSendPending: null,
|
|
8169
8018
|
overlay: state.overlay?.kind === "approval" ? null : state.overlay
|
|
8170
|
-
},
|
|
8019
|
+
}, import_core48.EMPTY_RUN));
|
|
8171
8020
|
// The daemon registers a session only once planning succeeds; when it does
|
|
8172
8021
|
// not, holding on to the id would send every next message to a session the
|
|
8173
8022
|
// server never had.
|
|
@@ -8177,20 +8026,20 @@ function reduceAction(state, action) {
|
|
|
8177
8026
|
sessionId: null,
|
|
8178
8027
|
goal: "",
|
|
8179
8028
|
taskView: null,
|
|
8180
|
-
turnGate:
|
|
8029
|
+
turnGate: import_core48.NO_TURN,
|
|
8181
8030
|
pendingApprovals: [],
|
|
8182
|
-
queuedPrompts:
|
|
8031
|
+
queuedPrompts: import_core48.EMPTY_HOLD,
|
|
8183
8032
|
stopArmed: false,
|
|
8184
8033
|
forceSendPending: null,
|
|
8185
8034
|
overlay: state.overlay?.kind === "approval" ? null : state.overlay
|
|
8186
|
-
},
|
|
8035
|
+
}, import_core48.EMPTY_RUN));
|
|
8187
8036
|
// Deleting the session on screen stops it in the daemon; a view left on it
|
|
8188
8037
|
// would answer every next message with a session-not-found.
|
|
8189
8038
|
case "sessionDeleted":
|
|
8190
8039
|
return action.sessionId === state.sessionId ? newSession(state) : step(state);
|
|
8191
8040
|
case "chatRestored":
|
|
8192
8041
|
if (stale(state, action.sessionId)) return step(state);
|
|
8193
|
-
return step({ ...state, conversation: (0,
|
|
8042
|
+
return step({ ...state, conversation: (0, import_core48.fromTranscript)(action.history, action.researchLog, action.plannerUsage, action.pendingTurns), scroll: 0 });
|
|
8194
8043
|
case "planRefreshed":
|
|
8195
8044
|
if (stale(state, action.sessionId)) return step(state);
|
|
8196
8045
|
return step(showPlan(state, action.plan));
|
|
@@ -8243,9 +8092,9 @@ function reduceAction(state, action) {
|
|
|
8243
8092
|
taskId: action.taskId,
|
|
8244
8093
|
order: action.order ?? 0,
|
|
8245
8094
|
title: action.title,
|
|
8246
|
-
runner: action.runner ??
|
|
8095
|
+
runner: action.runner ?? import_core48.DEFAULT_RUNNERS[0]
|
|
8247
8096
|
});
|
|
8248
|
-
const spoken = say(folded, "system", (0,
|
|
8097
|
+
const spoken = say(folded, "system", (0, import_core48.taskStartedNotice)(action.title, action.runner));
|
|
8249
8098
|
return step({ ...spoken, status: "executing" });
|
|
8250
8099
|
}
|
|
8251
8100
|
case "taskCheckpoint":
|
|
@@ -8297,7 +8146,7 @@ function reduceAction(state, action) {
|
|
|
8297
8146
|
completed: state.tasks.filter((t) => t.status === "completed").length,
|
|
8298
8147
|
total: state.tasks.length,
|
|
8299
8148
|
failed: state.tasks.filter((t) => t.status === "failed").length,
|
|
8300
|
-
blocked: (0,
|
|
8149
|
+
blocked: (0, import_core48.blockingFailures)(state.tasks).size,
|
|
8301
8150
|
skipped: state.tasks.filter((t) => t.status === "skipped").length
|
|
8302
8151
|
};
|
|
8303
8152
|
const failures = `${failed > 0 ? ` \xB7 ${failed} failed` : ""}${blocked ? ` \xB7 ${blocked} blocked` : ""}${skipped ? ` \xB7 ${skipped} skipped` : ""}`;
|
|
@@ -8340,7 +8189,7 @@ function reduceAction(state, action) {
|
|
|
8340
8189
|
providerErrors: action.providerErrors ?? state.providerErrors,
|
|
8341
8190
|
modesByRunner: action.modesByRunner ?? state.modesByRunner
|
|
8342
8191
|
},
|
|
8343
|
-
["set-
|
|
8192
|
+
["set-task-model", "set-task-effort", "set-task-mode"]
|
|
8344
8193
|
)
|
|
8345
8194
|
));
|
|
8346
8195
|
case "sessionsLoaded":
|
|
@@ -8360,14 +8209,14 @@ function reduceAction(state, action) {
|
|
|
8360
8209
|
taskView: null,
|
|
8361
8210
|
status: "idle",
|
|
8362
8211
|
planner: "idle",
|
|
8363
|
-
turnGate:
|
|
8212
|
+
turnGate: import_core48.NO_TURN,
|
|
8364
8213
|
planApproved: false,
|
|
8365
8214
|
pendingApprovals: [],
|
|
8366
|
-
queuedPrompts:
|
|
8215
|
+
queuedPrompts: import_core48.EMPTY_HOLD,
|
|
8367
8216
|
stopArmed: false,
|
|
8368
8217
|
forceSendPending: null,
|
|
8369
8218
|
overlay: state.overlay?.kind === "approval" ? null : state.overlay
|
|
8370
|
-
},
|
|
8219
|
+
}, import_core48.EMPTY_RUN));
|
|
8371
8220
|
// The rewound message comes back as a draft to edit and resend, so it lands
|
|
8372
8221
|
// as if just typed: history is not being browsed, and nothing is parked.
|
|
8373
8222
|
case "inputPrefilled":
|
|
@@ -8543,7 +8392,7 @@ function submit(state) {
|
|
|
8543
8392
|
const builtIn = builtInCommand(text);
|
|
8544
8393
|
if (builtIn) return runCommand(cleared, builtIn);
|
|
8545
8394
|
if (plannerInFlight(state)) {
|
|
8546
|
-
return step({ ...cleared, queuedPrompts: (0,
|
|
8395
|
+
return step({ ...cleared, queuedPrompts: (0, import_core48.holdPrompt)(state.queuedPrompts, text) });
|
|
8547
8396
|
}
|
|
8548
8397
|
const spoken = say(cleared, "user", text);
|
|
8549
8398
|
const effect = state.sessionId ? { type: "sendMessage", sessionId: state.sessionId, message: text } : { type: "startConversation", goal: text };
|
|
@@ -8618,7 +8467,7 @@ function createApp(deps) {
|
|
|
8618
8467
|
|
|
8619
8468
|
// src/tui/effects.ts
|
|
8620
8469
|
var import_child_process3 = require("child_process");
|
|
8621
|
-
var
|
|
8470
|
+
var import_core49 = require("@ordewell/core");
|
|
8622
8471
|
|
|
8623
8472
|
// src/tui/inbound.ts
|
|
8624
8473
|
var CONVERSATION_TYPES = /* @__PURE__ */ new Set([
|
|
@@ -9046,9 +8895,9 @@ function plannerModelNotice(recall2) {
|
|
|
9046
8895
|
case "remembered":
|
|
9047
8896
|
return `Restored ${recall2.model}.`;
|
|
9048
8897
|
case "catalog-default":
|
|
9049
|
-
return `Using its default model, ${recall2.model}. Pick another with /
|
|
8898
|
+
return `Using its default model, ${recall2.model}. Pick another with /planner.`;
|
|
9050
8899
|
case "none":
|
|
9051
|
-
return "Pick a model with /
|
|
8900
|
+
return "Pick a model with /planner.";
|
|
9052
8901
|
}
|
|
9053
8902
|
}
|
|
9054
8903
|
async function perform(effect, deps) {
|
|
@@ -9108,24 +8957,18 @@ async function perform(effect, deps) {
|
|
|
9108
8957
|
await refreshPlan(deps, sessionId);
|
|
9109
8958
|
return;
|
|
9110
8959
|
}
|
|
9111
|
-
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,
|
|
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);
|
|
9112
8961
|
await (effect.watch ? withExecutionStream(deps, sessionId, request) : request());
|
|
9113
8962
|
await refreshPlan(deps, sessionId);
|
|
9114
8963
|
return;
|
|
9115
8964
|
}
|
|
9116
8965
|
case "addTask": {
|
|
9117
|
-
const fields = (0,
|
|
8966
|
+
const fields = (0, import_core49.newTaskFields)(effect.title);
|
|
9118
8967
|
if (!fields) return;
|
|
9119
8968
|
await api.addTask(effect.sessionId, { ...fields });
|
|
9120
8969
|
await refreshPlan(deps, effect.sessionId);
|
|
9121
8970
|
return;
|
|
9122
8971
|
}
|
|
9123
|
-
case "setRunSettings": {
|
|
9124
|
-
const settings = await api.updateRunSettings(effect.changes, effect.sessionId);
|
|
9125
|
-
dispatch({ type: "settingsLoaded", settings });
|
|
9126
|
-
if (effect.sessionId) await refreshPlan(deps, effect.sessionId);
|
|
9127
|
-
return;
|
|
9128
|
-
}
|
|
9129
8972
|
case "updateTask":
|
|
9130
8973
|
await api.updateTask(effect.sessionId, effect.taskId, effect.changes);
|
|
9131
8974
|
await refreshPlan(deps, effect.sessionId);
|
|
@@ -9209,20 +9052,12 @@ async function perform(effect, deps) {
|
|
|
9209
9052
|
case "interruptTask":
|
|
9210
9053
|
await api.interruptTask(effect.sessionId, effect.taskId);
|
|
9211
9054
|
return;
|
|
9212
|
-
case "setModel": {
|
|
9213
|
-
const settled = await api.updateSettings({ orchestratorModel: effect.modelId });
|
|
9214
|
-
const plannerThinkingEffort = typeof settled.plannerThinkingEffort === "string" ? settled.plannerThinkingEffort : "";
|
|
9215
|
-
persistAfterDaemon(deps, { ORCHESTRATOR_MODEL: effect.modelId, ORDEWELL_PLANNER_EFFORT: plannerThinkingEffort });
|
|
9216
|
-
dispatch({ type: "settingsLoaded", settings: { orchestratorModel: effect.modelId, plannerThinkingEffort } });
|
|
9217
|
-
dispatch({ type: "notice", message: `Planner model set to ${effect.modelId}.` });
|
|
9218
|
-
return;
|
|
9219
|
-
}
|
|
9220
9055
|
case "setPlanner": {
|
|
9221
|
-
const meta = (0,
|
|
9056
|
+
const meta = (0, import_core49.getProviderMeta)(effect.provider);
|
|
9222
9057
|
if (!meta) throw new Error(`Unknown planner: ${effect.provider}`);
|
|
9223
|
-
if ((0,
|
|
9058
|
+
if ((0, import_core49.isCliProvider)(effect.provider)) {
|
|
9224
9059
|
const installed = ((await api.getRunners()).runners ?? []).map((r) => r.id);
|
|
9225
|
-
const refusal = uninstalledPlannerRefusal(effect.provider, installed,
|
|
9060
|
+
const refusal = uninstalledPlannerRefusal(effect.provider, installed, import_core49.TERMINAL_UI_COMMANDS.pickPlanner);
|
|
9226
9061
|
if (refusal) throw new Error(refusal);
|
|
9227
9062
|
}
|
|
9228
9063
|
const env = { AI_PROVIDER: effect.provider };
|
|
@@ -9235,7 +9070,7 @@ async function perform(effect, deps) {
|
|
|
9235
9070
|
});
|
|
9236
9071
|
dispatch({
|
|
9237
9072
|
type: "notice",
|
|
9238
|
-
message: `${(0,
|
|
9073
|
+
message: `${(0, import_core49.isCliProvider)(effect.provider) ? `Planning with ${meta.label}: no API key needed.` : `Planner set to ${meta.label}.`} ${plannerModelNotice(recall2)}`
|
|
9239
9074
|
});
|
|
9240
9075
|
await loadModels(deps);
|
|
9241
9076
|
return;
|
|
@@ -9256,14 +9091,8 @@ async function perform(effect, deps) {
|
|
|
9256
9091
|
dispatch({ type: "notice", message: effect.notice });
|
|
9257
9092
|
return;
|
|
9258
9093
|
}
|
|
9259
|
-
case "setPlannerEffort":
|
|
9260
|
-
await api.updateSettings({ env: { ORDEWELL_PLANNER_EFFORT: effect.effort } });
|
|
9261
|
-
deps.setEnvVar("ORDEWELL_PLANNER_EFFORT", effect.effort);
|
|
9262
|
-
dispatch({ type: "settingsLoaded", settings: { plannerThinkingEffort: effect.effort } });
|
|
9263
|
-
dispatch({ type: "notice", message: `Planner effort set to ${effect.effort || "the runner default"}.` });
|
|
9264
|
-
return;
|
|
9265
9094
|
case "setApiKey": {
|
|
9266
|
-
const meta = (0,
|
|
9095
|
+
const meta = (0, import_core49.isApiProvider)(effect.provider) ? (0, import_core49.getProviderMeta)(effect.provider) : void 0;
|
|
9267
9096
|
if (!meta) throw new Error(`Unknown provider: ${effect.provider}`);
|
|
9268
9097
|
await api.updateSettings({ env: { [meta.apiKeyEnvVar]: effect.key } });
|
|
9269
9098
|
deps.setEnvVar(meta.apiKeyEnvVar, effect.key);
|
|
@@ -9294,10 +9123,6 @@ async function perform(effect, deps) {
|
|
|
9294
9123
|
dispatch({ type: "notice", message: effect.message });
|
|
9295
9124
|
return;
|
|
9296
9125
|
}
|
|
9297
|
-
case "setMaxParallel":
|
|
9298
|
-
await saveMaxParallel(deps, effect.limit);
|
|
9299
|
-
dispatch({ type: "notice", message: `Up to ${effect.limit} AI task${effect.limit === 1 ? "" : "s"} now run at once.` });
|
|
9300
|
-
return;
|
|
9301
9126
|
case "saveSettings": {
|
|
9302
9127
|
if (Object.keys(effect.run).length > 0) {
|
|
9303
9128
|
const settings = await api.updateRunSettings(effect.run, effect.sessionId);
|
|
@@ -9309,12 +9134,6 @@ async function perform(effect, deps) {
|
|
|
9309
9134
|
dispatch({ type: "notice", message: overridden ? `${effect.message}: ORDEWELL_AUTONOMOUS_MODE in the environment decides the autonomy level until it is unset.` : effect.message });
|
|
9310
9135
|
return;
|
|
9311
9136
|
}
|
|
9312
|
-
case "setAutonomous": {
|
|
9313
|
-
const { overridden } = deps.saveAutonomy(effect.enabled);
|
|
9314
|
-
const level = (0, import_core50.autonomyLevelLabel)(effect.enabled);
|
|
9315
|
-
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.` });
|
|
9316
|
-
return;
|
|
9317
|
-
}
|
|
9318
9137
|
case "setMouseCapture":
|
|
9319
9138
|
deps.setMouseCapture(effect.enabled);
|
|
9320
9139
|
deps.setEnvVar("ORDEWELL_TUI_MOUSE", String(effect.enabled));
|
|
@@ -9487,7 +9306,7 @@ async function saveMaxParallel(deps, limit) {
|
|
|
9487
9306
|
function copySelection(deps, text) {
|
|
9488
9307
|
if (!text) return;
|
|
9489
9308
|
const lines = text.split("\n").length;
|
|
9490
|
-
const command = (0,
|
|
9309
|
+
const command = (0, import_core49.clipboardCopyCommand)(deps.hasBin);
|
|
9491
9310
|
if (command) {
|
|
9492
9311
|
try {
|
|
9493
9312
|
(deps.pipeToClipboard ?? pipeToClipboardDefault)(command, text);
|
|
@@ -9592,7 +9411,7 @@ function turnReplies(plan) {
|
|
|
9592
9411
|
const replies = [];
|
|
9593
9412
|
for (let i = history.length - 1; i >= 0; i--) {
|
|
9594
9413
|
const entry = history[i];
|
|
9595
|
-
if ((0,
|
|
9414
|
+
if ((0, import_core49.isUserMessage)(entry)) break;
|
|
9596
9415
|
if (entry.role === "assistant" && entry.kind === void 0) {
|
|
9597
9416
|
const { content, timestamp, runs } = entry;
|
|
9598
9417
|
replies.unshift({ content, ...timestamp ? { timestamp } : {}, ...runs ? { runs } : {} });
|
|
@@ -9948,7 +9767,7 @@ async function handleTui(subArgs) {
|
|
|
9948
9767
|
}
|
|
9949
9768
|
const workspace = flag(subArgs, "--workspace") || process.cwd();
|
|
9950
9769
|
try {
|
|
9951
|
-
(0,
|
|
9770
|
+
(0, import_core50.assertWorkspaceExists)(workspace);
|
|
9952
9771
|
} catch {
|
|
9953
9772
|
console.error(
|
|
9954
9773
|
`Workspace "${workspace}" does not exist.
|
|
@@ -9957,7 +9776,7 @@ cd into a directory that exists, or pass --workspace <path> naming one that does
|
|
|
9957
9776
|
);
|
|
9958
9777
|
process.exit(1);
|
|
9959
9778
|
}
|
|
9960
|
-
const discoveredSkills = (0,
|
|
9779
|
+
const discoveredSkills = (0, import_core50.createSkillsService)(workspace, new import_core50.EnvConfig().workspaceRepos).listSkills();
|
|
9961
9780
|
registerSkillCommands(discoveredSkills);
|
|
9962
9781
|
const taskSkills = discoveredSkills.filter((s) => s.appliesTo === "task").map((s) => ({ name: s.name, description: s.description }));
|
|
9963
9782
|
const explicitPort = flag(subArgs, "--port") || process.env.ORDEWELL_PORT;
|
|
@@ -9967,7 +9786,7 @@ cd into a directory that exists, or pass --workspace <path> naming one that does
|
|
|
9967
9786
|
const api = new ApiClient(port, workspace);
|
|
9968
9787
|
let terminal;
|
|
9969
9788
|
const mouseCapture = process.env.ORDEWELL_TUI_MOUSE !== "false" && process.env.ORDEWELL_TUI_MOUSE !== "0";
|
|
9970
|
-
const settings = new
|
|
9789
|
+
const settings = new import_core50.SettingsService();
|
|
9971
9790
|
const app = createApp({
|
|
9972
9791
|
// The level the daemon plans with: the saved one, unless the environment overrides it (ADR-0030).
|
|
9973
9792
|
// The run settings are seeded from the same file because the first frame is
|
|
@@ -9989,13 +9808,13 @@ cd into a directory that exists, or pass --workspace <path> naming one that does
|
|
|
9989
9808
|
workspace,
|
|
9990
9809
|
port,
|
|
9991
9810
|
dispatch: (action) => app.dispatch(action),
|
|
9992
|
-
newSessionId: () => (0,
|
|
9811
|
+
newSessionId: () => (0, import_core50.mintSessionId)(),
|
|
9993
9812
|
setEnvVar: (key, value) => {
|
|
9994
9813
|
writeEnvVar(findEnvFile(), key, value);
|
|
9995
9814
|
process.env[key] = value;
|
|
9996
9815
|
},
|
|
9997
9816
|
saveAutonomy: (enabled) => {
|
|
9998
|
-
const settings2 = new
|
|
9817
|
+
const settings2 = new import_core50.SettingsService();
|
|
9999
9818
|
settings2.setAutonomousMode(enabled);
|
|
10000
9819
|
return { overridden: settings2.autonomousModeOverridden() };
|
|
10001
9820
|
},
|
|
@@ -10112,7 +9931,7 @@ var COMMANDS = {
|
|
|
10112
9931
|
// src/main.ts
|
|
10113
9932
|
var TUI_FLAGS = /* @__PURE__ */ new Set(["--workspace", "--port"]);
|
|
10114
9933
|
async function main() {
|
|
10115
|
-
(0,
|
|
9934
|
+
(0, import_core51.migrateOldConfigDir)();
|
|
10116
9935
|
moveAutonomyToSettings();
|
|
10117
9936
|
loadEnvFile();
|
|
10118
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.
|
|
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.
|
|
55
|
-
"@ordewell/web": "^0.10.
|
|
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
|
},
|