@sma1lboy/kobe 0.5.7 → 0.5.9

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/cli/index.js CHANGED
@@ -5183,7 +5183,6 @@ function bindByIds(handlers) {
5183
5183
  }
5184
5184
  function useKobeKeybindings(opts) {
5185
5185
  const palette = useCommandPalette();
5186
- const dialog = useDialog();
5187
5186
  const renderer = useRenderer();
5188
5187
  const onQuit = opts.onQuit ?? (() => {
5189
5188
  try {
@@ -5195,7 +5194,6 @@ function useKobeKeybindings(opts) {
5195
5194
  });
5196
5195
  const onFocusNext = opts.onFocusNext ?? (() => {});
5197
5196
  const onFocusPrev = opts.onFocusPrev ?? (() => {});
5198
- const onFocusDetach = opts.onFocusDetach ?? (() => {});
5199
5197
  if (renderer) {
5200
5198
  const onSelection = () => {
5201
5199
  const text = renderer.getSelection()?.getSelectedText();
@@ -5237,17 +5235,7 @@ function useKobeKeybindings(opts) {
5237
5235
  "focus.next": () => onFocusNext(),
5238
5236
  "focus.prev": () => onFocusPrev(),
5239
5237
  "app.copy_or_quit": () => handleCtrlC()
5240
- }),
5241
- {
5242
- key: "escape",
5243
- cmd: () => {
5244
- if (dialog.stack.length > 0) {
5245
- dialog.pop();
5246
- } else {
5247
- onFocusDetach();
5248
- }
5249
- }
5250
- }
5238
+ })
5251
5239
  ];
5252
5240
  });
5253
5241
  useBindings(() => ({ bindings: bindings() }));
