@narumitw/pi-subagents 3.4.1 → 3.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,147 @@
1
+ # @narumitw/pi-subagents
2
+
3
+ ## 3.4.3
4
+
5
+ ### Patch Changes
6
+
7
+ - cf7b63d: Put editor widget names and short current count/state summaries in their divider lines. Remove duplicate body titles while retaining safety text, detail rows, privacy modes, and standalone RPC/tool output. In fullscreen Pi, click anywhere in a widget to collapse it to one named line, then click that line to restore the latest content. Preserve independent, session-local disclosure through updates without taking editor focus, changing domain data, or stopping background work. Existing owner controls provide keyboard restoration; regular-mode mouse input remains terminal-owned.
8
+
9
+ The Kit minor release supplies the named widget state and publisher disclosure APIs. Changesets raises all adopting consumers' Kit dependency floors in the same Version PR. Publish and verify the exact Kit artifact before its consumers.
10
+ - Updated dependencies [cf7b63d]
11
+ - @narumitw/pi-tui-kit@0.70.0
12
+
13
+ ## 3.4.2
14
+
15
+ ### Patch Changes
16
+
17
+ - 54f2700: Preserve fullscreen viewport capture through custom list wrappers so default and configured paging keys reach the focused list. Keep native transcript search, unrelated overlays, free-text modes, paste, and hard cancellation unchanged. Filter Kit key hints according to each screen's capture policy.
18
+
19
+ Update Recall and File Context to the current Kit dependency range. The selected consumer releases require the fixed Kit patch through Changesets dependency-floor updates.
20
+ - e484010: Include the existing package-root CHANGELOG.md in extension tarballs so Pi can show native update notices. Keep Changesets version headings and Pi's first-observation and collapseChangelog behavior unchanged.
21
+ - 5120d4d: Preserve TypeBox enum inference for direct imports and Pi's extension loader without changing provider-visible schemas or validation rules. Import Notes schemas from TypeBox, declare its host-provided peer, and complete Worktree's command result contract for the updated Pi APIs.
22
+ - 51e74e1: Use the host-injected key formatter for completion and broker-message expansion hints. Omit hints when the action is unbound or the host does not supply renderer key formatting, while preserving expanded content and terminal sanitization.
23
+ - Updated dependencies [54f2700]
24
+ - Updated dependencies [6c76ef1]
25
+ - @narumitw/pi-tui-kit@0.69.0
26
+
27
+ ## 3.4.1
28
+
29
+ ### Patch Changes
30
+
31
+ - 5803891: Wake an idle main agent when a subagent job reaches a terminal state. Keep steering delivery for a running main agent and suppress stale completions after session replacement or shutdown.
32
+
33
+ ## 3.4.0
34
+
35
+ ### Minor Changes
36
+
37
+ - a21d39b: Add opt-in editor status presentation helpers for stable snapshot publication, session-local view controls, and bounded whole-snapshot collections. Keep the existing EditorStatusWidget API unchanged.
38
+
39
+ Retain visible Progress, Subagents, and Herdr widgets during updates. Add bounded summaries, manual view and item controls, and explicit one-shot compaction policies to Progress and Subagents without changing task state or persistent defaults. Preserve Progress completion retention and keep Herdr observation policies local. Keep tree navigation and manual context compaction separate from response-cycle tracking.
40
+ - 106ef89: Add optional `provider` and `model` parameters to `subagent_spawn`. Each omitted value inherits independently from the effective parent model at spawn time. Explicit IDs use exact matching without fallback, including listed case-distinct and provider-prefixed IDs. Only the child checks model registration and current availability. The requested pair bypasses CLI pattern matching and is bound exactly before the child receives its task. A missing or unavailable model fails the job after `subagent_spawn` returns its `jobId`.
41
+
42
+ Unlisted custom model IDs previously accepted through Pi's CLI now fail, including inherited IDs. Register each exact model in Pi's `models.json` or attach a trusted extension that registers it in the child. Parent-only providers, runtime API keys, and virtual routing state are not forwarded. Reload or replace the session after upgrading to load the new tool schema.
43
+
44
+ Reject oversized provider and model IDs before character validation. Schema bounds and runtime byte checks use the existing shared 16 KiB child-bootstrap limit without adding a shorter naming limit.
45
+
46
+ ### Patch Changes
47
+
48
+ - 1e33872: Use task-first widget rows and hide job IDs and tool names by default while preserving saved preferences. Show thinking only when it differs from the main agent's level captured at spawn. Omit redundant running labels and unset timeout text; show elapsed time for running jobs and queued status for waiting jobs.
49
+ - 99b7c92: Show provider and model IDs in expanded widget rows only when they differ from the main agent's effective values captured at spawn, matching thinking-level display. Keep inherited and explicit-equal values hidden, and preserve each job's comparison after parent model changes.
50
+ - Updated dependencies [a21d39b]
51
+ - Updated dependencies [f68aa54]
52
+ - Updated dependencies [b062d21]
53
+ - @narumitw/pi-tui-kit@0.68.0
54
+
55
+ ## 3.3.3
56
+
57
+ ### Patch Changes
58
+
59
+ - Updated dependencies [57eeae7]
60
+ - @narumitw/pi-tui-kit@0.67.0
61
+
62
+ ## 3.3.2
63
+
64
+ ### Patch Changes
65
+
66
+ - 168248c: Reuse published TUI Kit frame metadata, masked input, configured-key syntax, and interaction ownership while retaining extension-owned settings and cancellation policy. Keep malformed Ticker key strings from suppressing valid reorder shortcuts, and drain Usage settings saves after cancellation.
67
+
68
+ ## 3.3.1
69
+
70
+ ### Patch Changes
71
+
72
+ - 9edf94b: Show each active job’s spawn-time thinking level in the above-editor widget.
73
+
74
+ ## 3.3.0
75
+
76
+ ### Minor Changes
77
+
78
+ - 53730f9: Add the `/subagents` job manager and `/subagents settings` route. Support confirmed active-job cancellation and persistent widget, job ID, tool, and timing display preferences without changing model tools or job execution.
79
+
80
+ ### Patch Changes
81
+
82
+ - 9f80b89: Reuse published Kit interaction ownership for native Progress and Subagents settings while preserving ordered saves, rollback, and durable-save recovery after the screen closes.
83
+
84
+ Share passive widget framing in Subagents, Tool, Plan Mode, and Cache Hit Monitor. Keep domain rendering and lifecycle ownership local, bound narrow and invalid widths, and retain lazy loading of Kit menus and other interactive APIs.
85
+ - 3dd82ec: Add transcript expansion and collapse for child requests and responses using Pi's configured tool-output expansion key.
86
+ - Updated dependencies [077137a]
87
+ - Updated dependencies [9f80b89]
88
+ - Updated dependencies [efc474c]
89
+ - @narumitw/pi-tui-kit@0.66.0
90
+
91
+ ## 3.2.1
92
+
93
+ ### Patch Changes
94
+
95
+ - dfc020b: Show a sanitized, shortened preview of each active subagent's existing task in the TUI widget without changing the spawn schema or inspection metadata.
96
+
97
+ ## 3.2.0
98
+
99
+ ### Minor Changes
100
+
101
+ - ca27497: Allow subagent jobs to select Pi's native codemode tool explicitly, with startup readiness verification and unchanged default tools.
102
+
103
+ ## 3.1.1
104
+
105
+ ### Patch Changes
106
+
107
+ - 68c4b95: Update runtime dependencies and preserve Pi tool-context types through the LSP session lifecycle guard for compatibility with current Pi releases.
108
+
109
+ ## 3.1.0
110
+
111
+ ### Minor Changes
112
+
113
+ - aec9773: Allow each subagent job to attach validated local skills and trusted extensions with an attested initial tool allowlist.
114
+
115
+ ## 3.0.2
116
+
117
+ ### Patch Changes
118
+
119
+ - 8abd5b7: Keep generated extension runtime graphs inside Pi's Jiti-loaded TypeScript path to avoid duplicate peer-runtime evaluation during startup. Add measured generated runtimes for Context Management, Herdr, and TypeSafe Search.
120
+
121
+ ## 3.0.1
122
+
123
+ ### Patch Changes
124
+
125
+ - 99f0bcc: Start subagent jobs from Pi's bundled executable when the package manifest points to a source-only CLI path.
126
+
127
+ ## 3.0.0
128
+
129
+ ### Major Changes
130
+
131
+ - 99c304e: Replace the legacy orchestration runtime with subagent jobs and authenticated main-agent messaging.
132
+
133
+ Remove `/subagents`, extension settings, persisted and retained agents, the previous blocking orchestration interfaces, custom agent catalogs, advanced orchestration, alternate transports, trust-aware cwd policy, and extension-owned worktrees.
134
+
135
+ Use `subagent_spawn`, `subagent_inspect`, `subagent_cancel`, `subagent_wait`, and the context-specific main-agent and child `subagent_send` contracts directly or through a user-designed skill after upgrading, and start a fresh Pi session so stored calls do not request removed tool names or the legacy `subagent_send` schema.
136
+
137
+ Main agents can send requests to queued or running jobs, and children can send requests to main, while either side answers with the same request ID through `subagent_send`.
138
+
139
+ A queued main-agent request interrupts active child response waits without consuming the original child requests, so RPC steering can proceed and those waits can be retried.
140
+
141
+ The package no longer registers or publishes a delegation skill, while the repository keeps `using-pi-subagents` as an example for designing one.
142
+
143
+ Completion messages follow Pi's global tool-output expansion state and configured `app.tools.expand` binding.
144
+
145
+ ### Patch Changes
146
+
147
+ - e55825e: Update the repository-only example skill to require independent work or a concrete context-isolation benefit before delegating to a subagent.
package/README.md CHANGED
@@ -22,18 +22,19 @@ Pi Subagents runs Pi jobs in separate child processes and supports authenticated
22
22
 
