@gotgenes/pi-subagents 18.0.0 → 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 +14 -0
- package/README.md +22 -31
- 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/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/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 -45
- package/docs/retro/0442-dissolve-agents-conversation-viewer.md +0 -108
- 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/src/observation/notification-state.ts +0 -27
- package/vitest.config.ts +0 -14
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
issue: 195
|
|
3
|
-
issue_title: "Convert tool factories to classes"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Convert tool factories to classes
|
|
7
|
-
|
|
8
|
-
## Problem Statement
|
|
9
|
-
|
|
10
|
-
`createAgentTool`, `createGetResultTool`, and `createSteerTool` are closure factories that capture dependencies and return tool definitions.
|
|
11
|
-
This pattern hides dependencies in closures, forces `index.ts` to build narrow adapter objects at each call site, and prevents direct structural typing between real objects and tool interfaces.
|
|
12
|
-
With #193 (runtime owns queries) and #194 (interfaces aligned) both complete, the conversions are mechanical.
|
|
13
|
-
|
|
14
|
-
## Goals
|
|
15
|
-
|
|
16
|
-
- Convert all three tool factories to classes with constructor-injected dependencies.
|
|
17
|
-
- Each class exposes a `toToolDefinition()` method that wraps the tool with `defineTool()`.
|
|
18
|
-
- `index.ts` passes real objects directly — no adapter closures for tool wiring.
|
|
19
|
-
- Eliminate 16+ adapter closures from `index.ts`.
|
|
20
|
-
|
|
21
|
-
## Non-Goals
|
|
22
|
-
|
|
23
|
-
- Converting `createAgentRunner` or `createAgentsMenuHandler` — those belong to #196.
|
|
24
|
-
- Simplifying `index.ts` beyond tool wiring — that's #196 Layer 4.
|
|
25
|
-
- Changing tool behavior or parameters — this is a purely structural refactoring.
|
|
26
|
-
|
|
27
|
-
## Background
|
|
28
|
-
|
|
29
|
-
### Dependencies (both closed)
|
|
30
|
-
|
|
31
|
-
- Issue #193 moved context queries (`buildSnapshot`, `getModelInfo`, `getSessionInfo`) onto `SubagentRuntime`.
|
|
32
|
-
- Issue #194 aligned tool interfaces so `AgentManager` and `SubagentRuntime` structurally satisfy the narrow tool interfaces without adapters.
|
|
33
|
-
|
|
34
|
-
### Existing module layout
|
|
35
|
-
|
|
36
|
-
The three factory functions live in:
|
|
37
|
-
|
|
38
|
-
- `src/tools/agent-tool.ts` — `createAgentTool(deps: AgentToolDeps)`
|
|
39
|
-
- `src/tools/get-result-tool.ts` — `createGetResultTool(getRecord, cancelNudge, getConversation, registry)`
|
|
40
|
-
- `src/tools/steer-tool.ts` — `createSteerTool(getRecord, emitEvent, steerAgent, queueSteer)`
|
|
41
|
-
|
|
42
|
-
Each returns a plain object with `name`, `label`, `description`, `parameters`, `execute`, and optional render methods.
|
|
43
|
-
`index.ts` wraps each in `defineTool()` at registration time.
|
|
44
|
-
|
|
45
|
-
### Architecture doc reference
|
|
46
|
-
|
|
47
|
-
Phase 11, Layer 3 in `docs/architecture/architecture.md` (lines 689–709).
|
|
48
|
-
|
|
49
|
-
## Design Overview
|
|
50
|
-
|
|
51
|
-
### Class structure
|
|
52
|
-
|
|
53
|
-
Each class stores constructor-injected dependencies as instance fields and exposes:
|
|
54
|
-
|
|
55
|
-
1. A `toToolDefinition()` method that calls `defineTool(this.buildToolSpec())` (or similar) — returning the Pi SDK tool registration object.
|
|
56
|
-
2. Private methods that correspond to the existing function body sections.
|
|
57
|
-
|
|
58
|
-
### Constructor signatures
|
|
59
|
-
|
|
60
|
-
| Class | Constructor params |
|
|
61
|
-
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
62
|
-
| `AgentTool` | `manager: AgentToolManager`, `runtime: AgentToolRuntime`, `settings: AgentToolSettings`, `registry: AgentTypeRegistry`, `agentDir: string` |
|
|
63
|
-
| `GetResultTool` | `manager: GetResultToolManager`, `notifications: GetResultToolNotifications`, `registry: AgentConfigLookup` |
|
|
64
|
-
| `SteerTool` | `manager: SteerToolManager`, `events: SteerToolEvents` |
|
|
65
|
-
|
|
66
|
-
### Narrow interfaces
|
|
67
|
-
|
|
68
|
-
Each class defines its own narrow interface for the collaborators it uses.
|
|
69
|
-
These already exist (e.g., `AgentToolManager`, `BackgroundManagerDeps`) — they stay as-is; the class uses them directly.
|
|
70
|
-
|
|
71
|
-
#### `AgentTool`
|
|
72
|
-
|
|
73
|
-
The existing `AgentToolDeps` interface (8 fields) collapses into 5 constructor params.
|
|
74
|
-
The `widget`, `agentActivity`, `buildSnapshot`, `getModelInfo`, and `getSessionInfo` fields merge into a single `runtime` param because `SubagentRuntime` structurally satisfies all of them after #193/#194.
|
|
75
|
-
|
|
76
|
-
New narrow interface for the runtime slice:
|
|
77
|
-
|
|
78
|
-
```typescript
|
|
79
|
-
export interface AgentToolRuntime {
|
|
80
|
-
readonly agentActivity: AgentActivityAccess;
|
|
81
|
-
setUICtx(ctx: UICtx): void;
|
|
82
|
-
ensureTimer(): void;
|
|
83
|
-
update(): void;
|
|
84
|
-
markFinished(id: string): void;
|
|
85
|
-
buildSnapshot(inheritContext: boolean): ParentSnapshot;
|
|
86
|
-
getModelInfo(): ModelInfo;
|
|
87
|
-
getSessionInfo(): { parentSessionFile: string; parentSessionId: string };
|
|
88
|
-
}
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
`SubagentRuntime` satisfies this structurally — no adapter needed in `index.ts`.
|
|
92
|
-
|
|
93
|
-
#### `GetResultTool`
|
|
94
|
-
|
|
95
|
-
New narrow interfaces:
|
|
96
|
-
|
|
97
|
-
```typescript
|
|
98
|
-
export interface GetResultToolManager {
|
|
99
|
-
getRecord(id: string): AgentRecord | undefined;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export interface GetResultToolNotifications {
|
|
103
|
-
cancelNudge(key: string): void;
|
|
104
|
-
}
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
`getAgentConversation` is a pure function — imported directly by the class, not injected.
|
|
108
|
-
|
|
109
|
-
#### `SteerTool`
|
|
110
|
-
|
|
111
|
-
New narrow interfaces:
|
|
112
|
-
|
|
113
|
-
```typescript
|
|
114
|
-
export interface SteerToolManager {
|
|
115
|
-
getRecord(id: string): AgentRecord | undefined;
|
|
116
|
-
queueSteer(id: string, message: string): boolean;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export interface SteerToolEvents {
|
|
120
|
-
emit(name: string, data: unknown): void;
|
|
121
|
-
}
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
`steerAgent` is a pure function — imported directly by the class, not injected.
|
|
125
|
-
|
|
126
|
-
### Call site after conversion
|
|
127
|
-
|
|
128
|
-
```typescript
|
|
129
|
-
const agentTool = new AgentTool(manager, runtime, settings, registry, getAgentDir());
|
|
130
|
-
const getResultTool = new GetResultTool(manager, notifications, registry);
|
|
131
|
-
const steerTool = new SteerTool(manager, pi.events);
|
|
132
|
-
pi.registerTool(agentTool.toToolDefinition());
|
|
133
|
-
pi.registerTool(getResultTool.toToolDefinition());
|
|
134
|
-
pi.registerTool(steerTool.toToolDefinition());
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
### Design decisions
|
|
138
|
-
|
|
139
|
-
1. **`toToolDefinition()` on each class** — encapsulates the `defineTool()` call so `index.ts` doesn't import `defineTool` for each tool.
|
|
140
|
-
2. **Pure functions imported directly** — `steerAgent` and `getAgentConversation` are pure utilities with no state; injecting them adds indirection without testability benefit.
|
|
141
|
-
3. **`agentDir` stays a constructor param** — it's a static string computed once at startup; putting it on the registry would add scope responsibility the registry doesn't need.
|
|
142
|
-
4. **Keep existing `AgentToolDeps` temporarily** — remove it in the same PR once the class replaces all usage.
|
|
143
|
-
|
|
144
|
-
## Module-Level Changes
|
|
145
|
-
|
|
146
|
-
### `src/tools/agent-tool.ts`
|
|
147
|
-
|
|
148
|
-
- Add `AgentToolRuntime` interface (narrow runtime slice).
|
|
149
|
-
- Add `AgentToolSettings` type alias (existing inline type, extracted for clarity).
|
|
150
|
-
- Add `AgentTool` class with constructor storing `manager`, `runtime`, `settings`, `registry`, `agentDir`.
|
|
151
|
-
- Move the existing factory body into class methods: `toToolDefinition()`, private `execute()`.
|
|
152
|
-
- Remove `createAgentTool` function and `AgentToolDeps` interface.
|
|
153
|
-
- Keep `AgentToolManager`, `AgentToolWidget`, `AgentActivityAccess` interfaces (still used by `background-spawner` and `foreground-runner` — though `AgentToolWidget` may be replaceable by `AgentToolRuntime`).
|
|
154
|
-
|
|
155
|
-
### `src/tools/get-result-tool.ts`
|
|
156
|
-
|
|
157
|
-
- Add `GetResultToolManager` and `GetResultToolNotifications` interfaces.
|
|
158
|
-
- Add `GetResultTool` class with constructor.
|
|
159
|
-
- Import `getAgentConversation` directly.
|
|
160
|
-
- Move factory body into class method.
|
|
161
|
-
- Remove `createGetResultTool` function.
|
|
162
|
-
|
|
163
|
-
### `src/tools/steer-tool.ts`
|
|
164
|
-
|
|
165
|
-
- Add `SteerToolManager` and `SteerToolEvents` interfaces.
|
|
166
|
-
- Add `SteerTool` class with constructor.
|
|
167
|
-
- Import `steerAgent` directly.
|
|
168
|
-
- Move factory body into class method.
|
|
169
|
-
- Remove `createSteerTool` function.
|
|
170
|
-
|
|
171
|
-
### `src/tools/background-spawner.ts`
|
|
172
|
-
|
|
173
|
-
- Update `BackgroundWidgetDeps` to reference `AgentToolRuntime` instead (or keep as-is since `AgentToolRuntime` is a superset).
|
|
174
|
-
Actually no change needed — `spawnBackground` already accepts narrow interfaces; the `AgentTool` class passes `this.runtime` which satisfies `BackgroundWidgetDeps` structurally.
|
|
175
|
-
|
|
176
|
-
### `src/tools/foreground-runner.ts`
|
|
177
|
-
|
|
178
|
-
- Same as above — no change needed.
|
|
179
|
-
The `AgentTool` class passes `this.runtime` which satisfies `ForegroundWidgetDeps` structurally.
|
|
180
|
-
|
|
181
|
-
### `src/index.ts`
|
|
182
|
-
|
|
183
|
-
- Remove adapter closures for all three tool registrations.
|
|
184
|
-
- Replace with class construction + `toToolDefinition()` calls.
|
|
185
|
-
- Remove `defineTool` import (moves into tool classes).
|
|
186
|
-
- Remove unused imports that were only needed for adapter closures.
|
|
187
|
-
|
|
188
|
-
### `test/tools/agent-tool.test.ts`
|
|
189
|
-
|
|
190
|
-
- Replace `createToolDeps()` with class construction in test helpers.
|
|
191
|
-
- Update `execute()` helper to instantiate `AgentTool` and call its execute.
|
|
192
|
-
- Keep all existing test cases — behavior is unchanged.
|
|
193
|
-
|
|
194
|
-
### `test/tools/get-result-tool.test.ts`
|
|
195
|
-
|
|
196
|
-
- Replace positional args with class construction.
|
|
197
|
-
- Update `makeDeps` and `execute` helpers.
|
|
198
|
-
- Keep all existing test cases.
|
|
199
|
-
|
|
200
|
-
### `test/tools/steer-tool.test.ts`
|
|
201
|
-
|
|
202
|
-
- Replace positional args with class construction.
|
|
203
|
-
- Update `makeDeps` and `execute` helpers.
|
|
204
|
-
- Keep all existing test cases.
|
|
205
|
-
|
|
206
|
-
### `test/helpers/make-deps.ts`
|
|
207
|
-
|
|
208
|
-
- Update `createToolDeps` to construct `AgentTool`-compatible deps (or remove if no longer needed).
|
|
209
|
-
Likely transforms into a factory that builds mock `AgentToolRuntime`, `AgentToolManager`, etc.
|
|
210
|
-
|
|
211
|
-
### `docs/architecture/architecture.md`
|
|
212
|
-
|
|
213
|
-
- Update the Layer 3 table to mark #195 as done.
|
|
214
|
-
- Update the file listing for `src/tools/` to reflect class names (if the listing is that detailed).
|
|
215
|
-
|
|
216
|
-
## Test Impact Analysis
|
|
217
|
-
|
|
218
|
-
1. **No new test surfaces** — this is a structural refactoring with identical behavior.
|
|
219
|
-
Existing tests already cover all tool paths.
|
|
220
|
-
2. **Test helper changes** — `createToolDeps()` and per-tool `makeDeps()` functions need updating to use class construction instead of function calls, but the mock shapes remain the same.
|
|
221
|
-
3. **All existing tests stay** — they exercise the tool execution logic which doesn't change.
|
|
222
|
-
|
|
223
|
-
## TDD Order
|
|
224
|
-
|
|
225
|
-
1. **Convert `SteerTool` to class** — smallest tool (fewest deps, no render methods).
|
|
226
|
-
- Update `steer-tool.ts`: add interfaces, add class, remove factory.
|
|
227
|
-
- Update `test/tools/steer-tool.test.ts`: use class construction.
|
|
228
|
-
- Verify: `pnpm vitest run test/tools/steer-tool.test.ts`
|
|
229
|
-
- Commit: `refactor: convert createSteerTool to SteerTool class (#195)`
|
|
230
|
-
|
|
231
|
-
2. **Convert `GetResultTool` to class** — medium complexity (3 deps, no render methods).
|
|
232
|
-
- Update `get-result-tool.ts`: add interfaces, add class, import `getAgentConversation`, remove factory.
|
|
233
|
-
- Update `test/tools/get-result-tool.test.ts`: use class construction.
|
|
234
|
-
- Verify: `pnpm vitest run test/tools/get-result-tool.test.ts`
|
|
235
|
-
- Commit: `refactor: convert createGetResultTool to GetResultTool class (#195)`
|
|
236
|
-
|
|
237
|
-
3. **Convert `AgentTool` to class** — largest (5 deps, render methods, delegates to spawner/runner).
|
|
238
|
-
- Add `AgentToolRuntime` and `AgentToolSettings` interfaces.
|
|
239
|
-
- Add `AgentTool` class.
|
|
240
|
-
- Remove `createAgentTool` and `AgentToolDeps`.
|
|
241
|
-
- Update `test/tools/agent-tool.test.ts` and `test/helpers/make-deps.ts`.
|
|
242
|
-
- Verify: `pnpm vitest run test/tools/agent-tool.test.ts`
|
|
243
|
-
- Commit: `refactor: convert createAgentTool to AgentTool class (#195)`
|
|
244
|
-
|
|
245
|
-
4. **Update `index.ts`** — wire class constructors, remove adapter closures and `defineTool` import.
|
|
246
|
-
- Verify: `pnpm vitest run` (full suite) + `pnpm run check` (type-check).
|
|
247
|
-
- Commit: `refactor: wire tool classes in index.ts, remove adapter closures (#195)`
|
|
248
|
-
|
|
249
|
-
5. **Update architecture doc** — mark Layer 3 (partial) as complete.
|
|
250
|
-
- Commit: `docs: mark #195 complete in architecture roadmap`
|
|
251
|
-
|
|
252
|
-
## Risks and Mitigations
|
|
253
|
-
|
|
254
|
-
| Risk | Mitigation |
|
|
255
|
-
| --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
|
|
256
|
-
| `background-spawner` and `foreground-runner` accept narrow interfaces that differ from `AgentToolRuntime` | `AgentToolRuntime` is a superset — pass `this.runtime` and structural typing handles it. |
|
|
257
|
-
| Test factories import `AgentToolDeps` which will be removed | Step 3 updates all test imports in the same commit. |
|
|
258
|
-
| `defineTool` import removed from `index.ts` — must live somewhere | Each class's `toToolDefinition()` imports it internally. |
|
|
259
|
-
| Spreading class instances in tests breaks method access | Tests will construct the class, not spread it. Step 3 uses lift-and-shift for `make-deps.ts`. |
|
|
260
|
-
|
|
261
|
-
## Open Questions
|
|
262
|
-
|
|
263
|
-
- Should `AgentToolWidget` interface be removed entirely (replaced by `AgentToolRuntime`)?
|
|
264
|
-
Defer to implementation — if `background-spawner` and `foreground-runner` can accept `AgentToolRuntime` directly, remove it; otherwise keep the narrow subset interfaces.
|
|
@@ -1,268 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
issue: 196
|
|
3
|
-
issue_title: "Convert AgentRunner and AgentsMenuHandler to classes, simplify index.ts"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Convert AgentRunner and AgentsMenuHandler to classes, simplify index.ts
|
|
7
|
-
|
|
8
|
-
## Problem Statement
|
|
9
|
-
|
|
10
|
-
Two remaining closure factories in pi-subagents mask class-shaped code:
|
|
11
|
-
|
|
12
|
-
1. `createAgentRunner(runnerIO)` captures `RunnerIO` and returns `{ run, resume }` — the `AgentRunner` interface already exists but lacks a concrete class implementation.
|
|
13
|
-
2. `createAgentsMenuHandler({...})` captures an 8-field deps object and returns a handler function.
|
|
14
|
-
|
|
15
|
-
With #195 (tool factory → class conversions) complete, these are the last two closure factories.
|
|
16
|
-
After converting them, `index.ts` can be simplified: adapter closures drop, fan-out decreases, and the composition root becomes pure object construction.
|
|
17
|
-
|
|
18
|
-
## Goals
|
|
19
|
-
|
|
20
|
-
- Convert `createAgentRunner` factory to a concrete `ConcreteAgentRunner` class implementing `AgentRunner`.
|
|
21
|
-
- Convert `createAgentsMenuHandler` factory to an `AgentsMenuHandler` class.
|
|
22
|
-
- Internalize the `getModelLabel` closure from `index.ts` into `AgentsMenuHandler` (it uses `resolveModel` and `getModelLabelFromConfig`, both pure functions the class can import directly).
|
|
23
|
-
- Pass `AgentManager` directly as the `manager` param (it structurally satisfies `AgentMenuManager`), eliminating 3 adapter closures.
|
|
24
|
-
- Simplify `index.ts` by removing eliminated adapter closures and unused imports.
|
|
25
|
-
- Update architecture doc to mark Layer 3 and Layer 4 as done.
|
|
26
|
-
|
|
27
|
-
## Non-Goals
|
|
28
|
-
|
|
29
|
-
- Changing `runAgent()` or `resumeAgent()` function signatures — they remain as free functions called by the class.
|
|
30
|
-
- Removing the `AgentRunner` interface — it stays as the contract for `AgentManager`.
|
|
31
|
-
- Removing `RunnerIO` type — it stays as the IO boundary for `runAgent()`.
|
|
32
|
-
- Changing the `AgentMenuManager` interface — it stays as the narrow contract; `AgentManager` satisfies it structurally.
|
|
33
|
-
- Removing `AgentMenuDeps` — it is replaced by the class constructor; the type itself is removed.
|
|
34
|
-
- Refactoring `NotificationManager`, `SettingsManager`, or `SessionLifecycleHandler` — those are already class-shaped.
|
|
35
|
-
- Phase 12 work (decompose `renderWidgetLines`, consolidate test duplication).
|
|
36
|
-
|
|
37
|
-
## Background
|
|
38
|
-
|
|
39
|
-
### Phase 11 layer structure
|
|
40
|
-
|
|
41
|
-
Phase 11 in `docs/architecture/architecture.md` converts closure factories to classes in four layers:
|
|
42
|
-
|
|
43
|
-
- Layer 0: `SessionContext` interface (#192) ✓
|
|
44
|
-
- Layer 1: Runtime owns context queries (#193) ✓
|
|
45
|
-
- Layer 2: Align interfaces for structural typing (#194) ✓
|
|
46
|
-
- Layer 3: Convert closure factories to classes (#195 tools ✓, #196 runner + menu)
|
|
47
|
-
- Layer 4: Simplify `index.ts` (#196)
|
|
48
|
-
|
|
49
|
-
Issue #196 completes Layer 3 (runner + menu) and Layer 4 (index.ts simplification).
|
|
50
|
-
|
|
51
|
-
### Current state
|
|
52
|
-
|
|
53
|
-
`createAgentRunner` (3 lines) wraps `runAgent`/`resumeAgent` in an object literal:
|
|
54
|
-
|
|
55
|
-
```typescript
|
|
56
|
-
export function createAgentRunner(io: RunnerIO): AgentRunner {
|
|
57
|
-
return {
|
|
58
|
-
run: (snapshot, type, prompt, options) => runAgent(snapshot, type, prompt, options, io),
|
|
59
|
-
resume: resumeAgent,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
`createAgentsMenuHandler` (200+ lines) captures 8 deps and returns a handler function.
|
|
65
|
-
The deps bag includes `getModelLabel` (a closure built in `index.ts`) and `agentActivity` (a `Map` from runtime).
|
|
66
|
-
|
|
67
|
-
`index.ts` currently has ~23 arrow closures and 27 imports at 229 lines.
|
|
68
|
-
|
|
69
|
-
### Structural typing confirmation
|
|
70
|
-
|
|
71
|
-
`AgentManager` already has `listAgents()`, `getRecord()`, and `spawnAndWait()` methods that structurally satisfy `AgentMenuManager`.
|
|
72
|
-
The `spawnAndWait` parameter type (`Omit<AgentSpawnConfig, "isBackground">`) is a superset of the menu's `{ description, maxTurns }`, so structural typing matches.
|
|
73
|
-
|
|
74
|
-
## Design Overview
|
|
75
|
-
|
|
76
|
-
### ConcreteAgentRunner
|
|
77
|
-
|
|
78
|
-
A minimal class that implements `AgentRunner` by delegating to the free functions:
|
|
79
|
-
|
|
80
|
-
```typescript
|
|
81
|
-
export class ConcreteAgentRunner implements AgentRunner {
|
|
82
|
-
constructor(private readonly io: RunnerIO) {}
|
|
83
|
-
|
|
84
|
-
async run(snapshot: ParentSnapshot, type: SubagentType, prompt: string, options: RunOptions): Promise<RunResult> {
|
|
85
|
-
return runAgent(snapshot, type, prompt, options, this.io);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
async resume(session: AgentSession, prompt: string, options?: ResumeOptions): Promise<string> {
|
|
89
|
-
return resumeAgent(session, prompt, options);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
The factory function `createAgentRunner` is removed.
|
|
95
|
-
The free functions `runAgent`, `resumeAgent`, `getAgentConversation`, and `normalizeMaxTurns` remain exported — they are used directly by tests and other modules.
|
|
96
|
-
|
|
97
|
-
### AgentsMenuHandler
|
|
98
|
-
|
|
99
|
-
The class replaces `createAgentsMenuHandler` and `AgentMenuDeps`.
|
|
100
|
-
Constructor params are the subset of deps that are true collaborators:
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
export class AgentsMenuHandler {
|
|
104
|
-
constructor(
|
|
105
|
-
private readonly manager: AgentMenuManager,
|
|
106
|
-
private readonly registry: AgentTypeRegistry,
|
|
107
|
-
private readonly agentActivity: AgentActivityReader,
|
|
108
|
-
private readonly settings: AgentMenuSettings,
|
|
109
|
-
private readonly fileOps: AgentFileOps,
|
|
110
|
-
private readonly personalAgentsDir: string,
|
|
111
|
-
private readonly projectAgentsDir: string,
|
|
112
|
-
) {}
|
|
113
|
-
|
|
114
|
-
async handle(ctx: { ui: MenuUI; modelRegistry: ModelRegistry; parentSnapshot: ParentSnapshot }): Promise<void> { ... }
|
|
115
|
-
}
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
Key design decisions:
|
|
119
|
-
|
|
120
|
-
1. **`agentActivity` stays as a constructor param** — it is a collaborator used in `viewAgentConversation`.
|
|
121
|
-
The issue's proposed signature omits it, but the class needs it at runtime.
|
|
122
|
-
2. **`getModelLabel` is internalized** — the class imports `resolveModel` and `getModelLabelFromConfig` directly and computes the label in a private method.
|
|
123
|
-
This eliminates the closure from `index.ts` and removes the `getModelLabel` field from the deps interface.
|
|
124
|
-
3. **`AgentMenuDeps` is removed** — the class constructor replaces it.
|
|
125
|
-
4. **The `handle` method** replaces the returned function.
|
|
126
|
-
The inner helpers (`showAgentsMenu`, `showAllAgentsList`, etc.) become private methods.
|
|
127
|
-
|
|
128
|
-
### index.ts simplification
|
|
129
|
-
|
|
130
|
-
After both conversions:
|
|
131
|
-
|
|
132
|
-
```typescript
|
|
133
|
-
// Before (adapter closures):
|
|
134
|
-
const agentsMenuHandler = createAgentsMenuHandler({
|
|
135
|
-
manager: {
|
|
136
|
-
listAgents: () => manager.listAgents(),
|
|
137
|
-
getRecord: (id) => manager.getRecord(id),
|
|
138
|
-
spawnAndWait: (...) => manager.spawnAndWait(...),
|
|
139
|
-
},
|
|
140
|
-
registry,
|
|
141
|
-
agentActivity: runtime.agentActivity,
|
|
142
|
-
getModelLabel: (type, modelRegistry) => { ... }, // 7-line closure
|
|
143
|
-
settings,
|
|
144
|
-
fileOps: new FsAgentFileOps(),
|
|
145
|
-
personalAgentsDir: join(getAgentDir(), 'agents'),
|
|
146
|
-
projectAgentsDir: join(process.cwd(), '.pi', 'agents'),
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
// After:
|
|
150
|
-
const agentsMenu = new AgentsMenuHandler(
|
|
151
|
-
manager, registry, runtime.agentActivity,
|
|
152
|
-
settings, new FsAgentFileOps(),
|
|
153
|
-
join(getAgentDir(), 'agents'),
|
|
154
|
-
join(process.cwd(), '.pi', 'agents'),
|
|
155
|
-
);
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
Eliminated closures: 4 (3 manager method adapters + 1 getModelLabel closure).
|
|
159
|
-
Eliminated imports: `getModelLabelFromConfig`, `resolveModel` (from index.ts), `createAgentRunner`, `type RunnerIO`, `createAgentsMenuHandler`.
|
|
160
|
-
|
|
161
|
-
Remaining adapter closures in `index.ts` (~15) are necessary: event handler registrations, SDK factory callbacks, `pi.sendMessage`/`pi.exec` adapters.
|
|
162
|
-
These are structural — they bridge the Pi SDK's callback-based API to the extension's object-oriented internals.
|
|
163
|
-
|
|
164
|
-
## Module-Level Changes
|
|
165
|
-
|
|
166
|
-
### `src/lifecycle/agent-runner.ts`
|
|
167
|
-
|
|
168
|
-
- Add `ConcreteAgentRunner` class implementing `AgentRunner`.
|
|
169
|
-
- Remove `createAgentRunner` factory function.
|
|
170
|
-
- Keep all free functions (`runAgent`, `resumeAgent`, `getAgentConversation`, `normalizeMaxTurns`) and all types exported.
|
|
171
|
-
|
|
172
|
-
### `src/ui/agent-menu.ts`
|
|
173
|
-
|
|
174
|
-
- Replace `createAgentsMenuHandler` factory with `AgentsMenuHandler` class.
|
|
175
|
-
- Remove `AgentMenuDeps` interface.
|
|
176
|
-
- Add private `getModelLabel` method (internalizes the closure from `index.ts`).
|
|
177
|
-
- Convert inner functions (`showAgentsMenu`, `showAllAgentsList`, `showRunningAgents`, `viewAgentConversation`, `showSettings`) to private methods.
|
|
178
|
-
- Add imports: `resolveModel` from `#src/session/model-resolver`, `getModelLabelFromConfig` from `#src/tools/helpers`.
|
|
179
|
-
- Keep exported interfaces: `AgentMenuManager`, `AgentMenuSettings`, `AgentActivityReader`, `MenuUI`.
|
|
180
|
-
|
|
181
|
-
### `src/index.ts`
|
|
182
|
-
|
|
183
|
-
- Replace `createAgentRunner(runnerIO)` with `new ConcreteAgentRunner(runnerIO)`.
|
|
184
|
-
- Replace `createAgentsMenuHandler({...})` with `new AgentsMenuHandler(...)`.
|
|
185
|
-
- Replace `agentsMenuHandler({...})` with `agentsMenu.handle({...})`.
|
|
186
|
-
- Remove adapter closures for `manager.listAgents`, `manager.getRecord`, `manager.spawnAndWait`, and `getModelLabel`.
|
|
187
|
-
- Remove unused imports: `createAgentRunner`, `type RunnerIO` → `ConcreteAgentRunner`; `createAgentsMenuHandler` → `AgentsMenuHandler`; `getModelLabelFromConfig`, `resolveModel`.
|
|
188
|
-
- Net effect: ~15 lines removed, 5 imports removed.
|
|
189
|
-
|
|
190
|
-
### `docs/architecture/architecture.md`
|
|
191
|
-
|
|
192
|
-
- Mark Layer 3 remaining items (runner, menu) as done.
|
|
193
|
-
- Mark Layer 4 as done.
|
|
194
|
-
- Update the factory→class table entries for `createAgentRunner` and `createAgentsMenuHandler` with ✓.
|
|
195
|
-
|
|
196
|
-
## Test Impact Analysis
|
|
197
|
-
|
|
198
|
-
### `test/lifecycle/agent-runner.test.ts` (and siblings)
|
|
199
|
-
|
|
200
|
-
No changes needed.
|
|
201
|
-
Tests call `runAgent()` and `resumeAgent()` directly — they never use `createAgentRunner`.
|
|
202
|
-
The `ConcreteAgentRunner` class is a trivial two-method delegation wrapper tested implicitly through `index.ts` integration and explicitly through one new unit test.
|
|
203
|
-
|
|
204
|
-
### `test/ui/agent-menu.test.ts`
|
|
205
|
-
|
|
206
|
-
Tests need updating:
|
|
207
|
-
|
|
208
|
-
1. Replace `createAgentsMenuHandler(makeDeps())` with `new AgentsMenuHandler(...)`.
|
|
209
|
-
2. Replace `handler(params)` with `handler.handle(params)`.
|
|
210
|
-
3. Remove `getModelLabel` from `makeDeps()` — it is now an internal method.
|
|
211
|
-
4. Remove `AgentMenuDeps` import; update `makeDeps` to construct positional args or a helper that returns a handler directly.
|
|
212
|
-
|
|
213
|
-
No test logic changes — only call-site updates for the new API shape.
|
|
214
|
-
|
|
215
|
-
### New tests
|
|
216
|
-
|
|
217
|
-
One new unit test for `ConcreteAgentRunner`: verify it delegates `run` and `resume` to the underlying functions.
|
|
218
|
-
|
|
219
|
-
## TDD Order
|
|
220
|
-
|
|
221
|
-
1. **Add `ConcreteAgentRunner` class alongside factory.**
|
|
222
|
-
Add the class to `agent-runner.ts`, keep `createAgentRunner` temporarily.
|
|
223
|
-
Add a unit test verifying delegation.
|
|
224
|
-
`test: add ConcreteAgentRunner delegation test`
|
|
225
|
-
|
|
226
|
-
2. **Switch `index.ts` to `ConcreteAgentRunner`, remove factory.**
|
|
227
|
-
Replace `createAgentRunner(runnerIO)` with `new ConcreteAgentRunner(runnerIO)`.
|
|
228
|
-
Remove the `createAgentRunner` factory function.
|
|
229
|
-
Update imports.
|
|
230
|
-
`refactor: replace createAgentRunner with ConcreteAgentRunner class`
|
|
231
|
-
|
|
232
|
-
3. **Convert `createAgentsMenuHandler` to `AgentsMenuHandler` class.**
|
|
233
|
-
Replace factory function with class.
|
|
234
|
-
Move inner functions to private methods.
|
|
235
|
-
Internalize `getModelLabel` as a private method.
|
|
236
|
-
Remove `AgentMenuDeps` interface.
|
|
237
|
-
`refactor: convert createAgentsMenuHandler to AgentsMenuHandler class`
|
|
238
|
-
|
|
239
|
-
4. **Update `agent-menu.test.ts` for class API.**
|
|
240
|
-
Replace `createAgentsMenuHandler(makeDeps())` with class construction.
|
|
241
|
-
Replace `handler(params)` with `handler.handle(params)`.
|
|
242
|
-
Remove `getModelLabel` from test deps.
|
|
243
|
-
All existing tests pass with updated call sites.
|
|
244
|
-
`test: update agent-menu tests for AgentsMenuHandler class`
|
|
245
|
-
|
|
246
|
-
5. **Simplify `index.ts` wiring.**
|
|
247
|
-
Replace `createAgentsMenuHandler({...})` with `new AgentsMenuHandler(...)`.
|
|
248
|
-
Pass `manager` directly (structural typing).
|
|
249
|
-
Remove adapter closures and unused imports.
|
|
250
|
-
`refactor: simplify index.ts wiring for AgentsMenuHandler`
|
|
251
|
-
|
|
252
|
-
6. **Update architecture doc.**
|
|
253
|
-
Mark Layer 3 remaining items and Layer 4 as done in `docs/architecture/architecture.md`.
|
|
254
|
-
`docs: mark Phase 11 Layer 3 and Layer 4 complete`
|
|
255
|
-
|
|
256
|
-
## Risks and Mitigations
|
|
257
|
-
|
|
258
|
-
| Risk | Mitigation |
|
|
259
|
-
| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
|
260
|
-
| `AgentManager` might not structurally satisfy `AgentMenuManager` | Confirmed: `listAgents()`, `getRecord()`, `spawnAndWait()` signatures are compatible. `pnpm run check` in step 5 verifies. |
|
|
261
|
-
| Internalized `getModelLabel` might diverge from the closure | The private method uses the same `resolveModel` and `getModelLabelFromConfig` imports — identical logic, just moved. |
|
|
262
|
-
| Tests that use `AgentMenuDeps` type break when removed | Step 4 updates all test call sites before step 5 changes production code. The test file is 215 lines — manageable in one step. |
|
|
263
|
-
| `agentActivity` missing from constructor | Included in the class constructor (diverging from the issue's proposed signature which omits it). |
|
|
264
|
-
|
|
265
|
-
## Open Questions
|
|
266
|
-
|
|
267
|
-
None — the issue's proposed design is clear and the implementation is mechanical.
|
|
268
|
-
The one deviation (keeping `agentActivity` as a constructor param) is necessary and minimal.
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
issue: 205
|
|
3
|
-
issue_title: "Decompose renderWidgetLines (cognitive 44)"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Decompose `renderWidgetLines`
|
|
7
|
-
|
|
8
|
-
## Problem Statement
|
|
9
|
-
|
|
10
|
-
`renderWidgetLines` in `ui/widget-renderer.ts` has cognitive complexity 44 (CRITICAL per fallow health).
|
|
11
|
-
It handles agent categorization, per-status line building with tree connectors, non-overflow assembly with last-connector fixup, and overflow-budget assembly — all in a single 106-line function.
|
|
12
|
-
This is the highest-complexity function remaining in the codebase (Phase 12, Step 1).
|
|
13
|
-
|
|
14
|
-
## Goals
|
|
15
|
-
|
|
16
|
-
- Extract distinct concerns into separate pure functions, each with cognitive complexity < 10.
|
|
17
|
-
- Preserve all existing behavior — no visual or behavioral changes.
|
|
18
|
-
- Keep all extracted functions in `widget-renderer.ts` (they are private helpers, not a separate module).
|
|
19
|
-
|
|
20
|
-
## Non-Goals
|
|
21
|
-
|
|
22
|
-
- Decomposing `showAgentDetail` (#206), `update` (#207), or shared test fixtures (#208) — those are sibling Phase 12 steps.
|
|
23
|
-
- Changing the widget's visual output or tree-connector style.
|
|
24
|
-
- Modifying `renderFinishedLine` or `renderRunningLines` — those are already single-concern functions.
|
|
25
|
-
|
|
26
|
-
## Background
|
|
27
|
-
|
|
28
|
-
`widget-renderer.ts` was extracted from `AgentWidget` in #148.
|
|
29
|
-
The per-agent renderers (`renderFinishedLine`, `renderRunningLines`) are already clean single-concern functions.
|
|
30
|
-
The remaining complexity lives entirely in `renderWidgetLines`, which orchestrates categorization, section building, and assembly.
|
|
31
|
-
|
|
32
|
-
The function has five interwoven concerns:
|
|
33
|
-
|
|
34
|
-
1. **Agent categorization** — filtering into running/queued/finished buckets.
|
|
35
|
-
2. **Section building** — rendering each bucket into pre-formatted line arrays with `├─` tree connectors.
|
|
36
|
-
3. **Heading construction** — choosing icon/color based on active vs. finished-only.
|
|
37
|
-
4. **Non-overflow assembly** — concatenating sections when under `MAX_WIDGET_LINES`, then fixing the last connector (`├─` → `└─`).
|
|
38
|
-
5. **Overflow assembly** — budget-based prioritized assembly (running > queued > finished) with an overflow indicator line.
|
|
39
|
-
|
|
40
|
-
## Design Overview
|
|
41
|
-
|
|
42
|
-
Extract four helper functions from the body of `renderWidgetLines`:
|
|
43
|
-
|
|
44
|
-
### `categorizeAgents`
|
|
45
|
-
|
|
46
|
-
Accepts the agents array and `shouldShowFinished` callback.
|
|
47
|
-
Returns `{ running, queued, finished }` arrays.
|
|
48
|
-
Pure filter — no rendering.
|
|
49
|
-
|
|
50
|
-
### `buildSections`
|
|
51
|
-
|
|
52
|
-
Accepts categorized agents, `activityMap`, `registry`, `spinnerFrame`, `theme`, and a `truncate` function.
|
|
53
|
-
Returns `{ finishedLines, runningLines, queuedLine }` — the pre-formatted line arrays with `├─` connectors.
|
|
54
|
-
Calls `renderFinishedLine` and `renderRunningLines` internally.
|
|
55
|
-
|
|
56
|
-
### `assembleWithinBudget`
|
|
57
|
-
|
|
58
|
-
Accepts `finishedLines`, `runningLines`, `queuedLine`, and the heading line.
|
|
59
|
-
Handles the non-overflow path: concatenates sections and fixes the last tree connector (`├─` → `└─`, `│` → space).
|
|
60
|
-
Returns the assembled `string[]`.
|
|
61
|
-
|
|
62
|
-
### `assembleOverflow`
|
|
63
|
-
|
|
64
|
-
Accepts `finishedLines`, `runningLines`, `queuedLine`, heading line, `maxBody` budget, `truncate`, and `theme`.
|
|
65
|
-
Handles the overflow path: budget-based prioritized assembly with an overflow indicator.
|
|
66
|
-
Returns the assembled `string[]`.
|
|
67
|
-
|
|
68
|
-
After extraction, `renderWidgetLines` becomes a thin orchestrator:
|
|
69
|
-
|
|
70
|
-
```typescript
|
|
71
|
-
export function renderWidgetLines(params: { ... }): string[] {
|
|
72
|
-
const { running, queued, finished } = categorizeAgents(agents, shouldShowFinished);
|
|
73
|
-
if (running.length === 0 && queued.length === 0 && finished.length === 0) return [];
|
|
74
|
-
|
|
75
|
-
const truncate = (line: string) => truncateToWidth(line, terminalWidth);
|
|
76
|
-
const heading = buildHeadingLine(running, queued, truncate, theme);
|
|
77
|
-
const sections = buildSections(running, queued, finished, activityMap, registry, spinnerFrame, theme, truncate);
|
|
78
|
-
const totalBody = sections.finishedLines.length + sections.runningLines.length * 2 + (sections.queuedLine ? 1 : 0);
|
|
79
|
-
|
|
80
|
-
if (totalBody <= MAX_WIDGET_LINES - 1) {
|
|
81
|
-
return assembleWithinBudget(heading, sections);
|
|
82
|
-
}
|
|
83
|
-
return assembleOverflow(heading, sections, MAX_WIDGET_LINES - 1, truncate, theme);
|
|
84
|
-
}
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
Each helper is a pure function with a single concern and low branching.
|
|
88
|
-
|
|
89
|
-
## Module-Level Changes
|
|
90
|
-
|
|
91
|
-
### Changed: `src/ui/widget-renderer.ts`
|
|
92
|
-
|
|
93
|
-
- Add `categorizeAgents` (private) — extracts the three `agents.filter(...)` calls.
|
|
94
|
-
- Add `buildSections` (private) — extracts the three section-building loops.
|
|
95
|
-
- Add `assembleWithinBudget` (private) — extracts the non-overflow assembly + connector fixup.
|
|
96
|
-
- Add `assembleOverflow` (private) — extracts the overflow-budget assembly + indicator line.
|
|
97
|
-
- Simplify `renderWidgetLines` to a thin orchestrator calling the four helpers.
|
|
98
|
-
|
|
99
|
-
No exports are added, removed, or renamed.
|
|
100
|
-
No other files change.
|
|
101
|
-
|
|
102
|
-
## Test Impact Analysis
|
|
103
|
-
|
|
104
|
-
1. No new unit tests for the extracted helpers are needed — they are private functions tested through `renderWidgetLines`.
|
|
105
|
-
The existing `renderWidgetLines` tests in `test/widget-renderer.test.ts` (8 tests) cover all branches: single running, mixed agents, filtered finished, overflow priority, empty arrays, dim heading.
|
|
106
|
-
2. No existing tests become redundant — they all exercise `renderWidgetLines` end-to-end, which is the correct level for assembly logic.
|
|
107
|
-
3. All existing tests must stay as-is — the extraction is purely internal.
|
|
108
|
-
|
|
109
|
-
## TDD Order
|
|
110
|
-
|
|
111
|
-
1. **Red → Green:** Extract `categorizeAgents` and call it from `renderWidgetLines`.
|
|
112
|
-
All existing tests pass (no behavior change).
|
|
113
|
-
Commit: `refactor: extract categorizeAgents from renderWidgetLines`
|
|
114
|
-
|
|
115
|
-
2. **Red → Green:** Extract `buildSections` and call it from `renderWidgetLines`.
|
|
116
|
-
All existing tests pass.
|
|
117
|
-
Commit: `refactor: extract buildSections from renderWidgetLines`
|
|
118
|
-
|
|
119
|
-
3. **Red → Green:** Extract `assembleWithinBudget` and call it from `renderWidgetLines`.
|
|
120
|
-
All existing tests pass.
|
|
121
|
-
Commit: `refactor: extract assembleWithinBudget from renderWidgetLines`
|
|
122
|
-
|
|
123
|
-
4. **Red → Green:** Extract `assembleOverflow` and call it from `renderWidgetLines`.
|
|
124
|
-
All existing tests pass.
|
|
125
|
-
Commit: `refactor: extract assembleOverflow from renderWidgetLines`
|
|
126
|
-
|
|
127
|
-
5. **Verify:** Run `pnpm run check` and `pnpm vitest run test/widget-renderer.test.ts` to confirm no regressions.
|
|
128
|
-
Commit: n/a (verification only).
|
|
129
|
-
|
|
130
|
-
## Risks and Mitigations
|
|
131
|
-
|
|
132
|
-
| Risk | Mitigation |
|
|
133
|
-
| --------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
134
|
-
| Tree-connector fixup logic is fragile (string replacement on Unicode chars) | Keep the fixup in `assembleWithinBudget` as-is — same logic, just relocated. Existing tests verify exact connector output. |
|
|
135
|
-
| Extracted helpers have many parameters | Accept a `sections` object from `buildSections` to bundle `finishedLines`, `runningLines`, `queuedLine` — avoids long parameter lists. |
|
|
136
|
-
| Intermediate commits break tests | Each extraction step is self-contained — the function body moves into a helper and the call site replaces it in the same commit. |
|
|
137
|
-
|
|
138
|
-
## Open Questions
|
|
139
|
-
|
|
140
|
-
None — the decomposition is purely mechanical extraction of existing code into named helpers.
|