@ordewell/cli 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/main.js +77 -11
  2. package/package.json +3 -3
package/dist/main.js CHANGED
@@ -133,6 +133,7 @@ Other:
133
133
  ordewell setup Interactive first-run setup wizard
134
134
  ordewell plugins list|install|remove|create Manage runner plugins
135
135
  ordewell --help Show this help
136
+ ordewell --version Print the installed version (alias: version, -v)
136
137
 
137
138
  TUI options:
138
139
  --workspace /path Workspace directory (default: cwd)
@@ -3070,6 +3071,7 @@ var SLASH_COMMANDS = [
3070
3071
  { name: "delete", usage: "/delete <id>", description: "Delete a saved session", category: "session" },
3071
3072
  // System
3072
3073
  { name: "help", usage: "/help", description: "Show available commands", category: "system" },
3074
+ { name: "mouse", usage: "/mouse [on|off]", description: "Wheel scrolling instead of drag-to-select text", category: "system" },
3073
3075
  { name: "quit", usage: "/quit", description: "Exit the TUI", category: "system" }
3074
3076
  ];
3075
3077
  var BY_NAME = new Map(SLASH_COMMANDS.map((c) => [c.name, c]));
@@ -3161,6 +3163,7 @@ function initialState(overrides = {}) {
3161
3163
  configuredProviders: [],
3162
3164
  allowlist: {},
3163
3165
  autonomous: true,
3166
+ mouseCapture: false,
3164
3167
  workspace: process.cwd(),
3165
3168
  overlay: null,
3166
3169
  pendingApprovals: [],
@@ -3191,6 +3194,10 @@ function restoredMessages(history) {
3191
3194
  }));
3192
3195
  }
3193
3196
  var isPendingResearch = (m) => m.role === "research" && !m.research?.outcome;
3197
+ function alreadySpoken(messages, content) {
3198
+ const last = findLastIndex(messages, (m) => m.role === "assistant" || m.role === "user");
3199
+ return last >= 0 && messages[last].role === "assistant" && messages[last].content === content;
3200
+ }
3194
3201
  function researchLabel(messages, summary) {
3195
3202
  const others = messages.filter(isPendingResearch).length - 1;
3196
3203
  return others > 0 ? `${summary} (+${others} more)` : summary;
@@ -3256,9 +3263,12 @@ function reduce(state, action) {
3256
3263
  taskEditor: tasks.some((task) => task.id === state.expandedTaskId) ? state.taskEditor : null
3257
3264
  });
3258
3265
  }
3259
- case "plannerMessage":
3266
+ case "plannerMessage": {
3260
3267
  if (stale(state, action.sessionId)) return step(state);
3261
- return step({ ...say(state, "assistant", action.content), status: "idle", busyLabel: "", thinkingLine: "" });
3268
+ const settled = { ...state, status: "idle", busyLabel: "", thinkingLine: "" };
3269
+ if (alreadySpoken(state.messages, action.content)) return step(settled);
3270
+ return step(say(settled, "assistant", action.content));
3271
+ }
3262
3272
  case "researchStep": {
3263
3273
  if (stale(state, action.sessionId)) return step(state);
3264
3274
  const spoken = say(state, "research", action.summary, { toolCallId: action.toolCallId });
@@ -3604,11 +3614,13 @@ function handlePlanKey(state, key) {
3604
3614
  planScroll: 0
3605
3615
  });
3606
3616
  }
