@ordewell/cli 0.10.0 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +617 -473
- package/package.json +5 -3
package/dist/main.js
CHANGED
|
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
));
|
|
25
25
|
|
|
26
26
|
// src/main.ts
|
|
27
|
-
var
|
|
27
|
+
var import_core49 = require("@ordewell/core");
|
|
28
28
|
|
|
29
29
|
// src/utils/env.ts
|
|
30
30
|
var import_fs = require("fs");
|
|
@@ -107,6 +107,23 @@ function moveAutonomyToSettings() {
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
// src/runnerNames.ts
|
|
111
|
+
var import_core2 = require("@ordewell/core");
|
|
112
|
+
function manifests() {
|
|
113
|
+
return new import_core2.RunnerRegistry().list().map((entry) => entry.manifest);
|
|
114
|
+
}
|
|
115
|
+
function runnerIdList() {
|
|
116
|
+
return manifests().map((m) => m.name).join(", ");
|
|
117
|
+
}
|
|
118
|
+
function runnerIdChoice() {
|
|
119
|
+
return manifests().map((m) => m.name).join("|");
|
|
120
|
+
}
|
|
121
|
+
function runnerNamesOr() {
|
|
122
|
+
const names = manifests().map((m) => m.displayName);
|
|
123
|
+
if (names.length < 2) return names.join("");
|
|
124
|
+
return `${names.slice(0, -1).join(", ")} or ${names[names.length - 1]}`;
|
|
125
|
+
}
|
|
126
|
+
|
|
110
127
|
// src/help.ts
|
|
111
128
|
function printHelp() {
|
|
112
129
|
console.log(`
|
|
@@ -157,7 +174,7 @@ Planner, models and runners:
|
|
|
157
174
|
ordewell model [set <id>] Show or set the planner model (applies without a restart)
|
|
158
175
|
ordewell planner-effort [lvl] Thinking effort for a coding-agent planner
|
|
159
176
|
ordewell key [set <p> <key>] Show which providers have a key, or store one
|
|
160
|
-
ordewell runners [<id> on|off] Enable or disable runners (
|
|
177
|
+
ordewell runners [<id> on|off] Enable or disable runners (${runnerIdList()})
|
|
161
178
|
ordewell allowlist set|clear|show Limit which models a runner may use
|
|
162
179
|
ordewell auto [full|guarded] Autonomy level for new plans: Full or Guarded
|
|
163
180
|
ordewell supervisor [off|watch|act] Whether the planner watches or acts on your runs (default watch);
|
|
@@ -236,13 +253,13 @@ Quick Start:
|
|
|
236
253
|
then run: ordewell plan --goal "Your task description"
|
|
237
254
|
|
|
238
255
|
No API key? Plan with a coding agent you already pay for:
|
|
239
|
-
AI_PROVIDER
|
|
256
|
+
AI_PROVIDER=<runner> ordewell plan --goal "Your task description"
|
|
240
257
|
|
|
241
258
|
Environment:
|
|
242
259
|
OPENROUTER_API_KEY OpenRouter API key (recommended)
|
|
243
260
|
GEMINI_API_KEY Google Gemini API key (alternative)
|
|
244
261
|
AI_PROVIDER openrouter, google \u2014 auto-detected from keys
|
|
245
|
-
|
|
262
|
+
${runnerIdList()} \u2014 plan with that CLI,
|
|
246
263
|
no API key (uses its own subscription)
|
|
247
264
|
ORDEWELL_PLANNER_EFFORT Thinking effort for a coding-agent planner
|
|
248
265
|
ORCHESTRATOR_MODEL Default: deepseek/deepseek-v4-flash
|
|
@@ -275,9 +292,9 @@ var import_os = require("os");
|
|
|
275
292
|
var import_path2 = require("path");
|
|
276
293
|
var import_http = __toESM(require("http"));
|
|
277
294
|
var import_net = require("net");
|
|
278
|
-
var
|
|
295
|
+
var import_core3 = require("@ordewell/core");
|
|
279
296
|
var DEFAULT_PORT = 3742;
|
|
280
|
-
var CONFIG_DIR = (0,
|
|
297
|
+
var CONFIG_DIR = (0, import_core3.globalDataDir)();
|
|
281
298
|
var LEGACY_PID_FILE = (0, import_path2.join)(CONFIG_DIR, "server.pid");
|
|
282
299
|
var OLD_CONFIG_DIR = (0, import_path2.join)((0, import_os.homedir)(), ".config", "ordewell");
|
|
283
300
|
function pidFileFor(port) {
|
|
@@ -317,12 +334,12 @@ function getWebServerPath() {
|
|
|
317
334
|
);
|
|
318
335
|
}
|
|
319
336
|
async function isDaemonRunning(port = DEFAULT_PORT) {
|
|
320
|
-
const token = (0,
|
|
337
|
+
const token = (0, import_core3.readDaemonToken)(port);
|
|
321
338
|
try {
|
|
322
339
|
const res = await httpGet(
|
|
323
340
|
`http://127.0.0.1:${port}/api/workspaces`,
|
|
324
341
|
2e3,
|
|
325
|
-
token ? { Authorization: (0,
|
|
342
|
+
token ? { Authorization: (0, import_core3.bearerHeaderValue)(token) } : {}
|
|
326
343
|
);
|
|
327
344
|
return res.status === 200 || res.status === 401;
|
|
328
345
|
} catch {
|
|
@@ -378,7 +395,7 @@ async function stopDaemon(port = DEFAULT_PORT) {
|
|
|
378
395
|
const pid = parseInt(pidStr, 10);
|
|
379
396
|
if (!pid || isNaN(pid)) {
|
|
380
397
|
(0, import_fs2.unlinkSync)(pidFile);
|
|
381
|
-
(0,
|
|
398
|
+
(0, import_core3.clearDaemonToken)(port);
|
|
382
399
|
return false;
|
|
383
400
|
}
|
|
384
401
|
process.kill(pid, "SIGTERM");
|
|
@@ -391,7 +408,7 @@ async function stopDaemon(port = DEFAULT_PORT) {
|
|
|
391
408
|
(0, import_fs2.unlinkSync)(pidFile);
|
|
392
409
|
} catch {
|
|
393
410
|
}
|
|
394
|
-
(0,
|
|
411
|
+
(0, import_core3.clearDaemonToken)(port);
|
|
395
412
|
console.log("Server was not running (stale PID removed).");
|
|
396
413
|
return true;
|
|
397
414
|
}
|
|
@@ -444,7 +461,7 @@ function resolvePort(args = []) {
|
|
|
444
461
|
// src/apiClient.ts
|
|
445
462
|
var import_http2 = __toESM(require("http"));
|
|
446
463
|
var import_ws = __toESM(require("ws"));
|
|
447
|
-
var
|
|
464
|
+
var import_core4 = require("@ordewell/core");
|
|
448
465
|
var DEFAULT_HTTP_TIMEOUT_MS = 15 * 60 * 1e3;
|
|
449
466
|
var DaemonError = class extends Error {
|
|
450
467
|
constructor(message, status, code) {
|
|
@@ -488,7 +505,7 @@ var ApiClient = class _ApiClient {
|
|
|
488
505
|
* A missing file is not an error here — the daemon's own 401 names the path.
|
|
489
506
|
*/
|
|
490
507
|
token() {
|
|
491
|
-
return (0,
|
|
508
|
+
return (0, import_core4.readDaemonToken)(this.port);
|
|
492
509
|
}
|
|
493
510
|
/**
|
|
494
511
|
* A daemon holds only the sessions adopted since it started, so after a
|
|
@@ -524,7 +541,7 @@ var ApiClient = class _ApiClient {
|
|
|
524
541
|
method,
|
|
525
542
|
headers: {
|
|
526
543
|
...body ? { "Content-Type": "application/json" } : {},
|
|
527
|
-
...token ? { Authorization: (0,
|
|
544
|
+
...token ? { Authorization: (0, import_core4.bearerHeaderValue)(token) } : {}
|
|
528
545
|
},
|
|
529
546
|
// Planner research on a real repository regularly exceeds two minutes.
|
|
530
547
|
// The benchmark harness uses the same 15-minute default explicitly;
|
|
@@ -554,7 +571,7 @@ var ApiClient = class _ApiClient {
|
|
|
554
571
|
req.end();
|
|
555
572
|
});
|
|
556
573
|
}
|
|
557
|
-
async generatePlan(goal, runners2, workspace, sessionId = (0,
|
|
574
|
+
async generatePlan(goal, runners2, workspace, sessionId = (0, import_core4.mintSessionId)()) {
|
|
558
575
|
const { plan, models, modelsByRunner, notes } = await this.call("POST", `/api/plans/${sessionId}/generate`, "Plan generation failed", {
|
|
559
576
|
goal,
|
|
560
577
|
runners: runners2 || void 0,
|
|
@@ -789,7 +806,7 @@ var ApiClient = class _ApiClient {
|
|
|
789
806
|
const token = this.token();
|
|
790
807
|
const socket = new import_ws.default(
|
|
791
808
|
`ws://127.0.0.1:${this.port}/ws/session/${sessionId}`,
|
|
792
|
-
token ? (0,
|
|
809
|
+
token ? (0, import_core4.tokenSubprotocols)(token) : void 0
|
|
793
810
|
);
|
|
794
811
|
socket.on("unexpected-response", (_req, res) => {
|
|
795
812
|
const chunks = [];
|
|
@@ -1012,15 +1029,15 @@ function positionals(args) {
|
|
|
1012
1029
|
}
|
|
1013
1030
|
|
|
1014
1031
|
// src/utils/tasks.ts
|
|
1015
|
-
var
|
|
1032
|
+
var import_core5 = require("@ordewell/core");
|
|
1016
1033
|
function allTasksOf(plan) {
|
|
1017
1034
|
const tasks = plan?.pendingTasks || plan?.tasks || [];
|
|
1018
1035
|
const executionLog = plan?.executionLog || [];
|
|
1019
|
-
return (0,
|
|
1036
|
+
return (0, import_core5.rejoinPlanTree)(tasks, executionLog);
|
|
1020
1037
|
}
|
|
1021
1038
|
function resolveTaskId(plan, identifier) {
|
|
1022
1039
|
const allTasks = allTasksOf(plan);
|
|
1023
|
-
const byRef = (0,
|
|
1040
|
+
const byRef = (0, import_core5.resolveTaskRef)(allTasks, identifier);
|
|
1024
1041
|
if (byRef) return byRef.id;
|
|
1025
1042
|
const prefixMatches = allTasks.filter((t) => typeof t.id === "string" && t.id.startsWith(identifier));
|
|
1026
1043
|
if (prefixMatches.length === 1) return prefixMatches[0].id;
|
|
@@ -1030,13 +1047,13 @@ function resolveTaskId(plan, identifier) {
|
|
|
1030
1047
|
// src/utils/session.ts
|
|
1031
1048
|
var import_fs3 = require("fs");
|
|
1032
1049
|
var import_path3 = require("path");
|
|
1033
|
-
var
|
|
1050
|
+
var import_core6 = require("@ordewell/core");
|
|
1034
1051
|
var LAST_SESSION_FILENAME = "last-session.json";
|
|
1035
1052
|
function lastSessionFile(workspace) {
|
|
1036
|
-
return (0, import_path3.join)((0,
|
|
1053
|
+
return (0, import_path3.join)((0, import_core6.getStateDir)(workspace), LAST_SESSION_FILENAME);
|
|
1037
1054
|
}
|
|
1038
1055
|
function saveLastSession(sessionId, goal, runners2, workspace) {
|
|
1039
|
-
const dir = (0,
|
|
1056
|
+
const dir = (0, import_core6.getStateDir)(workspace);
|
|
1040
1057
|
if (!(0, import_fs3.existsSync)(dir)) (0, import_fs3.mkdirSync)(dir, { recursive: true });
|
|
1041
1058
|
(0, import_fs3.writeFileSync)(
|
|
1042
1059
|
lastSessionFile(workspace),
|
|
@@ -1058,14 +1075,14 @@ function expandSessionId(id, workspace) {
|
|
|
1058
1075
|
if (id.startsWith(SESSION_PREFIX)) return id;
|
|
1059
1076
|
let files;
|
|
1060
1077
|
try {
|
|
1061
|
-
files = (0, import_fs3.readdirSync)((0, import_path3.join)((0,
|
|
1078
|
+
files = (0, import_fs3.readdirSync)((0, import_path3.join)((0, import_core6.getStateDir)(workspace), "sessions")).filter((f) => f.endsWith(".json"));
|
|
1062
1079
|
} catch {
|
|
1063
1080
|
return id;
|
|
1064
1081
|
}
|
|
1065
1082
|
const matches = /* @__PURE__ */ new Set();
|
|
1066
1083
|
for (const file of files) {
|
|
1067
1084
|
try {
|
|
1068
|
-
const full = JSON.parse((0, import_fs3.readFileSync)((0, import_path3.join)((0,
|
|
1085
|
+
const full = JSON.parse((0, import_fs3.readFileSync)((0, import_path3.join)((0, import_core6.getStateDir)(workspace), "sessions", file), "utf8"))?.meta?.id;
|
|
1069
1086
|
if (typeof full === "string" && (full.endsWith(id) || full.slice(SESSION_PREFIX.length).startsWith(id))) matches.add(full);
|
|
1070
1087
|
} catch {
|
|
1071
1088
|
}
|
|
@@ -1136,7 +1153,7 @@ ${describeApproval(event)}
|
|
|
1136
1153
|
}
|
|
1137
1154
|
|
|
1138
1155
|
// src/commands/researchLog.ts
|
|
1139
|
-
var
|
|
1156
|
+
var import_core7 = require("@ordewell/core");
|
|
1140
1157
|
var OUTCOME_MARK = {
|
|
1141
1158
|
success: "\u2713",
|
|
1142
1159
|
failure: "\u2717",
|
|
@@ -1148,7 +1165,7 @@ var RESULT_CHARS = 160;
|
|
|
1148
1165
|
var VERBOSE_RESULT_CHARS = 600;
|
|
1149
1166
|
var THINKING_CHARS = 300;
|
|
1150
1167
|
function summarize(tool, args, toolLabel) {
|
|
1151
|
-
const { name, keyArg } = (0,
|
|
1168
|
+
const { name, keyArg } = (0, import_core7.toolHeadline)(tool, args, toolLabel);
|
|
1152
1169
|
return `${name}(${keyArg})`;
|
|
1153
1170
|
}
|
|
1154
1171
|
function oneLine(text, max) {
|
|
@@ -1198,7 +1215,7 @@ function createStepLog(options = {}) {
|
|
|
1198
1215
|
}
|
|
1199
1216
|
|
|
1200
1217
|
// src/commands/plan.ts
|
|
1201
|
-
var
|
|
1218
|
+
var import_core8 = require("@ordewell/core");
|
|
1202
1219
|
function planTasks(plan) {
|
|
1203
1220
|
return plan ? allTasksOf(plan) : [];
|
|
1204
1221
|
}
|
|
@@ -1282,11 +1299,11 @@ Plan: ${tasks.length} task${tasks.length === 1 ? "" : "s"} (${aiCount} AI, ${man
|
|
|
1282
1299
|
for (const t of tasks) {
|
|
1283
1300
|
const typeIcon = t.type === "user" ? "[MAN]" : t.ops ? "[OPS]" : "[ AI]";
|
|
1284
1301
|
const deps = t.dependencies?.length ? ` \u2190 ${t.dependencies.join(", ")}` : "";
|
|
1285
|
-
console.log(` ${(0,
|
|
1302
|
+
console.log(` ${(0, import_core8.taskOrderLabel)(t).padStart(2)}. ${typeIcon} ${t.title}${modelSuffix(t)}${deps}`);
|
|
1286
1303
|
for (const sub of t.subtasks || []) {
|
|
1287
1304
|
const subTypeIcon = sub.type === "user" ? "[MAN]" : "[ AI]";
|
|
1288
1305
|
const subDeps = sub.dependencies?.length ? ` \u2190 ${sub.dependencies.join(", ")}` : "";
|
|
1289
|
-
console.log(` ${(0,
|
|
1306
|
+
console.log(` ${(0, import_core8.taskOrderLabel)(sub, t)}. ${subTypeIcon} ${sub.title}${modelSuffix(sub)}${subDeps}`);
|
|
1290
1307
|
}
|
|
1291
1308
|
}
|
|
1292
1309
|
if (manCount > 0) {
|
|
@@ -1336,7 +1353,7 @@ async function handlePlan(subArgs, deps = {}) {
|
|
|
1336
1353
|
runners2 = runnerFlags;
|
|
1337
1354
|
}
|
|
1338
1355
|
console.error(`Generating plan for: "${goal}"...`);
|
|
1339
|
-
const sessionId = (0,
|
|
1356
|
+
const sessionId = (0, import_core8.mintSessionId)();
|
|
1340
1357
|
const isTty = !!process.stderr.isTTY;
|
|
1341
1358
|
let lastLineLength = 0;
|
|
1342
1359
|
const stepLog = createStepLog({ verbose });
|
|
@@ -1442,7 +1459,7 @@ ${note}`);
|
|
|
1442
1459
|
}
|
|
1443
1460
|
|
|
1444
1461
|
// src/isolation.ts
|
|
1445
|
-
var
|
|
1462
|
+
var import_core9 = require("@ordewell/core");
|
|
1446
1463
|
var STATE_OF = {
|
|
1447
1464
|
active: "active",
|
|
1448
1465
|
merged: "integrated",
|
|
@@ -1526,9 +1543,9 @@ function repairedLanded(handoff) {
|
|
|
1526
1543
|
function repairedNotice(handoff) {
|
|
1527
1544
|
const repaired = repairedLanded(handoff);
|
|
1528
1545
|
if (repaired.length === 0) return "";
|
|
1529
|
-
const named = repaired.map((t) => `${t.title} (${(0,
|
|
1530
|
-
const
|
|
1531
|
-
return ` ${
|
|
1546
|
+
const named = repaired.map((t) => `${t.title} (${(0, import_core9.capConflictFiles)(t.repairedFiles)})`);
|
|
1547
|
+
const list2 = named.length === 1 ? named[0] : `${named.slice(0, -1).join(", ")} and ${named[named.length - 1]}`;
|
|
1548
|
+
return ` ${list2} landed through ${repaired.length === 1 ? "a conflict repair" : "conflict repairs"}.`;
|
|
1532
1549
|
}
|
|
1533
1550
|
function repoResultLines(handoff) {
|
|
1534
1551
|
return handoff.repos.map(({ path, landed }) => {
|
|
@@ -1541,14 +1558,14 @@ function mergeOutcome(result, branch, group, repaired = []) {
|
|
|
1541
1558
|
if (!group && result.outcome === "conflict") {
|
|
1542
1559
|
return { ok, message: `Merging ${branch} conflicted, so it was aborted \u2014 your tree is as it was. Merge it with git and resolve the conflict there.` };
|
|
1543
1560
|
}
|
|
1544
|
-
const { message } = (0,
|
|
1561
|
+
const { message } = (0, import_core9.describeMergeResult)(result, branch, group, repaired);
|
|
1545
1562
|
return { ok, message: ok || !group ? message : `${message} Each repository's ${branch} is a plain branch you can merge by hand.` };
|
|
1546
1563
|
}
|
|
1547
1564
|
|
|
1548
1565
|
// src/utils/output.ts
|
|
1549
|
-
var
|
|
1566
|
+
var import_core10 = require("@ordewell/core");
|
|
1550
1567
|
function iconFor(status) {
|
|
1551
|
-
switch ((0,
|
|
1568
|
+
switch ((0, import_core10.taskStatusKind)({ status })) {
|
|
1552
1569
|
case "done":
|
|
1553
1570
|
return "\x1B[32m\u2713\x1B[0m";
|
|
1554
1571
|
case "running":
|
|
@@ -1568,7 +1585,7 @@ function iconFor(status) {
|
|
|
1568
1585
|
}
|
|
1569
1586
|
|
|
1570
1587
|
// src/commands/run.ts
|
|
1571
|
-
var
|
|
1588
|
+
var import_core11 = require("@ordewell/core");
|
|
1572
1589
|
|
|
1573
1590
|
// src/commands/shared.ts
|
|
1574
1591
|
var import_readline2 = require("readline");
|
|
@@ -1727,11 +1744,11 @@ async function followExecution(api, sessionId, start, onBlocked) {
|
|
|
1727
1744
|
});
|
|
1728
1745
|
const stream = api.streamExecution(sessionId, (event) => {
|
|
1729
1746
|
if (event.type === "task_started") {
|
|
1730
|
-
process.stderr.write(`\xB7 ${(0,
|
|
1747
|
+
process.stderr.write(`\xB7 ${(0, import_core11.taskStartedNotice)(event.title, event.runner)}
|
|
1731
1748
|
`);
|
|
1732
1749
|
}
|
|
1733
1750
|
if (event.type === "checkpoint") {
|
|
1734
|
-
process.stderr.write(`\xB7 Checkpoint \u2014 ${event.taskTitle}: ${(0,
|
|
1751
|
+
process.stderr.write(`\xB7 Checkpoint \u2014 ${event.taskTitle}: ${(0, import_core11.truncateCheckpointSummary)(event.summary)} \u2014 \`ordewell checkpoint <id> approve|reject [reason]\` answers it
|
|
1735
1752
|
`);
|
|
1736
1753
|
}
|
|
1737
1754
|
if (event.type === "status_update" && event.tasks) {
|
|
@@ -1812,7 +1829,7 @@ async function handleRun(subArgs, injectedApi) {
|
|
|
1812
1829
|
}
|
|
1813
1830
|
|
|
1814
1831
|
// src/tui/blocks.ts
|
|
1815
|
-
var
|
|
1832
|
+
var import_core13 = require("@ordewell/core");
|
|
1816
1833
|
|
|
1817
1834
|
// src/tui/ansi.ts
|
|
1818
1835
|
var import_string_width = __toESM(require("string-width"));
|
|
@@ -2027,94 +2044,191 @@ var style = {
|
|
|
2027
2044
|
};
|
|
2028
2045
|
|
|
2029
2046
|
// src/tui/markdown.ts
|
|
2047
|
+
var import_core12 = require("@ordewell/core");
|
|
2030
2048
|
function renderMarkdown(source, cols) {
|
|
2031
|
-
|
|
2049
|
+
return blocks((0, import_core12.markdownTokens)(source), { room: Math.max(1, cols), base: [] });
|
|
2050
|
+
}
|
|
2051
|
+
function closeOf(tokens, open) {
|
|
2052
|
+
const { level } = tokens[open];
|
|
2053
|
+
for (let i = open + 1; i < tokens.length; i += 1) {
|
|
2054
|
+
if (tokens[i].nesting === -1 && tokens[i].level === level) return i;
|
|
2055
|
+
}
|
|
2056
|
+
return tokens.length - 1;
|
|
2057
|
+
}
|
|
2058
|
+
function lastLine(tokens) {
|
|
2059
|
+
let last = null;
|
|
2060
|
+
for (const token of tokens) {
|
|
2061
|
+
if (token.nesting === 0 && token.map && (last === null || token.map[1] > last)) last = token.map[1];
|
|
2062
|
+
}
|
|
2063
|
+
return last ?? tokens[0]?.map?.[1] ?? null;
|
|
2064
|
+
}
|
|
2065
|
+
function blocks(tokens, ctx) {
|
|
2032
2066
|
const out = [];
|
|
2033
|
-
let
|
|
2034
|
-
for (let i = 0; i <
|
|
2035
|
-
const
|
|
2036
|
-
if (
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
i = table.end;
|
|
2048
|
-
continue;
|
|
2049
|
-
}
|
|
2050
|
-
const heading = line.match(/^\s{0,3}(#{1,6})\s+(.+?)\s*#*\s*$/);
|
|
2051
|
-
if (heading) {
|
|
2052
|
-
const paint = heading[1].length <= 2 ? (text) => style.bold(style.brand(text)) : style.bold;
|
|
2053
|
-
out.push(...wrap(paint(inline(heading[2])), cols));
|
|
2054
|
-
continue;
|
|
2055
|
-
}
|
|
2056
|
-
if (/^\s{0,3}(?:[-*_]\s*){3,}$/.test(line)) {
|
|
2057
|
-
out.push(style.grey("\u2500".repeat(Math.max(1, cols))));
|
|
2058
|
-
continue;
|
|
2059
|
-
}
|
|
2060
|
-
const bullet = line.match(/^(\s*)[-*+]\s+(.+)$/);
|
|
2061
|
-
if (bullet) {
|
|
2062
|
-
out.push(...wrap(`${bullet[1]}\u2022 ${inline(bullet[2])}`, cols));
|
|
2063
|
-
continue;
|
|
2064
|
-
}
|
|
2065
|
-
const quote = line.match(/^\s*>\s?(.*)$/);
|
|
2066
|
-
if (quote) {
|
|
2067
|
-
out.push(...wrap(style.grey(`\u2502 ${inline(quote[1])}`), cols));
|
|
2068
|
-
continue;
|
|
2069
|
-
}
|
|
2070
|
-
out.push(...wrap(inline(line), cols));
|
|
2067
|
+
let previousEnd = null;
|
|
2068
|
+
for (let i = 0; i < tokens.length; i += 1) {
|
|
2069
|
+
const token = tokens[i];
|
|
2070
|
+
if (token.nesting === -1) continue;
|
|
2071
|
+
const end = token.nesting === 1 ? closeOf(tokens, i) : i;
|
|
2072
|
+
const children = tokens.slice(i + 1, end);
|
|
2073
|
+
const lines = block(token, children, ctx);
|
|
2074
|
+
const last = lastLine([token, ...children]);
|
|
2075
|
+
i = end;
|
|
2076
|
+
if (lines === null) continue;
|
|
2077
|
+
const start = token.map?.[0] ?? null;
|
|
2078
|
+
if (previousEnd !== null && start !== null && start > previousEnd && out.length > 0) out.push("");
|
|
2079
|
+
previousEnd = last ?? previousEnd;
|
|
2080
|
+
out.push(...lines);
|
|
2071
2081
|
}
|
|
2072
2082
|
return out;
|
|
2073
2083
|
}
|
|
2074
|
-
function
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2084
|
+
function block(token, children, ctx) {
|
|
2085
|
+
switch (token.type) {
|
|
2086
|
+
case "paragraph_open":
|
|
2087
|
+
return wrap(inline(children[0]?.children ?? [], ctx.base, "\n"), ctx.room);
|
|
2088
|
+
case "heading_open": {
|
|
2089
|
+
const level = Number(token.tag.slice(1));
|
|
2090
|
+
const base = level <= 2 ? [style.bold, style.brand] : [style.bold];
|
|
2091
|
+
return wrap(inline(children[0]?.children ?? [], [...ctx.base, ...base], "\n"), ctx.room);
|
|
2092
|
+
}
|
|
2093
|
+
case "fence":
|
|
2094
|
+
case "code_block":
|
|
2095
|
+
return token.content.replace(/\n$/, "").split("\n").flatMap((line) => wrap(` ${line}`, ctx.room)).map(style.grey);
|
|
2096
|
+
case "hr":
|
|
2097
|
+
return [style.grey("\u2500".repeat(ctx.room))];
|
|
2098
|
+
case "blockquote_open": {
|
|
2099
|
+
const inner = blocks(children, { room: Math.max(1, ctx.room - 2), base: [...ctx.base, style.grey] });
|
|
2100
|
+
return inner.map((line) => `${style.grey("\u2502")} ${line}`);
|
|
2101
|
+
}
|
|
2102
|
+
case "bullet_list_open":
|
|
2103
|
+
return list(children, ctx, () => "\u2022");
|
|
2104
|
+
case "ordered_list_open": {
|
|
2105
|
+
const start = Number(token.attrs?.find(([name]) => name === "start")?.[1] ?? 1);
|
|
2106
|
+
let n = start - 1;
|
|
2107
|
+
return list(children, ctx, (item) => {
|
|
2108
|
+
n += 1;
|
|
2109
|
+
return `${item.info || n}${item.markup || "."}`;
|
|
2110
|
+
});
|
|
2111
|
+
}
|
|
2112
|
+
case "table_open":
|
|
2113
|
+
return table(children, ctx);
|
|
2114
|
+
default:
|
|
2115
|
+
return null;
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
function list(items, ctx, marker2) {
|
|
2119
|
+
const out = [];
|
|
2120
|
+
let previousEnd = null;
|
|
2121
|
+
for (let i = 0; i < items.length; i += 1) {
|
|
2122
|
+
const item = items[i];
|
|
2123
|
+
if (item.type !== "list_item_open") continue;
|
|
2124
|
+
const end = closeOf(items, i);
|
|
2125
|
+
const mark = marker2(item);
|
|
2126
|
+
const hang = " ".repeat(width(mark) + 1);
|
|
2127
|
+
const content = items.slice(i + 1, end);
|
|
2128
|
+
const inner = blocks(content, { ...ctx, room: Math.max(1, ctx.room - hang.length) });
|
|
2129
|
+
i = end;
|
|
2130
|
+
const start = item.map?.[0] ?? null;
|
|
2131
|
+
if (previousEnd !== null && start !== null && start > previousEnd) out.push("");
|
|
2132
|
+
previousEnd = lastLine(content) ?? previousEnd;
|
|
2133
|
+
(inner.length > 0 ? inner : [""]).forEach((line, row) => out.push(row === 0 ? `${mark} ${line}` : line && `${hang}${line}`));
|
|
2085
2134
|
}
|
|
2086
|
-
return
|
|
2135
|
+
return out;
|
|
2087
2136
|
}
|
|
2088
|
-
function
|
|
2089
|
-
const
|
|
2090
|
-
|
|
2137
|
+
function inline(tokens, base, lineBreak) {
|
|
2138
|
+
const active = [...base];
|
|
2139
|
+
const paint = (text) => text.split(" ").map((word) => word ? active.reduce((acc, apply) => apply(acc), word) : word).join(" ");
|
|
2140
|
+
let out = "";
|
|
2141
|
+
let href = null;
|
|
2142
|
+
let linkText = "";
|
|
2143
|
+
const emit = (text) => {
|
|
2144
|
+
out += paint(text);
|
|
2145
|
+
if (href !== null) linkText += text;
|
|
2146
|
+
};
|
|
2147
|
+
for (const token of tokens) {
|
|
2148
|
+
switch (token.type) {
|
|
2149
|
+
case "text":
|
|
2150
|
+
case "image":
|
|
2151
|
+
emit(token.content);
|
|
2152
|
+
break;
|
|
2153
|
+
case "code_inline":
|
|
2154
|
+
active.push(style.brand);
|
|
2155
|
+
emit(token.content);
|
|
2156
|
+
active.pop();
|
|
2157
|
+
break;
|
|
2158
|
+
case "softbreak":
|
|
2159
|
+
case "hardbreak":
|
|
2160
|
+
out += lineBreak;
|
|
2161
|
+
break;
|
|
2162
|
+
case "strong_open":
|
|
2163
|
+
active.push(style.bold);
|
|
2164
|
+
break;
|
|
2165
|
+
case "em_open":
|
|
2166
|
+
active.push(style.italic);
|
|
2167
|
+
break;
|
|
2168
|
+
case "s_open":
|
|
2169
|
+
active.push(style.dim);
|
|
2170
|
+
break;
|
|
2171
|
+
case "link_open":
|
|
2172
|
+
href = token.attrs?.find(([name]) => name === "href")?.[1] ?? null;
|
|
2173
|
+
linkText = "";
|
|
2174
|
+
if (href !== null) active.push(style.underline);
|
|
2175
|
+
break;
|
|
2176
|
+
case "link_close":
|
|
2177
|
+
if (href !== null) {
|
|
2178
|
+
active.pop();
|
|
2179
|
+
if (linkText !== href) out += paint(" ") + style.grey(`(${href})`);
|
|
2180
|
+
}
|
|
2181
|
+
href = null;
|
|
2182
|
+
break;
|
|
2183
|
+
case "strong_close":
|
|
2184
|
+
case "em_close":
|
|
2185
|
+
case "s_close":
|
|
2186
|
+
active.pop();
|
|
2187
|
+
break;
|
|
2188
|
+
default:
|
|
2189
|
+
if (token.content) emit(token.content);
|
|
2190
|
+
}
|
|
2191
|
+
}
|
|
2192
|
+
return out;
|
|
2091
2193
|
}
|
|
2092
|
-
function
|
|
2093
|
-
|
|
2194
|
+
function table(tokens, ctx) {
|
|
2195
|
+
const headers = [];
|
|
2196
|
+
const rows = [];
|
|
2197
|
+
let inHead = false;
|
|
2198
|
+
let row = null;
|
|
2199
|
+
for (const token of tokens) {
|
|
2200
|
+
if (token.type === "thead_open") inHead = true;
|
|
2201
|
+
else if (token.type === "thead_close") inHead = false;
|
|
2202
|
+
else if (token.type === "tr_open") row = [];
|
|
2203
|
+
else if (token.type === "tr_close" && row) {
|
|
2204
|
+
if (inHead) headers.push(...row);
|
|
2205
|
+
else rows.push(row);
|
|
2206
|
+
row = null;
|
|
2207
|
+
} else if (token.type === "inline" && row) {
|
|
2208
|
+
row.push(inline(token.children ?? [], inHead ? [style.bold] : [], " "));
|
|
2209
|
+
}
|
|
2210
|
+
}
|
|
2211
|
+
return renderTable(headers, rows, ctx.room);
|
|
2094
2212
|
}
|
|
2095
2213
|
function renderTable(headers, rows, cols) {
|
|
2096
2214
|
const separator = " \u2502 ";
|
|
2097
2215
|
const separatorWidth = width(separator);
|
|
2098
2216
|
const available = Math.max(headers.length, cols - separatorWidth * (headers.length - 1));
|
|
2099
2217
|
const natural = headers.map(
|
|
2100
|
-
(header, column) => Math.max(width(
|
|
2218
|
+
(header, column) => Math.max(width(header), ...rows.map((row) => width(row[column] ?? "")))
|
|
2101
2219
|
);
|
|
2102
2220
|
const columnWidths = fitTableColumns(natural, available);
|
|
2103
|
-
if (columnWidths.some((size) => size < 4)) return
|
|
2104
|
-
const renderRow = (cells2
|
|
2105
|
-
const wrapped =
|
|
2221
|
+
if (columnWidths.some((size, index) => size < Math.min(4, natural[index]))) return renderRecords(headers, rows, cols);
|
|
2222
|
+
const renderRow = (cells2) => {
|
|
2223
|
+
const wrapped = headers.map((_, index) => wrap(cells2[index] ?? "", columnWidths[index]));
|
|
2106
2224
|
const height = Math.max(...wrapped.map((cell) => cell.length));
|
|
2107
2225
|
return Array.from(
|
|
2108
2226
|
{ length: height },
|
|
2109
|
-
(_, line) => wrapped.map((cell, column) => pad(
|
|
2227
|
+
(_, line) => wrapped.map((cell, column) => pad(cell[line] ?? "", columnWidths[column])).join(separator)
|
|
2110
2228
|
);
|
|
2111
2229
|
};
|
|
2112
2230
|
const rule = columnWidths.map((size) => style.grey("\u2500".repeat(size))).join(style.grey("\u2500\u253C\u2500"));
|
|
2113
|
-
return [
|
|
2114
|
-
...renderRow(headers, style.bold),
|
|
2115
|
-
rule,
|
|
2116
|
-
...rows.flatMap((row) => renderRow(row))
|
|
2117
|
-
];
|
|
2231
|
+
return [...renderRow(headers), rule, ...rows.flatMap(renderRow)];
|
|
2118
2232
|
}
|
|
2119
2233
|
function fitTableColumns(natural, available) {
|
|
2120
2234
|
const widths = [...natural];
|
|
@@ -2127,15 +2241,12 @@ function fitTableColumns(natural, available) {
|
|
|
2127
2241
|
}
|
|
2128
2242
|
return widths;
|
|
2129
2243
|
}
|
|
2130
|
-
function
|
|
2244
|
+
function renderRecords(headers, rows, cols) {
|
|
2131
2245
|
return rows.flatMap((row, rowIndex) => [
|
|
2132
|
-
...rowIndex === 0 ? [] : [""],
|
|
2133
|
-
...
|
|
2246
|
+
...rowIndex === 0 ? [] : [style.grey("\u2500".repeat(cols))],
|
|
2247
|
+
...headers.flatMap((header, column) => wrap(`${header}: ${row[column] ?? ""}`, cols))
|
|
2134
2248
|
]);
|
|
2135
2249
|
}
|
|
2136
|
-
function inline(text) {
|
|
2137
|
-
return text.replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/\[([^\]]+)\]\(([^\s)]+)(?:\s+[^)]*)?\)/g, "$1 ($2)").replace(/\*\*([^*]+)\*\*/g, (_, bold) => style.bold(bold)).replace(/__([^_]+)__/g, (_, bold) => style.bold(bold)).replace(/(^|[^\w])\*([^*]+)\*(?![\w*])/g, (_, prefix, italic) => `${prefix}${style.italic(italic)}`).replace(/(^|[^\w])_([^_]+)_(?![\w_])/g, (_, prefix, italic) => `${prefix}${style.italic(italic)}`).replace(/`([^`]+)`/g, (_, code) => style.brand(code));
|
|
2138
|
-
}
|
|
2139
2250
|
|
|
2140
2251
|
// src/tui/blocks.ts
|
|
2141
2252
|
function countOf(n, noun) {
|
|
@@ -2168,25 +2279,25 @@ var ROLE_CONTINUATION = {
|
|
|
2168
2279
|
error: style.red,
|
|
2169
2280
|
wake_up: style.yellow
|
|
2170
2281
|
};
|
|
2171
|
-
function messageLines(
|
|
2172
|
-
const text = sanitize(
|
|
2282
|
+
function messageLines(block2, cols) {
|
|
2283
|
+
const text = sanitize(block2.text);
|
|
2173
2284
|
const room = Math.max(1, cols - 2);
|
|
2174
|
-
const wrapped =
|
|
2175
|
-
const rest = ROLE_CONTINUATION[
|
|
2176
|
-
const rows = wrapped.map((line, i) => i === 0 ? ROLE_PREFIX[
|
|
2177
|
-
if (
|
|
2285
|
+
const wrapped = block2.role === "planner" || block2.role === "agent" || block2.role === "supervisor" ? renderMarkdown(text, room) : block2.skills ? skillPaintedLines(text, block2.skills, room) : wrap(text, room);
|
|
2286
|
+
const rest = ROLE_CONTINUATION[block2.role] ?? ((t) => t);
|
|
2287
|
+
const rows = wrapped.map((line, i) => i === 0 ? ROLE_PREFIX[block2.role](line) : rest(` ${line}`));
|
|
2288
|
+
if (block2.role === "user" && block2.forced) {
|
|
2178
2289
|
const note = style.grey(" \xB7 sent now");
|
|
2179
2290
|
if (width(rows[0]) + width(note) <= cols) rows[0] += note;
|
|
2180
2291
|
else rows.push(` ${note}`);
|
|
2181
2292
|
}
|
|
2182
|
-
return
|
|
2293
|
+
return block2.role === "user" ? onBand(rows, cols) : rows;
|
|
2183
2294
|
}
|
|
2184
2295
|
function onBand(rows, cols) {
|
|
2185
2296
|
const band = ["", ...rows, ""];
|
|
2186
2297
|
return style.enabled ? band.map((row) => style.band(pad(row, cols))) : band;
|
|
2187
2298
|
}
|
|
2188
2299
|
function skillPaintedLines(text, skills, room) {
|
|
2189
|
-
const tokens = (0,
|
|
2300
|
+
const tokens = (0, import_core13.loadedSkillTokens)(text, skills);
|
|
2190
2301
|
return wrapLines(text, room).map(({ line, start }) => {
|
|
2191
2302
|
let painted = "";
|
|
2192
2303
|
let at = 0;
|
|
@@ -2200,19 +2311,19 @@ function skillPaintedLines(text, skills, room) {
|
|
|
2200
2311
|
return painted + line.slice(at);
|
|
2201
2312
|
});
|
|
2202
2313
|
}
|
|
2203
|
-
function skillLoadLine(
|
|
2204
|
-
const head =
|
|
2205
|
-
const line = truncate(`${head}${truncatePath(sanitize(
|
|
2314
|
+
function skillLoadLine(block2, cols) {
|
|
2315
|
+
const head = block2.attaches ? `\u25CF /${sanitize(block2.name)} will be attached to fitting tasks \xB7 ` : block2.invokedBy === "planner" ? `\u25CF ${sanitize(block2.name)} skill loaded by planner \xB7 ` : `\u25CF /${sanitize(block2.name)} skill loaded \xB7 `;
|
|
2316
|
+
const line = truncate(`${head}${truncatePath(sanitize(block2.path), Math.max(1, cols - width(head)))}`, cols);
|
|
2206
2317
|
return `${style.green("\u25CF")}${style.grey(line.slice(1))}`;
|
|
2207
2318
|
}
|
|
2208
|
-
function thinkingLines(
|
|
2209
|
-
const text = sanitize(
|
|
2319
|
+
function thinkingLines(block2, cols, detailAll) {
|
|
2320
|
+
const text = sanitize(block2.text).trim();
|
|
2210
2321
|
const head = `\u2234 Thinking (${countOf(text ? text.split(/\s+/).length : 0, "word")})`;
|
|
2211
2322
|
if (detailAll) {
|
|
2212
2323
|
const body = text ? wrap(text, Math.max(1, cols - 2)).map((line) => style.grey(` ${line}`)) : [];
|
|
2213
2324
|
return [style.grey(truncate(head, cols)), ...body];
|
|
2214
2325
|
}
|
|
2215
|
-
const latest =
|
|
2326
|
+
const latest = block2.streaming ? (text.split("\n").at(-1) ?? "").trim() : "";
|
|
2216
2327
|
const room = cols - width(`${head} \xB7 `);
|
|
2217
2328
|
if (!latest || room < 2) return [style.grey(truncate(head, cols))];
|
|
2218
2329
|
const shown = width(latest) > room ? `\u2026${tailOf(latest, room - 1)}` : latest;
|
|
@@ -2224,21 +2335,21 @@ var PREVIEW_LINES = 3;
|
|
|
2224
2335
|
function underHeader(lines) {
|
|
2225
2336
|
return lines.map((line, i) => `${i === 0 ? style.grey(OUTPUT_HEAD) : OUTPUT_INDENT}${line}`);
|
|
2226
2337
|
}
|
|
2227
|
-
function unsettledOutcome(
|
|
2228
|
-
switch (
|
|
2338
|
+
function unsettledOutcome(block2) {
|
|
2339
|
+
switch (block2.status) {
|
|
2229
2340
|
case "error":
|
|
2230
2341
|
return { label: "Error", paint: style.red };
|
|
2231
2342
|
case "denied":
|
|
2232
|
-
return { label:
|
|
2343
|
+
return { label: block2.outcome === "refused" ? "Refused" : "Denied", paint: style.yellow };
|
|
2233
2344
|
case "interrupted":
|
|
2234
2345
|
return { label: "Interrupted", paint: style.grey };
|
|
2235
2346
|
default:
|
|
2236
2347
|
return null;
|
|
2237
2348
|
}
|
|
2238
2349
|
}
|
|
2239
|
-
function commandMark(
|
|
2240
|
-
if (
|
|
2241
|
-
return (unsettledOutcome(
|
|
2350
|
+
function commandMark(block2) {
|
|
2351
|
+
if (block2.status === "pending") return style.grey("\u25CB");
|
|
2352
|
+
return (unsettledOutcome(block2)?.paint ?? style.green)("\u25CF");
|
|
2242
2353
|
}
|
|
2243
2354
|
var PATH_LIKE = /^(?![a-z][a-z0-9+.-]*:\/\/)\S*\/\S*$/i;
|
|
2244
2355
|
function truncatePath(path, max) {
|
|
@@ -2251,17 +2362,17 @@ function truncatePath(path, max) {
|
|
|
2251
2362
|
const slash = tail.search(/[\\/]/);
|
|
2252
2363
|
return `\u2026${slash > 0 ? tail.slice(slash) : tail}`;
|
|
2253
2364
|
}
|
|
2254
|
-
function commandHeader(
|
|
2255
|
-
const name = sanitize(
|
|
2256
|
-
const keyArg = sanitize(
|
|
2365
|
+
function commandHeader(block2, cols, detailAll) {
|
|
2366
|
+
const name = sanitize(block2.headline.name);
|
|
2367
|
+
const keyArg = sanitize(block2.headline.keyArg);
|
|
2257
2368
|
if (detailAll) {
|
|
2258
|
-
return wrap(`${name}(${keyArg})`, Math.max(1, cols - 2)).map((line, i) => i === 0 ? `${commandMark(
|
|
2369
|
+
return wrap(`${name}(${keyArg})`, Math.max(1, cols - 2)).map((line, i) => i === 0 ? `${commandMark(block2)} ${line}` : ` ${line}`);
|
|
2259
2370
|
}
|
|
2260
2371
|
const open = `\u25CF ${name}(`;
|
|
2261
2372
|
const room = cols - width(open) - 1;
|
|
2262
2373
|
const cut = PATH_LIKE.test(keyArg) ? truncatePath(keyArg, room) : truncate(keyArg, room);
|
|
2263
2374
|
const text = room > 1 ? `${open}${cut})` : truncate(`${open}${keyArg})`, cols);
|
|
2264
|
-
return [`${commandMark(
|
|
2375
|
+
return [`${commandMark(block2)}${text.slice(1)}`];
|
|
2265
2376
|
}
|
|
2266
2377
|
function argumentLines(args) {
|
|
2267
2378
|
if (!args.trim()) return [];
|
|
@@ -2277,21 +2388,21 @@ function argumentLines(args) {
|
|
|
2277
2388
|
return [`${key}: ${first}`, ...rest];
|
|
2278
2389
|
});
|
|
2279
2390
|
}
|
|
2280
|
-
function resultLines(
|
|
2281
|
-
if (
|
|
2391
|
+
function resultLines(block2, room, detailAll) {
|
|
2392
|
+
if (block2.status === "pending") return [style.grey("Running\u2026")];
|
|
2282
2393
|
const fit2 = (line) => detailAll ? wrap(line, room) : [truncate(line, room)];
|
|
2283
|
-
const outcome = unsettledOutcome(
|
|
2394
|
+
const outcome = unsettledOutcome(block2);
|
|
2284
2395
|
if (outcome) {
|
|
2285
|
-
const [reason, ...rest] = (0,
|
|
2396
|
+
const [reason, ...rest] = (0, import_core13.outputLines)(block2.output).map(sanitize);
|
|
2286
2397
|
const status = fit2(reason ? `${outcome.label}: ${reason}` : outcome.label).map(outcome.paint);
|
|
2287
2398
|
return detailAll ? [...status, ...rest.flatMap(fit2).map(style.grey)] : status;
|
|
2288
2399
|
}
|
|
2289
2400
|
if (detailAll) {
|
|
2290
|
-
const lines2 = (0,
|
|
2401
|
+
const lines2 = (0, import_core13.outputLines)(block2.output).map(sanitize);
|
|
2291
2402
|
const note = lines2.length > PREVIEW_LINES ? ["\u2026 (ctrl+o to collapse)"] : [];
|
|
2292
2403
|
return lines2.length > 0 ? [...lines2.flatMap(fit2), ...note].map(style.grey) : [style.grey("(no output)")];
|
|
2293
2404
|
}
|
|
2294
|
-
const { lines, hiddenLineCount } = (0,
|
|
2405
|
+
const { lines, hiddenLineCount } = (0, import_core13.outputPreview)(block2.output, PREVIEW_LINES);
|
|
2295
2406
|
if (lines.length === 0) return [style.grey("(no output)")];
|
|
2296
2407
|
const more = hiddenLineCount > 0 ? [`\u2026 +${countOf(hiddenLineCount, "line")} (ctrl+o to expand)`] : [];
|
|
2297
2408
|
return [...lines.map(sanitize), ...more].map((line) => style.grey(truncate(line, room)));
|
|
@@ -2304,8 +2415,8 @@ var DIFF_PAINT = {
|
|
|
2304
2415
|
gap: style.grey
|
|
2305
2416
|
};
|
|
2306
2417
|
var DIFF_SIGN = { added: "+", removed: "-", context: " ", gap: "" };
|
|
2307
|
-
function diffLines(
|
|
2308
|
-
const rows = (0,
|
|
2418
|
+
function diffLines(block2, diff, room, detailAll) {
|
|
2419
|
+
const rows = (0, import_core13.diffRows)(block2.output);
|
|
2309
2420
|
const gutter = Math.max(0, ...rows.map((row) => String(row.line ?? "").length));
|
|
2310
2421
|
const draw = (row) => {
|
|
2311
2422
|
const text = row.kind === "gap" ? `${" ".repeat(gutter)} \u22EE` : `${String(row.line ?? "").padStart(gutter)} ${DIFF_SIGN[row.kind]} ${sanitize(row.text)}`;
|
|
@@ -2314,14 +2425,14 @@ function diffLines(block, diff, room, detailAll) {
|
|
|
2314
2425
|
const shown = detailAll ? rows : rows.slice(0, DIFF_PREVIEW_ROWS);
|
|
2315
2426
|
const hidden = rows.length - shown.length;
|
|
2316
2427
|
const more = hidden > 0 ? [style.grey(`\u2026 +${countOf(hidden, "line")} (ctrl+o to expand)`)] : [];
|
|
2317
|
-
return [(0,
|
|
2428
|
+
return [(0, import_core13.diffSummary)(diff), ...shown.flatMap(draw), ...more];
|
|
2318
2429
|
}
|
|
2319
|
-
function toolLines(
|
|
2430
|
+
function toolLines(block2, cols, detailAll) {
|
|
2320
2431
|
const room = Math.max(1, cols - OUTPUT_INDENT.length);
|
|
2321
|
-
const diff =
|
|
2322
|
-
const args = detailAll && !diff ? argumentLines(
|
|
2323
|
-
const result = diff ? diffLines(
|
|
2324
|
-
return [...commandHeader(
|
|
2432
|
+
const diff = block2.diff && block2.status === "ok" ? block2.diff : null;
|
|
2433
|
+
const args = detailAll && !diff ? argumentLines(block2.args).flatMap((line) => wrap(line, room)).map((line) => OUTPUT_INDENT + style.grey(line)) : [];
|
|
2434
|
+
const result = diff ? diffLines(block2, diff, room, detailAll) : resultLines(block2, room, detailAll);
|
|
2435
|
+
return [...commandHeader(block2, cols, detailAll), ...args, ...underHeader(result)];
|
|
2325
2436
|
}
|
|
2326
2437
|
var SUBAGENT_PAINT = {
|
|
2327
2438
|
running: style.yellow,
|
|
@@ -2330,24 +2441,24 @@ var SUBAGENT_PAINT = {
|
|
|
2330
2441
|
stopped: style.grey
|
|
2331
2442
|
};
|
|
2332
2443
|
var CHILD_INDENT = " ";
|
|
2333
|
-
function subagentHeader(
|
|
2334
|
-
const brief = firstLine(
|
|
2335
|
-
const steps =
|
|
2336
|
-
const status =
|
|
2444
|
+
function subagentHeader(block2, cols) {
|
|
2445
|
+
const brief = firstLine(block2.brief);
|
|
2446
|
+
const steps = block2.children.filter((c) => c.type === "tool").length;
|
|
2447
|
+
const status = block2.status === "running" && steps > 0 ? `running \xB7 ${countOf(steps, "step")}` : block2.status;
|
|
2337
2448
|
const head = brief ? " Agent: " : " Agent";
|
|
2338
2449
|
const briefRoom = cols - width(`\u25C6${head} ${status}`);
|
|
2339
2450
|
if (briefRoom < 4) return truncate(`\u25C6${head}${brief} ${status}`, cols);
|
|
2340
|
-
const named = `${style.brand("\u25C6")}${head}${truncate(brief, briefRoom)} ${SUBAGENT_PAINT[
|
|
2341
|
-
const digest = firstLine(
|
|
2451
|
+
const named = `${style.brand("\u25C6")}${head}${truncate(brief, briefRoom)} ${SUBAGENT_PAINT[block2.status](status)}`;
|
|
2452
|
+
const digest = firstLine(block2.digest);
|
|
2342
2453
|
const digestRoom = cols - width(named) - width(" \xB7 ");
|
|
2343
2454
|
return digest && digestRoom >= 4 ? `${named}${style.grey(` \xB7 ${truncate(digest, digestRoom)}`)}` : named;
|
|
2344
2455
|
}
|
|
2345
|
-
function subagentLines(
|
|
2346
|
-
const header = subagentHeader(
|
|
2456
|
+
function subagentLines(block2, cols, detailAll) {
|
|
2457
|
+
const header = subagentHeader(block2, cols);
|
|
2347
2458
|
if (!detailAll) return [header];
|
|
2348
2459
|
const childCols = Math.max(1, cols - CHILD_INDENT.length);
|
|
2349
|
-
const children =
|
|
2350
|
-
const digest = sanitize(
|
|
2460
|
+
const children = block2.children.flatMap((child) => blockLines(child, childCols, true).map((line) => CHILD_INDENT + line));
|
|
2461
|
+
const digest = sanitize(block2.digest).trim();
|
|
2351
2462
|
const handedBack = digest ? underHeader(wrap(digest, Math.max(1, cols - OUTPUT_INDENT.length)).map(style.grey)) : [];
|
|
2352
2463
|
return [header, ...children, ...handedBack];
|
|
2353
2464
|
}
|
|
@@ -2372,24 +2483,39 @@ var DECIDED_BY = {
|
|
|
2372
2483
|
budget: "web-read budget",
|
|
2373
2484
|
unsupported: "not usable on this runner version"
|
|
2374
2485
|
};
|
|
2375
|
-
function approvalLine(
|
|
2376
|
-
const policy =
|
|
2377
|
-
const [mark, status, paint] =
|
|
2378
|
-
const note =
|
|
2379
|
-
const line = `${mark} ${status} \xB7 ${APPROVAL_KIND[
|
|
2486
|
+
function approvalLine(block2, cols) {
|
|
2487
|
+
const policy = block2.decidedBy && block2.decidedBy !== "asked" ? DECIDED_BY[block2.decidedBy] : void 0;
|
|
2488
|
+
const [mark, status, paint] = block2.status === "pending" ? ["?", "Waiting for you", style.yellow] : block2.status === "granted" ? ["\u2713", policy ? `Auto-approved (${policy})` : block2.forTask ? "Approved for this task" : "Approved", style.green] : block2.status === "withdrawn" ? ["\xB7", "Withdrawn", style.grey] : ["\u2298", policy ? `Auto-denied (${policy})` : "Denied", style.yellow];
|
|
2489
|
+
const note = block2.note ? ` \u2014 \u201C${firstLine(block2.note)}\u201D` : "";
|
|
2490
|
+
const line = `${mark} ${status} \xB7 ${APPROVAL_KIND[block2.kind]}: ${firstLine(block2.subject)}${note}`;
|
|
2380
2491
|
return `${paint(mark)}${truncate(line, cols).slice(mark.length)}`;
|
|
2381
2492
|
}
|
|
2382
|
-
function approvalKeysLine(
|
|
2383
|
-
const keys = ["ctrl-y allow", ...
|
|
2493
|
+
function approvalKeysLine(block2, cols) {
|
|
2494
|
+
const keys = ["ctrl-y allow", ...block2.allowForTask ? ["ctrl-t allow for task"] : [], "ctrl-g deny (composer text is the note)"];
|
|
2384
2495
|
return style.grey(truncate(` ${keys.join(" \xB7 ")}`, cols));
|
|
2385
2496
|
}
|
|
2386
2497
|
function checkpointCardLines(order, question, cols, approvalFirst) {
|
|
2387
2498
|
const room = Math.max(1, cols - 2);
|
|
2388
|
-
const
|
|
2499
|
+
const first = approvalFirst ? wrap("answer the tool request above first (ctrl-y / ctrl-g), then:", room) : [];
|
|
2389
2500
|
return [
|
|
2390
2501
|
truncate(`${style.accent("\u25C6")} ${style.bold(`Task ${order} asks`)}`, cols),
|
|
2391
2502
|
...wrap(sanitize(question).trim(), room).map((line) => ` ${line}`),
|
|
2392
|
-
...
|
|
2503
|
+
...first.map((line) => style.grey(` ${line}`)),
|
|
2504
|
+
...CHECKPOINT_CHOICES.flatMap(([key, text]) => choiceLines(key, text, room))
|
|
2505
|
+
];
|
|
2506
|
+
}
|
|
2507
|
+
var CHECKPOINT_CHOICES = [
|
|
2508
|
+
["enter", "reply: the task goes on with what you typed"],
|
|
2509
|
+
["ctrl-y", "approve as is"],
|
|
2510
|
+
["ctrl-g", "reject (with nothing typed, a plain no)"]
|
|
2511
|
+
];
|
|
2512
|
+
var CHOICE_KEY_WIDTH = 6;
|
|
2513
|
+
function choiceLines(key, text, room) {
|
|
2514
|
+
const hang = CHOICE_KEY_WIDTH + 2;
|
|
2515
|
+
const [head = "", ...rest] = wrap(text, Math.max(1, room - hang));
|
|
2516
|
+
return [
|
|
2517
|
+
` ${style.accent(style.bold(pad(key, CHOICE_KEY_WIDTH)))} ${style.grey(head)}`,
|
|
2518
|
+
...rest.map((line) => ` ${" ".repeat(hang)}${style.grey(line)}`)
|
|
2393
2519
|
];
|
|
2394
2520
|
}
|
|
2395
2521
|
var COMMAND_PAINT = {
|
|
@@ -2398,22 +2524,22 @@ var COMMAND_PAINT = {
|
|
|
2398
2524
|
failed: style.red,
|
|
2399
2525
|
stopped: style.grey
|
|
2400
2526
|
};
|
|
2401
|
-
function runnerCommandLines(
|
|
2402
|
-
const typed = sanitize(`/${
|
|
2403
|
-
const status = ` ${
|
|
2404
|
-
const head = `${style.accent("\u276F")} ${truncate(typed, Math.max(1, cols - 2 - width(status)))}${COMMAND_PAINT[
|
|
2527
|
+
function runnerCommandLines(block2, cols, detailAll) {
|
|
2528
|
+
const typed = sanitize(`/${block2.name}${block2.args ? ` ${block2.args}` : ""}`);
|
|
2529
|
+
const status = ` ${block2.status}`;
|
|
2530
|
+
const head = `${style.accent("\u276F")} ${truncate(typed, Math.max(1, cols - 2 - width(status)))}${COMMAND_PAINT[block2.status](status)}`;
|
|
2405
2531
|
const room = Math.max(1, cols - OUTPUT_INDENT.length);
|
|
2406
|
-
const printed = (0,
|
|
2532
|
+
const printed = (0, import_core13.outputLines)(block2.output).map(sanitize);
|
|
2407
2533
|
const shown = detailAll ? printed.flatMap((line) => wrap(line, room)) : printed.slice(0, PREVIEW_LINES).map((line) => truncate(line, room));
|
|
2408
2534
|
return [head, ...underHeader(shown.map(style.grey))];
|
|
2409
2535
|
}
|
|
2410
|
-
function compactionLine(
|
|
2411
|
-
const sizes =
|
|
2412
|
-
const text =
|
|
2536
|
+
function compactionLine(block2, cols) {
|
|
2537
|
+
const sizes = block2.preTokens !== void 0 && block2.postTokens !== void 0 ? ` \xB7 ${compactCount(block2.preTokens)} \u2192 ${compactCount(block2.postTokens)} tokens` : "";
|
|
2538
|
+
const text = block2.trigger === "auto" && !sizes ? "\u2261 Context compacted by the runner on its own" : `\u2261 Context compacted${sizes}`;
|
|
2413
2539
|
return style.grey(truncate(text, cols));
|
|
2414
2540
|
}
|
|
2415
|
-
function runnerLoadedLines(
|
|
2416
|
-
const of = (kind) =>
|
|
2541
|
+
function runnerLoadedLines(block2, cols, detailAll) {
|
|
2542
|
+
const of = (kind) => block2.commands.filter((c) => c.kind === kind).map((c) => `/${sanitize(c.name)}`);
|
|
2417
2543
|
const skills = of("skill");
|
|
2418
2544
|
const commands = of("command");
|
|
2419
2545
|
const builtins = of("builtin");
|
|
@@ -2421,66 +2547,66 @@ function runnerLoadedLines(block, cols, detailAll) {
|
|
|
2421
2547
|
countOf(skills.length, "skill"),
|
|
2422
2548
|
countOf(commands.length, "command"),
|
|
2423
2549
|
countOf(builtins.length, "built-in command"),
|
|
2424
|
-
countOf(
|
|
2550
|
+
countOf(block2.mcpServers.length, "MCP server")
|
|
2425
2551
|
];
|
|
2426
2552
|
const head = truncate(`\u25CF Runner loaded ${counts.join(", ")}`, cols);
|
|
2427
2553
|
const lines = [`${style.green("\u25CF")}${style.grey(head.slice(1))}`];
|
|
2428
2554
|
if (!detailAll) return lines;
|
|
2429
2555
|
const room = Math.max(1, cols - OUTPUT_INDENT.length);
|
|
2430
|
-
const
|
|
2431
|
-
const servers =
|
|
2556
|
+
const list2 = (label, names) => names.length > 0 ? wrap(`${label}: ${names.join(" ")}`, room) : [];
|
|
2557
|
+
const servers = block2.mcpServers.map((m) => `${sanitize(m.name)}${m.status ? ` (${sanitize(m.status)})` : ""}`);
|
|
2432
2558
|
return [
|
|
2433
2559
|
...lines,
|
|
2434
|
-
...[...
|
|
2560
|
+
...[...list2("skills", skills), ...list2("commands", commands), ...list2("built-in", builtins), ...servers.length > 0 ? wrap(`MCP servers: ${servers.join(", ")}`, room) : []].map((line) => OUTPUT_INDENT + style.grey(line))
|
|
2435
2561
|
];
|
|
2436
2562
|
}
|
|
2437
|
-
function planLine(
|
|
2438
|
-
const count =
|
|
2439
|
-
const text =
|
|
2563
|
+
function planLine(block2, cols) {
|
|
2564
|
+
const count = block2.taskCount === void 0 ? "" : ` (${countOf(block2.taskCount, "task")})`;
|
|
2565
|
+
const text = block2.status === "building" ? "Building plan\u2026" : `Plan ${block2.status}${count}`;
|
|
2440
2566
|
return `${style.brand("\u25C7")}${truncate(`\u25C7 ${text}`, cols).slice(1)}`;
|
|
2441
2567
|
}
|
|
2442
|
-
function blockLines(
|
|
2443
|
-
switch (
|
|
2568
|
+
function blockLines(block2, cols, detailAll) {
|
|
2569
|
+
switch (block2.type) {
|
|
2444
2570
|
case "message":
|
|
2445
|
-
return messageLines(
|
|
2571
|
+
return messageLines(block2, cols);
|
|
2446
2572
|
case "thinking":
|
|
2447
|
-
return thinkingLines(
|
|
2573
|
+
return thinkingLines(block2, cols, detailAll);
|
|
2448
2574
|
case "tool":
|
|
2449
|
-
return toolLines(
|
|
2575
|
+
return toolLines(block2, cols, detailAll);
|
|
2450
2576
|
case "subagent":
|
|
2451
|
-
return subagentLines(
|
|
2577
|
+
return subagentLines(block2, cols, detailAll);
|
|
2452
2578
|
case "approval":
|
|
2453
|
-
return [approvalLine(
|
|
2579
|
+
return [approvalLine(block2, cols)];
|
|
2454
2580
|
case "plan":
|
|
2455
|
-
return [planLine(
|
|
2581
|
+
return [planLine(block2, cols)];
|
|
2456
2582
|
case "skill_load":
|
|
2457
|
-
return [skillLoadLine(
|
|
2583
|
+
return [skillLoadLine(block2, cols)];
|
|
2458
2584
|
case "command":
|
|
2459
|
-
return runnerCommandLines(
|
|
2585
|
+
return runnerCommandLines(block2, cols, detailAll);
|
|
2460
2586
|
case "compaction":
|
|
2461
|
-
return [compactionLine(
|
|
2587
|
+
return [compactionLine(block2, cols)];
|
|
2462
2588
|
case "runner_loaded":
|
|
2463
|
-
return runnerLoadedLines(
|
|
2589
|
+
return runnerLoadedLines(block2, cols, detailAll);
|
|
2464
2590
|
// Pinned under the pane rather than drawn in it — see `tokenLine`.
|
|
2465
2591
|
case "usage":
|
|
2466
2592
|
return [];
|
|
2467
2593
|
}
|
|
2468
2594
|
}
|
|
2469
2595
|
var drawnBlocks = /* @__PURE__ */ new WeakMap();
|
|
2470
|
-
function drawn(
|
|
2471
|
-
const cached = drawnBlocks.get(
|
|
2596
|
+
function drawn(block2, cols, detailAll) {
|
|
2597
|
+
const cached = drawnBlocks.get(block2);
|
|
2472
2598
|
if (cached && cached.cols === cols && cached.detailAll === detailAll) return cached.lines;
|
|
2473
|
-
const lines = blockLines(
|
|
2474
|
-
drawnBlocks.set(
|
|
2599
|
+
const lines = blockLines(block2, cols, detailAll);
|
|
2600
|
+
drawnBlocks.set(block2, { cols, detailAll, lines });
|
|
2475
2601
|
return lines;
|
|
2476
2602
|
}
|
|
2477
|
-
function conversationLines(
|
|
2603
|
+
function conversationLines(blocks2, cols, detailAll, answering) {
|
|
2478
2604
|
const lines = [];
|
|
2479
|
-
for (const [i,
|
|
2480
|
-
if (
|
|
2481
|
-
lines.push(...drawn(
|
|
2482
|
-
if (
|
|
2483
|
-
if (
|
|
2605
|
+
for (const [i, block2] of blocks2.entries()) {
|
|
2606
|
+
if (block2.type === "usage") continue;
|
|
2607
|
+
lines.push(...drawn(block2, cols, detailAll));
|
|
2608
|
+
if (block2 === answering) lines.push(approvalKeysLine(block2, cols));
|
|
2609
|
+
if (blocks2[i + 1]?.type !== "skill_load") lines.push("");
|
|
2484
2610
|
}
|
|
2485
2611
|
return lines;
|
|
2486
2612
|
}
|
|
@@ -2494,8 +2620,8 @@ function formatCost(currency, amount) {
|
|
|
2494
2620
|
const value = `${whole}.${frac.padEnd(2, "0")}`;
|
|
2495
2621
|
return currency.toLowerCase() === "usd" ? `$${value}` : `${value} ${currency.toUpperCase()}`;
|
|
2496
2622
|
}
|
|
2497
|
-
function tokenLine(
|
|
2498
|
-
const usage =
|
|
2623
|
+
function tokenLine(blocks2, cols) {
|
|
2624
|
+
const usage = blocks2[blocks2.length - 1];
|
|
2499
2625
|
if (usage?.type !== "usage") return null;
|
|
2500
2626
|
const parts = usageMeasures(usage.totals, false);
|
|
2501
2627
|
if (usage.model && !usage.contextFill) parts.push("ctx unknown");
|
|
@@ -2521,7 +2647,7 @@ function taskUsageText(usage) {
|
|
|
2521
2647
|
|
|
2522
2648
|
// src/commands/status.ts
|
|
2523
2649
|
var import_fs4 = require("fs");
|
|
2524
|
-
var
|
|
2650
|
+
var import_core14 = require("@ordewell/core");
|
|
2525
2651
|
async function handleStatus(subArgs, injectedApi) {
|
|
2526
2652
|
const sessionId = flag(subArgs, "--session-id");
|
|
2527
2653
|
const workspace = flag(subArgs, "--workspace") || process.cwd();
|
|
@@ -2576,8 +2702,8 @@ function emitJson(payload, outputPath) {
|
|
|
2576
2702
|
}
|
|
2577
2703
|
function printOneSession(sessionId, meta, plan) {
|
|
2578
2704
|
const allTasks = allTasksOf(plan);
|
|
2579
|
-
const everyTask = (0,
|
|
2580
|
-
const blocked = (0,
|
|
2705
|
+
const everyTask = (0, import_core14.flattenTasks)(allTasks);
|
|
2706
|
+
const blocked = (0, import_core14.blockingFailures)(everyTask.map((t) => ({ ...t, subtasks: [], dependencies: t.dependencies ?? [] })));
|
|
2581
2707
|
const count = (status) => everyTask.filter((t) => t.status === status || status === "blocked" && blocked.has(t.id)).length;
|
|
2582
2708
|
console.log(`Session: ${sessionId}`);
|
|
2583
2709
|
console.log(`Goal: ${meta.goal}`);
|
|
@@ -2585,25 +2711,25 @@ function printOneSession(sessionId, meta, plan) {
|
|
|
2585
2711
|
console.log(`Phase: ${plan?.phase || "unknown"} | Created: ${meta.createdAt}`);
|
|
2586
2712
|
console.log(`Tasks: ${everyTask.length} total | ${count("completed")} done | ${count("failed")} failed | ${count("in_progress")} running | ${count("blocked")} blocked | ${count("skipped")} skipped
|
|
2587
2713
|
`);
|
|
2588
|
-
const usage = (0,
|
|
2714
|
+
const usage = (0, import_core14.planUsage)(allTasks);
|
|
2589
2715
|
if (usage.attempts) console.log(`Tasks total: ${taskUsageText(usage)}`);
|
|
2590
2716
|
for (const t of allTasks) {
|
|
2591
2717
|
const icon = iconFor(blocked.has(t.id) ? "blocked" : t.status);
|
|
2592
2718
|
const model = t.assignedModel ? ` (${t.assignedModel.modelLabel})` : "";
|
|
2593
2719
|
const shortId = (t.id ?? "").slice(-8);
|
|
2594
|
-
console.log(` ${(0,
|
|
2595
|
-
const row = (0,
|
|
2596
|
-
if (row.blockedBy) console.log(` ${(0,
|
|
2597
|
-
if (row.status === "skipped") console.log(` ${(0,
|
|
2720
|
+
console.log(` ${(0, import_core14.taskOrderLabel)(t).padStart(2)}. ${icon} [${shortId}] ${t.title}${model}`);
|
|
2721
|
+
const row = (0, import_core14.taskRowView)({ ...t, dependencies: t.dependencies ?? [] }, { tasks: allTasks });
|
|
2722
|
+
if (row.blockedBy) console.log(` ${(0, import_core14.blockedByLabel)(row.blockedBy)}`);
|
|
2723
|
+
if (row.status === "skipped") console.log(` ${(0, import_core14.skippedLabel)(row.skipReason)}`);
|
|
2598
2724
|
if (row.usage) console.log(` ${taskUsageText(row.usage)}`);
|
|
2599
2725
|
for (const sub of t.subtasks || []) {
|
|
2600
2726
|
const subIcon = iconFor(blocked.has(sub.id) ? "blocked" : sub.status);
|
|
2601
2727
|
const subModel = sub.assignedModel ? ` (${sub.assignedModel.modelLabel})` : "";
|
|
2602
2728
|
const subShortId = (sub.id ?? "").slice(-8);
|
|
2603
|
-
console.log(` ${(0,
|
|
2604
|
-
const subRow = (0,
|
|
2605
|
-
if (subRow.blockedBy) console.log(` ${(0,
|
|
2606
|
-
if (subRow.status === "skipped") console.log(` ${(0,
|
|
2729
|
+
console.log(` ${(0, import_core14.taskOrderLabel)(sub, t)}. ${subIcon} [${subShortId}] ${sub.title}${subModel}`);
|
|
2730
|
+
const subRow = (0, import_core14.taskRowView)({ ...sub, dependencies: sub.dependencies ?? [] }, { parent: t, tasks: allTasks });
|
|
2731
|
+
if (subRow.blockedBy) console.log(` ${(0, import_core14.blockedByLabel)(subRow.blockedBy)}`);
|
|
2732
|
+
if (subRow.status === "skipped") console.log(` ${(0, import_core14.skippedLabel)(subRow.skipReason)}`);
|
|
2607
2733
|
if (subRow.usage) console.log(` ${taskUsageText(subRow.usage)}`);
|
|
2608
2734
|
}
|
|
2609
2735
|
}
|
|
@@ -2656,10 +2782,10 @@ async function handleWeb(subArgs) {
|
|
|
2656
2782
|
}
|
|
2657
2783
|
|
|
2658
2784
|
// src/commands/models.ts
|
|
2659
|
-
var
|
|
2785
|
+
var import_core16 = require("@ordewell/core");
|
|
2660
2786
|
|
|
2661
2787
|
// src/commands/model.ts
|
|
2662
|
-
var
|
|
2788
|
+
var import_core15 = require("@ordewell/core");
|
|
2663
2789
|
var USAGE = "Usage: ordewell model [show | set <model-id>]";
|
|
2664
2790
|
async function handleModel(subArgs, injectedApi) {
|
|
2665
2791
|
const [action, modelId] = positionals(subArgs);
|
|
@@ -2674,7 +2800,7 @@ async function handleModel(subArgs, injectedApi) {
|
|
|
2674
2800
|
if (!modelId) fail(USAGE);
|
|
2675
2801
|
const settings = await api.getSettings();
|
|
2676
2802
|
const provider = typeof settings.aiProvider === "string" ? settings.aiProvider : "";
|
|
2677
|
-
const runner = (0,
|
|
2803
|
+
const runner = (0, import_core15.runnerForProvider)(provider);
|
|
2678
2804
|
if (runner) {
|
|
2679
2805
|
const known = (await fetchCatalog(api)).models.filter((m) => m.runners?.includes(runner));
|
|
2680
2806
|
if (known.length > 0 && !known.some((m) => m.id === modelId)) {
|
|
@@ -2697,7 +2823,7 @@ async function showModels(api) {
|
|
|
2697
2823
|
const [settings, catalog] = await Promise.all([api.getSettings(), fetchCatalog(api)]);
|
|
2698
2824
|
const provider = typeof settings.aiProvider === "string" ? settings.aiProvider : "";
|
|
2699
2825
|
const current = typeof settings.orchestratorModel === "string" ? settings.orchestratorModel : "";
|
|
2700
|
-
const runner = (0,
|
|
2826
|
+
const runner = (0, import_core15.runnerForProvider)(provider);
|
|
2701
2827
|
const options = runner ? catalog.models.filter((m) => m.runners?.includes(runner)) : catalog.orchestratorModels;
|
|
2702
2828
|
console.log(`
|
|
2703
2829
|
Planner model: ${current || "(backend default)"}`);
|
|
@@ -2731,8 +2857,8 @@ async function handleModels(subArgs) {
|
|
|
2731
2857
|
const rest = subArgs.filter((_, i) => i !== setIdx && i !== setIdx + 1);
|
|
2732
2858
|
return handleModel(["set", subArgs[setIdx + 1], ...rest]);
|
|
2733
2859
|
}
|
|
2734
|
-
const config = new
|
|
2735
|
-
const providers = (0,
|
|
2860
|
+
const config = new import_core16.EnvConfig();
|
|
2861
|
+
const providers = (0, import_core16.configuredProviders)(config);
|
|
2736
2862
|
if (providers.length === 0) {
|
|
2737
2863
|
console.error("No providers configured. Set an API key for a provider, e.g.:");
|
|
2738
2864
|
console.error(" OPENROUTER_API_KEY=... (OpenRouter)");
|
|
@@ -2741,19 +2867,19 @@ async function handleModels(subArgs) {
|
|
|
2741
2867
|
console.error(" OPENAI_COMPATIBLE_BASE_URL=... (self-hosted / OpenAI-compatible)");
|
|
2742
2868
|
process.exit(1);
|
|
2743
2869
|
}
|
|
2744
|
-
const { apiKeys, baseUrls } = (0,
|
|
2870
|
+
const { apiKeys, baseUrls } = (0, import_core16.collectProviderCredentials)(config);
|
|
2745
2871
|
let models;
|
|
2746
2872
|
let errors;
|
|
2747
2873
|
try {
|
|
2748
|
-
const result = await (0,
|
|
2749
|
-
models = (0,
|
|
2874
|
+
const result = await (0, import_core16.fetchAllProviderModels)({ apiKeys, baseUrls });
|
|
2875
|
+
models = (0, import_core16.toOrchestratorOptions)(result.models, import_core16.ORCHESTRATOR_SHORTCUTS);
|
|
2750
2876
|
errors = result.errors;
|
|
2751
2877
|
} catch (err) {
|
|
2752
2878
|
console.error(`Failed to fetch models: ${err instanceof Error ? err.message : String(err)}`);
|
|
2753
2879
|
process.exit(1);
|
|
2754
2880
|
return;
|
|
2755
2881
|
}
|
|
2756
|
-
const providerLabel = (p) => (0,
|
|
2882
|
+
const providerLabel = (p) => (0, import_core16.getProviderMeta)(p)?.label ?? p;
|
|
2757
2883
|
console.log(
|
|
2758
2884
|
`
|
|
2759
2885
|
Available models (${models.length}) across ${providers.length} configured provider(s):`
|
|
@@ -2793,7 +2919,7 @@ ${providerLabel(provider)}`);
|
|
|
2793
2919
|
|
|
2794
2920
|
// src/commands/setup.ts
|
|
2795
2921
|
var import_fs6 = require("fs");
|
|
2796
|
-
var
|
|
2922
|
+
var import_core17 = require("@ordewell/core");
|
|
2797
2923
|
function handleSetup(subArgs) {
|
|
2798
2924
|
const modelIdx = subArgs.indexOf("--model");
|
|
2799
2925
|
const chosenModel = modelIdx !== -1 ? subArgs[modelIdx + 1] : null;
|
|
@@ -2838,7 +2964,7 @@ function handleSetup(subArgs) {
|
|
|
2838
2964
|
|
|
2839
2965
|
# Or plan with a coding agent you already have installed \u2014 no API key needed,
|
|
2840
2966
|
# it uses that agent's own subscription. Set the model to one of its own.
|
|
2841
|
-
# AI_PROVIDER
|
|
2967
|
+
# AI_PROVIDER=${runnerIdChoice()}
|
|
2842
2968
|
# ORCHESTRATOR_MODEL=haiku
|
|
2843
2969
|
# ORDEWELL_PLANNER_EFFORT=low
|
|
2844
2970
|
|
|
@@ -2865,13 +2991,13 @@ function handleSetup(subArgs) {
|
|
|
2865
2991
|
# STEPFUN_API_KEY=...
|
|
2866
2992
|
# SILICONFLOW_API_KEY=...
|
|
2867
2993
|
`;
|
|
2868
|
-
(0,
|
|
2994
|
+
(0, import_core17.writePrivateFile)(envFile, content);
|
|
2869
2995
|
console.log(`Wrote: ${envFile}`);
|
|
2870
2996
|
console.log("Review and edit the file, then run: ordewell tui");
|
|
2871
2997
|
}
|
|
2872
2998
|
|
|
2873
2999
|
// src/commands/skills.ts
|
|
2874
|
-
var
|
|
3000
|
+
var import_core18 = require("@ordewell/core");
|
|
2875
3001
|
var import_path5 = require("path");
|
|
2876
3002
|
function invocation(skill) {
|
|
2877
3003
|
if (skill.userInvocable && skill.modelInvocable) return "both";
|
|
@@ -2884,22 +3010,22 @@ function handleSkills(subArgs) {
|
|
|
2884
3010
|
fail("Usage: ordewell skills [--workspace /path] [--json]");
|
|
2885
3011
|
}
|
|
2886
3012
|
const workspace = (0, import_path5.resolve)(flag(subArgs, "--workspace") || process.cwd());
|
|
2887
|
-
const catalog = (0,
|
|
3013
|
+
const catalog = (0, import_core18.createSkillsService)(workspace, new import_core18.EnvConfig().workspaceRepos).readCatalog();
|
|
2888
3014
|
const skills = catalog.skills.map((skill) => ({
|
|
2889
3015
|
name: skill.name,
|
|
2890
3016
|
scope: skill.source,
|
|
2891
3017
|
appliesTo: skill.appliesTo,
|
|
2892
3018
|
invocation: invocation(skill),
|
|
2893
|
-
path: (0,
|
|
3019
|
+
path: (0, import_core18.abbreviateHome)(skill.path)
|
|
2894
3020
|
}));
|
|
2895
3021
|
const shadowed = catalog.shadowed.map(({ skill, shadowedBy }) => ({
|
|
2896
3022
|
name: skill.name,
|
|
2897
|
-
path: (0,
|
|
2898
|
-
shadowedBy: { scope: shadowedBy.source, path: (0,
|
|
3023
|
+
path: (0, import_core18.abbreviateHome)(skill.path),
|
|
3024
|
+
shadowedBy: { scope: shadowedBy.source, path: (0, import_core18.abbreviateHome)(shadowedBy.path) }
|
|
2899
3025
|
}));
|
|
2900
3026
|
const invalid = catalog.invalid.map((skill) => ({
|
|
2901
3027
|
name: skill.name,
|
|
2902
|
-
path: (0,
|
|
3028
|
+
path: (0, import_core18.abbreviateHome)(skill.path),
|
|
2903
3029
|
reason: skill.reason
|
|
2904
3030
|
}));
|
|
2905
3031
|
if (hasFlag(subArgs, "--json")) {
|
|
@@ -3014,7 +3140,7 @@ async function handleShow(args, api) {
|
|
|
3014
3140
|
}
|
|
3015
3141
|
|
|
3016
3142
|
// src/commands/task-control.ts
|
|
3017
|
-
var
|
|
3143
|
+
var import_core19 = require("@ordewell/core");
|
|
3018
3144
|
var PAST_TENSE = {
|
|
3019
3145
|
run: "Task started.",
|
|
3020
3146
|
"force-start": "Task force-started.",
|
|
@@ -3057,7 +3183,7 @@ async function confirmPastGate(subArgs, api, sessionId, taskId, confirm2) {
|
|
|
3057
3183
|
if (hasFlag(subArgs, "--yes")) return;
|
|
3058
3184
|
const unmerged = await api.getMergeGate(sessionId, taskId).catch(() => []);
|
|
3059
3185
|
if (unmerged.length === 0) return;
|
|
3060
|
-
const question = `${(0,
|
|
3186
|
+
const question = `${(0, import_core19.pastGateConfirmation)(unmerged.map((d) => (0, import_core19.titledTaskRef)(d)))} Start it anyway?`;
|
|
3061
3187
|
if (!await confirm2(question)) fail("Not started \u2014 nothing was changed. Pass --yes to start it without a prompt.");
|
|
3062
3188
|
}
|
|
3063
3189
|
function makeHandler(action, command = action) {
|
|
@@ -3370,24 +3496,24 @@ async function handleRewind(subArgs, injectedApi) {
|
|
|
3370
3496
|
}
|
|
3371
3497
|
|
|
3372
3498
|
// src/tui/transcript.ts
|
|
3373
|
-
var
|
|
3499
|
+
var import_core20 = require("@ordewell/core");
|
|
3374
3500
|
function show(state, { view: conversation, gate: turnGate }) {
|
|
3375
3501
|
const gated = turnGate === state.turnGate ? state : { ...state, turnGate };
|
|
3376
3502
|
if (conversation === state.conversation) return gated;
|
|
3377
3503
|
return { ...gated, conversation };
|
|
3378
3504
|
}
|
|
3379
3505
|
function fold(state, input) {
|
|
3380
|
-
return show(state, { view: (0,
|
|
3506
|
+
return show(state, { view: (0, import_core20.reduceConversation)(state.conversation, input), gate: state.turnGate });
|
|
3381
3507
|
}
|
|
3382
3508
|
function say(state, role, text) {
|
|
3383
3509
|
const said = fold(state, { type: "local_entry", role, text });
|
|
3384
3510
|
return said.conversation.nextId > state.conversation.nextId ? { ...said, scroll: 0 } : said;
|
|
3385
3511
|
}
|
|
3386
3512
|
function hear(state, message) {
|
|
3387
|
-
return show(state, (0,
|
|
3513
|
+
return show(state, (0, import_core20.followTurn)(state.conversation, state.turnGate, message));
|
|
3388
3514
|
}
|
|
3389
3515
|
function cutTurn(state) {
|
|
3390
|
-
return show(state, (0,
|
|
3516
|
+
return show(state, (0, import_core20.stopTurn)(state.conversation, state.turnGate));
|
|
3391
3517
|
}
|
|
3392
3518
|
function wiped(view) {
|
|
3393
3519
|
return { ...view, blocks: view.blocks.filter((b) => b.type === "usage") };
|
|
@@ -3636,7 +3762,7 @@ async function handleHandoff(subArgs, injectedApi, confirm2 = askYesNo) {
|
|
|
3636
3762
|
}
|
|
3637
3763
|
|
|
3638
3764
|
// src/commands/planner.ts
|
|
3639
|
-
var
|
|
3765
|
+
var import_core21 = require("@ordewell/core");
|
|
3640
3766
|
|
|
3641
3767
|
// src/plannerModelSwitch.ts
|
|
3642
3768
|
function plannerSwitchRecall(settings) {
|
|
@@ -3646,7 +3772,6 @@ function plannerSwitchRecall(settings) {
|
|
|
3646
3772
|
}
|
|
3647
3773
|
|
|
3648
3774
|
// src/commands/planner.ts
|
|
3649
|
-
var isAiProvider = (id) => Object.hasOwn(import_core19.ALL_PROVIDERS, id);
|
|
3650
3775
|
async function handlePlanner(subArgs, injectedApi) {
|
|
3651
3776
|
const api = await connect(subArgs, injectedApi);
|
|
3652
3777
|
const [wanted] = positionals(subArgs);
|
|
@@ -3655,19 +3780,19 @@ async function handlePlanner(subArgs, injectedApi) {
|
|
|
3655
3780
|
return;
|
|
3656
3781
|
}
|
|
3657
3782
|
const provider = wanted.toLowerCase();
|
|
3658
|
-
|
|
3783
|
+
const meta = (0, import_core21.getProviderMeta)(provider);
|
|
3784
|
+
if (!meta) {
|
|
3659
3785
|
fail(`Unknown planner: ${provider}`, "Run `ordewell planner` with no arguments to see the list.");
|
|
3660
3786
|
}
|
|
3661
3787
|
const settings = await persistEnv(api, { AI_PROVIDER: provider });
|
|
3662
3788
|
const recall2 = plannerSwitchRecall(settings);
|
|
3663
3789
|
writeEnv({ ORCHESTRATOR_MODEL: recall2.model, ORDEWELL_PLANNER_EFFORT: recall2.effort });
|
|
3664
|
-
const meta = import_core19.ALL_PROVIDERS[provider];
|
|
3665
3790
|
const catalog = await fetchCatalog(api);
|
|
3666
3791
|
console.log(
|
|
3667
|
-
(0,
|
|
3792
|
+
(0, import_core21.isCliProvider)(provider) ? `Planning with ${meta.label} \u2014 no API key needed, it uses that agent's own subscription.` : `Planner set to ${meta.label}.`
|
|
3668
3793
|
);
|
|
3669
3794
|
console.log(plannerModelLine(recall2));
|
|
3670
|
-
if (
|
|
3795
|
+
if ((0, import_core21.isApiProvider)(provider) && !catalog.providers.includes(provider)) {
|
|
3671
3796
|
console.log(` No ${meta.apiKeyEnvVar} configured yet \u2014 set one with \`ordewell key set ${provider} <key>\`.`);
|
|
3672
3797
|
}
|
|
3673
3798
|
}
|
|
@@ -3685,15 +3810,15 @@ async function showPlanners(api) {
|
|
|
3685
3810
|
const [settings, catalog] = await Promise.all([api.getSettings(), fetchCatalog(api)]);
|
|
3686
3811
|
const current = typeof settings.aiProvider === "string" ? settings.aiProvider : "";
|
|
3687
3812
|
console.log("\nCoding agents (no API key \u2014 they use their own subscription)");
|
|
3688
|
-
for (const id of
|
|
3689
|
-
const runner = (0,
|
|
3813
|
+
for (const id of import_core21.CLI_PROVIDERS) {
|
|
3814
|
+
const runner = (0, import_core21.runnerForProvider)(id);
|
|
3690
3815
|
const discovered = runner ? catalog.models.some((m) => m.runners?.includes(runner)) : false;
|
|
3691
|
-
console.log(` ${marker(id === current)} ${id.padEnd(14)} ${
|
|
3816
|
+
console.log(` ${marker(id === current)} ${id.padEnd(14)} ${(0, import_core21.getProviderMeta)(id)?.label ?? id}${discovered ? "" : " (not detected)"}`);
|
|
3692
3817
|
}
|
|
3693
3818
|
console.log("\nAPI providers");
|
|
3694
|
-
for (const id of
|
|
3819
|
+
for (const id of import_core21.PROVIDER_PRIORITY) {
|
|
3695
3820
|
const configured = catalog.providers.includes(id);
|
|
3696
|
-
const meta =
|
|
3821
|
+
const meta = (0, import_core21.getProviderMeta)(id);
|
|
3697
3822
|
console.log(` ${marker(id === current)} ${id.padEnd(14)} ${meta.label}${configured ? "" : ` (no ${meta.apiKeyEnvVar})`}`);
|
|
3698
3823
|
}
|
|
3699
3824
|
console.log(`
|
|
@@ -3710,11 +3835,11 @@ async function handlePlannerEffort(subArgs, injectedApi) {
|
|
|
3710
3835
|
const provider = typeof settings.aiProvider === "string" ? settings.aiProvider : "";
|
|
3711
3836
|
const modelId = typeof settings.orchestratorModel === "string" ? settings.orchestratorModel : "";
|
|
3712
3837
|
const currentEffort = typeof settings.plannerThinkingEffort === "string" ? settings.plannerThinkingEffort : "";
|
|
3713
|
-
const runner =
|
|
3838
|
+
const runner = (0, import_core21.runnerForProvider)(provider);
|
|
3714
3839
|
if (!runner) {
|
|
3715
3840
|
fail(
|
|
3716
3841
|
"Thinking effort applies to a coding-agent planner.",
|
|
3717
|
-
|
|
3842
|
+
`Switch with: ordewell planner ${runnerIdChoice()}`
|
|
3718
3843
|
);
|
|
3719
3844
|
}
|
|
3720
3845
|
const model = catalog.models.find((m) => m.id === modelId && m.runners?.includes(runner));
|
|
@@ -3750,7 +3875,7 @@ async function handlePlannerEffort(subArgs, injectedApi) {
|
|
|
3750
3875
|
}
|
|
3751
3876
|
|
|
3752
3877
|
// src/commands/parallel.ts
|
|
3753
|
-
var
|
|
3878
|
+
var import_core22 = require("@ordewell/core");
|
|
3754
3879
|
var USAGE5 = "Usage: ordewell parallel [<number of tasks, 1 or more>]";
|
|
3755
3880
|
async function handleParallel(subArgs, injectedApi) {
|
|
3756
3881
|
const [wanted] = positionals(subArgs);
|
|
@@ -3760,14 +3885,14 @@ async function handleParallel(subArgs, injectedApi) {
|
|
|
3760
3885
|
console.log(`Up to ${String(settings.maxParallel ?? "?")} AI tasks run at once. Change with: ordewell parallel <n>`);
|
|
3761
3886
|
return;
|
|
3762
3887
|
}
|
|
3763
|
-
const limit = (0,
|
|
3888
|
+
const limit = (0, import_core22.parseMaxParallel)(wanted);
|
|
3764
3889
|
if (limit === null) fail(`"${wanted}" is not a number of tasks (1 or more).`, USAGE5);
|
|
3765
3890
|
await persistEnv(api, { ORDEWELL_MAX_PARALLEL: String(limit) });
|
|
3766
3891
|
console.log(`Up to ${limit} AI task${limit === 1 ? "" : "s"} now run at once.`);
|
|
3767
3892
|
}
|
|
3768
3893
|
|
|
3769
3894
|
// src/commands/runSettings.ts
|
|
3770
|
-
var
|
|
3895
|
+
var import_core23 = require("@ordewell/core");
|
|
3771
3896
|
var SUPERVISOR_USAGE = "Usage: ordewell supervisor [off|watch|act] \xB7 ordewell supervisor retries <n> \xB7 ordewell supervisor reads <n>";
|
|
3772
3897
|
var AUTOMERGE_USAGE = "Usage: ordewell automerge [on|off]";
|
|
3773
3898
|
var AUTORUN_USAGE = "Usage: ordewell autorun [on|off]";
|
|
@@ -3778,28 +3903,28 @@ async function handleSupervisor(subArgs, injectedApi) {
|
|
|
3778
3903
|
const [arg, value] = positionals(subArgs);
|
|
3779
3904
|
let changes = null;
|
|
3780
3905
|
if (arg === "off" || arg === "watch" || arg === "act") changes = { supervisorLevel: arg };
|
|
3781
|
-
else if (arg === "retries") changes = maybe((0,
|
|
3782
|
-
else if (arg === "reads") changes = maybe((0,
|
|
3906
|
+
else if (arg === "retries") changes = maybe((0, import_core23.parseCount)(value, 0), (n) => ({ supervisorRetryLimit: n }));
|
|
3907
|
+
else if (arg === "reads") changes = maybe((0, import_core23.parseCount)(value, 1), (n) => ({ wakeUpReadBudget: n }));
|
|
3783
3908
|
if (arg !== void 0 && changes === null) fail(SUPERVISOR_USAGE);
|
|
3784
3909
|
const api = await connect(subArgs, injectedApi);
|
|
3785
3910
|
if (!changes) {
|
|
3786
|
-
console.log((0,
|
|
3911
|
+
console.log((0, import_core23.supervisorSummary)((await api.getSettings()).run));
|
|
3787
3912
|
console.log(` ${SUPERVISOR_USAGE}`);
|
|
3788
3913
|
return;
|
|
3789
3914
|
}
|
|
3790
3915
|
await save(api, changes);
|
|
3791
|
-
if (changes.supervisorLevel) console.log(`Supervisor: ${
|
|
3792
|
-
if (changes.supervisorLevel === "act") console.log(
|
|
3916
|
+
if (changes.supervisorLevel) console.log(`Supervisor: ${import_core23.SUPERVISOR_LEVEL_LABEL[changes.supervisorLevel]}, from each session's next run.`);
|
|
3917
|
+
if (changes.supervisorLevel === "act") console.log(import_core23.ACT_RISK);
|
|
3793
3918
|
if (changes.supervisorRetryLimit !== void 0) console.log(`Supervisor retry limit: ${changes.supervisorRetryLimit} per task.`);
|
|
3794
3919
|
if (changes.wakeUpReadBudget !== void 0) console.log(`Wake-up read budget: ${changes.wakeUpReadBudget} reads.`);
|
|
3795
3920
|
}
|
|
3796
3921
|
async function handleAutomerge(subArgs, injectedApi) {
|
|
3797
3922
|
const [arg] = positionals(subArgs);
|
|
3798
|
-
const enabled = arg === void 0 ? null : (0,
|
|
3923
|
+
const enabled = arg === void 0 ? null : (0, import_core23.parseSwitch)(arg);
|
|
3799
3924
|
if (arg !== void 0 && enabled === null) fail(AUTOMERGE_USAGE);
|
|
3800
3925
|
const api = await connect(subArgs, injectedApi);
|
|
3801
3926
|
if (enabled === null) {
|
|
3802
|
-
console.log((0,
|
|
3927
|
+
console.log((0, import_core23.automergeSummary)((await api.getSettings()).run));
|
|
3803
3928
|
console.log(` ${AUTOMERGE_USAGE}`);
|
|
3804
3929
|
return;
|
|
3805
3930
|
}
|
|
@@ -3808,24 +3933,24 @@ async function handleAutomerge(subArgs, injectedApi) {
|
|
|
3808
3933
|
}
|
|
3809
3934
|
async function handleAutorun(subArgs, injectedApi) {
|
|
3810
3935
|
const [arg] = positionals(subArgs);
|
|
3811
|
-
const enabled = arg === void 0 ? null : (0,
|
|
3936
|
+
const enabled = arg === void 0 ? null : (0, import_core23.parseSwitch)(arg);
|
|
3812
3937
|
if (arg !== void 0 && enabled === null) fail(AUTORUN_USAGE);
|
|
3813
3938
|
const api = await connect(subArgs, injectedApi);
|
|
3814
3939
|
if (enabled === null) {
|
|
3815
|
-
console.log((0,
|
|
3940
|
+
console.log((0, import_core23.autorunSummary)((await api.getSettings()).run));
|
|
3816
3941
|
console.log(` ${AUTORUN_USAGE}`);
|
|
3817
3942
|
return;
|
|
3818
3943
|
}
|
|
3819
3944
|
await save(api, { autorun: enabled });
|
|
3820
3945
|
console.log(`Autorun: ${enabled ? "on \u2014 each plan the planner submits starts at once" : "off \u2014 plans wait for your review"}.`);
|
|
3821
|
-
if (enabled) console.log(
|
|
3946
|
+
if (enabled) console.log(import_core23.AUTORUN_RISK);
|
|
3822
3947
|
}
|
|
3823
3948
|
function maybe(n, wrap2) {
|
|
3824
3949
|
return n === null ? null : wrap2(n);
|
|
3825
3950
|
}
|
|
3826
3951
|
|
|
3827
3952
|
// src/commands/key.ts
|
|
3828
|
-
var
|
|
3953
|
+
var import_core24 = require("@ordewell/core");
|
|
3829
3954
|
var USAGE6 = "Usage: ordewell key [list | set <provider> <key>]";
|
|
3830
3955
|
async function handleKey(subArgs, injectedApi) {
|
|
3831
3956
|
const [action, provider, ...keyParts] = positionals(subArgs);
|
|
@@ -3836,8 +3961,8 @@ async function handleKey(subArgs, injectedApi) {
|
|
|
3836
3961
|
if (action !== "set") {
|
|
3837
3962
|
const catalog = await fetchCatalog(api);
|
|
3838
3963
|
console.log("\nAPI provider keys\n");
|
|
3839
|
-
for (const id2 of
|
|
3840
|
-
const meta2 =
|
|
3964
|
+
for (const id2 of import_core24.PROVIDER_PRIORITY) {
|
|
3965
|
+
const meta2 = (0, import_core24.getProviderMeta)(id2);
|
|
3841
3966
|
const configured = catalog.providers.includes(id2);
|
|
3842
3967
|
console.log(` ${configured ? "\u2713" : " "} ${id2.padEnd(14)} ${meta2.apiKeyEnvVar.padEnd(28)} ${meta2.label}`);
|
|
3843
3968
|
}
|
|
@@ -3847,10 +3972,10 @@ async function handleKey(subArgs, injectedApi) {
|
|
|
3847
3972
|
}
|
|
3848
3973
|
if (!provider) fail(USAGE6);
|
|
3849
3974
|
const id = provider.toLowerCase();
|
|
3850
|
-
|
|
3851
|
-
if (!meta) {
|
|
3975
|
+
if (!(0, import_core24.isApiProvider)(id)) {
|
|
3852
3976
|
fail(`Unknown provider: ${provider}`, "Run `ordewell key` to see the list.");
|
|
3853
3977
|
}
|
|
3978
|
+
const meta = (0, import_core24.getProviderMeta)(id);
|
|
3854
3979
|
const key = keyParts.join(" ").trim();
|
|
3855
3980
|
if (!key) fail(`Usage: ordewell key set ${id} <key>`);
|
|
3856
3981
|
await persistEnv(api, { [meta.apiKeyEnvVar]: key });
|
|
@@ -3858,7 +3983,7 @@ async function handleKey(subArgs, injectedApi) {
|
|
|
3858
3983
|
}
|
|
3859
3984
|
|
|
3860
3985
|
// src/commands/runners.ts
|
|
3861
|
-
var
|
|
3986
|
+
var import_core25 = require("@ordewell/core");
|
|
3862
3987
|
var USAGE7 = "Usage: ordewell runners [<runner-id> on|off]";
|
|
3863
3988
|
async function handleRunners(subArgs, injectedApi) {
|
|
3864
3989
|
const [runner, toggle] = positionals(subArgs);
|
|
@@ -3869,7 +3994,7 @@ async function handleRunners(subArgs, injectedApi) {
|
|
|
3869
3994
|
for (const r of state2.runners) {
|
|
3870
3995
|
console.log(` ${r.enabled ? "\u2713" : " "} ${r.id.padEnd(14)} ${r.name}${r.enabled ? "" : " (disabled)"}`);
|
|
3871
3996
|
}
|
|
3872
|
-
const notice = (0,
|
|
3997
|
+
const notice = (0, import_core25.codexSandboxNotice)((await fetchCatalog(api).catch(() => null))?.modesByRunner);
|
|
3873
3998
|
if (notice) console.log(`
|
|
3874
3999
|
${notice.line}
|
|
3875
4000
|
${notice.docs}`);
|
|
@@ -3890,17 +4015,17 @@ async function handleRunners(subArgs, injectedApi) {
|
|
|
3890
4015
|
var AUTO_USAGE = "Usage: ordewell auto [full|guarded]";
|
|
3891
4016
|
function handleAuto(subArgs) {
|
|
3892
4017
|
const [arg] = positionals(subArgs);
|
|
3893
|
-
const settings = new
|
|
4018
|
+
const settings = new import_core25.SettingsService();
|
|
3894
4019
|
const current = settings.autonomousMode();
|
|
3895
4020
|
if (!arg) {
|
|
3896
|
-
console.log(`Autonomy level: ${(0,
|
|
4021
|
+
console.log(`Autonomy level: ${(0, import_core25.autonomyLevelLabel)(current)}`);
|
|
3897
4022
|
console.log(` ${AUTO_USAGE}`);
|
|
3898
4023
|
return;
|
|
3899
4024
|
}
|
|
3900
|
-
const enabled = (0,
|
|
4025
|
+
const enabled = (0, import_core25.parseAutonomyLevel)(arg);
|
|
3901
4026
|
if (enabled === null) fail(AUTO_USAGE);
|
|
3902
4027
|
settings.setAutonomousMode(enabled);
|
|
3903
|
-
console.log(settings.autonomousModeOverridden() ? `${(0,
|
|
4028
|
+
console.log(settings.autonomousModeOverridden() ? `${(0, import_core25.autonomyLevelLabel)(enabled)} is saved, but ORDEWELL_AUTONOMOUS_MODE in the environment decides the level until it is unset.` : `Autonomy level: ${(0, import_core25.autonomyLevelLabel)(enabled)} for new plans.`);
|
|
3904
4029
|
}
|
|
3905
4030
|
async function handleRefresh(subArgs, injectedApi) {
|
|
3906
4031
|
const api = await connect(subArgs, injectedApi);
|
|
@@ -3930,7 +4055,7 @@ async function handleApprove(subArgs, injectedApi) {
|
|
|
3930
4055
|
}
|
|
3931
4056
|
|
|
3932
4057
|
// src/commands/task-assign.ts
|
|
3933
|
-
var
|
|
4058
|
+
var import_core27 = require("@ordewell/core");
|
|
3934
4059
|
var import_plan_utils = require("@ordewell/core/plan-utils");
|
|
3935
4060
|
|
|
3936
4061
|
// src/tui/taskAssignment.ts
|
|
@@ -3970,7 +4095,7 @@ function modesForTask(modesByRunner, task) {
|
|
|
3970
4095
|
}
|
|
3971
4096
|
|
|
3972
4097
|
// src/tui/state.ts
|
|
3973
|
-
var
|
|
4098
|
+
var import_core26 = require("@ordewell/core");
|
|
3974
4099
|
|
|
3975
4100
|
// src/tui/editor.ts
|
|
3976
4101
|
function emptyEditor() {
|
|
@@ -4128,7 +4253,7 @@ function queuedTarget(tv) {
|
|
|
4128
4253
|
for (let i = queued.length - 1; i >= 0; i--) if (!queued[i].forced) return i;
|
|
4129
4254
|
return -1;
|
|
4130
4255
|
}
|
|
4131
|
-
var anyTaskRunning = (state) => state.tasks.some(
|
|
4256
|
+
var anyTaskRunning = (state) => state.tasks.some(import_core26.isTaskRunning);
|
|
4132
4257
|
var plannerInFlight = (state) => state.planner !== "idle";
|
|
4133
4258
|
var planPaneOpen = (state) => state.focus === "plan" && !state.overlay && (!!state.taskEditor || !!state.expandedTaskId);
|
|
4134
4259
|
function planRows(state) {
|
|
@@ -4148,8 +4273,8 @@ function selectedPlanRow(state) {
|
|
|
4148
4273
|
}
|
|
4149
4274
|
function runnerCommands(tv) {
|
|
4150
4275
|
for (let i = tv.view.blocks.length - 1; i >= 0; i--) {
|
|
4151
|
-
const
|
|
4152
|
-
if (
|
|
4276
|
+
const block2 = tv.view.blocks[i];
|
|
4277
|
+
if (block2.type === "runner_loaded") return block2.commands;
|
|
4153
4278
|
}
|
|
4154
4279
|
return [];
|
|
4155
4280
|
}
|
|
@@ -4174,10 +4299,10 @@ function findTask(tasks, id) {
|
|
|
4174
4299
|
return void 0;
|
|
4175
4300
|
}
|
|
4176
4301
|
function refFor(state, task) {
|
|
4177
|
-
return (0,
|
|
4302
|
+
return (0, import_core26.taskRefOf)(state.tasks, task.id) ?? (0, import_core26.taskRef)(task);
|
|
4178
4303
|
}
|
|
4179
4304
|
function titledRefFor(state, task) {
|
|
4180
|
-
return (0,
|
|
4305
|
+
return (0, import_core26.titledTaskRefOf)(state.tasks, task.id) ?? (0, import_core26.titledTaskRef)(task);
|
|
4181
4306
|
}
|
|
4182
4307
|
function asRunTasks(tasks) {
|
|
4183
4308
|
return tasks.map((task) => ({ ...task, subtasks: asRunTasks(task.subtasks ?? []) }));
|
|
@@ -4185,7 +4310,7 @@ function asRunTasks(tasks) {
|
|
|
4185
4310
|
function seedRun(overrides) {
|
|
4186
4311
|
if (overrides.run) return overrides.run;
|
|
4187
4312
|
return {
|
|
4188
|
-
...
|
|
4313
|
+
...import_core26.EMPTY_RUN,
|
|
4189
4314
|
tasks: asRunTasks(overrides.tasks ?? []),
|
|
4190
4315
|
handoff: overrides.handoff ?? null,
|
|
4191
4316
|
runMerge: overrides.runMerge ? { waitingAtGate: overrides.runMerge.waitingAtGate, paused: overrides.runMerge.paused, repos: overrides.runMerge.handoff.repos, landed: overrides.runMerge.handoff.landed } : null
|
|
@@ -4194,9 +4319,9 @@ function seedRun(overrides) {
|
|
|
4194
4319
|
function initialState(overrides = {}) {
|
|
4195
4320
|
return {
|
|
4196
4321
|
editor: emptyEditor(),
|
|
4197
|
-
conversation:
|
|
4322
|
+
conversation: import_core26.EMPTY_CONVERSATION,
|
|
4198
4323
|
taskView: null,
|
|
4199
|
-
turnGate:
|
|
4324
|
+
turnGate: import_core26.NO_TURN,
|
|
4200
4325
|
detailAll: false,
|
|
4201
4326
|
status: "idle",
|
|
4202
4327
|
planner: "idle",
|
|
@@ -4222,11 +4347,11 @@ function initialState(overrides = {}) {
|
|
|
4222
4347
|
plannerProvider: "",
|
|
4223
4348
|
plannerEffort: "",
|
|
4224
4349
|
plannerModels: {},
|
|
4225
|
-
maxParallel:
|
|
4350
|
+
maxParallel: import_core26.DEFAULT_MAX_PARALLEL,
|
|
4226
4351
|
configuredProviders: [],
|
|
4227
4352
|
allowlist: {},
|
|
4228
4353
|
autonomous: true,
|
|
4229
|
-
runSettings: { ...
|
|
4354
|
+
runSettings: { ...import_core26.RUN_SETTINGS_DEFAULTS },
|
|
4230
4355
|
runAutoMerge: null,
|
|
4231
4356
|
runSupervisor: null,
|
|
4232
4357
|
mouseCapture: true,
|
|
@@ -4236,7 +4361,7 @@ function initialState(overrides = {}) {
|
|
|
4236
4361
|
runMerge: null,
|
|
4237
4362
|
overlay: null,
|
|
4238
4363
|
pendingApprovals: [],
|
|
4239
|
-
queuedPrompts:
|
|
4364
|
+
queuedPrompts: import_core26.EMPTY_HOLD,
|
|
4240
4365
|
stopArmed: false,
|
|
4241
4366
|
stopArmToken: 0,
|
|
4242
4367
|
stopRequested: false,
|
|
@@ -4370,7 +4495,7 @@ Mode \xB7 ${namedOf(tasks, task)}${task.assignedRunner ? ` (${task.assignedRunne
|
|
|
4370
4495
|
for (const m of modes) {
|
|
4371
4496
|
console.log(` ${m.id === task.taskMode ? "*" : " "} ${m.id.padEnd(14)} ${m.label}${m.unavailable ? " \u2014 unavailable on this host" : m.description ? ` \u2014 ${m.description}` : ""}`);
|
|
4372
4497
|
}
|
|
4373
|
-
const notice = (0,
|
|
4498
|
+
const notice = (0, import_core27.codexSandboxNotice)(catalog.modesByRunner);
|
|
4374
4499
|
if (notice) console.log(`
|
|
4375
4500
|
${notice.line}
|
|
4376
4501
|
${notice.docs}`);
|
|
@@ -4419,7 +4544,7 @@ var SKILLS_USAGE = "Usage: ordewell task-skills <task-id-or-order> [<name> [<nam
|
|
|
4419
4544
|
async function handleTaskSkills(subArgs, injectedApi) {
|
|
4420
4545
|
await withTask(subArgs, SKILLS_USAGE, injectedApi, async (api, sessionId, task, tasks, value) => {
|
|
4421
4546
|
if (task.type !== "ai") fail("Manual tasks do not run an executor, so they take no skills.");
|
|
4422
|
-
const catalog = (0,
|
|
4547
|
+
const catalog = (0, import_core27.createSkillsService)(flag(subArgs, "--workspace") || process.cwd(), new import_core27.EnvConfig().workspaceRepos).listSkills().filter((s) => s.appliesTo === "task");
|
|
4423
4548
|
if (!value) {
|
|
4424
4549
|
console.log(`
|
|
4425
4550
|
Skills \xB7 ${namedOf(tasks, task)}
|
|
@@ -4464,10 +4589,10 @@ ${namedOf(tasks, task)} is ${task.ops ? "an ops task: it runs in your checkout o
|
|
|
4464
4589
|
}
|
|
4465
4590
|
|
|
4466
4591
|
// src/tui/index.ts
|
|
4467
|
-
var
|
|
4592
|
+
var import_core48 = require("@ordewell/core");
|
|
4468
4593
|
|
|
4469
4594
|
// src/tui/slash.ts
|
|
4470
|
-
var
|
|
4595
|
+
var import_core28 = require("@ordewell/core");
|
|
4471
4596
|
var SLASH_COMMANDS = [
|
|
4472
4597
|
// Planning. There is deliberately no `/plan`: typing the goal *is* the way to
|
|
4473
4598
|
// start planning, and an alias for it only shadowed `/planner` on completion.
|
|
@@ -4485,6 +4610,7 @@ var SLASH_COMMANDS = [
|
|
|
4485
4610
|
{ name: "cancel", usage: "/cancel <id>", description: "Kill a running task", category: "tasks" },
|
|
4486
4611
|
{ name: "force-start", usage: "/force-start <id>", description: "Start a task now, ignoring dependencies", category: "tasks" },
|
|
4487
4612
|
{ name: "continue", usage: "/continue <id> <message>", description: "Continue a finished task in its saved runner session, with your message", category: "tasks" },
|
|
4613
|
+
{ name: "open", usage: "/open <id>", description: "Open a task's view: its log, and the keys that answer its checkpoint or tool request", category: "tasks" },
|
|
4488
4614
|
{ name: "checkpoint", usage: "/checkpoint <id> approve|reject [reason]", description: "Answer the checkpoint a task waits at: approve lets it go on, reject tells it why not", category: "tasks" },
|
|
4489
4615
|
{ name: "task-runner", usage: "/task-runner <id> [runner]", description: "Choose or set a task's executor (re-picks its model and mode)", category: "tasks" },
|
|
4490
4616
|
{ name: "task-model", usage: "/task-model <id> [model]", description: "Choose or set a task's executor model", category: "tasks" },
|
|
@@ -4499,7 +4625,7 @@ var SLASH_COMMANDS = [
|
|
|
4499
4625
|
{ name: "planner-effort", usage: "/planner-effort [<level>]", description: "Thinking effort for a coding-agent planner", category: "models" },
|
|
4500
4626
|
{ name: "key", usage: "/key [set <provider> <key>]", description: "Configure API provider keys", category: "models" },
|
|
4501
4627
|
{ name: "allowlist", usage: "/allowlist [set <runner> <ids> | clear <runner>]", description: "Limit which models a runner may use", category: "models" },
|
|
4502
|
-
{ name: "runners", usage: "/runners [<id> on|off]", description:
|
|
4628
|
+
{ name: "runners", usage: "/runners [<id> on|off]", description: `Enable or disable runners (${runnerIdList()})`, category: "models" },
|
|
4503
4629
|
{ name: "auto", usage: "/auto [full|guarded]", description: "Autonomy level for new plans: Full or Guarded", category: "models" },
|
|
4504
4630
|
{ name: "supervisor", usage: "/supervisor [off|watch|act] \xB7 retries <n> \xB7 reads <n>", description: "Whether the planner watches or acts on your runs, now and from then on", category: "models" },
|
|
4505
4631
|
{ name: "automerge", usage: "/automerge [on|off]", description: "Merge into your branch by itself at merge gates and at the end of a run", category: "models" },
|
|
@@ -4585,7 +4711,7 @@ function parseRunnerCommand(text) {
|
|
|
4585
4711
|
return match ? { name: match[1], args: (match[2] ?? "").trim() } : null;
|
|
4586
4712
|
}
|
|
4587
4713
|
function runnerCommandFor(commands, name) {
|
|
4588
|
-
return (0,
|
|
4714
|
+
return (0, import_core28.findRunnerCommand)(commands, name) ?? (0, import_core28.findRunnerCommand)(commands, name.toLowerCase());
|
|
4589
4715
|
}
|
|
4590
4716
|
function composerCompletions(token, runner) {
|
|
4591
4717
|
if (runner) return token.start === 0 ? runner.filter((c) => c.name.toLowerCase().startsWith(token.name)).map((c) => c.name) : [];
|
|
@@ -4632,10 +4758,10 @@ function chatEditorRoomFor(state, active) {
|
|
|
4632
4758
|
}
|
|
4633
4759
|
|
|
4634
4760
|
// src/tui/layout.ts
|
|
4635
|
-
var
|
|
4761
|
+
var import_core31 = require("@ordewell/core");
|
|
4636
4762
|
|
|
4637
4763
|
// src/tui/reducers/pickers.ts
|
|
4638
|
-
var
|
|
4764
|
+
var import_core29 = require("@ordewell/core");
|
|
4639
4765
|
var import_plan_utils2 = require("@ordewell/core/plan-utils");
|
|
4640
4766
|
var DEFAULT_EFFORT = "__runner_default__";
|
|
4641
4767
|
function picker(title, items, action, extra = {}) {
|
|
@@ -4654,11 +4780,11 @@ function modelDetail(m) {
|
|
|
4654
4780
|
function providerErrorHint(state) {
|
|
4655
4781
|
const failed = Object.keys(state.providerErrors ?? {});
|
|
4656
4782
|
if (failed.length === 0) return void 0;
|
|
4657
|
-
const names = failed.map((p) =>
|
|
4783
|
+
const names = failed.map((p) => (0, import_core29.getProviderMeta)(p)?.label ?? p);
|
|
4658
4784
|
return `\u26A0 Unavailable (key or fetch failed): ${names.join(", ")} \u2014 showing working providers only.`;
|
|
4659
4785
|
}
|
|
4660
4786
|
function plannerModelItems(state, provider, selectedId) {
|
|
4661
|
-
const runner = (0,
|
|
4787
|
+
const runner = (0, import_core29.runnerForProvider)(provider);
|
|
4662
4788
|
if (!runner) {
|
|
4663
4789
|
return state.orchestratorModels.map((m) => ({ id: m.id, label: m.label, detail: modelDetail(m), selected: m.id === selectedId }));
|
|
4664
4790
|
}
|
|
@@ -4674,11 +4800,11 @@ function plannerModelItems(state, provider, selectedId) {
|
|
|
4674
4800
|
return items.length > 0 ? items : [{ id: "", label: `No ${runner} models discovered yet`, detail: "run /refresh", disabled: true }];
|
|
4675
4801
|
}
|
|
4676
4802
|
function plannerHarnessModel(state, provider, modelId) {
|
|
4677
|
-
const runner = (0,
|
|
4803
|
+
const runner = (0, import_core29.runnerForProvider)(provider);
|
|
4678
4804
|
return runner ? state.models.find((m) => m.id === modelId && m.runners?.includes(runner)) : void 0;
|
|
4679
4805
|
}
|
|
4680
4806
|
function plannerEffortItems(state, provider, modelId, selectedEffort) {
|
|
4681
|
-
if (!(0,
|
|
4807
|
+
if (!(0, import_core29.runnerForProvider)(provider)) {
|
|
4682
4808
|
return [{ id: "", label: "Thinking effort applies to a coding-agent planner", detail: "switch with /planner", disabled: true }];
|
|
4683
4809
|
}
|
|
4684
4810
|
const model = plannerHarnessModel(state, provider, modelId);
|
|
@@ -4796,11 +4922,11 @@ function pickerItemsFor(state, action) {
|
|
|
4796
4922
|
function plannerItems(state) {
|
|
4797
4923
|
const installed = new Set(state.runners.map((r) => r.id));
|
|
4798
4924
|
const usability = {};
|
|
4799
|
-
for (const id of
|
|
4800
|
-
const runner = (0,
|
|
4925
|
+
for (const id of import_core29.CLI_PROVIDERS) {
|
|
4926
|
+
const runner = (0, import_core29.runnerForProvider)(id);
|
|
4801
4927
|
usability[runner] = installed.has(runner) ? { usable: true } : { usable: false, reason: "CLI not installed or not on PATH" };
|
|
4802
4928
|
}
|
|
4803
|
-
const entries = (0,
|
|
4929
|
+
const entries = (0, import_core29.plannerBackendEntries)(usability, state.configuredProviders);
|
|
4804
4930
|
const items = entries.map((entry) => ({
|
|
4805
4931
|
id: entry.id,
|
|
4806
4932
|
label: entry.label,
|
|
@@ -4825,12 +4951,17 @@ function cliVersion() {
|
|
|
4825
4951
|
}
|
|
4826
4952
|
|
|
4827
4953
|
// src/tui/planKeys.ts
|
|
4828
|
-
var
|
|
4954
|
+
var import_core30 = require("@ordewell/core");
|
|
4829
4955
|
var PLAN_KEYS = {
|
|
4830
4956
|
move: { keys: "up / down", meaning: "move between tasks", group: "Navigation" },
|
|
4831
4957
|
scroll: { keys: "pgup / pgdn", meaning: "scroll the plan", group: "Navigation" },
|
|
4832
4958
|
expand: { keys: "\u2192", meaning: "reveal a task's subtasks, then edit its prompt", group: "Navigation", hint: "\u2192 expand" },
|
|
4833
|
-
log: {
|
|
4959
|
+
log: {
|
|
4960
|
+
keys: "enter",
|
|
4961
|
+
meaning: "open the task's log and message its runner \u2014 or, at a checkpoint, answer it",
|
|
4962
|
+
group: "Navigation",
|
|
4963
|
+
hint: (task) => task?.status === "awaiting_user" && task.awaitingReason === "checkpoint" ? "enter answer" : "enter log"
|
|
4964
|
+
},
|
|
4834
4965
|
back: { keys: "esc", meaning: "collapse the task, or leave a task's log for the plan", group: "Navigation" },
|
|
4835
4966
|
runner: { keys: "R", meaning: "pick the task's runner", group: "Assign" },
|
|
4836
4967
|
model: { keys: "o", meaning: "pick the task's model", group: "Assign", hint: "o model" },
|
|
@@ -4847,7 +4978,7 @@ var PLAN_KEYS = {
|
|
|
4847
4978
|
meaning: "cancel the task's runner, or keep a task paused on a usage limit from resuming on its own",
|
|
4848
4979
|
group: "Run",
|
|
4849
4980
|
// `c` cancels the resume while the task has one; it has no runner to cancel then.
|
|
4850
|
-
hint: (task) => task && (0,
|
|
4981
|
+
hint: (task) => task && (0, import_core30.resumeLabel)(task) ? "c don't resume" : "c cancel"
|
|
4851
4982
|
},
|
|
4852
4983
|
resume: { keys: "r", meaning: "resume a task paused on a usage limit now, once the limit has reset", group: "Run", hint: "r resume now" },
|
|
4853
4984
|
resolve: { keys: "x", meaning: "resolve a merge conflict", group: "Run", hint: "x resolve conflict" },
|
|
@@ -4857,7 +4988,7 @@ var PLAN_KEYS = {
|
|
|
4857
4988
|
meaning: "mark the task done, or take it back",
|
|
4858
4989
|
group: "Status",
|
|
4859
4990
|
// `m` toggles, so the hint names the direction it will go for this task.
|
|
4860
|
-
hint: (task) => task && (0,
|
|
4991
|
+
hint: (task) => task && (0, import_core30.markAction)(task) === "uncomplete" ? "m undone" : "m done"
|
|
4861
4992
|
},
|
|
4862
4993
|
skip: { keys: "s", meaning: "skip the task: none of its work lands, and what depends on it goes ahead", group: "Status", hint: "s skip" },
|
|
4863
4994
|
remove: { keys: "d", meaning: "remove the task", group: "Status" },
|
|
@@ -4884,7 +5015,7 @@ function hintOf(id, task) {
|
|
|
4884
5015
|
}
|
|
4885
5016
|
function taskKeyIds(task, runActive) {
|
|
4886
5017
|
if (!task) return ["add"];
|
|
4887
|
-
const row = (0,
|
|
5018
|
+
const row = (0, import_core30.taskRowView)(task);
|
|
4888
5019
|
if (row.conflict) return ["resolve", "log"];
|
|
4889
5020
|
if (row.actions.includes("resume-now") || row.resumes) {
|
|
4890
5021
|
return [...row.actions.includes("resume-now") ? ["resume"] : [], ...row.resumes ? ["cancel"] : [], "skip", "log"];
|
|
@@ -4912,7 +5043,7 @@ function planFooterHints(task, runActive) {
|
|
|
4912
5043
|
}
|
|
4913
5044
|
|
|
4914
5045
|
// src/tui/layout.ts
|
|
4915
|
-
var
|
|
5046
|
+
var import_core32 = require("@ordewell/core");
|
|
4916
5047
|
var CHROME_ROWS = 1;
|
|
4917
5048
|
function chatInputWrap(state) {
|
|
4918
5049
|
const active = state.focus === "chat" && !state.overlay;
|
|
@@ -4931,15 +5062,17 @@ function footerHints(state) {
|
|
|
4931
5062
|
const taskSends = !!tv && tv.view.working && !!state.editor.text.trim() && !continuesTask(findTask(state.tasks, tv.taskId));
|
|
4932
5063
|
const sendNowHint = planning || taskSends ? "ctrl-s send now" : null;
|
|
4933
5064
|
const stopRunnerHint = runnerStoppable(state) ? "ctrl-x stop runner" : null;
|
|
5065
|
+
const checkpointHints = tv && waitingCheckpoint(findTask(state.tasks, tv.taskId)) && !waitingApproval(tv) ? ["enter reply", "ctrl-y approve", "ctrl-g reject"] : [];
|
|
4934
5066
|
if (state.focus === "plan") {
|
|
4935
5067
|
if (state.taskEditor) {
|
|
4936
5068
|
return ["type to edit prompt", "pgup/pgdn scroll", "alt-enter newline", "enter save", "esc cancel"];
|
|
4937
5069
|
}
|
|
4938
5070
|
return [...escHint ? [escHint] : [], ...planFooterHints(selected, state.status === "executing")];
|
|
4939
5071
|
}
|
|
4940
|
-
const detailHint = (0,
|
|
5072
|
+
const detailHint = (0, import_core32.hasHiddenDetail)(state.taskView ? state.taskView.view.blocks : state.conversation.blocks) ? [state.detailAll ? "ctrl-o collapse all" : "ctrl-o expand all"] : [];
|
|
4941
5073
|
return [
|
|
4942
5074
|
"/help",
|
|
5075
|
+
...checkpointHints,
|
|
4943
5076
|
...stopRunnerHint ? [stopRunnerHint] : [],
|
|
4944
5077
|
"tab plan",
|
|
4945
5078
|
...detailHint,
|
|
@@ -4995,12 +5128,12 @@ function queuedTaskBubble(message, target, sends, cols) {
|
|
|
4995
5128
|
}
|
|
4996
5129
|
function taskActivity(task, working) {
|
|
4997
5130
|
if (task?.status === "completed" || task?.status === "failed") return task.status;
|
|
4998
|
-
const approvals = (0,
|
|
5131
|
+
const approvals = (0, import_core32.approvalLabel)(task?.awaitingApproval);
|
|
4999
5132
|
if (approvals) return inRow(approvals);
|
|
5000
5133
|
if (working) return "working";
|
|
5001
5134
|
if (task?.status === "awaiting_user") {
|
|
5002
|
-
const resumes = (0,
|
|
5003
|
-
return [inRow((0,
|
|
5135
|
+
const resumes = (0, import_core32.resumeLabel)(task);
|
|
5136
|
+
return [inRow((0, import_core32.awaitingLabel)(task) ?? "Waiting for your input"), resumes ? inRow(resumes) : ""].filter(Boolean).join(" \xB7 ");
|
|
5004
5137
|
}
|
|
5005
5138
|
return task?.status ?? "";
|
|
5006
5139
|
}
|
|
@@ -5013,7 +5146,7 @@ function taskHeaderLines(state, tv, cols) {
|
|
|
5013
5146
|
taskActivity(task, tv.view.working)
|
|
5014
5147
|
].filter(Boolean);
|
|
5015
5148
|
const approval = waitingApproval(tv);
|
|
5016
|
-
const hint = approval ? ["ctrl-y allow", ...approval.allowForTask ? ["ctrl-t allow for task"] : [], "ctrl-g deny (composer text is the note)"] : waitingCheckpoint(task) ? ["ctrl-y approve", "ctrl-g reject
|
|
5149
|
+
const hint = approval ? ["ctrl-y allow", ...approval.allowForTask ? ["ctrl-t allow for task"] : [], "ctrl-g deny (composer text is the note)"] : waitingCheckpoint(task) ? ["enter reply", "ctrl-y approve", "ctrl-g reject", "ctrl-x stop runner"] : task && (0, import_core32.resumeLabel)(task) ? ["ctrl-x don't resume"] : [...runnerStoppable(state) ? ["ctrl-x stop runner"] : [], "ctrl-r remove queued", "ctrl-s send now"];
|
|
5017
5150
|
if (approval && waitingCheckpoint(task)) hint.push("then the checkpoint");
|
|
5018
5151
|
const index = tv.attempts.indexOf(tv.attempt);
|
|
5019
5152
|
if (tv.attempts.length > 1) hint.push(`alt\u2190/\u2192 attempt ${index >= 0 ? index + 1 : 1}/${tv.attempts.length}`);
|
|
@@ -5043,9 +5176,9 @@ function chatActivity(state) {
|
|
|
5043
5176
|
const own = findTask(state.tasks, tv.taskId);
|
|
5044
5177
|
const task = state.tasks.find((t) => t.subtasks?.some((s) => s.id === tv.taskId)) ?? own;
|
|
5045
5178
|
if (!task) return null;
|
|
5046
|
-
if ((0,
|
|
5179
|
+
if ((0, import_core26.isTaskRunning)(task) || own && (0, import_core26.isTaskRunning)(own)) return { label: "Working\u2026", busy: true };
|
|
5047
5180
|
const at = task.status === "awaiting_user" && task.awaitingReason === "usage-limit" && task.resumeAt ? new Date(task.resumeAt) : null;
|
|
5048
|
-
if (at && !Number.isNaN(at.getTime())) return { label: `paused \xB7 resumes ${(0,
|
|
5181
|
+
if (at && !Number.isNaN(at.getTime())) return { label: `paused \xB7 resumes ${(0, import_core32.resumeTime)(at)}`, busy: false };
|
|
5049
5182
|
return null;
|
|
5050
5183
|
}
|
|
5051
5184
|
function runHints(state) {
|
|
@@ -5074,41 +5207,41 @@ function bodyRows(state) {
|
|
|
5074
5207
|
return Math.max(0, state.rows - CHROME_ROWS - composerRows(state) - footer);
|
|
5075
5208
|
}
|
|
5076
5209
|
var chatBodyMemo = null;
|
|
5077
|
-
function chatBodyLines(
|
|
5210
|
+
function chatBodyLines(blocks2, cols, detailAll, answering) {
|
|
5078
5211
|
const memo = chatBodyMemo;
|
|
5079
|
-
if (memo && memo.blocks ===
|
|
5080
|
-
const lines = conversationLines(
|
|
5081
|
-
chatBodyMemo = { blocks, cols, detailAll, lines };
|
|
5212
|
+
if (memo && memo.blocks === blocks2 && memo.cols === cols && memo.detailAll === detailAll) return memo.lines;
|
|
5213
|
+
const lines = conversationLines(blocks2, cols, detailAll, answering);
|
|
5214
|
+
chatBodyMemo = { blocks: blocks2, cols, detailAll, lines };
|
|
5082
5215
|
return lines;
|
|
5083
5216
|
}
|
|
5084
5217
|
function chatLayout(state, rows, cols) {
|
|
5085
5218
|
const tv = state.taskView;
|
|
5086
|
-
const
|
|
5219
|
+
const blocks2 = tv ? tv.view.blocks : state.conversation.blocks;
|
|
5087
5220
|
const welcome = !tv && state.tasks.length === 0;
|
|
5088
5221
|
const checkpoint = tv ? waitingCheckpoint(findTask(state.tasks, tv.taskId)) : void 0;
|
|
5089
5222
|
const card = tv && checkpoint ? checkpointCardLines(findTask(state.tasks, tv.taskId)?.order ?? 0, checkpoint, cols, waitingApproval(tv) !== void 0) : [];
|
|
5090
|
-
const answering = chatBodyLines(
|
|
5223
|
+
const answering = chatBodyLines(blocks2, cols, state.detailAll, tv ? waitingApproval(tv) : void 0);
|
|
5091
5224
|
const body = card.length > 0 ? [...answering, ...card] : answering;
|
|
5092
5225
|
const transcript = !welcome ? body : body.length === 0 ? welcomeLines(state, rows, cols) : [...welcomeLines(state, rows, cols), "", ...body];
|
|
5093
5226
|
const bubbles = tv ? taskQueuedRows(state, cols) : queuedPromptRows(state, cols);
|
|
5094
5227
|
const content = [...transcript, ...bubbles.length > 0 ? ["", ...bubbles] : []];
|
|
5095
5228
|
const taskHeader = tv ? taskHeaderLines(state, tv, cols) : [];
|
|
5096
|
-
const usage = rows <= 1 ? [] : tv ? taskUsageFooter(state, tv,
|
|
5229
|
+
const usage = rows <= 1 ? [] : tv ? taskUsageFooter(state, tv, blocks2, cols) : tokenRow(blocks2, cols);
|
|
5097
5230
|
const footer = usage.slice(0, Math.max(1, rows - taskHeader.length - 1));
|
|
5098
5231
|
const space = Math.max(0, rows - taskHeader.length - footer.length);
|
|
5099
5232
|
return { lines: content, header: taskHeader, footer, anchor: content.length > space ? "bottom" : "top", maxScroll: Math.max(0, content.length - space) };
|
|
5100
5233
|
}
|
|
5101
|
-
var tokenRow = (
|
|
5102
|
-
const line = tokenLine(
|
|
5234
|
+
var tokenRow = (blocks2, cols) => {
|
|
5235
|
+
const line = tokenLine(blocks2, cols);
|
|
5103
5236
|
return line ? [line] : [];
|
|
5104
5237
|
};
|
|
5105
|
-
function taskUsageFooter(state, tv,
|
|
5238
|
+
function taskUsageFooter(state, tv, blocks2, cols) {
|
|
5106
5239
|
const task = findTask(state.tasks, tv.taskId);
|
|
5107
5240
|
const reported = task?.attemptUsage ?? [];
|
|
5108
5241
|
const onScreen = tv.attempt > 0 ? reported.find((a) => a.attempt === tv.attempt) : reported.at(-1);
|
|
5109
|
-
if (!task || !onScreen) return tokenRow(
|
|
5110
|
-
const usage = (0,
|
|
5111
|
-
if (!usage) return tokenRow(
|
|
5242
|
+
if (!task || !onScreen) return tokenRow(blocks2, cols);
|
|
5243
|
+
const usage = (0, import_core32.taskRowView)({ ...task, attemptUsage: [onScreen] }).usage;
|
|
5244
|
+
if (!usage) return tokenRow(blocks2, cols);
|
|
5112
5245
|
const models = usage.byModel ?? [];
|
|
5113
5246
|
return [
|
|
5114
5247
|
style.grey(truncate(taskUsageText(usage), cols)),
|
|
@@ -5120,17 +5253,17 @@ function chatScrollMax(state) {
|
|
|
5120
5253
|
}
|
|
5121
5254
|
function plannerSetup(state) {
|
|
5122
5255
|
const provider = state.plannerProvider;
|
|
5123
|
-
const registration =
|
|
5256
|
+
const registration = (0, import_core32.getProviderMeta)(provider);
|
|
5124
5257
|
if (!registration) return { label: "not set", ready: false };
|
|
5125
|
-
const runner = (0,
|
|
5126
|
-
const ready = runner ? state.runners.some((r) => r.id === runner) : state.configuredProviders.includes(provider);
|
|
5258
|
+
const runner = (0, import_core32.runnerForProvider)(provider);
|
|
5259
|
+
const ready = runner ? state.runners.some((r) => r.id === runner) : (0, import_core32.isApiProvider)(provider) && state.configuredProviders.includes(provider);
|
|
5127
5260
|
return { label: registration.label, ready };
|
|
5128
5261
|
}
|
|
5129
5262
|
var SETUP_KEY_COLS = 10;
|
|
5130
5263
|
var SETUP_VALUE_COLS = 32;
|
|
5131
5264
|
function runSettingsValue(state) {
|
|
5132
5265
|
const { supervisorLevel, mergeAtGatesAutomatically, autorun } = state.runSettings;
|
|
5133
|
-
const level = `supervisor ${
|
|
5266
|
+
const level = `supervisor ${import_core31.SUPERVISOR_LEVEL_LABEL[supervisorLevel]}`;
|
|
5134
5267
|
return [
|
|
5135
5268
|
supervisorLevel === "act" ? style.yellow(level) : level,
|
|
5136
5269
|
`auto-merge ${mergeAtGatesAutomatically ? "on" : "off"}`,
|
|
@@ -5231,7 +5364,7 @@ function welcomeLines(state, rows, cols) {
|
|
|
5231
5364
|
];
|
|
5232
5365
|
const notice = canPlan ? [] : [
|
|
5233
5366
|
...wrap(
|
|
5234
|
-
style.yellow(
|
|
5367
|
+
style.yellow(`Ordewell needs one coding agent installed (${runnerNamesOr()}) \u2014 or an API key from a provider such as OpenRouter, added with /key.`),
|
|
5235
5368
|
Math.max(1, cols - 1)
|
|
5236
5369
|
),
|
|
5237
5370
|
""
|
|
@@ -5265,7 +5398,7 @@ var STATUS_ICON = {
|
|
|
5265
5398
|
var inRow = (label) => label.charAt(0).toLowerCase() + label.slice(1);
|
|
5266
5399
|
function planLayout(state, rows, cols) {
|
|
5267
5400
|
const done = state.tasks.filter((t) => t.status === "completed").length;
|
|
5268
|
-
const totalUsage = (0,
|
|
5401
|
+
const totalUsage = (0, import_core32.planUsage)(state.tasks);
|
|
5269
5402
|
const unmerged = state.runMerge?.handoff.landed.length ?? 0;
|
|
5270
5403
|
const count = `${done}/${state.tasks.length}`;
|
|
5271
5404
|
const hints = runHints(state);
|
|
@@ -5343,7 +5476,7 @@ function planScrollExtent(state) {
|
|
|
5343
5476
|
}
|
|
5344
5477
|
function taskLines(state, planRow, index, cols) {
|
|
5345
5478
|
const { task, parent } = planRow;
|
|
5346
|
-
const row = (0,
|
|
5479
|
+
const row = (0, import_core32.taskRowView)(task, { parent, tasks: state.tasks, modes: modesForTask(state.modesByRunner, task) });
|
|
5347
5480
|
const selected = state.focus === "plan" && index === state.selectedTask;
|
|
5348
5481
|
const expanded = state.expandedTaskId === task.id;
|
|
5349
5482
|
const rawIcon = row.status === "running" ? SPINNER[state.spinnerFrame % SPINNER.length] : STATUS_ICON[row.status];
|
|
@@ -5394,10 +5527,10 @@ function taskLines(state, planRow, index, cols) {
|
|
|
5394
5527
|
lines.push(style.yellow(truncate(`${bodyPad}\u23F8 waits for Merge all \u2014 ${row.mergeGate.join(", ")} not merged into your branch yet`, cols)));
|
|
5395
5528
|
}
|
|
5396
5529
|
if (row.blockedBy) {
|
|
5397
|
-
lines.push(style.red(truncate(`${bodyPad}\u2298 ${inRow((0,
|
|
5530
|
+
lines.push(style.red(truncate(`${bodyPad}\u2298 ${inRow((0, import_core32.blockedByLabel)(row.blockedBy))} \u2014 runs once ${row.blockedBy.length === 1 ? "it is retried and passes" : "they are retried and pass"}`, cols)));
|
|
5398
5531
|
}
|
|
5399
5532
|
if (row.status === "skipped") {
|
|
5400
|
-
lines.push(style.grey(truncate(`${bodyPad}\xBB ${inRow((0,
|
|
5533
|
+
lines.push(style.grey(truncate(`${bodyPad}\xBB ${inRow((0, import_core32.skippedLabel)(row.skipReason))} \u2014 nothing of it landed; m done lands its kept work`, cols)));
|
|
5401
5534
|
}
|
|
5402
5535
|
const resumable = row.actions.includes("resume-now");
|
|
5403
5536
|
if (row.resumes) {
|
|
@@ -5515,7 +5648,7 @@ function commandSheetBody(cols) {
|
|
|
5515
5648
|
style.grey(" ctrl-n/ctrl-p pick a pending message (the newest until you do) \xB7 ctrl-r removes a queued one"),
|
|
5516
5649
|
style.grey(" ctrl-x stops the runner's running turn, and it then waits for your next message \u2014 on a task paused on a usage limit, it keeps it from resuming"),
|
|
5517
5650
|
style.grey(" ctrl-y allows a tool request (its keys sit under it) \xB7 ctrl-t allows it for the task \xB7 ctrl-g denies it, with the composer text as the note"),
|
|
5518
|
-
style.grey(" at a checkpoint, ctrl-y approves
|
|
5651
|
+
style.grey(" at a checkpoint, enter replies with what you typed, ctrl-y approves, ctrl-g rejects (the text is its reason) \xB7 /checkpoint <id> approve|reject [reason] from anywhere"),
|
|
5519
5652
|
style.grey(" alt\u2190/\u2192 changes attempt \xB7 esc returns")
|
|
5520
5653
|
);
|
|
5521
5654
|
return body;
|
|
@@ -5532,8 +5665,8 @@ function helpScrollMax(state) {
|
|
|
5532
5665
|
}
|
|
5533
5666
|
|
|
5534
5667
|
// src/tui/render.ts
|
|
5535
|
-
var
|
|
5536
|
-
var
|
|
5668
|
+
var import_core33 = require("@ordewell/core");
|
|
5669
|
+
var import_core34 = require("@ordewell/core");
|
|
5537
5670
|
function render(state) {
|
|
5538
5671
|
const { rows, cols } = state;
|
|
5539
5672
|
const rowsForBody = bodyRows(state);
|
|
@@ -5632,8 +5765,8 @@ function runSettingsBadge(state) {
|
|
|
5632
5765
|
const { supervisorLevel, mergeAtGatesAutomatically, autorun } = state.runSettings;
|
|
5633
5766
|
const paint = (text, warn) => warn ? style.yellow(text) : style.grey(text);
|
|
5634
5767
|
const run = state.status === "executing" ? state.runSupervisor : null;
|
|
5635
|
-
const actual = run?.unsupervised ? "unsupervised" : run && run.level !== supervisorLevel ?
|
|
5636
|
-
const level = `supervisor ${
|
|
5768
|
+
const actual = run?.unsupervised ? "unsupervised" : run && run.level !== supervisorLevel ? import_core34.SUPERVISOR_LEVEL_LABEL[run.level] : null;
|
|
5769
|
+
const level = `supervisor ${import_core34.SUPERVISOR_LEVEL_LABEL[supervisorLevel]}${actual ? ` \u2192 ${actual}` : ""}`;
|
|
5637
5770
|
return [
|
|
5638
5771
|
paint(level, supervisorLevel === "act"),
|
|
5639
5772
|
...mergeAtGatesAutomatically ? [style.grey("auto-merge")] : [],
|
|
@@ -5830,8 +5963,8 @@ function renderHandoff(state, overlay, rows, cols) {
|
|
|
5830
5963
|
return frame(`Diff \u2014 ${handoffBranch(handoff)}`, [...shown, "", style.grey(`${more}enter or esc goes back`)], rows, cols);
|
|
5831
5964
|
}
|
|
5832
5965
|
const landed = handoff.landed.length === 0 ? [style.grey("Nothing landed on it.")] : handoff.landed.map((task) => {
|
|
5833
|
-
const repaired = task.repairedFiles?.length ? style.yellow(` \u2014 repaired (${(0,
|
|
5834
|
-
return ` ${style.green("\u2713")} ${(0,
|
|
5966
|
+
const repaired = task.repairedFiles?.length ? style.yellow(` \u2014 repaired (${(0, import_core33.capConflictFiles)(task.repairedFiles)})`) : "";
|
|
5967
|
+
return ` ${style.green("\u2713")} ${(0, import_core33.titledTaskRefOf)(state.tasks, task.taskId) ?? (0, import_core33.titledTaskRef)(task)}${repaired}`;
|
|
5835
5968
|
});
|
|
5836
5969
|
const actions = handoffActions(handoff).map((action, index) => {
|
|
5837
5970
|
const active = index === overlay.index;
|
|
@@ -5879,8 +6012,8 @@ function renderPicker(picker2, rows, cols) {
|
|
|
5879
6012
|
...picker2.filterable ? [["type", "to filter"]] : []
|
|
5880
6013
|
]);
|
|
5881
6014
|
const room = Math.max(1, rows - head.length - 3);
|
|
5882
|
-
const
|
|
5883
|
-
return frame(picker2.title, [...head, ...
|
|
6015
|
+
const list2 = items.length === 0 ? [style.grey(picker2.filter ? "Nothing matches that filter." : "Nothing to show yet\u2026")] : pickerRows({ items, index: picker2.index, numbered: !picker2.filterable, chosen: picker2.multi ? picker2.chosen : void 0 }, room, inner);
|
|
6016
|
+
return frame(picker2.title, [...head, ...list2, "", footer], rows, cols);
|
|
5884
6017
|
}
|
|
5885
6018
|
function renderStepper(stepper, rows, cols) {
|
|
5886
6019
|
const { definition, trail } = stepper;
|
|
@@ -5911,13 +6044,13 @@ function renderStepper(stepper, rows, cols) {
|
|
|
5911
6044
|
cancel
|
|
5912
6045
|
]);
|
|
5913
6046
|
const room = Math.max(1, rows - head.length - 3);
|
|
5914
|
-
const
|
|
5915
|
-
return frame(definition.title, [...head, ...
|
|
6047
|
+
const list2 = items.length === 0 ? [style.grey(stepper.filter ? "Nothing matches that filter." : "Nothing to show yet\u2026")] : pickerRows({ items, index: stepper.index, numbered: !active.filterable }, room, inner);
|
|
6048
|
+
return frame(definition.title, [...head, ...list2, "", footer], rows, cols);
|
|
5916
6049
|
}
|
|
5917
6050
|
var DETAIL_GAP = 2;
|
|
5918
|
-
function pickerRows(
|
|
5919
|
-
const { items, numbered, chosen } =
|
|
5920
|
-
const index = Math.max(0, Math.min(
|
|
6051
|
+
function pickerRows(list2, room, inner) {
|
|
6052
|
+
const { items, numbered, chosen } = list2;
|
|
6053
|
+
const index = Math.max(0, Math.min(list2.index, items.length - 1));
|
|
5921
6054
|
const digits = String(items.length).length;
|
|
5922
6055
|
const prefixWidth = 2 + (numbered ? digits + 2 : 0) + (chosen ? 4 : 0);
|
|
5923
6056
|
const rowWidth = Math.max(1, inner - prefixWidth);
|
|
@@ -5926,7 +6059,7 @@ function pickerRows(list, room, inner) {
|
|
|
5926
6059
|
const labelWidth = items.some((item) => item.detail) ? Math.min(widest, Math.max(8, rowWidth - DETAIL_GAP - Math.max(16, Math.floor(rowWidth / 3)))) : Math.min(widest, rowWidth);
|
|
5927
6060
|
const detailWidth = Math.max(1, rowWidth - labelWidth - DETAIL_GAP);
|
|
5928
6061
|
const detailIndent = " ".repeat(prefixWidth + labelWidth + DETAIL_GAP);
|
|
5929
|
-
const
|
|
6062
|
+
const block2 = (item, i) => {
|
|
5930
6063
|
const active = i === index;
|
|
5931
6064
|
const current = isCurrent(item);
|
|
5932
6065
|
const number = numbered ? `${String(i + 1).padStart(digits)}. ` : "";
|
|
@@ -5943,29 +6076,29 @@ function pickerRows(list, room, inner) {
|
|
|
5943
6076
|
];
|
|
5944
6077
|
return active ? lines.map((line) => style.highlight(pad(line, inner))) : lines;
|
|
5945
6078
|
};
|
|
5946
|
-
const
|
|
5947
|
-
if (
|
|
6079
|
+
const blocks2 = items.map(block2);
|
|
6080
|
+
if (blocks2.reduce((n, b) => n + b.length, 0) <= room) return blocks2.flat();
|
|
5948
6081
|
const fit2 = Math.max(1, room - 2);
|
|
5949
6082
|
let lo = index;
|
|
5950
6083
|
let hi = index;
|
|
5951
|
-
let used =
|
|
6084
|
+
let used = blocks2[index].length;
|
|
5952
6085
|
for (let grew = true; grew; ) {
|
|
5953
6086
|
grew = false;
|
|
5954
|
-
if (hi + 1 <
|
|
6087
|
+
if (hi + 1 < blocks2.length && used + blocks2[hi + 1].length <= fit2) {
|
|
5955
6088
|
hi += 1;
|
|
5956
|
-
used +=
|
|
6089
|
+
used += blocks2[hi].length;
|
|
5957
6090
|
grew = true;
|
|
5958
6091
|
}
|
|
5959
|
-
if (lo > 0 && used +
|
|
6092
|
+
if (lo > 0 && used + blocks2[lo - 1].length <= fit2) {
|
|
5960
6093
|
lo -= 1;
|
|
5961
|
-
used +=
|
|
6094
|
+
used += blocks2[lo].length;
|
|
5962
6095
|
grew = true;
|
|
5963
6096
|
}
|
|
5964
6097
|
}
|
|
5965
6098
|
return [
|
|
5966
6099
|
...lo > 0 ? [style.grey(` \u2191 \u2026 +${lo} more`)] : [],
|
|
5967
|
-
...
|
|
5968
|
-
...hi <
|
|
6100
|
+
...blocks2.slice(lo, hi + 1).flat().slice(0, fit2),
|
|
6101
|
+
...hi < blocks2.length - 1 ? [style.grey(` \u2193 \u2026 +${blocks2.length - 1 - hi} more`)] : []
|
|
5969
6102
|
];
|
|
5970
6103
|
}
|
|
5971
6104
|
function keyHints(hints) {
|
|
@@ -6005,7 +6138,10 @@ function frame(title, body, rows, cols) {
|
|
|
6005
6138
|
}
|
|
6006
6139
|
|
|
6007
6140
|
// src/tui/reducer.ts
|
|
6008
|
-
var
|
|
6141
|
+
var import_core46 = require("@ordewell/core");
|
|
6142
|
+
|
|
6143
|
+
// src/tui/reducers/overlays.ts
|
|
6144
|
+
var import_core45 = require("@ordewell/core");
|
|
6009
6145
|
|
|
6010
6146
|
// src/tui/reducers/shared.ts
|
|
6011
6147
|
function step(state, effects = []) {
|
|
@@ -6064,10 +6200,10 @@ function handleApprovalKey(state, overlay, key) {
|
|
|
6064
6200
|
}
|
|
6065
6201
|
|
|
6066
6202
|
// src/tui/reducers/commands.ts
|
|
6067
|
-
var
|
|
6203
|
+
var import_core44 = require("@ordewell/core");
|
|
6068
6204
|
|
|
6069
6205
|
// src/tui/reducers/plannerStepper.ts
|
|
6070
|
-
var
|
|
6206
|
+
var import_core35 = require("@ordewell/core");
|
|
6071
6207
|
var offered = (items) => new Set(items.filter((i) => !i.disabled).map((i) => i.id));
|
|
6072
6208
|
function preferredModel(state, provider) {
|
|
6073
6209
|
const listed = offered(plannerModelItems(state, provider, ""));
|
|
@@ -6115,7 +6251,7 @@ var plannerStepper = {
|
|
|
6115
6251
|
const model = plannerModelItems(state, provider, "").find((m) => m.id === modelId);
|
|
6116
6252
|
const level = plannerEffortItems(state, provider, modelId, "").find((e) => e.id === effort);
|
|
6117
6253
|
const parts = [
|
|
6118
|
-
|
|
6254
|
+
(0, import_core35.getProviderMeta)(provider)?.label ?? provider,
|
|
6119
6255
|
model?.label ?? modelId,
|
|
6120
6256
|
...effort ? [effortLabel(level?.label ?? effort)] : []
|
|
6121
6257
|
];
|
|
@@ -6130,10 +6266,10 @@ var plannerStepper = {
|
|
|
6130
6266
|
};
|
|
6131
6267
|
|
|
6132
6268
|
// src/tui/reducers/stepper.ts
|
|
6133
|
-
var
|
|
6269
|
+
var import_core36 = require("@ordewell/core");
|
|
6134
6270
|
function openStepper(state, definition) {
|
|
6135
6271
|
const { choices, lists } = settle(state, definition, {});
|
|
6136
|
-
const first = lists.findIndex((
|
|
6272
|
+
const first = lists.findIndex((list2) => list2 !== null);
|
|
6137
6273
|
if (first === -1) return definition.save(state, choices);
|
|
6138
6274
|
return step({ ...state, overlay: { kind: "stepper", stepper: show2(state, definition, choices, first) } });
|
|
6139
6275
|
}
|
|
@@ -6153,11 +6289,11 @@ function handleStepperKey(state, stepper, key) {
|
|
|
6153
6289
|
const reopen = (next) => step({ ...state, overlay: { kind: "stepper", stepper: next } });
|
|
6154
6290
|
const { definition, current, entry, choices } = stepper;
|
|
6155
6291
|
const def = definition.steps[current];
|
|
6156
|
-
const typed = def.number && entry ? (0,
|
|
6292
|
+
const typed = def.number && entry ? (0, import_core36.parseCount)(entry.text, def.number.min) : null;
|
|
6157
6293
|
const { lists } = settle(state, definition, choices);
|
|
6158
6294
|
const items = matchingItems(stepper.items, stepper.filter);
|
|
6159
6295
|
const before = lastIndexBefore(lists, current);
|
|
6160
|
-
const after = lists.findIndex((
|
|
6296
|
+
const after = lists.findIndex((list2, i) => i > current && list2 !== null);
|
|
6161
6297
|
if (key.name === "escape") return step({ ...state, overlay: null });
|
|
6162
6298
|
if (key.name === "tab" || key.name === "right") return after === -1 ? reopen(stepper) : reopen(show2(state, definition, choices, after));
|
|
6163
6299
|
if (key.name === "shift-tab" || key.name === "left") return before === -1 ? reopen(stepper) : reopen(show2(state, definition, choices, before));
|
|
@@ -6203,14 +6339,14 @@ function choose(state, stepper, value) {
|
|
|
6203
6339
|
const saved = definition.save(open, choices);
|
|
6204
6340
|
if (saved.state.overlay !== open.overlay) return saved;
|
|
6205
6341
|
const { lists } = settle(saved.state, definition, choices);
|
|
6206
|
-
const next = !definition.advanceOnEnter ? current : lists.findIndex((
|
|
6342
|
+
const next = !definition.advanceOnEnter ? current : lists.findIndex((list2, i) => i > current && list2 !== null);
|
|
6207
6343
|
if (next === -1 || lists[next] === null) return { ...saved, state: { ...saved.state, overlay: null } };
|
|
6208
6344
|
return { ...saved, state: { ...saved.state, overlay: { kind: "stepper", stepper: show2(saved.state, definition, choices, next) } } };
|
|
6209
6345
|
}
|
|
6210
6346
|
function reopenStepper(state, stepper) {
|
|
6211
6347
|
const { definition, current } = stepper;
|
|
6212
6348
|
const { lists } = settle(state, definition, {});
|
|
6213
|
-
const at = lists[current] !== null ? current : lists.findIndex((
|
|
6349
|
+
const at = lists[current] !== null ? current : lists.findIndex((list2) => list2 !== null);
|
|
6214
6350
|
if (at === -1) return { ...state, overlay: null };
|
|
6215
6351
|
return { ...state, overlay: { kind: "stepper", stepper: show2(state, definition, {}, at) } };
|
|
6216
6352
|
}
|
|
@@ -6219,7 +6355,7 @@ function settle(state, definition, wanted) {
|
|
|
6219
6355
|
const lists = definition.steps.map((def) => {
|
|
6220
6356
|
if (def.skip?.(state, { ...choices })) return null;
|
|
6221
6357
|
if (def.number) {
|
|
6222
|
-
choices[def.id] = String((0,
|
|
6358
|
+
choices[def.id] = String((0, import_core36.parseCount)(wanted[def.id], def.number.min) ?? def.number.current(state, { ...choices }));
|
|
6223
6359
|
return [];
|
|
6224
6360
|
}
|
|
6225
6361
|
const items = def.items(state, { ...choices });
|
|
@@ -6233,10 +6369,10 @@ function settle(state, definition, wanted) {
|
|
|
6233
6369
|
function show2(state, definition, wanted, current) {
|
|
6234
6370
|
const { choices, lists } = settle(state, definition, wanted);
|
|
6235
6371
|
const items = lists[current] ?? [];
|
|
6236
|
-
const trail = lists.flatMap((
|
|
6237
|
-
if (
|
|
6372
|
+
const trail = lists.flatMap((list2, i) => {
|
|
6373
|
+
if (list2 === null) return [];
|
|
6238
6374
|
const def2 = definition.steps[i];
|
|
6239
|
-
const value = i >= current ? void 0 : def2.number ? choices[def2.id] :
|
|
6375
|
+
const value = i >= current ? void 0 : def2.number ? choices[def2.id] : list2.find((item) => item.id === choices[def2.id])?.label;
|
|
6240
6376
|
return [{ label: def2.label, active: i === current, ...value !== void 0 ? { value } : {} }];
|
|
6241
6377
|
});
|
|
6242
6378
|
const def = definition.steps[current];
|
|
@@ -6258,7 +6394,7 @@ function lastIndexBefore(lists, index) {
|
|
|
6258
6394
|
}
|
|
6259
6395
|
|
|
6260
6396
|
// src/tui/reducers/planPane.ts
|
|
6261
|
-
var
|
|
6397
|
+
var import_core39 = require("@ordewell/core");
|
|
6262
6398
|
|
|
6263
6399
|
// src/tui/reducers/pointer.ts
|
|
6264
6400
|
var WHEEL_NOTCH = 3;
|
|
@@ -6336,13 +6472,13 @@ function handleMouseSelect(state, key) {
|
|
|
6336
6472
|
}
|
|
6337
6473
|
|
|
6338
6474
|
// src/tui/reducers/taskView.ts
|
|
6339
|
-
var
|
|
6475
|
+
var import_core37 = require("@ordewell/core");
|
|
6340
6476
|
function openTaskView(state, sessionId, taskId) {
|
|
6341
6477
|
const task = findTask(state.tasks, taskId);
|
|
6342
6478
|
if (!task) return step(say(state, "system", `No task ${taskId} in this plan.`));
|
|
6343
6479
|
const taskView = {
|
|
6344
6480
|
taskId,
|
|
6345
|
-
view:
|
|
6481
|
+
view: import_core37.EMPTY_TASK_LOG,
|
|
6346
6482
|
attempts: [],
|
|
6347
6483
|
attempt: 0,
|
|
6348
6484
|
pending: [],
|
|
@@ -6372,13 +6508,13 @@ function applyLive(tv, attempt, events) {
|
|
|
6372
6508
|
}
|
|
6373
6509
|
next = {
|
|
6374
6510
|
...next,
|
|
6375
|
-
view:
|
|
6511
|
+
view: import_core37.EMPTY_TASK_LOG,
|
|
6376
6512
|
attempt,
|
|
6377
6513
|
attempts: next.attempts.includes(attempt) ? next.attempts : [...next.attempts, attempt]
|
|
6378
6514
|
};
|
|
6379
6515
|
}
|
|
6380
6516
|
if (attempt < next.attempt) return next;
|
|
6381
|
-
return clampQueueIndex({ ...next, view: events.reduce(
|
|
6517
|
+
return clampQueueIndex({ ...next, view: events.reduce(import_core37.reduceTaskLog, next.view) });
|
|
6382
6518
|
}
|
|
6383
6519
|
function taskLogAbandoned(state) {
|
|
6384
6520
|
const tv = state.taskView;
|
|
@@ -6398,14 +6534,15 @@ function taskLogArrived(state, action) {
|
|
|
6398
6534
|
function announceApprovals(state, action) {
|
|
6399
6535
|
if (state.taskView?.taskId === action.taskId) return state;
|
|
6400
6536
|
const task = findTask(state.tasks, action.taskId);
|
|
6401
|
-
const
|
|
6537
|
+
const way = task ? `tab to the plan, select task ${task.order} and press enter (or /open ${task.order})` : "tab to the plan, select it and press enter";
|
|
6538
|
+
const spoken = action.events.reduce((s, event) => event.type === "approval_requested" && !event.decided ? say(s, "system", `Task ${task?.order ?? "?"} waits for approval: ${(0, import_core37.runnerToolSubject)(event.tool, event.args)} \u2014 ${way}, then ctrl-y allows or ctrl-g denies`) : s, state);
|
|
6402
6539
|
return spoken !== state ? { ...spoken, scroll: state.scroll } : spoken;
|
|
6403
6540
|
}
|
|
6404
6541
|
function announceCheckpoint(state, action) {
|
|
6405
6542
|
const task = findTask(state.tasks, action.taskId) ?? state.tasks.find((t) => t.title === action.title);
|
|
6406
6543
|
const label = task ? `Task ${task.order}` : action.title;
|
|
6407
|
-
const where =
|
|
6408
|
-
const spoken = say(state, "system", `${label} asks: ${(0,
|
|
6544
|
+
const where = task ? `tab to the plan, select task ${task.order} and press enter (or /open ${task.order}) to answer` : "tab to the plan, select it and press enter to answer";
|
|
6545
|
+
const spoken = say(state, "system", `${label} asks: ${(0, import_core37.truncateCheckpointSummary)(action.summary)} \u2014 ${where}`);
|
|
6409
6546
|
return { ...spoken, scroll: state.scroll };
|
|
6410
6547
|
}
|
|
6411
6548
|
function taskLogLoaded(state, action) {
|
|
@@ -6413,7 +6550,7 @@ function taskLogLoaded(state, action) {
|
|
|
6413
6550
|
if (!tv || tv.taskId !== action.taskId) return state;
|
|
6414
6551
|
const loaded = action.attempt >= 1 ? {
|
|
6415
6552
|
...tv,
|
|
6416
|
-
view: (0,
|
|
6553
|
+
view: (0, import_core37.replayTaskLog)(action.events),
|
|
6417
6554
|
attempts: action.attempts ?? tv.attempts,
|
|
6418
6555
|
attempt: action.attempt
|
|
6419
6556
|
} : { ...tv, attempts: action.attempts ?? tv.attempts };
|
|
@@ -6487,7 +6624,7 @@ function handleTaskViewKey(state, key) {
|
|
|
6487
6624
|
if (key.name === "ctrl-s") return sendNow(state, tv, state.sessionId);
|
|
6488
6625
|
if (key.name === "ctrl-x") {
|
|
6489
6626
|
const task = findTask(state.tasks, tv.taskId);
|
|
6490
|
-
if (task && (0,
|
|
6627
|
+
if (task && (0, import_core37.resumeLabel)(task)) return step(state, [{ type: "taskAction", sessionId: state.sessionId, taskId: tv.taskId, action: "cancel-resume" }]);
|
|
6491
6628
|
return step(state, [{ type: "interruptTask", sessionId: state.sessionId, taskId: tv.taskId }]);
|
|
6492
6629
|
}
|
|
6493
6630
|
if (key.name === "ctrl-y") return answerWaiting(state, tv, state.sessionId, "allow");
|
|
@@ -6505,7 +6642,7 @@ function handleTaskViewKey(state, key) {
|
|
|
6505
6642
|
}
|
|
6506
6643
|
|
|
6507
6644
|
// src/tui/reducers/taskEdits.ts
|
|
6508
|
-
var
|
|
6645
|
+
var import_core38 = require("@ordewell/core");
|
|
6509
6646
|
var import_plan_utils3 = require("@ordewell/core/plan-utils");
|
|
6510
6647
|
function openTaskRunnerPicker(state, task) {
|
|
6511
6648
|
if (task.type !== "ai") return fail3(state, "Manual tasks do not run on an executor, so they have no runner.");
|
|
@@ -6616,7 +6753,7 @@ function openTaskModePicker(state, task) {
|
|
|
6616
6753
|
overlay: {
|
|
6617
6754
|
kind: "picker",
|
|
6618
6755
|
picker: picker(`Mode \xB7 ${refFor(state, task)}`, pickerItemsFor(state, action), action, {
|
|
6619
|
-
hint: [`Modes declared by ${task.assignedRunner}.`, (0,
|
|
6756
|
+
hint: [`Modes declared by ${task.assignedRunner}.`, (0, import_core38.codexSandboxNotice)(state.modesByRunner)?.line].filter(Boolean).join(" ")
|
|
6620
6757
|
})
|
|
6621
6758
|
}
|
|
6622
6759
|
}
|
|
@@ -6844,11 +6981,11 @@ function handlePlanKey(state, key) {
|
|
|
6844
6981
|
if (!state.sessionId || key.name !== "char") return step(state);
|
|
6845
6982
|
if (key.char === "E") return step(state, [{ type: "execute", sessionId: state.sessionId }]);
|
|
6846
6983
|
if (key.char === "S") return step(state, [{ type: "stopExecution", sessionId: state.sessionId }]);
|
|
6847
|
-
const shortcut = key.char === "c" && (0,
|
|
6984
|
+
const shortcut = key.char === "c" && (0, import_core39.resumeLabel)(task) ? "cancel-resume" : PLAN_SHORTCUTS[key.char ?? ""];
|
|
6848
6985
|
if (key.char === "r") {
|
|
6849
|
-
return (0,
|
|
6986
|
+
return (0, import_core39.taskRowActions)(task).includes("resume-now") ? step(state, [taskActionEffect(state, state.sessionId, task.id, "resume-now")]) : step(state);
|
|
6850
6987
|
}
|
|
6851
|
-
const action = key.char === "m" ? (0,
|
|
6988
|
+
const action = key.char === "m" ? (0, import_core39.markAction)(task) : shortcut;
|
|
6852
6989
|
if (action === "force-start" && task.mergeGate?.length) return confirmForceStartPastGate(state, task);
|
|
6853
6990
|
if (action) {
|
|
6854
6991
|
return step(state, [taskActionEffect(state, state.sessionId, task.id, action)]);
|
|
@@ -6888,9 +7025,9 @@ function commitTaskEdit(state, task, editor) {
|
|
|
6888
7025
|
}
|
|
6889
7026
|
|
|
6890
7027
|
// src/tui/reducers/turnQueue.ts
|
|
6891
|
-
var
|
|
7028
|
+
var import_core40 = require("@ordewell/core");
|
|
6892
7029
|
function drainQueue(state, settled) {
|
|
6893
|
-
const next = (0,
|
|
7030
|
+
const next = (0, import_core40.drainNext)(state.queuedPrompts);
|
|
6894
7031
|
const ended = disarmStop({ ...settled, stopRequested: false, forceSendPending: null });
|
|
6895
7032
|
if (!next) return step(ended);
|
|
6896
7033
|
const spoken = say(ended, "user", next.text);
|
|
@@ -6905,7 +7042,7 @@ function restoreForced(state) {
|
|
|
6905
7042
|
if (!forced) return state;
|
|
6906
7043
|
const cleared = { ...state, forceSendPending: null };
|
|
6907
7044
|
if (forced.queueIndex === void 0) {
|
|
6908
|
-
const text = (0,
|
|
7045
|
+
const text = (0, import_core40.aheadOfDraft)(forced.text, state.editor.text);
|
|
6909
7046
|
return { ...cleared, editor: { ...state.editor, text, cursor: text.length } };
|
|
6910
7047
|
}
|
|
6911
7048
|
const queued = [...state.queuedPrompts];
|
|
@@ -6921,14 +7058,14 @@ function stopPlanning(state, sessionId) {
|
|
|
6921
7058
|
return step(queueToEditor(cutTurn({ ...dismissed, stopArmed: false, stopRequested: true, forceSendPending: null })), [{ type: "cancelPlanning", sessionId }]);
|
|
6922
7059
|
}
|
|
6923
7060
|
function queueToEditor(state) {
|
|
6924
|
-
const all = (0,
|
|
7061
|
+
const all = (0, import_core40.unsendAll)(state.queuedPrompts);
|
|
6925
7062
|
if (!all) return state;
|
|
6926
7063
|
return { ...state, queuedPrompts: all.rest, editor: { ...state.editor, text: all.text, cursor: all.text.length } };
|
|
6927
7064
|
}
|
|
6928
7065
|
function unsendLatest(state) {
|
|
6929
|
-
const latest = (0,
|
|
7066
|
+
const latest = (0, import_core40.unsendLatest)(state.queuedPrompts);
|
|
6930
7067
|
if (!latest) return step(state);
|
|
6931
|
-
const text = (0,
|
|
7068
|
+
const text = (0, import_core40.aheadOfDraft)(latest.text, state.editor.text);
|
|
6932
7069
|
return step({
|
|
6933
7070
|
...state,
|
|
6934
7071
|
queuedPrompts: latest.rest,
|
|
@@ -6944,7 +7081,7 @@ function forceSendPlanner(state) {
|
|
|
6944
7081
|
{ type: "forceSendPlannerMessage", sessionId: state.sessionId, message: text }
|
|
6945
7082
|
]);
|
|
6946
7083
|
}
|
|
6947
|
-
const latest = (0,
|
|
7084
|
+
const latest = (0, import_core40.unsendLatest)(state.queuedPrompts);
|
|
6948
7085
|
if (!latest) return step(say(state, "system", "Nothing to send now: type a message, or queue one with enter."));
|
|
6949
7086
|
const forced = { text: latest.text, queueIndex: latest.rest.length };
|
|
6950
7087
|
return step({ ...state, queuedPrompts: latest.rest, stopRequested: false, forceSendPending: forced }, [
|
|
@@ -6960,7 +7097,7 @@ function plannerEscape(state) {
|
|
|
6960
7097
|
}
|
|
6961
7098
|
|
|
6962
7099
|
// src/tui/reducers/incoming.ts
|
|
6963
|
-
var
|
|
7100
|
+
var import_core41 = require("@ordewell/core");
|
|
6964
7101
|
var planText = (value, fallback = "") => sanitize(String(value ?? fallback));
|
|
6965
7102
|
var planLabel = (value, fallback = "") => planText(value, fallback).replace(/\n+/g, " ");
|
|
6966
7103
|
var asRecord = (value) => typeof value === "object" && value !== null ? value : {};
|
|
@@ -6999,7 +7136,7 @@ function runTaskToView(t) {
|
|
|
6999
7136
|
...Array.isArray(model.availableVariants) ? { availableVariants: model.availableVariants.map((variant) => planLabel(variant)) } : {}
|
|
7000
7137
|
} : void 0,
|
|
7001
7138
|
isolation: t.isolation,
|
|
7002
|
-
awaitingReason: t.status === "awaiting_user" && (0,
|
|
7139
|
+
awaitingReason: t.status === "awaiting_user" && (0, import_core41.isAwaitingReason)(t.awaitingReason) ? t.awaitingReason : void 0,
|
|
7003
7140
|
...t.status === "awaiting_user" && t.awaitingReason === "usage-limit" && typeof t.resumeAt === "string" ? { resumeAt: t.resumeAt } : {},
|
|
7004
7141
|
...t.status === "skipped" && typeof t.skipReason === "string" ? { skipReason: sanitize(t.skipReason) } : {},
|
|
7005
7142
|
checkpoint: typeof t.checkpoint === "string" ? sanitize(t.checkpoint) : void 0,
|
|
@@ -7018,7 +7155,7 @@ function supervisorOfRun(runSettings) {
|
|
|
7018
7155
|
const unsupervised = typeof runSettings.unsupervised === "string" ? runSettings.unsupervised : void 0;
|
|
7019
7156
|
return {
|
|
7020
7157
|
runSupervisor: {
|
|
7021
|
-
level: (0,
|
|
7158
|
+
level: (0, import_core41.isSupervisorLevel)(runSettings.supervisorLevel) ? runSettings.supervisorLevel : "off",
|
|
7022
7159
|
...unsupervised ? { unsupervised } : {}
|
|
7023
7160
|
}
|
|
7024
7161
|
};
|
|
@@ -7035,7 +7172,7 @@ function withRun(state, run) {
|
|
|
7035
7172
|
};
|
|
7036
7173
|
}
|
|
7037
7174
|
function foldRun(state, input) {
|
|
7038
|
-
const run = (0,
|
|
7175
|
+
const run = (0, import_core41.reduceRun)(state.run, input);
|
|
7039
7176
|
return run === state.run ? state : withRun(state, run);
|
|
7040
7177
|
}
|
|
7041
7178
|
function mapRunTasks(tasks, map) {
|
|
@@ -7083,21 +7220,21 @@ function followSession(state, message) {
|
|
|
7083
7220
|
}
|
|
7084
7221
|
|
|
7085
7222
|
// src/tui/reducers/runSettings.ts
|
|
7086
|
-
var
|
|
7223
|
+
var import_core42 = require("@ordewell/core");
|
|
7087
7224
|
function runSettingsEffect(state, changes) {
|
|
7088
7225
|
return { type: "setRunSettings", changes, ...state.sessionId ? { sessionId: state.sessionId } : {} };
|
|
7089
7226
|
}
|
|
7090
7227
|
function supervisorCommand(state, args) {
|
|
7091
7228
|
const [arg, value] = args;
|
|
7092
7229
|
if (arg === void 0) {
|
|
7093
|
-
return step(say(state, "system", `${(0,
|
|
7230
|
+
return step(say(state, "system", `${(0, import_core42.supervisorSummary)(state.runSettings)} \u2014 /supervisor off|watch|act, /supervisor retries <n>, /supervisor reads <n>.`));
|
|
7094
7231
|
}
|
|
7095
7232
|
if (arg === "retries") {
|
|
7096
|
-
const n = (0,
|
|
7233
|
+
const n = (0, import_core42.parseCount)(value, 0);
|
|
7097
7234
|
return n === null ? fail3(state, "Usage: /supervisor retries <whole number, 0 or more>") : step(state, [runSettingsEffect(state, { supervisorRetryLimit: n })]);
|
|
7098
7235
|
}
|
|
7099
7236
|
if (arg === "reads") {
|
|
7100
|
-
const n = (0,
|
|
7237
|
+
const n = (0, import_core42.parseCount)(value, 1);
|
|
7101
7238
|
return n === null ? fail3(state, "Usage: /supervisor reads <whole number, 1 or more>") : step(state, [runSettingsEffect(state, { wakeUpReadBudget: n })]);
|
|
7102
7239
|
}
|
|
7103
7240
|
if (arg === "act") return confirmSupervisorAct(state);
|
|
@@ -7106,17 +7243,17 @@ function supervisorCommand(state, args) {
|
|
|
7106
7243
|
}
|
|
7107
7244
|
function automergeCommand(state, arg) {
|
|
7108
7245
|
if (arg === void 0) {
|
|
7109
|
-
return step(say(state, "system", `${(0,
|
|
7246
|
+
return step(say(state, "system", `${(0, import_core42.automergeSummary)(state.runSettings)} \u2014 /automerge on|off.`));
|
|
7110
7247
|
}
|
|
7111
|
-
const enabled = (0,
|
|
7248
|
+
const enabled = (0, import_core42.parseSwitch)(arg);
|
|
7112
7249
|
if (enabled === null) return fail3(state, "Usage: /automerge [on|off]");
|
|
7113
7250
|
return step(state, [runSettingsEffect(state, { mergeAtGatesAutomatically: enabled })]);
|
|
7114
7251
|
}
|
|
7115
7252
|
function autorunCommand(state, arg) {
|
|
7116
7253
|
if (arg === void 0) {
|
|
7117
|
-
return step(say(state, "system", `${(0,
|
|
7254
|
+
return step(say(state, "system", `${(0, import_core42.autorunSummary)(state.runSettings)} \u2014 /autorun on starts each plan the planner submits, without review.`));
|
|
7118
7255
|
}
|
|
7119
|
-
const enabled = (0,
|
|
7256
|
+
const enabled = (0, import_core42.parseSwitch)(arg);
|
|
7120
7257
|
if (enabled === null) return fail3(state, "Usage: /autorun [on|off]");
|
|
7121
7258
|
if (enabled) return confirmAutorun(state);
|
|
7122
7259
|
return step(state, [runSettingsEffect(state, { autorun: false })]);
|
|
@@ -7128,7 +7265,7 @@ function confirmSupervisorAct(state) {
|
|
|
7128
7265
|
kind: "confirm",
|
|
7129
7266
|
title: "Let the supervisor act?",
|
|
7130
7267
|
message: "At Act the supervisor runs, stops and retries tasks, answers their requests (never allowing), edits the plan and merges, without asking you.",
|
|
7131
|
-
note: `${
|
|
7268
|
+
note: `${import_core42.ACT_RISK}
|
|
7132
7269
|
It applies to this session's run now, and to every later run.`,
|
|
7133
7270
|
action: { kind: "supervisor-act" }
|
|
7134
7271
|
}
|
|
@@ -7141,14 +7278,14 @@ function confirmAutorun(state) {
|
|
|
7141
7278
|
kind: "confirm",
|
|
7142
7279
|
title: "Start plans without review?",
|
|
7143
7280
|
message: "With autorun on, each plan the planner submits starts at once, as if you had pressed Execute. The planner still asks when something is unclear.",
|
|
7144
|
-
note:
|
|
7281
|
+
note: import_core42.AUTORUN_RISK,
|
|
7145
7282
|
action: { kind: "autorun-on" }
|
|
7146
7283
|
}
|
|
7147
7284
|
});
|
|
7148
7285
|
}
|
|
7149
7286
|
|
|
7150
7287
|
// src/tui/reducers/settings.ts
|
|
7151
|
-
var
|
|
7288
|
+
var import_core43 = require("@ordewell/core");
|
|
7152
7289
|
var SUPERVISOR_DETAIL = {
|
|
7153
7290
|
off: "The planner speaks only when you write",
|
|
7154
7291
|
watch: "The planner follows your runs and suggests what to do",
|
|
@@ -7173,7 +7310,7 @@ var SETTINGS = {
|
|
|
7173
7310
|
{
|
|
7174
7311
|
id: "guarded",
|
|
7175
7312
|
label: "Guarded",
|
|
7176
|
-
detail: [`New plans run tasks in each runner's safer mode`, (0,
|
|
7313
|
+
detail: [`New plans run tasks in each runner's safer mode`, (0, import_core43.codexSandboxNotice)(state.modesByRunner)?.line].filter(Boolean).join(" \xB7 "),
|
|
7177
7314
|
selected: !state.autonomous
|
|
7178
7315
|
}
|
|
7179
7316
|
]
|
|
@@ -7183,7 +7320,7 @@ var SETTINGS = {
|
|
|
7183
7320
|
label: "Supervisor",
|
|
7184
7321
|
items: (state) => ["off", "watch", "act"].map((level) => ({
|
|
7185
7322
|
id: level,
|
|
7186
|
-
label:
|
|
7323
|
+
label: import_core43.SUPERVISOR_LEVEL_LABEL[level],
|
|
7187
7324
|
detail: SUPERVISOR_DETAIL[level],
|
|
7188
7325
|
selected: state.runSettings.supervisorLevel === level
|
|
7189
7326
|
}))
|
|
@@ -7237,12 +7374,12 @@ function saveChoices(state, choices) {
|
|
|
7237
7374
|
const autonomous = choices.autonomy === "full";
|
|
7238
7375
|
if (autonomous !== state.autonomous) {
|
|
7239
7376
|
save2.autonomous = autonomous;
|
|
7240
|
-
changed.push(`Autonomy ${(0,
|
|
7377
|
+
changed.push(`Autonomy ${(0, import_core43.autonomyLevelLabel)(autonomous)}`);
|
|
7241
7378
|
}
|
|
7242
7379
|
const level = choices.supervisor;
|
|
7243
7380
|
if (level !== state.runSettings.supervisorLevel) {
|
|
7244
7381
|
run.supervisorLevel = level;
|
|
7245
|
-
changed.push(`Supervisor ${
|
|
7382
|
+
changed.push(`Supervisor ${import_core43.SUPERVISOR_LEVEL_LABEL[level]}`);
|
|
7246
7383
|
}
|
|
7247
7384
|
if (choices.retries !== void 0 && Number(choices.retries) !== state.runSettings.supervisorRetryLimit) {
|
|
7248
7385
|
run.supervisorRetryLimit = Number(choices.retries);
|
|
@@ -7269,7 +7406,7 @@ function saveChoices(state, choices) {
|
|
|
7269
7406
|
}
|
|
7270
7407
|
if (changed.length === 0) return step(state);
|
|
7271
7408
|
const effect = { ...save2, message: `Settings: ${changed.join(" \xB7 ")}` };
|
|
7272
|
-
const risks = [...run.supervisorLevel === "act" ? [
|
|
7409
|
+
const risks = [...run.supervisorLevel === "act" ? [import_core43.ACT_RISK] : [], ...run.autorun ? [import_core43.AUTORUN_RISK] : []];
|
|
7273
7410
|
if (risks.length === 0) return saveSettings(state, effect);
|
|
7274
7411
|
return step({
|
|
7275
7412
|
...state,
|
|
@@ -7298,7 +7435,6 @@ function saveSettings(state, effect) {
|
|
|
7298
7435
|
}
|
|
7299
7436
|
|
|
7300
7437
|
// src/tui/reducers/commands.ts
|
|
7301
|
-
var KNOWN_PROVIDERS = Object.keys(import_core42.ALL_PROVIDERS);
|
|
7302
7438
|
var unknownCommand = (state, name) => fail3(state, `Unknown command: /${name} \u2014 type /help to see what's available.`);
|
|
7303
7439
|
function runCommand(state, { name, args }) {
|
|
7304
7440
|
if (!findCommand(name)) return unknownCommand(state, name);
|
|
@@ -7385,6 +7521,8 @@ function runCommand(state, { name, args }) {
|
|
|
7385
7521
|
if (!text) return fail3(state, "Usage: /continue <id> <message>");
|
|
7386
7522
|
return continueTaskStep(state, sessionId, taskId, text);
|
|
7387
7523
|
});
|
|
7524
|
+
case "open":
|
|
7525
|
+
return taskCommand(state, args[0], (sessionId, taskId) => openTaskView(state, sessionId, taskId));
|
|
7388
7526
|
case "checkpoint":
|
|
7389
7527
|
return taskCommand(state, args[0], (sessionId, taskId) => {
|
|
7390
7528
|
const answer = args[1]?.toLowerCase();
|
|
@@ -7459,8 +7597,8 @@ function newSession(state) {
|
|
|
7459
7597
|
goal: "",
|
|
7460
7598
|
taskView: null,
|
|
7461
7599
|
planApproved: false,
|
|
7462
|
-
conversation:
|
|
7463
|
-
turnGate:
|
|
7600
|
+
conversation: import_core44.EMPTY_CONVERSATION,
|
|
7601
|
+
turnGate: import_core44.NO_TURN,
|
|
7464
7602
|
selectedTask: 0,
|
|
7465
7603
|
expandedTaskId: null,
|
|
7466
7604
|
taskEditor: null,
|
|
@@ -7471,15 +7609,15 @@ function newSession(state) {
|
|
|
7471
7609
|
// Prompts belong to the session that raised them; the old planner is gone
|
|
7472
7610
|
// and its pending requests deny on their own timeout.
|
|
7473
7611
|
pendingApprovals: [],
|
|
7474
|
-
queuedPrompts:
|
|
7612
|
+
queuedPrompts: import_core44.EMPTY_HOLD,
|
|
7475
7613
|
stopArmed: false,
|
|
7476
7614
|
forceSendPending: null,
|
|
7477
7615
|
overlay: state.overlay?.kind === "approval" ? null : state.overlay
|
|
7478
|
-
},
|
|
7616
|
+
}, import_core44.EMPTY_RUN), closeEffects);
|
|
7479
7617
|
}
|
|
7480
7618
|
function setModel(state, args) {
|
|
7481
7619
|
if (args[0] === "set" && args[1]) {
|
|
7482
|
-
const runner = (0,
|
|
7620
|
+
const runner = (0, import_core44.runnerForProvider)(state.plannerProvider);
|
|
7483
7621
|
const known = runner ? modelsForRunner(state.models, runner) : [];
|
|
7484
7622
|
if (runner && known.length > 0 && !known.some((m) => m.id === args[1])) {
|
|
7485
7623
|
return fail3(state, `${args[1]} was not discovered for ${runner}.`);
|
|
@@ -7502,7 +7640,7 @@ function setModel(state, args) {
|
|
|
7502
7640
|
function setPlanner(state, args) {
|
|
7503
7641
|
if (args[0]) {
|
|
7504
7642
|
const id = args[0].toLowerCase();
|
|
7505
|
-
if (!
|
|
7643
|
+
if (!(0, import_core44.isPlannerBackend)(id)) {
|
|
7506
7644
|
return fail3(state, `Unknown planner: ${id}. Run /planner with no arguments to see the list.`);
|
|
7507
7645
|
}
|
|
7508
7646
|
return step(state, [{ type: "setPlanner", provider: id }]);
|
|
@@ -7534,7 +7672,7 @@ function setPlannerEffort(state, args) {
|
|
|
7534
7672
|
function setKey(state, args) {
|
|
7535
7673
|
if (args[0] === "set" && args[1]) {
|
|
7536
7674
|
const provider = args[1].toLowerCase();
|
|
7537
|
-
if (!
|
|
7675
|
+
if (!(0, import_core44.isApiProvider)(provider)) {
|
|
7538
7676
|
return fail3(state, `Unknown provider: ${provider}. Run /key with no arguments to see the list.`);
|
|
7539
7677
|
}
|
|
7540
7678
|
if (!args[2]) {
|
|
@@ -7545,16 +7683,16 @@ function setKey(state, args) {
|
|
|
7545
7683
|
}
|
|
7546
7684
|
return step(state, [{ type: "setApiKey", provider, key: args.slice(2).join(" ") }]);
|
|
7547
7685
|
}
|
|
7548
|
-
const items =
|
|
7686
|
+
const items = import_core44.PROVIDER_PRIORITY.map((id) => ({
|
|
7549
7687
|
id,
|
|
7550
|
-
label:
|
|
7551
|
-
detail:
|
|
7688
|
+
label: (0, import_core44.getProviderMeta)(id).label,
|
|
7689
|
+
detail: (0, import_core44.getProviderMeta)(id).apiKeyEnvVar,
|
|
7552
7690
|
selected: state.configuredProviders.includes(id)
|
|
7553
7691
|
}));
|
|
7554
7692
|
return step({ ...state, overlay: { kind: "picker", picker: picker("API provider key", items, { kind: "set-key" }) } });
|
|
7555
7693
|
}
|
|
7556
7694
|
function keyPrompt(provider) {
|
|
7557
|
-
const meta =
|
|
7695
|
+
const meta = (0, import_core44.getProviderMeta)(provider);
|
|
7558
7696
|
return {
|
|
7559
7697
|
kind: "prompt",
|
|
7560
7698
|
title: `${meta.label} API key`,
|
|
@@ -7631,13 +7769,13 @@ function runners(state, args) {
|
|
|
7631
7769
|
}
|
|
7632
7770
|
function setMaxParallel(state, arg) {
|
|
7633
7771
|
if (!arg) return step(say(state, "system", `Up to ${state.maxParallel} AI task${state.maxParallel === 1 ? "" : "s"} run at once \u2014 /parallel <n> changes it.`));
|
|
7634
|
-
const limit = (0,
|
|
7772
|
+
const limit = (0, import_core44.parseMaxParallel)(arg);
|
|
7635
7773
|
if (limit === null) return fail3(state, "Usage: /parallel [<number of tasks, 1 or more>]");
|
|
7636
7774
|
return step({ ...state, maxParallel: limit }, [{ type: "setMaxParallel", limit }]);
|
|
7637
7775
|
}
|
|
7638
7776
|
function setAutonomous(state, arg) {
|
|
7639
|
-
if (arg === void 0) return step(say(state, "system", `Autonomy level: ${(0,
|
|
7640
|
-
const enabled = (0,
|
|
7777
|
+
if (arg === void 0) return step(say(state, "system", `Autonomy level: ${(0, import_core44.autonomyLevelLabel)(state.autonomous)} \u2014 /auto full or /auto guarded changes it for new plans.`));
|
|
7778
|
+
const enabled = (0, import_core44.parseAutonomyLevel)(arg);
|
|
7641
7779
|
if (enabled === null) return fail3(state, "Usage: /auto [full|guarded]");
|
|
7642
7780
|
return step({ ...state, autonomous: enabled }, [{ type: "setAutonomous", enabled }]);
|
|
7643
7781
|
}
|
|
@@ -7846,7 +7984,7 @@ function choose2(state, picker2, item) {
|
|
|
7846
7984
|
case "delete-session":
|
|
7847
7985
|
return step(closed, [{ type: "deleteSession", sessionId: item.id }]);
|
|
7848
7986
|
case "set-key":
|
|
7849
|
-
return step({ ...state, overlay: keyPrompt(item.id) });
|
|
7987
|
+
return (0, import_core45.isApiProvider)(item.id) ? step({ ...state, overlay: keyPrompt(item.id) }) : step(closed);
|
|
7850
7988
|
case "choose-allowlist-runner": {
|
|
7851
7989
|
const action = { kind: "set-allowlist", runner: item.id };
|
|
7852
7990
|
const items = pickerItemsFor(state, action);
|
|
@@ -7922,7 +8060,7 @@ function reduceAction(state, action) {
|
|
|
7922
8060
|
// (`task-1`), so nothing of the last one's — a merge gate, a checkpoint, its
|
|
7923
8061
|
// tasks — may carry over into this.
|
|
7924
8062
|
case "sessionStarted":
|
|
7925
|
-
return step(withRun({ ...state, sessionId: action.sessionId, goal: action.goal, taskView: null },
|
|
8063
|
+
return step(withRun({ ...state, sessionId: action.sessionId, goal: action.goal, taskView: null }, import_core46.EMPTY_RUN));
|
|
7926
8064
|
// The daemon registers a session only once planning succeeds; when it does
|
|
7927
8065
|
// not, holding on to the id would send every next message to a session the
|
|
7928
8066
|
// server never had.
|
|
@@ -7933,18 +8071,18 @@ function reduceAction(state, action) {
|
|
|
7933
8071
|
goal: "",
|
|
7934
8072
|
taskView: null,
|
|
7935
8073
|
pendingApprovals: [],
|
|
7936
|
-
queuedPrompts:
|
|
8074
|
+
queuedPrompts: import_core46.EMPTY_HOLD,
|
|
7937
8075
|
stopArmed: false,
|
|
7938
8076
|
forceSendPending: null,
|
|
7939
8077
|
overlay: state.overlay?.kind === "approval" ? null : state.overlay
|
|
7940
|
-
},
|
|
8078
|
+
}, import_core46.EMPTY_RUN));
|
|
7941
8079
|
// Deleting the session on screen stops it in the daemon; a view left on it
|
|
7942
8080
|
// would answer every next message with a session-not-found.
|
|
7943
8081
|
case "sessionDeleted":
|
|
7944
8082
|
return action.sessionId === state.sessionId ? newSession(state) : step(state);
|
|
7945
8083
|
case "chatRestored":
|
|
7946
8084
|
if (stale(state, action.sessionId)) return step(state);
|
|
7947
|
-
return step({ ...state, conversation: (0,
|
|
8085
|
+
return step({ ...state, conversation: (0, import_core46.fromTranscript)(action.history, action.researchLog, action.plannerUsage, action.pendingTurns), scroll: 0 });
|
|
7948
8086
|
case "planUpdated": {
|
|
7949
8087
|
if (stale(state, action.sessionId)) return step(state);
|
|
7950
8088
|
const settled = { ...showPlan(state, action.plan), planner: "idle" };
|
|
@@ -7984,15 +8122,15 @@ function reduceAction(state, action) {
|
|
|
7984
8122
|
case "taskStarted": {
|
|
7985
8123
|
if (stale(state, action.sessionId)) return step(state);
|
|
7986
8124
|
const existing = findTask(state.tasks, action.taskId);
|
|
7987
|
-
if (existing && (0,
|
|
8125
|
+
if (existing && (0, import_core26.isTaskRunning)(existing)) return step(state);
|
|
7988
8126
|
const folded = foldRun(state, {
|
|
7989
8127
|
type: "task_started",
|
|
7990
8128
|
taskId: action.taskId,
|
|
7991
8129
|
order: action.order ?? 0,
|
|
7992
8130
|
title: action.title,
|
|
7993
|
-
runner: action.runner ??
|
|
8131
|
+
runner: action.runner ?? import_core46.DEFAULT_RUNNERS[0]
|
|
7994
8132
|
});
|
|
7995
|
-
const spoken = say(folded, "system", (0,
|
|
8133
|
+
const spoken = say(folded, "system", (0, import_core46.taskStartedNotice)(action.title, action.runner));
|
|
7996
8134
|
return step({ ...spoken, status: "executing" });
|
|
7997
8135
|
}
|
|
7998
8136
|
case "taskCheckpoint":
|
|
@@ -8038,7 +8176,7 @@ function reduceAction(state, action) {
|
|
|
8038
8176
|
completed: state.tasks.filter((t) => t.status === "completed").length,
|
|
8039
8177
|
total: state.tasks.length,
|
|
8040
8178
|
failed: state.tasks.filter((t) => t.status === "failed").length,
|
|
8041
|
-
blocked: (0,
|
|
8179
|
+
blocked: (0, import_core46.blockingFailures)(state.tasks).size,
|
|
8042
8180
|
skipped: state.tasks.filter((t) => t.status === "skipped").length
|
|
8043
8181
|
};
|
|
8044
8182
|
const failures = `${failed > 0 ? ` \xB7 ${failed} failed` : ""}${blocked ? ` \xB7 ${blocked} blocked` : ""}${skipped ? ` \xB7 ${skipped} skipped` : ""}`;
|
|
@@ -8102,11 +8240,11 @@ function reduceAction(state, action) {
|
|
|
8102
8240
|
planner: "idle",
|
|
8103
8241
|
planApproved: false,
|
|
8104
8242
|
pendingApprovals: [],
|
|
8105
|
-
queuedPrompts:
|
|
8243
|
+
queuedPrompts: import_core46.EMPTY_HOLD,
|
|
8106
8244
|
stopArmed: false,
|
|
8107
8245
|
forceSendPending: null,
|
|
8108
8246
|
overlay: state.overlay?.kind === "approval" ? null : state.overlay
|
|
8109
|
-
},
|
|
8247
|
+
}, import_core46.EMPTY_RUN));
|
|
8110
8248
|
// The rewound message comes back as a draft to edit and resend, so it lands
|
|
8111
8249
|
// as if just typed: history is not being browsed, and nothing is parked.
|
|
8112
8250
|
case "inputPrefilled":
|
|
@@ -8178,7 +8316,7 @@ function showPlan(state, plan) {
|
|
|
8178
8316
|
});
|
|
8179
8317
|
}
|
|
8180
8318
|
function runStatus(state, tasks) {
|
|
8181
|
-
if (tasks.some(
|
|
8319
|
+
if (tasks.some(import_core26.isTaskRunning)) return "executing";
|
|
8182
8320
|
if (tasks.some((t) => t.status === "awaiting_user") || state.runMerge?.paused) return "executing";
|
|
8183
8321
|
return "idle";
|
|
8184
8322
|
}
|
|
@@ -8257,6 +8395,12 @@ function submit(state) {
|
|
|
8257
8395
|
return step({ ...cleared, taskView: { ...state.taskView, notice } });
|
|
8258
8396
|
}
|
|
8259
8397
|
if (state.taskView.notice) cleared.taskView = { ...state.taskView, notice: void 0 };
|
|
8398
|
+
if (!command && waitingCheckpoint(task)) {
|
|
8399
|
+
if (waitingApproval(state.taskView)) {
|
|
8400
|
+
return step(say(state, "system", "A tool request is waiting ahead of the checkpoint \u2014 answer it first (ctrl-y to allow, ctrl-g to deny), then enter replies to the checkpoint."));
|
|
8401
|
+
}
|
|
8402
|
+
return answerCheckpoint(cleared, state.sessionId, taskId, "reject", text);
|
|
8403
|
+
}
|
|
8260
8404
|
if (continuesTask(task)) return continueTaskStep(cleared, state.sessionId, taskId, text);
|
|
8261
8405
|
if (command && offered2.length > 0) return step(cleared, [{ type: "invokeTaskCommand", sessionId: state.sessionId, taskId, ...command }]);
|
|
8262
8406
|
return step(cleared, [{ type: "sendTaskMessage", sessionId: state.sessionId, taskId, text }]);
|
|
@@ -8264,7 +8408,7 @@ function submit(state) {
|
|
|
8264
8408
|
const builtIn = builtInCommand(text);
|
|
8265
8409
|
if (builtIn) return runCommand(cleared, builtIn);
|
|
8266
8410
|
if (plannerInFlight(state)) {
|
|
8267
|
-
return step({ ...cleared, queuedPrompts: (0,
|
|
8411
|
+
return step({ ...cleared, queuedPrompts: (0, import_core46.holdPrompt)(state.queuedPrompts, text) });
|
|
8268
8412
|
}
|
|
8269
8413
|
const spoken = say(cleared, "user", text);
|
|
8270
8414
|
const effect = state.sessionId ? { type: "sendMessage", sessionId: state.sessionId, message: text } : { type: "startConversation", goal: text };
|
|
@@ -8339,7 +8483,7 @@ function createApp(deps) {
|
|
|
8339
8483
|
|
|
8340
8484
|
// src/tui/effects.ts
|
|
8341
8485
|
var import_child_process3 = require("child_process");
|
|
8342
|
-
var
|
|
8486
|
+
var import_core47 = require("@ordewell/core");
|
|
8343
8487
|
|
|
8344
8488
|
// src/tui/inbound.ts
|
|
8345
8489
|
var CONVERSATION_TYPES = /* @__PURE__ */ new Set([
|
|
@@ -8748,13 +8892,13 @@ async function perform(effect, deps) {
|
|
|
8748
8892
|
await refreshPlan(deps, sessionId);
|
|
8749
8893
|
return;
|
|
8750
8894
|
}
|
|
8751
|
-
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,
|
|
8895
|
+
const request = action === "cancel" || action === "retry" || action === "force-start" ? () => api.taskControl(sessionId, taskId, action) : action === "resume-now" ? () => api.resumeNow(sessionId, taskId) : action === "skip" ? () => api.skipTask(sessionId, taskId) : (0, import_core47.markRequestFor)(action) === "uncomplete" ? () => api.markTaskIncomplete(sessionId, taskId) : () => api.markTaskComplete(sessionId, taskId);
|
|
8752
8896
|
await (effect.watch ? withExecutionStream(deps, sessionId, request) : request());
|
|
8753
8897
|
await refreshPlan(deps, sessionId);
|
|
8754
8898
|
return;
|
|
8755
8899
|
}
|
|
8756
8900
|
case "addTask": {
|
|
8757
|
-
const fields = (0,
|
|
8901
|
+
const fields = (0, import_core47.newTaskFields)(effect.title);
|
|
8758
8902
|
if (!fields) return;
|
|
8759
8903
|
await api.addTask(effect.sessionId, { ...fields });
|
|
8760
8904
|
await refreshPlan(deps, effect.sessionId);
|
|
@@ -8862,7 +9006,7 @@ async function perform(effect, deps) {
|
|
|
8862
9006
|
return;
|
|
8863
9007
|
}
|
|
8864
9008
|
case "setPlanner": {
|
|
8865
|
-
const meta =
|
|
9009
|
+
const meta = (0, import_core47.getProviderMeta)(effect.provider);
|
|
8866
9010
|
if (!meta) throw new Error(`Unknown planner: ${effect.provider}`);
|
|
8867
9011
|
const env = { AI_PROVIDER: effect.provider };
|
|
8868
9012
|
const settings = await api.updateSettings({ env });
|
|
@@ -8874,7 +9018,7 @@ async function perform(effect, deps) {
|
|
|
8874
9018
|
});
|
|
8875
9019
|
dispatch({
|
|
8876
9020
|
type: "notice",
|
|
8877
|
-
message: `${(0,
|
|
9021
|
+
message: `${(0, import_core47.isCliProvider)(effect.provider) ? `Planning with ${meta.label} \u2014 no API key needed.` : `Planner set to ${meta.label}.`} ${plannerModelNotice(recall2)}`
|
|
8878
9022
|
});
|
|
8879
9023
|
await loadModels(deps);
|
|
8880
9024
|
return;
|
|
@@ -8902,7 +9046,7 @@ async function perform(effect, deps) {
|
|
|
8902
9046
|
dispatch({ type: "notice", message: `Planner effort set to ${effect.effort || "the runner default"}.` });
|
|
8903
9047
|
return;
|
|
8904
9048
|
case "setApiKey": {
|
|
8905
|
-
const meta =
|
|
9049
|
+
const meta = (0, import_core47.isApiProvider)(effect.provider) ? (0, import_core47.getProviderMeta)(effect.provider) : void 0;
|
|
8906
9050
|
if (!meta) throw new Error(`Unknown provider: ${effect.provider}`);
|
|
8907
9051
|
await api.updateSettings({ env: { [meta.apiKeyEnvVar]: effect.key } });
|
|
8908
9052
|
deps.setEnvVar(meta.apiKeyEnvVar, effect.key);
|
|
@@ -8950,7 +9094,7 @@ async function perform(effect, deps) {
|
|
|
8950
9094
|
}
|
|
8951
9095
|
case "setAutonomous": {
|
|
8952
9096
|
const { overridden } = deps.saveAutonomy(effect.enabled);
|
|
8953
|
-
const level = (0,
|
|
9097
|
+
const level = (0, import_core47.autonomyLevelLabel)(effect.enabled);
|
|
8954
9098
|
dispatch({ type: "notice", message: overridden ? `${level} is saved, but ORDEWELL_AUTONOMOUS_MODE in the environment decides the level until it is unset.` : `Autonomy level: ${level} for new plans.` });
|
|
8955
9099
|
return;
|
|
8956
9100
|
}
|
|
@@ -9114,7 +9258,7 @@ async function saveMaxParallel(deps, limit) {
|
|
|
9114
9258
|
function copySelection(deps, text) {
|
|
9115
9259
|
if (!text) return;
|
|
9116
9260
|
const lines = text.split("\n").length;
|
|
9117
|
-
const command = (0,
|
|
9261
|
+
const command = (0, import_core47.clipboardCopyCommand)(deps.hasBin);
|
|
9118
9262
|
if (command) {
|
|
9119
9263
|
try {
|
|
9120
9264
|
(deps.pipeToClipboard ?? pipeToClipboardDefault)(command, text);
|
|
@@ -9219,7 +9363,7 @@ function lastAssistantMessage(plan) {
|
|
|
9219
9363
|
const history = plan?.conversationHistory ?? [];
|
|
9220
9364
|
for (let i = history.length - 1; i >= 0; i--) {
|
|
9221
9365
|
const entry = history[i];
|
|
9222
|
-
if ((0,
|
|
9366
|
+
if ((0, import_core47.isUserMessage)(entry)) return null;
|
|
9223
9367
|
if (entry.role === "assistant" && entry.kind === void 0) {
|
|
9224
9368
|
const { content, timestamp } = entry;
|
|
9225
9369
|
return { content, ...timestamp ? { timestamp } : {} };
|
|
@@ -9241,14 +9385,14 @@ async function loadModels(deps) {
|
|
|
9241
9385
|
}
|
|
9242
9386
|
async function loadSessions(deps) {
|
|
9243
9387
|
const sessions = await deps.api.getSessions(deps.workspace);
|
|
9244
|
-
const
|
|
9388
|
+
const list2 = sessions.map((s) => ({
|
|
9245
9389
|
id: String(s.id),
|
|
9246
9390
|
goal: String(s.goal ?? ""),
|
|
9247
9391
|
taskCount: Number(s.taskCount ?? 0),
|
|
9248
9392
|
status: String(s.status ?? ""),
|
|
9249
9393
|
createdAt: String(s.createdAt ?? "")
|
|
9250
9394
|
}));
|
|
9251
|
-
deps.dispatch({ type: "sessionsLoaded", sessions:
|
|
9395
|
+
deps.dispatch({ type: "sessionsLoaded", sessions: list2 });
|
|
9252
9396
|
}
|
|
9253
9397
|
async function loadRunners(deps) {
|
|
9254
9398
|
const state = await deps.api.getRunners();
|
|
@@ -9574,7 +9718,7 @@ async function handleTui(subArgs) {
|
|
|
9574
9718
|
}
|
|
9575
9719
|
const workspace = flag(subArgs, "--workspace") || process.cwd();
|
|
9576
9720
|
try {
|
|
9577
|
-
(0,
|
|
9721
|
+
(0, import_core48.assertWorkspaceExists)(workspace);
|
|
9578
9722
|
} catch {
|
|
9579
9723
|
console.error(
|
|
9580
9724
|
`Workspace "${workspace}" does not exist.
|
|
@@ -9583,7 +9727,7 @@ cd into a directory that exists, or pass --workspace <path> naming one that does
|
|
|
9583
9727
|
);
|
|
9584
9728
|
process.exit(1);
|
|
9585
9729
|
}
|
|
9586
|
-
const discoveredSkills = (0,
|
|
9730
|
+
const discoveredSkills = (0, import_core48.createSkillsService)(workspace, new import_core48.EnvConfig().workspaceRepos).listSkills();
|
|
9587
9731
|
registerSkillCommands(discoveredSkills);
|
|
9588
9732
|
const taskSkills = discoveredSkills.filter((s) => s.appliesTo === "task").map((s) => ({ name: s.name, description: s.description }));
|
|
9589
9733
|
const explicitPort = flag(subArgs, "--port") || process.env.ORDEWELL_PORT;
|
|
@@ -9595,20 +9739,20 @@ cd into a directory that exists, or pass --workspace <path> naming one that does
|
|
|
9595
9739
|
const mouseCapture = process.env.ORDEWELL_TUI_MOUSE !== "false" && process.env.ORDEWELL_TUI_MOUSE !== "0";
|
|
9596
9740
|
const app = createApp({
|
|
9597
9741
|
// The level the daemon plans with: the saved one, unless the environment overrides it (ADR-0030).
|
|
9598
|
-
initial: { workspace, autonomous: new
|
|
9742
|
+
initial: { workspace, autonomous: new import_core48.SettingsService().autonomousMode(), mouseCapture, taskSkills },
|
|
9599
9743
|
draw: (frame2) => terminal?.draw(frame2),
|
|
9600
9744
|
perform: (effect) => runEffect(effect, {
|
|
9601
9745
|
api,
|
|
9602
9746
|
workspace,
|
|
9603
9747
|
port,
|
|
9604
9748
|
dispatch: (action) => app.dispatch(action),
|
|
9605
|
-
newSessionId: () => (0,
|
|
9749
|
+
newSessionId: () => (0, import_core48.mintSessionId)(),
|
|
9606
9750
|
setEnvVar: (key, value) => {
|
|
9607
9751
|
writeEnvVar(findEnvFile(), key, value);
|
|
9608
9752
|
process.env[key] = value;
|
|
9609
9753
|
},
|
|
9610
9754
|
saveAutonomy: (enabled) => {
|
|
9611
|
-
const settings = new
|
|
9755
|
+
const settings = new import_core48.SettingsService();
|
|
9612
9756
|
settings.setAutonomousMode(enabled);
|
|
9613
9757
|
return { overridden: settings.autonomousModeOverridden() };
|
|
9614
9758
|
},
|
|
@@ -9722,7 +9866,7 @@ var COMMANDS = {
|
|
|
9722
9866
|
// src/main.ts
|
|
9723
9867
|
var TUI_FLAGS = /* @__PURE__ */ new Set(["--workspace", "--port"]);
|
|
9724
9868
|
async function main() {
|
|
9725
|
-
(0,
|
|
9869
|
+
(0, import_core49.migrateOldConfigDir)();
|
|
9726
9870
|
moveAutonomyToSettings();
|
|
9727
9871
|
loadEnvFile();
|
|
9728
9872
|
const argv = process.argv.slice(2);
|