23
23
  ## 📦 Install
24
24
 
25
- The version 3 runtime documented here is not yet published to npm.
26
- The npm package still contains the legacy 2.x runtime and does not provide the tools below.
27
-
28
- Install the repository source as one Pi package:
25
+ Install from npm:
29
26
 
30
27
  ```bash
31
- pi install git:github.com/narumiruna/pi-extensions
28
+ pi install npm:@narumitw/pi-subagents
32
29
  ```
33
30
 
34
- This Git installation enables every extension listed in the repository root manifest, including Pi Subagents.
31
+ Try it for one invocation:
35
32
 
36
- To install only Pi Subagents, clone the repository, install dependencies, build its generated runtime, and install its package directory:
33
+ ```bash
34
+ pi -e npm:@narumitw/pi-subagents
35
+ ```
36
+
37
+ To install from a local checkout, clone the repository, install dependencies, build its generated runtime, and install its package directory:
37
38
 
38
39
  ```bash
39
40
  git clone https://github.com/narumiruna/pi-extensions.git
@@ -73,8 +74,9 @@ Use messaging only when needed:
73
74
  - Answer a child-originated request by calling `subagent_send` with its `requestId`.
74
75
 
75
76
  Completion messages and child requests and responses follow Pi's global tool-output expansion state and the `app.tools.expand` binding (`Ctrl+O` by default).
76
- Collapsed messages show a summary and the configured expansion key; expanded messages show the full content.
77
- This display state does not change the content sent to the model.
77
+ Collapsed messages show a summary and the host's configured expansion keys.
78
+ The hint is omitted when the action is unbound or an older host does not supply renderer key formatting.
79
+ Expanded messages show the full content; this display state does not change the content sent to the model.
78
80
 
79
81
  ## 💬 Commands
80
82
 
@@ -93,7 +95,7 @@ The widget is TUI-only and contains only queued or running jobs. Each row starts
93
95
  For example, with a main-agent thinking level of `high` at spawn:
94
96
 
95
97
  ```text