3607
- if (key.name === "scrollup") {
3608
- return step({ ...state, planScroll: Math.max(0, state.planScroll - 3) });
3617
+ if (key.name === "scrollup" || key.name === "pageup") {
3618
+ const notch = key.name === "pageup" ? 10 : 3;
3619
+ return step({ ...state, planScroll: Math.max(0, state.planScroll - notch) });
3609
3620
  }
3610
- if (key.name === "scrolldown") {
3611
- return step({ ...state, planScroll: Math.min(planScrollBound(state), state.planScroll + 3) });
3621
+ if (key.name === "scrolldown" || key.name === "pagedown") {
3622
+ const notch = key.name === "pagedown" ? 10 : 3;
3623
+ return step({ ...state, planScroll: Math.min(planScrollBound(state), state.planScroll + notch) });
3612
3624
  }
3613
3625
  const task = state.tasks[state.selectedTask];
3614
3626
  if (!task) return step(state);
@@ -3914,6 +3926,8 @@ function runCommand(state, { name, args }) {
3914
3926
  return runners(state, args);
3915
3927
  case "auto":
3916
3928
  return setAutonomous(state, args[0]);
3929
+ case "mouse":
3930
+ return setMouseCapture(state, args[0]);
3917
3931
  case "sessions":
3918
3932
  return step(
3919
3933
  { ...state, overlay: { kind: "picker", picker: picker("Sessions", [], { kind: "load-session" }) } },
@@ -4210,6 +4224,16 @@ function setAutonomous(state, arg) {
4210
4224
  if (enabled === null) return fail2(state, "Usage: /auto [on|off]");
4211
4225
  return step({ ...state, autonomous: enabled }, [{ type: "setAutonomous", enabled }]);
4212
4226
  }
4227
+ function setMouseCapture(state, arg) {
4228
+ const enabled = resolveToggle(arg, state.mouseCapture);
4229
+ if (enabled === null) return fail2(state, "Usage: /mouse [on|off]");
4230
+ const noted = say(
4231
+ { ...state, mouseCapture: enabled },
4232
+ "system",
4233
+ enabled ? "Mouse capture on \u2014 the wheel scrolls, but dragging no longer selects text." : "Mouse capture off \u2014 drag to select and copy; scroll with pgup/pgdn."
4234
+ );
4235
+ return step(noted, [{ type: "setMouseCapture", enabled }]);
4236
+ }
4213
4237
  function openTaskRunnerPicker(state, task) {
4214
4238
  if (task.type !== "ai") return fail2(state, "Manual tasks do not run on an executor, so they have no runner.");
4215
4239
  const action = { kind: "set-task-runner", taskId: task.id };
@@ -4518,8 +4542,9 @@ function renderFooter(state, cols) {
4518
4542
  "a add",
4519
4543
  "d remove",
4520
4544
  "t terminal",
4545
+ "pgup/pgdn scroll",
4521
4546
  "tab chat"
4522
- ] : ["/help", "tab plan", "alt-enter newline", "ctrl-c quit"];
4547
+ ] : ["/help", "tab plan", "alt-enter newline", "pgup/pgdn scroll", "ctrl-c quit"];
4523
4548
  return packHints(hints, cols);
4524
4549
  }
4525
4550
  function packHints(hints, cols) {
@@ -5190,6 +5215,10 @@ async function perform(effect, deps) {
5190
5215
  deps.setEnvVar("ORDEWELL_AUTONOMOUS_MODE", String(effect.enabled));
5191
5216
  dispatch({ type: "notice", message: `Autonomous mode ${effect.enabled ? "on" : "off"}.` });
5192
5217
  return;
5218
+ case "setMouseCapture":
5219
+ deps.setMouseCapture(effect.enabled);
5220
+ deps.setEnvVar("ORDEWELL_TUI_MOUSE", String(effect.enabled));
5221
+ return;
5193
5222
  case "loadModels":
5194
5223
  await loadModels(deps);
5195
5224
  return;
@@ -5244,6 +5273,7 @@ async function withExecutionStream(deps, sessionId, request) {
5244
5273
  await stream;
5245
5274
  }
5246
5275
  async function converse(deps, sessionId, call) {
5276
+ let streamed = null;
5247
5277
  const stream = deps.api.streamPlanning(sessionId, (event) => {
5248
5278
  if (event?.type === "approval_request") {
5249
5279
  deps.dispatch({
@@ -5284,6 +5314,11 @@ async function converse(deps, sessionId, call) {
5284
5314
  });
5285
5315
  return;
5286
5316
  }
5317
+ if (event?.type === "planner_message") {
5318
+ streamed = String(event.content ?? "");
5319
+ deps.dispatch({ type: "plannerMessage", content: streamed, sessionId });
5320
+ return;
5321
+ }
5287
5322
  if (event?.type === "plan_thinking" && event.text) {
5288
5323
  deps.dispatch({ type: "plannerThinking", text: event.text, sessionId });
5289
5324
  }
@@ -5292,7 +5327,9 @@ async function converse(deps, sessionId, call) {
5292
5327
  const plan = await call();
5293
5328
  deps.dispatch({ type: "planUpdated", plan, sessionId });
5294
5329
  const question = lastAssistantMessage(plan);
5295
- if (question) deps.dispatch({ type: "plannerMessage", content: question, sessionId });
5330
+ if (question && question !== streamed) {
5331
+ deps.dispatch({ type: "plannerMessage", content: question, sessionId });
5332
+ }
5296
5333
  } finally {
5297
5334
  stream.close();
5298
5335
  }
@@ -5548,6 +5585,9 @@ var KITTY_KEYBOARD_ON = "\x1B[>1u";
5548
5585
  var KITTY_KEYBOARD_OFF = "\x1B[<u";
5549
5586
  var MOUSE_TRACKING_ON = "\x1B[?1000h\x1B[?1006h";
5550
5587
  var MOUSE_TRACKING_OFF = "\x1B[?1000l\x1B[?1006l";
5588
+ var ALT_SCROLL_SAVE = "\x1B[?1007s";
5589
+ var ALT_SCROLL_OFF = "\x1B[?1007l";
5590
+ var ALT_SCROLL_RESTORE = "\x1B[?1007r";
5551
5591
  var HOME = "\x1B[H";
5552
5592
  var CLEAR = "\x1B[2J";
5553
5593
  function openTerminal(options) {
@@ -5557,8 +5597,9 @@ function openTerminal(options) {
5557
5597
  if (input.isTTY) input.setRawMode(true);
5558
5598
  input.resume();
5559
5599
  input.setEncoding("utf8");
5600
+ let mouse = options.mouse === true;
5560
5601
  output.write(
5561
- ALT_SCREEN_ON + HIDE_CURSOR + PASTE_MODE_ON + KITTY_KEYBOARD_ON + MOUSE_TRACKING_ON + CLEAR
5602
+ ALT_SCREEN_ON + HIDE_CURSOR + PASTE_MODE_ON + KITTY_KEYBOARD_ON + ALT_SCROLL_SAVE + ALT_SCROLL_OFF + (mouse ? MOUSE_TRACKING_ON : "") + CLEAR
5562
5603
  );
5563
5604
  const decode = createKeyDecoder();
5564
5605
  const onData = (chunk) => {
@@ -5581,6 +5622,11 @@ function openTerminal(options) {
5581
5622
  if (closed) return;
5582
5623
  output.write(HOME + frame2.join("\n"));
5583
5624
  },
5625
+ setMouse(enabled) {
5626
+ if (closed || enabled === mouse) return;
5627
+ mouse = enabled;
5628
+ output.write(enabled ? MOUSE_TRACKING_ON : MOUSE_TRACKING_OFF);
5629
+ },
5584
5630
  close() {
5585
5631
  if (closed) return;
5586
5632
  closed = true;
@@ -5589,7 +5635,7 @@ function openTerminal(options) {
5589
5635
  if (input.isTTY) input.setRawMode(false);
5590
5636
  input.pause();
5591
5637
  output.write(
5592
- MOUSE_TRACKING_OFF + KITTY_KEYBOARD_OFF + PASTE_MODE_OFF + SHOW_CURSOR + ALT_SCREEN_OFF
5638
+ MOUSE_TRACKING_OFF + ALT_SCROLL_RESTORE + KITTY_KEYBOARD_OFF + PASTE_MODE_OFF + SHOW_CURSOR + ALT_SCREEN_OFF
5593
5639
  );
5594
5640
  }
5595
5641
  };
@@ -5608,8 +5654,9 @@ async function handleTui(subArgs) {
5608
5654
  const conversationQueue = new ConversationQueue();
5609
5655
  let terminal;
5610
5656
  const autoMode = process.env.ORDEWELL_AUTONOMOUS_MODE;
5657
+ const mouseCapture = process.env.ORDEWELL_TUI_MOUSE === "true" || process.env.ORDEWELL_TUI_MOUSE === "1";
5611
5658
  const app = createApp({
5612
- initial: { workspace, autonomous: autoMode !== "false" && autoMode !== "0" },
5659
+ initial: { workspace, autonomous: autoMode !== "false" && autoMode !== "0", mouseCapture },
5613
5660
  draw: (frame2) => terminal?.draw(frame2),
5614
5661
  perform: (effect) => runEffect(effect, {
5615
5662
  api,
@@ -5623,6 +5670,7 @@ async function handleTui(subArgs) {
5623
5670
  process.env[key] = value;
5624
5671
  },
5625
5672
  openTerminal: (sessionId, taskId) => openTaskTerminal(port, sessionId, taskId),
5673
+ setMouseCapture: (enabled) => terminal?.setMouse(enabled),
5626
5674
  reviveDaemon: async () => {
5627
5675
  const { owned: freshlyOwned } = await ensureDaemonOwned(port, { detached: false, quiet: true });
5628
5676
  if (freshlyOwned) owned = true;
@@ -5633,6 +5681,7 @@ async function handleTui(subArgs) {
5633
5681
  onExit: () => shutdown(0)
5634
5682
  });
5635
5683
  terminal = openTerminal({
5684
+ mouse: mouseCapture,
5636
5685
  onKey: (key) => app.dispatch({ type: "key", key }),
5637
5686
  onResize: (rows2, cols2) => app.dispatch({ type: "resize", rows: rows2, cols: cols2 })
5638
5687
  });
@@ -5704,6 +5753,19 @@ var COMMANDS = {
5704
5753
  tui: handleTui
5705
5754
  };
5706
5755
 
5756
+ // src/version.ts
5757
+ var import_fs7 = require("fs");
5758
+ var import_path5 = require("path");
5759
+ function cliVersion() {
5760
+ try {
5761
+ const pkg = JSON.parse((0, import_fs7.readFileSync)((0, import_path5.join)(__dirname, "..", "package.json"), "utf8"));
5762
+ const version = pkg.version;
5763
+ return typeof version === "string" && version ? version : "unknown";
5764
+ } catch {
5765
+ return "unknown";
5766
+ }
5767
+ }
5768
+
5707
5769
  // src/main.ts
5708
5770
  async function main() {
5709
5771
  loadEnvFile();
@@ -5713,6 +5775,10 @@ async function main() {
5713
5775
  printHelp();
5714
5776
  return;
5715
5777
  }
5778
+ if (command === "--version" || command === "-v" || command === "version") {
5779
+ console.log(cliVersion());
5780
+ return;
5781
+ }
5716
5782
  const handler = COMMANDS[command];
5717
5783
  if (!handler) {
5718
5784
  console.error(`Unknown command: ${command}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ordewell/cli",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
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",
@@ -48,8 +48,8 @@
48
48
  "typecheck": "tsc --noEmit"
49
49
  },
50
50
  "dependencies": {
51
- "@ordewell/core": "^0.4.2",
52
- "@ordewell/web": "^0.4.2",
51
+ "@ordewell/core": "^0.4.3",
52
+ "@ordewell/web": "^0.4.3",
53
53
  "string-width": "^7.2.0",
54
54
  "ws": "^8.18.0"
55
55
  },