@hheei/pi-subagents 0.1.2 → 0.2.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.
Files changed (65) hide show
  1. package/README.md +42 -137
  2. package/dist/agent-resolver.d.ts +20 -0
  3. package/dist/agent-resolver.js +155 -21
  4. package/dist/bridge-client.d.ts +55 -0
  5. package/dist/bridge-client.js +453 -0
  6. package/dist/bridge-server.d.ts +72 -0
  7. package/dist/bridge-server.js +490 -0
  8. package/dist/builtin-agents.d.ts +24 -0
  9. package/dist/builtin-agents.js +152 -0
  10. package/dist/child-bridge.d.ts +31 -15
  11. package/dist/child-bridge.js +95 -117
  12. package/dist/child-control.d.ts +58 -0
  13. package/dist/child-control.js +176 -0
  14. package/dist/child-process.d.ts +21 -0
  15. package/dist/child-process.js +93 -0
  16. package/dist/commands.d.ts +2 -2
  17. package/dist/commands.js +52 -52
  18. package/dist/diagnostics.d.ts +0 -2
  19. package/dist/diagnostics.js +0 -8
  20. package/dist/domain.d.ts +57 -27
  21. package/dist/domain.js +60 -11
  22. package/dist/extension.d.ts +26 -1
  23. package/dist/extension.js +243 -46
  24. package/dist/host-adapter.d.ts +37 -12
  25. package/dist/host-adapter.js +214 -63
  26. package/dist/json-lines.js +2 -1
  27. package/dist/launch-spec.d.ts +8 -6
  28. package/dist/launch-spec.js +61 -18
  29. package/dist/manager.d.ts +93 -49
  30. package/dist/manager.js +1175 -528
  31. package/dist/markdown.d.ts +8 -0
  32. package/dist/markdown.js +21 -0
  33. package/dist/protocol.d.ts +33 -52
  34. package/dist/protocol.js +41 -52
  35. package/dist/registry.d.ts +3 -8
  36. package/dist/registry.js +41 -163
  37. package/dist/rpc-events.d.ts +3 -5
  38. package/dist/rpc-events.js +5 -9
  39. package/dist/runtime.d.ts +66 -11
  40. package/dist/runtime.js +182 -208
  41. package/dist/session-bootstrap.d.ts +23 -7
  42. package/dist/session-bootstrap.js +79 -15
  43. package/dist/session-fork.d.ts +16 -0
  44. package/dist/session-fork.js +67 -0
  45. package/dist/state.d.ts +7 -0
  46. package/dist/state.js +60 -25
  47. package/dist/tool-activation.d.ts +18 -0
  48. package/dist/tool-activation.js +227 -0
  49. package/dist/tools.d.ts +6 -3
  50. package/dist/tools.js +213 -72
  51. package/dist/widget.d.ts +4 -8
  52. package/dist/widget.js +55 -64
  53. package/package.json +51 -52
  54. package/dist/child-nudge.d.ts +0 -24
  55. package/dist/child-nudge.js +0 -102
  56. package/dist/connector.d.ts +0 -53
  57. package/dist/connector.js +0 -283
  58. package/dist/pause-gate.d.ts +0 -14
  59. package/dist/pause-gate.js +0 -64
  60. package/dist/rpc-adapter.d.ts +0 -40
  61. package/dist/rpc-adapter.js +0 -194
  62. package/dist/runner-entry.d.ts +0 -24
  63. package/dist/runner-entry.js +0 -166
  64. package/dist/runner.d.ts +0 -52
  65. package/dist/runner.js +0 -930
package/dist/manager.d.ts CHANGED
@@ -1,7 +1,19 @@
1
- import type { EffectiveLaunchConfig, OperationError, PublicSubagent, SendMode, SpawnSubagentInput, SubagentRecord, SubagentState } from "./domain.js";
2
- import type { HostKind, HostSelection } from "./host-adapter.js";
1
+ import { type TaskRegistry } from "@hheei/pi-ext-core";
2
+ import type { ChildRuntime } from "./child-process.js";
3
+ import type { EffectiveLaunchConfig, OperationError, Presentation, PublicSubagent, SendMode, SpawnSubagentInput, SubagentRecord, SubagentState } from "./domain.js";
4
+ import type { HostAttachment } from "./host-adapter.js";
5
+ import { type BridgeOperation } from "./protocol.js";
3
6
  import type { SubagentRegistry } from "./registry.js";