@@ -5257,7 +5245,6 @@ var init_keybindings = __esm(() => {
5257
5245
  init_solid();
5258
5246
  init_dev();
5259
5247
  init_keymap();
5260
- init_dialog();
5261
5248
  init_command_palette();
5262
5249
  [ctrlCArmed, setCtrlCArmed] = createSignal(false);
5263
5250
  KobeKeymap = [
@@ -5345,14 +5332,6 @@ var init_keybindings = __esm(() => {
5345
5332
  category: "Global",
5346
5333
  description: "Copy selection / press twice within 1.5s to quit"
5347
5334
  },
5348
- {
5349
- id: "focus.detach",
5350
- scope: "global",
5351
- keys: ["esc"],
5352
- category: "Navigation",
5353
- description: "Back to sidebar. In chat while streaming, interrupts the turn instead. Closes top dialog if any.",
5354
- hint: { keys: "esc", label: "back to sidebar" }
5355
- },
5356
5335
  {
5357
5336
  id: "chat.interrupt",
5358
5337
  scope: "workspace",
@@ -8878,7 +8857,7 @@ var init_package = __esm(() => {
8878
8857
  package_default = {
8879
8858
  $schema: "https://json.schemastore.org/package.json",
8880
8859
  name: "@sma1lboy/kobe",
8881
- version: "0.5.7",
8860
+ version: "0.5.9",
8882
8861
  description: "TUI orchestrator for Claude Code (codename)",
8883
8862
  type: "module",
8884
8863
  packageManager: "bun@1.3.13",
@@ -10601,6 +10580,7 @@ class Orchestrator {
10601
10580
  worktrees;
10602
10581
  metadataSuggester;
10603
10582
  handles = new Map;
10583
+ firstSpawnLatches = new Map;
10604
10584
  subscribers = new Map;
10605
10585
  pumps = new Map;
10606
10586
  pendingInputBroker = new InMemoryPendingInputBroker;
@@ -10654,6 +10634,9 @@ class Orchestrator {
10654
10634
  planUsageSignal() {
10655
10635
  return () => null;
10656
10636
  }
10637
+ rcBridgeSignal() {
10638
+ return () => ({ state: "off" });
10639
+ }
10657
10640
  subscribeTasks(listener2) {
10658
10641
  return this.store.subscribe(listener2);
10659
10642
  }
@@ -10830,8 +10813,16 @@ class Orchestrator {
10830
10813
  const renameTabId = this.resolveTab(task, tabId).id;
10831
10814
  this.maybeRenameTempBranch(task.id, renameTabId, prompt);
10832
10815
  }
10833
- const targetTab = this.resolveTab(task, tabId);
10816
+ let targetTab = this.resolveTab(task, tabId);
10834
10817
  const key = tabKey(task.id, targetTab.id);
10818
+ if (!targetTab.sessionId) {
10819
+ const inflight = this.firstSpawnLatches.get(key);
10820
+ if (inflight) {
10821
+ await inflight.catch(() => {});
10822
+ task = this.requireTask(id);
10823
+ targetTab = this.resolveTab(task, tabId);
10824
+ }
10825
+ }
10835
10826
  if (this.handles.has(key) === false) {
10836
10827
  const running = this.countRunning();
10837
10828
  if (running >= CONCURRENCY_CAP) {
@@ -10852,18 +10843,28 @@ class Orchestrator {
10852
10843
  model: modelToUse
10853
10844
  });
10854
10845
  } else {
10855
- handle = await this.engine.spawn(task.worktreePath, promptToSend, {
10856
- permissionMode: task.permissionMode,
10857
- model: modelToUse
10846
+ let releaseLatch = () => {};
10847
+ const latch = new Promise((resolve3) => {
10848
+ releaseLatch = resolve3;
10858
10849
  });
10859
- await this.updateTab(task.id, targetTab.id, { sessionId: handle.sessionId });
10860
- if (task.title === PLACEHOLDER_TASK_TITLE && prompt && prompt.trim().length > 0) {
10861
- const derived = deriveTitleFromPrompt(prompt);
10862
- if (derived)
10863
- await this.store.update(task.id, { title: derived });
10864
- }
10865
- if (prompt && prompt.trim().length > 0) {
10866
- this.maybeUpgradeTitle(task.id, prompt);
10850
+ this.firstSpawnLatches.set(key, latch);
10851
+ try {
10852
+ handle = await this.engine.spawn(task.worktreePath, promptToSend, {
10853
+ permissionMode: task.permissionMode,
10854
+ model: modelToUse
10855
+ });
10856
+ await this.updateTab(task.id, targetTab.id, { sessionId: handle.sessionId });
10857
+ if (task.title === PLACEHOLDER_TASK_TITLE && prompt && prompt.trim().length > 0) {
10858
+ const derived = deriveTitleFromPrompt(prompt);
10859
+ if (derived)
10860
+ await this.store.update(task.id, { title: derived });
10861
+ }
10862
+ if (prompt && prompt.trim().length > 0) {
10863
+ this.maybeUpgradeTitle(task.id, prompt);
10864
+ }
10865
+ } finally {
10866
+ releaseLatch();
10867
+ this.firstSpawnLatches.delete(key);
10867
10868
  }
10868
10869
  }
10869
10870
  this.handles.set(key, handle);
@@ -10930,6 +10931,12 @@ class Orchestrator {
10930
10931
  }
10931
10932
  this.dispatchEvent(task.id, targetTab.id, { type: "done" });
10932
10933
  }
10934
+ async steerTask(id, prompt, tabId) {
10935
+ const task = this.requireTask(id);
10936
+ const targetTab = this.resolveTab(task, tabId);
10937
+ await this.interruptTask(task.id, targetTab.id);
10938
+ await this.runTask(task.id, prompt, targetTab.id);
10939
+ }
10933
10940
  async pauseTask(id) {
10934
10941
  const task = this.requireTask(id);
10935
10942
  if (task.status !== "in_progress") {
@@ -11368,6 +11375,8 @@ class RemoteOrchestrator {
11368
11375
  setRunState;
11369
11376
  planUsageAcc;
11370
11377
  setPlanUsage;
11378
+ rcBridgeAcc;
11379
+ setRcBridge;
11371
11380
  subscribers = new Map;
11372
11381
  pendingInputBroker = new InMemoryPendingInputBroker;
11373
11382
  constructor(client) {
@@ -11375,12 +11384,15 @@ class RemoteOrchestrator {
11375
11384
  const [tasks, setTasks] = createSignal([]);
11376
11385
  const [runState, setRunState] = createSignal(new Map);
11377
11386
  const [planUsage, setPlanUsage] = createSignal(null);
11387
+ const [rcBridge, setRcBridge] = createSignal({ state: "off" });
11378
11388
  this.tasksAcc = tasks;
11379
11389
  this.setTasks = (next) => setTasks(() => next);
11380
11390
  this.runStateAcc = runState;
11381
11391
  this.setRunState = (next) => setRunState(() => next);
11382
11392
  this.planUsageAcc = planUsage;
11383
11393
  this.setPlanUsage = (next) => setPlanUsage(() => next);
11394
+ this.rcBridgeAcc = rcBridge;
11395
+ this.setRcBridge = (next) => setRcBridge(() => next);
11384
11396
  this.client.on("*", (frame) => this.handleEvent(frame.name, frame.payload));
11385
11397
  }
11386
11398
  async init() {
@@ -11402,6 +11414,8 @@ class RemoteOrchestrator {
11402
11414
  }
11403
11415
  if (hello.planUsage)
11404
11416
  this.setPlanUsage(hello.planUsage);
11417
+ if (hello.rcBridge)
11418
+ this.setRcBridge(hello.rcBridge);
11405
11419
  await this.client.request("subscribe", { taskIds: "all" });
11406
11420
  if (hello.pending) {
11407
11421
  for (const [taskId, entries] of Object.entries(hello.pending)) {
@@ -11434,6 +11448,21 @@ class RemoteOrchestrator {
11434
11448
  planUsageSignal() {
11435
11449
  return this.planUsageAcc;
11436
11450
  }
11451
+ rcBridgeSignal() {
11452
+ return this.rcBridgeAcc;
11453
+ }
11454
+ async startRcBridge(opts = {}) {
11455
+ const res = await this.client.request("rcBridge.start", {
11456
+ taskId: opts.taskId,
11457
+ tabId: opts.tabId,
11458
+ cwd: opts.cwd
11459
+ });
11460
+ return res.status;
11461
+ }
11462
+ async stopRcBridge() {
11463
+ const res = await this.client.request("rcBridge.stop", {});
11464
+ return res.status;
11465
+ }
11437
11466
  listTasks() {
11438
11467
  return this.tasksAcc().slice();
11439
11468
  }
@@ -11455,6 +11484,10 @@ class RemoteOrchestrator {
11455
11484
  async interruptTask(taskId, tabId) {
11456
11485
  await this.client.request("chat.interrupt", { taskId, tabId });
11457
11486
  }
11487
+ async steerTask(taskId, text, tabId) {
11488
+ await this.client.request("chat.steer", { taskId, text, tabId });
11489
+ this.markRunState(taskId, tabId ?? this.getTask(taskId)?.activeTabId, "running");
11490
+ }
11458
11491
  async setArchived(taskId, archived) {
11459
11492
  await this.client.request("task.archive", { taskId, archived });
11460
11493
  }
@@ -11574,6 +11607,12 @@ class RemoteOrchestrator {
11574
11607
  this.setPlanUsage(usage ?? null);
11575
11608
  return;
11576
11609
  }
11610
+ if (name === "rcBridge.changed") {
11611
+ const status = obj.status;
11612
+ if (status)
11613
+ this.setRcBridge(status);
11614
+ return;
11615
+ }
11577
11616
  const taskId = obj.taskId;
11578
11617
  const tabId = obj.tabId;
11579
11618
  if (!taskId || !tabId)
@@ -13532,228 +13571,665 @@ var init_pane_header = __esm(() => {
13532
13571
  init_theme();
13533
13572
  });
13534
13573
 
13535
- // src/tui/component/border.tsx
13536
- var EmptyBorder, SplitBorder, HSplitBorder;
13537
- var init_border = __esm(() => {
13538
- EmptyBorder = {
13539
- topLeft: "",
13540
- bottomLeft: "",
13541
- vertical: "",
13542
- topRight: "",
13543
- bottomRight: "",
13544
- horizontal: " ",
13545
- bottomT: "",
13546
- topT: "",
13547
- cross: "",
13548
- leftT: "",
13549
- rightT: ""
13550
- };
13551
- SplitBorder = {
13552
- border: ["left", "right"],
13553
- customBorderChars: {
13554
- ...EmptyBorder,
13555
- vertical: "\u2503"
13556
- }
13557
- };
13558
- HSplitBorder = {
13559
- customBorderChars: {
13560
- ...EmptyBorder,
13561
- horizontal: "\u2501"
13562
- }
13563
- };
13564
- });
13565
-
13566
- // src/tui/component/resizable-edge.tsx
13567
- function ResizableEdge(props) {
13574
+ // src/tui/component/rc-bridge-dialog.tsx
13575
+ import { TextAttributes as TextAttributes12 } from "@opentui/core";
13576
+ function RcBridgeDialog(props) {
13577
+ const dialog = useDialog();
13568
13578
  const {
13569
13579
  theme
13570
13580
  } = useTheme();
13571
- const [hovering, setHovering] = createSignal(false);
13572
- const [dragging, setDragging] = createSignal(false);
13573
- let startCoord = 0;
13574
- let startSize = 0;
13575
- const isVertical = () => props.orientation === "vertical";
13576
- const color = () => {
13577
- if (dragging())
13578
- return theme.accent;
13579
- if (hovering())
13580
- return theme.borderActive;
13581
- if (props.focused?.())
13582
- return theme.focusAccent;
13583
- return theme.border;
13584
- };
13585
- return (() => {
13586
- var _el$ = createElement("box");
13587
- setProp(_el$, "flexShrink", 0);
13588
- setProp(_el$, "onMouseOver", () => setHovering(true));
13589
- setProp(_el$, "onMouseOut", () => setHovering(false));
13590
- setProp(_el$, "onMouseDown", (e) => {
13591
- setDragging(true);
13592
- startCoord = isVertical() ? e.x : e.y;
13593
- startSize = props.size();
13594
- });
13595
- setProp(_el$, "onMouseDrag", (e) => {
13596
- if (!dragging())
13597
- return;
13598
- const cur = isVertical() ? e.x : e.y;
13599
- const next = startSize + (cur - startCoord);
13600
- props.setSize(props.clamp ? props.clamp(next) : next);
13601
- });
13602
- setProp(_el$, "onMouseDragEnd", () => {
13603
- if (dragging())
13604
- setDragging(false);
13605
- });
13606
- setProp(_el$, "onMouseUp", () => {
13607
- if (dragging())
13608
- setDragging(false);
13609
- });
13610
- effect((_p$) => {
13611
- var _v$ = isVertical() ? 1 : undefined, _v$2 = isVertical() ? undefined : 1, _v$3 = isVertical() ? ["left"] : ["top"], _v$4 = isVertical() ? SplitBorder.customBorderChars : HSplitBorder.customBorderChars, _v$5 = color();
13612
- _v$ !== _p$.e && (_p$.e = setProp(_el$, "width", _v$, _p$.e));
13613
- _v$2 !== _p$.t && (_p$.t = setProp(_el$, "height", _v$2, _p$.t));
13614
- _v$3 !== _p$.a && (_p$.a = setProp(_el$, "border", _v$3, _p$.a));
13615
- _v$4 !== _p$.o && (_p$.o = setProp(_el$, "customBorderChars", _v$4, _p$.o));
13616
- _v$5 !== _p$.i && (_p$.i = setProp(_el$, "borderColor", _v$5, _p$.i));
13617
- return _p$;
13618
- }, {
13619
- e: undefined,
13620
- t: undefined,
13621
- a: undefined,
13622
- o: undefined,
13623
- i: undefined
13624
- });
13625
- return _el$;
13626
- })();
13627
- }
13628
- var init_resizable_edge = __esm(() => {
13629
- init_solid();
13630
- init_solid();
13631
- init_solid();
13632
- init_dev();
13633
- init_theme();
13634
- init_border();
13635
- });
13636
-
13637
- // src/tui/context/focus.tsx
13638
- function FocusProvider(props) {
13639
- const [focused, setFocusedSignal] = createSignal(props.initial ?? "sidebar");
13640
- const [refocusTick, setRefocusTick] = createSignal(0);
13641
- const renderer = useRenderer();
13642
- function setFocused(pane) {
13643
- setRefocusTick((t) => t + 1);
13644
- if (focused() === pane)
13581
+ const [busy, setBusy] = createSignal(false);
13582
+ const targetTask = () => props.activeTask?.();
13583
+ const canEnable = () => Boolean(targetTask());
13584
+ async function activate() {
13585
+ if (busy())
13645
13586
  return;
13646
- const current = renderer?.currentFocusedRenderable;
13647
- if (current && !current.isDestroyed) {
13648
- try {
13649
- current.blur();
13650
- } catch {}
13651
- }
13652
- setFocusedSignal(pane);
13653
- }
13654
- function cycle(delta) {
13655
- const idx = PANE_ORDER.indexOf(focused());
13656
- const next = (idx + delta + PANE_ORDER.length) % PANE_ORDER.length;
13657
- setFocused(PANE_ORDER[next]);
13658
- }
13659
- const accessorCache = new Map;
13660
- function is(pane) {
13661
- let acc = accessorCache.get(pane);
13662
- if (!acc) {
13663
- acc = () => focused() === pane;
13664
- accessorCache.set(pane, acc);
13665
- }
13666
- return acc;
13667
- }
13668
- const value = {
13669
- focused,
13670
- is,
13671
- setFocused,
13672
- cycle,
13673
- refocusTick
13674
- };
13675
- return createComponent2(FocusContext.Provider, {
13676
- value,
13677
- get children() {
13678
- return props.children;
13587
+ const s = props.status();
13588
+ setBusy(true);
13589
+ try {
13590
+ if (s.state === "off" || s.state === "error") {
13591
+ const task = targetTask();
13592
+ if (!task)
13593
+ return;
13594
+ await props.orchestrator.startRcBridge({
13595
+ taskId: task.id,
13596
+ tabId: props.activeTabId?.() ?? undefined
13597
+ });
13598
+ } else if (s.state === "running") {
13599
+ await props.orchestrator.stopRcBridge();
13600
+ }
13601
+ } catch (err) {
13602
+ console.error("kobe: rcBridge action failed:", err);
13603
+ } finally {
13604
+ setBusy(false);
13679
13605
  }
13680
- });
13681
- }
13682
- function useFocus() {
13683
- const ctx4 = useContext(FocusContext);
13684
- if (!ctx4) {
13685
- throw new Error("useFocus: must be called inside <FocusProvider>. See src/tui/context/focus.tsx.");
13686
13606
  }
13687
- return ctx4;
13688
- }
13689
- var PANE_ORDER, FocusContext;
13690
- var init_focus = __esm(() => {
13691
- init_solid();
13692
- init_solid();
13693
- init_dev();
13694
- PANE_ORDER = ["sidebar", "workspace", "files", "terminal"];
13695
- FocusContext = createContext(null);
13696
- });
13697
-
13698
- // src/tui/component/status-bar.tsx
13699
- import { TextAttributes as TextAttributes12 } from "@opentui/core";
13700
- function Hotkey(props) {
13701
- const {
13702
- theme
13703
- } = useTheme();
13607
+ useBindings(() => ({
13608
+ enabled: dialog.stack.length > 0,
13609
+ bindings: [{
13610
+ key: "return",
13611
+ cmd: () => void activate()
13612
+ }]
13613
+ }));
13704
13614
  return (() => {
13705
- var _el$ = createElement("box"), _el$2 = createElement("text"), _el$3 = createTextNode(`[`), _el$4 = createTextNode(`]`), _el$5 = createElement("text");
13615
+ var _el$ = createElement("box"), _el$2 = createElement("box"), _el$3 = createElement("text"), _el$5 = createElement("text"), _el$7 = createElement("text"), _el$8 = createTextNode(`Binds this task's worktree to a claude.ai environment so you can pick it up from another device. claude.ai sessions on that environment run on your machine under the task's worktree \u2014 and if this tab already has a kobe conversation, you can \`/resume &lt;id>\` it in claude.ai to keep going from where you left off.`);
13706
13616
  insertNode(_el$, _el$2);
13707
- insertNode(_el$, _el$5);
13708
- setProp(_el$, "flexDirection", "row");
13617
+ insertNode(_el$, _el$7);
13618
+ setProp(_el$, "paddingLeft", 2);
13619
+ setProp(_el$, "paddingRight", 2);
13709
13620
  setProp(_el$, "gap", 1);
13710
- setProp(_el$, "flexShrink", 0);
13711
13621
  insertNode(_el$2, _el$3);
13712
- insertNode(_el$2, _el$4);
13713
- setProp(_el$2, "wrapMode", "none");
13714
- insert(_el$2, () => props.keys, _el$4);
13715
- setProp(_el$5, "wrapMode", "none");
13716
- insert(_el$5, () => props.label);
13717
- effect((_p$) => {
13718
- var _v$ = theme.accent, _v$2 = TextAttributes12.BOLD, _v$3 = theme.textMuted;
13719
- _v$ !== _p$.e && (_p$.e = setProp(_el$2, "fg", _v$, _p$.e));
13720
- _v$2 !== _p$.t && (_p$.t = setProp(_el$2, "attributes", _v$2, _p$.t));
13721
- _v$3 !== _p$.a && (_p$.a = setProp(_el$5, "fg", _v$3, _p$.a));
13722
- return _p$;
13723
- }, {
13724
- e: undefined,
13725
- t: undefined,
13726
- a: undefined
13727
- });
13728
- return _el$;
13729
- })();
13730
- }
13731
- function StatusBar() {
13732
- const {
13733
- theme
13734
- } = useTheme();
13735
- const focus = useFocus();
13736
- const ctrlCArmed2 = useCtrlCArmed();
13737
- const sectionLabel = () => {
13738
- switch (focus.focused()) {
13739
- case "sidebar":
13740
- return "Tasks:";
13741
- case "workspace":
13742
- return "Chat:";
13743
- case "files":
13744
- return "Files:";
13745
- case "terminal":
13746
- return "Terminal:";
13747
- }
13622
+ insertNode(_el$2, _el$5);
13623
+ setProp(_el$2, "flexDirection", "row");
13624
+ setProp(_el$2, "justifyContent", "space-between");
13625
+ insertNode(_el$3, createTextNode(`Share to claude.ai`));
13626
+ insertNode(_el$5, createTextNode(`esc`));
13627
+ setProp(_el$5, "onMouseUp", () => dialog.clear());
13628
+ insertNode(_el$7, _el$8);
13629
+ setProp(_el$7, "wrapMode", "word");
13630
+ insert(_el$, createComponent2(Switch, {
13631
+ get children() {
13632
+ return [createComponent2(Match, {
13633
+ get when() {
13634
+ return props.status().state === "off";
13635
+ },
13636
+ get children() {
13637
+ return createComponent2(Show, {
13638
+ get when() {
13639
+ return canEnable();
13640
+ },
13641
+ get fallback() {
13642
+ return (() => {
13643
+ var _el$48 = createElement("text");
13644
+ insertNode(_el$48, createTextNode(`No active task \u2014 select a task in the sidebar first, then re-open this dialog.`));
13645
+ effect((_$p) => setProp(_el$48, "fg", theme.textMuted, _$p));
13646
+ return _el$48;
13647
+ })();
13648
+ },
13649
+ get children() {
13650
+ var _el$1 = createElement("box"), _el$10 = createElement("text"), _el$12 = createElement("box"), _el$13 = createElement("text"), _el$14 = createElement("text"), _el$16 = createElement("text");
13651
+ insertNode(_el$1, _el$10);
13652
+ insertNode(_el$1, _el$12);
13653
+ setProp(_el$1, "flexDirection", "column");
13654
+ setProp(_el$1, "gap", 0);
13655
+ insertNode(_el$10, createTextNode(`Will share:`));
13656
+ insertNode(_el$12, _el$13);
13657
+ insertNode(_el$12, _el$14);
13658
+ insertNode(_el$12, _el$16);
13659
+ setProp(_el$12, "flexDirection", "row");
13660
+ setProp(_el$12, "gap", 1);
13661
+ insert(_el$13, () => targetTask()?.title ?? "");
13662
+ insertNode(_el$14, createTextNode(`\xB7`));
13663
+ setProp(_el$16, "wrapMode", "none");
13664
+ insert(_el$16, () => targetTask()?.worktreePath ?? "");
13665
+ effect((_p$) => {
13666
+ var { textMuted: _v$, text: _v$2 } = theme, _v$3 = TextAttributes12.BOLD, _v$4 = theme.textMuted, _v$5 = theme.text;
13667
+ _v$ !== _p$.e && (_p$.e = setProp(_el$10, "fg", _v$, _p$.e));
13668
+ _v$2 !== _p$.t && (_p$.t = setProp(_el$13, "fg", _v$2, _p$.t));
13669
+ _v$3 !== _p$.a && (_p$.a = setProp(_el$13, "attributes", _v$3, _p$.a));
13670
+ _v$4 !== _p$.o && (_p$.o = setProp(_el$14, "fg", _v$4, _p$.o));
13671
+ _v$5 !== _p$.i && (_p$.i = setProp(_el$16, "fg", _v$5, _p$.i));
13672
+ return _p$;
13673
+ }, {
13674
+ e: undefined,
13675
+ t: undefined,
13676
+ a: undefined,
13677
+ o: undefined,
13678
+ i: undefined
13679
+ });
13680
+ return _el$1;
13681
+ }
13682
+ });
13683
+ }
13684
+ }), createComponent2(Match, {
13685
+ get when() {
13686
+ return props.status().state === "starting";
13687
+ },
13688
+ get children() {
13689
+ var _el$17 = createElement("text");
13690
+ insertNode(_el$17, createTextNode(`Connecting to claude.ai\u2026`));
13691
+ effect((_$p) => setProp(_el$17, "fg", theme.accent, _$p));
13692
+ return _el$17;
13693
+ }
13694
+ }), createComponent2(Match, {
13695
+ get when() {
13696
+ return props.status().state === "running";
13697
+ },
13698
+ get children() {
13699
+ var _el$19 = createElement("box"), _el$20 = createElement("box"), _el$21 = createElement("text"), _el$23 = createElement("text");
13700
+ insertNode(_el$19, _el$20);
13701
+ setProp(_el$19, "flexDirection", "column");
13702
+ setProp(_el$19, "gap", 0);
13703
+ insertNode(_el$20, _el$21);
13704
+ insertNode(_el$20, _el$23);
13705
+ setProp(_el$20, "flexDirection", "row");
13706
+ setProp(_el$20, "gap", 1);
13707
+ insertNode(_el$21, createTextNode(`Env:`));
13708
+ insert(_el$23, () => props.status().envId);
13709
+ insert(_el$19, createComponent2(Show, {
13710
+ get when() {
13711
+ return props.status().deeplink;
13712
+ },
13713
+ get children() {
13714
+ var _el$24 = createElement("box"), _el$25 = createElement("text"), _el$27 = createElement("text");
13715
+ insertNode(_el$24, _el$25);
13716
+ insertNode(_el$24, _el$27);
13717
+ setProp(_el$24, "flexDirection", "column");
13718
+ setProp(_el$24, "gap", 0);
13719
+ setProp(_el$24, "paddingTop", 1);
13720
+ insertNode(_el$25, createTextNode(`Open from another device:`));
13721
+ insert(_el$27, () => props.status().deeplink);
13722
+ effect((_p$) => {
13723
+ var { textMuted: _v$6, accent: _v$7 } = theme;
13724
+ _v$6 !== _p$.e && (_p$.e = setProp(_el$25, "fg", _v$6, _p$.e));
13725
+ _v$7 !== _p$.t && (_p$.t = setProp(_el$27, "fg", _v$7, _p$.t));
13726
+ return _p$;
13727
+ }, {
13728
+ e: undefined,
13729
+ t: undefined
13730
+ });
13731
+ return _el$24;
13732
+ }
13733
+ }), null);
13734
+ insert(_el$19, createComponent2(Show, {
13735
+ get when() {
13736
+ return props.status().bound;
13737
+ },
13738
+ get children() {
13739
+ var _el$28 = createElement("box"), _el$29 = createElement("box"), _el$30 = createElement("text"), _el$32 = createElement("text");
13740
+ insertNode(_el$28, _el$29);
13741
+ setProp(_el$28, "flexDirection", "column");
13742
+ setProp(_el$28, "gap", 0);
13743
+ setProp(_el$28, "paddingTop", 1);
13744
+ insertNode(_el$29, _el$30);
13745
+ insertNode(_el$29, _el$32);
13746
+ setProp(_el$29, "flexDirection", "row");
13747
+ setProp(_el$29, "gap", 1);
13748
+ insertNode(_el$30, createTextNode(`Sharing:`));
13749
+ setProp(_el$32, "wrapMode", "none");
13750
+ insert(_el$32, () => props.status().bound?.taskTitle ?? props.status().bound?.taskId);
13751
+ insert(_el$28, createComponent2(Show, {
13752
+ get when() {
13753
+ return props.status().bound?.sessionId;
13754
+ },
13755
+ get fallback() {
13756
+ return (() => {
13757
+ var _el$50 = createElement("text");
13758
+ insertNode(_el$50, createTextNode(`(no kobe session yet \u2014 claude.ai will start a fresh one in this worktree)`));
13759
+ setProp(_el$50, "wrapMode", "word");
13760
+ effect((_$p) => setProp(_el$50, "fg", theme.textMuted, _$p));
13761
+ return _el$50;
13762
+ })();
13763
+ },
13764
+ get children() {
13765
+ var _el$33 = createElement("box"), _el$34 = createElement("text"), _el$36 = createElement("text"), _el$37 = createTextNode(`/resume `);
13766
+ insertNode(_el$33, _el$34);
13767
+ insertNode(_el$33, _el$36);
13768
+ setProp(_el$33, "flexDirection", "column");
13769
+ setProp(_el$33, "gap", 0);
13770
+ insertNode(_el$34, createTextNode(`To continue this tab's conversation in claude.ai, run:`));
13771
+ insertNode(_el$36, _el$37);
13772
+ insert(_el$36, () => props.status().bound?.sessionId, null);
13773
+ effect((_p$) => {
13774
+ var { textMuted: _v$8, accent: _v$9 } = theme, _v$0 = TextAttributes12.BOLD;
13775
+ _v$8 !== _p$.e && (_p$.e = setProp(_el$34, "fg", _v$8, _p$.e));
13776
+ _v$9 !== _p$.t && (_p$.t = setProp(_el$36, "fg", _v$9, _p$.t));
13777
+ _v$0 !== _p$.a && (_p$.a = setProp(_el$36, "attributes", _v$0, _p$.a));
13778
+ return _p$;
13779
+ }, {
13780
+ e: undefined,
13781
+ t: undefined,
13782
+ a: undefined
13783
+ });
13784
+ return _el$33;
13785
+ }
13786
+ }), null);
13787
+ effect((_p$) => {
13788
+ var { textMuted: _v$1, text: _v$10 } = theme, _v$11 = TextAttributes12.BOLD;
13789
+ _v$1 !== _p$.e && (_p$.e = setProp(_el$30, "fg", _v$1, _p$.e));
13790
+ _v$10 !== _p$.t && (_p$.t = setProp(_el$32, "fg", _v$10, _p$.t));
13791
+ _v$11 !== _p$.a && (_p$.a = setProp(_el$32, "attributes", _v$11, _p$.a));
13792
+ return _p$;
13793
+ }, {
13794
+ e: undefined,
13795
+ t: undefined,
13796
+ a: undefined
13797
+ });
13798
+ return _el$28;
13799
+ }
13800
+ }), null);
13801
+ insert(_el$19, createComponent2(Show, {
13802
+ get when() {
13803
+ return props.status().cwd;
13804
+ },
13805
+ get children() {
13806
+ var _el$38 = createElement("box"), _el$39 = createElement("text"), _el$41 = createElement("text");
13807
+ insertNode(_el$38, _el$39);
13808
+ insertNode(_el$38, _el$41);
13809
+ setProp(_el$38, "flexDirection", "row");
13810
+ setProp(_el$38, "gap", 1);
13811
+ setProp(_el$38, "paddingTop", 1);
13812
+ insertNode(_el$39, createTextNode(`Cwd:`));
13813
+ setProp(_el$41, "wrapMode", "none");
13814
+ insert(_el$41, () => props.status().cwd);
13815
+ effect((_p$) => {
13816
+ var { textMuted: _v$12, text: _v$13 } = theme;
13817
+ _v$12 !== _p$.e && (_p$.e = setProp(_el$39, "fg", _v$12, _p$.e));
13818
+ _v$13 !== _p$.t && (_p$.t = setProp(_el$41, "fg", _v$13, _p$.t));
13819
+ return _p$;
13820
+ }, {
13821
+ e: undefined,
13822
+ t: undefined
13823
+ });
13824
+ return _el$38;
13825
+ }
13826
+ }), null);
13827
+ effect((_p$) => {
13828
+ var { textMuted: _v$14, accent: _v$15 } = theme, _v$16 = TextAttributes12.BOLD;
13829
+ _v$14 !== _p$.e && (_p$.e = setProp(_el$21, "fg", _v$14, _p$.e));
13830
+ _v$15 !== _p$.t && (_p$.t = setProp(_el$23, "fg", _v$15, _p$.t));
13831
+ _v$16 !== _p$.a && (_p$.a = setProp(_el$23, "attributes", _v$16, _p$.a));
13832
+ return _p$;
13833
+ }, {
13834
+ e: undefined,
13835
+ t: undefined,
13836
+ a: undefined
13837
+ });
13838
+ return _el$19;
13839
+ }
13840
+ }), createComponent2(Match, {
13841
+ get when() {
13842
+ return props.status().state === "stopping";
13843
+ },
13844
+ get children() {
13845
+ var _el$42 = createElement("text");
13846
+ insertNode(_el$42, createTextNode(`Disconnecting\u2026`));
13847
+ effect((_$p) => setProp(_el$42, "fg", theme.textMuted, _$p));
13848
+ return _el$42;
13849
+ }
13850
+ }), createComponent2(Match, {
13851
+ get when() {
13852
+ return props.status().state === "error";
13853
+ },
13854
+ get children() {
13855
+ var _el$44 = createElement("box"), _el$45 = createElement("text");
13856
+ insertNode(_el$44, _el$45);
13857
+ setProp(_el$44, "flexDirection", "column");
13858
+ setProp(_el$44, "gap", 0);
13859
+ insertNode(_el$45, createTextNode(`Bridge failed.`));
13860
+ insert(_el$44, createComponent2(Show, {
13861
+ get when() {
13862
+ return props.status().errorMessage;
13863
+ },
13864
+ get children() {
13865
+ var _el$47 = createElement("text");
13866
+ setProp(_el$47, "wrapMode", "word");
13867
+ insert(_el$47, () => props.status().errorMessage);
13868
+ effect((_$p) => setProp(_el$47, "fg", theme.textMuted, _$p));
13869
+ return _el$47;
13870
+ }
13871
+ }), null);
13872
+ effect((_p$) => {
13873
+ var _v$17 = theme.error, _v$18 = TextAttributes12.BOLD;
13874
+ _v$17 !== _p$.e && (_p$.e = setProp(_el$45, "fg", _v$17, _p$.e));
13875
+ _v$18 !== _p$.t && (_p$.t = setProp(_el$45, "attributes", _v$18, _p$.t));
13876
+ return _p$;
13877
+ }, {
13878
+ e: undefined,
13879
+ t: undefined
13880
+ });
13881
+ return _el$44;
13882
+ }
13883
+ })];
13884
+ }
13885
+ }), null);
13886
+ insert(_el$, createComponent2(Switch, {
13887
+ get children() {
13888
+ return [createComponent2(Match, {
13889
+ get when() {
13890
+ return props.status().state === "off";
13891
+ },
13892
+ get children() {
13893
+ return createComponent2(ActionButton, {
13894
+ label: "[ enter ] Enable",
13895
+ get disabled() {
13896
+ return busy() || !canEnable();
13897
+ },
13898
+ onClick: activate
13899
+ });
13900
+ }
13901
+ }), createComponent2(Match, {
13902
+ get when() {
13903
+ return props.status().state === "running";
13904
+ },
13905
+ get children() {
13906
+ return createComponent2(ActionButton, {
13907
+ label: "[ enter ] Disable",
13908
+ get disabled() {
13909
+ return busy();
13910
+ },
13911
+ onClick: activate,
13912
+ variant: "warning"
13913
+ });
13914
+ }
13915
+ }), createComponent2(Match, {
13916
+ get when() {
13917
+ return props.status().state === "error";
13918
+ },
13919
+ get children() {
13920
+ return createComponent2(ActionButton, {
13921
+ label: "[ enter ] Retry",
13922
+ get disabled() {
13923
+ return busy() || !canEnable();
13924
+ },
13925
+ onClick: activate
13926
+ });
13927
+ }
13928
+ }), createComponent2(Match, {
13929
+ get when() {
13930
+ return props.status().state === "starting" || props.status().state === "stopping";
13931
+ },
13932
+ get children() {
13933
+ return createComponent2(ActionButton, {
13934
+ label: "working\u2026",
13935
+ disabled: true
13936
+ });
13937
+ }
13938
+ })];
13939
+ }
13940
+ }), null);
13941
+ effect((_p$) => {
13942
+ var _v$19 = TextAttributes12.BOLD, _v$20 = theme.text, _v$21 = theme.textMuted, _v$22 = theme.textMuted;
13943
+ _v$19 !== _p$.e && (_p$.e = setProp(_el$3, "attributes", _v$19, _p$.e));
13944
+ _v$20 !== _p$.t && (_p$.t = setProp(_el$3, "fg", _v$20, _p$.t));
13945
+ _v$21 !== _p$.a && (_p$.a = setProp(_el$5, "fg", _v$21, _p$.a));
13946
+ _v$22 !== _p$.o && (_p$.o = setProp(_el$7, "fg", _v$22, _p$.o));
13947
+ return _p$;
13948
+ }, {
13949
+ e: undefined,
13950
+ t: undefined,
13951
+ a: undefined,
13952
+ o: undefined
13953
+ });
13954
+ return _el$;
13955
+ })();
13956
+ }
13957
+ function ActionButton(props) {
13958
+ const {
13959
+ theme
13960
+ } = useTheme();
13961
+ const fg = () => {
13962
+ if (props.disabled)
13963
+ return theme.textMuted;
13964
+ if (props.variant === "warning")
13965
+ return theme.warning;
13966
+ return theme.accent;
13967
+ };
13968
+ return (() => {
13969
+ var _el$52 = createElement("box"), _el$53 = createElement("text");
13970
+ insertNode(_el$52, _el$53);
13971
+ setProp(_el$52, "paddingLeft", 1);
13972
+ setProp(_el$52, "paddingRight", 1);
13973
+ setProp(_el$52, "onMouseUp", () => {
13974
+ if (!props.disabled)
13975
+ props.onClick?.();
13976
+ });
13977
+ insert(_el$53, () => props.label);
13978
+ effect((_p$) => {
13979
+ var _v$23 = theme.backgroundElement, _v$24 = fg(), _v$25 = TextAttributes12.BOLD;
13980
+ _v$23 !== _p$.e && (_p$.e = setProp(_el$52, "backgroundColor", _v$23, _p$.e));
13981
+ _v$24 !== _p$.t && (_p$.t = setProp(_el$53, "fg", _v$24, _p$.t));
13982
+ _v$25 !== _p$.a && (_p$.a = setProp(_el$53, "attributes", _v$25, _p$.a));
13983
+ return _p$;
13984
+ }, {
13985
+ e: undefined,
13986
+ t: undefined,
13987
+ a: undefined
13988
+ });
13989
+ return _el$52;
13990
+ })();
13991
+ }
13992
+ var init_rc_bridge_dialog = __esm(() => {
13993
+ init_solid();
13994
+ init_solid();
13995
+ init_solid();
13996
+ init_solid();
13997
+ init_solid();
13998
+ init_solid();
13999
+ init_solid();
14000
+ init_solid();
14001
+ init_dev();
14002
+ init_theme();
14003
+ init_keymap();
14004
+ init_dialog();
14005
+ RcBridgeDialog.show = (dialog, orchestrator, status, activeTask, activeTabId) => {
14006
+ dialog.replace(() => createComponent2(RcBridgeDialog, {
14007
+ orchestrator,
14008
+ status,
14009
+ activeTask,
14010
+ activeTabId
14011
+ }));
14012
+ };
14013
+ });
14014
+
14015
+ // src/tui/component/border.tsx
14016
+ var EmptyBorder, SplitBorder, HSplitBorder;
14017
+ var init_border = __esm(() => {
14018
+ EmptyBorder = {
14019
+ topLeft: "",
14020
+ bottomLeft: "",
14021
+ vertical: "",
14022
+ topRight: "",
14023
+ bottomRight: "",
14024
+ horizontal: " ",
14025
+ bottomT: "",
14026
+ topT: "",
14027
+ cross: "",
14028
+ leftT: "",
14029
+ rightT: ""
14030
+ };
14031
+ SplitBorder = {
14032
+ border: ["left", "right"],
14033
+ customBorderChars: {
14034
+ ...EmptyBorder,
14035
+ vertical: "\u2503"
14036
+ }
14037
+ };
14038
+ HSplitBorder = {
14039
+ customBorderChars: {
14040
+ ...EmptyBorder,
14041
+ horizontal: "\u2501"
14042
+ }
14043
+ };
14044
+ });
14045
+
14046
+ // src/tui/component/resizable-edge.tsx
14047
+ function ResizableEdge(props) {
14048
+ const {
14049
+ theme
14050
+ } = useTheme();
14051
+ const [hovering, setHovering] = createSignal(false);
14052
+ const [dragging, setDragging] = createSignal(false);
14053
+ let startCoord = 0;
14054
+ let startSize = 0;
14055
+ const isVertical = () => props.orientation === "vertical";
14056
+ const color = () => {
14057
+ if (dragging())
14058
+ return theme.accent;
14059
+ if (hovering())
14060
+ return theme.borderActive;
14061
+ if (props.focused?.())
14062
+ return theme.focusAccent;
14063
+ return theme.border;
14064
+ };
14065
+ return (() => {
14066
+ var _el$ = createElement("box");
14067
+ setProp(_el$, "flexShrink", 0);
14068
+ setProp(_el$, "onMouseOver", () => setHovering(true));
14069
+ setProp(_el$, "onMouseOut", () => setHovering(false));
14070
+ setProp(_el$, "onMouseDown", (e) => {
14071
+ setDragging(true);
14072
+ startCoord = isVertical() ? e.x : e.y;
14073
+ startSize = props.size();
14074
+ });
14075
+ setProp(_el$, "onMouseDrag", (e) => {
14076
+ if (!dragging())
14077
+ return;
14078
+ const cur = isVertical() ? e.x : e.y;
14079
+ const next = startSize + (cur - startCoord);
14080
+ props.setSize(props.clamp ? props.clamp(next) : next);
14081
+ });
14082
+ setProp(_el$, "onMouseDragEnd", () => {
14083
+ if (dragging())
14084
+ setDragging(false);
14085
+ });
14086
+ setProp(_el$, "onMouseUp", () => {
14087
+ if (dragging())
14088
+ setDragging(false);
14089
+ });
14090
+ effect((_p$) => {
14091
+ var _v$ = isVertical() ? 1 : undefined, _v$2 = isVertical() ? undefined : 1, _v$3 = isVertical() ? ["left"] : ["top"], _v$4 = isVertical() ? SplitBorder.customBorderChars : HSplitBorder.customBorderChars, _v$5 = color();
14092
+ _v$ !== _p$.e && (_p$.e = setProp(_el$, "width", _v$, _p$.e));
14093
+ _v$2 !== _p$.t && (_p$.t = setProp(_el$, "height", _v$2, _p$.t));
14094
+ _v$3 !== _p$.a && (_p$.a = setProp(_el$, "border", _v$3, _p$.a));
14095
+ _v$4 !== _p$.o && (_p$.o = setProp(_el$, "customBorderChars", _v$4, _p$.o));
14096
+ _v$5 !== _p$.i && (_p$.i = setProp(_el$, "borderColor", _v$5, _p$.i));
14097
+ return _p$;
14098
+ }, {
14099
+ e: undefined,
14100
+ t: undefined,
14101
+ a: undefined,
14102
+ o: undefined,
14103
+ i: undefined
14104
+ });
14105
+ return _el$;
14106
+ })();
14107
+ }
14108
+ var init_resizable_edge = __esm(() => {
14109
+ init_solid();
14110
+ init_solid();
14111
+ init_solid();
14112
+ init_dev();
14113
+ init_theme();
14114
+ init_border();
14115
+ });
14116
+
14117
+ // src/tui/context/focus.tsx
14118
+ function FocusProvider(props) {
14119
+ const [focused, setFocusedSignal] = createSignal(props.initial ?? "sidebar");
14120
+ const [refocusTick, setRefocusTick] = createSignal(0);
14121
+ const renderer = useRenderer();
14122
+ function setFocused(pane) {
14123
+ setRefocusTick((t) => t + 1);
14124
+ if (focused() === pane)
14125
+ return;
14126
+ const current = renderer?.currentFocusedRenderable;
14127
+ if (current && !current.isDestroyed) {
14128
+ try {
14129
+ current.blur();
14130
+ } catch {}
14131
+ }
14132
+ setFocusedSignal(pane);
14133
+ }
14134
+ function cycle(delta) {
14135
+ const idx = PANE_ORDER.indexOf(focused());
14136
+ const next = (idx + delta + PANE_ORDER.length) % PANE_ORDER.length;
14137
+ setFocused(PANE_ORDER[next]);
14138
+ }
14139
+ const accessorCache = new Map;
14140
+ function is(pane) {
14141
+ let acc = accessorCache.get(pane);
14142
+ if (!acc) {
14143
+ acc = () => focused() === pane;
14144
+ accessorCache.set(pane, acc);
14145
+ }
14146
+ return acc;
14147
+ }
14148
+ const value = {
14149
+ focused,
14150
+ is,
14151
+ setFocused,
14152
+ cycle,
14153
+ refocusTick
14154
+ };
14155
+ return createComponent2(FocusContext.Provider, {
14156
+ value,
14157
+ get children() {
14158
+ return props.children;
14159
+ }
14160
+ });
14161
+ }
14162
+ function useFocus() {
14163
+ const ctx4 = useContext(FocusContext);
14164
+ if (!ctx4) {
14165
+ throw new Error("useFocus: must be called inside <FocusProvider>. See src/tui/context/focus.tsx.");
14166
+ }
14167
+ return ctx4;
14168
+ }
14169
+ var PANE_ORDER, FocusContext;
14170
+ var init_focus = __esm(() => {
14171
+ init_solid();
14172
+ init_solid();
14173
+ init_dev();
14174
+ PANE_ORDER = ["sidebar", "workspace", "files", "terminal"];
14175
+ FocusContext = createContext(null);
14176
+ });
14177
+
14178
+ // src/tui/component/status-bar.tsx
14179
+ import { TextAttributes as TextAttributes13 } from "@opentui/core";
14180
+ function Hotkey(props) {
14181
+ const {
14182
+ theme
14183
+ } = useTheme();
14184
+ return (() => {
14185
+ var _el$ = createElement("box"), _el$2 = createElement("text"), _el$3 = createTextNode(`[`), _el$4 = createTextNode(`]`), _el$5 = createElement("text");
14186
+ insertNode(_el$, _el$2);
14187
+ insertNode(_el$, _el$5);
14188
+ setProp(_el$, "flexDirection", "row");
14189
+ setProp(_el$, "gap", 1);
14190
+ setProp(_el$, "flexShrink", 0);
14191
+ insertNode(_el$2, _el$3);
14192
+ insertNode(_el$2, _el$4);
14193
+ setProp(_el$2, "wrapMode", "none");
14194
+ insert(_el$2, () => props.keys, _el$4);
14195
+ setProp(_el$5, "wrapMode", "none");
14196
+ insert(_el$5, () => props.label);
14197
+ effect((_p$) => {
14198
+ var _v$ = theme.accent, _v$2 = TextAttributes13.BOLD, _v$3 = theme.textMuted;
14199
+ _v$ !== _p$.e && (_p$.e = setProp(_el$2, "fg", _v$, _p$.e));
14200
+ _v$2 !== _p$.t && (_p$.t = setProp(_el$2, "attributes", _v$2, _p$.t));
14201
+ _v$3 !== _p$.a && (_p$.a = setProp(_el$5, "fg", _v$3, _p$.a));
14202
+ return _p$;
14203
+ }, {
14204
+ e: undefined,
14205
+ t: undefined,
14206
+ a: undefined
14207
+ });
14208
+ return _el$;
14209
+ })();
14210
+ }
14211
+ function StatusBar() {
14212
+ const {
14213
+ theme
14214
+ } = useTheme();
14215
+ const focus = useFocus();
14216
+ const ctrlCArmed2 = useCtrlCArmed();
14217
+ const sectionLabel = () => {
14218
+ switch (focus.focused()) {
14219
+ case "sidebar":
14220
+ return "Tasks:";
14221
+ case "workspace":
14222
+ return "Chat:";
14223
+ case "files":
14224
+ return "Files:";
14225
+ case "terminal":
14226
+ return "Terminal:";
14227
+ }
13748
14228
  };
13749
14229
  const leftHints = () => KobeKeymap.filter((b) => {
13750
14230
  if (!b.hint || b.hint.pin)
13751
14231
  return false;
13752
- if (b.scope === focus.focused())
13753
- return true;
13754
- if (b.id === "focus.detach" && focus.focused() === "workspace")
13755
- return true;
13756
- return false;
14232
+ return b.scope === focus.focused();
13757
14233
  });
13758
14234
  const rightHints = KobeKeymap.filter((b) => b.hint?.pin === "right");
13759
14235
  return (() => {
@@ -13807,7 +14283,7 @@ function StatusBar() {
13807
14283
  insertNode(_el$0, createTextNode(`Press Ctrl+C again to exit`));
13808
14284
  setProp(_el$0, "wrapMode", "none");
13809
14285
  effect((_p$) => {
13810
- var _v$4 = theme.warning, _v$5 = TextAttributes12.BOLD;
14286
+ var _v$4 = theme.warning, _v$5 = TextAttributes13.BOLD;
13811
14287
  _v$4 !== _p$.e && (_p$.e = setProp(_el$0, "fg", _v$4, _p$.e));
13812
14288
  _v$5 !== _p$.t && (_p$.t = setProp(_el$0, "attributes", _v$5, _p$.t));
13813
14289
  return _p$;
@@ -13819,7 +14295,7 @@ function StatusBar() {
13819
14295
  }
13820
14296
  }), null);
13821
14297
  effect((_p$) => {
13822
- var _v$6 = theme.primary, _v$7 = TextAttributes12.BOLD;
14298
+ var _v$6 = theme.primary, _v$7 = TextAttributes13.BOLD;
13823
14299
  _v$6 !== _p$.e && (_p$.e = setProp(_el$8, "fg", _v$6, _p$.e));
13824
14300
  _v$7 !== _p$.t && (_p$.t = setProp(_el$8, "attributes", _v$7, _p$.t));
13825
14301
  return _p$;
@@ -13845,7 +14321,7 @@ var init_status_bar = __esm(() => {
13845
14321
  });
13846
14322
 
13847
14323
  // src/tui/component/toast-overlay.tsx
13848
- import { TextAttributes as TextAttributes13 } from "@opentui/core";
14324
+ import { TextAttributes as TextAttributes14 } from "@opentui/core";
13849
14325
  function ToastOverlay() {
13850
14326
  const {
13851
14327
  theme
@@ -13888,7 +14364,7 @@ function ToastOverlay() {
13888
14364
  setProp(_el$4, "wrapMode", "none");
13889
14365
  insert(_el$4, () => toast.title);
13890
14366
  effect((_p$) => {
13891
- var _v$3 = bg(), _v$4 = fg(), _v$5 = TextAttributes13.BOLD, _v$6 = fg();
14367
+ var _v$3 = bg(), _v$4 = fg(), _v$5 = TextAttributes14.BOLD, _v$6 = fg();
13892
14368
  _v$3 !== _p$.e && (_p$.e = setProp(_el$2, "backgroundColor", _v$3, _p$.e));
13893
14369
  _v$4 !== _p$.t && (_p$.t = setProp(_el$3, "fg", _v$4, _p$.t));
13894
14370
  _v$5 !== _p$.a && (_p$.a = setProp(_el$3, "attributes", _v$5, _p$.a));
@@ -13932,7 +14408,7 @@ var init_toast_overlay = __esm(() => {
13932
14408
  });
13933
14409
 
13934
14410
  // src/tui/component/create-pr-button.tsx
13935
- import { TextAttributes as TextAttributes14 } from "@opentui/core";
14411
+ import { TextAttributes as TextAttributes15 } from "@opentui/core";
13936
14412
  function isEnabled(task) {
13937
14413
  if (!task)
13938
14414
  return false;
@@ -13969,7 +14445,7 @@ function CreatePRButton(props) {
13969
14445
  insertNode(_el$4, createTextNode(`Create PR`));
13970
14446
  setProp(_el$4, "wrapMode", "none");
13971
14447
  effect((_p$) => {
13972
- var _v$ = enabled() ? onClick : undefined, _v$2 = bracketColor(), _v$3 = TextAttributes14.BOLD, _v$4 = labelColor();
14448
+ var _v$ = enabled() ? onClick : undefined, _v$2 = bracketColor(), _v$3 = TextAttributes15.BOLD, _v$4 = labelColor();
13973
14449
  _v$ !== _p$.e && (_p$.e = setProp(_el$, "onMouseUp", _v$, _p$.e));
13974
14450
  _v$2 !== _p$.t && (_p$.t = setProp(_el$2, "fg", _v$2, _p$.t));
13975
14451
  _v$3 !== _p$.a && (_p$.a = setProp(_el$2, "attributes", _v$3, _p$.a));
@@ -14259,7 +14735,7 @@ var init_markdown_parser = __esm(() => {
14259
14735
  });
14260
14736
 
14261
14737
  // src/tui/panes/chat/Markdown.tsx
14262
- import { TextAttributes as TextAttributes15 } from "@opentui/core";
14738
+ import { TextAttributes as TextAttributes16 } from "@opentui/core";
14263
14739
  function InlineSpans(props) {
14264
14740
  const {
14265
14741
  theme
@@ -14289,7 +14765,7 @@ function InlineSpans(props) {
14289
14765
  insert(_el$3, () => t.text, _el$5);
14290
14766
  effect((_$p) => setProp(_el$3, "style", {
14291
14767
  fg: theme.accent,
14292
- attributes: TextAttributes15.DIM
14768
+ attributes: TextAttributes16.DIM
14293
14769
  }, _$p));
14294
14770
  return _el$3;
14295
14771
  })();
@@ -14301,7 +14777,7 @@ function InlineSpans(props) {
14301
14777
  insert(_el$6, () => showUrl ? t.text : t.href);
14302
14778
  effect((_$p) => setProp(_el$6, "style", {
14303
14779
  fg: theme.accent,
14304
- attributes: TextAttributes15.UNDERLINE
14780
+ attributes: TextAttributes16.UNDERLINE
14305
14781
  }, _$p));
14306
14782
  return _el$6;
14307
14783
  })(), createComponent2(Show, {
@@ -14313,7 +14789,7 @@ function InlineSpans(props) {
14313
14789
  insert(_el$7, () => t.href, _el$9);
14314
14790
  effect((_$p) => setProp(_el$7, "style", {
14315
14791
  fg: theme.textMuted,
14316
- attributes: TextAttributes15.DIM
14792
+ attributes: TextAttributes16.DIM
14317
14793
  }, _$p));
14318
14794
  return _el$7;
14319
14795
  }
@@ -14490,7 +14966,7 @@ function VerticalTable(props) {
14490
14966
  var _el$20 = createElement("text");
14491
14967
  insertNode(_el$20, createTextNode(`\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`));
14492
14968
  effect((_p$) => {
14493
- var _v$4 = theme.textMuted, _v$5 = TextAttributes15.DIM;
14969
+ var _v$4 = theme.textMuted, _v$5 = TextAttributes16.DIM;
14494
14970
  _v$4 !== _p$.e && (_p$.e = setProp(_el$20, "fg", _v$4, _p$.e));
14495
14971
  _v$5 !== _p$.t && (_p$.t = setProp(_el$20, "attributes", _v$5, _p$.t));
14496
14972
  return _p$;
@@ -14581,7 +15057,7 @@ function BlockNode(props) {
14581
15057
  })();
14582
15058
  }
14583
15059
  if (b.kind === "heading") {
14584
- const attrs = b.level === 1 ? TextAttributes15.BOLD | TextAttributes15.UNDERLINE : TextAttributes15.BOLD;
15060
+ const attrs = b.level === 1 ? TextAttributes16.BOLD | TextAttributes16.UNDERLINE : TextAttributes16.BOLD;
14585
15061
  const fg = b.level <= 2 ? theme.accent : theme.text;
14586
15062
  const tokens = parseInline(b.text);
14587
15063
  return (() => {
@@ -14607,7 +15083,7 @@ function BlockNode(props) {
14607
15083
  const checkbox = item.checked ? "[x] " : "[ ] ";
14608
15084
  const bullet = b.ordered ? `${b.start + idx()}. ` : "\u2022 ";
14609
15085
  const prefix = isTask ? checkbox : bullet;
14610
- const labelAttrs = isTask && item.checked ? TextAttributes15.DIM : 0;
15086
+ const labelAttrs = isTask && item.checked ? TextAttributes16.DIM : 0;
14611
15087
  return (() => {
14612
15088
  var _el$30 = createElement("text"), _el$31 = createElement("span");
14613
15089
  insertNode(_el$30, _el$31);
@@ -14654,9 +15130,9 @@ function BlockNode(props) {
14654
15130
  }
14655
15131
  }), null);
14656
15132
  effect((_p$) => {
14657
- var _v$10 = theme.textMuted, _v$11 = TextAttributes15.ITALIC, _v$12 = {
15133
+ var _v$10 = theme.textMuted, _v$11 = TextAttributes16.ITALIC, _v$12 = {
14658
15134
  fg: theme.textMuted,
14659
- attributes: TextAttributes15.DIM
15135
+ attributes: TextAttributes16.DIM
14660
15136
  };
14661
15137
  _v$10 !== _p$.e && (_p$.e = setProp(_el$33, "fg", _v$10, _p$.e));
14662
15138
  _v$11 !== _p$.t && (_p$.t = setProp(_el$33, "attributes", _v$11, _p$.t));
@@ -14698,7 +15174,7 @@ function BlockNode(props) {
14698
15174
  var _el$37 = createElement("text");
14699
15175
  insert(_el$37, () => b.lang);
14700
15176
  effect((_p$) => {
14701
- var _v$13 = theme.textMuted, _v$14 = TextAttributes15.DIM;
15177
+ var _v$13 = theme.textMuted, _v$14 = TextAttributes16.DIM;
14702
15178
  _v$13 !== _p$.e && (_p$.e = setProp(_el$37, "fg", _v$13, _p$.e));
14703
15179
  _v$14 !== _p$.t && (_p$.t = setProp(_el$37, "attributes", _v$14, _p$.t));
14704
15180
  return _p$;
@@ -14758,7 +15234,7 @@ var init_Markdown = __esm(() => {
14758
15234
  });
14759
15235
 
14760
15236
  // src/tui/component/update-dialog.tsx
14761
- import { TextAttributes as TextAttributes16 } from "@opentui/core";
15237
+ import { TextAttributes as TextAttributes17 } from "@opentui/core";
14762
15238
  function UpdateDialog(props) {
14763
15239
  const dialog = useDialog();
14764
15240
  const {
@@ -14873,7 +15349,7 @@ function UpdateDialog(props) {
14873
15349
  }
14874
15350
  }));
14875
15351
  effect((_p$) => {
14876
- var _v$ = TextAttributes16.BOLD, _v$2 = theme.text, _v$3 = theme.textMuted, _v$4 = theme.textMuted, _v$5 = theme.textMuted, _v$6 = theme.warning, _v$7 = TextAttributes16.BOLD, _v$8 = theme.textMuted, _v$9 = theme.accent, _v$0 = TextAttributes16.BOLD, _v$1 = theme.textMuted;
15352
+ var _v$ = TextAttributes17.BOLD, _v$2 = theme.text, _v$3 = theme.textMuted, _v$4 = theme.textMuted, _v$5 = theme.textMuted, _v$6 = theme.warning, _v$7 = TextAttributes17.BOLD, _v$8 = theme.textMuted, _v$9 = theme.accent, _v$0 = TextAttributes17.BOLD, _v$1 = theme.textMuted;
14877
15353
  _v$ !== _p$.e && (_p$.e = setProp(_el$3, "attributes", _v$, _p$.e));
14878
15354
  _v$2 !== _p$.t && (_p$.t = setProp(_el$3, "fg", _v$2, _p$.t));
14879
15355
  _v$3 !== _p$.a && (_p$.a = setProp(_el$5, "fg", _v$3, _p$.a));
@@ -14924,17 +15400,20 @@ var init_update_dialog = __esm(() => {
14924
15400
  });
14925
15401
 
14926
15402
  // src/tui/component/top-bar.tsx
14927
- import { TextAttributes as TextAttributes17 } from "@opentui/core";
15403
+ import { TextAttributes as TextAttributes18 } from "@opentui/core";
14928
15404
  function TopBar(props) {
14929
15405
  const {
14930
15406
  theme
14931
15407
  } = useTheme();
14932
15408
  const dialog = useDialog();
15409
+ const remoteOrch = props.orchestrator instanceof RemoteOrchestrator ? props.orchestrator : null;
15410
+ const rcBridge = props.orchestrator.rcBridgeSignal();
15411
+ const isBridgeOn = () => rcBridge().state === "running" || rcBridge().state === "starting";
14933
15412
  return (() => {
14934
- var _el$ = createElement("box"), _el$2 = createElement("box"), _el$3 = createElement("text"), _el$5 = createElement("text"), _el$6 = createTextNode(`v`), _el$0 = createElement("box"), _el$10 = createElement("box");
15413
+ var _el$ = createElement("box"), _el$2 = createElement("box"), _el$3 = createElement("text"), _el$5 = createElement("text"), _el$6 = createTextNode(`v`), _el$10 = createElement("box"), _el$12 = createElement("box");
14935
15414
  insertNode(_el$, _el$2);
14936
- insertNode(_el$, _el$0);
14937
15415
  insertNode(_el$, _el$10);
15416
+ insertNode(_el$, _el$12);
14938
15417
  setProp(_el$, "flexDirection", "row");
14939
15418
  setProp(_el$, "paddingLeft", 2);
14940
15419
  setProp(_el$, "paddingRight", 2);
@@ -14965,7 +15444,7 @@ function TopBar(props) {
14965
15444
  });
14966
15445
  insert(_el$7, () => props.updateInfo()?.latest, _el$9);
14967
15446
  effect((_p$) => {
14968
- var _v$ = theme.warning, _v$2 = TextAttributes17.BOLD;
15447
+ var _v$ = theme.warning, _v$2 = TextAttributes18.BOLD;
14969
15448
  _v$ !== _p$.e && (_p$.e = setProp(_el$7, "fg", _v$, _p$.e));
14970
15449
  _v$2 !== _p$.t && (_p$.t = setProp(_el$7, "attributes", _v$2, _p$.t));
14971
15450
  return _p$;
@@ -14976,38 +15455,66 @@ function TopBar(props) {
14976
15455
  return _el$7;
14977
15456
  }
14978
15457
  }), null);
14979
- setProp(_el$0, "flexDirection", "row");
14980
- setProp(_el$0, "flexGrow", 1);
14981
- setProp(_el$0, "flexShrink", 1);
14982
- setProp(_el$0, "flexBasis", 0);
14983
- setProp(_el$0, "gap", 1);
14984
- setProp(_el$0, "justifyContent", "center");
14985
- insert(_el$0, createComponent2(Show, {
15458
+ insert(_el$2, createComponent2(Show, {
14986
15459
  get when() {
14987
- return props.activeTask() !== undefined;
15460
+ return remoteOrch && isBridgeOn();
14988
15461
  },
14989
15462
  get children() {
14990
- var _el$1 = createElement("text");
14991
- setProp(_el$1, "wrapMode", "none");
14992
- insert(_el$1, () => props.activeTask()?.branch);
15463
+ var _el$0 = createElement("text"), _el$1 = createTextNode(`\u25C9 `);
15464
+ insertNode(_el$0, _el$1);
15465
+ setProp(_el$0, "onMouseUp", () => {
15466
+ const orch = remoteOrch;
15467
+ if (orch)
15468
+ RcBridgeDialog.show(dialog, orch, rcBridge, props.activeTask, props.activeChatTabId);
15469
+ });
15470
+ insert(_el$0, (() => {
15471
+ var _c$ = memo2(() => rcBridge().state === "running");
15472
+ return () => _c$() ? rcBridge().bound?.taskTitle ?? rcBridge().envId ?? "RC" : "RC connecting\u2026";
15473
+ })(), null);
14993
15474
  effect((_p$) => {
14994
- var _v$3 = theme.text, _v$4 = TextAttributes17.BOLD;
14995
- _v$3 !== _p$.e && (_p$.e = setProp(_el$1, "fg", _v$3, _p$.e));
14996
- _v$4 !== _p$.t && (_p$.t = setProp(_el$1, "attributes", _v$4, _p$.t));
15475
+ var _v$3 = theme.accent, _v$4 = TextAttributes18.BOLD;
15476
+ _v$3 !== _p$.e && (_p$.e = setProp(_el$0, "fg", _v$3, _p$.e));
15477
+ _v$4 !== _p$.t && (_p$.t = setProp(_el$0, "attributes", _v$4, _p$.t));
14997
15478
  return _p$;
14998
15479
  }, {
14999
15480
  e: undefined,
15000
15481
  t: undefined
15001
15482
  });
15002
- return _el$1;
15483
+ return _el$0;
15003
15484
  }
15004
- }));
15485
+ }), null);
15005
15486
  setProp(_el$10, "flexDirection", "row");
15006
15487
  setProp(_el$10, "flexGrow", 1);
15007
15488
  setProp(_el$10, "flexShrink", 1);
15008
15489
  setProp(_el$10, "flexBasis", 0);
15009
- setProp(_el$10, "justifyContent", "flex-end");
15010
- insert(_el$10, createComponent2(CreatePRButton, {
15490
+ setProp(_el$10, "gap", 1);
15491
+ setProp(_el$10, "justifyContent", "center");
15492
+ insert(_el$10, createComponent2(Show, {
15493
+ get when() {
15494
+ return props.activeTask() !== undefined;
15495
+ },
15496
+ get children() {
15497
+ var _el$11 = createElement("text");
15498
+ setProp(_el$11, "wrapMode", "none");
15499
+ insert(_el$11, () => props.activeTask()?.branch);
15500
+ effect((_p$) => {
15501
+ var _v$5 = theme.text, _v$6 = TextAttributes18.BOLD;
15502
+ _v$5 !== _p$.e && (_p$.e = setProp(_el$11, "fg", _v$5, _p$.e));
15503
+ _v$6 !== _p$.t && (_p$.t = setProp(_el$11, "attributes", _v$6, _p$.t));
15504
+ return _p$;
15505
+ }, {
15506
+ e: undefined,
15507
+ t: undefined
15508
+ });
15509
+ return _el$11;
15510
+ }
15511
+ }));
15512
+ setProp(_el$12, "flexDirection", "row");
15513
+ setProp(_el$12, "flexGrow", 1);
15514
+ setProp(_el$12, "flexShrink", 1);
15515
+ setProp(_el$12, "flexBasis", 0);
15516
+ setProp(_el$12, "justifyContent", "flex-end");
15517
+ insert(_el$12, createComponent2(CreatePRButton, {
15011
15518
  get orchestrator() {
15012
15519
  return props.orchestrator;
15013
15520
  },
@@ -15016,10 +15523,10 @@ function TopBar(props) {
15016
15523
  }
15017
15524
  }));
15018
15525
  effect((_p$) => {
15019
- var _v$5 = theme.primary, _v$6 = TextAttributes17.BOLD, _v$7 = theme.textMuted;
15020
- _v$5 !== _p$.e && (_p$.e = setProp(_el$3, "fg", _v$5, _p$.e));
15021
- _v$6 !== _p$.t && (_p$.t = setProp(_el$3, "attributes", _v$6, _p$.t));
15022
- _v$7 !== _p$.a && (_p$.a = setProp(_el$5, "fg", _v$7, _p$.a));
15526
+ var _v$7 = theme.primary, _v$8 = TextAttributes18.BOLD, _v$9 = theme.textMuted;
15527
+ _v$7 !== _p$.e && (_p$.e = setProp(_el$3, "fg", _v$7, _p$.e));
15528
+ _v$8 !== _p$.t && (_p$.t = setProp(_el$3, "attributes", _v$8, _p$.t));
15529
+ _v$9 !== _p$.a && (_p$.a = setProp(_el$5, "fg", _v$9, _p$.a));
15023
15530
  return _p$;
15024
15531
  }, {
15025
15532
  e: undefined,
@@ -15037,11 +15544,14 @@ var init_top_bar = __esm(() => {
15037
15544
  init_solid();
15038
15545
  init_solid();
15039
15546
  init_solid();
15547
+ init_solid();
15040
15548
  init_dev();
15041
15549
  init_package();
15550
+ init_remote_orchestrator();
15042
15551
  init_theme();
15043
15552
  init_dialog();
15044
15553
  init_create_pr_button();
15554
+ init_rc_bridge_dialog();
15045
15555
  init_update_dialog();
15046
15556
  });
15047
15557
 
@@ -15090,7 +15600,8 @@ var init_sync = __esm(() => {
15090
15600
  });
15091
15601
 
15092
15602
  // src/engine/claude-code-local/history.ts
15093
- import { readFile as readFile4, readdir, unlink as unlink2 } from "fs/promises";
15603
+ import { randomUUID } from "crypto";
15604
+ import { appendFile, mkdir as mkdir3, readFile as readFile4, readdir, unlink as unlink2, writeFile as writeFile3 } from "fs/promises";
15094
15605
  import { homedir as homedir8 } from "os";
15095
15606
  import path6 from "path";
15096
15607
  function encodeCwd(cwd) {
@@ -15187,6 +15698,76 @@ function extractUsage(v) {
15187
15698
  function isObject(v) {
15188
15699
  return typeof v === "object" && v !== null && !Array.isArray(v);
15189
15700
  }
15701
+ async function appendInterruptedUserPrompt(sessionId, cwd, prompt, deps = defaultDeps2) {
15702
+ if (!prompt || prompt.trim().length === 0)
15703
+ return;
15704
+ const projectDir = path6.join(deps.projectsDir(), encodeCwd(cwd));
15705
+ const filePath = path6.join(projectDir, `${sessionId}.jsonl`);
15706
+ let lines = [];
15707
+ try {
15708
+ const raw = await readFile4(filePath, "utf8");
15709
+ lines = raw.split(`
15710
+ `).filter((l) => l.length > 0);
15711
+ } catch (err) {
15712
+ if (err.code !== "ENOENT")
15713
+ throw err;
15714
+ await mkdir3(projectDir, { recursive: true });
15715
+ }
15716
+ let lastConvIdx = -1;
15717
+ let lastConvRecord = null;
15718
+ let lastConvRole = null;
15719
+ for (let i = lines.length - 1;i >= 0; i--) {
15720
+ let parsed;
15721
+ try {
15722
+ parsed = JSON.parse(lines[i]);
15723
+ } catch {
15724
+ continue;
15725
+ }
15726
+ if (!isObject(parsed))
15727
+ continue;
15728
+ const inner = isObject(parsed.message) ? parsed.message : parsed;
15729
+ const role = inner.role;
15730
+ if (role === "user" || role === "assistant") {
15731
+ lastConvIdx = i;
15732
+ lastConvRecord = parsed;
15733
+ lastConvRole = role;
15734
+ break;
15735
+ }
15736
+ }
15737
+ const now = new Date().toISOString();
15738
+ if (lastConvRole === "user" && lastConvRecord && lastConvIdx >= 0) {
15739
+ const inner = isObject(lastConvRecord.message) ? lastConvRecord.message : lastConvRecord;
15740
+ const existing = typeof inner.content === "string" ? inner.content : "";
15741
+ if (existing === prompt || existing.endsWith(`
15742
+
15743
+ ${prompt}`))
15744
+ return;
15745
+ inner.content = existing.length > 0 ? `${existing}
15746
+
15747
+ ${prompt}` : prompt;
15748
+ lastConvRecord.timestamp = now;
15749
+ lines[lastConvIdx] = JSON.stringify(lastConvRecord);
15750
+ await writeFile3(filePath, `${lines.join(`
15751
+ `)}
15752
+ `);
15753
+ return;
15754
+ }
15755
+ const parentUuid = lastConvRecord && typeof lastConvRecord.uuid === "string" ? lastConvRecord.uuid : null;
15756
+ const record = {
15757
+ type: "user",
15758
+ message: { role: "user", content: prompt },
15759
+ uuid: randomUUID(),
15760
+ parentUuid,
15761
+ sessionId,
15762
+ cwd,
15763
+ timestamp: now,
15764
+ isSidechain: false,
15765
+ userType: "external",
15766
+ version: "1.0.0"
15767
+ };
15768
+ await appendFile(filePath, `${JSON.stringify(record)}
15769
+ `);
15770
+ }
15190
15771
  var defaultDeps2;
15191
15772
  var init_history = __esm(() => {
15192
15773
  defaultDeps2 = {
@@ -15594,13 +16175,21 @@ class ClaudeCodeLocal {
15594
16175
  }
15595
16176
  async stop(handle) {
15596
16177
  const sid = handle.sessionId;
15597
- await this.registry.kill(sid, this.stopGraceMs);
15598
16178
  const session = this.running.get(sid);
16179
+ const shouldRescue = !!session && !session.completedNaturally && session.prompt.trim().length > 0;
16180
+ const rescuePrompt = session?.prompt ?? "";
16181
+ const rescueCwd = session?.cwd ?? handle.cwd;
16182
+ await this.registry.kill(sid, this.stopGraceMs);
15599
16183
  if (session) {
15600
16184
  session.closed = true;
15601
16185
  this.notify(session);
15602
16186
  this.running.delete(sid);
15603
16187
  }
16188
+ if (shouldRescue) {
16189
+ try {
16190
+ await appendInterruptedUserPrompt(sid, rescueCwd, rescuePrompt);
16191
+ } catch {}
16192
+ }
15604
16193
  }
15605
16194
  async start(args2) {
15606
16195
  const binaryPath = await this.binaryPathResolver();
@@ -15633,14 +16222,17 @@ class ClaudeCodeLocal {
15633
16222
  spawned,
15634
16223
  queue,
15635
16224
  waiters: [],
15636
- closed: false
16225
+ closed: false,
16226
+ completedNaturally: false,
16227
+ prompt: args2.prompt
15637
16228
  };
15638
16229
  this.running.set(sessionId, session);
15639
16230
  this.registry.register({
15640
16231
  sessionId,
15641
16232
  cwd: args2.cwd,
15642
16233
  proc: spawned.proc,
15643
- startedAt: Date.now()
16234
+ startedAt: Date.now(),
16235
+ prompt: args2.prompt
15644
16236
  });
15645
16237
  resolveHandle({ sessionId, cwd: args2.cwd });
15646
16238
  };
@@ -15662,6 +16254,9 @@ class ClaudeCodeLocal {
15662
16254
  try {
15663
16255
  for await (const ev of events) {
15664
16256
  queue.push(ev);
16257
+ if (ev.type === "done" && session) {
16258
+ session.completedNaturally = true;
16259
+ }
15665
16260
  if (session)
15666
16261
  this.notify(session);
15667
16262
  }
@@ -16235,11 +16830,26 @@ var init_use_pane_sizes = __esm(() => {
16235
16830
 
16236
16831
  // src/tui/component/new-task-dialog/state.ts
16237
16832
  import * as fs5 from "fs";
16833
+ import * as os from "os";
16834
+ function pickerModeFor(value, repoOptions) {
16835
+ const trimmed = value.trim();
16836
+ if (repoOptions.includes(trimmed))
16837
+ return "saved";
16838
+ if (trimmed.startsWith("~"))
16839
+ return "browse";
16840
+ if (trimmed.includes("/"))
16841
+ return "browse";
16842
+ return "saved";
16843
+ }
16238
16844
  function stripNewlines(v) {
16239
16845
  return v.replace(/[\r\n]+/g, "");
16240
16846
  }
16241
16847
  function nextField(field) {
16242
- return field === "repoPicker" ? "repoCustom" : field === "repoCustom" ? "baseRef" : "repoPicker";
16848
+ if (field === "repo")
16849
+ return "baseRef";
16850
+ if (field === "baseRef")
16851
+ return "confirm";
16852
+ return "repo";
16243
16853
  }
16244
16854
  function computeRepoOptions(defaultRepo, savedRepos) {
16245
16855
  const seen = new Set;
@@ -16307,6 +16917,27 @@ function validateRepoPath(repo) {
16307
16917
  }
16308
16918
  return null;
16309
16919
  }
16920
+ function getCurrentBranch(repo) {
16921
+ if (!repo)
16922
+ return null;
16923
+ try {
16924
+ const { spawnSync: spawnSync8 } = __require("child_process");
16925
+ const out = spawnSync8("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
16926
+ cwd: repo,
16927
+ encoding: "utf-8",
16928
+ timeout: 2000,
16929
+ stdio: ["ignore", "pipe", "ignore"]
16930
+ });
16931
+ if (out.status !== 0)
16932
+ return null;
16933
+ const name = out.stdout.trim();
16934
+ if (!name || name === "HEAD")
16935
+ return null;
16936
+ return name;
16937
+ } catch {
16938
+ return null;
16939
+ }
16940
+ }
16310
16941
  function listLocalBranches(repo) {
16311
16942
  if (!repo)
16312
16943
  return [];
@@ -16332,6 +16963,59 @@ function listLocalBranches(repo) {
16332
16963
  return [];
16333
16964
  }
16334
16965
  }
16966
+ function expandHome(p) {
16967
+ if (p === "~")
16968
+ return os.homedir();
16969
+ if (p.startsWith("~/"))
16970
+ return os.homedir() + p.slice(1);
16971
+ return p;
16972
+ }
16973
+ function splitPathForDirSuggest(value) {
16974
+ if (!value)
16975
+ return { base: "", filter: "" };
16976
+ const normalized = value === "~" ? "~/" : value;
16977
+ const expanded = expandHome(normalized);
16978
+ if (expanded.endsWith("/"))
16979
+ return { base: expanded, filter: "" };
16980
+ const lastSlash = expanded.lastIndexOf("/");
16981
+ if (lastSlash === -1)
16982
+ return { base: "", filter: expanded };
16983
+ return { base: expanded.slice(0, lastSlash + 1), filter: expanded.slice(lastSlash + 1) };
16984
+ }
16985
+ function listSubdirs(base) {
16986
+ if (!base)
16987
+ return [];
16988
+ try {
16989
+ const entries = fs5.readdirSync(base, { withFileTypes: true });
16990
+ const out = [];
16991
+ for (const e of entries) {
16992
+ if (e.isDirectory())
16993
+ out.push(e.name);
16994
+ }
16995
+ return out.sort((a, b) => a.localeCompare(b));
16996
+ } catch {
16997
+ return [];
16998
+ }
16999
+ }
17000
+ function filterSubdirs(all, filter) {
17001
+ const f = filter.toLowerCase();
17002
+ const showHidden = f.startsWith(".");
17003
+ const visible = showHidden ? all : all.filter((n) => !n.startsWith("."));
17004
+ if (!f)
17005
+ return visible;
17006
+ return visible.filter((n) => n.toLowerCase().startsWith(f));
17007
+ }
17008
+ function joinDrill(typedValue, baseExpanded, name) {
17009
+ const out = `${baseExpanded + name}/`;
17010
+ if (typedValue.startsWith("~")) {
17011
+ const home = os.homedir();
17012
+ if (out === `${home}/`)
17013
+ return "~/";
17014
+ if (out.startsWith(`${home}/`))
17015
+ return `~${out.slice(home.length)}`;
17016
+ }
17017
+ return out;
17018
+ }
16335
17019
  function resolveBaseRef(typed, filteredBranches, cursor) {
16336
17020
  const picked = filteredBranches[cursor];
16337
17021
  if (picked)
@@ -16343,63 +17027,115 @@ var DEFAULT_BASE_REF = "main", PICKER_MAX_VISIBLE = 8;
16343
17027
  var init_state2 = () => {};
16344
17028
 
16345
17029
  // src/tui/component/new-task-dialog/dialog.tsx
16346
- import { TextAttributes as TextAttributes18 } from "@opentui/core";
17030
+ import { TextAttributes as TextAttributes19 } from "@opentui/core";
16347
17031
  function NewTaskDialogView(props) {
16348
17032
  const dialog = useDialog();
16349
17033
  const {
16350
17034
  theme
16351
17035
  } = useTheme();
16352
- const [field, setField] = createSignal("repoPicker");
17036
+ const [field, setField] = createSignal("repo");
16353
17037
  const [repo, setRepo] = createSignal(props.defaultRepo);
16354
- const [baseRef, setBaseRef] = createSignal(DEFAULT_BASE_REF);
17038
+ const [baseRef, setBaseRef] = createSignal(getCurrentBranch(expandHome(props.defaultRepo.trim())) ?? DEFAULT_BASE_REF);
17039
+ const [baseRefTouched, setBaseRefTouched] = createSignal(false);
16355
17040
  const repoOptions = createMemo(() => computeRepoOptions(props.defaultRepo, props.savedRepos));
16356
- const repoFiltered = createMemo(() => {
16357
- const all = repoOptions();
16358
- if (field() !== "repoCustom")
16359
- return all;
16360
- return filterRepos(all, repo());
16361
- });
17041
+ const mode = createMemo(() => pickerModeFor(repo(), repoOptions()));
17042
+ const subdirSplit = createMemo(() => splitPathForDirSuggest(repo()));
17043
+ const subdirAll = createMemo(() => listSubdirs(subdirSplit().base));
17044
+ const subdirFiltered = createMemo(() => filterSubdirs(subdirAll(), subdirSplit().filter));
17045
+ const savedFiltered = createMemo(() => filterRepos(repoOptions(), repo()));
17046
+ const activeList = createMemo(() => mode() === "browse" ? subdirFiltered() : savedFiltered());
16362
17047
  const [repoCursor, setRepoCursor] = createSignal(0);
16363
- const branches = createMemo(() => listLocalBranches(repo().trim()));
17048
+ const activeWindow = createMemo(() => windowAround(activeList(), repoCursor()));
17049
+ const branches = createMemo(() => listLocalBranches(expandHome(repo().trim())));
16364
17050
  const branchFiltered = createMemo(() => filterBranches(branches(), baseRef()));
16365
17051
  const [branchCursor, setBranchCursor] = createSignal(0);
17052
+ const branchWindow = createMemo(() => windowAround(branchFiltered(), branchCursor()));
16366
17053
  createEffect(() => {
16367
17054
  branchFiltered();
16368
17055
  setBranchCursor(0);
16369
17056
  });
16370
17057
  createEffect(() => {
16371
- repoFiltered();
17058
+ const r = expandHome(repo().trim());
17059
+ if (!r)
17060
+ return;
17061
+ if (baseRefTouched())
17062
+ return;
17063
+ const current = getCurrentBranch(r);
17064
+ if (current)
17065
+ setBaseRef(current);
17066
+ });
17067
+ createEffect(() => {
17068
+ activeList();
16372
17069
  setRepoCursor(0);
16373
17070
  });
16374
- const repoWindow = createMemo(() => windowAround(repoFiltered(), repoCursor()));
16375
- const branchWindow = createMemo(() => windowAround(branchFiltered(), branchCursor()));
16376
17071
  const [submitError, setSubmitError] = createSignal(null);
16377
17072
  createEffect(() => {
16378
17073
  repo();
16379
17074
  setSubmitError(null);
16380
17075
  });
16381
17076
  function commit() {
16382
- const r = repo().trim();
17077
+ const r = expandHome(repo().trim());
16383
17078
  if (!r)
16384
17079
  return;
16385
- const reason = validateRepoPath(r);
16386
- if (reason) {
16387
- setSubmitError(reason);
16388
- setField("repoCustom");
17080
+ const reason = validateRepoPath(r);
17081
+ if (reason) {
17082
+ setSubmitError(reason);
17083
+ setField("repo");
17084
+ return;
17085
+ }
17086
+ const b = baseRef().trim() || DEFAULT_BASE_REF;
17087
+ props.onSubmit({
17088
+ repo: r,
17089
+ baseRef: b
17090
+ });
17091
+ dialog.clear();
17092
+ }
17093
+ function onRepoSubmit() {
17094
+ if (!repo().trim() && mode() === "saved") {
17095
+ const picked2 = activeList()[0];
17096
+ if (picked2) {
17097
+ setRepo(picked2);
17098
+ setField("baseRef");
17099
+ return;
17100
+ }
17101
+ }
17102
+ if (mode() === "browse") {
17103
+ const list = subdirFiltered();
17104
+ const picked2 = list[repoCursor()];
17105
+ const split = subdirSplit();
17106
+ if (picked2) {
17107
+ if (split.filter) {
17108
+ setRepo(joinDrill(repo(), split.base, picked2));
17109
+ return;
17110
+ }
17111
+ const resolved = expandHome(repo().trim());
17112
+ if (!resolved || validateRepoPath(resolved) !== null) {
17113
+ setRepo(joinDrill(repo(), split.base, picked2));
17114
+ return;
17115
+ }
17116
+ }
17117
+ setField("baseRef");
17118
+ return;
17119
+ }
17120
+ const picked = activeList()[repoCursor()];
17121
+ if (picked) {
17122
+ setRepo(picked);
17123
+ setField("baseRef");
16389
17124
  return;
16390
17125
  }
16391
- const b = baseRef().trim() || DEFAULT_BASE_REF;
16392
- props.onSubmit({
16393
- repo: r,
16394
- baseRef: b
16395
- });
16396
- dialog.clear();
17126
+ setField("baseRef");
16397
17127
  }
16398
- function selectRepoAt(absoluteIndex) {
16399
- const list = repoFiltered();
17128
+ function selectRepoAtMouse(absoluteIndex) {
17129
+ const list = activeList();
16400
17130
  const picked = list[absoluteIndex];
16401
17131
  if (!picked)
16402
17132
  return;
17133
+ if (mode() === "browse") {
17134
+ const split = subdirSplit();
17135
+ setRepo(joinDrill(repo(), split.base, picked));
17136
+ setRepoCursor(absoluteIndex);
17137
+ return;
17138
+ }
16403
17139
  setRepo(picked);
16404
17140
  setRepoCursor(absoluteIndex);
16405
17141
  setField("baseRef");
@@ -16411,15 +17147,13 @@ function NewTaskDialogView(props) {
16411
17147
  }, {
16412
17148
  key: "up",
16413
17149
  cmd: () => {
16414
- if (field() === "repoPicker") {
16415
- const list2 = repoFiltered();
17150
+ if (field() === "repo") {
17151
+ const list2 = activeList();
16416
17152
  if (list2.length === 0)
16417
17153
  return;
16418
17154
  setRepoCursor(clampCursor(repoCursor() - 1, list2.length));
16419
17155
  return;
16420
17156
  }
16421
- if (field() === "repoCustom")
16422
- return;
16423
17157
  if (field() !== "baseRef")
16424
17158
  return;
16425
17159
  const list = branchFiltered();
@@ -16430,15 +17164,13 @@ function NewTaskDialogView(props) {
16430
17164
  }, {
16431
17165
  key: "down",
16432
17166
  cmd: () => {
16433
- if (field() === "repoPicker") {
16434
- const list2 = repoFiltered();
17167
+ if (field() === "repo") {
17168
+ const list2 = activeList();
16435
17169
  if (list2.length === 0)
16436
17170
  return;
16437
17171
  setRepoCursor(clampCursor(repoCursor() + 1, list2.length));
16438
17172
  return;
16439
17173
  }
16440
- if (field() === "repoCustom")
16441
- return;
16442
17174
  if (field() !== "baseRef")
16443
17175
  return;
16444
17176
  const list = branchFiltered();
@@ -16446,20 +17178,21 @@ function NewTaskDialogView(props) {
16446
17178
  return;
16447
17179
  setBranchCursor(clampCursor(branchCursor() + 1, list.length));
16448
17180
  }
16449
- }, {
17181
+ }]
17182
+ }));
17183
+ useBindings(() => ({
17184
+ enabled: field() === "confirm",
17185
+ bindings: [{
16450
17186
  key: "return",
16451
- cmd: () => {
16452
- if (field() === "repoPicker")
16453
- selectRepoAt(repoCursor());
16454
- }
17187
+ cmd: () => commit()
16455
17188
  }]
16456
17189
  }));
16457
17190
  return (() => {
16458
- var _el$ = createElement("box"), _el$2 = createElement("box"), _el$3 = createElement("text"), _el$5 = createElement("text"), _el$14 = createElement("box"), _el$15 = createElement("text"), _el$17 = createElement("input"), _el$20 = createElement("box"), _el$21 = createElement("text"), _el$23 = createElement("input"), _el$33 = createElement("box"), _el$34 = createElement("text");
17191
+ var _el$ = createElement("box"), _el$2 = createElement("box"), _el$3 = createElement("text"), _el$5 = createElement("text"), _el$7 = createElement("box"), _el$8 = createElement("text"), _el$0 = createElement("input"), _el$18 = createElement("box"), _el$19 = createElement("text"), _el$21 = createElement("input"), _el$31 = createElement("box"), _el$32 = createElement("text"), _el$34 = createElement("text");
16459
17192
  insertNode(_el$, _el$2);
16460
- insertNode(_el$, _el$14);
16461
- insertNode(_el$, _el$20);
16462
- insertNode(_el$, _el$33);
17193
+ insertNode(_el$, _el$7);
17194
+ insertNode(_el$, _el$18);
17195
+ insertNode(_el$, _el$31);
16463
17196
  setProp(_el$, "paddingLeft", 2);
16464
17197
  setProp(_el$, "paddingRight", 2);
16465
17198
  setProp(_el$, "gap", 1);
@@ -16470,148 +17203,153 @@ function NewTaskDialogView(props) {
16470
17203
  insertNode(_el$3, createTextNode(`New task`));
16471
17204
  insertNode(_el$5, createTextNode(`esc`));
16472
17205
  setProp(_el$5, "onMouseUp", () => props.onCancel());
17206
+ insertNode(_el$7, _el$8);
17207
+ insertNode(_el$7, _el$0);
17208
+ setProp(_el$7, "gap", 0);
17209
+ insertNode(_el$8, createTextNode(`repo`));
17210
+ setProp(_el$0, "onInput", (v) => setRepo(stripNewlines(v)));
17211
+ setProp(_el$0, "onSubmit", () => {
17212
+ if (!repo().trim())
17213
+ return;
17214
+ onRepoSubmit();
17215
+ });
16473
17216
  insert(_el$, createComponent2(Show, {
16474
17217
  get when() {
16475
- return repoOptions().length > 0;
17218
+ return memo2(() => field() === "repo")() && activeList().length > 0;
16476
17219
  },
16477
17220
  get children() {
16478
- var _el$7 = createElement("box"), _el$8 = createElement("text");
16479
- insertNode(_el$7, _el$8);
16480
- setProp(_el$7, "gap", 0);
16481
- insertNode(_el$8, createTextNode(`pick a repo`));
16482
- insert(_el$7, createComponent2(Show, {
17221
+ var _el$1 = createElement("box");
17222
+ setProp(_el$1, "gap", 0);
17223
+ setProp(_el$1, "paddingLeft", 2);
17224
+ insert(_el$1, createComponent2(Show, {
16483
17225
  get when() {
16484
- return repoWindow().start > 0;
17226
+ return activeWindow().start > 0;
16485
17227
  },
16486
17228
  get children() {
16487
- var _el$0 = createElement("text"), _el$1 = createTextNode(`\u2191 `), _el$10 = createTextNode(` more`);
16488
- insertNode(_el$0, _el$1);
16489
- insertNode(_el$0, _el$10);
16490
- setProp(_el$0, "wrapMode", "none");
16491
- insert(_el$0, () => repoWindow().start, _el$10);
16492
- effect((_$p) => setProp(_el$0, "fg", theme.textMuted, _$p));
16493
- return _el$0;
17229
+ var _el$10 = createElement("text"), _el$11 = createTextNode(`\u2191 `), _el$12 = createTextNode(` more`);
17230
+ insertNode(_el$10, _el$11);
17231
+ insertNode(_el$10, _el$12);
17232
+ setProp(_el$10, "wrapMode", "none");
17233
+ insert(_el$10, () => activeWindow().start, _el$12);
17234
+ effect((_$p) => setProp(_el$10, "fg", theme.textMuted, _$p));
17235
+ return _el$10;
16494
17236
  }
16495
17237
  }), null);
16496
- insert(_el$7, createComponent2(For, {
17238
+ insert(_el$1, createComponent2(For, {
16497
17239
  get each() {
16498
- return repoWindow().items;
17240
+ return activeWindow().items;
16499
17241
  },
16500
- children: (path8, i) => {
16501
- const absoluteIndex = () => repoWindow().start + i();
16502
- const isCursor = () => field() === "repoPicker" && absoluteIndex() === repoCursor();
16503
- const isSelected = () => repo().trim() === path8;
16504
- const isCurrentDir = () => path8 === props.defaultRepo;
17242
+ children: (name, i) => {
17243
+ const absoluteIndex = () => activeWindow().start + i();
17244
+ const isCursor = () => absoluteIndex() === repoCursor();
17245
+ const isCurrentDir = () => mode() === "saved" && name === props.defaultRepo;
17246
+ const isSelected = () => mode() === "saved" && repo().trim() === name;
17247
+ const suffix = () => mode() === "browse" ? "/" : "";
17248
+ const tag = () => isCurrentDir() ? " (current dir)" : "";
16505
17249
  return (() => {
16506
- var _el$36 = createElement("text");
16507
- setProp(_el$36, "wrapMode", "none");
16508
- setProp(_el$36, "onMouseUp", () => selectRepoAt(absoluteIndex()));
16509
- insert(_el$36, () => isCursor() ? "\u25B8 " : " ", null);
16510
- insert(_el$36, path8, null);
16511
- insert(_el$36, () => isCurrentDir() ? " (current dir)" : "", null);
17250
+ var _el$35 = createElement("text");
17251
+ setProp(_el$35, "wrapMode", "none");
17252
+ setProp(_el$35, "onMouseUp", () => selectRepoAtMouse(absoluteIndex()));
17253
+ insert(_el$35, () => isCursor() ? "\u25B8 " : " ", null);
17254
+ insert(_el$35, name, null);
17255
+ insert(_el$35, suffix, null);
17256
+ insert(_el$35, tag, null);
16512
17257
  effect((_p$) => {
16513
- var _v$10 = isCursor() ? theme.primary : isSelected() ? theme.accent : theme.textMuted, _v$11 = isCursor() ? TextAttributes18.BOLD : undefined;
16514
- _v$10 !== _p$.e && (_p$.e = setProp(_el$36, "fg", _v$10, _p$.e));
16515
- _v$11 !== _p$.t && (_p$.t = setProp(_el$36, "attributes", _v$11, _p$.t));
17258
+ var _v$12 = isCursor() ? theme.primary : isSelected() ? theme.accent : theme.textMuted, _v$13 = isCursor() ? TextAttributes19.BOLD : undefined;
17259
+ _v$12 !== _p$.e && (_p$.e = setProp(_el$35, "fg", _v$12, _p$.e));
17260
+ _v$13 !== _p$.t && (_p$.t = setProp(_el$35, "attributes", _v$13, _p$.t));
16516
17261
  return _p$;
16517
17262
  }, {
16518
17263
  e: undefined,
16519
17264
  t: undefined
16520
17265
  });
16521
- return _el$36;
17266
+ return _el$35;
16522
17267
  })();
16523
17268
  }
16524
17269
  }), null);
16525
- insert(_el$7, createComponent2(Show, {
17270
+ insert(_el$1, createComponent2(Show, {
16526
17271
  get when() {
16527
- return repoWindow().start + repoWindow().items.length < repoWindow().total;
17272
+ return activeWindow().start + activeWindow().items.length < activeWindow().total;
16528
17273
  },
16529
17274
  get children() {
16530
- var _el$11 = createElement("text"), _el$12 = createTextNode(`\u2193 `), _el$13 = createTextNode(` more`);
16531
- insertNode(_el$11, _el$12);
16532
- insertNode(_el$11, _el$13);
16533
- setProp(_el$11, "wrapMode", "none");
16534
- insert(_el$11, () => repoWindow().total - repoWindow().start - repoWindow().items.length, _el$13);
16535
- effect((_$p) => setProp(_el$11, "fg", theme.textMuted, _$p));
16536
- return _el$11;
17275
+ var _el$13 = createElement("text"), _el$14 = createTextNode(`\u2193 `), _el$15 = createTextNode(` more`);
17276
+ insertNode(_el$13, _el$14);
17277
+ insertNode(_el$13, _el$15);
17278
+ setProp(_el$13, "wrapMode", "none");
17279
+ insert(_el$13, () => activeWindow().total - activeWindow().start - activeWindow().items.length, _el$15);
17280
+ effect((_$p) => setProp(_el$13, "fg", theme.textMuted, _$p));
17281
+ return _el$13;
16537
17282
  }
16538
17283
  }), null);
16539
- effect((_$p) => setProp(_el$8, "fg", field() === "repoPicker" ? theme.accent : theme.textMuted, _$p));
16540
- return _el$7;
17284
+ return _el$1;
16541
17285
  }
16542
- }), _el$14);
16543
- insertNode(_el$14, _el$15);
16544
- insertNode(_el$14, _el$17);
16545
- setProp(_el$14, "gap", 0);
16546
- insertNode(_el$15, createTextNode(`or type a custom path`));
16547
- setProp(_el$17, "onInput", (v) => setRepo(stripNewlines(v)));
16548
- setProp(_el$17, "onSubmit", () => {
16549
- if (!repo().trim())
16550
- return;
16551
- commit();
16552
- });
17286
+ }), _el$18);
16553
17287
  insert(_el$, createComponent2(Show, {
16554
17288
  get when() {
16555
17289
  return submitError();
16556
17290
  },
16557
17291
  get children() {
16558
- var _el$18 = createElement("text"), _el$19 = createTextNode(`\u203B `);
16559
- insertNode(_el$18, _el$19);
16560
- insert(_el$18, submitError, null);
16561
- effect((_$p) => setProp(_el$18, "fg", theme.error, _$p));
16562
- return _el$18;
16563
- }
16564
- }), _el$20);
16565
- insertNode(_el$20, _el$21);
16566
- insertNode(_el$20, _el$23);
16567
- setProp(_el$20, "gap", 0);
16568
- insertNode(_el$21, createTextNode(`from branch`));
16569
- setProp(_el$23, "placeholder", DEFAULT_BASE_REF);
16570
- setProp(_el$23, "onInput", (v) => setBaseRef(stripNewlines(v)));
16571
- setProp(_el$23, "onSubmit", () => {
17292
+ var _el$16 = createElement("text"), _el$17 = createTextNode(`\u203B `);
17293
+ insertNode(_el$16, _el$17);
17294
+ insert(_el$16, submitError, null);
17295
+ effect((_$p) => setProp(_el$16, "fg", theme.error, _$p));
17296
+ return _el$16;
17297
+ }
17298
+ }), _el$18);
17299
+ insertNode(_el$18, _el$19);
17300
+ insertNode(_el$18, _el$21);
17301
+ setProp(_el$18, "gap", 0);
17302
+ insertNode(_el$19, createTextNode(`from branch`));
17303
+ setProp(_el$21, "placeholder", DEFAULT_BASE_REF);
17304
+ setProp(_el$21, "onInput", (v) => {
17305
+ setBaseRefTouched(true);
17306
+ setBaseRef(stripNewlines(v));
17307
+ });
17308
+ setProp(_el$21, "onSubmit", () => {
16572
17309
  setBaseRef(resolveBaseRef(baseRef(), branchFiltered(), branchCursor()));
16573
- commit();
17310
+ setBaseRefTouched(true);
17311
+ setField("confirm");
16574
17312
  });
16575
17313
  insert(_el$, createComponent2(Show, {
16576
17314
  get when() {
16577
17315
  return memo2(() => !!(field() === "baseRef" && branchFiltered().length === 0))() && submitError() == null;
16578
17316
  },
16579
17317
  get children() {
16580
- var _el$24 = createElement("box"), _el$25 = createElement("text");
16581
- insertNode(_el$24, _el$25);
16582
- setProp(_el$24, "gap", 0);
16583
- setProp(_el$24, "paddingLeft", 2);
16584
- setProp(_el$24, "paddingBottom", 1);
16585
- setProp(_el$25, "wrapMode", "none");
16586
- insert(_el$25, () => branches().length === 0 ? "(no local branches found \u2014 typed text will be used as ref)" : "(no match \u2014 typed text will be used as ref)");
16587
- effect((_$p) => setProp(_el$25, "fg", theme.textMuted, _$p));
16588
- return _el$24;
17318
+ var _el$22 = createElement("box"), _el$23 = createElement("text");
17319
+ insertNode(_el$22, _el$23);
17320
+ setProp(_el$22, "gap", 0);
17321
+ setProp(_el$22, "paddingLeft", 2);
17322
+ setProp(_el$22, "paddingBottom", 1);
17323
+ setProp(_el$23, "wrapMode", "none");
17324
+ insert(_el$23, () => branches().length === 0 ? "(no local branches found \u2014 typed text will be used as ref)" : "(no match \u2014 typed text will be used as ref)");
17325
+ effect((_$p) => setProp(_el$23, "fg", theme.textMuted, _$p));
17326
+ return _el$22;
16589
17327
  }
16590
- }), _el$33);
17328
+ }), _el$31);
16591
17329
  insert(_el$, createComponent2(Show, {
16592
17330
  get when() {
16593
17331
  return memo2(() => field() === "baseRef")() && branchFiltered().length > 0;
16594
17332
  },
16595
17333
  get children() {
16596
- var _el$26 = createElement("box");
16597
- setProp(_el$26, "gap", 0);
16598
- setProp(_el$26, "paddingLeft", 2);
16599
- setProp(_el$26, "paddingBottom", 1);
16600
- insert(_el$26, createComponent2(Show, {
17334
+ var _el$24 = createElement("box");
17335
+ setProp(_el$24, "gap", 0);
17336
+ setProp(_el$24, "paddingLeft", 2);
17337
+ setProp(_el$24, "paddingBottom", 1);
17338
+ insert(_el$24, createComponent2(Show, {
16601
17339
  get when() {
16602
17340
  return branchWindow().start > 0;
16603
17341
  },
16604
17342
  get children() {
16605
- var _el$27 = createElement("text"), _el$28 = createTextNode(`\u2191 `), _el$29 = createTextNode(` more`);
16606
- insertNode(_el$27, _el$28);
16607
- insertNode(_el$27, _el$29);
16608
- setProp(_el$27, "wrapMode", "none");
16609
- insert(_el$27, () => branchWindow().start, _el$29);
16610
- effect((_$p) => setProp(_el$27, "fg", theme.textMuted, _$p));
16611
- return _el$27;
17343
+ var _el$25 = createElement("text"), _el$26 = createTextNode(`\u2191 `), _el$27 = createTextNode(` more`);
17344
+ insertNode(_el$25, _el$26);
17345
+ insertNode(_el$25, _el$27);
17346
+ setProp(_el$25, "wrapMode", "none");
17347
+ insert(_el$25, () => branchWindow().start, _el$27);
17348
+ effect((_$p) => setProp(_el$25, "fg", theme.textMuted, _$p));
17349
+ return _el$25;
16612
17350
  }
16613
17351
  }), null);
16614
- insert(_el$26, createComponent2(For, {
17352
+ insert(_el$24, createComponent2(For, {
16615
17353
  get each() {
16616
17354
  return branchWindow().items;
16617
17355
  },
@@ -16620,61 +17358,69 @@ function NewTaskDialogView(props) {
16620
17358
  const isCursor = () => absoluteIndex() === branchCursor();
16621
17359
  const isSelected = () => baseRef().trim() === name;
16622
17360
  return (() => {
16623
- var _el$37 = createElement("text");
16624
- setProp(_el$37, "wrapMode", "none");
16625
- setProp(_el$37, "onMouseUp", () => {
17361
+ var _el$36 = createElement("text");
17362
+ setProp(_el$36, "wrapMode", "none");
17363
+ setProp(_el$36, "onMouseUp", () => {
16626
17364
  setBaseRef(name);
17365
+ setBaseRefTouched(true);
16627
17366
  setBranchCursor(absoluteIndex());
16628
- commit();
17367
+ setField("confirm");
16629
17368
  });
16630
- insert(_el$37, () => isCursor() ? "\u25B8 " : " ", null);
16631
- insert(_el$37, name, null);
17369
+ insert(_el$36, () => isCursor() ? "\u25B8 " : " ", null);
17370
+ insert(_el$36, name, null);
16632
17371
  effect((_p$) => {
16633
- var _v$12 = isCursor() ? theme.primary : isSelected() ? theme.accent : theme.textMuted, _v$13 = isCursor() ? TextAttributes18.BOLD : undefined;
16634
- _v$12 !== _p$.e && (_p$.e = setProp(_el$37, "fg", _v$12, _p$.e));
16635
- _v$13 !== _p$.t && (_p$.t = setProp(_el$37, "attributes", _v$13, _p$.t));
17372
+ var _v$14 = isCursor() ? theme.primary : isSelected() ? theme.accent : theme.textMuted, _v$15 = isCursor() ? TextAttributes19.BOLD : undefined;
17373
+ _v$14 !== _p$.e && (_p$.e = setProp(_el$36, "fg", _v$14, _p$.e));
17374
+ _v$15 !== _p$.t && (_p$.t = setProp(_el$36, "attributes", _v$15, _p$.t));
16636
17375
  return _p$;
16637
17376
  }, {
16638
17377
  e: undefined,
16639
17378
  t: undefined
16640
17379
  });
16641
- return _el$37;
17380
+ return _el$36;
16642
17381
  })();
16643
17382
  }
16644
17383
  }), null);
16645
- insert(_el$26, createComponent2(Show, {
17384
+ insert(_el$24, createComponent2(Show, {
16646
17385
  get when() {
16647
17386
  return branchWindow().start + branchWindow().items.length < branchWindow().total;
16648
17387
  },
16649
17388
  get children() {
16650
- var _el$30 = createElement("text"), _el$31 = createTextNode(`\u2193 `), _el$32 = createTextNode(` more`);
16651
- insertNode(_el$30, _el$31);
16652
- insertNode(_el$30, _el$32);
16653
- setProp(_el$30, "wrapMode", "none");
16654
- insert(_el$30, () => branchWindow().total - branchWindow().start - branchWindow().items.length, _el$32);
16655
- effect((_$p) => setProp(_el$30, "fg", theme.textMuted, _$p));
16656
- return _el$30;
17389
+ var _el$28 = createElement("text"), _el$29 = createTextNode(`\u2193 `), _el$30 = createTextNode(` more`);
17390
+ insertNode(_el$28, _el$29);
17391
+ insertNode(_el$28, _el$30);
17392
+ setProp(_el$28, "wrapMode", "none");
17393
+ insert(_el$28, () => branchWindow().total - branchWindow().start - branchWindow().items.length, _el$30);
17394
+ effect((_$p) => setProp(_el$28, "fg", theme.textMuted, _$p));
17395
+ return _el$28;
16657
17396
  }
16658
17397
  }), null);
16659
- return _el$26;
17398
+ return _el$24;
16660
17399
  }
16661
- }), _el$33);
16662
- insertNode(_el$33, _el$34);
16663
- setProp(_el$33, "paddingBottom", 1);
16664
- insertNode(_el$34, createTextNode(`\u2191\u2193 pick \xB7 enter select \xB7 tab next field \xB7 esc cancel`));
17400
+ }), _el$31);
17401
+ insertNode(_el$31, _el$32);
17402
+ insertNode(_el$31, _el$34);
17403
+ setProp(_el$31, "flexDirection", "row");
17404
+ setProp(_el$31, "justifyContent", "space-between");
17405
+ setProp(_el$31, "paddingBottom", 1);
17406
+ insertNode(_el$32, createTextNode(`\u2191\u2193 pick \xB7 enter select \xB7 tab next field \xB7 esc cancel`));
17407
+ setProp(_el$34, "onMouseUp", () => commit());
17408
+ insert(_el$34, () => field() === "confirm" ? "\u25B8 [ Create ]" : " [ Create ]");
16665
17409
  effect((_p$) => {
16666
- var _v$ = TextAttributes18.BOLD, _v$2 = theme.text, _v$3 = theme.textMuted, _v$4 = field() === "repoCustom" ? theme.accent : theme.textMuted, _v$5 = repo(), _v$6 = props.defaultRepo, _v$7 = field() === "repoCustom", _v$8 = field() === "baseRef" ? theme.accent : theme.textMuted, _v$9 = baseRef(), _v$0 = field() === "baseRef", _v$1 = theme.textMuted;
17410
+ var _v$ = TextAttributes19.BOLD, _v$2 = theme.text, _v$3 = theme.textMuted, _v$4 = field() === "repo" ? theme.accent : theme.textMuted, _v$5 = repo(), _v$6 = props.defaultRepo, _v$7 = field() === "repo", _v$8 = field() === "baseRef" ? theme.accent : theme.textMuted, _v$9 = baseRef(), _v$0 = field() === "baseRef", _v$1 = theme.textMuted, _v$10 = field() === "confirm" ? theme.primary : theme.text, _v$11 = field() === "confirm" ? TextAttributes19.BOLD : undefined;
16667
17411
  _v$ !== _p$.e && (_p$.e = setProp(_el$3, "attributes", _v$, _p$.e));
16668
17412
  _v$2 !== _p$.t && (_p$.t = setProp(_el$3, "fg", _v$2, _p$.t));
16669
17413
  _v$3 !== _p$.a && (_p$.a = setProp(_el$5, "fg", _v$3, _p$.a));
16670
- _v$4 !== _p$.o && (_p$.o = setProp(_el$15, "fg", _v$4, _p$.o));
16671
- _v$5 !== _p$.i && (_p$.i = setProp(_el$17, "value", _v$5, _p$.i));
16672
- _v$6 !== _p$.n && (_p$.n = setProp(_el$17, "placeholder", _v$6, _p$.n));
16673
- _v$7 !== _p$.s && (_p$.s = setProp(_el$17, "focused", _v$7, _p$.s));
16674
- _v$8 !== _p$.h && (_p$.h = setProp(_el$21, "fg", _v$8, _p$.h));
16675
- _v$9 !== _p$.r && (_p$.r = setProp(_el$23, "value", _v$9, _p$.r));
16676
- _v$0 !== _p$.d && (_p$.d = setProp(_el$23, "focused", _v$0, _p$.d));
16677
- _v$1 !== _p$.l && (_p$.l = setProp(_el$34, "fg", _v$1, _p$.l));
17414
+ _v$4 !== _p$.o && (_p$.o = setProp(_el$8, "fg", _v$4, _p$.o));
17415
+ _v$5 !== _p$.i && (_p$.i = setProp(_el$0, "value", _v$5, _p$.i));
17416
+ _v$6 !== _p$.n && (_p$.n = setProp(_el$0, "placeholder", _v$6, _p$.n));
17417
+ _v$7 !== _p$.s && (_p$.s = setProp(_el$0, "focused", _v$7, _p$.s));
17418
+ _v$8 !== _p$.h && (_p$.h = setProp(_el$19, "fg", _v$8, _p$.h));
17419
+ _v$9 !== _p$.r && (_p$.r = setProp(_el$21, "value", _v$9, _p$.r));
17420
+ _v$0 !== _p$.d && (_p$.d = setProp(_el$21, "focused", _v$0, _p$.d));
17421
+ _v$1 !== _p$.l && (_p$.l = setProp(_el$32, "fg", _v$1, _p$.l));
17422
+ _v$10 !== _p$.u && (_p$.u = setProp(_el$34, "fg", _v$10, _p$.u));
17423
+ _v$11 !== _p$.c && (_p$.c = setProp(_el$34, "attributes", _v$11, _p$.c));
16678
17424
  return _p$;
16679
17425
  }, {
16680
17426
  e: undefined,
@@ -16687,7 +17433,9 @@ function NewTaskDialogView(props) {
16687
17433
  h: undefined,
16688
17434
  r: undefined,
16689
17435
  d: undefined,
16690
- l: undefined
17436
+ l: undefined,
17437
+ u: undefined,
17438
+ c: undefined
16691
17439
  });
16692
17440
  return _el$;
16693
17441
  })();
@@ -16731,7 +17479,7 @@ var init_new_task_dialog = __esm(() => {
16731
17479
  });
16732
17480
 
16733
17481
  // src/tui/component/rename-task-dialog/dialog.tsx
16734
- import { TextAttributes as TextAttributes19 } from "@opentui/core";
17482
+ import { TextAttributes as TextAttributes20 } from "@opentui/core";
16735
17483
  function RenameTaskDialogView(props) {
16736
17484
  const dialog = useDialog();
16737
17485
  const {
@@ -16771,7 +17519,7 @@ function RenameTaskDialogView(props) {
16771
17519
  setProp(_el$0, "paddingBottom", 1);
16772
17520
  insertNode(_el$1, createTextNode(`enter rename \xB7 esc cancel`));
16773
17521
  effect((_p$) => {
16774
- var _v$ = TextAttributes19.BOLD, _v$2 = theme.text, _v$3 = theme.textMuted, _v$4 = theme.accent, _v$5 = title(), _v$6 = props.currentTitle, _v$7 = theme.textMuted;
17522
+ var _v$ = TextAttributes20.BOLD, _v$2 = theme.text, _v$3 = theme.textMuted, _v$4 = theme.accent, _v$5 = title(), _v$6 = props.currentTitle, _v$7 = theme.textMuted;
16775
17523
  _v$ !== _p$.e && (_p$.e = setProp(_el$3, "attributes", _v$, _p$.e));
16776
17524
  _v$2 !== _p$.t && (_p$.t = setProp(_el$3, "fg", _v$2, _p$.t));
16777
17525
  _v$3 !== _p$.a && (_p$.a = setProp(_el$4, "fg", _v$3, _p$.a));
@@ -16832,11 +17580,17 @@ var init_rename_task_dialog = __esm(() => {
16832
17580
  function useTaskActions(deps) {
16833
17581
  const { orchestrator, dialog, kv, selectedId, setSelectedId, setFocusedPane, savedRepos } = deps;
16834
17582
  async function openNewTaskFlow() {
16835
- const lastRepo = (() => {
17583
+ const defaultRepo = (() => {
17584
+ const sid = selectedId();
17585
+ if (sid) {
17586
+ const task = orchestrator.getTask(sid);
17587
+ if (task?.repo?.trim())
17588
+ return task.repo;
17589
+ }
16836
17590
  const raw = kv.get("lastNewTaskRepo");
16837
17591
  return typeof raw === "string" && raw.trim() ? raw : process.cwd();
16838
17592
  })();
16839
- const result = await NewTaskDialog.show(dialog, lastRepo, savedRepos());
17593
+ const result = await NewTaskDialog.show(dialog, defaultRepo, savedRepos());
16840
17594
  if (!result)
16841
17595
  return;
16842
17596
  try {
@@ -17094,7 +17848,7 @@ var init_use_workspace_tabs = __esm(() => {
17094
17848
  });
17095
17849
 
17096
17850
  // src/tui/component/resume-dialog.tsx
17097
- import { TextAttributes as TextAttributes20 } from "@opentui/core";
17851
+ import { TextAttributes as TextAttributes21 } from "@opentui/core";
17098
17852
  function ResumeDialog(props) {
17099
17853
  const dialog = useDialog();
17100
17854
  const {
@@ -17241,7 +17995,7 @@ function ResumeDialog(props) {
17241
17995
  setProp(_el$9, "paddingBottom", 1);
17242
17996
  insertNode(_el$0, createTextNode(`j/k or \u2191\u2193 navigate \u2022 enter resume \u2022 esc dismiss`));
17243
17997
  effect((_p$) => {
17244
- var _v$ = TextAttributes20.BOLD, _v$2 = theme.text, _v$3 = theme.textMuted, _v$4 = theme.textMuted;
17998
+ var _v$ = TextAttributes21.BOLD, _v$2 = theme.text, _v$3 = theme.textMuted, _v$4 = theme.textMuted;
17245
17999
  _v$ !== _p$.e && (_p$.e = setProp(_el$3, "attributes", _v$, _p$.e));
17246
18000
  _v$2 !== _p$.t && (_p$.t = setProp(_el$3, "fg", _v$2, _p$.t));
17247
18001
  _v$3 !== _p$.a && (_p$.a = setProp(_el$5, "fg", _v$3, _p$.a));
@@ -17379,7 +18133,7 @@ var init_history2 = __esm(() => {
17379
18133
  });
17380
18134
 
17381
18135
  // src/tui/panes/chat/composer/image-paste.ts
17382
- import { randomUUID } from "crypto";
18136
+ import { randomUUID as randomUUID2 } from "crypto";
17383
18137
  import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync4 } from "fs";
17384
18138
  import { join as join13 } from "path";
17385
18139
  function pastedImagesDir() {
@@ -17463,7 +18217,7 @@ function mimeTypeToExt(mimeType) {
17463
18217
  return ".png";
17464
18218
  }
17465
18219
  function mintPath(ext) {
17466
- return join13(pastedImagesDir(), `${randomUUID()}${ext}`);
18220
+ return join13(pastedImagesDir(), `${randomUUID2()}${ext}`);
17467
18221
  }
17468
18222
  var IMAGE_TOKEN_RE;
17469
18223
  var init_image_paste = __esm(() => {
@@ -17566,7 +18320,7 @@ var init_mention = __esm(() => {
17566
18320
  });
17567
18321
 
17568
18322
  // src/tui/panes/chat/Composer.tsx
17569
- import { TextAttributes as TextAttributes21 } from "@opentui/core";
18323
+ import { TextAttributes as TextAttributes22 } from "@opentui/core";
17570
18324
  function resolvePlaceholder(opts) {
17571
18325
  if (!opts.hasTask)
17572
18326
  return opts.noTaskMessage ?? "(no task \u2014 press n to create)";
@@ -18065,9 +18819,9 @@ function Composer(props) {
18065
18819
  return theme.border;
18066
18820
  };
18067
18821
  return (() => {
18068
- var _el$ = createElement("box"), _el$14 = createElement("box"), _el$15 = createElement("box"), _el$16 = createElement("box"), _el$17 = createElement("text"), _el$18 = createElement("box"), _el$25 = createElement("box"), _el$26 = createElement("box");
18822
+ var _el$ = createElement("box"), _el$14 = createElement("box"), _el$15 = createElement("box"), _el$21 = createElement("box"), _el$22 = createElement("text"), _el$23 = createElement("box"), _el$30 = createElement("box"), _el$31 = createElement("box");
18069
18823
  insertNode(_el$, _el$14);
18070
- insertNode(_el$, _el$25);
18824
+ insertNode(_el$, _el$30);
18071
18825
  setProp(_el$, "flexShrink", 0);
18072
18826
  setProp(_el$, "flexDirection", "column");
18073
18827
  setProp(_el$, "paddingTop", 1);
@@ -18114,35 +18868,35 @@ function Composer(props) {
18114
18868
  return idx >= 0 ? match.displayPath.slice(0, idx) : "";
18115
18869
  };
18116
18870
  return (() => {
18117
- var _el$27 = createElement("box"), _el$28 = createElement("text");
18118
- insertNode(_el$27, _el$28);
18119
- setProp(_el$27, "flexDirection", "row");
18120
- setProp(_el$27, "gap", 2);
18121
- setProp(_el$28, "wrapMode", "none");
18122
- insert(_el$28, () => active() ? "\u25B8 " : " ", null);
18123
- insert(_el$28, filename, null);
18124
- insert(_el$27, createComponent2(Show, {
18871
+ var _el$32 = createElement("box"), _el$33 = createElement("text");
18872
+ insertNode(_el$32, _el$33);
18873
+ setProp(_el$32, "flexDirection", "row");
18874
+ setProp(_el$32, "gap", 2);
18875
+ setProp(_el$33, "wrapMode", "none");
18876
+ insert(_el$33, () => active() ? "\u25B8 " : " ", null);
18877
+ insert(_el$33, filename, null);
18878
+ insert(_el$32, createComponent2(Show, {
18125
18879
  get when() {
18126
18880
  return directory().length > 0;
18127
18881
  },
18128
18882
  get children() {
18129
- var _el$29 = createElement("text");
18130
- setProp(_el$29, "wrapMode", "none");
18131
- insert(_el$29, directory);
18132
- effect((_$p) => setProp(_el$29, "fg", theme.textMuted, _$p));
18133
- return _el$29;
18883
+ var _el$34 = createElement("text");
18884
+ setProp(_el$34, "wrapMode", "none");
18885
+ insert(_el$34, directory);
18886
+ effect((_$p) => setProp(_el$34, "fg", theme.textMuted, _$p));
18887
+ return _el$34;
18134
18888
  }
18135
18889
  }), null);
18136
18890
  effect((_p$) => {
18137
- var _v$20 = active() ? theme.primary : theme.text, _v$21 = active() ? TextAttributes21.BOLD : undefined;
18138
- _v$20 !== _p$.e && (_p$.e = setProp(_el$28, "fg", _v$20, _p$.e));
18139
- _v$21 !== _p$.t && (_p$.t = setProp(_el$28, "attributes", _v$21, _p$.t));
18891
+ var _v$23 = active() ? theme.primary : theme.text, _v$24 = active() ? TextAttributes22.BOLD : undefined;
18892
+ _v$23 !== _p$.e && (_p$.e = setProp(_el$33, "fg", _v$23, _p$.e));
18893
+ _v$24 !== _p$.t && (_p$.t = setProp(_el$33, "attributes", _v$24, _p$.t));
18140
18894
  return _p$;
18141
18895
  }, {
18142
18896
  e: undefined,
18143
18897
  t: undefined
18144
18898
  });
18145
- return _el$27;
18899
+ return _el$32;
18146
18900
  })();
18147
18901
  }
18148
18902
  }), null);
@@ -18209,47 +18963,47 @@ function Composer(props) {
18209
18963
  const absoluteIndex = () => slashWindow().start + i();
18210
18964
  const active = () => absoluteIndex() === slashCursor();
18211
18965
  return (() => {
18212
- var _el$30 = createElement("box"), _el$31 = createElement("text");
18213
- insertNode(_el$30, _el$31);
18214
- setProp(_el$30, "flexDirection", "row");
18215
- setProp(_el$30, "gap", 2);
18216
- setProp(_el$31, "wrapMode", "none");
18217
- insert(_el$31, () => active() ? "\u25B8 " : " ", null);
18218
- insert(_el$31, () => entry.display, null);
18219
- insert(_el$30, createComponent2(Show, {
18966
+ var _el$35 = createElement("box"), _el$36 = createElement("text");
18967
+ insertNode(_el$35, _el$36);
18968
+ setProp(_el$35, "flexDirection", "row");
18969
+ setProp(_el$35, "gap", 2);
18970
+ setProp(_el$36, "wrapMode", "none");
18971
+ insert(_el$36, () => active() ? "\u25B8 " : " ", null);
18972
+ insert(_el$36, () => entry.display, null);
18973
+ insert(_el$35, createComponent2(Show, {
18220
18974
  get when() {
18221
18975
  return entry.source === "user";
18222
18976
  },
18223
18977
  get children() {
18224
- var _el$32 = createElement("text");
18225
- insertNode(_el$32, createTextNode(`user`));
18226
- setProp(_el$32, "wrapMode", "none");
18227
- effect((_$p) => setProp(_el$32, "fg", theme.textMuted, _$p));
18228
- return _el$32;
18978
+ var _el$37 = createElement("text");
18979
+ insertNode(_el$37, createTextNode(`user`));
18980
+ setProp(_el$37, "wrapMode", "none");
18981
+ effect((_$p) => setProp(_el$37, "fg", theme.textMuted, _$p));
18982
+ return _el$37;
18229
18983
  }
18230
18984
  }), null);
18231
- insert(_el$30, createComponent2(Show, {
18985
+ insert(_el$35, createComponent2(Show, {
18232
18986
  get when() {
18233
18987
  return entry.description;
18234
18988
  },
18235
18989
  get children() {
18236
- var _el$34 = createElement("text");
18237
- setProp(_el$34, "wrapMode", "none");
18238
- insert(_el$34, () => entry.description);
18239
- effect((_$p) => setProp(_el$34, "fg", theme.textMuted, _$p));
18240
- return _el$34;
18990
+ var _el$39 = createElement("text");
18991
+ setProp(_el$39, "wrapMode", "none");
18992
+ insert(_el$39, () => entry.description);
18993
+ effect((_$p) => setProp(_el$39, "fg", theme.textMuted, _$p));
18994
+ return _el$39;
18241
18995
  }
18242
18996
  }), null);
18243
18997
  effect((_p$) => {
18244
- var _v$22 = active() ? theme.primary : theme.text, _v$23 = active() ? TextAttributes21.BOLD : undefined;
18245
- _v$22 !== _p$.e && (_p$.e = setProp(_el$31, "fg", _v$22, _p$.e));
18246
- _v$23 !== _p$.t && (_p$.t = setProp(_el$31, "attributes", _v$23, _p$.t));
18998
+ var _v$25 = active() ? theme.primary : theme.text, _v$26 = active() ? TextAttributes22.BOLD : undefined;
18999
+ _v$25 !== _p$.e && (_p$.e = setProp(_el$36, "fg", _v$25, _p$.e));
19000
+ _v$26 !== _p$.t && (_p$.t = setProp(_el$36, "attributes", _v$26, _p$.t));
18247
19001
  return _p$;
18248
19002
  }, {
18249
19003
  e: undefined,
18250
19004
  t: undefined
18251
19005
  });
18252
- return _el$30;
19006
+ return _el$35;
18253
19007
  })();
18254
19008
  }
18255
19009
  }), null);
@@ -18283,37 +19037,125 @@ function Composer(props) {
18283
19037
  }), _el$14);
18284
19038
  insertNode(_el$14, _el$15);
18285
19039
  setProp(_el$14, "border", ["left"]);
18286
- insertNode(_el$15, _el$16);
19040
+ insertNode(_el$15, _el$21);
18287
19041
  setProp(_el$15, "paddingLeft", 2);
18288
19042
  setProp(_el$15, "paddingRight", 2);
18289
19043
  setProp(_el$15, "paddingTop", 1);
18290
19044
  setProp(_el$15, "paddingBottom", 0);
18291
19045
  setProp(_el$15, "flexDirection", "column");
18292
19046
  setProp(_el$15, "flexGrow", 1);
18293
- insertNode(_el$16, _el$17);
18294
- insertNode(_el$16, _el$18);
18295
- setProp(_el$16, "flexDirection", "row");
18296
- setProp(_el$16, "gap", 1);
18297
- setProp(_el$16, "alignItems", "flex-start");
18298
- insert(_el$17, () => props.isStreaming ? "\u2026" : ">");
18299
- setProp(_el$18, "flexGrow", 1);
18300
- setProp(_el$18, "flexShrink", 1);
18301
- setProp(_el$18, "maxHeight", 8);
18302
- setProp(_el$18, "minHeight", 1);
18303
- insert(_el$18, createComponent2(Show, {
19047
+ insert(_el$15, createComponent2(Show, {
19048
+ get when() {
19049
+ return (props.queue?.() ?? []).length > 0;
19050
+ },
19051
+ get children() {
19052
+ var _el$16 = createElement("box");
19053
+ setProp(_el$16, "flexDirection", "column");
19054
+ setProp(_el$16, "paddingBottom", 1);
19055
+ insert(_el$16, createComponent2(For, {
19056
+ get each() {
19057
+ return (props.queue?.() ?? []).slice(0, QUEUE_VISIBLE_CAP);
19058
+ },
19059
+ children: (entry, idx) => (() => {
19060
+ var _el$40 = createElement("box"), _el$41 = createElement("text"), _el$43 = createElement("text"), _el$44 = createTextNode(`queued`), _el$45 = createTextNode(`:`), _el$46 = createElement("box"), _el$47 = createElement("text"), _el$48 = createElement("text"), _el$50 = createElement("text");
19061
+ insertNode(_el$40, _el$41);
19062
+ insertNode(_el$40, _el$43);
19063
+ insertNode(_el$40, _el$46);
19064
+ insertNode(_el$40, _el$48);
19065
+ insertNode(_el$40, _el$50);
19066
+ setProp(_el$40, "flexDirection", "row");
19067
+ setProp(_el$40, "gap", 1);
19068
+ setProp(_el$40, "alignItems", "flex-start");
19069
+ insertNode(_el$41, createTextNode(`+`));
19070
+ insertNode(_el$43, _el$44);
19071
+ insertNode(_el$43, _el$45);
19072
+ setProp(_el$43, "wrapMode", "none");
19073
+ insert(_el$43, () => idx() === 0 ? " (next)" : "", _el$45);
19074
+ insertNode(_el$46, _el$47);
19075
+ setProp(_el$46, "flexGrow", 1);
19076
+ insert(_el$47, () => entry.text);
19077
+ insertNode(_el$48, createTextNode(`[\u25B6]`));
19078
+ setProp(_el$48, "onMouseUp", () => props.onSendQueuedNow?.(entry.id));
19079
+ insertNode(_el$50, createTextNode(`[x]`));
19080
+ setProp(_el$50, "onMouseUp", () => props.onCancelQueued?.(entry.id));
19081
+ effect((_p$) => {
19082
+ var _v$27 = theme.textMuted, _v$28 = TextAttributes22.BOLD, _v$29 = theme.textMuted, _v$30 = theme.text, _v$31 = theme.primary, _v$32 = TextAttributes22.BOLD, _v$33 = theme.error, _v$34 = TextAttributes22.BOLD;
19083
+ _v$27 !== _p$.e && (_p$.e = setProp(_el$41, "fg", _v$27, _p$.e));
19084
+ _v$28 !== _p$.t && (_p$.t = setProp(_el$41, "attributes", _v$28, _p$.t));
19085
+ _v$29 !== _p$.a && (_p$.a = setProp(_el$43, "fg", _v$29, _p$.a));
19086
+ _v$30 !== _p$.o && (_p$.o = setProp(_el$47, "fg", _v$30, _p$.o));
19087
+ _v$31 !== _p$.i && (_p$.i = setProp(_el$48, "fg", _v$31, _p$.i));
19088
+ _v$32 !== _p$.n && (_p$.n = setProp(_el$48, "attributes", _v$32, _p$.n));
19089
+ _v$33 !== _p$.s && (_p$.s = setProp(_el$50, "fg", _v$33, _p$.s));
19090
+ _v$34 !== _p$.h && (_p$.h = setProp(_el$50, "attributes", _v$34, _p$.h));
19091
+ return _p$;
19092
+ }, {
19093
+ e: undefined,
19094
+ t: undefined,
19095
+ a: undefined,
19096
+ o: undefined,
19097
+ i: undefined,
19098
+ n: undefined,
19099
+ s: undefined,
19100
+ h: undefined
19101
+ });
19102
+ return _el$40;
19103
+ })()
19104
+ }), null);
19105
+ insert(_el$16, createComponent2(Show, {
19106
+ get when() {
19107
+ return (props.queue?.() ?? []).length > QUEUE_VISIBLE_CAP;
19108
+ },
19109
+ get children() {
19110
+ var _el$17 = createElement("box"), _el$18 = createElement("text"), _el$20 = createElement("text");
19111
+ insertNode(_el$17, _el$18);
19112
+ insertNode(_el$17, _el$20);
19113
+ setProp(_el$17, "flexDirection", "row");
19114
+ setProp(_el$17, "gap", 1);
19115
+ setProp(_el$17, "alignItems", "flex-start");
19116
+ insertNode(_el$18, createTextNode(`+`));
19117
+ insert(_el$20, () => `\u2026 ${(props.queue?.() ?? []).length - QUEUE_VISIBLE_CAP} more queued`);
19118
+ effect((_p$) => {
19119
+ var _v$7 = theme.textMuted, _v$8 = TextAttributes22.BOLD, _v$9 = theme.textMuted;
19120
+ _v$7 !== _p$.e && (_p$.e = setProp(_el$18, "fg", _v$7, _p$.e));
19121
+ _v$8 !== _p$.t && (_p$.t = setProp(_el$18, "attributes", _v$8, _p$.t));
19122
+ _v$9 !== _p$.a && (_p$.a = setProp(_el$20, "fg", _v$9, _p$.a));
19123
+ return _p$;
19124
+ }, {
19125
+ e: undefined,
19126
+ t: undefined,
19127
+ a: undefined
19128
+ });
19129
+ return _el$17;
19130
+ }
19131
+ }), null);
19132
+ return _el$16;
19133
+ }
19134
+ }), _el$21);
19135
+ insertNode(_el$21, _el$22);
19136
+ insertNode(_el$21, _el$23);
19137
+ setProp(_el$21, "flexDirection", "row");
19138
+ setProp(_el$21, "gap", 1);
19139
+ setProp(_el$21, "alignItems", "flex-start");
19140
+ insert(_el$22, () => props.isStreaming ? "\u2026" : ">");
19141
+ setProp(_el$23, "flexGrow", 1);
19142
+ setProp(_el$23, "flexShrink", 1);
19143
+ setProp(_el$23, "maxHeight", 8);
19144
+ setProp(_el$23, "minHeight", 1);
19145
+ insert(_el$23, createComponent2(Show, {
18304
19146
  get when() {
18305
19147
  return props.hasTask;
18306
19148
  },
18307
19149
  get fallback() {
18308
19150
  return (() => {
18309
- var _el$35 = createElement("text");
18310
- insert(_el$35, () => props.noTaskMessage ?? "(no task \u2014 press n to create)");
18311
- effect((_$p) => setProp(_el$35, "fg", theme.textMuted, _$p));
18312
- return _el$35;
19151
+ var _el$52 = createElement("text");
19152
+ insert(_el$52, () => props.noTaskMessage ?? "(no task \u2014 press n to create)");
19153
+ effect((_$p) => setProp(_el$52, "fg", theme.textMuted, _$p));
19154
+ return _el$52;
18313
19155
  })();
18314
19156
  },
18315
19157
  get children() {
18316
- var _el$19 = createElement("textarea");
19158
+ var _el$24 = createElement("textarea");
18317
19159
  use((r) => {
18318
19160
  textareaRef = r;
18319
19161
  if (props.draft)
@@ -18321,23 +19163,23 @@ function Composer(props) {
18321
19163
  r.onPaste = handlePaste;
18322
19164
  if (props.focused?.())
18323
19165
  r.focus();
18324
- }, _el$19);
18325
- setProp(_el$19, "wrapMode", "word");
18326
- setProp(_el$19, "keyBindings", composerKeyBindings);
18327
- setProp(_el$19, "onContentChange", handleContentChange);
18328
- setProp(_el$19, "onKeyDown", handleKeyDown);
18329
- setProp(_el$19, "onSubmit", () => handleSubmit("auto"));
19166
+ }, _el$24);
19167
+ setProp(_el$24, "wrapMode", "word");
19168
+ setProp(_el$24, "keyBindings", composerKeyBindings);
19169
+ setProp(_el$24, "onContentChange", handleContentChange);
19170
+ setProp(_el$24, "onKeyDown", handleKeyDown);
19171
+ setProp(_el$24, "onSubmit", () => handleSubmit("auto"));
18330
19172
  effect((_p$) => {
18331
- var _v$7 = resolvePlaceholder({
19173
+ var _v$0 = resolvePlaceholder({
18332
19174
  isStreaming: props.isStreaming,
18333
19175
  hasTask: props.hasTask,
18334
19176
  noTaskMessage: props.noTaskMessage
18335
- }), _v$8 = theme.textMuted, _v$9 = theme.text, _v$0 = theme.backgroundElement, _v$1 = theme.backgroundElement;
18336
- _v$7 !== _p$.e && (_p$.e = setProp(_el$19, "placeholder", _v$7, _p$.e));
18337
- _v$8 !== _p$.t && (_p$.t = setProp(_el$19, "placeholderColor", _v$8, _p$.t));
18338
- _v$9 !== _p$.a && (_p$.a = setProp(_el$19, "textColor", _v$9, _p$.a));
18339
- _v$0 !== _p$.o && (_p$.o = setProp(_el$19, "backgroundColor", _v$0, _p$.o));
18340
- _v$1 !== _p$.i && (_p$.i = setProp(_el$19, "focusedBackgroundColor", _v$1, _p$.i));
19177
+ }), _v$1 = theme.textMuted, _v$10 = theme.text, _v$11 = theme.backgroundElement, _v$12 = theme.backgroundElement;
19178
+ _v$0 !== _p$.e && (_p$.e = setProp(_el$24, "placeholder", _v$0, _p$.e));
19179
+ _v$1 !== _p$.t && (_p$.t = setProp(_el$24, "placeholderColor", _v$1, _p$.t));
19180
+ _v$10 !== _p$.a && (_p$.a = setProp(_el$24, "textColor", _v$10, _p$.a));
19181
+ _v$11 !== _p$.o && (_p$.o = setProp(_el$24, "backgroundColor", _v$11, _p$.o));
19182
+ _v$12 !== _p$.i && (_p$.i = setProp(_el$24, "focusedBackgroundColor", _v$12, _p$.i));
18341
19183
  return _p$;
18342
19184
  }, {
18343
19185
  e: undefined,
@@ -18346,7 +19188,7 @@ function Composer(props) {
18346
19188
  o: undefined,
18347
19189
  i: undefined
18348
19190
  });
18349
- return _el$19;
19191
+ return _el$24;
18350
19192
  }
18351
19193
  }));
18352
19194
  insert(_el$15, createComponent2(Show, {
@@ -18354,74 +19196,74 @@ function Composer(props) {
18354
19196
  return props.hasTask;
18355
19197
  },
18356
19198
  get children() {
18357
- var _el$20 = createElement("box"), _el$21 = createElement("text"), _el$22 = createElement("box"), _el$23 = createElement("box"), _el$24 = createElement("text");
18358
- insertNode(_el$20, _el$21);
18359
- insertNode(_el$20, _el$22);
18360
- setProp(_el$20, "flexDirection", "row");
18361
- setProp(_el$20, "justifyContent", "space-between");
18362
- setProp(_el$20, "paddingTop", 1);
18363
- setProp(_el$20, "flexShrink", 0);
18364
- setProp(_el$21, "wrapMode", "none");
18365
- insert(_el$21, footerHint);
18366
- insertNode(_el$22, _el$23);
18367
- setProp(_el$22, "flexDirection", "row");
18368
- setProp(_el$22, "gap", 2);
18369
- setProp(_el$22, "flexShrink", 0);
18370
- insert(_el$22, createComponent2(Show, {
19199
+ var _el$25 = createElement("box"), _el$26 = createElement("text"), _el$27 = createElement("box"), _el$28 = createElement("box"), _el$29 = createElement("text");
19200
+ insertNode(_el$25, _el$26);
19201
+ insertNode(_el$25, _el$27);
19202
+ setProp(_el$25, "flexDirection", "row");
19203
+ setProp(_el$25, "justifyContent", "space-between");
19204
+ setProp(_el$25, "paddingTop", 1);
19205
+ setProp(_el$25, "flexShrink", 0);
19206
+ setProp(_el$26, "wrapMode", "none");
19207
+ insert(_el$26, footerHint);
19208
+ insertNode(_el$27, _el$28);
19209
+ setProp(_el$27, "flexDirection", "row");
19210
+ setProp(_el$27, "gap", 2);
19211
+ setProp(_el$27, "flexShrink", 0);
19212
+ insert(_el$27, createComponent2(Show, {
18371
19213
  get when() {
18372
19214
  return modeBadge();
18373
19215
  },
18374
19216
  children: (badge) => (() => {
18375
- var _el$36 = createElement("text");
18376
- setProp(_el$36, "wrapMode", "none");
18377
- insert(_el$36, () => badge().label);
18378
- effect((_$p) => setProp(_el$36, "fg", toneColor(badge().tone), _$p));
18379
- return _el$36;
19217
+ var _el$53 = createElement("text");
19218
+ setProp(_el$53, "wrapMode", "none");
19219
+ insert(_el$53, () => badge().label);
19220
+ effect((_$p) => setProp(_el$53, "fg", toneColor(badge().tone), _$p));
19221
+ return _el$53;
18380
19222
  })()
18381
- }), _el$23);
18382
- insertNode(_el$23, _el$24);
18383
- setProp(_el$23, "flexDirection", "row");
18384
- setProp(_el$23, "flexShrink", 0);
18385
- setProp(_el$23, "onMouseUp", () => props.onChooseModel?.());
18386
- setProp(_el$24, "wrapMode", "none");
18387
- insert(_el$24, modelLabel, null);
18388
- insert(_el$24, () => props.onChooseModel ? " \u25BE" : "", null);
19223
+ }), _el$28);
19224
+ insertNode(_el$28, _el$29);
19225
+ setProp(_el$28, "flexDirection", "row");
19226
+ setProp(_el$28, "flexShrink", 0);
19227
+ setProp(_el$28, "onMouseUp", () => props.onChooseModel?.());
19228
+ setProp(_el$29, "wrapMode", "none");
19229
+ insert(_el$29, modelLabel, null);
19230
+ insert(_el$29, () => props.onChooseModel ? " \u25BE" : "", null);
18389
19231
  effect((_p$) => {
18390
- var _v$10 = props.isStreaming ? theme.accent : theme.textMuted, _v$11 = theme.textMuted;
18391
- _v$10 !== _p$.e && (_p$.e = setProp(_el$21, "fg", _v$10, _p$.e));
18392
- _v$11 !== _p$.t && (_p$.t = setProp(_el$24, "fg", _v$11, _p$.t));
19232
+ var _v$13 = props.isStreaming ? theme.accent : theme.textMuted, _v$14 = theme.textMuted;
19233
+ _v$13 !== _p$.e && (_p$.e = setProp(_el$26, "fg", _v$13, _p$.e));
19234
+ _v$14 !== _p$.t && (_p$.t = setProp(_el$29, "fg", _v$14, _p$.t));
18393
19235
  return _p$;
18394
19236
  }, {
18395
19237
  e: undefined,
18396
19238
  t: undefined
18397
19239
  });
18398
- return _el$20;
19240
+ return _el$25;
18399
19241
  }
18400
19242
  }), null);
18401
- insertNode(_el$25, _el$26);
18402
- setProp(_el$25, "height", 1);
18403
- setProp(_el$25, "border", ["left"]);
18404
- setProp(_el$26, "height", 1);
18405
- setProp(_el$26, "border", ["bottom"]);
19243
+ insertNode(_el$30, _el$31);
19244
+ setProp(_el$30, "height", 1);
19245
+ setProp(_el$30, "border", ["left"]);
19246
+ setProp(_el$31, "height", 1);
19247
+ setProp(_el$31, "border", ["bottom"]);
18406
19248
  effect((_p$) => {
18407
- var _v$12 = railColor(), _v$13 = {
19249
+ var _v$15 = railColor(), _v$16 = {
18408
19250
  ...SplitBorder.customBorderChars,
18409
19251
  bottomLeft: "\u2579"
18410
- }, _v$14 = theme.backgroundElement, _v$15 = props.isStreaming ? theme.accent : theme.primary, _v$16 = railColor(), _v$17 = {
19252
+ }, _v$17 = theme.backgroundElement, _v$18 = props.isStreaming ? theme.accent : theme.primary, _v$19 = railColor(), _v$20 = {
18411
19253
  ...EmptyBorder,
18412
19254
  vertical: theme.backgroundElement.a !== 0 ? "\u2579" : " "
18413
- }, _v$18 = theme.backgroundElement, _v$19 = {
19255
+ }, _v$21 = theme.backgroundElement, _v$22 = {
18414
19256
  ...EmptyBorder,
18415
19257
  horizontal: theme.backgroundElement.a !== 0 ? "\u2580" : " "
18416
19258
  };
18417
- _v$12 !== _p$.e && (_p$.e = setProp(_el$14, "borderColor", _v$12, _p$.e));
18418
- _v$13 !== _p$.t && (_p$.t = setProp(_el$14, "customBorderChars", _v$13, _p$.t));
18419
- _v$14 !== _p$.a && (_p$.a = setProp(_el$15, "backgroundColor", _v$14, _p$.a));
18420
- _v$15 !== _p$.o && (_p$.o = setProp(_el$17, "fg", _v$15, _p$.o));
18421
- _v$16 !== _p$.i && (_p$.i = setProp(_el$25, "borderColor", _v$16, _p$.i));
18422
- _v$17 !== _p$.n && (_p$.n = setProp(_el$25, "customBorderChars", _v$17, _p$.n));
18423
- _v$18 !== _p$.s && (_p$.s = setProp(_el$26, "borderColor", _v$18, _p$.s));
18424
- _v$19 !== _p$.h && (_p$.h = setProp(_el$26, "customBorderChars", _v$19, _p$.h));
19259
+ _v$15 !== _p$.e && (_p$.e = setProp(_el$14, "borderColor", _v$15, _p$.e));
19260
+ _v$16 !== _p$.t && (_p$.t = setProp(_el$14, "customBorderChars", _v$16, _p$.t));
19261
+ _v$17 !== _p$.a && (_p$.a = setProp(_el$15, "backgroundColor", _v$17, _p$.a));
19262
+ _v$18 !== _p$.o && (_p$.o = setProp(_el$22, "fg", _v$18, _p$.o));
19263
+ _v$19 !== _p$.i && (_p$.i = setProp(_el$30, "borderColor", _v$19, _p$.i));
19264
+ _v$20 !== _p$.n && (_p$.n = setProp(_el$30, "customBorderChars", _v$20, _p$.n));
19265
+ _v$21 !== _p$.s && (_p$.s = setProp(_el$31, "borderColor", _v$21, _p$.s));
19266
+ _v$22 !== _p$.h && (_p$.h = setProp(_el$31, "customBorderChars", _v$22, _p$.h));
18425
19267
  return _p$;
18426
19268
  }, {
18427
19269
  e: undefined,
@@ -18436,6 +19278,7 @@ function Composer(props) {
18436
19278
  return _el$;
18437
19279
  })();
18438
19280
  }
19281
+ var QUEUE_VISIBLE_CAP = 4;
18439
19282
  var init_Composer = __esm(() => {
18440
19283
  init_solid();
18441
19284
  init_solid();
@@ -19075,7 +19918,7 @@ function summarizeGlob(input, output, done) {
19075
19918
  }
19076
19919
 
19077
19920
  // src/tui/panes/chat/MessageList.tsx
19078
- import { TextAttributes as TextAttributes22 } from "@opentui/core";
19921
+ import { TextAttributes as TextAttributes23 } from "@opentui/core";
19079
19922
  function previewToolInput(input) {
19080
19923
  if (input == null)
19081
19924
  return "";
@@ -19171,7 +20014,7 @@ function UserRow(props) {
19171
20014
  })() : null;
19172
20015
  })(), null);
19173
20016
  effect((_p$) => {
19174
- var _v$ = theme.accent, _v$2 = TextAttributes22.BOLD, _v$3 = theme.primary, _v$4 = TextAttributes22.BOLD;
20017
+ var _v$ = theme.accent, _v$2 = TextAttributes23.BOLD, _v$3 = theme.primary, _v$4 = TextAttributes23.BOLD;
19175
20018
  _v$ !== _p$.e && (_p$.e = setProp(_el$2, "fg", _v$, _p$.e));
19176
20019
  _v$2 !== _p$.t && (_p$.t = setProp(_el$2, "attributes", _v$2, _p$.t));
19177
20020
  _v$3 !== _p$.a && (_p$.a = setProp(_el$5, "fg", _v$3, _p$.a));
@@ -19251,7 +20094,7 @@ function UserRow(props) {
19251
20094
  setProp(_el$21, "flexGrow", 1);
19252
20095
  insert(_el$22, () => view.text);
19253
20096
  effect((_p$) => {
19254
- var _v$9 = theme.accent, _v$0 = TextAttributes22.BOLD, _v$1 = theme.text;
20097
+ var _v$9 = theme.accent, _v$0 = TextAttributes23.BOLD, _v$1 = theme.text;
19255
20098
  _v$9 !== _p$.e && (_p$.e = setProp(_el$19, "fg", _v$9, _p$.e));
19256
20099
  _v$0 !== _p$.t && (_p$.t = setProp(_el$19, "attributes", _v$0, _p$.t));
19257
20100
  _v$1 !== _p$.a && (_p$.a = setProp(_el$22, "fg", _v$1, _p$.a));
@@ -19287,7 +20130,7 @@ function AssistantRow(props) {
19287
20130
  }
19288
20131
  }));
19289
20132
  effect((_p$) => {
19290
- var _v$10 = theme.accent, _v$11 = TextAttributes22.BOLD;
20133
+ var _v$10 = theme.accent, _v$11 = TextAttributes23.BOLD;
19291
20134
  _v$10 !== _p$.e && (_p$.e = setProp(_el$25, "fg", _v$10, _p$.e));
19292
20135
  _v$11 !== _p$.t && (_p$.t = setProp(_el$25, "attributes", _v$11, _p$.t));
19293
20136
  return _p$;
@@ -19362,7 +20205,7 @@ function ToolRow(props) {
19362
20205
  }), null);
19363
20206
  effect((_p$) => {
19364
20207
  var _v$18 = theme.text, _v$19 = {
19365
- attributes: TextAttributes22.BOLD
20208
+ attributes: TextAttributes23.BOLD
19366
20209
  };
19367
20210
  _v$18 !== _p$.e && (_p$.e = setProp(_el$45, "fg", _v$18, _p$.e));
19368
20211
  _v$19 !== _p$.t && (_p$.t = setProp(_el$46, "style", _v$19, _p$.t));
@@ -19530,7 +20373,7 @@ function ToolRow(props) {
19530
20373
  }
19531
20374
  }), null);
19532
20375
  effect((_p$) => {
19533
- var _v$16 = prefixColor(), _v$17 = TextAttributes22.BOLD;
20376
+ var _v$16 = prefixColor(), _v$17 = TextAttributes23.BOLD;
19534
20377
  _v$16 !== _p$.e && (_p$.e = setProp(_el$29, "fg", _v$16, _p$.e));
19535
20378
  _v$17 !== _p$.t && (_p$.t = setProp(_el$29, "attributes", _v$17, _p$.t));
19536
20379
  return _p$;
@@ -19769,7 +20612,7 @@ function BashBanner(props) {
19769
20612
  }
19770
20613
  }), null);
19771
20614
  effect((_p$) => {
19772
- var _v$28 = theme.accent, _v$29 = TextAttributes22.BOLD, _v$30 = theme.text;
20615
+ var _v$28 = theme.accent, _v$29 = TextAttributes23.BOLD, _v$30 = theme.text;
19773
20616
  _v$28 !== _p$.e && (_p$.e = setProp(_el$73, "fg", _v$28, _p$.e));
19774
20617
  _v$29 !== _p$.t && (_p$.t = setProp(_el$73, "attributes", _v$29, _p$.t));
19775
20618
  _v$30 !== _p$.a && (_p$.a = setProp(_el$76, "fg", _v$30, _p$.a));
@@ -19857,7 +20700,7 @@ function ReadGrepGlobBanner(props) {
19857
20700
  }), null);
19858
20701
  effect((_p$) => {
19859
20702
  var _v$31 = theme.text, _v$32 = {
19860
- attributes: TextAttributes22.BOLD
20703
+ attributes: TextAttributes23.BOLD
19861
20704
  };
19862
20705
  _v$31 !== _p$.e && (_p$.e = setProp(_el$81, "fg", _v$31, _p$.e));
19863
20706
  _v$32 !== _p$.t && (_p$.t = setProp(_el$82, "style", _v$32, _p$.t));
@@ -19886,7 +20729,7 @@ function SystemRow(props) {
19886
20729
  setProp(_el$87, "flexGrow", 1);
19887
20730
  insert(_el$88, () => props.text);
19888
20731
  effect((_p$) => {
19889
- var _v$33 = theme.textMuted, _v$34 = TextAttributes22.DIM, _v$35 = isError() ? theme.error : theme.textMuted;
20732
+ var _v$33 = theme.textMuted, _v$34 = TextAttributes23.DIM, _v$35 = isError() ? theme.error : theme.textMuted;
19890
20733
  _v$33 !== _p$.e && (_p$.e = setProp(_el$85, "fg", _v$33, _p$.e));
19891
20734
  _v$34 !== _p$.t && (_p$.t = setProp(_el$85, "attributes", _v$34, _p$.t));
19892
20735
  _v$35 !== _p$.a && (_p$.a = setProp(_el$88, "fg", _v$35, _p$.a));
@@ -19976,7 +20819,7 @@ function ApprovalRow(props) {
19976
20819
  insertNode(_el$103, _el$105);
19977
20820
  insert(_el$103, () => r().status, _el$105);
19978
20821
  effect((_p$) => {
19979
- var _v$44 = r().status === "approved" ? theme.success : theme.error, _v$45 = TextAttributes22.BOLD;
20822
+ var _v$44 = r().status === "approved" ? theme.success : theme.error, _v$45 = TextAttributes23.BOLD;
19980
20823
  _v$44 !== _p$.e && (_p$.e = setProp(_el$103, "fg", _v$44, _p$.e));
19981
20824
  _v$45 !== _p$.t && (_p$.t = setProp(_el$103, "attributes", _v$45, _p$.t));
19982
20825
  return _p$;
@@ -19993,7 +20836,7 @@ function ApprovalRow(props) {
19993
20836
  insertNode(_el$99, createTextNode(`[ Approve ]`));
19994
20837
  setProp(_el$99, "onMouseUp", () => props.onApprove(true));
19995
20838
  effect((_p$) => {
19996
- var _v$36 = theme.success, _v$37 = TextAttributes22.BOLD;
20839
+ var _v$36 = theme.success, _v$37 = TextAttributes23.BOLD;
19997
20840
  _v$36 !== _p$.e && (_p$.e = setProp(_el$99, "fg", _v$36, _p$.e));
19998
20841
  _v$37 !== _p$.t && (_p$.t = setProp(_el$99, "attributes", _v$37, _p$.t));
19999
20842
  return _p$;
@@ -20007,7 +20850,7 @@ function ApprovalRow(props) {
20007
20850
  insertNode(_el$101, createTextNode(`[ Reject ]`));
20008
20851
  setProp(_el$101, "onMouseUp", () => props.onApprove(false));
20009
20852
  effect((_p$) => {
20010
- var _v$38 = theme.error, _v$39 = TextAttributes22.BOLD;
20853
+ var _v$38 = theme.error, _v$39 = TextAttributes23.BOLD;
20011
20854
  _v$38 !== _p$.e && (_p$.e = setProp(_el$101, "fg", _v$38, _p$.e));
20012
20855
  _v$39 !== _p$.t && (_p$.t = setProp(_el$101, "attributes", _v$39, _p$.t));
20013
20856
  return _p$;
@@ -20020,7 +20863,7 @@ function ApprovalRow(props) {
20020
20863
  }
20021
20864
  }));
20022
20865
  effect((_p$) => {
20023
- var _v$40 = headerColor(), _v$41 = TextAttributes22.BOLD, _v$42 = headerColor(), _v$43 = TextAttributes22.BOLD;
20866
+ var _v$40 = headerColor(), _v$41 = TextAttributes23.BOLD, _v$42 = headerColor(), _v$43 = TextAttributes23.BOLD;
20024
20867
  _v$40 !== _p$.e && (_p$.e = setProp(_el$91, "fg", _v$40, _p$.e));
20025
20868
  _v$41 !== _p$.t && (_p$.t = setProp(_el$91, "attributes", _v$41, _p$.t));
20026
20869
  _v$42 !== _p$.a && (_p$.a = setProp(_el$92, "fg", _v$42, _p$.a));
@@ -20242,7 +21085,7 @@ function QuestionRow(props) {
20242
21085
  insertNode(_el$116, _el$118);
20243
21086
  insert(_el$116, () => q.header, _el$118);
20244
21087
  effect((_p$) => {
20245
- var _v$52 = theme.accent, _v$53 = TextAttributes22.BOLD;
21088
+ var _v$52 = theme.accent, _v$53 = TextAttributes23.BOLD;
20246
21089
  _v$52 !== _p$.e && (_p$.e = setProp(_el$116, "fg", _v$52, _p$.e));
20247
21090
  _v$53 !== _p$.t && (_p$.t = setProp(_el$116, "attributes", _v$53, _p$.t));
20248
21091
  return _p$;
@@ -20356,7 +21199,7 @@ function QuestionRow(props) {
20356
21199
  }
20357
21200
  }), null);
20358
21201
  effect((_p$) => {
20359
- var _v$58 = isHl() ? theme.accent : theme.textMuted, _v$59 = TextAttributes22.BOLD, _v$60 = theme.textMuted, _v$61 = isPicked() ? theme.accent : theme.textMuted, _v$62 = TextAttributes22.BOLD, _v$63 = theme.text;
21202
+ var _v$58 = isHl() ? theme.accent : theme.textMuted, _v$59 = TextAttributes23.BOLD, _v$60 = theme.textMuted, _v$61 = isPicked() ? theme.accent : theme.textMuted, _v$62 = TextAttributes23.BOLD, _v$63 = theme.text;
20360
21203
  _v$58 !== _p$.e && (_p$.e = setProp(_el$136, "fg", _v$58, _p$.e));
20361
21204
  _v$59 !== _p$.t && (_p$.t = setProp(_el$136, "attributes", _v$59, _p$.t));
20362
21205
  _v$60 !== _p$.a && (_p$.a = setProp(_el$137, "fg", _v$60, _p$.a));
@@ -20401,7 +21244,7 @@ function QuestionRow(props) {
20401
21244
  insertNode(_el$147, createTextNode(`Other`));
20402
21245
  insertNode(_el$149, createTextNode(`Type your own answer`));
20403
21246
  effect((_p$) => {
20404
- var _v$64 = isOtherHl() ? theme.accent : theme.textMuted, _v$65 = TextAttributes22.BOLD, _v$66 = theme.textMuted, _v$67 = otherPicked() ? theme.accent : theme.textMuted, _v$68 = TextAttributes22.BOLD, _v$69 = theme.text, _v$70 = theme.textMuted;
21247
+ var _v$64 = isOtherHl() ? theme.accent : theme.textMuted, _v$65 = TextAttributes23.BOLD, _v$66 = theme.textMuted, _v$67 = otherPicked() ? theme.accent : theme.textMuted, _v$68 = TextAttributes23.BOLD, _v$69 = theme.text, _v$70 = theme.textMuted;
20405
21248
  _v$64 !== _p$.e && (_p$.e = setProp(_el$143, "fg", _v$64, _p$.e));
20406
21249
  _v$65 !== _p$.t && (_p$.t = setProp(_el$143, "attributes", _v$65, _p$.t));
20407
21250
  _v$66 !== _p$.a && (_p$.a = setProp(_el$144, "fg", _v$66, _p$.a));
@@ -20457,7 +21300,7 @@ function QuestionRow(props) {
20457
21300
  }
20458
21301
  }), null);
20459
21302
  effect((_p$) => {
20460
- var _v$54 = isQuestionComplete(index()) ? theme.success : theme.textMuted, _v$55 = TextAttributes22.BOLD;
21303
+ var _v$54 = isQuestionComplete(index()) ? theme.success : theme.textMuted, _v$55 = TextAttributes23.BOLD;
20461
21304
  _v$54 !== _p$.e && (_p$.e = setProp(_el$132, "fg", _v$54, _p$.e));
20462
21305
  _v$55 !== _p$.t && (_p$.t = setProp(_el$132, "attributes", _v$55, _p$.t));
20463
21306
  return _p$;
@@ -20493,7 +21336,7 @@ function QuestionRow(props) {
20493
21336
  setProp(_el$111, "paddingTop", 1);
20494
21337
  insertNode(_el$112, createTextNode(`[submitted]`));
20495
21338
  effect((_p$) => {
20496
- var _v$46 = theme.success, _v$47 = TextAttributes22.BOLD;
21339
+ var _v$46 = theme.success, _v$47 = TextAttributes23.BOLD;
20497
21340
  _v$46 !== _p$.e && (_p$.e = setProp(_el$112, "fg", _v$46, _p$.e));
20498
21341
  _v$47 !== _p$.t && (_p$.t = setProp(_el$112, "attributes", _v$47, _p$.t));
20499
21342
  return _p$;
@@ -20505,7 +21348,7 @@ function QuestionRow(props) {
20505
21348
  }
20506
21349
  }), null);
20507
21350
  effect((_p$) => {
20508
- var _v$48 = theme.warning, _v$49 = TextAttributes22.BOLD, _v$50 = theme.warning, _v$51 = TextAttributes22.BOLD;
21351
+ var _v$48 = theme.warning, _v$49 = TextAttributes23.BOLD, _v$50 = theme.warning, _v$51 = TextAttributes23.BOLD;
20509
21352
  _v$48 !== _p$.e && (_p$.e = setProp(_el$108, "fg", _v$48, _p$.e));
20510
21353
  _v$49 !== _p$.t && (_p$.t = setProp(_el$108, "attributes", _v$49, _p$.t));
20511
21354
  _v$50 !== _p$.a && (_p$.a = setProp(_el$110, "fg", _v$50, _p$.a));
@@ -20625,7 +21468,7 @@ function MessageList(props) {
20625
21468
  insertNode(_el$160, _el$161);
20626
21469
  insert(_el$160, () => props.error, null);
20627
21470
  effect((_p$) => {
20628
- var _v$71 = theme.error, _v$72 = TextAttributes22.BOLD, _v$73 = theme.error;
21471
+ var _v$71 = theme.error, _v$72 = TextAttributes23.BOLD, _v$73 = theme.error;
20629
21472
  _v$71 !== _p$.e && (_p$.e = setProp(_el$158, "fg", _v$71, _p$.e));
20630
21473
  _v$72 !== _p$.t && (_p$.t = setProp(_el$158, "attributes", _v$72, _p$.t));
20631
21474
  _v$73 !== _p$.a && (_p$.a = setProp(_el$160, "fg", _v$73, _p$.a));
@@ -20781,7 +21624,7 @@ function ToolFoldRow(props) {
20781
21624
  setProp(_el$164, "flexGrow", 1);
20782
21625
  insert(_el$165, () => props.summary);
20783
21626
  effect((_p$) => {
20784
- var _v$74 = fg(), _v$75 = TextAttributes22.DIM, _v$76 = theme.textMuted;
21627
+ var _v$74 = fg(), _v$75 = TextAttributes23.DIM, _v$76 = theme.textMuted;
20785
21628
  _v$74 !== _p$.e && (_p$.e = setProp(_el$163, "fg", _v$74, _p$.e));
20786
21629
  _v$75 !== _p$.t && (_p$.t = setProp(_el$163, "attributes", _v$75, _p$.t));
20787
21630
  _v$76 !== _p$.a && (_p$.a = setProp(_el$165, "fg", _v$76, _p$.a));
@@ -20846,7 +21689,7 @@ var init_models = __esm(() => {
20846
21689
  });
20847
21690
 
20848
21691
  // src/tui/panes/chat/composer/ModelPicker.tsx
20849
- import { TextAttributes as TextAttributes23 } from "@opentui/core";
21692
+ import { TextAttributes as TextAttributes24 } from "@opentui/core";
20850
21693
  function ModelPicker(props) {
20851
21694
  const dialog = useDialog();
20852
21695
  const {
@@ -20926,7 +21769,7 @@ function ModelPicker(props) {
20926
21769
  })() : null;
20927
21770
  })(), null);
20928
21771
  effect((_p$) => {
20929
- var _v$5 = active() ? theme.primary : undefined, _v$6 = active() ? theme.selectedListItemText : theme.text, _v$7 = active() ? TextAttributes23.BOLD : undefined;
21772
+ var _v$5 = active() ? theme.primary : undefined, _v$6 = active() ? theme.selectedListItemText : theme.text, _v$7 = active() ? TextAttributes24.BOLD : undefined;
20930
21773
  _v$5 !== _p$.e && (_p$.e = setProp(_el$1, "backgroundColor", _v$5, _p$.e));
20931
21774
  _v$6 !== _p$.t && (_p$.t = setProp(_el$10, "fg", _v$6, _p$.t));
20932
21775
  _v$7 !== _p$.a && (_p$.a = setProp(_el$10, "attributes", _v$7, _p$.a));
@@ -20944,7 +21787,7 @@ function ModelPicker(props) {
20944
21787
  setProp(_el$8, "paddingBottom", 1);
20945
21788
  insertNode(_el$9, createTextNode(`\u2191\u2193 pick \xB7 enter select \xB7 esc cancel`));
20946
21789
  effect((_p$) => {
20947
- var _v$ = TextAttributes23.BOLD, _v$2 = theme.text, _v$3 = theme.textMuted, _v$4 = theme.textMuted;
21790
+ var _v$ = TextAttributes24.BOLD, _v$2 = theme.text, _v$3 = theme.textMuted, _v$4 = theme.textMuted;
20948
21791
  _v$ !== _p$.e && (_p$.e = setProp(_el$3, "attributes", _v$, _p$.e));
20949
21792
  _v$2 !== _p$.t && (_p$.t = setProp(_el$3, "fg", _v$2, _p$.t));
20950
21793
  _v$3 !== _p$.a && (_p$.a = setProp(_el$5, "fg", _v$3, _p$.a));
@@ -20986,10 +21829,10 @@ var init_ModelPicker = __esm(() => {
20986
21829
 
20987
21830
  // src/tui/panes/chat/composer/user-slashes.ts
20988
21831
  import { readFile as readFile6, readdir as readdir3, stat as stat3 } from "fs/promises";
20989
- import { homedir as homedir10 } from "os";
21832
+ import { homedir as homedir11 } from "os";
20990
21833
  import { join as join14 } from "path";
20991
21834
  function resolveHome() {
20992
- return process.env.HOME ?? homedir10();
21835
+ return process.env.HOME ?? homedir11();
20993
21836
  }
20994
21837
  async function safeReaddir(path8) {
20995
21838
  try {
@@ -21146,6 +21989,81 @@ var init_user_slashes = () => {};
21146
21989
  function totalContextTokens(u) {
21147
21990
  return u.input_tokens + (u.cache_read_input_tokens ?? 0) + (u.cache_creation_input_tokens ?? 0);
21148
21991
  }
21992
+ function parseTimestampMs(value) {
21993
+ const ms = new Date(value).getTime();
21994
+ return Number.isFinite(ms) ? ms : null;
21995
+ }
21996
+ function mergeIntervals(intervals) {
21997
+ if (intervals.length === 0)
21998
+ return [];
21999
+ const sorted = [...intervals].sort((a, b) => a.startMs - b.startMs);
22000
+ const first = sorted[0];
22001
+ if (!first)
22002
+ return [];
22003
+ const merged = [{ startMs: first.startMs, endMs: first.endMs }];
22004
+ for (let i = 1;i < sorted.length; i++) {
22005
+ const current = sorted[i];
22006
+ const last = merged[merged.length - 1];
22007
+ if (!current || !last)
22008
+ continue;
22009
+ if (current.startMs <= last.endMs) {
22010
+ last.endMs = Math.max(last.endMs, current.endMs);
22011
+ } else {
22012
+ merged.push({ startMs: current.startMs, endMs: current.endMs });
22013
+ }
22014
+ }
22015
+ return merged;
22016
+ }
22017
+ function durationMs(intervals) {
22018
+ return intervals.reduce((total, interval) => total + (interval.endMs - interval.startMs), 0);
22019
+ }
22020
+ function deriveUsageMetricsFromHistory(past) {
22021
+ let latestUsage;
22022
+ let latestUsageTimestampMs = null;
22023
+ let lastUserTimestampMs = null;
22024
+ let inputTokens = 0;
22025
+ let outputTokens = 0;
22026
+ const intervals = [];
22027
+ for (const message of past) {
22028
+ const timestampMs = parseTimestampMs(message.timestamp);
22029
+ if (message.role === "user" && timestampMs !== null) {
22030
+ lastUserTimestampMs = timestampMs;
22031
+ continue;
22032
+ }
22033
+ if (message.role !== "assistant" || !message.usage)
22034
+ continue;
22035
+ if (timestampMs !== null && (latestUsageTimestampMs === null || timestampMs > latestUsageTimestampMs)) {
22036
+ latestUsageTimestampMs = timestampMs;
22037
+ latestUsage = message.usage;
22038
+ } else if (latestUsage === undefined) {
22039
+ latestUsage = message.usage;
22040
+ }
22041
+ inputTokens += message.usage.input_tokens;
22042
+ outputTokens += message.usage.output_tokens;
22043
+ if (timestampMs !== null && lastUserTimestampMs !== null && timestampMs > lastUserTimestampMs) {
22044
+ intervals.push({ startMs: lastUserTimestampMs, endMs: timestampMs });
22045
+ }
22046
+ }
22047
+ if (!latestUsage)
22048
+ return;
22049
+ const totalDurationMs = durationMs(mergeIntervals(intervals));
22050
+ if (totalDurationMs <= 0)
22051
+ return latestUsage;
22052
+ return {
22053
+ ...latestUsage,
22054
+ total_speed_tokens_per_second: (inputTokens + outputTokens) / (totalDurationMs / 1000)
22055
+ };
22056
+ }
22057
+ function withTotalSpeedForTurn(usage, startedAtIso, endedAtIso) {
22058
+ const startMs = startedAtIso ? parseTimestampMs(startedAtIso) : null;
22059
+ const endMs = parseTimestampMs(endedAtIso);
22060
+ if (startMs === null || endMs === null || endMs <= startMs)
22061
+ return usage;
22062
+ return {
22063
+ ...usage,
22064
+ total_speed_tokens_per_second: (usage.input_tokens + usage.output_tokens) / ((endMs - startMs) / 1000)
22065
+ };
22066
+ }
21149
22067
  function contextWindowTokensForModel(modelId) {
21150
22068
  const id = modelId ?? resolveDefaultModelId();
21151
22069
  if (id.includes("[1m]"))
@@ -21168,13 +22086,21 @@ function formatTokShort(n) {
21168
22086
  return `${(n / 1000).toFixed(1)}k`;
21169
22087
  return String(n);
21170
22088
  }
22089
+ function formatTotalSpeed(tokensPerSecond) {
22090
+ if (typeof tokensPerSecond !== "number" || !Number.isFinite(tokensPerSecond))
22091
+ return null;
22092
+ if (tokensPerSecond >= 1000)
22093
+ return `${(tokensPerSecond / 1000).toFixed(1)}k t/s`;
22094
+ return `${tokensPerSecond.toFixed(1)} t/s`;
22095
+ }
21171
22096
  function formatContextUsageCompact(u, modelId) {
21172
22097
  const window = contextWindowTokensForModel(modelId);
21173
22098
  const total = totalContextTokens(u);
21174
22099
  if (total <= 0 || window <= 0)
21175
22100
  return null;
21176
22101
  const pct2 = Math.min(100, Math.max(0, Math.round(total / window * 100)));
21177
- return `${pct2}% \xB7 ${formatTokShort(total)}/${formatTokShort(window)}`;
22102
+ const speed = formatTotalSpeed(u.total_speed_tokens_per_second);
22103
+ return [`${pct2}% \xB7 ${formatTokShort(total)}/${formatTokShort(window)}`, speed].filter(Boolean).join(" \xB7 ");
21178
22104
  }
21179
22105
  var LONG_CTX = 1e6, STD_CTX = 200000;
21180
22106
  var init_context_meter = __esm(() => {
@@ -21226,14 +22152,7 @@ function setMessagesFromHistory(state, past) {
21226
22152
  for (const m of past) {
21227
22153
  appendRowsFromMessage(rows, toolIndexById, m);
21228
22154
  }
21229
- let latestUsage;
21230
- for (let i = past.length - 1;i >= 0; i--) {
21231
- const u = past[i]?.usage;
21232
- if (u) {
21233
- latestUsage = u;
21234
- break;
21235
- }
21236
- }
22155
+ const latestUsage = deriveUsageMetricsFromHistory(past);
21237
22156
  return {
21238
22157
  ...state,
21239
22158
  messages: capMessages(rows, new Date().toISOString()),
@@ -21311,19 +22230,20 @@ function applyEvent(state, ev, nowIso = new Date().toISOString()) {
21311
22230
  case "usage":
21312
22231
  return {
21313
22232
  ...state,
21314
- lastUsage: {
22233
+ lastUsage: withTotalSpeedForTurn({
21315
22234
  input_tokens: ev.input_tokens,
21316
22235
  output_tokens: ev.output_tokens,
21317
22236
  cache_read_input_tokens: ev.cache_read_input_tokens,
21318
22237
  cache_creation_input_tokens: ev.cache_creation_input_tokens
21319
- }
22238
+ }, state.activeTurnStartedAt, nowIso)
21320
22239
  };
21321
22240
  case "done":
21322
- return { ...state, isStreaming: false };
22241
+ return { ...state, isStreaming: false, activeTurnStartedAt: undefined };
21323
22242
  case "error":
21324
22243
  return {
21325
22244
  ...state,
21326
22245
  isStreaming: false,
22246
+ activeTurnStartedAt: undefined,
21327
22247
  error: ev.message,
21328
22248
  messages: capMessages([...state.messages, { kind: "system", text: `error: ${ev.message}`, ts: nowIso }], nowIso)
21329
22249
  };
@@ -21333,6 +22253,7 @@ function applyEvent(state, ev, nowIso = new Date().toISOString()) {
21333
22253
  isStreaming: true,
21334
22254
  error: null,
21335
22255
  lastUsage: undefined,
22256
+ activeTurnStartedAt: nowIso,
21336
22257
  messages: capMessages([...state.messages, { kind: "user", text: ev.text, ts: nowIso }], nowIso)
21337
22258
  };
21338
22259
  case "system.info":
@@ -21501,6 +22422,7 @@ function findLastIndex(arr, pred) {
21501
22422
  }
21502
22423
  var SCROLLBACK_CAP = 1000, SENTINEL_PREFIX = "(scrollback truncated \u2014 ", SENTINEL_SUFFIX = " rows dropped)", CLAUDE_NOISE_TAGS, NOISE_TAG_PATTERN, QUEUE_SOFT_CAP = 50;
21503
22424
  var init_store2 = __esm(() => {
22425
+ init_context_meter();
21504
22426
  CLAUDE_NOISE_TAGS = [
21505
22427
  "local-command-caveat",
21506
22428
  "command-message",
@@ -21701,7 +22623,6 @@ var init_use_chat_session = __esm(() => {
21701
22623
  });
21702
22624
 
21703
22625
  // src/tui/panes/chat/Chat.tsx
21704
- import { TextAttributes as TextAttributes24 } from "@opentui/core";
21705
22626
  function Chat(props) {
21706
22627
  const {
21707
22628
  theme
@@ -21906,7 +22827,7 @@ function Chat(props) {
21906
22827
  send(pp);
21907
22828
  });
21908
22829
  });
21909
- let draining = false;
22830
+ let dispatching = false;
21910
22831
  createEffect(() => {
21911
22832
  const taskId = props.taskId();
21912
22833
  const tabId = activeTabId();
@@ -21919,15 +22840,15 @@ function Chat(props) {
21919
22840
  return;
21920
22841
  if (hasPendingInput())
21921
22842
  return;
21922
- if (draining)
22843
+ if (dispatching)
21923
22844
  return;
21924
22845
  queueMicrotask(async () => {
21925
- if (draining)
22846
+ if (dispatching)
21926
22847
  return;
21927
22848
  const cur = activeState();
21928
22849
  if (cur.isStreaming || cur.queue.length === 0)
21929
22850
  return;
21930
- draining = true;
22851
+ dispatching = true;
21931
22852
  try {
21932
22853
  let head = null;
21933
22854
  patchActiveState((s) => {
@@ -21944,7 +22865,7 @@ function Chat(props) {
21944
22865
  patchActiveState((s) => pushSystemError(s, `queued runTask failed: ${stringifyErr2(err)}`));
21945
22866
  }
21946
22867
  } finally {
21947
- draining = false;
22868
+ dispatching = false;
21948
22869
  }
21949
22870
  });
21950
22871
  });
@@ -21970,16 +22891,17 @@ function Chat(props) {
21970
22891
  const streaming = activeState().isStreaming;
21971
22892
  if (streaming && mode === "steer") {
21972
22893
  setDraft("");
21973
- try {
21974
- await props.orchestrator.interruptTask(taskId, tabId);
21975
- } catch (err) {
21976
- patchActiveState((s) => pushSystemError(s, `interrupt failed: ${stringifyErr2(err)}`));
22894
+ if (dispatching)
21977
22895
  return;
21978
- }
22896
+ dispatching = true;
21979
22897
  try {
21980
- await props.orchestrator.runTask(taskId, text, tabId);
21981
- } catch (err) {
21982
- patchActiveState((s) => pushSystemError(s, `runTask failed: ${stringifyErr2(err)}`));
22898
+ try {
22899
+ await props.orchestrator.steerTask(taskId, text, tabId);
22900
+ } catch (err) {
22901
+ patchActiveState((s) => pushSystemError(s, `steer failed: ${stringifyErr2(err)}`));
22902
+ }
22903
+ } finally {
22904
+ dispatching = false;
21983
22905
  }
21984
22906
  return;
21985
22907
  }
@@ -22002,6 +22924,13 @@ function Chat(props) {
22002
22924
  function cancelQueued(id) {
22003
22925
  patchActiveState((s) => removeFromQueue(s, id));
22004
22926
  }
22927
+ function sendQueuedNow(id) {
22928
+ const entry = activeState().queue.find((q) => q.id === id);
22929
+ if (!entry)
22930
+ return;
22931
+ patchActiveState((s) => removeFromQueue(s, id));
22932
+ send(entry.text, "steer");
22933
+ }
22005
22934
  async function newTab() {
22006
22935
  const taskId = props.taskId();
22007
22936
  if (!taskId)
@@ -22255,19 +23184,6 @@ function Chat(props) {
22255
23184
  return _el$5;
22256
23185
  }
22257
23186
  }), null);
22258
- insert(_el$, createComponent2(Show, {
22259
- get when() {
22260
- return memo2(() => !!props.taskId())() && activeState().queue.length > 0;
22261
- },
22262
- get children() {
22263
- return createComponent2(QueuedPromptList, {
22264
- get queue() {
22265
- return activeState().queue;
22266
- },
22267
- onCancel: cancelQueued
22268
- });
22269
- }
22270
- }), null);
22271
23187
  insert(_el$, createComponent2(Show, {
22272
23188
  get when() {
22273
23189
  return memo2(() => !!showThinking())() && props.taskId();
@@ -22312,7 +23228,10 @@ function Chat(props) {
22312
23228
  onCyclePermissionMode: cyclePermissionMode,
22313
23229
  modelLabel,
22314
23230
  onChooseModel: () => void chooseModel(),
22315
- worktreePath
23231
+ worktreePath,
23232
+ queue: () => activeState().queue,
23233
+ onCancelQueued: cancelQueued,
23234
+ onSendQueuedNow: sendQueuedNow
22316
23235
  });
22317
23236
  }
22318
23237
  }), null);
@@ -22328,97 +23247,6 @@ function stringifyErr2(err) {
22328
23247
  return String(err);
22329
23248
  }
22330
23249
  }
22331
- function QueuedPromptList(props) {
22332
- const {
22333
- theme
22334
- } = useTheme();
22335
- const visible = () => props.queue.slice(0, QUEUE_VISIBLE_CAP);
22336
- const hidden = () => Math.max(0, props.queue.length - QUEUE_VISIBLE_CAP);
22337
- return (() => {
22338
- var _el$7 = createElement("box");
22339
- setProp(_el$7, "flexDirection", "column");
22340
- setProp(_el$7, "gap", 0);
22341
- setProp(_el$7, "paddingTop", 1);
22342
- setProp(_el$7, "paddingLeft", 1);
22343
- setProp(_el$7, "paddingRight", 1);
22344
- insert(_el$7, createComponent2(For, {
22345
- get each() {
22346
- return visible();
22347
- },
22348
- children: (entry, idx) => (() => {
22349
- var _el$10 = createElement("box"), _el$11 = createElement("text"), _el$13 = createElement("box"), _el$14 = createElement("text"), _el$15 = createTextNode(`queued`), _el$16 = createTextNode(`:`), _el$17 = createElement("box"), _el$18 = createElement("text"), _el$19 = createElement("text");
22350
- insertNode(_el$10, _el$11);
22351
- insertNode(_el$10, _el$13);
22352
- setProp(_el$10, "flexDirection", "row");
22353
- setProp(_el$10, "gap", 1);
22354
- setProp(_el$10, "alignItems", "flex-start");
22355
- insertNode(_el$11, createTextNode(`+`));
22356
- insertNode(_el$13, _el$14);
22357
- insertNode(_el$13, _el$17);
22358
- insertNode(_el$13, _el$19);
22359
- setProp(_el$13, "flexGrow", 1);
22360
- setProp(_el$13, "flexDirection", "row");
22361
- setProp(_el$13, "gap", 1);
22362
- insertNode(_el$14, _el$15);
22363
- insertNode(_el$14, _el$16);
22364
- setProp(_el$14, "wrapMode", "none");
22365
- insert(_el$14, () => idx() === 0 ? " (next)" : "", _el$16);
22366
- insertNode(_el$17, _el$18);
22367
- setProp(_el$17, "flexGrow", 1);
22368
- insert(_el$18, () => entry.text);
22369
- insertNode(_el$19, createTextNode(`[x]`));
22370
- setProp(_el$19, "onMouseUp", () => props.onCancel(entry.id));
22371
- effect((_p$) => {
22372
- var _v$4 = theme.textMuted, _v$5 = TextAttributes24.BOLD, _v$6 = theme.textMuted, _v$7 = theme.text, _v$8 = theme.error, _v$9 = TextAttributes24.BOLD;
22373
- _v$4 !== _p$.e && (_p$.e = setProp(_el$11, "fg", _v$4, _p$.e));
22374
- _v$5 !== _p$.t && (_p$.t = setProp(_el$11, "attributes", _v$5, _p$.t));
22375
- _v$6 !== _p$.a && (_p$.a = setProp(_el$14, "fg", _v$6, _p$.a));
22376
- _v$7 !== _p$.o && (_p$.o = setProp(_el$18, "fg", _v$7, _p$.o));
22377
- _v$8 !== _p$.i && (_p$.i = setProp(_el$19, "fg", _v$8, _p$.i));
22378
- _v$9 !== _p$.n && (_p$.n = setProp(_el$19, "attributes", _v$9, _p$.n));
22379
- return _p$;
22380
- }, {
22381
- e: undefined,
22382
- t: undefined,
22383
- a: undefined,
22384
- o: undefined,
22385
- i: undefined,
22386
- n: undefined
22387
- });
22388
- return _el$10;
22389
- })()
22390
- }), null);
22391
- insert(_el$7, createComponent2(Show, {
22392
- get when() {
22393
- return hidden() > 0;
22394
- },
22395
- get children() {
22396
- var _el$8 = createElement("box"), _el$9 = createElement("text"), _el$1 = createElement("text");
22397
- insertNode(_el$8, _el$9);
22398
- insertNode(_el$8, _el$1);
22399
- setProp(_el$8, "flexDirection", "row");
22400
- setProp(_el$8, "gap", 1);
22401
- setProp(_el$8, "alignItems", "flex-start");
22402
- insertNode(_el$9, createTextNode(`+`));
22403
- insert(_el$1, () => `\u2026 ${hidden()} more queued`);
22404
- effect((_p$) => {
22405
- var _v$ = theme.textMuted, _v$2 = TextAttributes24.BOLD, _v$3 = theme.textMuted;
22406
- _v$ !== _p$.e && (_p$.e = setProp(_el$9, "fg", _v$, _p$.e));
22407
- _v$2 !== _p$.t && (_p$.t = setProp(_el$9, "attributes", _v$2, _p$.t));
22408
- _v$3 !== _p$.a && (_p$.a = setProp(_el$1, "fg", _v$3, _p$.a));
22409
- return _p$;
22410
- }, {
22411
- e: undefined,
22412
- t: undefined,
22413
- a: undefined
22414
- });
22415
- return _el$8;
22416
- }
22417
- }), null);
22418
- return _el$7;
22419
- })();
22420
- }
22421
- var QUEUE_VISIBLE_CAP = 4;
22422
23250
  var init_Chat = __esm(() => {
22423
23251
  init_solid();
22424
23252
  init_solid();
@@ -23028,13 +23856,16 @@ var init_Sidebar = __esm(() => {
23028
23856
  });
23029
23857
 
23030
23858
  // src/orchestrator/bridge/server.ts
23031
- import { mkdir as mkdir3, unlink as unlink3 } from "fs/promises";
23859
+ import { mkdir as mkdir4, unlink as unlink3 } from "fs/promises";
23032
23860
  import { createServer } from "net";
23033
23861
  import { dirname as dirname6 } from "path";
23034
23862
  async function startBridgeServer(orch, socketPath) {
23035
- await mkdir3(dirname6(socketPath), { recursive: true });
23863
+ await mkdir4(dirname6(socketPath), { recursive: true });
23036
23864
  await unlink3(socketPath).catch(() => {});
23865
+ const conns = new Set;
23037
23866
  const server = createServer((conn) => {
23867
+ conns.add(conn);
23868
+ conn.on("close", () => conns.delete(conn));
23038
23869
  let buffer = "";
23039
23870
  conn.on("data", (chunk) => {
23040
23871
  buffer += chunk.toString("utf8");
@@ -23067,6 +23898,9 @@ async function startBridgeServer(orch, socketPath) {
23067
23898
  return {
23068
23899
  socketPath,
23069
23900
  async close() {
23901
+ for (const conn of conns)
23902
+ conn.destroy();
23903
+ conns.clear();
23070
23904
  await new Promise((resolve4) => server.close(() => resolve4()));
23071
23905
  await unlink3(socketPath).catch(() => {});
23072
23906
  }
@@ -23159,12 +23993,12 @@ var exports_bridge = {};
23159
23993
  __export(exports_bridge, {
23160
23994
  startBridge: () => startBridge
23161
23995
  });
23162
- import { writeFile as writeFile3 } from "fs/promises";
23163
- import { homedir as homedir11 } from "os";
23996
+ import { writeFile as writeFile4 } from "fs/promises";
23997
+ import { homedir as homedir12 } from "os";
23164
23998
  import { join as join15 } from "path";
23165
23999
  import { fileURLToPath as fileURLToPath2 } from "url";
23166
24000
  async function startBridge(orch, opts = {}) {
23167
- const home = opts.homeDir ?? process.env.KOBE_HOME_DIR ?? homedir11();
24001
+ const home = opts.homeDir ?? process.env.KOBE_HOME_DIR ?? homedir12();
23168
24002
  const runDir = join15(home, ".kobe", "run");
23169
24003
  const socketPath = join15(runDir, `bridge-${process.pid}.sock`);
23170
24004
  const mcpConfigPath = join15(runDir, `mcp-${process.pid}.json`);
@@ -23179,7 +24013,7 @@ async function startBridge(orch, opts = {}) {
23179
24013
  }
23180
24014
  }
23181
24015
  };
23182
- await writeFile3(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf8");
24016
+ await writeFile4(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf8");
23183
24017
  process.env.KOBE_MCP_CONFIG = mcpConfigPath;
23184
24018
  return {
23185
24019
  socketPath,
@@ -23194,7 +24028,7 @@ var init_bridge = __esm(() => {
23194
24028
  });
23195
24029
 
23196
24030
  // src/tui/app.tsx
23197
- import { homedir as homedir12 } from "os";
24031
+ import { homedir as homedir13 } from "os";
23198
24032
  import { join as join16 } from "path";
23199
24033
  function Shell(props) {
23200
24034
  const themeCtx = useTheme();
@@ -23213,6 +24047,7 @@ function Shell(props) {
23213
24047
  const [workspaceContextAside, setWorkspaceContextAside] = createSignal(null);
23214
24048
  const planUsageAcc = props.orchestrator.planUsageSignal();
23215
24049
  const workspacePlanAside = createMemo(() => formatPlanUsageCompact(planUsageAcc()));
24050
+ const rcBridgeAcc = props.orchestrator.rcBridgeSignal();
23216
24051
  const [updateInfo, setUpdateInfo] = createSignal(null);
23217
24052
  onMount(() => {
23218
24053
  checkLatestVersion().then((info) => {
@@ -23303,6 +24138,20 @@ function Shell(props) {
23303
24138
  return;
23304
24139
  return parts.join(" \u2022 ");
23305
24140
  });
24141
+ const palette = useCommandPalette();
24142
+ onMount(() => {
24143
+ if (!(props.orchestrator instanceof RemoteOrchestrator))
24144
+ return;
24145
+ const orch = props.orchestrator;
24146
+ const unregister = palette.addCommand({
24147
+ name: "rcBridge.share",
24148
+ title: "Share to claude.ai (remote-control)",
24149
+ desc: "Bind this task's worktree to a claude.ai environment so you can resume the conversation from another device.",
24150
+ slashName: "share",
24151
+ run: () => RcBridgeDialog.show(dialog, orch, rcBridgeAcc, activeTask, activeChatTabIdAcc)
24152
+ });
24153
+ onCleanup(unregister);
24154
+ });
23306
24155
  let pendingPersistedId = persistedSelectedId ?? null;
23307
24156
  createEffect(() => {
23308
24157
  const tasks = tasksAcc();
@@ -23325,7 +24174,6 @@ function Shell(props) {
23325
24174
  });
23326
24175
  useKobeKeybindings({
23327
24176
  onShowHelp: () => HelpDialog.show(dialog),
23328
- onFocusDetach: () => setFocusedPane("sidebar"),
23329
24177
  onFocusNext: () => {
23330
24178
  if (focusedPane() !== "workspace")
23331
24179
  focus.cycle(1);
@@ -23400,6 +24248,7 @@ function Shell(props) {
23400
24248
  return props.orchestrator;
23401
24249
  },
23402
24250
  activeTask,
24251
+ activeChatTabId: activeChatTabIdAcc,
23403
24252
  updateInfo
23404
24253
  }), _el$2);
23405
24254
  insertNode(_el$2, _el$3);
@@ -23648,7 +24497,7 @@ async function startApp() {
23648
24497
  } of loadUserThemes()) {
23649
24498
  addTheme(name, theme);
23650
24499
  }
23651
- const homeDir2 = process.env.KOBE_HOME_DIR ?? homedir12();
24500
+ const homeDir2 = process.env.KOBE_HOME_DIR ?? homedir13();
23652
24501
  let orchestrator;
23653
24502
  if (process.env.KOBE_TEST_ENGINE || process.env.KOBE_NO_DAEMON === "1") {
23654
24503
  const engine3 = await buildEngine();
@@ -23715,6 +24564,7 @@ var init_app = __esm(() => {
23715
24564
  init_center_tab_strip();
23716
24565
  init_help_dialog();
23717
24566
  init_pane_header();
24567
+ init_rc_bridge_dialog();
23718
24568
  init_resizable_edge();
23719
24569
  init_status_bar();
23720
24570
  init_toast_overlay();