@fitchmultz/pi-subagents 0.46.1 → 0.46.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 +16 -0
- package/dist/agents/agent-management.js +8 -2
- package/dist/agents/agents.js +8 -8
- package/dist/extension/build-info.js +1 -1
- package/dist/extension/index.js +11 -5
- package/dist/extension/result-snapshot.js +0 -18
- package/dist/history/ingest.js +40 -31
- package/dist/history/prune.js +1 -1
- package/dist/history/run-projection.js +1 -2
- package/dist/history/search-queries.js +8 -2
- package/dist/history/store.js +20 -4
- package/dist/history/text-chunks.js +1 -2
- package/dist/history/transcript-queries.js +12 -6
- package/dist/intercom/result-intercom.js +0 -74
- package/dist/pi-intercom/broker/broker.js +33 -16
- package/dist/pi-intercom/broker/framing.js +67 -17
- package/dist/pi-intercom/broker/snapshot-reader.js +29 -8
- package/dist/pi-intercom/broker/snapshots.js +144 -41
- package/dist/pi-intercom/session-targets.js +0 -1
- package/dist/runs/background/async-run-discovery.js +4 -6
- package/dist/runs/background/completion-dedupe.js +4 -55
- package/dist/runs/background/notify.js +1 -9
- package/dist/runs/background/result-watcher.js +1 -1
- package/dist/runs/background/runner-child-observer.js +12 -7
- package/dist/runs/background/runner-monitor.js +2 -0
- package/dist/runs/background/runner-parallel.js +2 -3
- package/dist/runs/shared/child-observation-spool.js +8 -3
- package/dist/runs/shared/run-restoration.js +4 -5
- package/dist/runs/shared/supervisor-questions.js +7 -4
- package/dist/shared/journal-frames.js +1 -1
- package/dist/slash/command-discovery.js +13 -12
- package/dist/tui/agent-history.js +0 -14
- package/dist/tui/agent-view.js +0 -1
- package/dist/tui/conversation-history.js +10 -1
- package/dist/tui/history-cards.js +8 -22
- package/docs/intercom.md +5 -1
- package/docs/performance.md +72 -3
- package/package.json +1 -1
- package/src/agents/agent-management.ts +8 -4
- package/src/agents/agents.ts +17 -12
- package/src/extension/index.ts +12 -5
- package/src/extension/result-snapshot.ts +1 -27
- package/src/history/ingest.ts +57 -49
- package/src/history/prune.ts +1 -1
- package/src/history/run-projection.ts +2 -4
- package/src/history/search-queries.ts +9 -2
- package/src/history/store.ts +21 -5
- package/src/history/text-chunks.ts +7 -2
- package/src/history/transcript-queries.ts +16 -10
- package/src/intercom/result-intercom.ts +0 -103
- package/src/pi-intercom/broker/broker.ts +34 -20
- package/src/pi-intercom/broker/framing.ts +71 -20
- package/src/pi-intercom/broker/snapshot-reader.ts +47 -9
- package/src/pi-intercom/broker/snapshots.ts +184 -51
- package/src/pi-intercom/session-targets.ts +0 -2
- package/src/runs/background/async-run-discovery.ts +4 -10
- package/src/runs/background/completion-dedupe.ts +6 -69
- package/src/runs/background/notify.ts +2 -12
- package/src/runs/background/result-watcher.ts +1 -1
- package/src/runs/background/runner-child-observer.ts +19 -11
- package/src/runs/background/runner-monitor.ts +2 -0
- package/src/runs/background/runner-parallel.ts +2 -3
- package/src/runs/shared/child-observation-spool.ts +8 -3
- package/src/runs/shared/run-restoration.ts +4 -4
- package/src/runs/shared/supervisor-questions.ts +10 -10
- package/src/shared/journal-frames.ts +1 -1
- package/src/slash/command-discovery.ts +13 -12
- package/src/tui/agent-history.ts +1 -18
- package/src/tui/agent-view.ts +0 -1
- package/src/tui/conversation-history.ts +15 -1
- package/src/tui/history-cards.ts +8 -26
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
import {
|
|
23
23
|
getRunMetadataDir,
|
|
24
24
|
migrateSupervisorQuestionSteps,
|
|
25
|
+
readQuestionOwner,
|
|
25
26
|
readRunJson,
|
|
26
27
|
saveQuestionOwner,
|
|
27
28
|
saveRunStatus,
|
|
@@ -254,14 +255,13 @@ function nativeLaunchCwd(run: OwnedRun, details: ReadonlyDetails): OwnedRun {
|
|
|
254
255
|
}
|
|
255
256
|
|
|
256
257
|
function repairQuestionOwner(run: OwnedRun): void {
|
|
257
|
-
let
|
|
258
|
+
let sessionId: string | undefined;
|
|
258
259
|
try {
|
|
259
|
-
|
|
260
|
+
sessionId = readQuestionOwner(run.runId)?.sessionId;
|
|
260
261
|
} catch {
|
|
261
262
|
// A genuine receipt can repair unusable supplemental metadata.
|
|
262
263
|
}
|
|
263
|
-
|
|
264
|
-
if (typeof sessionId !== "string" || sessionId.trim() === "") {
|
|
264
|
+
if (sessionId === undefined || sessionId.trim() === "") {
|
|
265
265
|
saveQuestionOwner(run.runId, run.ownerSessionId);
|
|
266
266
|
}
|
|
267
267
|
}
|
|
@@ -216,7 +216,10 @@ export function createSupervisorQuestion(
|
|
|
216
216
|
return question;
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
-
export function listRunQuestions(
|
|
219
|
+
export function listRunQuestions(
|
|
220
|
+
runDir: string,
|
|
221
|
+
ownerSessionId?: string,
|
|
222
|
+
): SupervisorQuestionView[] {
|
|
220
223
|
let entries: fs.Dirent[];
|
|
221
224
|
try {
|
|
222
225
|
entries = fs.readdirSync(path.join(runDir, "questions"), { withFileTypes: true });
|
|
@@ -233,7 +236,10 @@ export function listRunQuestions(runDir: string): SupervisorQuestionView[] {
|
|
|
233
236
|
path.join(runDir, "questions", entry.name, "question.json"),
|
|
234
237
|
parseSupervisorQuestion,
|
|
235
238
|
);
|
|
236
|
-
return question
|
|
239
|
+
return question &&
|
|
240
|
+
(ownerSessionId === undefined || question.ownerSessionId === ownerSessionId)
|
|
241
|
+
? [readQuestionState(question, path.dirname(runDir))]
|
|
242
|
+
: [];
|
|
237
243
|
});
|
|
238
244
|
}
|
|
239
245
|
|
|
@@ -243,9 +249,7 @@ export function listOwnedRunQuestions(
|
|
|
243
249
|
runId: string,
|
|
244
250
|
): SupervisorQuestionView[] {
|
|
245
251
|
migrateSupervisorQuestions(ownerSessionId, runId);
|
|
246
|
-
return listRunQuestions(getRunMetadataDir(runId))
|
|
247
|
-
(question) => question.ownerSessionId === ownerSessionId,
|
|
248
|
-
);
|
|
252
|
+
return listRunQuestions(getRunMetadataDir(runId), ownerSessionId);
|
|
249
253
|
}
|
|
250
254
|
|
|
251
255
|
export function pendingSupervisorQuestion(input: {
|
|
@@ -321,11 +325,7 @@ function* supervisorQuestionSteps(
|
|
|
321
325
|
for (const entry of runs) {
|
|
322
326
|
yield;
|
|
323
327
|
try {
|
|
324
|
-
questions.push(
|
|
325
|
-
...listRunQuestions(path.join(root, entry.name)).filter(
|
|
326
|
-
(question) => question.ownerSessionId === ownerSessionId,
|
|
327
|
-
),
|
|
328
|
-
);
|
|
328
|
+
questions.push(...listRunQuestions(path.join(root, entry.name), ownerSessionId));
|
|
329
329
|
} catch (error) {
|
|
330
330
|
if (runId !== undefined) {
|
|
331
331
|
throw error;
|
|
@@ -172,7 +172,7 @@ export function readJsonProjection(file: string, select: Projection): UnknownRec
|
|
|
172
172
|
const projection = new JsonProjection(select, undefined, () => Infinity);
|
|
173
173
|
try {
|
|
174
174
|
const end = fs.fstatSync(fd).size;
|
|
175
|
-
const bytes = Buffer.allocUnsafe(64 * 1024);
|
|
175
|
+
const bytes = Buffer.allocUnsafe(Math.min(64 * 1024, end));
|
|
176
176
|
for (let offset = 0; offset < end;) {
|
|
177
177
|
const count = fs.readSync(fd, bytes, 0, Math.min(bytes.length, end - offset), offset);
|
|
178
178
|
if (count === 0) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import { discoverAgents,
|
|
2
|
+
import { discoverAgents, discoverChains } from "../agents/agents.ts";
|
|
3
3
|
import type { ChainConfig } from "../shared/types/config.ts";
|
|
4
4
|
import { resolveExecutionCwd } from "../shared/execution-cwd.ts";
|
|
5
5
|
|
|
@@ -51,21 +51,19 @@ export function makeAgentCompletions(
|
|
|
51
51
|
multiAgent: boolean,
|
|
52
52
|
): (prefix: string) => Completion[] | null {
|
|
53
53
|
return (prefix) => {
|
|
54
|
+
const position = multiAgent ? completionPosition(prefix) : { word: prefix, before: "" };
|
|
55
|
+
if (!position || (!multiAgent && prefix.includes(" "))) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
54
58
|
const cwd = completionCwd(pi, state);
|
|
55
59
|
if (cwd === null || cwd.length === 0) {
|
|
56
60
|
return null;
|
|
57
61
|
}
|
|
58
62
|
const agents = discoverAgents(cwd, "both", { projectTrusted: projectTrusted(state) }).agents;
|
|
59
63
|
if (!multiAgent) {
|
|
60
|
-
return
|
|
61
|
-
|
|
62
|
-
:
|
|
63
|
-
.filter((agent) => agent.name.startsWith(prefix))
|
|
64
|
-
.map((agent) => ({ value: agent.name, label: agent.name }));
|
|
65
|
-
}
|
|
66
|
-
const position = completionPosition(prefix);
|
|
67
|
-
if (!position) {
|
|
68
|
-
return null;
|
|
64
|
+
return agents
|
|
65
|
+
.filter((agent) => agent.name.startsWith(prefix))
|
|
66
|
+
.map((agent) => ({ value: agent.name, label: agent.name }));
|
|
69
67
|
}
|
|
70
68
|
const { word: lastWord, before: beforeLastWord } = position;
|
|
71
69
|
if (lastWord === "->") {
|
|
@@ -79,7 +77,7 @@ export function makeAgentCompletions(
|
|
|
79
77
|
|
|
80
78
|
export function discoverSavedChains(cwd: string, trusted: boolean): ChainConfig[] {
|
|
81
79
|
const chains = new Map<string, ChainConfig>();
|
|
82
|
-
for (const chain of
|
|
80
|
+
for (const chain of discoverChains(cwd, { projectTrusted: trusted }).chains) {
|
|
83
81
|
const existing = chains.get(chain.name);
|
|
84
82
|
const projectOverride = existing?.source === "user" && chain.source === "project";
|
|
85
83
|
const jsonOverride =
|
|
@@ -98,8 +96,11 @@ export function makeChainCompletions(
|
|
|
98
96
|
state: SlashDiscoveryState,
|
|
99
97
|
): (prefix: string) => Completion[] | null {
|
|
100
98
|
return (prefix) => {
|
|
99
|
+
if (prefix.includes(" ")) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
101
102
|
const cwd = completionCwd(pi, state);
|
|
102
|
-
if (
|
|
103
|
+
if (cwd === null || cwd.length === 0) {
|
|
103
104
|
return null;
|
|
104
105
|
}
|
|
105
106
|
return discoverSavedChains(cwd, projectTrusted(state))
|
package/src/tui/agent-history.ts
CHANGED
|
@@ -1,27 +1,10 @@
|
|
|
1
|
-
import type { SessionEntry } from "@earendil-works/pi-coding-agent";
|
|
2
1
|
import { stripAcceptanceReport } from "../runs/shared/acceptance-reports.ts";
|
|
3
|
-
import {
|
|
4
|
-
import type { DisplayEntry } from "./history-record.ts";
|
|
2
|
+
import type { AgentHistory, AgentHistoryItem } from "./history-display.ts";
|
|
5
3
|
import { readableText } from "./history-text.ts";
|
|
6
4
|
export { readableText } from "./history-text.ts";
|
|
7
5
|
export { indexedHistory } from "./indexed-history.ts";
|
|
8
6
|
export type { AgentHistory, AgentHistoryItem } from "./history-display.ts";
|
|
9
7
|
|
|
10
|
-
/** Read native entries, not a compacted model context: earlier messages remain inspectable. */
|
|
11
|
-
export function historyItems(entries: readonly SessionEntry[]): AgentHistory {
|
|
12
|
-
const visible: DisplayEntry[] = [];
|
|
13
|
-
for (const entry of entries) {
|
|
14
|
-
if (
|
|
15
|
-
entry.type === "message" ||
|
|
16
|
-
entry.type === "custom_message" ||
|
|
17
|
-
entry.type === "compaction" ||
|
|
18
|
-
entry.type === "branch_summary"
|
|
19
|
-
) {
|
|
20
|
-
visible.push(entry.type === "message" ? { ...entry, native: entry.message } : entry);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return displayHistory(visible);
|
|
24
|
-
}
|
|
25
8
|
function finalMatch(history: AgentHistory, text: string): string | undefined {
|
|
26
9
|
if (history.finalId !== undefined) {
|
|
27
10
|
return history.finalId;
|
package/src/tui/agent-view.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { errorText } from "./text-values.ts";
|
|
2
|
+
import { isDeepStrictEqual } from "node:util";
|
|
2
3
|
import {
|
|
3
4
|
historyStatus,
|
|
4
5
|
pageNotices,
|
|
@@ -183,9 +184,22 @@ export class ConversationHistory {
|
|
|
183
184
|
? { ...item, load: () => this.controller.savedResult(this.key, item.id) }
|
|
184
185
|
: item,
|
|
185
186
|
);
|
|
187
|
+
const previous = task.page,
|
|
188
|
+
sameSource =
|
|
189
|
+
previous !== undefined &&
|
|
190
|
+
previous.sourceId === result.page.sourceId &&
|
|
191
|
+
previous.generation === result.page.generation &&
|
|
192
|
+
previous.sessionId === result.page.sessionId &&
|
|
193
|
+
previous.sourceState === result.page.sourceState &&
|
|
194
|
+
isDeepStrictEqual(
|
|
195
|
+
previous.entries.map((entry) => entry.ref),
|
|
196
|
+
result.page.entries.map((entry) => entry.ref),
|
|
197
|
+
);
|
|
186
198
|
this.seenSource ||= result.page.count > 0;
|
|
187
199
|
this.controller.applyHistoryPage(this.key, { ...history, items }, result.page, this.seenSource);
|
|
188
|
-
|
|
200
|
+
if (!sameSource) {
|
|
201
|
+
this.source.clearCards();
|
|
202
|
+
}
|
|
189
203
|
}
|
|
190
204
|
|
|
191
205
|
assignment(): AgentHistoryItem {
|
package/src/tui/history-cards.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AssistantMessage } from "@earendil-works/pi-ai";
|
|
2
|
+
import { isDeepStrictEqual } from "node:util";
|
|
2
3
|
import {
|
|
3
4
|
AssistantMessageComponent,
|
|
4
5
|
UserMessageComponent,
|
|
@@ -47,29 +48,9 @@ interface CardLine {
|
|
|
47
48
|
readonly contentStart: number;
|
|
48
49
|
readonly end: number;
|
|
49
50
|
}
|
|
50
|
-
function plainItem(item: AgentHistoryItem): boolean {
|
|
51
|
-
return (
|
|
52
|
-
item.load === undefined &&
|
|
53
|
-
item.assistant === undefined &&
|
|
54
|
-
item.previewAssistant === undefined &&
|
|
55
|
-
item.call === undefined &&
|
|
56
|
-
item.result === undefined
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
function plainSignature(item: AgentHistoryItem): string {
|
|
60
|
-
return JSON.stringify([
|
|
61
|
-
item.kind,
|
|
62
|
-
item.title,
|
|
63
|
-
item.text,
|
|
64
|
-
item.details,
|
|
65
|
-
item.diff,
|
|
66
|
-
item.model,
|
|
67
|
-
item.timestamp,
|
|
68
|
-
item.messageId,
|
|
69
|
-
]);
|
|
70
|
-
}
|
|
71
51
|
function sameDisplay(left: AgentHistoryItem, right: AgentHistoryItem): boolean {
|
|
72
|
-
|
|
52
|
+
// Detail loaders stay fresh in contentItems; only the native display component is reused.
|
|
53
|
+
return isDeepStrictEqual({ ...left, load: undefined }, { ...right, load: undefined });
|
|
73
54
|
}
|
|
74
55
|
function previewStop(reason: string | undefined): AssistantMessage["stopReason"] {
|
|
75
56
|
if (reason === "error" || reason === "aborted" || reason === "length") {
|
|
@@ -191,10 +172,11 @@ export class HistoryCards {
|
|
|
191
172
|
private card(item: AgentHistoryItem, expanded: boolean, detail: boolean): Component {
|
|
192
173
|
const signature = `${expanded}:${detail}`,
|
|
193
174
|
cached = this.components.get(item.id);
|
|
194
|
-
if (
|
|
195
|
-
cached
|
|
196
|
-
|
|
197
|
-
) {
|
|
175
|
+
if (cached?.signature === signature && cached.item === item) {
|
|
176
|
+
return cached.component;
|
|
177
|
+
}
|
|
178
|
+
if (cached?.signature === signature && sameDisplay(cached.item, item)) {
|
|
179
|
+
this.components.set(item.id, { ...cached, item });
|
|
198
180
|
return cached.component;
|
|
199
181
|
}
|
|
200
182
|
const component = this.create(item, { expanded, detail });
|