@ordewell/cli 0.5.1 → 0.5.3
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 +182 -64
- package/package.json +4 -4
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_core23 = require("@ordewell/core");
|
|
28
28
|
|
|
29
29
|
// src/utils/env.ts
|
|
30
30
|
var import_fs = require("fs");
|
|
@@ -95,6 +95,7 @@ Planning:
|
|
|
95
95
|
ordewell fork Continue in a copy of the conversation and its tasks
|
|
96
96
|
ordewell compact Condense the conversation into a summary (tasks are kept)
|
|
97
97
|
ordewell rewind [<n>] Fork the conversation from before message <n> (no <n>: list them)
|
|
98
|
+
ordewell handoff [action] Review, merge, discard or clean up a finished isolated run
|
|
98
99
|
|
|
99
100
|
Tasks (<id> is an order number or a task ID):
|
|
100
101
|
ordewell add-task --title "..." Add a task to the current plan
|
|
@@ -123,6 +124,7 @@ Planner, models and runners:
|
|
|
123
124
|
ordewell runners [<id> on|off] Enable or disable runners (claude-code, opencode, codex)
|
|
124
125
|
ordewell allowlist set|clear|show Limit which models a runner may use
|
|
125
126
|
ordewell auto [on|off] Autonomous permission mode for new sessions
|
|
127
|
+
ordewell parallel [<n>] How many AI tasks run at once (default 3; applies to a live run)
|
|
126
128
|
ordewell refresh Re-discover runners and model catalogs
|
|
127
129
|
ordewell models List every provider's catalog (works without a server)
|
|
128
130
|
|
|
@@ -196,8 +198,9 @@ Environment:
|
|
|
196
198
|
OPENROUTER_BASE_URL Default: https://openrouter.ai/api/v1
|
|
197
199
|
ORDEWELL_AUTONOMOUS_MODE Approval posture for new sessions (see "ordewell auto")
|
|
198
200
|
ORDEWELL_PORT Daemon port CLI commands target (default: 3742)
|
|
201
|
+
ORDEWELL_DIRENV false: agents skip the project's direnv .envrc
|
|
199
202
|
ORDEWELL_RESEARCH_ENABLED true (default) or false
|
|
200
|
-
ORDEWELL_MAX_PARALLEL Default: 3
|
|
203
|
+
ORDEWELL_MAX_PARALLEL Default: 3 \u2014 set with "ordewell parallel"
|
|
201
204
|
`);
|
|
202
205
|
}
|
|
203
206
|
|
|
@@ -387,10 +390,15 @@ var WorkspaceInitNeededError = class extends Error {
|
|
|
387
390
|
}
|
|
388
391
|
workspace;
|
|
389
392
|
};
|
|
390
|
-
var
|
|
393
|
+
var SESSION_PATH = /^\/api\/(?:plans|sessions)\/([^/?]+)/;
|
|
394
|
+
var ApiClient = class _ApiClient {
|
|
395
|
+
/** Where a CLI invocation's sessions live, when a client is built without one: `--workspace`, else the cwd. */
|
|
396
|
+
static defaultWorkspace;
|
|
391
397
|
port;
|
|
392
|
-
|
|
398
|
+
workspace;
|
|
399
|
+
constructor(port, workspace) {
|
|
393
400
|
this.port = port || DEFAULT_PORT;
|
|
401
|
+
this.workspace = workspace ?? _ApiClient.defaultWorkspace ?? process.cwd();
|
|
394
402
|
}
|
|
395
403
|
/**
|
|
396
404
|
* Read at call time rather than at construction: a daemon restarted mid-run
|
|
@@ -400,7 +408,23 @@ var ApiClient = class {
|
|
|
400
408
|
token() {
|
|
401
409
|
return (0, import_core3.readDaemonToken)(this.port);
|
|
402
410
|
}
|
|
403
|
-
|
|
411
|
+
/**
|
|
412
|
+
* A daemon holds only the sessions adopted since it started, so after a
|
|
413
|
+
* restart every session-scoped call answered "Session not found" until the
|
|
414
|
+
* user ran `ordewell sessions load`. The saved session is adopted here
|
|
415
|
+
* instead — idempotent for one the daemon still holds — and the call made
|
|
416
|
+
* once more; a 404 means the first attempt never ran, so the retry cannot
|
|
417
|
+
* act twice.
|
|
418
|
+
*/
|
|
419
|
+
async httpRequest(method, urlPath, body) {
|
|
420
|
+
const res = await this.rawRequest(method, urlPath, body);
|
|
421
|
+
const sessionId = urlPath.match(SESSION_PATH)?.[1];
|
|
422
|
+
const missing = res.status === 404 && res.data?.error === "Session not found";
|
|
423
|
+
if (!missing || !sessionId || urlPath.split("?")[0].endsWith("/load")) return res;
|
|
424
|
+
const adopted2 = await this.rawRequest("POST", `/api/sessions/${sessionId}/load?workspace=${encodeURIComponent(this.workspace)}`);
|
|
425
|
+
return adopted2.status === 200 ? this.rawRequest(method, urlPath, body) : res;
|
|
426
|
+
}
|
|
427
|
+
rawRequest(method, urlPath, body) {
|
|
404
428
|
return new Promise((resolve3, reject) => {
|
|
405
429
|
const url = new URL(urlPath, `http://127.0.0.1:${this.port}`);
|
|
406
430
|
const configuredTimeout = Number.parseInt(process.env.ORDEWELL_HTTP_TIMEOUT_MS || "", 10);
|
|
@@ -941,6 +965,25 @@ function readLastSession(workspace) {
|
|
|
941
965
|
}
|
|
942
966
|
return null;
|
|
943
967
|
}
|
|
968
|
+
var SESSION_PREFIX = "session-";
|
|
969
|
+
function expandSessionId(id, workspace) {
|
|
970
|
+
if (id.startsWith(SESSION_PREFIX)) return id;
|
|
971
|
+
let files;
|
|
972
|
+
try {
|
|
973
|
+
files = (0, import_fs3.readdirSync)((0, import_path3.join)((0, import_core5.getStateDir)(workspace), "sessions")).filter((f) => f.endsWith(".json"));
|
|
974
|
+
} catch {
|
|
975
|
+
return id;
|
|
976
|
+
}
|
|
977
|
+
const matches = /* @__PURE__ */ new Set();
|
|
978
|
+
for (const file of files) {
|
|
979
|
+
try {
|
|
980
|
+
const full = JSON.parse((0, import_fs3.readFileSync)((0, import_path3.join)((0, import_core5.getStateDir)(workspace), "sessions", file), "utf8"))?.meta?.id;
|
|
981
|
+
if (typeof full === "string" && (full.endsWith(id) || full.slice(SESSION_PREFIX.length).startsWith(id))) matches.add(full);
|
|
982
|
+
} catch {
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
return matches.size === 1 ? [...matches][0] : id;
|
|
986
|
+
}
|
|
944
987
|
|
|
945
988
|
// src/approvals.ts
|
|
946
989
|
function describeApproval(event) {
|
|
@@ -1043,7 +1086,7 @@ function isTransient(event) {
|
|
|
1043
1086
|
// src/commands/plan.ts
|
|
1044
1087
|
var import_core6 = require("@ordewell/core");
|
|
1045
1088
|
function planTasks(plan) {
|
|
1046
|
-
return plan
|
|
1089
|
+
return plan ? allTasksOf(plan) : [];
|
|
1047
1090
|
}
|
|
1048
1091
|
function hasCommittedPlan(plan) {
|
|
1049
1092
|
return planTasks(plan).length > 0;
|
|
@@ -1111,7 +1154,7 @@ function printPlan(plan, sessionId, runners2, models) {
|
|
|
1111
1154
|
return rp ? ` (${task.assignedModel.modelLabel} \xB7 ${label})` : ` (${task.assignedModel.modelLabel})`;
|
|
1112
1155
|
};
|
|
1113
1156
|
console.log(`
|
|
1114
|
-
Plan: ${tasks.length} tasks (${aiCount} AI, ${manCount} Manual) \u2014 ${(plan.runners || runners2).join(", ")}`);
|
|
1157
|
+
Plan: ${tasks.length} task${tasks.length === 1 ? "" : "s"} (${aiCount} AI, ${manCount} Manual) \u2014 ${(plan.runners || runners2).join(", ")}`);
|
|
1115
1158
|
console.log(`Session: ${sessionId}
|
|
1116
1159
|
`);
|
|
1117
1160
|
for (const t of tasks) {
|
|
@@ -2961,30 +3004,47 @@ async function handlePlannerEffort(subArgs, injectedApi) {
|
|
|
2961
3004
|
console.log(`Planner effort set to ${level}.`);
|
|
2962
3005
|
}
|
|
2963
3006
|
|
|
2964
|
-
// src/commands/
|
|
3007
|
+
// src/commands/parallel.ts
|
|
2965
3008
|
var import_core14 = require("@ordewell/core");
|
|
2966
|
-
var USAGE5 = "Usage: ordewell
|
|
3009
|
+
var USAGE5 = "Usage: ordewell parallel [<number of tasks, 1 or more>]";
|
|
3010
|
+
async function handleParallel(subArgs, injectedApi) {
|
|
3011
|
+
const [wanted] = positionals(subArgs);
|
|
3012
|
+
const api = await connect(subArgs, injectedApi);
|
|
3013
|
+
if (!wanted || wanted === "show") {
|
|
3014
|
+
const settings = await api.getSettings();
|
|
3015
|
+
console.log(`Up to ${String(settings.maxParallel ?? "?")} AI tasks run at once. Change with: ordewell parallel <n>`);
|
|
3016
|
+
return;
|
|
3017
|
+
}
|
|
3018
|
+
const limit = (0, import_core14.parseMaxParallel)(wanted);
|
|
3019
|
+
if (limit === null) fail(`"${wanted}" is not a number of tasks (1 or more).`, USAGE5);
|
|
3020
|
+
await persistEnv(api, { ORDEWELL_MAX_PARALLEL: String(limit) });
|
|
3021
|
+
console.log(`Up to ${limit} AI task${limit === 1 ? "" : "s"} now run at once.`);
|
|
3022
|
+
}
|
|
3023
|
+
|
|
3024
|
+
// src/commands/key.ts
|
|
3025
|
+
var import_core15 = require("@ordewell/core");
|
|
3026
|
+
var USAGE6 = "Usage: ordewell key [list | set <provider> <key>]";
|
|
2967
3027
|
async function handleKey(subArgs, injectedApi) {
|
|
2968
3028
|
const [action, provider, ...keyParts] = positionals(subArgs);
|
|
2969
3029
|
if (action && action !== "list" && action !== "set") {
|
|
2970
|
-
fail(`Unknown key action: "${action}"`,
|
|
3030
|
+
fail(`Unknown key action: "${action}"`, USAGE6);
|
|
2971
3031
|
}
|
|
2972
3032
|
const api = await connect(subArgs, injectedApi);
|
|
2973
3033
|
if (action !== "set") {
|
|
2974
3034
|
const catalog = await fetchCatalog(api);
|
|
2975
3035
|
console.log("\nAPI provider keys\n");
|
|
2976
|
-
for (const id2 of
|
|
2977
|
-
const meta2 =
|
|
3036
|
+
for (const id2 of import_core15.PROVIDER_PRIORITY) {
|
|
3037
|
+
const meta2 = import_core15.ALL_PROVIDERS[id2];
|
|
2978
3038
|
const configured = catalog.providers.includes(id2);
|
|
2979
3039
|
console.log(` ${configured ? "\u2713" : " "} ${id2.padEnd(14)} ${meta2.apiKeyEnvVar.padEnd(28)} ${meta2.label}`);
|
|
2980
3040
|
}
|
|
2981
3041
|
console.log(`
|
|
2982
|
-
\u2713 = a working key was found. ${
|
|
3042
|
+
\u2713 = a working key was found. ${USAGE6}`);
|
|
2983
3043
|
return;
|
|
2984
3044
|
}
|
|
2985
|
-
if (!provider) fail(
|
|
3045
|
+
if (!provider) fail(USAGE6);
|
|
2986
3046
|
const id = provider.toLowerCase();
|
|
2987
|
-
const meta =
|
|
3047
|
+
const meta = import_core15.ALL_PROVIDERS[id];
|
|
2988
3048
|
if (!meta) {
|
|
2989
3049
|
fail(`Unknown provider: ${provider}`, "Run `ordewell key` to see the list.");
|
|
2990
3050
|
}
|
|
@@ -2995,7 +3055,7 @@ async function handleKey(subArgs, injectedApi) {
|
|
|
2995
3055
|
}
|
|
2996
3056
|
|
|
2997
3057
|
// src/commands/runners.ts
|
|
2998
|
-
var
|
|
3058
|
+
var USAGE7 = "Usage: ordewell runners [<runner-id> on|off]";
|
|
2999
3059
|
async function handleRunners(subArgs, injectedApi) {
|
|
3000
3060
|
const [runner, toggle] = positionals(subArgs);
|
|
3001
3061
|
const api = await connect(subArgs, injectedApi);
|
|
@@ -3006,7 +3066,7 @@ async function handleRunners(subArgs, injectedApi) {
|
|
|
3006
3066
|
console.log(` ${r.enabled ? "\u2713" : " "} ${r.id.padEnd(14)} ${r.name}${r.enabled ? "" : " (disabled)"}`);
|
|
3007
3067
|
}
|
|
3008
3068
|
console.log(`
|
|
3009
|
-
\u2713 = offered to the planner. ${
|
|
3069
|
+
\u2713 = offered to the planner. ${USAGE7}`);
|
|
3010
3070
|
return;
|
|
3011
3071
|
}
|
|
3012
3072
|
const state = await api.getRunners();
|
|
@@ -3015,7 +3075,7 @@ async function handleRunners(subArgs, injectedApi) {
|
|
|
3015
3075
|
fail(`Unknown runner: ${runner}`, `Enabled or not, this daemon knows: ${state.runners.map((r) => r.id).join(", ")}`);
|
|
3016
3076
|
}
|
|
3017
3077
|
const enabled = toggle === void 0 ? !known.enabled : toggle === "on" ? true : toggle === "off" ? false : null;
|
|
3018
|
-
if (enabled === null) fail(
|
|
3078
|
+
if (enabled === null) fail(USAGE7);
|
|
3019
3079
|
await api.setRunnerEnabled(runner, enabled);
|
|
3020
3080
|
console.log(`${runner} ${enabled ? "enabled" : "disabled"}.`);
|
|
3021
3081
|
}
|
|
@@ -3065,7 +3125,7 @@ async function handleApprove(subArgs, injectedApi) {
|
|
|
3065
3125
|
// src/tui/terminalLauncher.ts
|
|
3066
3126
|
var import_child_process3 = require("child_process");
|
|
3067
3127
|
var import_util = require("util");
|
|
3068
|
-
var
|
|
3128
|
+
var import_core16 = require("@ordewell/core");
|
|
3069
3129
|
var execFileAsync = (0, import_util.promisify)(import_child_process3.execFile);
|
|
3070
3130
|
var defaultExecFile = async (command, args) => {
|
|
3071
3131
|
const { stdout, stderr } = await execFileAsync(command, args);
|
|
@@ -3085,16 +3145,16 @@ var defaultWhich = (bin) => {
|
|
|
3085
3145
|
async function openTaskTerminal(port, planSessionId, taskId, deps = {}) {
|
|
3086
3146
|
const platform = deps.platform ?? process.platform;
|
|
3087
3147
|
const env = deps.env ?? process.env;
|
|
3088
|
-
const hasTmuxImpl = deps.hasTmuxImpl ??
|
|
3148
|
+
const hasTmuxImpl = deps.hasTmuxImpl ?? import_core16.hasTmux;
|
|
3089
3149
|
const execFileImpl = deps.execFileImpl ?? defaultExecFile;
|
|
3090
3150
|
const spawnImpl = deps.spawnImpl ?? defaultSpawn;
|
|
3091
3151
|
const which = deps.which ?? defaultWhich;
|
|
3092
3152
|
if (!hasTmuxImpl()) {
|
|
3093
3153
|
return { ok: false, message: "tmux is not installed \u2014 install it to get a real terminal per task." };
|
|
3094
3154
|
}
|
|
3095
|
-
const session = (0,
|
|
3096
|
-
const socket = (0,
|
|
3097
|
-
const base = (0,
|
|
3155
|
+
const session = (0, import_core16.tmuxSessionName)(port);
|
|
3156
|
+
const socket = (0, import_core16.tmuxSocketName)(port);
|
|
3157
|
+
const base = (0, import_core16.tmuxWindowName)(taskId, planSessionId);
|
|
3098
3158
|
let windows;
|
|
3099
3159
|
try {
|
|
3100
3160
|
const { stdout } = await execFileImpl("tmux", ["-L", socket, "list-windows", "-t", session, "-F", "#{window_name}"]);
|
|
@@ -3388,7 +3448,7 @@ Dependencies \xB7 #${task.order} ${task.title}
|
|
|
3388
3448
|
}
|
|
3389
3449
|
|
|
3390
3450
|
// src/tui/index.ts
|
|
3391
|
-
var
|
|
3451
|
+
var import_core22 = require("@ordewell/core");
|
|
3392
3452
|
|
|
3393
3453
|
// src/tui/editor.ts
|
|
3394
3454
|
function emptyEditor() {
|
|
@@ -3550,6 +3610,7 @@ var SLASH_COMMANDS = [
|
|
|
3550
3610
|
{ name: "allowlist", usage: "/allowlist [set <runner> <ids> | clear <runner>]", description: "Limit which models a runner may use", category: "models" },
|
|
3551
3611
|
{ name: "runners", usage: "/runners [<id> on|off]", description: "Enable or disable runners (claude-code, opencode, codex)", category: "models" },
|
|
3552
3612
|
{ name: "auto", usage: "/auto [on|off]", description: "Autonomous permission mode for new plans", category: "models" },
|
|
3613
|
+
{ name: "parallel", usage: "/parallel [<n>]", description: "How many AI tasks run at once (applies to a live run)", category: "models" },
|
|
3553
3614
|
{ name: "refresh", usage: "/refresh", description: "Re-discover runners and model catalogs", category: "models" },
|
|
3554
3615
|
// Skills
|
|
3555
3616
|
{ name: "tdd", usage: "/tdd [on|off]", description: "Test-Driven Development mode", category: "skills" },
|
|
@@ -3774,6 +3835,7 @@ function chatEditorRoom(cols, active) {
|
|
|
3774
3835
|
}
|
|
3775
3836
|
|
|
3776
3837
|
// src/tui/state.ts
|
|
3838
|
+
var import_core17 = require("@ordewell/core");
|
|
3777
3839
|
var SKILL_IDS = ["tdd", "verify"];
|
|
3778
3840
|
function noSkills() {
|
|
3779
3841
|
return { tdd: false, verify: false };
|
|
@@ -3838,6 +3900,7 @@ function initialState(overrides = {}) {
|
|
|
3838
3900
|
orchestratorModel: "",
|
|
3839
3901
|
plannerProvider: "",
|
|
3840
3902
|
plannerEffort: "",
|
|
3903
|
+
maxParallel: import_core17.DEFAULT_MAX_PARALLEL,
|
|
3841
3904
|
configuredProviders: [],
|
|
3842
3905
|
allowlist: {},
|
|
3843
3906
|
autonomous: true,
|
|
@@ -3857,7 +3920,7 @@ function initialState(overrides = {}) {
|
|
|
3857
3920
|
}
|
|
3858
3921
|
|
|
3859
3922
|
// src/tui/layout.ts
|
|
3860
|
-
var
|
|
3923
|
+
var import_core18 = require("@ordewell/core");
|
|
3861
3924
|
var CHROME_ROWS = 4;
|
|
3862
3925
|
function chatInputWrap(state) {
|
|
3863
3926
|
const active = state.focus === "chat" && !state.overlay;
|
|
@@ -3993,9 +4056,9 @@ function chatScrollMax(state) {
|
|
|
3993
4056
|
}
|
|
3994
4057
|
function plannerSetup(state) {
|
|
3995
4058
|
const provider = state.plannerProvider;
|
|
3996
|
-
const registration =
|
|
4059
|
+
const registration = import_core18.ALL_PROVIDERS[provider];
|
|
3997
4060
|
if (!registration) return { label: "not set", ready: false };
|
|
3998
|
-
const runner = (0,
|
|
4061
|
+
const runner = (0, import_core18.runnerForProvider)(provider);
|
|
3999
4062
|
const ready = runner ? state.runners.some((r) => r.id === runner) : state.configuredProviders.includes(provider);
|
|
4000
4063
|
return { label: registration.label, ready };
|
|
4001
4064
|
}
|
|
@@ -4178,7 +4241,7 @@ function taskLines(state, row, index, cols) {
|
|
|
4178
4241
|
const icon = paint(rawIcon);
|
|
4179
4242
|
const kind = running ? style.yellow("RUN") : task.type === "user" ? style.yellow("MAN") : style.grey(" AI");
|
|
4180
4243
|
const caret = selected ? style.cyan("\u276F") : " ";
|
|
4181
|
-
const orderLabel = parent ? (0,
|
|
4244
|
+
const orderLabel = parent ? (0, import_core18.taskOrderLabel)(task, parent) : String(task.order).padStart(2);
|
|
4182
4245
|
const indent = parent ? " " : "";
|
|
4183
4246
|
const head = `${indent}${caret} ${icon} ${orderLabel} ${kind} `;
|
|
4184
4247
|
const titleRoom = Math.max(1, cols - width(head));
|
|
@@ -4199,21 +4262,22 @@ function taskLines(state, row, index, cols) {
|
|
|
4199
4262
|
const mode = task.type === "ai" ? `mode: ${task.taskMode ?? "default"}${modeInfo?.autonomous ? style.yellow(" \u26A1") : ""}` : "";
|
|
4200
4263
|
const runner = task.assignedRunner ?? "";
|
|
4201
4264
|
const bodyPad = parent ? " " : " ";
|
|
4202
|
-
const
|
|
4265
|
+
const activity = idle ? "quiet \u2014 t opens its terminal" : running ? "working" : "";
|
|
4266
|
+
const meta = [activity, runner, model].filter(Boolean).join(" \xB7 ");
|
|
4203
4267
|
if (meta) lines.push(style.grey(truncate(`${bodyPad}${meta}`, cols)));
|
|
4204
4268
|
if (effort || mode) lines.push(style.grey(truncate(`${bodyPad}${[effort, mode].filter(Boolean).join(" \xB7 ")}`, cols)));
|
|
4205
4269
|
if (task.isolation?.state === "conflict") {
|
|
4206
4270
|
const where = task.isolation.conflictRepo && task.isolation.conflictRepo !== "." ? ` in ${task.isolation.conflictRepo}` : "";
|
|
4207
|
-
const files = task.isolation.conflictFiles?.length ? ` (${(0,
|
|
4271
|
+
const files = task.isolation.conflictFiles?.length ? ` (${(0, import_core18.capConflictFiles)(task.isolation.conflictFiles)})` : "";
|
|
4208
4272
|
lines.push(style.red(truncate(`${bodyPad}\u26A0 merge conflict${where}${files} \u2014 its work is kept on its own branch`, cols)));
|
|
4209
4273
|
}
|
|
4210
4274
|
if (task.isolation?.state === "repairing") {
|
|
4211
|
-
const files = task.isolation.conflictFiles?.length ? ` in ${(0,
|
|
4275
|
+
const files = task.isolation.conflictFiles?.length ? ` in ${(0, import_core18.capConflictFiles)(task.isolation.conflictFiles)}` : "";
|
|
4212
4276
|
const attempt = task.isolation.repair ? ` (attempt ${task.isolation.repair.attempt}/${task.isolation.repair.limit})` : "";
|
|
4213
4277
|
lines.push(style.yellow(truncate(`${bodyPad}\u21BB repairing conflict${files}${attempt}`, cols)));
|
|
4214
4278
|
}
|
|
4215
4279
|
if (task.isolation?.state === "integrated" && task.isolation.repairedFiles?.length) {
|
|
4216
|
-
lines.push(style.grey(truncate(`${bodyPad}\u21BB landed after repairing conflict in ${(0,
|
|
4280
|
+
lines.push(style.grey(truncate(`${bodyPad}\u21BB landed after repairing conflict in ${(0, import_core18.capConflictFiles)(task.isolation.repairedFiles)}`, cols)));
|
|
4217
4281
|
}
|
|
4218
4282
|
let editorLine;
|
|
4219
4283
|
if (expanded) {
|
|
@@ -4298,7 +4362,7 @@ function helpScrollMax(state) {
|
|
|
4298
4362
|
}
|
|
4299
4363
|
|
|
4300
4364
|
// src/tui/render.ts
|
|
4301
|
-
var
|
|
4365
|
+
var import_core19 = require("@ordewell/core");
|
|
4302
4366
|
function render(state) {
|
|
4303
4367
|
const { rows, cols } = state;
|
|
4304
4368
|
const rowsForBody = bodyRows(state);
|
|
@@ -4562,7 +4626,7 @@ function renderHandoff(state, overlay, rows, cols) {
|
|
|
4562
4626
|
return frame(`Diff \u2014 ${handoffBranch(handoff)}`, [...shown, "", style.grey(`${more}enter or esc goes back`)], rows, cols);
|
|
4563
4627
|
}
|
|
4564
4628
|
const landed = handoff.landed.length === 0 ? [style.grey("Nothing landed on it.")] : handoff.landed.map((task) => {
|
|
4565
|
-
const repaired = task.repairedFiles?.length ? style.yellow(` \u2014 repaired (${(0,
|
|
4629
|
+
const repaired = task.repairedFiles?.length ? style.yellow(` \u2014 repaired (${(0, import_core19.capConflictFiles)(task.repairedFiles)})`) : "";
|
|
4566
4630
|
return ` ${style.green("\u2713")} #${task.order} ${task.title}${repaired}`;
|
|
4567
4631
|
});
|
|
4568
4632
|
const actions = handoffActions(handoff).map((action, index) => {
|
|
@@ -4652,9 +4716,9 @@ function frame(title, body, rows, cols) {
|
|
|
4652
4716
|
}
|
|
4653
4717
|
|
|
4654
4718
|
// src/tui/reducer.ts
|
|
4655
|
-
var
|
|
4719
|
+
var import_core20 = require("@ordewell/core");
|
|
4656
4720
|
var import_plan_utils3 = require("@ordewell/core/plan-utils");
|
|
4657
|
-
var KNOWN_PROVIDERS2 = Object.keys(
|
|
4721
|
+
var KNOWN_PROVIDERS2 = Object.keys(import_core20.ALL_PROVIDERS);
|
|
4658
4722
|
var DEFAULT_EFFORT = "__runner_default__";
|
|
4659
4723
|
function step(state, effects = []) {
|
|
4660
4724
|
return { state, effects };
|
|
@@ -4673,6 +4737,17 @@ function alreadySpoken(messages, content) {
|
|
|
4673
4737
|
const redrawn = messages.at(-1)?.role === "system" && messages.at(-1)?.content === content;
|
|
4674
4738
|
return spoken || redrawn;
|
|
4675
4739
|
}
|
|
4740
|
+
function runLabel(tasks) {
|
|
4741
|
+
const running = tasks.filter(isTaskRunning);
|
|
4742
|
+
if (running.length > 0) {
|
|
4743
|
+
const [first] = running;
|
|
4744
|
+
const name = first.assignedRunner ? `${first.title} \xB7 ${first.assignedRunner}` : first.title;
|
|
4745
|
+
return running.length > 1 ? `${name} (+${running.length - 1} more)` : name;
|
|
4746
|
+
}
|
|
4747
|
+
const waiting = tasks.filter((t) => t.status === "awaiting_user").length;
|
|
4748
|
+
if (waiting === 0) return "";
|
|
4749
|
+
return waiting === 1 ? "1 task waits for you" : `${waiting} tasks wait for you`;
|
|
4750
|
+
}
|
|
4676
4751
|
function researchLabel(messages, summary) {
|
|
4677
4752
|
const others = messages.filter(isPendingResearch).length - 1;
|
|
4678
4753
|
return others > 0 ? `${summary} (+${others} more)` : summary;
|
|
@@ -4776,6 +4851,16 @@ function reduce(state, action) {
|
|
|
4776
4851
|
const status = state.status === "planning" ? "researching" : state.status;
|
|
4777
4852
|
return step({ ...spoken, status, busyLabel: researchLabel(spoken.messages, summary) });
|
|
4778
4853
|
}
|
|
4854
|
+
// A settled transcript line, not a research step: nothing ever settles a
|
|
4855
|
+
// task's start, so as a step it stayed "⋯" forever and was counted into
|
|
4856
|
+
// the planner's next "(+N more)".
|
|
4857
|
+
case "taskStarted": {
|
|
4858
|
+
if (stale(state, action.sessionId)) return step(state);
|
|
4859
|
+
const tasks = state.tasks.map((t) => t.id === action.taskId && !isTaskRunning(t) ? { ...t, status: "in_progress" } : t);
|
|
4860
|
+
const who = action.runner ? ` \xB7 ${action.runner}` : "";
|
|
4861
|
+
const spoken = say(state, "system", sanitize(`Started "${action.title}"${who}`));
|
|
4862
|
+
return step({ ...spoken, tasks, status: "executing", busyLabel: runLabel(tasks) });
|
|
4863
|
+
}
|
|
4779
4864
|
case "researchStepDone": {
|
|
4780
4865
|
if (stale(state, action.sessionId)) return step(state);
|
|
4781
4866
|
const messages = settleResearchStep(state.messages, action);
|
|
@@ -4816,7 +4901,7 @@ function reduce(state, action) {
|
|
|
4816
4901
|
return t;
|
|
4817
4902
|
});
|
|
4818
4903
|
if (!changed) return step(state);
|
|
4819
|
-
return step({ ...state, status: "executing", tasks });
|
|
4904
|
+
return step({ ...state, status: "executing", tasks, busyLabel: runLabel(tasks) });
|
|
4820
4905
|
}
|
|
4821
4906
|
case "queueReady": {
|
|
4822
4907
|
if (stale(state, action.sessionId)) return step(state);
|
|
@@ -4986,6 +5071,7 @@ function applySettings(state, settings) {
|
|
|
4986
5071
|
orchestratorModel: typeof settings.orchestratorModel === "string" ? settings.orchestratorModel : state.orchestratorModel,
|
|
4987
5072
|
plannerProvider: typeof settings.aiProvider === "string" ? settings.aiProvider : state.plannerProvider,
|
|
4988
5073
|
plannerEffort: typeof settings.plannerThinkingEffort === "string" ? settings.plannerThinkingEffort : state.plannerEffort,
|
|
5074
|
+
maxParallel: typeof settings.maxParallel === "number" ? settings.maxParallel : state.maxParallel,
|
|
4989
5075
|
allowlist: settings.modelAllowlist && typeof settings.modelAllowlist === "object" ? settings.modelAllowlist : state.allowlist
|
|
4990
5076
|
};
|
|
4991
5077
|
}
|
|
@@ -5002,11 +5088,11 @@ function modelDetail(m) {
|
|
|
5002
5088
|
function providerErrorHint(state) {
|
|
5003
5089
|
const failed = Object.keys(state.providerErrors ?? {});
|
|
5004
5090
|
if (failed.length === 0) return void 0;
|
|
5005
|
-
const names = failed.map((p) =>
|
|
5091
|
+
const names = failed.map((p) => import_core20.ALL_PROVIDERS[p]?.label ?? p);
|
|
5006
5092
|
return `\u26A0 Unavailable (key or fetch failed): ${names.join(", ")} \u2014 showing working providers only.`;
|
|
5007
5093
|
}
|
|
5008
5094
|
function plannerModelItems(state) {
|
|
5009
|
-
const runner = (0,
|
|
5095
|
+
const runner = (0, import_core20.runnerForProvider)(state.plannerProvider);
|
|
5010
5096
|
if (!runner) return state.orchestratorModels.map((m) => ({ id: m.id, label: m.label, detail: modelDetail(m) }));
|
|
5011
5097
|
const items = state.models.filter((m) => m.runners?.includes(runner)).map((m) => ({
|
|
5012
5098
|
id: m.id,
|
|
@@ -5020,7 +5106,7 @@ function plannerModelItems(state) {
|
|
|
5020
5106
|
return items.length > 0 ? items : [{ id: "", label: `No ${runner} models discovered yet`, detail: "run /refresh", disabled: true }];
|
|
5021
5107
|
}
|
|
5022
5108
|
function plannerEffortItems(state) {
|
|
5023
|
-
const runner = (0,
|
|
5109
|
+
const runner = (0, import_core20.runnerForProvider)(state.plannerProvider);
|
|
5024
5110
|
if (!runner) {
|
|
5025
5111
|
return [{ id: "", label: "Thinking effort applies to a coding-agent planner", detail: "switch with /planner", disabled: true }];
|
|
5026
5112
|
}
|
|
@@ -5601,6 +5687,8 @@ function runCommand(state, { name, args }) {
|
|
|
5601
5687
|
return runners(state, args);
|
|
5602
5688
|
case "auto":
|
|
5603
5689
|
return setAutonomous(state, args[0]);
|
|
5690
|
+
case "parallel":
|
|
5691
|
+
return setMaxParallel(state, args[0]);
|
|
5604
5692
|
case "mouse":
|
|
5605
5693
|
return setMouseCapture(state, args[0]);
|
|
5606
5694
|
case "sessions":
|
|
@@ -5769,7 +5857,7 @@ function newSession(state) {
|
|
|
5769
5857
|
}
|
|
5770
5858
|
function setModel(state, args) {
|
|
5771
5859
|
if (args[0] === "set" && args[1]) {
|
|
5772
|
-
const runner = (0,
|
|
5860
|
+
const runner = (0, import_core20.runnerForProvider)(state.plannerProvider);
|
|
5773
5861
|
const known = runner ? modelsForRunner(state.models, runner) : [];
|
|
5774
5862
|
if (runner && known.length > 0 && !known.some((m) => m.id === args[1])) {
|
|
5775
5863
|
return fail3(state, `${args[1]} was not discovered for ${runner}.`);
|
|
@@ -5791,21 +5879,21 @@ function setModel(state, args) {
|
|
|
5791
5879
|
}
|
|
5792
5880
|
function plannerItems(state) {
|
|
5793
5881
|
const installed = new Set(state.runners.map((r) => r.id));
|
|
5794
|
-
const agents =
|
|
5795
|
-
const runner = (0,
|
|
5882
|
+
const agents = import_core20.CLI_PROVIDERS.map((id) => {
|
|
5883
|
+
const runner = (0, import_core20.runnerForProvider)(id);
|
|
5796
5884
|
const ready = installed.has(runner);
|
|
5797
5885
|
return {
|
|
5798
5886
|
id,
|
|
5799
|
-
label:
|
|
5887
|
+
label: import_core20.ALL_PROVIDERS[id].label,
|
|
5800
5888
|
detail: ready ? "coding agent \xB7 no API key needed" : "CLI not installed or not on PATH",
|
|
5801
5889
|
selected: state.plannerProvider === id,
|
|
5802
5890
|
disabled: !ready
|
|
5803
5891
|
};
|
|
5804
5892
|
});
|
|
5805
|
-
const vendors =
|
|
5893
|
+
const vendors = import_core20.PROVIDER_PRIORITY.filter((id) => state.configuredProviders.includes(id)).map((id) => ({
|
|
5806
5894
|
id,
|
|
5807
|
-
label:
|
|
5808
|
-
detail:
|
|
5895
|
+
label: import_core20.ALL_PROVIDERS[id].label,
|
|
5896
|
+
detail: import_core20.ALL_PROVIDERS[id].apiKeyEnvVar,
|
|
5809
5897
|
selected: state.plannerProvider === id
|
|
5810
5898
|
}));
|
|
5811
5899
|
return vendors.length > 0 ? [...agents, ...vendors] : [...agents, { id: "", label: "No API providers configured", detail: "add a key with /key", disabled: true }];
|
|
@@ -5863,16 +5951,16 @@ function setKey(state, args) {
|
|
|
5863
5951
|
}
|
|
5864
5952
|
return step(state, [{ type: "setApiKey", provider, key: args.slice(2).join(" ") }]);
|
|
5865
5953
|
}
|
|
5866
|
-
const items =
|
|
5954
|
+
const items = import_core20.PROVIDER_PRIORITY.map((id) => ({
|
|
5867
5955
|
id,
|
|
5868
|
-
label:
|
|
5869
|
-
detail:
|
|
5956
|
+
label: import_core20.ALL_PROVIDERS[id].label,
|
|
5957
|
+
detail: import_core20.ALL_PROVIDERS[id].apiKeyEnvVar,
|
|
5870
5958
|
selected: state.configuredProviders.includes(id)
|
|
5871
5959
|
}));
|
|
5872
5960
|
return step({ ...state, overlay: { kind: "picker", picker: picker("API provider key", items, { kind: "set-key" }) } });
|
|
5873
5961
|
}
|
|
5874
5962
|
function keyPrompt(provider) {
|
|
5875
|
-
const meta =
|
|
5963
|
+
const meta = import_core20.ALL_PROVIDERS[provider];
|
|
5876
5964
|
return {
|
|
5877
5965
|
kind: "prompt",
|
|
5878
5966
|
title: `${meta.label} API key`,
|
|
@@ -5947,6 +6035,12 @@ function runners(state, args) {
|
|
|
5947
6035
|
})
|
|
5948
6036
|
} });
|
|
5949
6037
|
}
|
|
6038
|
+
function setMaxParallel(state, arg) {
|
|
6039
|
+
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.`));
|
|
6040
|
+
const limit = (0, import_core20.parseMaxParallel)(arg);
|
|
6041
|
+
if (limit === null) return fail3(state, "Usage: /parallel [<number of tasks, 1 or more>]");
|
|
6042
|
+
return step({ ...state, maxParallel: limit }, [{ type: "setMaxParallel", limit }]);
|
|
6043
|
+
}
|
|
5950
6044
|
function setAutonomous(state, arg) {
|
|
5951
6045
|
const enabled = resolveToggle(arg, state.autonomous);
|
|
5952
6046
|
if (enabled === null) return fail3(state, "Usage: /auto [on|off]");
|
|
@@ -6202,7 +6296,9 @@ function createApp(deps) {
|
|
|
6202
6296
|
function dispatch(action) {
|
|
6203
6297
|
if (exited) return;
|
|
6204
6298
|
const result = reduce(state, action);
|
|
6299
|
+
const previousSession = state.sessionId;
|
|
6205
6300
|
state = result.state;
|
|
6301
|
+
if (state.sessionId && state.sessionId !== previousSession) deps.onSessionChange?.(state.sessionId, state);
|
|
6206
6302
|
if (state.exiting) {
|
|
6207
6303
|
exited = true;
|
|
6208
6304
|
clearInterval(spinnerInterval);
|
|
@@ -6234,7 +6330,7 @@ function createApp(deps) {
|
|
|
6234
6330
|
|
|
6235
6331
|
// src/tui/effects.ts
|
|
6236
6332
|
var import_child_process4 = require("child_process");
|
|
6237
|
-
var
|
|
6333
|
+
var import_core21 = require("@ordewell/core");
|
|
6238
6334
|
var import_plan_utils4 = require("@ordewell/core/plan-utils");
|
|
6239
6335
|
var ConversationQueue = class {
|
|
6240
6336
|
tail = Promise.resolve();
|
|
@@ -6405,7 +6501,7 @@ async function perform(effect, deps) {
|
|
|
6405
6501
|
dispatch({ type: "notice", message: `Orchestrator model set to ${effect.modelId}.` });
|
|
6406
6502
|
return;
|
|
6407
6503
|
case "setPlanner": {
|
|
6408
|
-
const meta =
|
|
6504
|
+
const meta = import_core21.ALL_PROVIDERS[effect.provider];
|
|
6409
6505
|
if (!meta) throw new Error(`Unknown planner: ${effect.provider}`);
|
|
6410
6506
|
const env = { AI_PROVIDER: effect.provider };
|
|
6411
6507
|
const settings = await api.updateSettings({ env });
|
|
@@ -6417,7 +6513,7 @@ async function perform(effect, deps) {
|
|
|
6417
6513
|
});
|
|
6418
6514
|
dispatch({
|
|
6419
6515
|
type: "notice",
|
|
6420
|
-
message: `${(0,
|
|
6516
|
+
message: `${(0, import_core21.isCliProvider)(effect.provider) ? `Planning with ${meta.label} \u2014 no API key needed.` : `Planner set to ${meta.label}.`} ${plannerModelNotice(recall2)}`
|
|
6421
6517
|
});
|
|
6422
6518
|
await loadModels(deps);
|
|
6423
6519
|
return;
|
|
@@ -6429,7 +6525,7 @@ async function perform(effect, deps) {
|
|
|
6429
6525
|
dispatch({ type: "notice", message: `Planner effort set to ${effect.effort || "the runner default"}.` });
|
|
6430
6526
|
return;
|
|
6431
6527
|
case "setApiKey": {
|
|
6432
|
-
const meta =
|
|
6528
|
+
const meta = import_core21.ALL_PROVIDERS[effect.provider];
|
|
6433
6529
|
if (!meta) throw new Error(`Unknown provider: ${effect.provider}`);
|
|
6434
6530
|
await api.updateSettings({ env: { [meta.apiKeyEnvVar]: effect.key } });
|
|
6435
6531
|
deps.setEnvVar(meta.apiKeyEnvVar, effect.key);
|
|
@@ -6460,6 +6556,11 @@ async function perform(effect, deps) {
|
|
|
6460
6556
|
dispatch({ type: "notice", message: effect.message });
|
|
6461
6557
|
return;
|
|
6462
6558
|
}
|
|
6559
|
+
case "setMaxParallel":
|
|
6560
|
+
await api.updateSettings({ env: { ORDEWELL_MAX_PARALLEL: String(effect.limit) } });
|
|
6561
|
+
deps.setEnvVar("ORDEWELL_MAX_PARALLEL", String(effect.limit));
|
|
6562
|
+
dispatch({ type: "notice", message: `Up to ${effect.limit} AI task${effect.limit === 1 ? "" : "s"} now run at once.` });
|
|
6563
|
+
return;
|
|
6463
6564
|
case "setAutonomous":
|
|
6464
6565
|
deps.setEnvVar("ORDEWELL_AUTONOMOUS_MODE", String(effect.enabled));
|
|
6465
6566
|
dispatch({ type: "notice", message: `Autonomous mode ${effect.enabled ? "on" : "off"}.` });
|
|
@@ -6590,7 +6691,7 @@ function osc52(text) {
|
|
|
6590
6691
|
function copySelection(deps, text) {
|
|
6591
6692
|
if (!text) return;
|
|
6592
6693
|
const lines = text.split("\n").length;
|
|
6593
|
-
const command = (0,
|
|
6694
|
+
const command = (0, import_core21.clipboardCopyCommand)(deps.hasBin);
|
|
6594
6695
|
if (command) {
|
|
6595
6696
|
try {
|
|
6596
6697
|
(deps.pipeToClipboard ?? pipeToClipboardDefault)(command, text);
|
|
@@ -6727,12 +6828,12 @@ function onExecutionEvent(dispatch, event, sessionId) {
|
|
|
6727
6828
|
return;
|
|
6728
6829
|
}
|
|
6729
6830
|
case "task_started":
|
|
6730
|
-
dispatch({ type: "
|
|
6831
|
+
dispatch({ type: "taskStarted", taskId: String(event.taskId), title: String(event.title ?? event.taskId), runner: event.runner, sessionId });
|
|
6731
6832
|
return;
|
|
6732
6833
|
// The extension shows these in its checkpoint panel; here they are
|
|
6733
6834
|
// transcript lines, which is the TUI's equivalent surface.
|
|
6734
6835
|
case "checkpoint":
|
|
6735
|
-
dispatch({ type: "notice", message: `\xB7 Checkpoint \u2014 ${event.taskTitle}: ${(0,
|
|
6836
|
+
dispatch({ type: "notice", message: `\xB7 Checkpoint \u2014 ${event.taskTitle}: ${(0, import_core21.truncateCheckpointSummary)(event.summary)}` });
|
|
6736
6837
|
return;
|
|
6737
6838
|
case "approval_decided":
|
|
6738
6839
|
dispatch({ type: "notice", message: describeApprovalDecision2(event) });
|
|
@@ -7116,7 +7217,7 @@ async function handleTui(subArgs) {
|
|
|
7116
7217
|
}
|
|
7117
7218
|
const workspace = flag(subArgs, "--workspace") || process.cwd();
|
|
7118
7219
|
try {
|
|
7119
|
-
(0,
|
|
7220
|
+
(0, import_core22.assertWorkspaceExists)(workspace);
|
|
7120
7221
|
} catch {
|
|
7121
7222
|
console.error(
|
|
7122
7223
|
`Workspace "${workspace}" does not exist.
|
|
@@ -7125,12 +7226,12 @@ cd into a directory that exists, or pass --workspace <path> naming one that does
|
|
|
7125
7226
|
);
|
|
7126
7227
|
process.exit(1);
|
|
7127
7228
|
}
|
|
7128
|
-
registerSkillCommands((0,
|
|
7229
|
+
registerSkillCommands((0, import_core22.createSkillsService)(workspace).listSkills());
|
|
7129
7230
|
const explicitPort = flag(subArgs, "--port") || process.env.ORDEWELL_PORT;
|
|
7130
7231
|
const targetPort = explicitPort ? resolvePort(subArgs) : await findFreePort();
|
|
7131
7232
|
const { port, owned: ownedAtLaunch } = await ensureDaemonOwned(targetPort, { detached: false });
|
|
7132
7233
|
let owned = ownedAtLaunch;
|
|
7133
|
-
const api = new ApiClient(port);
|
|
7234
|
+
const api = new ApiClient(port, workspace);
|
|
7134
7235
|
const conversationQueue = new ConversationQueue();
|
|
7135
7236
|
let terminal;
|
|
7136
7237
|
const autoMode = process.env.ORDEWELL_AUTONOMOUS_MODE;
|
|
@@ -7144,7 +7245,7 @@ cd into a directory that exists, or pass --workspace <path> naming one that does
|
|
|
7144
7245
|
conversationQueue,
|
|
7145
7246
|
port,
|
|
7146
7247
|
dispatch: (action) => app.dispatch(action),
|
|
7147
|
-
newSessionId: () => (0,
|
|
7248
|
+
newSessionId: () => (0, import_core22.mintSessionId)(),
|
|
7148
7249
|
setEnvVar: (key, value) => {
|
|
7149
7250
|
writeEnvVar(findEnvFile(), key, value);
|
|
7150
7251
|
process.env[key] = value;
|
|
@@ -7161,7 +7262,16 @@ cd into a directory that exists, or pass --workspace <path> naming one that does
|
|
|
7161
7262
|
},
|
|
7162
7263
|
exit: () => shutdown(0)
|
|
7163
7264
|
}),
|
|
7164
|
-
onExit: () => shutdown(0)
|
|
7265
|
+
onExit: () => shutdown(0),
|
|
7266
|
+
// The same pointer `ordewell plan` leaves, so `ordewell handoff`,
|
|
7267
|
+
// `terminal <n>` and the other one-shot commands act on the session this
|
|
7268
|
+
// TUI is showing instead of saying there is none.
|
|
7269
|
+
onSessionChange: (sessionId, state) => {
|
|
7270
|
+
try {
|
|
7271
|
+
saveLastSession(sessionId, state.goal, state.runners.filter((r) => r.enabled).map((r) => r.id), workspace);
|
|
7272
|
+
} catch {
|
|
7273
|
+
}
|
|
7274
|
+
}
|
|
7165
7275
|
});
|
|
7166
7276
|
terminal = openTerminal({
|
|
7167
7277
|
mouse: mouseCapture,
|
|
@@ -7207,6 +7317,7 @@ var COMMANDS = {
|
|
|
7207
7317
|
model: handleModel,
|
|
7208
7318
|
planner: handlePlanner,
|
|
7209
7319
|
"planner-effort": handlePlannerEffort,
|
|
7320
|
+
parallel: handleParallel,
|
|
7210
7321
|
key: handleKey,
|
|
7211
7322
|
runners: handleRunners,
|
|
7212
7323
|
auto: handleAuto,
|
|
@@ -7253,10 +7364,12 @@ function cliVersion() {
|
|
|
7253
7364
|
}
|
|
7254
7365
|
|
|
7255
7366
|
// src/main.ts
|
|
7367
|
+
var TUI_FLAGS = /* @__PURE__ */ new Set(["--workspace", "--port"]);
|
|
7256
7368
|
async function main() {
|
|
7257
|
-
(0,
|
|
7369
|
+
(0, import_core23.migrateOldConfigDir)();
|
|
7258
7370
|
loadEnvFile();
|
|
7259
7371
|
const argv = process.argv.slice(2);
|
|
7372
|
+
if (TUI_FLAGS.has(argv[0] ?? "")) argv.unshift("tui");
|
|
7260
7373
|
const command = argv[0] ?? (process.stdin.isTTY ? "tui" : "--help");
|
|
7261
7374
|
if (command === "--help" || command === "-h") {
|
|
7262
7375
|
printHelp();
|
|
@@ -7266,6 +7379,11 @@ async function main() {
|
|
|
7266
7379
|
console.log(cliVersion());
|
|
7267
7380
|
return;
|
|
7268
7381
|
}
|
|
7382
|
+
ApiClient.defaultWorkspace = flag(argv, "--workspace") || void 0;
|
|
7383
|
+
const sessionAt = argv.indexOf("--session-id");
|
|
7384
|
+
if (sessionAt > 0 && argv[sessionAt + 1]) {
|
|
7385
|
+
argv[sessionAt + 1] = expandSessionId(argv[sessionAt + 1], flag(argv, "--workspace") || process.cwd());
|
|
7386
|
+
}
|
|
7269
7387
|
const handler = COMMANDS[command];
|
|
7270
7388
|
if (!handler) {
|
|
7271
7389
|
console.error(`Unknown command: ${command}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ordewell/cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "Ordewell CLI and TUI — plan, run and verify coding-agent tasks from the terminal.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Alessandro Costanzo Ciano",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"main": "./dist/main.js",
|
|
34
34
|
"bin": {
|
|
35
|
-
"ordewell": "
|
|
35
|
+
"ordewell": "dist/main.js"
|
|
36
36
|
},
|
|
37
37
|
"files": [
|
|
38
38
|
"dist",
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
"typecheck": "tsc --noEmit"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@ordewell/core": "^0.5.
|
|
52
|
-
"@ordewell/web": "^0.5.
|
|
51
|
+
"@ordewell/core": "^0.5.3",
|
|
52
|
+
"@ordewell/web": "^0.5.3",
|
|
53
53
|
"string-width": "^7.2.0",
|
|
54
54
|
"ws": "^8.18.0"
|
|
55
55
|
},
|