@gotgenes/pi-subagents 18.0.1 → 18.0.2
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 +7 -0
- package/docs/architecture/architecture.md +157 -204
- package/docs/architecture/history/phase-19-implement-ui-decisions.md +282 -0
- package/package.json +5 -6
- package/src/lifecycle/subagent.ts +5 -9
- package/src/observation/notification.ts +23 -10
- package/src/observation/subagent-events-observer.ts +1 -3
- package/src/tools/get-result-report.ts +60 -0
- package/src/tools/get-result-tool.ts +25 -40
- package/src/types.ts +1 -1
- package/src/ui/session-navigator.ts +0 -2
- package/.prettierignore +0 -5
- package/AGENTS.md +0 -7
- package/docs/plans/0048-implement-subagents-api.md +0 -304
- package/docs/plans/0049-remove-group-join-output-file-rpc.md +0 -180
- package/docs/plans/0051-update-adr-0001-hard-fork.md +0 -77
- package/docs/plans/0052-remove-scheduled-subagents.md +0 -133
- package/docs/plans/0053-extract-model-resolution-from-execute.md +0 -181
- package/docs/plans/0054-decompose-index-into-modules.md +0 -302
- package/docs/plans/0057-structured-debug-logging.md +0 -154
- package/docs/plans/0061-session-format-transcript.md +0 -284
- package/docs/plans/0066-replace-as-any-with-sdk-types.md +0 -215
- package/docs/plans/0069-create-subagent-runtime.md +0 -345
- package/docs/plans/0070-extract-event-handlers.md +0 -306
- package/docs/plans/0071-extract-session-config-assembler.md +0 -362
- package/docs/plans/0072-inject-agent-manager-collaborators.md +0 -329
- package/docs/plans/0076-inject-cwd-into-agent-manager.md +0 -102
- package/docs/plans/0077-inject-project-agents-dir.md +0 -115
- package/docs/plans/0080-consolidate-agent-config-lookup.md +0 -247
- package/docs/plans/0084-extract-git-worktree-manager.md +0 -142
- package/docs/plans/0087-evolve-subagent-runtime-methods.md +0 -240
- package/docs/plans/0098-extract-agent-record-state-machine.md +0 -435
- package/docs/plans/0099-replace-ctx-with-parent-snapshot.md +0 -488
- package/docs/plans/0100-replace-callback-threading-with-session-subscription.md +0 -454
- package/docs/plans/0102-consolidate-test-record-factory.md +0 -176
- package/docs/plans/0108-extract-agent-type-registry.md +0 -322
- package/docs/plans/0109-extract-settings-manager.md +0 -276
- package/docs/plans/0110-agent-activity-tracker.md +0 -297
- package/docs/plans/0111-split-agent-record-lifecycle.md +0 -582
- package/docs/plans/0112-replace-agent-manager-callbacks.md +0 -241
- package/docs/plans/0113-disambiguate-spawn-options.md +0 -155
- package/docs/plans/0114-narrow-agent-tool-menu-deps.md +0 -279
- package/docs/plans/0115-decompose-agent-tool.md +0 -337
- package/docs/plans/0116-type-housekeeping.md +0 -351
- package/docs/plans/0118-settings-manager-apply-methods.md +0 -271
- package/docs/plans/0123-remove-vi-fn-cast-smell.md +0 -179
- package/docs/plans/0131-consolidate-shared-test-fixtures.md +0 -207
- package/docs/plans/0132-inject-io-into-session-config.md +0 -219
- package/docs/plans/0133-inject-sdk-boundary-into-agent-runner.md +0 -373
- package/docs/plans/0134-reduce-as-any-casts.md +0 -366
- package/docs/plans/0135-extract-display-helpers.md +0 -182
- package/docs/plans/0136-decompose-agent-menu.md +0 -300
- package/docs/plans/0144-consolidate-observation-model.md +0 -263
- package/docs/plans/0145-decompose-execute-push-ctx-to-boundary.md +0 -290
- package/docs/plans/0146-narrow-ui-context.md +0 -319
- package/docs/plans/0147-inject-wrap-text-into-conversation-viewer.md +0 -166
- package/docs/plans/0148-split-agent-widget-rendering.md +0 -255
- package/docs/plans/0152-add-prompt-snippet.md +0 -91
- package/docs/plans/0164-reorganize-into-domain-directories.md +0 -409
- package/docs/plans/0165-decompose-resolved-spawn-config.md +0 -157
- package/docs/plans/0166-extract-parent-session-info.md +0 -231
- package/docs/plans/0167-narrow-runner-io.md +0 -150
- package/docs/plans/0168-extract-tool-filter-config.md +0 -173
- package/docs/plans/0169-extract-run-context-from-run-options.md +0 -194
- package/docs/plans/0170-reduce-build-content-lines-complexity.md +0 -225
- package/docs/plans/0171-reduce-render-result-complexity.md +0 -200
- package/docs/plans/0172-extract-turn-formatting.md +0 -206
- package/docs/plans/0180-reorder-append-prompt-for-kv-cache.md +0 -100
- package/docs/plans/0185-remove-persistent-agent-memory.md +0 -161
- package/docs/plans/0188-replace-any-casts-with-sdk-types.md +0 -162
- package/docs/plans/0192-define-session-context-interface.md +0 -107
- package/docs/plans/0193-runtime-owns-context-queries.md +0 -245
- package/docs/plans/0194-align-tool-interfaces-for-structural-typing.md +0 -139
- package/docs/plans/0195-convert-tool-factories-to-classes.md +0 -264
- package/docs/plans/0196-convert-runner-menu-to-classes.md +0 -268
- package/docs/plans/0205-decompose-render-widget-lines.md +0 -140
- package/docs/plans/0206-decompose-show-agent-detail.md +0 -211
- package/docs/plans/0207-decompose-agent-widget-update.md +0 -242
- package/docs/plans/0208-extract-shared-test-fixtures.md +0 -298
- package/docs/plans/0214-convert-remaining-closure-factories-to-classes.md +0 -261
- package/docs/plans/0215-decompose-build-parent-context.md +0 -166
- package/docs/plans/0216-decompose-start-agent.md +0 -255
- package/docs/plans/0217-extract-overwrite-guard.md +0 -176
- package/docs/plans/0218-push-sdk-boundary-in-settings.md +0 -172
- package/docs/plans/0219-reduce-test-duplication-top-3-clone-families.md +0 -162
- package/docs/plans/0227-evolve-agent-record-into-agent.md +0 -322
- package/docs/plans/0228-async-start-agent-dissolve-run-handle.md +0 -288
- package/docs/plans/0229-agent-born-complete.md +0 -564
- package/docs/plans/0230-extract-concurrency-queue.md +0 -265
- package/docs/plans/0231-push-exec-registry-to-runner.md +0 -245
- package/docs/plans/0232-agent-resume-internal-observer-lifecycle.md +0 -180
- package/docs/plans/0237-remove-disallowed-tools.md +0 -180
- package/docs/plans/0238-remove-extensions-filtering.md +0 -191
- package/docs/plans/0239-collapse-filter-active-tools.md +0 -217
- package/docs/plans/0242-rename-agent-tool-to-subagent.md +0 -165
- package/docs/plans/0256-extract-worktree-isolation.md +0 -256
- package/docs/plans/0257-extract-child-session-factory.md +0 -285
- package/docs/plans/0262-add-workspace-provider-seam.md +0 -264
- package/docs/plans/0264-remove-extension-lifecycle-control.md +0 -277
- package/docs/plans/0265-born-complete-subagent-session.md +0 -333
- package/docs/plans/0270-type-consumable-public-surface.md +0 -204
- package/docs/plans/0272-export-workspace-collaborator-types.md +0 -147
- package/docs/plans/0277-encapsulate-agent-session.md +0 -304
- package/docs/plans/0280-rename-agent-to-subagent.md +0 -197
- package/docs/plans/0360-custom-agents-default-append.md +0 -132
- package/docs/plans/0373-extract-subagent-state.md +0 -250
- package/docs/plans/0374-encapsulate-subagent-start-notification.md +0 -268
- package/docs/plans/0375-extract-run-listener-workspace-bracket.md +0 -300
- package/docs/plans/0376-extract-manager-observer.md +0 -232
- package/docs/plans/0377-split-widget-delegation-from-runtime.md +0 -254
- package/docs/plans/0378-consolidate-lifecycle-test-fixtures.md +0 -243
- package/docs/plans/0379-consolidate-ui-tools-test-fixtures.md +0 -335
- package/docs/plans/0380-extract-layered-settings-loader.md +0 -223
- package/docs/plans/0381-replace-concurrency-queue-with-limiter.md +0 -267
- package/docs/plans/0400-include-parent-prompt-in-replace-mode.md +0 -199
- package/docs/plans/0403-abort-subagents-on-interrupt.md +0 -180
- package/docs/plans/0412-unify-session-mock-builders.md +0 -146
- package/docs/plans/0420-fold-run-metrics-live-activity-onto-record.md +0 -228
- package/docs/plans/0421-migrate-activity-readers-to-record-getters.md +0 -309
- package/docs/plans/0422-delete-activity-tracker-ui-observer.md +0 -204
- package/docs/plans/0423-widget-self-drive-from-lifecycle.md +0 -264
- package/docs/plans/0424-drop-widget-dep-from-subagent-tool.md +0 -166
- package/docs/plans/0425-reconcile-subagent-events-contract.md +0 -144
- package/docs/plans/0426-consolidate-residual-test-clone-families.md +0 -235
- package/docs/plans/0427-reconsider-ui-direction.md +0 -212
- package/docs/plans/0441-remove-agent-definition-management-subtree.md +0 -180
- package/docs/plans/0442-dissolve-agents-conversation-viewer.md +0 -195
- package/docs/plans/0443-consolidate-remaining-test-clone-families.md +0 -268
- package/docs/plans/0444-shrink-widget-to-background-agents.md +0 -156
- package/docs/plans/0445-native-session-navigation.md +0 -365
- package/docs/plans/0446-spike-session-navigation-entry-criteria.md +0 -171
- package/docs/plans/0447-extract-subagents-settings-command.md +0 -220
- package/docs/plans/0448-block-disabled-agent-spawn.md +0 -207
- package/docs/plans/0462-navigation-renderer-tui-components.md +0 -338
- package/docs/plans/0463-file-snapshot-source-evicted-agents.md +0 -306
- package/docs/plans/0470-refresh-readme-command-surface.md +0 -159
- package/docs/retro/0048-implement-subagents-api.md +0 -44
- package/docs/retro/0049-remove-group-join-output-file-rpc.md +0 -49
- package/docs/retro/0051-update-adr-0001-hard-fork.md +0 -39
- package/docs/retro/0053-extract-model-resolution-from-execute.md +0 -40
- package/docs/retro/0054-decompose-index-into-modules.md +0 -53
- package/docs/retro/0057-structured-debug-logging.md +0 -77
- package/docs/retro/0061-session-format-transcript.md +0 -41
- package/docs/retro/0066-replace-as-any-with-sdk-types.md +0 -44
- package/docs/retro/0069-create-subagent-runtime.md +0 -43
- package/docs/retro/0070-extract-event-handlers.md +0 -49
- package/docs/retro/0071-extract-session-config-assembler.md +0 -60
- package/docs/retro/0072-inject-agent-manager-collaborators.md +0 -46
- package/docs/retro/0076-inject-cwd-into-agent-manager.md +0 -35
- package/docs/retro/0077-inject-project-agents-dir.md +0 -33
- package/docs/retro/0080-consolidate-agent-config-lookup.md +0 -35
- package/docs/retro/0084-extract-git-worktree-manager.md +0 -37
- package/docs/retro/0087-evolve-subagent-runtime-methods.md +0 -42
- package/docs/retro/0098-extract-agent-record-state-machine.md +0 -46
- package/docs/retro/0099-replace-ctx-with-parent-snapshot.md +0 -37
- package/docs/retro/0100-replace-callback-threading-with-session-subscription.md +0 -36
- package/docs/retro/0102-consolidate-test-record-factory.md +0 -30
- package/docs/retro/0108-extract-agent-type-registry.md +0 -41
- package/docs/retro/0109-extract-settings-manager.md +0 -55
- package/docs/retro/0110-agent-activity-tracker.md +0 -44
- package/docs/retro/0111-split-agent-record-lifecycle.md +0 -61
- package/docs/retro/0112-replace-agent-manager-callbacks.md +0 -35
- package/docs/retro/0113-disambiguate-spawn-options.md +0 -29
- package/docs/retro/0114-narrow-agent-tool-menu-deps.md +0 -38
- package/docs/retro/0115-decompose-agent-tool.md +0 -51
- package/docs/retro/0116-type-housekeeping.md +0 -42
- package/docs/retro/0118-settings-manager-apply-methods.md +0 -40
- package/docs/retro/0123-remove-vi-fn-cast-smell.md +0 -49
- package/docs/retro/0131-consolidate-shared-test-fixtures.md +0 -46
- package/docs/retro/0132-inject-io-into-session-config.md +0 -33
- package/docs/retro/0133-inject-sdk-boundary-into-agent-runner.md +0 -45
- package/docs/retro/0134-reduce-as-any-casts.md +0 -56
- package/docs/retro/0135-extract-display-helpers.md +0 -38
- package/docs/retro/0136-decompose-agent-menu.md +0 -43
- package/docs/retro/0144-consolidate-observation-model.md +0 -39
- package/docs/retro/0145-decompose-execute-push-ctx-to-boundary.md +0 -56
- package/docs/retro/0146-narrow-ui-context.md +0 -70
- package/docs/retro/0147-inject-wrap-text-into-conversation-viewer.md +0 -90
- package/docs/retro/0148-split-agent-widget-rendering.md +0 -39
- package/docs/retro/0152-add-prompt-snippet.md +0 -34
- package/docs/retro/0164-reorganize-into-domain-directories.md +0 -82
- package/docs/retro/0165-decompose-resolved-spawn-config.md +0 -78
- package/docs/retro/0166-extract-parent-session-info.md +0 -66
- package/docs/retro/0167-narrow-runner-io.md +0 -63
- package/docs/retro/0168-extract-tool-filter-config.md +0 -76
- package/docs/retro/0169-extract-run-context-from-run-options.md +0 -68
- package/docs/retro/0170-reduce-build-content-lines-complexity.md +0 -72
- package/docs/retro/0171-reduce-render-result-complexity.md +0 -77
- package/docs/retro/0172-extract-turn-formatting.md +0 -80
- package/docs/retro/0180-reorder-append-prompt-for-kv-cache.md +0 -62
- package/docs/retro/0185-remove-persistent-agent-memory.md +0 -73
- package/docs/retro/0188-replace-any-casts-with-sdk-types.md +0 -69
- package/docs/retro/0192-define-session-context-interface.md +0 -59
- package/docs/retro/0193-runtime-owns-context-queries.md +0 -75
- package/docs/retro/0194-align-tool-interfaces-for-structural-typing.md +0 -62
- package/docs/retro/0195-convert-tool-factories-to-classes.md +0 -84
- package/docs/retro/0196-convert-runner-menu-to-classes.md +0 -73
- package/docs/retro/0205-decompose-render-widget-lines.md +0 -64
- package/docs/retro/0206-decompose-show-agent-detail.md +0 -67
- package/docs/retro/0207-decompose-agent-widget-update.md +0 -92
- package/docs/retro/0208-extract-shared-test-fixtures.md +0 -102
- package/docs/retro/0214-convert-remaining-closure-factories-to-classes.md +0 -66
- package/docs/retro/0215-decompose-build-parent-context.md +0 -61
- package/docs/retro/0216-decompose-start-agent.md +0 -80
- package/docs/retro/0217-extract-overwrite-guard.md +0 -63
- package/docs/retro/0218-push-sdk-boundary-in-settings.md +0 -72
- package/docs/retro/0219-reduce-test-duplication-top-3-clone-families.md +0 -64
- package/docs/retro/0227-evolve-agent-record-into-agent.md +0 -80
- package/docs/retro/0228-async-start-agent-dissolve-run-handle.md +0 -80
- package/docs/retro/0229-agent-born-complete.md +0 -89
- package/docs/retro/0230-extract-concurrency-queue.md +0 -38
- package/docs/retro/0231-push-exec-registry-to-runner.md +0 -71
- package/docs/retro/0232-agent-resume-internal-observer-lifecycle.md +0 -109
- package/docs/retro/0237-remove-disallowed-tools.md +0 -78
- package/docs/retro/0238-remove-extensions-filtering.md +0 -72
- package/docs/retro/0239-collapse-filter-active-tools.md +0 -70
- package/docs/retro/0242-rename-agent-tool-to-subagent.md +0 -82
- package/docs/retro/0256-extract-worktree-isolation.md +0 -89
- package/docs/retro/0257-extract-child-session-factory.md +0 -33
- package/docs/retro/0262-add-workspace-provider-seam.md +0 -89
- package/docs/retro/0264-remove-extension-lifecycle-control.md +0 -91
- package/docs/retro/0265-born-complete-subagent-session.md +0 -97
- package/docs/retro/0270-type-consumable-public-surface.md +0 -108
- package/docs/retro/0272-export-workspace-collaborator-types.md +0 -38
- package/docs/retro/0277-encapsulate-agent-session.md +0 -80
- package/docs/retro/0280-rename-agent-to-subagent.md +0 -96
- package/docs/retro/0360-custom-agents-default-append.md +0 -81
- package/docs/retro/0373-extract-subagent-state.md +0 -94
- package/docs/retro/0374-encapsulate-subagent-start-notification.md +0 -171
- package/docs/retro/0375-extract-run-listener-workspace-bracket.md +0 -104
- package/docs/retro/0376-extract-manager-observer.md +0 -81
- package/docs/retro/0377-split-widget-delegation-from-runtime.md +0 -105
- package/docs/retro/0378-consolidate-lifecycle-test-fixtures.md +0 -100
- package/docs/retro/0379-consolidate-ui-tools-test-fixtures.md +0 -52
- package/docs/retro/0380-extract-layered-settings-loader.md +0 -97
- package/docs/retro/0381-replace-concurrency-queue-with-limiter.md +0 -95
- package/docs/retro/0400-include-parent-prompt-in-replace-mode.md +0 -84
- package/docs/retro/0403-abort-subagents-on-interrupt.md +0 -90
- package/docs/retro/0412-unify-session-mock-builders.md +0 -80
- package/docs/retro/0420-fold-run-metrics-live-activity-onto-record.md +0 -90
- package/docs/retro/0421-migrate-activity-readers-to-record-getters.md +0 -105
- package/docs/retro/0422-delete-activity-tracker-ui-observer.md +0 -97
- package/docs/retro/0423-widget-self-drive-from-lifecycle.md +0 -112
- package/docs/retro/0424-drop-widget-dep-from-subagent-tool.md +0 -89
- package/docs/retro/0425-reconcile-subagent-events-contract.md +0 -101
- package/docs/retro/0426-consolidate-residual-test-clone-families.md +0 -100
- package/docs/retro/0427-reconsider-ui-direction.md +0 -102
- package/docs/retro/0441-remove-agent-definition-management-subtree.md +0 -97
- package/docs/retro/0442-dissolve-agents-conversation-viewer.md +0 -108
- package/docs/retro/0443-consolidate-remaining-test-clone-families.md +0 -28
- package/docs/retro/0444-shrink-widget-to-background-agents.md +0 -81
- package/docs/retro/0445-native-session-navigation.md +0 -122
- package/docs/retro/0446-spike-session-navigation-entry-criteria.md +0 -99
- package/docs/retro/0447-extract-subagents-settings-command.md +0 -91
- package/docs/retro/0448-block-disabled-agent-spawn.md +0 -75
- package/docs/retro/0462-navigation-renderer-tui-components.md +0 -105
- package/docs/retro/0463-file-snapshot-source-evicted-agents.md +0 -103
- package/docs/retro/0470-refresh-readme-command-surface.md +0 -40
- package/src/observation/notification-state.ts +0 -27
- package/vitest.config.ts +0 -14
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
issue: 147
|
|
3
|
-
issue_title: "Inject text wrapping into ConversationViewer (Phase 9, Step O)"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Inject text wrapping into ConversationViewer
|
|
7
|
-
|
|
8
|
-
## Problem Statement
|
|
9
|
-
|
|
10
|
-
`ConversationViewer` calls `wrapTextWithAnsi` directly from `@earendil-works/pi-tui` in four places inside `buildContentLines`.
|
|
11
|
-
Because the function is a module-level binding, tests must intercept it via a hoisted `vi.mock("@earendil-works/pi-tui")` factory that replaces the entire TUI module.
|
|
12
|
-
This is the last `vi.mock` on an SDK module in the test suite, added specifically to exercise the overwidth-clamping safety net.
|
|
13
|
-
|
|
14
|
-
## Goals
|
|
15
|
-
|
|
16
|
-
- Accept `wrapText: (text: string, width: number) => string[]` via `ConversationViewerOptions`.
|
|
17
|
-
- Destructure `ConversationViewerOptions` in the constructor signature (dependency bag convention).
|
|
18
|
-
- Replace all four `wrapTextWithAnsi` calls in `buildContentLines` with `this.wrapText`.
|
|
19
|
-
- Remove `wrapTextWithAnsi` from `conversation-viewer.ts`'s `@earendil-works/pi-tui` import.
|
|
20
|
-
- Pass `wrapTextWithAnsi` at the production call site in `agent-menu.ts`.
|
|
21
|
-
- Eliminate the hoisted `vi.mock("@earendil-works/pi-tui")` from `conversation-viewer.test.ts`.
|
|
22
|
-
|
|
23
|
-
## Non-Goals
|
|
24
|
-
|
|
25
|
-
- Injecting `truncateToWidth` or any other TUI function (only `wrapTextWithAnsi` is relevant here).
|
|
26
|
-
- Changing the overwidth-clamping behavior of `buildContentLines`.
|
|
27
|
-
- Touching `agent-widget.ts` (tracked separately as Issue #148, Step P — already closed).
|
|
28
|
-
|
|
29
|
-
## Background
|
|
30
|
-
|
|
31
|
-
`ui/conversation-viewer.ts` is the live conversation overlay rendered when a user selects an agent in the `/agents` menu.
|
|
32
|
-
Its `buildContentLines` method formats messages from the agent session into displayable lines, calling `wrapTextWithAnsi` to soft-wrap text to the available terminal width.
|
|
33
|
-
|
|
34
|
-
The overwidth-clamping safety net (`truncateToWidth` applied after `wrapTextWithAnsi`) exists because a prior upstream bug returned lines wider than the requested width.
|
|
35
|
-
The `vi.mock` in the test is the mechanism for simulating that bug by returning overwidth strings from `wrapTextWithAnsi`.
|
|
36
|
-
|
|
37
|
-
The only production call site for `new ConversationViewer(...)` is in the `viewAgentConversation` closure inside `createAgentsMenuHandler` in `ui/agent-menu.ts`.
|
|
38
|
-
|
|
39
|
-
Architecture reference: `docs/architecture/architecture.md` § Phase 9, Step O.
|
|
40
|
-
|
|
41
|
-
## Design Overview
|
|
42
|
-
|
|
43
|
-
### `ConversationViewerOptions` — add `wrapText`
|
|
44
|
-
|
|
45
|
-
```typescript
|
|
46
|
-
export interface ConversationViewerOptions {
|
|
47
|
-
tui: TUI;
|
|
48
|
-
session: AgentSession;
|
|
49
|
-
record: AgentRecord;
|
|
50
|
-
activity: AgentActivityTracker | undefined;
|
|
51
|
-
theme: Theme;
|
|
52
|
-
done: (result: undefined) => void;
|
|
53
|
-
registry: AgentConfigLookup;
|
|
54
|
-
wrapText: (text: string, width: number) => string[];
|
|
55
|
-
}
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
The field is **required** — it must be supplied at every construction site.
|
|
59
|
-
No default is provided; the default would be an invisible SDK dependency hidden inside the class.
|
|
60
|
-
|
|
61
|
-
### Constructor destructuring
|
|
62
|
-
|
|
63
|
-
The constructor adopts the dependency bag convention — destructure the options object rather than accessing via `options.*`:
|
|
64
|
-
|
|
65
|
-
```typescript
|
|
66
|
-
constructor({
|
|
67
|
-
tui, session, record, activity, theme, done, registry, wrapText,
|
|
68
|
-
}: ConversationViewerOptions) {
|
|
69
|
-
this.tui = tui;
|
|
70
|
-
this.session = session;
|
|
71
|
-
// … etc.
|
|
72
|
-
this.wrapText = wrapText;
|
|
73
|
-
this.unsubscribe = session.subscribe(() => { … });
|
|
74
|
-
}
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### Production wiring — `agent-menu.ts`
|
|
78
|
-
|
|
79
|
-
`agent-menu.ts` statically imports `wrapTextWithAnsi` from `@earendil-works/pi-tui` and passes it when constructing `ConversationViewer`:
|
|
80
|
-
|
|
81
|
-
```typescript
|
|
82
|
-
import { wrapTextWithAnsi } from "@earendil-works/pi-tui";
|
|
83
|
-
// …
|
|
84
|
-
return new ConversationViewer({
|
|
85
|
-
tui, session, record, activity, theme, done, registry,
|
|
86
|
-
wrapText: wrapTextWithAnsi,
|
|
87
|
-
});
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
Adding `wrapText` to `AgentMenuDeps` and threading it through the closure would violate the Law of Demeter — `AgentMenuDeps` has no conceptual ownership of a text-wrapping function.
|
|
91
|
-
The `viewAgentConversation` closure is the direct consumer; the import belongs there.
|
|
92
|
-
|
|
93
|
-
### Test strategy
|
|
94
|
-
|
|
95
|
-
After DI, tests pass `wrapText` directly in `ConversationViewerOptions`:
|
|
96
|
-
|
|
97
|
-
- **"render width safety" tests**: pass `wrapText: wrapTextWithAnsi` (real function, statically imported — no mock).
|
|
98
|
-
- **"safety net" tests**: pass a stub `wrapText: () => ["X".repeat(width + 50)]` inline in options — no `vi.mock` needed.
|
|
99
|
-
- The "mock is intercepting wrapTextWithAnsi" test is removed (it verified the mock mechanism, not viewer behavior).
|
|
100
|
-
- The module-level `wrapOverride` variable and the `vi.mock` block are removed entirely.
|
|
101
|
-
- The `await import("@earendil-works/pi-tui")` and `await import("../src/ui/conversation-viewer.js")` dynamic imports are converted to ordinary top-level `import` statements.
|
|
102
|
-
|
|
103
|
-
## Module-Level Changes
|
|
104
|
-
|
|
105
|
-
| File | Change |
|
|
106
|
-
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
107
|
-
| `src/ui/conversation-viewer.ts` | Add `wrapText` field to `ConversationViewerOptions`; add `private wrapText` field; destructure options in constructor; replace 4× `wrapTextWithAnsi(...)` with `this.wrapText(...)`; remove `wrapTextWithAnsi` from the `@earendil-works/pi-tui` import line |
|
|
108
|
-
| `src/ui/agent-menu.ts` | Add `import { wrapTextWithAnsi } from "@earendil-works/pi-tui"`; pass `wrapText: wrapTextWithAnsi` in `viewAgentConversation` |
|
|
109
|
-
| `test/conversation-viewer.test.ts` | Convert top-level dynamic `await import()` to static imports; remove `vi.mock`, `wrapOverride`, and "mock is intercepting" test; add `wrapText` to every `new ConversationViewer({…})` call; update safety-net tests to pass inline stub `wrapText` |
|
|
110
|
-
|
|
111
|
-
No symbols are removed from exported API (`ConversationViewerOptions`, `ConversationViewer`, `VIEWPORT_HEIGHT_PCT` all remain).
|
|
112
|
-
The `wrapText` addition to `ConversationViewerOptions` is a breaking change for any external consumers that construct `ConversationViewer` — check for usages outside this package.
|
|
113
|
-
|
|
114
|
-
Grep check: `ConversationViewer` appears only in `src/ui/conversation-viewer.ts`, `src/ui/agent-menu.ts`, and `test/conversation-viewer.test.ts` — no other files construct it.
|
|
115
|
-
|
|
116
|
-
## Test Impact Analysis
|
|
117
|
-
|
|
118
|
-
1. **New unit-test capability**: The safety-net tests can now inject exactly the stub they need without patching a module.
|
|
119
|
-
Each test is self-contained and immediately legible — the stub is declared inline at the call site.
|
|
120
|
-
|
|
121
|
-
2. **Tests that become redundant**: The "mock is intercepting wrapTextWithAnsi" test verified the test mechanism, not production behavior.
|
|
122
|
-
It is deleted.
|
|
123
|
-
The `wrapOverride` reset in `beforeEach` is no longer needed.
|
|
124
|
-
|
|
125
|
-
3. **Tests that stay**: All "render width safety" tests and all overwidth-clamping tests remain; they exercise real viewer behavior with real or controlled inputs.
|
|
126
|
-
|
|
127
|
-
## TDD Order
|
|
128
|
-
|
|
129
|
-
### Cycle 1 — Add `wrapText` field and update production wiring
|
|
130
|
-
|
|
131
|
-
1. **Red**: Update one `new ConversationViewer({…})` in the test to include `wrapText: vi.fn()` — TypeScript rejects the unknown field.
|
|
132
|
-
2. **Green**:
|
|
133
|
-
- Add `wrapText: (text: string, width: number) => string[]` to `ConversationViewerOptions`.
|
|
134
|
-
- Add `private wrapText: (text: string, width: number) => string[]` field to the class.
|
|
135
|
-
- Destructure options in the constructor; assign `this.wrapText = wrapText`.
|
|
136
|
-
- Replace all four `wrapTextWithAnsi(...)` calls with `this.wrapText(...)` in `buildContentLines`.
|
|
137
|
-
- Remove `wrapTextWithAnsi` from the `@earendil-works/pi-tui` import in `conversation-viewer.ts`.
|
|
138
|
-
- In `agent-menu.ts`: add static import of `wrapTextWithAnsi` from `@earendil-works/pi-tui`; pass `wrapText: wrapTextWithAnsi`.
|
|
139
|
-
- Update **all** `new ConversationViewer({…})` calls in `conversation-viewer.test.ts` to include `wrapText`.
|
|
140
|
-
"Render width safety" tests pass `wrapText: wrapTextWithAnsi` (real function, still imported via the existing `vi.mock` shim for now).
|
|
141
|
-
Safety-net tests pass a stub inline: `wrapText: () => ["X".repeat(w + 50)]`.
|
|
142
|
-
- Delete the "mock is intercepting wrapTextWithAnsi" test.
|
|
143
|
-
3. **Verify**: `pnpm vitest run test/conversation-viewer.test.ts` passes.
|
|
144
|
-
4. **Commit**: `feat: inject wrapText into ConversationViewer (Phase 9, Step O) (#147)`
|
|
145
|
-
|
|
146
|
-
### Cycle 2 — Remove the module mock
|
|
147
|
-
|
|
148
|
-
1. **Red**: Remove the `vi.mock("@earendil-works/pi-tui", …)` block, the `wrapOverride` variable, and the `beforeEach(() => { wrapOverride = null; })` reset.
|
|
149
|
-
Convert `const { visibleWidth } = await import("@earendil-works/pi-tui")` to `import { visibleWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui"`.
|
|
150
|
-
Convert `const { ConversationViewer } = await import("../src/ui/conversation-viewer.js")` to `import { ConversationViewer } from "../src/ui/conversation-viewer.js"`.
|
|
151
|
-
Run tests — they should still pass (the mock was no longer needed after Cycle 1).
|
|
152
|
-
2. **Green**: Tests pass without any module mock.
|
|
153
|
-
3. **Verify**: `pnpm vitest run test/conversation-viewer.test.ts` and `pnpm run check` both pass.
|
|
154
|
-
4. **Commit**: `refactor: remove vi.mock from conversation-viewer tests (#147)`
|
|
155
|
-
|
|
156
|
-
## Risks and Mitigations
|
|
157
|
-
|
|
158
|
-
| Risk | Mitigation |
|
|
159
|
-
| --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
160
|
-
| Missing a `new ConversationViewer({…})` call site in tests | Grep confirms only `test/conversation-viewer.test.ts` constructs the viewer; all instances are in-file |
|
|
161
|
-
| TypeScript missing the `private wrapText` field type | Use `pnpm run check` after Cycle 1 to verify no type errors |
|
|
162
|
-
| The dynamic `await import()` pattern in tests was necessary for some other reason | The only purpose was to run after `vi.mock` hoisting; once the mock is gone, static imports work fine |
|
|
163
|
-
|
|
164
|
-
## Open Questions
|
|
165
|
-
|
|
166
|
-
None — the issue's "Changes" section is unambiguous and the call-site inventory is small.
|
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
issue: 148
|
|
3
|
-
issue_title: "Split AgentWidget rendering from lifecycle (Phase 9, Step P)"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Split AgentWidget rendering from lifecycle
|
|
7
|
-
|
|
8
|
-
## Problem Statement
|
|
9
|
-
|
|
10
|
-
`AgentWidget` (374 lines) mixes rendering, lifecycle management, spinner animation, state filtering, and status bar management in a single class.
|
|
11
|
-
`renderWidget` alone is ~109 lines, and `renderFinishedLine` adds another ~40.
|
|
12
|
-
The constructor takes 3 concrete collaborators (`AgentManager`, `Map<string, AgentActivityTracker>`, `AgentTypeRegistry`) with no interface extraction.
|
|
13
|
-
Rendering logic cannot be unit-tested without instantiating the full widget with its lifecycle machinery.
|
|
14
|
-
|
|
15
|
-
## Goals
|
|
16
|
-
|
|
17
|
-
- Extract pure rendering functions from `AgentWidget` into `ui/widget-renderer.ts`.
|
|
18
|
-
- Make `AgentWidget` a thin lifecycle/polling wrapper that delegates to pure render functions.
|
|
19
|
-
- Enable direct unit testing of rendering logic with plain data — no widget lifecycle, no mocks for `setInterval`/`setWidget`/`requestRender`.
|
|
20
|
-
|
|
21
|
-
## Non-Goals
|
|
22
|
-
|
|
23
|
-
- Changing the visual output of the widget (this is a pure refactor).
|
|
24
|
-
- Extracting the status bar logic into a separate module (could follow up).
|
|
25
|
-
- Narrowing the `AgentManager` dependency to an interface (tracked separately in the architecture doc).
|
|
26
|
-
- Injecting `truncateToWidth` (tracked as #147, Step O — an independent track).
|
|
27
|
-
|
|
28
|
-
## Background
|
|
29
|
-
|
|
30
|
-
### Dependency: #144 (Step L) — Consolidate observation model
|
|
31
|
-
|
|
32
|
-
Issue #144 is **closed/implemented**.
|
|
33
|
-
The renderer now reads stats (`toolUses`, `lifetimeUsage`, `compactionCount`) from `AgentRecord` and live UI state (`activeTools`, `responseText`, `turnCount`, `maxTurns`) from `AgentActivityTracker`.
|
|
34
|
-
No dual-counting fallback exists.
|
|
35
|
-
|
|
36
|
-
### Existing pure helpers
|
|
37
|
-
|
|
38
|
-
`ui/display.ts` already contains stateless formatting functions (`formatMs`, `formatTurns`, `formatSessionTokens`, `describeActivity`, `getDisplayName`, `getPromptModeLabel`, `SPINNER`, `ERROR_STATUSES`, `Theme`).
|
|
39
|
-
The new `widget-renderer.ts` will consume these — it does not duplicate them.
|
|
40
|
-
|
|
41
|
-
### Rendering data flow
|
|
42
|
-
|
|
43
|
-
The widget's `renderWidget` currently:
|
|
44
|
-
|
|
45
|
-
1. Calls `this.manager.listAgents()` to get `AgentRecord[]`.
|
|
46
|
-
2. Categorizes into running/queued/finished.
|
|
47
|
-
3. Filters finished agents via `this.shouldShowFinished()`.
|
|
48
|
-
4. Looks up `this.agentActivity.get(a.id)` for live stats.
|
|
49
|
-
5. Calls `this.registry` for display names.
|
|
50
|
-
6. Reads `this.widgetFrame` for spinner animation.
|
|
51
|
-
7. Assembles tree-style lines with overflow logic.
|
|
52
|
-
|
|
53
|
-
Steps 3–7 are pure given the right inputs.
|
|
54
|
-
Steps 1–2 are also pure categorization.
|
|
55
|
-
|
|
56
|
-
## Design Overview
|
|
57
|
-
|
|
58
|
-
### Separation of concerns
|
|
59
|
-
|
|
60
|
-
The rendering extraction splits the widget into two layers:
|
|
61
|
-
|
|
62
|
-
1. **`widget-renderer.ts`** — Pure functions that accept data and return `string[]`.
|
|
63
|
-
No `this`, no timers, no SDK types, no side effects.
|
|
64
|
-
2. **`agent-widget.ts`** — Thin lifecycle wrapper that owns timers, UICtx, finished-turn aging, and calls the renderer with live data.
|
|
65
|
-
|
|
66
|
-
### Renderer input shape
|
|
67
|
-
|
|
68
|
-
Rather than passing the full `AgentRecord` class (which carries mutation methods and phase collaborators), the renderer receives a plain data slice:
|
|
69
|
-
|
|
70
|
-
```typescript
|
|
71
|
-
/** Minimal agent snapshot for rendering — no class methods, no mutation surface. */
|
|
72
|
-
export interface WidgetAgent {
|
|
73
|
-
readonly id: string;
|
|
74
|
-
readonly type: SubagentType;
|
|
75
|
-
readonly status: string;
|
|
76
|
-
readonly description: string;
|
|
77
|
-
readonly toolUses: number;
|
|
78
|
-
readonly startedAt: number;
|
|
79
|
-
readonly completedAt?: number;
|
|
80
|
-
readonly error?: string;
|
|
81
|
-
readonly lifetimeUsage?: Readonly<LifetimeUsage>;
|
|
82
|
-
readonly compactionCount: number;
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
This is structurally compatible with `AgentRecord` (the class satisfies it), so no mapping code is needed at the call site — `listAgents()` returns `AgentRecord[]` which satisfies `WidgetAgent[]`.
|
|
87
|
-
|
|
88
|
-
### Renderer input for activity
|
|
89
|
-
|
|
90
|
-
Activity state is read from `AgentActivityTracker`.
|
|
91
|
-
The renderer needs a read-only view per agent:
|
|
92
|
-
|
|
93
|
-
```typescript
|
|
94
|
-
/** Read-only activity snapshot for widget rendering. */
|
|
95
|
-
export interface WidgetActivity {
|
|
96
|
-
readonly activeTools: ReadonlyMap<string, string>;
|
|
97
|
-
readonly responseText: string;
|
|
98
|
-
readonly turnCount: number;
|
|
99
|
-
readonly maxTurns?: number;
|
|
100
|
-
readonly session?: SessionLike;
|
|
101
|
-
}
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
`AgentActivityTracker` already satisfies this structurally (it exposes these as getters).
|
|
105
|
-
|
|
106
|
-
### Agent config lookup
|
|
107
|
-
|
|
108
|
-
The renderer needs `getDisplayName` and `getPromptModeLabel`, which take a `SubagentType` and an `AgentConfigLookup`.
|
|
109
|
-
The renderer accepts `AgentConfigLookup` (the existing interface from `agent-types.ts`) — not the concrete `AgentTypeRegistry` class.
|
|
110
|
-
|
|
111
|
-
### Renderer API
|
|
112
|
-
|
|
113
|
-
```typescript
|
|
114
|
-
/** Pure rendering of the widget body. Returns lines to display. */
|
|
115
|
-
export function renderWidgetLines(params: {
|
|
116
|
-
agents: readonly WidgetAgent[];
|
|
117
|
-
activityMap: ReadonlyMap<string, WidgetActivity>;
|
|
118
|
-
registry: AgentConfigLookup;
|
|
119
|
-
spinnerFrame: number;
|
|
120
|
-
terminalWidth: number;
|
|
121
|
-
shouldShowFinished: (agentId: string, status: string) => boolean;
|
|
122
|
-
}): string[];
|
|
123
|
-
|
|
124
|
-
/** Pure rendering of a single finished agent line (no tree connector prefix). */
|
|
125
|
-
export function renderFinishedLine(
|
|
126
|
-
agent: WidgetAgent,
|
|
127
|
-
activity: WidgetActivity | undefined,
|
|
128
|
-
registry: AgentConfigLookup,
|
|
129
|
-
theme: Theme,
|
|
130
|
-
): string;
|
|
131
|
-
|
|
132
|
-
/** Pure rendering of a single running agent (header + activity lines, no tree connector prefix). */
|
|
133
|
-
export function renderRunningLines(
|
|
134
|
-
agent: WidgetAgent,
|
|
135
|
-
activity: WidgetActivity | undefined,
|
|
136
|
-
registry: AgentConfigLookup,
|
|
137
|
-
spinnerFrame: number,
|
|
138
|
-
theme: Theme,
|
|
139
|
-
): [header: string, activity: string];
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
The top-level `renderWidgetLines` encapsulates the full categorization, overflow logic, and tree-connector fixup.
|
|
143
|
-
The per-agent functions are exported for fine-grained testing.
|
|
144
|
-
|
|
145
|
-
The `shouldShowFinished` callback is injected rather than re-implementing the aging logic inside the renderer, keeping the renderer pure and the aging state in the widget.
|
|
146
|
-
|
|
147
|
-
### Call site in AgentWidget
|
|
148
|
-
|
|
149
|
-
```typescript
|
|
150
|
-
// Inside renderWidget(tui, theme):
|
|
151
|
-
const w = tui.terminal.columns;
|
|
152
|
-
return renderWidgetLines({
|
|
153
|
-
agents: this.manager.listAgents(),
|
|
154
|
-
activityMap: this.agentActivity,
|
|
155
|
-
registry: this.registry,
|
|
156
|
-
spinnerFrame: this.widgetFrame,
|
|
157
|
-
terminalWidth: w,
|
|
158
|
-
shouldShowFinished: (id, status) => this.shouldShowFinished(id, status),
|
|
159
|
-
});
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
The widget's `renderWidget` method shrinks to ~5 lines.
|
|
163
|
-
|
|
164
|
-
### Tell-Don't-Ask verification
|
|
165
|
-
|
|
166
|
-
The renderer receives pre-collected data and returns formatted strings.
|
|
167
|
-
It does not reach through collaborators — it reads flat fields from `WidgetAgent` and `WidgetActivity`.
|
|
168
|
-
The widget tells the renderer "render this data"; the renderer returns lines.
|
|
169
|
-
No Law of Demeter violations.
|
|
170
|
-
|
|
171
|
-
## Module-Level Changes
|
|
172
|
-
|
|
173
|
-
### New file: `src/ui/widget-renderer.ts`
|
|
174
|
-
|
|
175
|
-
- `WidgetAgent` interface (structural subset of `AgentRecord`).
|
|
176
|
-
- `WidgetActivity` interface (structural subset of `AgentActivityTracker`).
|
|
177
|
-
- `renderWidgetLines()` — top-level rendering with categorization, overflow, tree connectors.
|
|
178
|
-
- `renderFinishedLine()` — single finished-agent line.
|
|
179
|
-
- `renderRunningLines()` — single running-agent header + activity pair.
|
|
180
|
-
- Imports from `display.ts` (`SPINNER`, `ERROR_STATUSES`, `formatMs`, `formatTurns`, `formatSessionTokens`, `describeActivity`, `getDisplayName`, `getPromptModeLabel`, `Theme`), from `usage.ts` (`getLifetimeTotal`, `getSessionContextPercent`, `LifetimeUsage`, `SessionLike`), and from `@earendil-works/pi-tui` (`truncateToWidth`).
|
|
181
|
-
|
|
182
|
-
### Modified: `src/ui/agent-widget.ts`
|
|
183
|
-
|
|
184
|
-
- Remove `renderWidget()` method body — replace with call to `renderWidgetLines()`.
|
|
185
|
-
- Remove `renderFinishedLine()` method entirely.
|
|
186
|
-
- Remove direct imports of display helpers and usage helpers that are now only consumed by `widget-renderer.ts`.
|
|
187
|
-
- Keep: constructor, `setUICtx`, `onTurnStart`, `ensureTimer`, `shouldShowFinished`, `markFinished`, `update`, `dispose`, `UICtx` type, `MAX_WIDGET_LINES`.
|
|
188
|
-
- The inline type on `renderFinishedLine`'s parameter `a` is replaced by the `WidgetAgent` import.
|
|
189
|
-
|
|
190
|
-
### New file: `test/widget-renderer.test.ts`
|
|
191
|
-
|
|
192
|
-
- Unit tests for `renderWidgetLines`, `renderFinishedLine`, `renderRunningLines`.
|
|
193
|
-
- Uses plain data objects (no mocks for `AgentManager`, `setInterval`, or SDK).
|
|
194
|
-
- Stub `Theme` matching the pattern in `test/renderer.test.ts`.
|
|
195
|
-
|
|
196
|
-
### No changes to
|
|
197
|
-
|
|
198
|
-
- `src/index.ts` — the widget is constructed the same way; renderer is internal to the widget module.
|
|
199
|
-
- `src/ui/display.ts` — unchanged; consumed by the new renderer.
|
|
200
|
-
- `src/usage.ts` — unchanged.
|
|
201
|
-
|
|
202
|
-
## Test Impact Analysis
|
|
203
|
-
|
|
204
|
-
1. The extraction enables direct unit testing of widget rendering that was previously impossible — testing `renderWidget` required constructing a full `AgentWidget` with mocked `AgentManager`, fake timers, and a stubbed UICtx.
|
|
205
|
-
The new tests cover: finished-agent line formatting (all status variants), running-agent header/activity rendering, overflow logic, tree-connector fixup, empty-state handling, and `shouldShowFinished` filtering.
|
|
206
|
-
2. No existing tests become redundant — there are currently **no** unit tests for `AgentWidget` rendering.
|
|
207
|
-
The existing `display.test.ts` tests lower-level formatters and remains as-is.
|
|
208
|
-
3. `renderer.test.ts` tests the notification renderer — unrelated, stays as-is.
|
|
209
|
-
|
|
210
|
-
## TDD Order
|
|
211
|
-
|
|
212
|
-
1. **Red → Green:** Test `renderFinishedLine` for a completed agent (success icon, stats, duration).
|
|
213
|
-
Commit: `test: add renderFinishedLine tests for completed status`
|
|
214
|
-
|
|
215
|
-
2. **Red → Green:** Test `renderFinishedLine` for error/aborted/steered/stopped statuses (icon and status text variations).
|
|
216
|
-
Commit: `test: renderFinishedLine error and terminal status variants`
|
|
217
|
-
|
|
218
|
-
3. **Red → Green:** Test `renderRunningLines` (spinner frame, stats, activity description, token display).
|
|
219
|
-
Commit: `test: add renderRunningLines tests`
|
|
220
|
-
|
|
221
|
-
4. **Red → Green:** Test `renderWidgetLines` — basic case with one running agent (heading, tree connectors).
|
|
222
|
-
Commit: `test: renderWidgetLines single running agent`
|
|
223
|
-
|
|
224
|
-
5. **Red → Green:** Test `renderWidgetLines` — mixed running + finished + queued, verifying categorization and ordering.
|
|
225
|
-
Commit: `test: renderWidgetLines mixed agent states`
|
|
226
|
-
|
|
227
|
-
6. **Red → Green:** Test `renderWidgetLines` — overflow cap with many agents, verifying the priority (running > queued > finished) and overflow summary line.
|
|
228
|
-
Commit: `test: renderWidgetLines overflow behavior`
|
|
229
|
-
|
|
230
|
-
7. **Red → Green:** Test `renderWidgetLines` — empty state returns `[]`; finished-only state uses dim heading.
|
|
231
|
-
Commit: `test: renderWidgetLines empty and finished-only states`
|
|
232
|
-
|
|
233
|
-
8. **Green → Refactor:** Extract `renderFinishedLine`, `renderRunningLines`, and `renderWidgetLines` into `src/ui/widget-renderer.ts`.
|
|
234
|
-
All tests pass against the extracted module.
|
|
235
|
-
Commit: `refactor: extract widget rendering into widget-renderer`
|
|
236
|
-
|
|
237
|
-
9. **Green → Refactor:** Wire `AgentWidget.renderWidget()` to delegate to `renderWidgetLines()`.
|
|
238
|
-
Remove the inlined rendering logic from `agent-widget.ts`.
|
|
239
|
-
Remove unused imports.
|
|
240
|
-
Commit: `refactor: AgentWidget delegates rendering to widget-renderer`
|
|
241
|
-
|
|
242
|
-
10. **Verify:** Run full test suite (`pnpm vitest run`) and type check (`pnpm run check`).
|
|
243
|
-
Commit: none (verification only).
|
|
244
|
-
|
|
245
|
-
## Risks and Mitigations
|
|
246
|
-
|
|
247
|
-
| Risk | Mitigation |
|
|
248
|
-
| -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
249
|
-
| Structural compatibility between `AgentRecord` and `WidgetAgent` could drift if `AgentRecord` renames a field. | TypeScript's structural checking catches this at the call site in `agent-widget.ts` — `listAgents()` returns `AgentRecord[]` which must satisfy `readonly WidgetAgent[]`. |
|
|
250
|
-
| `truncateToWidth` is an external dependency (`@earendil-works/pi-tui`) in the renderer. | Step O (#147) will inject it; for now, the renderer imports it directly, matching the current widget behavior. |
|
|
251
|
-
| Overflow logic is complex and hand-tested — extraction could introduce subtle line-count bugs. | TDD steps 4–7 exercise overflow edge cases before the extraction step. The extraction is a mechanical move with tests already passing. |
|
|
252
|
-
|
|
253
|
-
## Open Questions
|
|
254
|
-
|
|
255
|
-
- None — the design follows the architecture doc's Step P specification and the dependency (#144) is already implemented.
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
issue: 152
|
|
3
|
-
issue_title: "Add promptSnippet to pi-subagents tools"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Add `promptSnippet` to pi-subagents tools
|
|
7
|
-
|
|
8
|
-
## Problem Statement
|
|
9
|
-
|
|
10
|
-
The `Agent`, `get_subagent_result`, and `steer_subagent` tools are the only tools across the monorepo that lack `promptSnippet`.
|
|
11
|
-
Pi's `buildSystemPrompt` uses `promptSnippet` to build a concise tool summary in the system prompt.
|
|
12
|
-
Without it, these tools rely entirely on their `description` field for model guidance.
|
|
13
|
-
The `Agent` tool's description is especially long (embeds full usage guidelines), so a short snippet would give the model a better quick-reference view.
|
|
14
|
-
|
|
15
|
-
## Goals
|
|
16
|
-
|
|
17
|
-
- Add `promptSnippet` to each of the three tool registrations in pi-subagents.
|
|
18
|
-
- Match the established `"<toolName>: <one-liner>"` format used by pi-github-tools and pi-colgrep.
|
|
19
|
-
|
|
20
|
-
## Non-Goals
|
|
21
|
-
|
|
22
|
-
- Changing `description`, `promptGuidelines`, or any other tool registration field.
|
|
23
|
-
- Adding `promptSnippet` to tools in other packages (already done).
|
|
24
|
-
|
|
25
|
-
## Background
|
|
26
|
-
|
|
27
|
-
Sibling packages pi-github-tools and pi-colgrep already provide `promptSnippet` on every tool.
|
|
28
|
-
The convention is a single string in the form `"tool_name: Short imperative description."`.
|
|
29
|
-
For example: `"ci_list: List recent CI runs for a workflow."`.
|
|
30
|
-
|
|
31
|
-
The three tool factories live in:
|
|
32
|
-
|
|
33
|
-
| Factory | File |
|
|
34
|
-
| --------------------- | ------------------------------ |
|
|
35
|
-
| `createAgentTool` | `src/tools/agent-tool.ts` |
|
|
36
|
-
| `createGetResultTool` | `src/tools/get-result-tool.ts` |
|
|
37
|
-
| `createSteerTool` | `src/tools/steer-tool.ts` |
|
|
38
|
-
|
|
39
|
-
Each factory returns a plain object with `name`, `label`, `description`, `parameters`, and `execute`.
|
|
40
|
-
Adding `promptSnippet` is a single property addition per factory.
|
|
41
|
-
|
|
42
|
-
## Design Overview
|
|
43
|
-
|
|
44
|
-
No structural change — this is a property addition to three existing object literals.
|
|
45
|
-
|
|
46
|
-
Proposed snippets:
|
|
47
|
-
|
|
48
|
-
- **Agent** — `"Agent: Launch a specialized agent for complex, multi-step tasks."`
|
|
49
|
-
- **get_subagent_result** — `"get_subagent_result: Check status and retrieve results from a background agent."`
|
|
50
|
-
- **steer_subagent** — `"steer_subagent: Send a mid-run message to redirect a running background agent."`
|
|
51
|
-
|
|
52
|
-
These are the exact phrasings from the issue.
|
|
53
|
-
Exact wording may be refined during implementation.
|
|
54
|
-
|
|
55
|
-
## Module-Level Changes
|
|
56
|
-
|
|
57
|
-
### `src/tools/agent-tool.ts`
|
|
58
|
-
|
|
59
|
-
Add `promptSnippet` property to the object returned by `createAgentTool`, after `label`.
|
|
60
|
-
|
|
61
|
-
### `src/tools/get-result-tool.ts`
|
|
62
|
-
|
|
63
|
-
Add `promptSnippet` property to the object returned by `createGetResultTool`, after `label`.
|
|
64
|
-
|
|
65
|
-
### `src/tools/steer-tool.ts`
|
|
66
|
-
|
|
67
|
-
Add `promptSnippet` property to the object returned by `createSteerTool`, after `label`.
|
|
68
|
-
|
|
69
|
-
## Test Impact Analysis
|
|
70
|
-
|
|
71
|
-
Existing tool-definition tests (`test/tools/agent-tool.test.ts`, `get-result-tool.test.ts`, `steer-tool.test.ts`) assert `name`, `label`, and `description` but not `promptSnippet`.
|
|
72
|
-
New assertions will verify the property exists with the expected value.
|
|
73
|
-
No existing tests need modification — the new property is additive.
|
|
74
|
-
|
|
75
|
-
## TDD Order
|
|
76
|
-
|
|
77
|
-
1. **Red → Green:** Add `promptSnippet` assertions to the tool-definition tests for all three tools, then add the `promptSnippet` property to each factory.
|
|
78
|
-
Commit: `feat: add promptSnippet to Agent, get_subagent_result, and steer_subagent (#152)`
|
|
79
|
-
|
|
80
|
-
This is a single-cycle change — one test step, one implementation step, one commit.
|
|
81
|
-
|
|
82
|
-
## Risks and Mitigations
|
|
83
|
-
|
|
84
|
-
| Risk | Mitigation |
|
|
85
|
-
| ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
86
|
-
| Snippet wording doesn't match what Pi displays well | The snippets mirror the first sentence of each tool's `description`; can be tweaked in a follow-up without breaking anything. |
|
|
87
|
-
| SDK `defineTool` doesn't pass through `promptSnippet` | Sibling packages already use it successfully, confirming SDK support. |
|
|
88
|
-
|
|
89
|
-
## Open Questions
|
|
90
|
-
|
|
91
|
-
None.
|