96
- Subagents · 2 active
98
+ ─ ▾ Subagents · 1 running · 1 queued ───────
97
99
  ▶ Review widget tests · 12s
98
100
  ○ Audit settings · thinking: medium · queued
99
101
  ```
@@ -106,9 +108,13 @@ The task preview removes terminal controls, collapses whitespace, and uses at mo
106
108
  Task text is visible in this local widget, but `subagent_inspect` continues to omit it. Optional tool names include selected core and extension tools, not fixed communication tools.
107
109
  The widget omits attachment paths and resource totals, disappears when no jobs remain active, and clears when the session ends.
108
110
 
111
+ The separator shows **Subagents** and current running and queued counts, including while collapsed. In fullscreen TUI mode, click anywhere in the widget, including blank columns, to collapse it to that separator. Click the separator to restore the latest jobs without moving keyboard focus.
112
+ Disclosure survives job updates, temporary absence, and host remounts. Select a visible view in `/subagents` to restore disclosure with the keyboard. Session start and tree navigation reset it.
113
+ Collapse does not change jobs, settings, item views, pins, or automatic rules.
114
+
109
115
  Ordinary updates refresh the mounted widget without changing its position among other widgets. Hiding and showing it again can change that position.
110
116
  The widget uses at most ten rows, including one separator, and reserves eight terminal rows for the editor and footer. This is a local height limit, not a calculation of space left by other widgets.
111
- With fewer than two available rows it renders nothing. Short layouts use a summary with active, running, queued, and omitted-row counts. Narrow layouts clip each line to the terminal width.
117
+ With no available rows it renders nothing. One available row shows only the separator with current counts and omitted-row information. Summary view also uses only the separator, but does not count its intentionally absent job rows as omitted. Narrow layouts clip each line to the terminal width.
112
118
 
113
119
  In `/subagents`, **Widget view** provides details, summary, hide/show, pin/unpin, automatic compaction, and item-view reset controls.
114
120
  These controls are session-local and do not write settings. Manual hide remains in effect across job changes until you show the widget again.
@@ -108,6 +108,9 @@ async function showSubagentSettings(ctx, options) {
108
108
  () => complete("back")
109
109
  );
110
110
  return {
111
+ get capturesViewportInput() {
112
+ return list.capturesViewportInput;
113
+ },
111
114
  render(width) {
112
115
  if (!current()) complete("stale");
113
116
  renderedWidth = Number.isFinite(width) ? Math.max(0, Math.floor(width)) : 0;
@@ -182,4 +185,4 @@ async function showSubagentSettings(ctx, options) {
182
185
  export {
183
186
  showSubagentSettings
184
187
  };
185
- //# sourceMappingURL=settings-ui-24GHO6E2.ts.map
188
+ //# sourceMappingURL=settings-ui-KOX3DMZP.ts.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/settings-ui.ts"],
4
- "sourcesContent": ["import { stripVTControlCharacters } from \"node:util\";\nimport { type ExtensionCommandContext, getSettingsListTheme } from \"@earendil-works/pi-coding-agent\";\nimport { Key, matchesKey, type SettingItem, SettingsList, Text, type TuiMouseEvent } from \"@earendil-works/pi-tui\";\nimport {\n HorizontalRule,\n renderBoundedFrameLayout,\n runCustomInteraction,\n sanitizeTerminalText,\n} from \"@narumitw/pi-tui-kit\";\nimport type { SubagentSettings } from \"./settings.js\";\n\ninterface SubagentSettingsUIOptions {\n signal: AbortSignal;\n isCurrent(): boolean;\n get(): SubagentSettings;\n save(key: keyof SubagentSettings, value: boolean, signal: AbortSignal): Promise<SubagentSettings>;\n apply(settings: SubagentSettings): void;\n}\n\ntype CloseReason = \"back\" | \"close\" | \"stale\";\n\nconst SETTINGS: { key: keyof SubagentSettings; label: string; description: string }[] = [\n { key: \"showWidget\", label: \"Show widget\", description: \"Show subagent jobs above the editor.\" },\n { key: \"showJobId\", label: \"Show job ID\", description: \"Show job IDs in the widget.\" },\n { key: \"showTools\", label: \"Show tools\", description: \"Show active tools in the widget.\" },\n { key: \"showTiming\", label: \"Show timing\", description: \"Show job timing in the widget.\" },\n];\n\nexport async function showSubagentSettings(\n ctx: ExtensionCommandContext,\n options: SubagentSettingsUIOptions,\n): Promise<CloseReason> {\n const result = await runCustomInteraction<CloseReason>(ctx, {\n signal: options.signal,\n isCurrent: options.isCurrent,\n // The command owner reports interaction failures and non-TUI settings paths.\n onError: () => {},\n create({ tui, theme, signal, complete }) {\n let queue = Promise.resolve();\n const current = () => !signal.aborted && options.isCurrent();\n const revisions = new Map<string, number>();\n const pending = new Map<string, number>();\n const mouseRows = new Map<number, number>();\n let renderedWidth = 0;\n let contentHeight = 0;\n let mousePressed = false;\n const reportFailure = (message: string) => {\n if (!current()) return;\n try {\n ctx.ui.notify(sanitizeTerminalText(`Could not save pi-subagents.json: ${message}`), \"error\");\n } catch {\n // The host can dispose its notifier after the ownership check.\n }\n };\n const rule = new HorizontalRule({ ruleStyle: (text) => theme.fg(\"border\", text) });\n // Keep native SettingsList semantics, but use this screen's callback theme.\n const listTheme = {\n ...getSettingsListTheme(),\n label: (text: string, selected: boolean) => (selected ? theme.fg(\"accent\", text) : text),\n value: (text: string, selected: boolean) => theme.fg(selected ? \"accent\" : \"muted\", text),\n description: (text: string) => theme.fg(\"dim\", text),\n cursor: theme.fg(\"accent\", \"\u2192 \"),\n hint: (text: string) => theme.fg(\"dim\", text),\n };\n const initial = options.get();\n const items: SettingItem[] = SETTINGS.map(({ key, label, description }) => ({\n id: key,\n label,\n description,\n currentValue: String(initial[key]),\n values: [\"true\", \"false\"],\n }));\n const list = new SettingsList(\n items,\n items.length,\n listTheme,\n (id, value) => {\n if (!current()) return;\n const key = id as keyof SubagentSettings;\n const revision = (revisions.get(id) ?? 0) + 1;\n revisions.set(id, revision);\n pending.set(id, revision);\n queue = queue\n .then(async () => {\n if (!current()) {\n complete(\"stale\");\n return;\n }\n const before = { ...options.get() };\n let effective = before;\n try {\n const settings = await options.save(key, value === \"true\", signal);\n // A successful rename is durable, even when closing aborted the save signal.\n if (!options.isCurrent()) {\n complete(\"stale\");\n return;\n }\n options.apply(settings);\n effective = options.get();\n } catch (error) {\n if (!options.isCurrent()) {\n complete(\"stale\");\n return;\n }\n let message = error instanceof Error ? error.message : String(error);\n try {\n options.apply(before);\n } catch (rollbackError) {\n message += `; could not restore effective settings: ${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)}`;\n }\n reportFailure(message);\n }\n if (!current()) return;\n if (pending.get(id) === revision) pending.delete(id);\n // Saving rereads the full document, including unrelated manual edits. Keep newer\n // optimistic choices, but refresh every row with no outstanding user change.\n for (const { key: settingKey } of SETTINGS) {\n if (!pending.has(settingKey)) list.updateValue(settingKey, String(effective[settingKey]));\n }\n tui.requestRender();\n })\n .catch((error: unknown) => {\n // A failed action must not prevent later requests from entering the queue.\n reportFailure(error instanceof Error ? error.message : String(error));\n });\n },\n () => complete(\"back\"),\n );\n return {\n render(width: number) {\n if (!current()) complete(\"stale\");\n renderedWidth = Number.isFinite(width) ? Math.max(0, Math.floor(width)) : 0;\n listTheme.cursor = theme.fg(\"accent\", \"\u2192 \");\n // The native footer hardcodes keys. Advertise only the hard-cancel key owned here;\n // configured native navigation, change, and Back actions remain unchanged.\n const content = list.render(Math.max(4, renderedWidth)).slice(0, -2);\n contentHeight = content.length;\n const focusedRow = content.findIndex((line) => stripVTControlCharacters(line).startsWith(\"\u2192\"));\n mouseRows.clear();\n\n const terminalRows = Number.isFinite(tui.terminal.rows) ? Math.floor(tui.terminal.rows) : 24;\n const frame = renderBoundedFrameLayout({\n width: renderedWidth,\n maxRows: Math.max(1, terminalRows - 3),\n rule: rule.render(renderedWidth)[0] ?? \"\",\n title: new Text(theme.fg(\"accent\", theme.bold(\"Subagents Settings\")), 0, 0).render(renderedWidth),\n context: [theme.fg(\"muted\", \"Saved changes apply immediately.\")],\n content,\n hints: new Text(theme.fg(\"muted\", \"Ctrl+C close\"), 0, 0).render(renderedWidth),\n priorityRows: focusedRow < 0 ? [] : [focusedRow],\n focusedRow,\n });\n for (const { frameIndex, contentIndex } of frame.contentRows) mouseRows.set(frameIndex, contentIndex);\n return frame.lines;\n },\n invalidate() {\n mouseRows.clear();\n mousePressed = false;\n list.invalidate();\n },\n handleInput(data: string) {\n if (!current()) return complete(\"stale\");\n mouseRows.clear();\n mousePressed = false;\n if (matchesKey(data, Key.ctrl(\"c\"))) complete(\"close\");\n else {\n // SettingsList uses Pi's effective native keybindings for standard actions.\n list.handleInput(data);\n }\n tui.requestRender();\n },\n handleMouse(event: TuiMouseEvent) {\n if (!current()) {\n complete(\"stale\");\n return;\n }\n const nativeRow = mouseRows.get(event.y);\n if (nativeRow === undefined || event.x < 0 || event.x >= renderedWidth) {\n if (event.button === \"left\" && (event.type === \"press\" || event.type === \"click\")) mousePressed = false;\n return;\n }\n const nativeEvent = { ...event, y: nativeRow, width: renderedWidth, height: contentHeight };\n if (event.type === \"click\" && event.button === \"left\" && !mousePressed) {\n list.handleMouse({ ...nativeEvent, type: \"press\" });\n }\n const result = list.handleMouse(nativeEvent);\n if (event.type === \"press\" && event.button === \"left\") mousePressed = result?.handled === true;\n if (event.type === \"click\" || event.type === \"wheel\") mousePressed = false;\n if (result?.handled && result.render !== false) tui.requestRender();\n return result;\n },\n waitForPending() {\n return queue;\n },\n dispose() {\n mouseRows.clear();\n mousePressed = false;\n },\n };\n },\n });\n if (result.kind === \"error\") throw result.error;\n return result.kind === \"completed\" ? result.value : result.kind === \"unsupported\" ? \"back\" : \"stale\";\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { stripVTControlCharacters } from \"node:util\";\nimport { type ExtensionCommandContext, getSettingsListTheme } from \"@earendil-works/pi-coding-agent\";\nimport { Key, matchesKey, type SettingItem, SettingsList, Text, type TuiMouseEvent } from \"@earendil-works/pi-tui\";\nimport {\n HorizontalRule,\n renderBoundedFrameLayout,\n runCustomInteraction,\n sanitizeTerminalText,\n} from \"@narumitw/pi-tui-kit\";\nimport type { SubagentSettings } from \"./settings.js\";\n\ninterface SubagentSettingsUIOptions {\n signal: AbortSignal;\n isCurrent(): boolean;\n get(): SubagentSettings;\n save(key: keyof SubagentSettings, value: boolean, signal: AbortSignal): Promise<SubagentSettings>;\n apply(settings: SubagentSettings): void;\n}\n\ntype CloseReason = \"back\" | \"close\" | \"stale\";\n\nconst SETTINGS: { key: keyof SubagentSettings; label: string; description: string }[] = [\n { key: \"showWidget\", label: \"Show widget\", description: \"Show subagent jobs above the editor.\" },\n { key: \"showJobId\", label: \"Show job ID\", description: \"Show job IDs in the widget.\" },\n { key: \"showTools\", label: \"Show tools\", description: \"Show active tools in the widget.\" },\n { key: \"showTiming\", label: \"Show timing\", description: \"Show job timing in the widget.\" },\n];\n\nexport async function showSubagentSettings(\n ctx: ExtensionCommandContext,\n options: SubagentSettingsUIOptions,\n): Promise<CloseReason> {\n const result = await runCustomInteraction<CloseReason>(ctx, {\n signal: options.signal,\n isCurrent: options.isCurrent,\n // The command owner reports interaction failures and non-TUI settings paths.\n onError: () => {},\n create({ tui, theme, signal, complete }) {\n let queue = Promise.resolve();\n const current = () => !signal.aborted && options.isCurrent();\n const revisions = new Map<string, number>();\n const pending = new Map<string, number>();\n const mouseRows = new Map<number, number>();\n let renderedWidth = 0;\n let contentHeight = 0;\n let mousePressed = false;\n const reportFailure = (message: string) => {\n if (!current()) return;\n try {\n ctx.ui.notify(sanitizeTerminalText(`Could not save pi-subagents.json: ${message}`), \"error\");\n } catch {\n // The host can dispose its notifier after the ownership check.\n }\n };\n const rule = new HorizontalRule({ ruleStyle: (text) => theme.fg(\"border\", text) });\n // Keep native SettingsList semantics, but use this screen's callback theme.\n const listTheme = {\n ...getSettingsListTheme(),\n label: (text: string, selected: boolean) => (selected ? theme.fg(\"accent\", text) : text),\n value: (text: string, selected: boolean) => theme.fg(selected ? \"accent\" : \"muted\", text),\n description: (text: string) => theme.fg(\"dim\", text),\n cursor: theme.fg(\"accent\", \"\u2192 \"),\n hint: (text: string) => theme.fg(\"dim\", text),\n };\n const initial = options.get();\n const items: SettingItem[] = SETTINGS.map(({ key, label, description }) => ({\n id: key,\n label,\n description,\n currentValue: String(initial[key]),\n values: [\"true\", \"false\"],\n }));\n const list = new SettingsList(\n items,\n items.length,\n listTheme,\n (id, value) => {\n if (!current()) return;\n const key = id as keyof SubagentSettings;\n const revision = (revisions.get(id) ?? 0) + 1;\n revisions.set(id, revision);\n pending.set(id, revision);\n queue = queue\n .then(async () => {\n if (!current()) {\n complete(\"stale\");\n return;\n }\n const before = { ...options.get() };\n let effective = before;\n try {\n const settings = await options.save(key, value === \"true\", signal);\n // A successful rename is durable, even when closing aborted the save signal.\n if (!options.isCurrent()) {\n complete(\"stale\");\n return;\n }\n options.apply(settings);\n effective = options.get();\n } catch (error) {\n if (!options.isCurrent()) {\n complete(\"stale\");\n return;\n }\n let message = error instanceof Error ? error.message : String(error);\n try {\n options.apply(before);\n } catch (rollbackError) {\n message += `; could not restore effective settings: ${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)}`;\n }\n reportFailure(message);\n }\n if (!current()) return;\n if (pending.get(id) === revision) pending.delete(id);\n // Saving rereads the full document, including unrelated manual edits. Keep newer\n // optimistic choices, but refresh every row with no outstanding user change.\n for (const { key: settingKey } of SETTINGS) {\n if (!pending.has(settingKey)) list.updateValue(settingKey, String(effective[settingKey]));\n }\n tui.requestRender();\n })\n .catch((error: unknown) => {\n // A failed action must not prevent later requests from entering the queue.\n reportFailure(error instanceof Error ? error.message : String(error));\n });\n },\n () => complete(\"back\"),\n );\n return {\n get capturesViewportInput() {\n return list.capturesViewportInput;\n },\n render(width: number) {\n if (!current()) complete(\"stale\");\n renderedWidth = Number.isFinite(width) ? Math.max(0, Math.floor(width)) : 0;\n listTheme.cursor = theme.fg(\"accent\", \"\u2192 \");\n // The native footer hardcodes keys. Advertise only the hard-cancel key owned here;\n // configured native navigation, change, and Back actions remain unchanged.\n const content = list.render(Math.max(4, renderedWidth)).slice(0, -2);\n contentHeight = content.length;\n const focusedRow = content.findIndex((line) => stripVTControlCharacters(line).startsWith(\"\u2192\"));\n mouseRows.clear();\n\n const terminalRows = Number.isFinite(tui.terminal.rows) ? Math.floor(tui.terminal.rows) : 24;\n const frame = renderBoundedFrameLayout({\n width: renderedWidth,\n maxRows: Math.max(1, terminalRows - 3),\n rule: rule.render(renderedWidth)[0] ?? \"\",\n title: new Text(theme.fg(\"accent\", theme.bold(\"Subagents Settings\")), 0, 0).render(renderedWidth),\n context: [theme.fg(\"muted\", \"Saved changes apply immediately.\")],\n content,\n hints: new Text(theme.fg(\"muted\", \"Ctrl+C close\"), 0, 0).render(renderedWidth),\n priorityRows: focusedRow < 0 ? [] : [focusedRow],\n focusedRow,\n });\n for (const { frameIndex, contentIndex } of frame.contentRows) mouseRows.set(frameIndex, contentIndex);\n return frame.lines;\n },\n invalidate() {\n mouseRows.clear();\n mousePressed = false;\n list.invalidate();\n },\n handleInput(data: string) {\n if (!current()) return complete(\"stale\");\n mouseRows.clear();\n mousePressed = false;\n if (matchesKey(data, Key.ctrl(\"c\"))) complete(\"close\");\n else {\n // SettingsList uses Pi's effective native keybindings for standard actions.\n list.handleInput(data);\n }\n tui.requestRender();\n },\n handleMouse(event: TuiMouseEvent) {\n if (!current()) {\n complete(\"stale\");\n return;\n }\n const nativeRow = mouseRows.get(event.y);\n if (nativeRow === undefined || event.x < 0 || event.x >= renderedWidth) {\n if (event.button === \"left\" && (event.type === \"press\" || event.type === \"click\")) mousePressed = false;\n return;\n }\n const nativeEvent = { ...event, y: nativeRow, width: renderedWidth, height: contentHeight };\n if (event.type === \"click\" && event.button === \"left\" && !mousePressed) {\n list.handleMouse({ ...nativeEvent, type: \"press\" });\n }\n const result = list.handleMouse(nativeEvent);\n if (event.type === \"press\" && event.button === \"left\") mousePressed = result?.handled === true;\n if (event.type === \"click\" || event.type === \"wheel\") mousePressed = false;\n if (result?.handled && result.render !== false) tui.requestRender();\n return result;\n },\n waitForPending() {\n return queue;\n },\n dispose() {\n mouseRows.clear();\n mousePressed = false;\n },\n };\n },\n });\n if (result.kind === \"error\") throw result.error;\n return result.kind === \"completed\" ? result.value : result.kind === \"unsupported\" ? \"back\" : \"stale\";\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["result"]
7
7
  }
package/dist/index.ts CHANGED
@@ -53,7 +53,7 @@ function sanitizeSubagentDisplayText(value) {
53
53
  }
54
54
 
55
55
  // src/message-renderers.ts
56
- import { getMarkdownTheme, keyText } from "@earendil-works/pi-coding-agent";
56
+ import { getMarkdownTheme } from "@earendil-works/pi-coding-agent";
57
57
  import { Box, Markdown, Spacer, Text } from "@earendil-works/pi-tui";
58
58
  var COMPLETION_MESSAGE_TYPE = "pi-subagents-completion";
59
59
  var BROKER_MESSAGE_TYPE = "pi-subagents-message";
@@ -82,13 +82,9 @@ function registerMessageRenderers(pi) {
82
82
  new Spacer(1)
83
83
  ];
84
84
  if (!options.expanded) {
85
- children.push(
86
- new Text(
87
- theme.fg("customMessageText", `${summary} (`) + theme.fg("dim", keyText("app.tools.expand")) + theme.fg("customMessageText", " to expand)"),
88
- 0,
89
- 0
90
- )
91
- );
85
+ const expansionKey = options.keyText?.("app.tools.expand");
86
+ const hint = expansionKey ? theme.fg("muted", ` (${expansionKey} to expand)`) : "";
87
+ children.push(new Text(theme.fg("customMessageText", summary) + hint, 0, 0));
92
88
  } else {
93
89
  const content = typeof message.content === "string" ? message.content : message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
94
90
  children.push(
@@ -2258,9 +2254,11 @@ var SpawnParameters = Type.Object(
2258
2254
  ),
2259
2255
  tools: Type.Optional(
2260
2256
  Type.Array(
2261
- StringEnum(CHILD_CORE_TOOL_NAMES, {
2262
- description: "Available Pi core child work tool name."
2263
- }),
2257
+ Type.Unsafe(
2258
+ StringEnum(CHILD_CORE_TOOL_NAMES, {
2259
+ description: "Available Pi core child work tool name."
2260
+ })
2261
+ ),
2264
2262
  {
2265
2263
  description: "Child work tools. Defaults to read, grep, find, and ls. Communication tools are always added.",
2266
2264
  maxItems: MAX_TOOLS
@@ -2310,9 +2308,11 @@ var SpawnParameters = Type.Object(
2310
2308
  )
2311
2309
  ),
2312
2310
  thinkingLevel: Type.Optional(
2313
- StringEnum(SUBAGENT_THINKING_LEVELS, {
2314
- description: "Child thinking level. Defaults to the main agent's effective level."
2315
- })
2311
+ Type.Unsafe(
2312
+ StringEnum(SUBAGENT_THINKING_LEVELS, {
2313
+ description: "Child thinking level. Defaults to the main agent's effective level."
2314
+ })
2315
+ )
2316
2316
  ),
2317
2317
  timeout: Type.Optional(Type.Number({ description: "Timeout in seconds (optional, no default timeout)" }))
2318
2318
  },
@@ -2663,10 +2663,34 @@ var SUBAGENT_WIDGET_MAX_ROWS = 10;
2663
2663
  function subagentWidgetRowBudget(rows) {
2664
2664
  return Number.isFinite(rows) ? Math.min(SUBAGENT_WIDGET_MAX_ROWS, Math.max(0, Math.floor(rows) - SUBAGENT_WIDGET_RESERVED_ROWS)) : 0;
2665
2665
  }
2666
- function renderSubagentWidgetSnapshot(snapshot, theme, width, maxRows) {
2666
+ function subagentWidgetSummary(snapshot, maxRows) {
2667
+ const { jobs, items, mode } = snapshot;
2668
+ const budget = normalizeRowBudget(maxRows);
2669
+ if (!isVisible(snapshot) || budget === 0) return "";
2670
+ const shown = mode === "compact" ? items.length : Math.min(items.length, budget - 1);
2671
+ const omitted = jobs.length - shown;
2672
+ const removed = jobs.length - items.length;
2673
+ const running = jobs.filter((job) => job.state === "running").length;
2674
+ const counts = `${running} running \xB7 ${jobs.length - running} queued`;
2675
+ return `${counts}${omitted > 0 ? ` \xB7 ${omitted} not shown${removed > 0 ? ` (${removed} removed)` : ""}` : ""}`;
2676
+ }
2677
+ function normalizeRowBudget(maxRows) {
2678
+ return Number.isFinite(maxRows) ? Math.max(0, Math.floor(maxRows)) : 0;
2679
+ }
2680
+ function isVisible({ jobs, items, settings, mode }) {
2681
+ return settings.showWidget && mode !== "hidden" && jobs.length > 0 && items.length > 0;
2682
+ }
2683
+ function renderSubagentWidgetSnapshot(snapshot, theme, width, maxRows, includeHeader = true) {
2667
2684
  const { jobs, items, settings, mode } = snapshot;
2668
- const budget = Number.isFinite(maxRows) ? Math.max(0, Math.floor(maxRows)) : 0;
2669
- if (!settings.showWidget || mode === "hidden" || jobs.length === 0 || items.length === 0 || budget < 2) return [];
2685
+ const budget = normalizeRowBudget(maxRows);
2686
+ if (!isVisible(snapshot) || budget < (includeHeader ? 2 : 1)) return [];
2687
+ if (!includeHeader) {
2688
+ const shown = mode === "compact" ? [] : items.slice(0, budget - 1);
2689
+ return new EditorStatusWidget({
2690
+ theme,
2691
+ renderBody: () => shown.map(({ value, mode: itemMode }) => renderJob(value, theme, settings, itemMode === "compact"))
2692
+ }).render(width);
2693
+ }
2670
2694
  const running = jobs.filter((job) => job.state === "running").length;
2671
2695
  const counts = `Subagents \xB7 ${jobs.length} active \xB7 ${running} running \xB7 ${jobs.length - running} queued`;
2672
2696
  const removed = jobs.length - items.length;
@@ -2842,9 +2866,11 @@ function createSubagentWidgetController(runtime) {
2842
2866
  view = createEditorStatusView({ onChange: publish, canCompact: () => settings.showWidget && jobs.length > 0 });
2843
2867
  publisher = createEditorStatusPublisher({
2844
2868
  key: SUBAGENT_WIDGET_KEY,
2869
+ name: "Subagents",
2845
2870
  context: ctx,
2846
2871
  isCurrent,
2847
- render: (snapshot, theme, width, rows) => renderSubagentWidgetSnapshot(snapshot, theme, width, subagentWidgetRowBudget(rows))
2872
+ summary: (snapshot, _width, rows) => subagentWidgetSummary(snapshot, subagentWidgetRowBudget(rows)),
2873
+ render: (snapshot, theme, width, rows) => renderSubagentWidgetSnapshot(snapshot, theme, width, subagentWidgetRowBudget(rows), false)
2848
2874
  });
2849
2875
  if (phase === "maintenance") cyclePhase = phase;
2850
2876
  else if (phase !== "idle") startCycle(phase);
@@ -2853,7 +2879,9 @@ function createSubagentWidgetController(runtime) {
2853
2879
  controls = {
2854
2880
  state: () => ({ mode: ownedView.mode, pinned: ownedView.pinned, trigger: ownedView.trigger }),
2855
2881
  setMode: (mode) => {
2856
- if (isCurrent()) ownedView.setMode(mode);
2882
+ if (!isCurrent()) return;
2883
+ if (mode !== "hidden") publisher?.setCollapsed(false);
2884
+ ownedView.setMode(mode);
2857
2885
  },
2858
2886
  setPinned: (pinned) => {
2859
2887
  if (isCurrent()) ownedView.setPinned(pinned);
@@ -2973,7 +3001,7 @@ function subagents(pi, dependencies = {}) {
2973
3001
  ctx.ui.notify(sanitizeSubagentDisplayText(`Edit user settings: ${store.userPath}. Then run /reload.`), "info");
2974
3002
  return "back";
2975
3003
  }
2976
- const { showSubagentSettings } = await import("./chunks/settings-ui-24GHO6E2.ts");
3004
+ const { showSubagentSettings } = await import("./chunks/settings-ui-KOX3DMZP.ts");
2977
3005
  if (signal.aborted || !isCurrent()) return "stale";
2978
3006
  return showSubagentSettings(ctx, {
2979
3007
  signal,