@nklisch/pi-enhanced 0.2.7 → 0.3.0
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 +10 -0
- package/node_modules/@nklisch/pi-clearance/native/clearance-core.linux-x64-gnu.node +0 -0
- package/node_modules/@nklisch/pi-clearance/native/clearance-core.win32-x64-msvc.node +0 -0
- package/node_modules/@nklisch/pi-plugins/README.md +4 -2
- package/node_modules/@nklisch/pi-plugins/dist/hooks.js +81 -8
- package/node_modules/@nklisch/pi-plugins/dist/hooks.js.map +1 -1
- package/node_modules/@nklisch/pi-plugins/dist/mcp.js +32 -1
- package/node_modules/@nklisch/pi-plugins/dist/mcp.js.map +1 -1
- package/node_modules/@nklisch/pi-plugins/dist/pi/plugin-manager.d.ts +10 -4
- package/node_modules/@nklisch/pi-plugins/dist/pi/plugin-manager.js +144 -10
- package/node_modules/@nklisch/pi-plugins/dist/pi/plugin-manager.js.map +1 -1
- package/node_modules/@nklisch/pi-plugins/dist/runtime-discovery.js +40 -14
- package/node_modules/@nklisch/pi-plugins/dist/runtime-discovery.js.map +1 -1
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/CHANGELOG.md +19 -0
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/README.md +75 -47
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/dist/public.d.ts +171 -140
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/dist/settings.d.ts +2 -2
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/FORK-MAINTENANCE.md +8 -7
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/VISION.md +12 -10
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/architecture.md +111 -104
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/comparison-with-upstream.md +3 -3
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/decisions/0004-reconsider-ui-direction.md +5 -0
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/package.json +1 -1
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/config/custom-agents.ts +31 -4
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/config/default-agents.ts +1 -1
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/config/invocation-config.ts +7 -4
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/index.ts +18 -9
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/layered-settings.ts +2 -2
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/child-lifecycle.ts +10 -63
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/concurrency-limiter.ts +122 -76
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/create-subagent-session.ts +3 -5
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/lifecycle-interceptor.ts +4 -3
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/run-listeners.ts +2 -23
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/subagent-manager.ts +177 -252
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/subagent-session.ts +90 -280
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/subagent-state.ts +153 -239
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/subagent.ts +569 -700
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/workspace.ts +1 -1
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/observation/notification.ts +78 -122
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/observation/renderer.ts +15 -42
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/observation/subagent-events-observer.ts +44 -95
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/service/service-adapter.ts +157 -90
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/service/service.ts +60 -68
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/session/conversation.ts +3 -3
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/session/query-source.ts +28 -0
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/session/query.ts +327 -0
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/settings.ts +1 -1
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/agent-tool.ts +171 -249
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/get-result-tool.ts +51 -94
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/helpers.ts +9 -6
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/list-tool.ts +46 -0
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/parent-tool-registry.ts +17 -0
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/query-session-tool.ts +330 -0
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/result-renderer.ts +27 -111
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/resume-tool.ts +105 -0
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/spawn-config.ts +26 -8
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/steer-tool.ts +27 -111
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/stop-tool.ts +53 -0
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/types.ts +11 -5
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/agent-widget.ts +33 -27
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/display.ts +6 -3
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/session-navigation.ts +121 -10
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/session-navigator.ts +430 -112
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/subagents-settings.ts +1 -1
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/widget-renderer.ts +8 -9
- package/node_modules/@nklisch/pi-plugins/package.json +2 -2
- package/package.json +1 -1
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/background-spawner.ts +0 -81
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/foreground-runner.ts +0 -149
- package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/get-result-report.ts +0 -77
|
@@ -3,20 +3,22 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Splits the unit-testable core of the `/subagents:sessions` command from its TUI
|
|
5
5
|
* wiring (`session-navigator.ts`): which subagents are navigable and how a picked
|
|
6
|
-
* agent's transcript is sourced (live
|
|
6
|
+
* agent's transcript is sourced (live or a retained file snapshot).
|
|
7
7
|
*
|
|
8
8
|
* The `TranscriptSource` seam decouples *how messages are sourced* (live record
|
|
9
|
-
*
|
|
9
|
+
* or a retained file snapshot) from *how they render* — the renderer
|
|
10
10
|
* (`session-navigator.ts`, which mounts Pi's per-entry components) talks only to
|
|
11
11
|
* this seam. Rendering lives in the SDK/TUI module because the per-entry
|
|
12
|
-
* components require a `TUI`, `cwd`, and markdown theme.
|
|
12
|
+
* components require a `TUI`, `cwd`, and markdown theme. The query tool uses
|
|
13
|
+
* the same JSONL adapter so file and live reads cannot drift.
|
|
13
14
|
*/
|
|
14
15
|
|
|
15
|
-
import
|
|
16
|
+
import type { ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
16
17
|
import type { AgentConfigLookup } from "#src/config/agent-types";
|
|
17
18
|
import type { SubagentStatus } from "#src/lifecycle/subagent-state";
|
|
18
19
|
import type { AgentSessionEvent, SessionMessage, SubagentType, ThinkingLevel } from "#src/types";
|
|
19
20
|
import { formatDuration, formatModelThinking, getDisplayName } from "#src/ui/display";
|
|
21
|
+
import { parseSessionFileMessages } from "#src/session/query-source";
|
|
20
22
|
|
|
21
23
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
22
24
|
|
|
@@ -37,14 +39,17 @@ export interface NavigableSubagent {
|
|
|
37
39
|
readonly agentMessages: readonly SessionMessage[];
|
|
38
40
|
isSessionReady(): boolean;
|
|
39
41
|
subscribeToUpdates(fn: (event: AgentSessionEvent) => void): (() => void) | undefined;
|
|
42
|
+
/** Notifies consumers when a retained session is released and changes source. */
|
|
43
|
+
subscribeToRecordUpdates?: (fn: () => void) => () => void;
|
|
40
44
|
getToolDefinition(name: string): ToolDefinition | undefined;
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
/**
|
|
44
48
|
* A navigable entry plus the label shown in the picker.
|
|
45
49
|
*
|
|
46
|
-
* A `live` entry sources its transcript from the in-memory session
|
|
47
|
-
* `evicted`-kind entry is a persisted
|
|
50
|
+
* A `live` entry sources its transcript from the in-memory session and can
|
|
51
|
+
* transition to its retained file; an `evicted`-kind entry is a persisted
|
|
52
|
+
* snapshot for a released live session.
|
|
48
53
|
*/
|
|
49
54
|
export interface RunDisplayMetadata {
|
|
50
55
|
readonly modelLabel: string;
|
|
@@ -75,6 +80,12 @@ export interface StreamingState {
|
|
|
75
80
|
readonly responseText: string;
|
|
76
81
|
}
|
|
77
82
|
|
|
83
|
+
/** Source state shown when a live record is released or its snapshot cannot load. */
|
|
84
|
+
export type TranscriptSourceAvailability =
|
|
85
|
+
| { readonly kind: "live"; readonly path?: string }
|
|
86
|
+
| { readonly kind: "file"; readonly path: string }
|
|
87
|
+
| { readonly kind: "unavailable"; readonly path?: string; readonly error?: string };
|
|
88
|
+
|
|
78
89
|
/** Liveness-agnostic transcript source consumed by the renderer. */
|
|
79
90
|
export interface TranscriptSource {
|
|
80
91
|
/** Current message history. */
|
|
@@ -85,6 +96,8 @@ export interface TranscriptSource {
|
|
|
85
96
|
streaming(): StreamingState | undefined;
|
|
86
97
|
/** Resolve a registered tool definition by name, for Pi's tool-execution components. */
|
|
87
98
|
getToolDefinition(name: string): ToolDefinition | undefined;
|
|
99
|
+
/** Current source state; unavailable retains the last readable messages. */
|
|
100
|
+
availability?(): TranscriptSourceAvailability;
|
|
88
101
|
}
|
|
89
102
|
|
|
90
103
|
/**
|
|
@@ -126,18 +139,17 @@ export function fileSnapshotSource(
|
|
|
126
139
|
outputFile: string,
|
|
127
140
|
readFile: (path: string) => string,
|
|
128
141
|
): TranscriptSource {
|
|
129
|
-
const
|
|
130
|
-
const sessionEntries = entries.filter((entry): entry is SessionEntry => entry.type !== "session");
|
|
131
|
-
const { messages } = buildSessionContext(sessionEntries);
|
|
142
|
+
const messages = parseSessionFileMessages(readFile(outputFile));
|
|
132
143
|
return {
|
|
133
144
|
getMessages: () => messages,
|
|
134
145
|
subscribe: () => undefined,
|
|
135
146
|
streaming: () => undefined,
|
|
136
147
|
getToolDefinition: () => undefined,
|
|
148
|
+
availability: () => ({ kind: "file", path: outputFile }),
|
|
137
149
|
};
|
|
138
150
|
}
|
|
139
151
|
|
|
140
|
-
/** Source a transcript live from an in-memory record
|
|
152
|
+
/** Source a transcript live from an in-memory record. */
|
|
141
153
|
export function liveSource(record: NavigableSubagent): TranscriptSource {
|
|
142
154
|
return {
|
|
143
155
|
getMessages: () => record.agentMessages,
|
|
@@ -147,6 +159,105 @@ export function liveSource(record: NavigableSubagent): TranscriptSource {
|
|
|
147
159
|
? { activeTools: record.activeTools, responseText: record.responseText }
|
|
148
160
|
: undefined,
|
|
149
161
|
getToolDefinition: (name) => record.getToolDefinition(name),
|
|
162
|
+
availability: () => ({ kind: "live", ...(record.outputFile ? { path: record.outputFile } : {}) }),
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Keep a live viewer useful across retention release. The source swaps to the
|
|
168
|
+
* persisted snapshot on the release notification and retains the last live
|
|
169
|
+
* content when that snapshot cannot be read.
|
|
170
|
+
*/
|
|
171
|
+
export function liveFileSource(
|
|
172
|
+
record: NavigableSubagent,
|
|
173
|
+
readFile: (path: string) => string,
|
|
174
|
+
): TranscriptSource {
|
|
175
|
+
let mode: "live" | "file" | "unavailable" = record.isSessionReady() ? "live" : "unavailable";
|
|
176
|
+
let messages: readonly SessionMessage[] = record.agentMessages;
|
|
177
|
+
let error: string | undefined;
|
|
178
|
+
let fileAttempted = false;
|
|
179
|
+
|
|
180
|
+
const swapIfReleased = (): void => {
|
|
181
|
+
if (record.isSessionReady()) {
|
|
182
|
+
mode = "live";
|
|
183
|
+
error = undefined;
|
|
184
|
+
messages = record.agentMessages;
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (fileAttempted || !record.outputFile) {
|
|
188
|
+
if (!record.outputFile && mode === "live") mode = "unavailable";
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
fileAttempted = true;
|
|
192
|
+
try {
|
|
193
|
+
messages = parseSessionFileMessages(readFile(record.outputFile));
|
|
194
|
+
mode = "file";
|
|
195
|
+
error = undefined;
|
|
196
|
+
} catch (cause) {
|
|
197
|
+
mode = "unavailable";
|
|
198
|
+
error = cause instanceof Error ? cause.message : String(cause);
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const notify = (onChange: () => void): void => {
|
|
203
|
+
try {
|
|
204
|
+
// Do not replace the last live snapshot with Subagent's empty post-release
|
|
205
|
+
// getter before the file adapter succeeds; the degraded path must retain
|
|
206
|
+
// content that was already visible.
|
|
207
|
+
if (mode === "live" && record.isSessionReady()) messages = record.agentMessages;
|
|
208
|
+
swapIfReleased();
|
|
209
|
+
onChange();
|
|
210
|
+
} catch (cause) {
|
|
211
|
+
mode = "unavailable";
|
|
212
|
+
error = cause instanceof Error ? cause.message : String(cause);
|
|
213
|
+
onChange();
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
return {
|
|
218
|
+
getMessages: () => {
|
|
219
|
+
try {
|
|
220
|
+
if (mode === "live") {
|
|
221
|
+
if (!record.isSessionReady()) swapIfReleased();
|
|
222
|
+
else messages = record.agentMessages;
|
|
223
|
+
} else swapIfReleased();
|
|
224
|
+
} catch (cause) {
|
|
225
|
+
mode = "unavailable";
|
|
226
|
+
error = cause instanceof Error ? cause.message : String(cause);
|
|
227
|
+
}
|
|
228
|
+
return messages;
|
|
229
|
+
},
|
|
230
|
+
subscribe: (onChange) => {
|
|
231
|
+
const unsubscribers: Array<() => void> = [];
|
|
232
|
+
try {
|
|
233
|
+
const unsubscribe = record.subscribeToUpdates(() => notify(onChange));
|
|
234
|
+
if (unsubscribe) unsubscribers.push(unsubscribe);
|
|
235
|
+
} catch (cause) {
|
|
236
|
+
mode = "unavailable";
|
|
237
|
+
error = cause instanceof Error ? cause.message : String(cause);
|
|
238
|
+
}
|
|
239
|
+
if (record.subscribeToRecordUpdates) {
|
|
240
|
+
try {
|
|
241
|
+
unsubscribers.push(record.subscribeToRecordUpdates(() => notify(onChange)));
|
|
242
|
+
} catch (cause) {
|
|
243
|
+
mode = "unavailable";
|
|
244
|
+
error = cause instanceof Error ? cause.message : String(cause);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return unsubscribers.length === 0 ? undefined : () => {
|
|
248
|
+
for (const unsubscribe of unsubscribers) unsubscribe();
|
|
249
|
+
};
|
|
250
|
+
},
|
|
251
|
+
streaming: () => mode === "live" && record.status === "running"
|
|
252
|
+
? { activeTools: record.activeTools, responseText: record.responseText }
|
|
253
|
+
: undefined,
|
|
254
|
+
getToolDefinition: (name) => mode === "live" ? record.getToolDefinition(name) : undefined,
|
|
255
|
+
availability: () => {
|
|
256
|
+
swapIfReleased();
|
|
257
|
+
if (mode === "live") return { kind: "live", ...(record.outputFile ? { path: record.outputFile } : {}) };
|
|
258
|
+
if (mode === "file" && record.outputFile) return { kind: "file", path: record.outputFile };
|
|
259
|
+
return { kind: "unavailable", ...(record.outputFile ? { path: record.outputFile } : {}), ...(error ? { error } : {}) };
|
|
260
|
+
},
|
|
150
261
|
};
|
|
151
262
|
}
|
|
152
263
|
|