@leanandmean/coding-agent 0.74.1-scramjet.32 → 0.74.1-scramjet.33

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.
@@ -891,7 +891,7 @@ UI methods for user interaction. See [Custom UI](#custom-ui) for full details.
891
891
 
892
892
  ### ctx.hasUI
893
893
 
894
- `false` in print mode (`-p`) and JSON mode. `true` in interactive and RPC mode. In RPC mode, dialog methods (`select`, `confirm`, `input`, `editor`) work via the extension UI sub-protocol, and fire-and-forget methods (`notify`, `setStatus`, `setWidget`, `setTitle`, `setEditorText`) emit requests to the client. Some TUI-specific methods are no-ops or return defaults (see [rpc.md](rpc.md#extension-ui-protocol)).
894
+ `false` in print mode (`-p`) and JSON mode. `true` in interactive and RPC mode. This is a transport-level signal, not a guarantee that every UI method is supported. In RPC mode, dialog methods (`select`, `confirm`, `input`, `editor`) work via the extension UI sub-protocol, and fire-and-forget methods (`notify`, `setStatus`, `setWidget`, `setTitle`, `setEditorText`) emit requests to the client, but TUI-only `custom()` resolves `undefined`. Other TUI-specific methods are no-ops or return defaults (see [rpc.md](rpc.md#extension-ui-protocol)). Extensions that require a specific UI method must handle that method's documented unsupported result.
895
895
 
896
896
  ### ctx.cwd
897
897
 
@@ -1529,10 +1529,17 @@ if (pi.getFlag("plan")) {
1529
1529
  Execute a shell command.
1530
1530
 
1531
1531
  ```typescript
1532
- const result = await pi.exec("git", ["status"], { signal, timeout: 5000 });
1533
- // result.stdout, result.stderr, result.code, result.killed
1532
+ const result = await pi.exec("gh", ["api", "--method", "POST", "--input", "-", endpoint], {
1533
+ signal,
1534
+ timeout: 5000,
1535
+ stdin: JSON.stringify(payload),
1536
+ });
1537
+ // result.stdout, result.stderr, result.code, result.killed,
1538
+ // result.spawnError, result.stdinError, result.stdoutError, result.stderrError
1534
1539
  ```
1535
1540
 
1541
+ When `stdin` is supplied, `pi.exec` writes that exact UTF-8 string once and closes standard input without adding a newline. `spawnError` is present only when the command failed before spawning; `stdinError` reports a write or close failure; `stdoutError` and `stderrError` report output-pipe failures after spawn. Each error contains a safe `message` and optional system `code`, never stdin or process output content. Once the child has spawned, callers must use command-specific semantics to decide whether a failed execution may have produced side effects.
1542
+
1536
1543
  ### pi.getActiveTools() / pi.getAllTools() / pi.setActiveTools(names)
1537
1544
 
1538
1545
  Manage active tools. This works for both built-in tools and dynamically registered tools.
@@ -2423,6 +2430,22 @@ The callback receives:
2423
2430
  - `keybindings` - App keybinding manager (for checking shortcuts)
2424
2431
  - `done(value)` - Call to close component and return value
2425
2432
 
2433
+ A pending sequential tool can attach immutable long-form context to its own tool row before compact controls become interactive. Pass the current `toolCallId` from the tool's `execute()` method:
2434
+
2435
+ ```typescript
2436
+ const result = await ctx.ui.custom(
2437
+ (_tui, _theme, _keybindings, done) => new ApprovalSelector(done),
2438
+ {
2439
+ toolAttachedContext: {
2440
+ toolCallId,
2441
+ render: (_tui, theme) => new Text(theme.fg("muted", completeContext), 0, 0),
2442
+ },
2443
+ },
2444
+ );
2445
+ ```
2446
+
2447
+ The context is rendered at that pending tool's transcript position, the editor is defocused, and the context is committed once and flushed before its controls receive focus. The complete context is emitted to native terminal scrollback; retention depends on terminal capacity and configuration. It is visual-only and is not persisted or sent to the model. The call fails closed if the named tool row is absent or no longer pending. Use this only from the sequential tool whose id is supplied; ordinary custom UIs remain live and terminal-height bounded.
2448
+
2426
2449
  See [tui.md](tui.md) for the full component API.
2427
2450
 
2428
2451
  #### Overlay Mode (Experimental)
@@ -2577,7 +2600,7 @@ const highlighted = highlightCode(code, lang, theme);
2577
2600
  | Mode | UI Methods | Notes |
2578
2601
  |------|-----------|-------|
2579
2602
  | Interactive | Full TUI | Normal operation |
2580
- | RPC (`--mode rpc`) | JSON protocol | Host handles UI, see [rpc.md](rpc.md) |
2603
+ | RPC (`--mode rpc`) | JSON protocol | Host handles supported UI methods; TUI-only `custom()` resolves `undefined`, see [rpc.md](rpc.md) |
2581
2604
  | JSON (`--mode json`) | No-op | Event stream to stdout, see [json.md](json.md) |
2582
2605
  | Print (`-p`) | No-op | Extensions run but can't prompt |
2583
2606
 
package/docs/tui.md CHANGED
@@ -14,7 +14,7 @@ The interactive mode separates terminal output into append-only committed histor
14
14
 
15
15
  Mutable output is tail-windowed to at most `terminal.rows - 1` rendered lines before it is written, so live content cannot push mutable rows into native scrollback. Finalization removes the mutable preview and commits the component's finalized presentation once. Pending tools form an ordering barrier, and image-backed tools commit only after their conversions settle.
16
16
 
17
- At the TUI API level, `setLiveRegionStart(component)` selects the first direct child in the live canvas, `commit()` atomically appends newly finalized rows, and `rebuild()` deliberately repaints retained history. Detaching the selected component safely resets committed rendering and returns the TUI to legacy full-repaint rendering. Routine updates, content shrink, temporary-UI dismissal, and height-only resize do not clear scrollback or replay committed history. Width and theme changes, session reconstruction, presentation-setting changes, reload, resume, and external-editor return use deliberate rebuilds because retained output must be reflowed or restyled; those rebuilds intentionally bottom-anchor the display.
17
+ At the TUI API level, `setLiveRegionStart(component)` selects the first direct child in the live canvas, `commit()` schedules atomic append of newly finalized rows, `commitNow()` renders immediately and waits for terminal output to flush when controls must not receive input first, and `rebuild()` deliberately repaints retained history. Detaching the selected component safely resets committed rendering and returns the TUI to legacy full-repaint rendering. Routine updates, content shrink, temporary-UI dismissal, and height-only resize do not clear scrollback or replay committed history. Width and theme changes, session reconstruction, presentation-setting changes, reload, resume, and external-editor return use deliberate rebuilds because retained output must be reflowed or restyled; those rebuilds intentionally bottom-anchor the display.
18
18
 
19
19
  Overlays remain screen-relative and are composed over the bounded live canvas. Closing an overlay or autocomplete restores the underlying live rows without mutating committed history.
20
20
 
@@ -108,16 +108,33 @@ pi.on("session_start", async (_event, ctx) => {
108
108
  });
109
109
  ```
110
110
 
111
- **In custom tools** via `pi.ui.custom()`:
111
+ **In custom tools** via `ctx.ui.custom()`:
112
112
 
113
113
  ```typescript
114
114
  async execute(toolCallId, params, onUpdate, ctx, signal) {
115
- const handle = pi.ui.custom(myComponent);
115
+ const result = await ctx.ui.custom((_tui, _theme, _keybindings, done) => myComponent(done));
116
116
  // ...
117
- handle.close();
118
117
  }
119
118
  ```
120
119
 
120
+ ### Tool-attached committed context
121
+
122
+ A pending sequential tool can pair compact live controls with immutable long-form context committed at that tool's transcript position:
123
+
124
+ ```typescript
125
+ const result = await ctx.ui.custom(
126
+ (_tui, _theme, _keybindings, done) => new ApprovalSelector(done),
127
+ {
128
+ toolAttachedContext: {
129
+ toolCallId,
130
+ render: (_tui, theme) => new Markdown(completePayload, 0, 0, getMarkdownTheme()),
131
+ },
132
+ },
133
+ );
134
+ ```
135
+
136
+ The context is constructed after the controls factory resolves, anchored to the named pending tool row, and committed once. The editor is defocused before terminal flushing begins; controls receive focus only after that flush settles. It is retained internally for deliberate width/theme rebuilds but is not persisted or sent to the model. Native scrollback retention depends on terminal capacity and configuration. The operation fails closed when the row is missing, settled, or cannot be flushed; use it only from the sequential tool identified by `toolCallId`.
137
+
121
138
  ## Overlays
122
139
 
123
140
  Overlays render components on top of existing content without clearing the screen. Pass `{ overlay: true }` to `ctx.ui.custom()`:
@@ -722,6 +739,8 @@ pi.registerCommand("settings", {
722
739
  container.addChild(settingsList);
723
740
 
724
741
  return {
742
+ get focused() { return settingsList.focused; },
743
+ set focused(value) { settingsList.focused = value; },
725
744
  render: (w) => container.render(w),
726
745
  invalidate: () => container.invalidate(),
727
746
  handleInput: (data) => settingsList.handleInput?.(data),
@@ -731,6 +750,8 @@ pi.registerCommand("settings", {
731
750
  });
732
751
  ```
733
752
 
753
+ With `enableSearch`, typing fuzzy-filters labels, Backspace edits the query, and Up/Down plus Enter/Space navigate and activate matches. `SettingsList` propagates focus to its search input and nested focusable submenus for IME cursor placement; a wrapper returned from `ctx.ui.custom()` must forward `focused` as shown above.
754
+
734
755
  **Examples:** [tools.ts](../examples/extensions/tools.ts)
735
756
 
736
757
  ### Pattern 4: Persistent Status Indicator
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leanandmean/coding-agent",
3
- "version": "0.74.1-scramjet.32",
3
+ "version": "0.74.1-scramjet.33",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -35,7 +35,7 @@
35
35
  "dependencies": {
36
36
  "@leanandmean/agent": "0.74.1-scramjet.15",
37
37
  "@leanandmean/ai": "0.74.1-scramjet.11",
38
- "@leanandmean/tui": "0.74.1-scramjet.9",
38
+ "@leanandmean/tui": "0.74.1-scramjet.10",
39
39
  "@silvia-odwyer/photon-node": "^0.3.4",
40
40
  "chalk": "^5.5.0",
41
41
  "dictionary-en": "^4.0.0",