@gotgenes/pi-subagents 18.0.1 → 18.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/docs/architecture/architecture.md +165 -203
- package/docs/architecture/history/phase-19-implement-ui-decisions.md +282 -0
- package/package.json +6 -7
- package/src/config/default-agents.ts +3 -0
- package/src/lifecycle/subagent.ts +25 -14
- package/src/observation/notification.ts +23 -10
- package/src/observation/subagent-events-observer.ts +1 -3
- package/src/runtime.ts +2 -1
- package/src/service/service-adapter.ts +20 -17
- package/src/session/model-resolver.ts +31 -30
- package/src/tools/agent-tool.ts +17 -13
- package/src/tools/get-result-report.ts +60 -0
- package/src/tools/get-result-tool.ts +25 -40
- package/src/tools/helpers.ts +21 -5
- package/src/tools/spawn-config.ts +5 -5
- package/src/tools/steer-tool.ts +37 -27
- package/src/types.ts +4 -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,24 +1,17 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-redundant-type-constituents -- Pi SDK types are not fully exported; see upstream Pi SDK for type improvements */
|
|
2
1
|
/**
|
|
3
2
|
* Model resolution: exact match ("provider/modelId") with fuzzy fallback.
|
|
4
3
|
*/
|
|
5
|
-
|
|
6
|
-
export interface ModelEntry {
|
|
7
|
-
id: string;
|
|
8
|
-
name: string;
|
|
9
|
-
provider: string;
|
|
10
|
-
}
|
|
4
|
+
import type { Model } from "@earendil-works/pi-ai";
|
|
11
5
|
|
|
12
6
|
export interface ModelRegistry {
|
|
13
|
-
find(provider: string, modelId: string): any;
|
|
14
|
-
getAll(): any[];
|
|
15
|
-
getAvailable?(): any[];
|
|
7
|
+
find(provider: string, modelId: string): Model<any> | undefined;
|
|
8
|
+
getAll(): Model<any>[];
|
|
9
|
+
getAvailable?(): Model<any>[];
|
|
16
10
|
}
|
|
17
11
|
|
|
18
12
|
/** Successful model resolution — `model` is the resolved or inherited model instance. */
|
|
19
13
|
export interface ModelResolutionResult {
|
|
20
|
-
|
|
21
|
-
model: any;
|
|
14
|
+
model: Model<any> | undefined;
|
|
22
15
|
error?: undefined;
|
|
23
16
|
}
|
|
24
17
|
|
|
@@ -42,12 +35,13 @@ export type ModelResolution = ModelResolutionResult | ModelResolutionError;
|
|
|
42
35
|
* - `modelFromParams` false → silent fallback to `parentModel`.
|
|
43
36
|
*/
|
|
44
37
|
export function resolveInvocationModel(
|
|
45
|
-
parentModel:
|
|
38
|
+
parentModel: Model<any> | undefined,
|
|
46
39
|
modelInput: string | undefined,
|
|
47
40
|
modelFromParams: boolean,
|
|
48
|
-
registry: ModelRegistry,
|
|
41
|
+
registry: ModelRegistry | undefined,
|
|
49
42
|
): ModelResolution {
|
|
50
43
|
if (!modelInput) return { model: parentModel };
|
|
44
|
+
if (!registry) return { error: "No model registry available." };
|
|
51
45
|
const resolved = resolveModel(modelInput, registry);
|
|
52
46
|
if (typeof resolved !== "string") return { model: resolved };
|
|
53
47
|
if (modelFromParams) return { error: resolved };
|
|
@@ -62,9 +56,9 @@ export function resolveInvocationModel(
|
|
|
62
56
|
export function resolveModel(
|
|
63
57
|
input: string,
|
|
64
58
|
registry: ModelRegistry,
|
|
65
|
-
): any | string {
|
|
59
|
+
): Model<any> | string {
|
|
66
60
|
// Available models (those with auth configured)
|
|
67
|
-
const all =
|
|
61
|
+
const all = registry.getAvailable?.() ?? registry.getAll();
|
|
68
62
|
const availableSet = new Set(all.map(m => `${m.provider}/${m.id}`.toLowerCase()));
|
|
69
63
|
|
|
70
64
|
// 1. Exact match: "provider/modelId" — only if available (has auth)
|
|
@@ -79,10 +73,27 @@ export function resolveModel(
|
|
|
79
73
|
}
|
|
80
74
|
|
|
81
75
|
// 2. Fuzzy match against available models
|
|
82
|
-
const
|
|
76
|
+
const bestMatch = findBestFuzzyMatch(all, input.toLowerCase());
|
|
77
|
+
if (bestMatch) {
|
|
78
|
+
const found = registry.find(bestMatch.provider, bestMatch.id);
|
|
79
|
+
if (found) return found;
|
|
80
|
+
}
|
|
83
81
|
|
|
84
|
-
//
|
|
85
|
-
|
|
82
|
+
// 3. No match — list available models
|
|
83
|
+
const modelList = all
|
|
84
|
+
.map(m => ` ${m.provider}/${m.id}`)
|
|
85
|
+
.sort()
|
|
86
|
+
.join("\n");
|
|
87
|
+
return `Model not found: "${input}".\n\nAvailable models:\n${modelList}`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Score each candidate model — prefer exact id match > id contains > name
|
|
92
|
+
* contains > provider+id contains — and return the best match at or above
|
|
93
|
+
* the acceptance threshold (20), or undefined if nothing scores high enough.
|
|
94
|
+
*/
|
|
95
|
+
function findBestFuzzyMatch(all: Model<any>[], query: string): Model<any> | undefined {
|
|
96
|
+
let bestMatch: Model<any> | undefined;
|
|
86
97
|
let bestScore = 0;
|
|
87
98
|
|
|
88
99
|
for (const m of all) {
|
|
@@ -107,15 +118,5 @@ export function resolveModel(
|
|
|
107
118
|
}
|
|
108
119
|
}
|
|
109
120
|
|
|
110
|
-
|
|
111
|
-
const found = registry.find(bestMatch.provider, bestMatch.id);
|
|
112
|
-
if (found) return found;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// 3. No match — list available models
|
|
116
|
-
const modelList = all
|
|
117
|
-
.map(m => ` ${m.provider}/${m.id}`)
|
|
118
|
-
.sort()
|
|
119
|
-
.join("\n");
|
|
120
|
-
return `Model not found: "${input}".\n\nAvailable models:\n${modelList}`;
|
|
121
|
+
return bestScore >= 20 ? bestMatch : undefined;
|
|
121
122
|
}
|
package/src/tools/agent-tool.ts
CHANGED
|
@@ -8,7 +8,7 @@ import type { ParentSnapshot } from "#src/lifecycle/parent-snapshot";
|
|
|
8
8
|
import type { AgentSpawnConfig } from "#src/lifecycle/subagent-manager";
|
|
9
9
|
import { spawnBackground } from "#src/tools/background-spawner";
|
|
10
10
|
import { runForeground } from "#src/tools/foreground-runner";
|
|
11
|
-
import { buildDetails, buildTypeListText, textResult } from "#src/tools/helpers";
|
|
11
|
+
import { buildAgentGuidelines, buildDetails, buildTypeListText, textResult } from "#src/tools/helpers";
|
|
12
12
|
import { renderAgentResult } from "#src/tools/result-renderer";
|
|
13
13
|
import { type ModelInfo, resolveSpawnConfig } from "#src/tools/spawn-config";
|
|
14
14
|
import type { ParentSessionInfo, Subagent } from "#src/types";
|
|
@@ -42,6 +42,7 @@ export type AgentToolSettings = {
|
|
|
42
42
|
export class AgentTool {
|
|
43
43
|
private readonly typeListText: string;
|
|
44
44
|
private readonly availableTypesText: string;
|
|
45
|
+
private readonly agentGuidelines: string[];
|
|
45
46
|
|
|
46
47
|
constructor(
|
|
47
48
|
private readonly manager: AgentToolManager,
|
|
@@ -52,6 +53,7 @@ export class AgentTool {
|
|
|
52
53
|
) {
|
|
53
54
|
this.typeListText = buildTypeListText(registry, agentDir);
|
|
54
55
|
this.availableTypesText = registry.getAvailableTypes().join(", ");
|
|
56
|
+
this.agentGuidelines = buildAgentGuidelines(registry);
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
async execute(
|
|
@@ -128,6 +130,19 @@ export class AgentTool {
|
|
|
128
130
|
const agentDir = this.agentDir;
|
|
129
131
|
const registry = this.registry;
|
|
130
132
|
|
|
133
|
+
const guidelines = [
|
|
134
|
+
"- For parallel work, use run_in_background: true on each agent. Foreground calls run sequentially — only one executes at a time.",
|
|
135
|
+
...this.agentGuidelines,
|
|
136
|
+
"- Provide clear, detailed prompts so the agent can work autonomously.",
|
|
137
|
+
"- Subagent results are returned as text — summarize them for the user.",
|
|
138
|
+
"- Use run_in_background for work you don't need immediately. You will be notified when it completes.",
|
|
139
|
+
"- Use resume with an agent ID to continue a previous agent's work.",
|
|
140
|
+
"- Use steer_subagent to send mid-run messages to a running background agent.",
|
|
141
|
+
'- Use model to specify a different model (as "provider/modelId", or fuzzy e.g. "haiku", "sonnet").',
|
|
142
|
+
"- Use thinking to control extended thinking level.",
|
|
143
|
+
"- Use inherit_context if the agent needs the parent conversation history.",
|
|
144
|
+
].join("\n");
|
|
145
|
+
|
|
131
146
|
return defineTool({
|
|
132
147
|
name: "subagent" as const,
|
|
133
148
|
label: "Subagent",
|
|
@@ -140,18 +155,7 @@ Available agent types:
|
|
|
140
155
|
${typeListText}
|
|
141
156
|
|
|
142
157
|
Guidelines:
|
|
143
|
-
|
|
144
|
-
- Use Explore for codebase searches and code understanding.
|
|
145
|
-
- Use Plan for architecture and implementation planning.
|
|
146
|
-
- Use general-purpose for complex tasks that need file editing.
|
|
147
|
-
- Provide clear, detailed prompts so the agent can work autonomously.
|
|
148
|
-
- Subagent results are returned as text — summarize them for the user.
|
|
149
|
-
- Use run_in_background for work you don't need immediately. You will be notified when it completes.
|
|
150
|
-
- Use resume with an agent ID to continue a previous agent's work.
|
|
151
|
-
- Use steer_subagent to send mid-run messages to a running background agent.
|
|
152
|
-
- Use model to specify a different model (as "provider/modelId", or fuzzy e.g. "haiku", "sonnet").
|
|
153
|
-
- Use thinking to control extended thinking level.
|
|
154
|
-
- Use inherit_context if the agent needs the parent conversation history.
|
|
158
|
+
${guidelines}
|
|
155
159
|
`,
|
|
156
160
|
parameters: Type.Object({
|
|
157
161
|
prompt: Type.String({
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* get-result-report.ts — Pure report assembly for get_subagent_result.
|
|
3
|
+
*
|
|
4
|
+
* All functions are stateless: they receive an AgentReport, returning
|
|
5
|
+
* formatted strings. No SDK types, no timers, no side effects.
|
|
6
|
+
* Consumed by GetResultTool.execute in get-result-tool.ts. Mirrors the
|
|
7
|
+
* result-renderer.ts pattern used by the subagent tool's TUI renderer.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { SubagentStatus } from "#src/lifecycle/subagent";
|
|
11
|
+
|
|
12
|
+
/** The data a get_subagent_result report renders from — only what the formatter reads. */
|
|
13
|
+
export interface AgentReport {
|
|
14
|
+
id: string;
|
|
15
|
+
displayName: string;
|
|
16
|
+
status: SubagentStatus;
|
|
17
|
+
toolUses: number;
|
|
18
|
+
/** Pre-formatted lifetime token total; "" when zero. */
|
|
19
|
+
tokens: string;
|
|
20
|
+
contextPercent: number | null;
|
|
21
|
+
compactionCount: number;
|
|
22
|
+
/** Pre-formatted duration string. */
|
|
23
|
+
duration: string;
|
|
24
|
+
description: string;
|
|
25
|
+
result: string | undefined;
|
|
26
|
+
error: string | undefined;
|
|
27
|
+
/** Present only when verbose was requested and a conversation is available. */
|
|
28
|
+
conversation?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Assemble the stats parts: Tool uses / tokens? / Context? / Compactions? / Duration. */
|
|
32
|
+
export function renderStatsParts(report: AgentReport): string[] {
|
|
33
|
+
const parts = [`Tool uses: ${report.toolUses}`];
|
|
34
|
+
if (report.tokens) parts.push(report.tokens);
|
|
35
|
+
if (report.contextPercent !== null) parts.push(`Context: ${Math.round(report.contextPercent)}%`);
|
|
36
|
+
if (report.compactionCount) parts.push(`Compactions: ${report.compactionCount}`);
|
|
37
|
+
parts.push(`Duration: ${report.duration}`);
|
|
38
|
+
return parts;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Select the per-status body: running note, error line, or trimmed result. */
|
|
42
|
+
export function renderReportBody(report: AgentReport): string {
|
|
43
|
+
if (report.status === "running")
|
|
44
|
+
return "Agent is still running. Use wait: true or check back later.";
|
|
45
|
+
if (report.status === "error") return `Error: ${report.error}`;
|
|
46
|
+
return report.result?.trim() ?? "No output.";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Assemble the full get_subagent_result report text. */
|
|
50
|
+
export function formatAgentReport(report: AgentReport): string {
|
|
51
|
+
let output =
|
|
52
|
+
`Agent: ${report.id}\n` +
|
|
53
|
+
`Type: ${report.displayName} | Status: ${report.status} | ${renderStatsParts(report).join(" | ")}\n` +
|
|
54
|
+
`Description: ${report.description}\n\n`;
|
|
55
|
+
output += renderReportBody(report);
|
|
56
|
+
if (report.conversation) {
|
|
57
|
+
output += `\n\n--- Agent Conversation ---\n${report.conversation}`;
|
|
58
|
+
}
|
|
59
|
+
return output;
|
|
60
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { defineTool } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { Type } from "@sinclair/typebox";
|
|
3
3
|
import type { AgentConfigLookup } from "#src/config/agent-types";
|
|
4
|
+
import { type AgentReport, formatAgentReport } from "#src/tools/get-result-report";
|
|
4
5
|
import { formatLifetimeTokens, textResult } from "#src/tools/helpers";
|
|
5
6
|
import type { Subagent } from "#src/types";
|
|
6
7
|
import { formatDuration, getDisplayName } from "#src/ui/display";
|
|
@@ -12,7 +13,7 @@ export interface GetResultToolManager {
|
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
export interface GetResultToolNotifications {
|
|
15
|
-
|
|
16
|
+
consume(id: string): void;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
// ---- Class ----
|
|
@@ -37,53 +38,37 @@ export class GetResultTool {
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
// Wait for completion if requested.
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
//
|
|
41
|
+
// Consume BEFORE awaiting: onComplete fires inside .then() (attached
|
|
42
|
+
// earlier at spawn time) and always runs before this await resumes.
|
|
43
|
+
// Consuming here prevents a redundant follow-up notification.
|
|
43
44
|
if (params.wait && record.status === "running" && record.promise) {
|
|
44
|
-
|
|
45
|
-
// always runs before this await resumes. Prevents a redundant notification.
|
|
46
|
-
record.notification?.markConsumed();
|
|
47
|
-
this.notifications.cancelNudge(params.agent_id);
|
|
45
|
+
this.notifications.consume(params.agent_id);
|
|
48
46
|
await record.promise;
|
|
49
47
|
}
|
|
50
48
|
|
|
51
|
-
|
|
52
|
-
const duration = formatDuration(record.startedAt, record.completedAt);
|
|
53
|
-
const tokens = formatLifetimeTokens(record);
|
|
54
|
-
const contextPercent = record.getContextPercent();
|
|
55
|
-
const statsParts = [`Tool uses: ${record.toolUses}`];
|
|
56
|
-
if (tokens) statsParts.push(tokens);
|
|
57
|
-
if (contextPercent !== null) statsParts.push(`Context: ${Math.round(contextPercent)}%`);
|
|
58
|
-
if (record.compactionCount) statsParts.push(`Compactions: ${record.compactionCount}`);
|
|
59
|
-
statsParts.push(`Duration: ${duration}`);
|
|
60
|
-
|
|
61
|
-
let output =
|
|
62
|
-
`Agent: ${record.id}\n` +
|
|
63
|
-
`Type: ${displayName} | Status: ${record.status} | ${statsParts.join(" | ")}\n` +
|
|
64
|
-
`Description: ${record.description}\n\n`;
|
|
65
|
-
|
|
66
|
-
if (record.status === "running") {
|
|
67
|
-
output += "Agent is still running. Use wait: true or check back later.";
|
|
68
|
-
} else if (record.status === "error") {
|
|
69
|
-
output += `Error: ${record.error}`;
|
|
70
|
-
} else {
|
|
71
|
-
output += record.result?.trim() ?? "No output.";
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Mark result as consumed — suppresses the completion notification
|
|
49
|
+
// Consume the settled result — suppresses the completion notification.
|
|
75
50
|
if (record.status !== "running" && record.status !== "queued") {
|
|
76
|
-
|
|
77
|
-
this.notifications.cancelNudge(params.agent_id);
|
|
51
|
+
this.notifications.consume(params.agent_id);
|
|
78
52
|
}
|
|
79
53
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (conversation) {
|
|
83
|
-
output += `\n\n--- Agent Conversation ---\n${conversation}`;
|
|
84
|
-
}
|
|
54
|
+
return textResult(formatAgentReport(this.buildReport(record, params.verbose)));
|
|
55
|
+
}
|
|
85
56
|
|
|
86
|
-
|
|
57
|
+
private buildReport(record: Subagent, verbose?: boolean): AgentReport {
|
|
58
|
+
return {
|
|
59
|
+
id: record.id,
|
|
60
|
+
displayName: getDisplayName(record.type, this.registry),
|
|
61
|
+
status: record.status,
|
|
62
|
+
toolUses: record.toolUses,
|
|
63
|
+
tokens: formatLifetimeTokens(record),
|
|
64
|
+
contextPercent: record.getContextPercent(),
|
|
65
|
+
compactionCount: record.compactionCount,
|
|
66
|
+
duration: formatDuration(record.startedAt, record.completedAt),
|
|
67
|
+
description: record.description,
|
|
68
|
+
result: record.result,
|
|
69
|
+
error: record.error,
|
|
70
|
+
conversation: verbose ? record.getConversation() : undefined,
|
|
71
|
+
};
|
|
87
72
|
}
|
|
88
73
|
|
|
89
74
|
toToolDefinition() {
|
package/src/tools/helpers.ts
CHANGED
|
@@ -72,9 +72,8 @@ export interface TypeListRegistry extends AgentConfigLookup {
|
|
|
72
72
|
* Extracted from index.ts so it can be called inside createAgentTool.
|
|
73
73
|
*/
|
|
74
74
|
export function buildTypeListText(registry: TypeListRegistry, agentDir: string): string {
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
const userNames = registry.getUserAgentNames().filter(isEnabled);
|
|
75
|
+
const defaultNames = registry.getDefaultAgentNames().filter((name) => isEnabledAgent(registry, name));
|
|
76
|
+
const userNames = registry.getUserAgentNames().filter((name) => isEnabledAgent(registry, name));
|
|
78
77
|
|
|
79
78
|
const defaultDescs = defaultNames.map((name) => {
|
|
80
79
|
const cfg = registry.resolveAgentConfig(name);
|
|
@@ -88,14 +87,31 @@ export function buildTypeListText(registry: TypeListRegistry, agentDir: string):
|
|
|
88
87
|
});
|
|
89
88
|
|
|
90
89
|
return [
|
|
91
|
-
"Default agents:",
|
|
92
|
-
...defaultDescs,
|
|
90
|
+
...(defaultDescs.length > 0 ? ["Default agents:", ...defaultDescs] : []),
|
|
93
91
|
...(customDescs.length > 0 ? ["", "Custom agents:", ...customDescs] : []),
|
|
94
92
|
"",
|
|
95
93
|
`Custom agents can be defined in .pi/agents/<name>.md (project) or ${agentDir}/agents/<name>.md (global) — they are picked up automatically. Project-level agents override global ones. Creating a .md file with the same name as a default agent overrides it.`,
|
|
96
94
|
].join("\n");
|
|
97
95
|
}
|
|
98
96
|
|
|
97
|
+
/** True when an agent config is present and not explicitly disabled. */
|
|
98
|
+
function isEnabledAgent(registry: AgentConfigLookup, name: string): boolean {
|
|
99
|
+
return registry.resolveAgentConfig(name).enabled !== false;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Collect the per-agent usage guidelines for the subagent tool's Guidelines: block.
|
|
104
|
+
* Sourced from each enabled default agent's `toolGuideline`, in registry order,
|
|
105
|
+
* so a disabled built-in drops its guideline automatically.
|
|
106
|
+
*/
|
|
107
|
+
export function buildAgentGuidelines(registry: TypeListRegistry): string[] {
|
|
108
|
+
return registry
|
|
109
|
+
.getDefaultAgentNames()
|
|
110
|
+
.filter((name) => isEnabledAgent(registry, name))
|
|
111
|
+
.map((name) => registry.resolveAgentConfig(name).toolGuideline)
|
|
112
|
+
.filter((line): line is string => line !== undefined);
|
|
113
|
+
}
|
|
114
|
+
|
|
99
115
|
/** Derive a short model label from a model string. */
|
|
100
116
|
export function getModelLabelFromConfig(model: string): string {
|
|
101
117
|
// Strip provider prefix (e.g. "anthropic/claude-sonnet-4-6" → "claude-sonnet-4-6")
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-argument -- Pi SDK types are not fully exported; see upstream Pi SDK for type improvements */
|
|
2
1
|
/**
|
|
3
2
|
* spawn-config.ts — Pure config resolution for the Agent tool.
|
|
4
3
|
*
|
|
@@ -11,6 +10,7 @@ import type { Model } from "@earendil-works/pi-ai";
|
|
|
11
10
|
import type { AgentTypeRegistry } from "#src/config/agent-types";
|
|
12
11
|
import { resolveAgentInvocationConfig } from "#src/config/invocation-config";
|
|
13
12
|
import { normalizeMaxTurns } from "#src/lifecycle/turn-limits";
|
|
13
|
+
import type { ModelRegistry } from "#src/session/model-resolver";
|
|
14
14
|
import { resolveInvocationModel } from "#src/session/model-resolver";
|
|
15
15
|
import type { AgentInvocation, SubagentType, ThinkingLevel } from "#src/types";
|
|
16
16
|
import {
|
|
@@ -22,8 +22,8 @@ import {
|
|
|
22
22
|
|
|
23
23
|
/** Model info extracted from the parent session context. */
|
|
24
24
|
export interface ModelInfo {
|
|
25
|
-
parentModel:
|
|
26
|
-
modelRegistry:
|
|
25
|
+
parentModel: Model<any> | undefined;
|
|
26
|
+
modelRegistry: ModelRegistry | undefined;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/** Identity: who is being spawned. */
|
|
@@ -99,7 +99,7 @@ export function resolveSpawnConfig(
|
|
|
99
99
|
modelInfo.parentModel,
|
|
100
100
|
resolvedConfig.modelInput,
|
|
101
101
|
resolvedConfig.modelFromParams,
|
|
102
|
-
modelInfo.modelRegistry
|
|
102
|
+
modelInfo.modelRegistry,
|
|
103
103
|
);
|
|
104
104
|
if (resolution.error) return { error: resolution.error };
|
|
105
105
|
const model = resolution.model;
|
|
@@ -113,7 +113,7 @@ export function resolveSpawnConfig(
|
|
|
113
113
|
const effectiveModelId = model?.id;
|
|
114
114
|
const modelName =
|
|
115
115
|
effectiveModelId && effectiveModelId !== parentModelId
|
|
116
|
-
?
|
|
116
|
+
? model.name.replace(/^Claude\s+/i, "").toLowerCase()
|
|
117
117
|
: undefined;
|
|
118
118
|
|
|
119
119
|
const effectiveMaxTurns = normalizeMaxTurns(
|
package/src/tools/steer-tool.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineTool } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { Type } from "@sinclair/typebox";
|
|
3
3
|
import { formatLifetimeTokens, textResult } from "#src/tools/helpers";
|
|
4
|
-
import type { Subagent } from "#src/types";
|
|
4
|
+
import type { SteerOutcome, Subagent } from "#src/types";
|
|
5
5
|
|
|
6
6
|
// ---- Deps interfaces ----
|
|
7
7
|
|
|
@@ -34,41 +34,51 @@ export class SteerTool {
|
|
|
34
34
|
`Agent not found: "${params.agent_id}". It may have been cleaned up.`,
|
|
35
35
|
);
|
|
36
36
|
}
|
|
37
|
-
|
|
37
|
+
|
|
38
|
+
let outcome: SteerOutcome;
|
|
39
|
+
try {
|
|
40
|
+
outcome = await record.steer(params.message);
|
|
41
|
+
} catch (err) {
|
|
38
42
|
return textResult(
|
|
39
|
-
`
|
|
43
|
+
`Failed to steer agent: ${err instanceof Error ? err.message : String(err)}`,
|
|
40
44
|
);
|
|
41
45
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (!delivered) {
|
|
46
|
+
|
|
47
|
+
switch (outcome.kind) {
|
|
48
|
+
case "rejected":
|
|
46
49
|
return textResult(
|
|
47
|
-
`
|
|
50
|
+
`Agent "${params.agent_id}" is not running (status: ${outcome.status}). Cannot steer a non-running agent.`,
|
|
48
51
|
);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (tokens) stateParts.push(tokens);
|
|
54
|
-
stateParts.push(`${record.toolUses} tool ${record.toolUses === 1 ? "use" : "uses"}`);
|
|
55
|
-
if (contextPercent !== null)
|
|
56
|
-
stateParts.push(`context ${Math.round(contextPercent)}% full`);
|
|
57
|
-
if (record.compactionCount)
|
|
58
|
-
stateParts.push(
|
|
59
|
-
`${record.compactionCount} compaction${record.compactionCount === 1 ? "" : "s"}`,
|
|
52
|
+
case "buffered":
|
|
53
|
+
this.events.emit("subagents:steered", { id: record.id, message: params.message });
|
|
54
|
+
return textResult(
|
|
55
|
+
`Steering message queued for agent ${record.id}. It will be delivered once the session initializes.`,
|
|
60
56
|
);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
);
|
|
65
|
-
} catch (err) {
|
|
66
|
-
return textResult(
|
|
67
|
-
`Failed to steer agent: ${err instanceof Error ? err.message : String(err)}`,
|
|
68
|
-
);
|
|
57
|
+
case "delivered":
|
|
58
|
+
this.events.emit("subagents:steered", { id: record.id, message: params.message });
|
|
59
|
+
return this.renderDelivered(record);
|
|
69
60
|
}
|
|
70
61
|
}
|
|
71
62
|
|
|
63
|
+
/** Render the success message with live state for a delivered steer. */
|
|
64
|
+
private renderDelivered(record: Subagent) {
|
|
65
|
+
const tokens = formatLifetimeTokens(record);
|
|
66
|
+
const contextPercent = record.getContextPercent();
|
|
67
|
+
const stateParts: string[] = [];
|
|
68
|
+
if (tokens) stateParts.push(tokens);
|
|
69
|
+
stateParts.push(`${record.toolUses} tool ${record.toolUses === 1 ? "use" : "uses"}`);
|
|
70
|
+
if (contextPercent !== null)
|
|
71
|
+
stateParts.push(`context ${Math.round(contextPercent)}% full`);
|
|
72
|
+
if (record.compactionCount)
|
|
73
|
+
stateParts.push(
|
|
74
|
+
`${record.compactionCount} compaction${record.compactionCount === 1 ? "" : "s"}`,
|
|
75
|
+
);
|
|
76
|
+
return textResult(
|
|
77
|
+
`Steering message sent to agent ${record.id}. The agent will process it after its current tool execution.\n` +
|
|
78
|
+
`Current state: ${stateParts.join(" · ")}`,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
72
82
|
toToolDefinition() {
|
|
73
83
|
return defineTool({
|
|
74
84
|
name: "steer_subagent" as const,
|
package/src/types.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type { AgentSessionEvent, SessionContext as SdkSessionContext } from "@ea
|
|
|
7
7
|
import type { ModelRegistry } from "#src/session/model-resolver";
|
|
8
8
|
|
|
9
9
|
|
|
10
|
+
export type { SteerOutcome } from "#src/lifecycle/subagent";
|
|
10
11
|
export { Subagent } from "#src/lifecycle/subagent";
|
|
11
12
|
export type { AgentSessionEvent, ThinkingLevel };
|
|
12
13
|
|
|
@@ -55,6 +56,8 @@ export interface AgentConfig extends AgentIdentity, AgentPromptConfig {
|
|
|
55
56
|
inheritContext?: boolean;
|
|
56
57
|
/** Default for spawn: run in background. undefined = caller decides. */
|
|
57
58
|
runInBackground?: boolean;
|
|
59
|
+
/** One-line usage guideline for the subagent tool's Guidelines: block. Omitted — no guideline line. */
|
|
60
|
+
toolGuideline?: string;
|
|
58
61
|
/** true = this is an embedded default agent (informational) */
|
|
59
62
|
isDefault?: boolean;
|
|
60
63
|
/** false = agent is hidden from the registry */
|
|
@@ -108,7 +111,7 @@ export interface ParentSessionInfo {
|
|
|
108
111
|
parentSessionFile?: string;
|
|
109
112
|
/** Session ID of the parent agent (stored in the child session's parentSession header). */
|
|
110
113
|
parentSessionId?: string;
|
|
111
|
-
/** Tool call ID for background notification wiring.
|
|
114
|
+
/** Tool call ID for background notification wiring. Exposed on the record via Subagent.toolCallId. */
|
|
112
115
|
toolCallId?: string;
|
|
113
116
|
}
|
|
114
117
|
|
|
@@ -167,7 +167,6 @@ export class TranscriptOverlay implements Component {
|
|
|
167
167
|
});
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
// fallow-ignore-next-line unused-class-member
|
|
171
170
|
handleInput(data: string): void {
|
|
172
171
|
if (matchesKey(data, "escape") || matchesKey(data, "q")) {
|
|
173
172
|
this.closed = true;
|
|
@@ -244,7 +243,6 @@ export class TranscriptOverlay implements Component {
|
|
|
244
243
|
this.content.invalidate();
|
|
245
244
|
}
|
|
246
245
|
|
|
247
|
-
// fallow-ignore-next-line unused-class-member
|
|
248
246
|
dispose(): void {
|
|
249
247
|
this.closed = true;
|
|
250
248
|
if (this.unsubscribe) {
|
package/.prettierignore
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
# This fork does not use Prettier — formatting is handled by Biome
|
|
2
|
-
# (see biome.json and the sibling Pi-package conventions). Ignore all
|
|
3
|
-
# files to prevent Prettier from being run accidentally (e.g. by an
|
|
4
|
-
# agent harness with project-level write-time Prettier formatting).
|
|
5
|
-
*
|
package/AGENTS.md
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
# AGENTS.md
|
|
2
|
-
|
|
3
|
-
⚠️ It looks like the agent was started from a package subdirectory.
|
|
4
|
-
|
|
5
|
-
Advise the user to launch Pi from the **repository root** (`pi-packages/`) instead.
|
|
6
|
-
The root provides `.pi/settings.json`, `.pi/prompts/`, and the full skill set.
|
|
7
|
-
Package-specific context for this package is available via the `package-pi-subagents` skill.
|