@ordewell/cli 0.4.8 → 0.4.10
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 +55 -34
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -1409,7 +1409,8 @@ function normalizeCatalog(result) {
|
|
|
1409
1409
|
(modes ?? []).map((m) => ({
|
|
1410
1410
|
id: String(m.id),
|
|
1411
1411
|
label: String(m.label ?? m.id),
|
|
1412
|
-
description: m.description ? String(m.description) : void 0
|
|
1412
|
+
description: m.description ? String(m.description) : void 0,
|
|
1413
|
+
autonomous: m.autonomous ? true : void 0
|
|
1413
1414
|
}))
|
|
1414
1415
|
])
|
|
1415
1416
|
)
|
|
@@ -2728,9 +2729,21 @@ var import_core13 = require("@ordewell/core");
|
|
|
2728
2729
|
|
|
2729
2730
|
// src/tui/ansi.ts
|
|
2730
2731
|
var import_string_width = __toESM(require("string-width"));
|
|
2731
|
-
var
|
|
2732
|
+
var ESCAPE = /\x1b(?:\][\s\S]*?(?:\x07|\x1b\\|$)|[P^_][\s\S]*?(?:\x1b\\|$)|\[[0-?]*[ -/]*[@-~]?|[ -/]*[0-~]?)/g;
|
|
2733
|
+
var ESCAPE_SPLIT = new RegExp(`(${ESCAPE.source})`);
|
|
2734
|
+
var CONTROL = /[\x00-\x08\x0b-\x1f\x7f-\x9f]/g;
|
|
2735
|
+
var CONTROL_IN_ROW = /[\x00-\x1f\x7f-\x9f]/g;
|
|
2736
|
+
var HAS_CONTROL = /[\x00-\x1f\x7f-\x9f]/;
|
|
2737
|
+
var PAINT_ESCAPE = /^\x1b\[[0-9;]*[mGK]$/;
|
|
2732
2738
|
function stripAnsi(text) {
|
|
2733
|
-
return text.replace(
|
|
2739
|
+
return text.replace(ESCAPE, "");
|
|
2740
|
+
}
|
|
2741
|
+
function sanitize(text) {
|
|
2742
|
+
return text.replace(ESCAPE, "").replace(/\r\n?/g, "\n").replace(/\t/g, " ").replace(CONTROL, "");
|
|
2743
|
+
}
|
|
2744
|
+
function paintOnly(line) {
|
|
2745
|
+
if (!HAS_CONTROL.test(line)) return line;
|
|
2746
|
+
return line.split(ESCAPE_SPLIT).map((piece) => piece.startsWith("\x1B") ? PAINT_ESCAPE.test(piece) ? piece : "" : piece.replace(CONTROL_IN_ROW, "")).join("");
|
|
2734
2747
|
}
|
|
2735
2748
|
function width(text) {
|
|
2736
2749
|
return (0, import_string_width.default)(stripAnsi(text));
|
|
@@ -2748,9 +2761,6 @@ function truncate(text, max) {
|
|
|
2748
2761
|
}
|
|
2749
2762
|
return out + "\u2026";
|
|
2750
2763
|
}
|
|
2751
|
-
function stripTabs(text) {
|
|
2752
|
-
return text.replace(/\t/g, " ");
|
|
2753
|
-
}
|
|
2754
2764
|
function pad(text, target) {
|
|
2755
2765
|
const current = width(text);
|
|
2756
2766
|
if (current > target) return truncate(text, target);
|
|
@@ -3553,7 +3563,8 @@ function taskLines(state, task, index, cols) {
|
|
|
3553
3563
|
});
|
|
3554
3564
|
const model = task.assignedModel?.modelLabel ?? (task.type === "ai" ? "default model" : "");
|
|
3555
3565
|
const effort = task.type === "ai" ? `effort: ${task.assignedModel?.thinkingEffort ?? "default"}` : "";
|
|
3556
|
-
const
|
|
3566
|
+
const modeInfo = task.type === "ai" ? modesForTask(state.modesByRunner, task).find((m) => m.id === task.taskMode) : void 0;
|
|
3567
|
+
const mode = task.type === "ai" ? `mode: ${task.taskMode ?? "default"}${modeInfo?.autonomous ? style.yellow(" \u26A1") : ""}` : "";
|
|
3557
3568
|
const runner = task.assignedRunner ?? "";
|
|
3558
3569
|
const meta = [running ? "working" : "", runner, model].filter(Boolean).join(" \xB7 ");
|
|
3559
3570
|
if (meta) lines.push(style.grey(truncate(` ${meta}`, cols)));
|
|
@@ -3561,6 +3572,9 @@ function taskLines(state, task, index, cols) {
|
|
|
3561
3572
|
let editorLine;
|
|
3562
3573
|
if (expanded) {
|
|
3563
3574
|
lines.push(style.grey(` ${task.status.replace(/_/g, " ")}`));
|
|
3575
|
+
if (modeInfo?.autonomous) {
|
|
3576
|
+
lines.push(...taskText("Autonomy", "Runs without permission prompts. Toggle with /auto.", cols));
|
|
3577
|
+
}
|
|
3564
3578
|
const editableSeed = task.prompt ?? task.description ?? task.title;
|
|
3565
3579
|
if (task.description && task.description !== task.title && task.description !== editableSeed) {
|
|
3566
3580
|
lines.push(...taskText("Description", task.description, cols));
|
|
@@ -3671,13 +3685,16 @@ function cells(line) {
|
|
|
3671
3685
|
}
|
|
3672
3686
|
var INVERSE_ON = "\x1B[7m";
|
|
3673
3687
|
var INVERSE_OFF = "\x1B[27m";
|
|
3674
|
-
var
|
|
3688
|
+
var ESCAPE_SPLIT2 = /(\x1b\[[0-9;]*[A-Za-z])/;
|
|
3689
|
+
var CURSOR_COLUMN = /^\x1b\[([0-9]*)G$/;
|
|
3675
3690
|
function invertCells(line, from, to) {
|
|
3676
3691
|
let out = "";
|
|
3677
3692
|
let col = 1;
|
|
3678
3693
|
let inside = false;
|
|
3679
|
-
for (const piece of line.split(
|
|
3680
|
-
if (
|
|
3694
|
+
for (const piece of line.split(ESCAPE_SPLIT2)) {
|
|
3695
|
+
if (ESCAPE_SPLIT2.test(piece)) {
|
|
3696
|
+
const jump = CURSOR_COLUMN.exec(piece);
|
|
3697
|
+
if (jump) col = Number(jump[1] || "1");
|
|
3681
3698
|
out += piece + (inside ? INVERSE_ON : "");
|
|
3682
3699
|
continue;
|
|
3683
3700
|
}
|
|
@@ -3777,15 +3794,18 @@ function suggest(state, room) {
|
|
|
3777
3794
|
function renderFooter(state, cols) {
|
|
3778
3795
|
return packHints(footerHints(state), cols).map((line) => truncate(style.grey(line), cols));
|
|
3779
3796
|
}
|
|
3797
|
+
var ERASE_TO_END = "\x1B[K";
|
|
3798
|
+
var atColumn = (col) => `\x1B[${col}G`;
|
|
3780
3799
|
function renderBody(state, rows, cols) {
|
|
3781
3800
|
const planCols = planPaneWidth(state);
|
|
3782
3801
|
if (planCols === 0) return renderChat(state, rows, cols);
|
|
3783
3802
|
const chatCols = chatPaneWidth(state);
|
|
3784
3803
|
const chat = renderChat(state, rows, chatCols);
|
|
3785
3804
|
const plan = renderPlan(state, rows, planCols);
|
|
3805
|
+
const divider = `${ERASE_TO_END}${atColumn(chatCols + 1)}${style.grey("\u2502")}`;
|
|
3786
3806
|
return Array.from(
|
|
3787
3807
|
{ length: rows },
|
|
3788
|
-
(_, i) => `${pad(chat[i] ?? "", chatCols)}${
|
|
3808
|
+
(_, i) => `${pad(chat[i] ?? "", chatCols)}${divider}${pad(plan[i] ?? "", planCols)}`
|
|
3789
3809
|
);
|
|
3790
3810
|
}
|
|
3791
3811
|
function renderChat(state, rows, cols) {
|
|
@@ -3896,13 +3916,13 @@ function step(state, effects = []) {
|
|
|
3896
3916
|
return { state, effects };
|
|
3897
3917
|
}
|
|
3898
3918
|
function say(state, role, content, research) {
|
|
3899
|
-
const message = { role, content:
|
|
3919
|
+
const message = { role, content: sanitize(content), timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...research ? { research } : {} };
|
|
3900
3920
|
return { ...state, messages: [...state.messages, message], scroll: 0 };
|
|
3901
3921
|
}
|
|
3902
3922
|
function restoredMessages(history) {
|
|
3903
3923
|
return history.map((entry) => ({
|
|
3904
3924
|
role: entry.kind === "plan_generated" ? "system" : entry.kind === "system" ? "system" : entry.role,
|
|
3905
|
-
content:
|
|
3925
|
+
content: sanitize(entry.kind === "plan_generated" ? "Plan generated." : entry.content),
|
|
3906
3926
|
timestamp: entry.timestamp
|
|
3907
3927
|
}));
|
|
3908
3928
|
}
|
|
@@ -3916,13 +3936,13 @@ function researchLabel(messages, summary) {
|
|
|
3916
3936
|
return others > 0 ? `${summary} (+${others} more)` : summary;
|
|
3917
3937
|
}
|
|
3918
3938
|
function settleResearchStep(messages, action) {
|
|
3919
|
-
const summary =
|
|
3939
|
+
const summary = sanitize(action.summary);
|
|
3920
3940
|
const index = findLastIndex(messages, (m) => isPendingResearch(m) && (action.toolCallId ? m.research?.toolCallId === action.toolCallId : m.content === summary));
|
|
3921
3941
|
if (index < 0) return messages;
|
|
3922
3942
|
const next = [...messages];
|
|
3923
3943
|
next[index] = {
|
|
3924
3944
|
...next[index],
|
|
3925
|
-
research: { ...next[index].research, outcome: action.outcome, result:
|
|
3945
|
+
research: { ...next[index].research, outcome: action.outcome, result: sanitize(action.result) }
|
|
3926
3946
|
};
|
|
3927
3947
|
return next;
|
|
3928
3948
|
}
|
|
@@ -3980,13 +4000,13 @@ function reduce(state, action) {
|
|
|
3980
4000
|
case "plannerMessage": {
|
|
3981
4001
|
if (stale(state, action.sessionId)) return step(state);
|
|
3982
4002
|
const settled = { ...state, status: "idle", busyLabel: "", thinkingLine: "" };
|
|
3983
|
-
const content =
|
|
4003
|
+
const content = sanitize(action.content);
|
|
3984
4004
|
if (alreadySpoken(state.messages, content)) return step(settled);
|
|
3985
4005
|
return step(say(settled, "assistant", content));
|
|
3986
4006
|
}
|
|
3987
4007
|
case "researchStep": {
|
|
3988
4008
|
if (stale(state, action.sessionId)) return step(state);
|
|
3989
|
-
const summary =
|
|
4009
|
+
const summary = sanitize(action.summary);
|
|
3990
4010
|
const spoken = say(state, "research", summary, { toolCallId: action.toolCallId });
|
|
3991
4011
|
const status = state.status === "planning" ? "researching" : state.status;
|
|
3992
4012
|
return step({ ...spoken, status, busyLabel: researchLabel(spoken.messages, summary) });
|
|
@@ -4005,7 +4025,7 @@ function reduce(state, action) {
|
|
|
4005
4025
|
}
|
|
4006
4026
|
case "plannerThinking": {
|
|
4007
4027
|
if (stale(state, action.sessionId)) return step(state);
|
|
4008
|
-
return step({ ...state, thinkingLine: (state.thinkingLine + action.text).slice(-THINKING_TAIL) });
|
|
4028
|
+
return step({ ...state, thinkingLine: (state.thinkingLine + sanitize(action.text)).slice(-THINKING_TAIL) });
|
|
4009
4029
|
}
|
|
4010
4030
|
case "taskStatus": {
|
|
4011
4031
|
if (stale(state, action.sessionId) || !state.tasks.some((t) => t.id === action.taskId)) return step(state);
|
|
@@ -4094,6 +4114,8 @@ function reduce(state, action) {
|
|
|
4094
4114
|
return step({ ...state, spinnerFrame: (state.spinnerFrame + 1) % 10 });
|
|
4095
4115
|
}
|
|
4096
4116
|
}
|
|
4117
|
+
var planText = (value, fallback = "") => sanitize(String(value ?? fallback));
|
|
4118
|
+
var planLabel = (value, fallback = "") => planText(value, fallback).replace(/\n+/g, " ");
|
|
4097
4119
|
function normalizeTasks(plan) {
|
|
4098
4120
|
const source = plan;
|
|
4099
4121
|
const byId = /* @__PURE__ */ new Map();
|
|
@@ -4106,19 +4128,19 @@ function normalizeTasks(plan) {
|
|
|
4106
4128
|
return raw.map((t, i) => ({
|
|
4107
4129
|
id: String(t.id ?? `task-${i + 1}`),
|
|
4108
4130
|
order: typeof t.order === "number" ? t.order : i + 1,
|
|
4109
|
-
title:
|
|
4110
|
-
description:
|
|
4111
|
-
prompt: typeof t.prompt === "string" ? t.prompt : void 0,
|
|
4131
|
+
title: planLabel(t.title, "Untitled task"),
|
|
4132
|
+
description: planText(t.description ?? t.title),
|
|
4133
|
+
prompt: typeof t.prompt === "string" ? sanitize(t.prompt) : void 0,
|
|
4112
4134
|
type: t.type === "user" ? "user" : "ai",
|
|
4113
|
-
status:
|
|
4114
|
-
dependencies: Array.isArray(t.dependencies) ? t.dependencies.map(
|
|
4115
|
-
assignedRunner: typeof t.assignedRunner === "string" ? t.assignedRunner : void 0,
|
|
4116
|
-
taskMode: typeof t.taskMode === "string" ? t.taskMode : void 0,
|
|
4135
|
+
status: planLabel(t.status, "pending"),
|
|
4136
|
+
dependencies: Array.isArray(t.dependencies) ? t.dependencies.map((id) => planLabel(id)) : [],
|
|
4137
|
+
assignedRunner: typeof t.assignedRunner === "string" ? planLabel(t.assignedRunner) : void 0,
|
|
4138
|
+
taskMode: typeof t.taskMode === "string" ? planLabel(t.taskMode) : void 0,
|
|
4117
4139
|
assignedModel: t.assignedModel && typeof t.assignedModel === "object" ? {
|
|
4118
|
-
modelId:
|
|
4119
|
-
modelLabel:
|
|
4120
|
-
thinkingEffort: typeof t.assignedModel.thinkingEffort === "string" ? t.assignedModel.thinkingEffort : typeof t.thinkingEffort === "string" ? t.thinkingEffort : void 0,
|
|
4121
|
-
availableVariants: Array.isArray(t.assignedModel.availableVariants) ? t.assignedModel.availableVariants.map(
|
|
4140
|
+
modelId: planLabel(t.assignedModel.modelId),
|
|
4141
|
+
modelLabel: planLabel(t.assignedModel.modelLabel ?? t.assignedModel.modelId),
|
|
4142
|
+
thinkingEffort: typeof t.assignedModel.thinkingEffort === "string" ? planLabel(t.assignedModel.thinkingEffort) : typeof t.thinkingEffort === "string" ? planLabel(t.thinkingEffort) : void 0,
|
|
4143
|
+
availableVariants: Array.isArray(t.assignedModel.availableVariants) ? t.assignedModel.availableVariants.map((variant) => planLabel(variant)) : void 0
|
|
4122
4144
|
} : void 0
|
|
4123
4145
|
}));
|
|
4124
4146
|
}
|
|
@@ -5740,7 +5762,7 @@ async function loadSettings(deps) {
|
|
|
5740
5762
|
}
|
|
5741
5763
|
|
|
5742
5764
|
// src/tui/keys.ts
|
|
5743
|
-
var
|
|
5765
|
+
var CONTROL2 = {
|
|
5744
5766
|
"\r": "enter",
|
|
5745
5767
|
"\n": "enter",
|
|
5746
5768
|
" ": "tab",
|
|
@@ -5845,7 +5867,7 @@ function decodeMouse(seq) {
|
|
|
5845
5867
|
function decodeKey(seq) {
|
|
5846
5868
|
const escaped = ESCAPES[seq];
|
|
5847
5869
|
if (escaped) return { name: escaped };
|
|
5848
|
-
const control =
|
|
5870
|
+
const control = CONTROL2[seq];
|
|
5849
5871
|
if (control) return { name: control };
|
|
5850
5872
|
if (seq.startsWith("\x1B[")) {
|
|
5851
5873
|
const mouse = decodeMouse(seq);
|
|
@@ -5857,8 +5879,7 @@ function decodeKey(seq) {
|
|
|
5857
5879
|
var PASTE_START = "\x1B[200~";
|
|
5858
5880
|
var PASTE_END = "\x1B[201~";
|
|
5859
5881
|
function pasteKey(raw) {
|
|
5860
|
-
|
|
5861
|
-
return { name: "paste", text };
|
|
5882
|
+
return { name: "paste", text: sanitize(raw) };
|
|
5862
5883
|
}
|
|
5863
5884
|
function createKeyDecoder() {
|
|
5864
5885
|
let paste = null;
|
|
@@ -5992,7 +6013,7 @@ function openTerminal(options) {
|
|
|
5992
6013
|
draw(frame2) {
|
|
5993
6014
|
if (closed) return;
|
|
5994
6015
|
const { cols } = size();
|
|
5995
|
-
const rows = frame2.map((line, i) => `\x1B[${i + 1};1H${clampToCols(line, cols)}\x1B[K`).join("");
|
|
6016
|
+
const rows = frame2.map((line, i) => `\x1B[${i + 1};1H${clampToCols(paintOnly(line), cols)}\x1B[K`).join("");
|
|
5996
6017
|
output.write(AUTOWRAP_OFF + rows + AUTOWRAP_ON);
|
|
5997
6018
|
},
|
|
5998
6019
|
setMouse(enabled) {
|
package/package.json
CHANGED