4
- import type { RuntimeTokenStore } from "./runtime.js";
7
+ import type { LaunchOutcome, RuntimeTokenStore } from "./runtime.js";
8
+ /**
9
+ * How long an idle child keeps its runtime. A background child holds a whole Pi process and its
10
+ * session lock, so an idle one is reclaimed after this window and a later `send_agent` starts it
11
+ * again from the same session.
12
+ */
13
+ export declare const SUBAGENT_IDLE_TIMEOUT_MS = 15000;
14
+ export declare const SUBAGENT_SETTLED_CLOSE_TIMEOUT_MS = 15000;
15
+ /** How long stop waits for an adopted child's bridge to go away before calling the exit unconfirmed. */
16
+ export declare const SUBAGENT_EXIT_WAIT_MS = 2000;
5
17
  export interface ParentChannelReport {
6
18
  readonly parentSessionId: string;
7
19
  readonly childId: string;
@@ -14,34 +26,21 @@ export interface ParentChannelReport {
14
26
  export interface ParentChannel {
15
27
  deliver(report: ParentChannelReport): Promise<void>;
16
28
  }
17
- export interface RunnerLike {
18
- readonly connected: boolean;
19
- request(operation: "prompt" | "steer" | "follow_up" | "get_state" | "get_entries" | "shutdown" | "pause" | "cancel_pause" | "close_writer" | "start_rpc", payload?: unknown, options?: {
29
+ /**
30
+ * The parent side of the bridge, as the manager needs it: one connection per child, requests the
31
+ * parent may send, and the events and connection transitions the child reports. Liveness is a
32
+ * connection: no other channel can say whether this child is still running.
33
+ */
34
+ export interface ChildBridgeTransport {
35
+ isConnected(childId: string): boolean;
36
+ /** Ends a child's connection from this side, for a process that stopped being this child. */
37
+ disconnect(childId: string): void;
38
+ request(childId: string, operation: BridgeOperation, payload?: unknown, options?: {
20
39
  readonly timeoutMs?: number;
21
40
  readonly signal?: AbortSignal;
22
41
  }): Promise<unknown>;
23
- close(): void;
24
- onEvent(listener: (event: unknown) => void): () => void;
25
- }
26
- export interface AttachHost {
27
- select(preferredHost?: HostKind): Promise<HostSelection>;
28
- }
29
- export interface AttachOptions {
30
- readonly preferredHost?: HostKind;
31
- readonly signal?: AbortSignal;
32
- }
33
- export interface AttachResult {
34
- readonly child: PublicSubagent;
35
- readonly host: HostKind;
36
- readonly attachmentId: string;
37
- }
38
- export type DetachOrigin = "tui_exit" | "tui_crash" | "session_switch" | "manual";
39
- export interface DetachOptions {
40
- readonly origin: DetachOrigin;
41
- /** Close the host pane. False when session B still owns that TUI process. */
42
- readonly closeHost?: boolean;
43
- /** Operation label reported in failures; defaults to "detach". */
44
- readonly operation?: string;
42
+ onEvent(listener: (childId: string, event: unknown) => void): () => void;
43
+ onConnectionChange(listener: (childId: string, connected: boolean) => void): () => void;
45
44
  }
46
45
  export interface ManagerDependencies {
47
46
  readonly parentSessionId: string;
@@ -51,17 +50,40 @@ export interface ManagerDependencies {
51
50
  readonly parentSessionId: string;
52
51
  readonly task: string;
53
52
  readonly launchConfig: EffectiveLaunchConfig;
53
+ readonly presentation: Presentation;
54
54
  }) => Promise<SubagentRecord>;
55
- readonly launch: (record: SubagentRecord) => Promise<RunnerLike>;
56
- readonly connect?: (record: SubagentRecord) => Promise<RunnerLike>;
55
+ readonly bridge: ChildBridgeTransport;
56
+ /** Starts a background runtime for this record and resolves once the child has connected. */
57
+ readonly launch: (record: SubagentRecord) => Promise<LaunchOutcome<ChildRuntime>>;
58
+ /**
59
+ * Presentation hosts of this parent. Absent when no panel host is available, in which case every
60
+ * child runs in the background; `hostReason` is what the spawn result tells the caller, so a
61
+ * fallback is visible instead of silent.
62
+ */
63
+ readonly presentation?: PresentationDeps;
64
+ /** Waits for an already-running runtime to reconnect; false when it does not. */
65
+ readonly connect: (record: SubagentRecord) => Promise<boolean>;
57
66
  readonly deadlineMs?: number;
58
- readonly watchIntervalMs?: number;
67
+ readonly settledCloseTimeoutMs?: number;
68
+ readonly idleTimeoutMs?: number;
69
+ readonly failedPanelCloseTimeoutMs?: number;
59
70
  readonly channel?: ParentChannel;
60
- readonly attachHost?: AttachHost;
61
71
  readonly tokens?: RuntimeTokenStore;
62
72
  }
73
+ /**
74
+ * How this parent presents children, as the manager needs it: something that opens a panel for a
75
+ * record and resolves once the child has connected, plus the reason for that state of affairs,
76
+ * which is said out loud when a child falls back to the background.
77
+ */
78
+ export interface PresentationDeps {
79
+ readonly reason: string;
80
+ /** Absent when this parent has no presentation host, which makes every child a background one. */
81
+ readonly openPanel?: (record: SubagentRecord) => Promise<LaunchOutcome<HostAttachment>>;
82
+ }
63
83
  export interface SpawnResult {
64
84
  readonly child: PublicSubagent;
85
+ /** Set when the child did not run where it would have by default. */
86
+ readonly note?: string;
65
87
  }
66
88
  export interface RecoveryResult {
67
89
  readonly recovered: readonly string[];
@@ -70,32 +92,54 @@ export interface RecoveryResult {
70
92
  readonly reason: string;
71
93
  }[];
72
94
  }
95
+ /**
96
+ * Extracts the trailing text of the most recent assistant message in session entries.
97
+ * Used to automatically capture a subagent's final output without requiring a tool call.
98
+ */
99
+ export declare function extractLastAssistantText(entries: readonly unknown[]): string | undefined;
73
100
  export declare class SubagentManager {
74
101
  #private;
102
+ bindTaskRegistry(registry: TaskRegistry): () => void;
75
103
  constructor(deps: ManagerDependencies);
104
+ /**
105
+ * Observes the raw bridge events of every child. A Task producer needs the child's
106
+ * `task_result` and settle events without also owning the bridge connection.
107
+ */
108
+ onChildEvent(listener: (childId: string, event: unknown) => void): () => void;
76
109
  /** Presentation-only: widget and similar projections re-read list() after this. */
77
110
  onChange(listener: () => void): () => void;
78
- /** Reattaches active persisted children without replaying any historical input. */
111
+ dispose(): void;
112
+ /**
113
+ * Releases this process's local view of its children. Child processes are deliberately left
114
+ * alone: a background child is held by its stdin pipe, so it ends when this Pi process ends and
115
+ * not when extensions are reloaded.
116
+ */
117
+ closeLocalConnections(): void;
118
+ /** Reads a child's session entries; exposed for Task completion inspection. */
119
+ getEntries(id: string): Promise<readonly unknown[] | undefined>;
120
+ /**
121
+ * Adopts the children that are still running. Nothing is launched here: a child that survived a
122
+ * parent restart reconnects its bridge by itself, and a child that did not is simply not live
123
+ * until a later send starts it from its recorded session.
124
+ */
79
125
  recover(): Promise<RecoveryResult>;
80
126
  spawn(input: SpawnSubagentInput): Promise<SpawnResult | OperationError>;
81
- send(id: string, message: string, mode?: SendMode, signal?: AbortSignal): Promise<OperationError | PublicSubagent>;
127
+ send(id: string, rawMessage: string, mode?: SendMode, signal?: AbortSignal): Promise<OperationError | PublicSubagent>;
82
128
  get(id: string): Promise<PublicSubagent | OperationError>;
83
129
  list(): Promise<readonly PublicSubagent[]>;
84
- stop(id: string, signal?: AbortSignal): Promise<OperationError | PublicSubagent>;
85
- ownsHostAttachment(identity: {
86
- readonly host: HostKind;
87
- readonly attachmentId: string;
88
- }): boolean;
89
- attach(id: string, options?: AttachOptions): Promise<AttachResult | OperationError>;
90
- restoreRpc(id: string): Promise<OperationError | PublicSubagent>;
91
- detach(id: string, options: DetachOptions): Promise<OperationError | PublicSubagent>;
92
- inspectHost(id: string): Promise<OperationError | PublicSubagent | {
93
- readonly alive: boolean;
94
- readonly known: boolean;
95
- readonly detail: string;
96
- }>;
97
- contactParent(id: string, reason: string, message: string): Promise<OperationError | {
130
+ /** Child startup and runs count until Pi settles, including post-agent_end continuation. */
131
+ get activeCount(): number;
132
+ stop(id: string): Promise<OperationError | PublicSubagent>;
133
+ contactParent(id: string, reason: string, message: string, knownRecord?: SubagentRecord): Promise<OperationError | {
98
134
  readonly delivered: true;
99
135
  }>;
100
- closeLocalConnections(): void;
136
+ /**
137
+ * Handles a request a child sent to its parent. The two child-initiated operations are the
138
+ * child's report channel and its Task result, and both are answered here so the child learns
139
+ * whether the parent accepted them.
140
+ */
141
+ handleChildRequest(childId: string, operation: string, payload: unknown): Promise<unknown>;
142
+ /** Applies a bridge event to this child's record and notifies the raw child-event listeners. */
143
+ handleEvent(childId: string, event: unknown): void;
144
+ handleConnectionChange(childId: string, connected: boolean): void;
101
145
  }