@averyyy/pi-coding-agent 0.82.1-piclient.6 → 0.82.1-piclient.7
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 +0 -12
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +1 -2
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +0 -5
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session.d.ts +1 -12
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +89 -317
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/pi-server-client.d.ts +2 -54
- package/dist/core/pi-server-client.d.ts.map +1 -1
- package/dist/core/pi-server-client.js +272 -2320
- package/dist/core/pi-server-client.js.map +1 -1
- package/dist/core/pi-server-protocol.d.ts +0 -2
- package/dist/core/pi-server-protocol.d.ts.map +1 -1
- package/dist/core/pi-server-protocol.js +1 -24
- package/dist/core/pi-server-protocol.js.map +1 -1
- package/dist/core/pi-server-request.d.ts +0 -28
- package/dist/core/pi-server-request.d.ts.map +1 -1
- package/dist/core/pi-server-request.js +75 -492
- package/dist/core/pi-server-request.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +53 -69
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +2 -86
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +144 -737
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts +1 -3
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +26 -46
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +0 -13
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +0 -15
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +29 -98
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/package.json +4 -4
- package/dist/cli/tool-effects.d.ts +0 -6
- package/dist/cli/tool-effects.d.ts.map +0 -1
- package/dist/cli/tool-effects.js +0 -164
- package/dist/cli/tool-effects.js.map +0 -1
- package/dist/core/pi-server-compact-state.d.ts +0 -81
- package/dist/core/pi-server-compact-state.d.ts.map +0 -1
- package/dist/core/pi-server-compact-state.js +0 -439
- package/dist/core/pi-server-compact-state.js.map +0 -1
- package/dist/core/pi-server-run-state.d.ts +0 -42
- package/dist/core/pi-server-run-state.d.ts.map +0 -1
- package/dist/core/pi-server-run-state.js +0 -320
- package/dist/core/pi-server-run-state.js.map +0 -1
- package/dist/core/tool-effect-journal.d.ts +0 -103
- package/dist/core/tool-effect-journal.d.ts.map +0 -1
- package/dist/core/tool-effect-journal.js +0 -1442
- package/dist/core/tool-effect-journal.js.map +0 -1
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
*
|
|
13
13
|
* Modes use this class and add their own I/O layer on top.
|
|
14
14
|
*/
|
|
15
|
-
import { randomUUID } from "node:crypto";
|
|
16
15
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
17
16
|
import { basename, dirname } from "node:path";
|
|
18
17
|
import { contentText } from "@earendil-works/pi-ai";
|
|
@@ -30,14 +29,11 @@ import { createToolHtmlRenderer } from "./export-html/tool-renderer.js";
|
|
|
30
29
|
import { ExtensionRunner, wrapRegisteredTools, } from "./extensions/index.js";
|
|
31
30
|
import { emitSessionShutdownEvent } from "./extensions/runner.js";
|
|
32
31
|
import { ModelRegistry } from "./model-registry.js";
|
|
33
|
-
import {
|
|
34
|
-
import { getPiServerCompactStatePath, readPiServerPendingCompact } from "./pi-server-compact-state.js";
|
|
35
|
-
import { getPiServerRunStatePath, readPiServerPendingRun } from "./pi-server-run-state.js";
|
|
32
|
+
import { compactPiServer, syncPiServerTree, } from "./pi-server-client.js";
|
|
36
33
|
import { expandPromptTemplate } from "./prompt-templates.js";
|
|
37
34
|
import { CURRENT_SESSION_VERSION, getLatestCompactionEntry } from "./session-manager.js";
|
|
38
35
|
import { createSyntheticSourceInfo } from "./source-info.js";
|
|
39
36
|
import { buildSystemPrompt } from "./system-prompt.js";
|
|
40
|
-
import { beginSessionToolEffect, beginSessionToolEffectFinalization, commitSessionToolEffect, recoverToolEffects, writeSessionToolEffectFinalResult, writeSessionToolEffectResult, } from "./tool-effect-journal.js";
|
|
41
37
|
import { createLocalBashOperations } from "./tools/bash.js";
|
|
42
38
|
import { createAllToolDefinitions } from "./tools/index.js";
|
|
43
39
|
import { createToolDefinitionFromAgentTool } from "./tools/tool-definition-wrapper.js";
|
|
@@ -97,26 +93,16 @@ function getStringField(input, key) {
|
|
|
97
93
|
const value = input[key];
|
|
98
94
|
return typeof value === "string" && value.trim().length > 0 ? value : undefined;
|
|
99
95
|
}
|
|
100
|
-
function
|
|
96
|
+
function getPiServerFailurePhase(message) {
|
|
101
97
|
for (const diagnostic of message.diagnostics ?? []) {
|
|
102
98
|
if (diagnostic.type !== "pi_server_failure")
|
|
103
99
|
continue;
|
|
104
100
|
const phase = diagnostic.details?.phase;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
phase: typeof phase === "string" ? phase : undefined,
|
|
108
|
-
retryable: typeof retryable === "boolean" ? retryable : undefined,
|
|
109
|
-
};
|
|
101
|
+
if (typeof phase === "string")
|
|
102
|
+
return phase;
|
|
110
103
|
}
|
|
111
104
|
return undefined;
|
|
112
105
|
}
|
|
113
|
-
function isPiServerControlPlaneFailure(message) {
|
|
114
|
-
const hasFailure = message.diagnostics?.some((diagnostic) => diagnostic.type === "pi_server_failure") === true;
|
|
115
|
-
return hasFailure && getPiServerRunDiagnostic(message) === undefined;
|
|
116
|
-
}
|
|
117
|
-
function isPiServerRestartUncertainty(message) {
|
|
118
|
-
return getPiServerRunDiagnostic(message)?.restartUnknown === true;
|
|
119
|
-
}
|
|
120
106
|
function toolTextContent(content) {
|
|
121
107
|
return content
|
|
122
108
|
.filter((part) => part.type === "text")
|
|
@@ -179,7 +165,6 @@ export class AgentSession {
|
|
|
179
165
|
_isAgentRunActive = false;
|
|
180
166
|
_idleWaitPromise;
|
|
181
167
|
_resolveIdleWait;
|
|
182
|
-
_toolResultsInFinalization = new WeakSet();
|
|
183
168
|
/** Tracks pending steering messages for UI display. Removed when delivered. */
|
|
184
169
|
_steeringMessages = [];
|
|
185
170
|
/** Tracks pending follow-up messages for UI display. Removed when delivered. */
|
|
@@ -191,7 +176,6 @@ export class AgentSession {
|
|
|
191
176
|
_autoCompactionAbortController = undefined;
|
|
192
177
|
_overflowRecoveryAttempted = false;
|
|
193
178
|
_lastServerCompactionTimestamp = undefined;
|
|
194
|
-
_piServerSessionLeaseOwner;
|
|
195
179
|
// Branch summarization state
|
|
196
180
|
_branchSummaryAbortController = undefined;
|
|
197
181
|
// Retry state
|
|
@@ -224,7 +208,6 @@ export class AgentSession {
|
|
|
224
208
|
_extensionErrorUnsubscriber;
|
|
225
209
|
_autoSessionNameEnabled;
|
|
226
210
|
_autoSessionNameAttempted = false;
|
|
227
|
-
_auxiliaryStreamFunction;
|
|
228
211
|
_modelRuntime;
|
|
229
212
|
// Tool registry for extension getTools/setTools
|
|
230
213
|
_toolRegistry = new Map();
|
|
@@ -244,7 +227,6 @@ export class AgentSession {
|
|
|
244
227
|
this._customTools = config.customTools ?? [];
|
|
245
228
|
this._cwd = config.cwd;
|
|
246
229
|
this._modelRuntime = config.modelRuntime;
|
|
247
|
-
this._auxiliaryStreamFunction = config.auxiliaryStreamFunction;
|
|
248
230
|
this._extensionRunnerRef = config.extensionRunnerRef;
|
|
249
231
|
this._initialActiveToolNames = config.initialActiveToolNames;
|
|
250
232
|
this._allowedToolNames = config.allowedToolNames ? new Set(config.allowedToolNames) : undefined;
|
|
@@ -252,10 +234,6 @@ export class AgentSession {
|
|
|
252
234
|
this._baseToolsOverride = config.baseToolsOverride;
|
|
253
235
|
this._sessionStartEvent = config.sessionStartEvent ?? { type: "session_start", reason: "startup" };
|
|
254
236
|
this._autoSessionNameEnabled = config.autoSessionName ?? true;
|
|
255
|
-
const toolEffectRecovery = recoverToolEffects(this.sessionManager);
|
|
256
|
-
if (toolEffectRecovery.recoveredToolCallIds.length > 0) {
|
|
257
|
-
this.agent.state.messages = this.sessionManager.buildSessionContext().messages;
|
|
258
|
-
}
|
|
259
237
|
if (isPiServerMode()) {
|
|
260
238
|
this._detachPiServerTerminalAssistantFailure();
|
|
261
239
|
}
|
|
@@ -272,9 +250,6 @@ export class AgentSession {
|
|
|
272
250
|
get modelRuntime() {
|
|
273
251
|
return this._modelRuntime;
|
|
274
252
|
}
|
|
275
|
-
_getAuxiliaryStreamFunction() {
|
|
276
|
-
return this._auxiliaryStreamFunction ?? this.agent.streamFunction;
|
|
277
|
-
}
|
|
278
253
|
reconcilePiServerHistory(snapshot) {
|
|
279
254
|
this.sessionManager.replaceTree(snapshot.entries, snapshot.leafId);
|
|
280
255
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
@@ -285,105 +260,6 @@ export class AgentSession {
|
|
|
285
260
|
messageCount: snapshot.messages.length,
|
|
286
261
|
});
|
|
287
262
|
}
|
|
288
|
-
async _syncAndAcknowledgePiServerAssistantMessage(message, signal) {
|
|
289
|
-
const persistenceSignal = signal.aborted ? undefined : signal;
|
|
290
|
-
const sessionFile = this.sessionManager.getSessionFile();
|
|
291
|
-
const runStatePath = sessionFile ? getPiServerRunStatePath(sessionFile) : undefined;
|
|
292
|
-
try {
|
|
293
|
-
await syncPiServerTree(this.sessionId, {
|
|
294
|
-
systemPrompt: this.systemPrompt,
|
|
295
|
-
messages: this.agent.state.messages,
|
|
296
|
-
tools: this.agent.state.tools,
|
|
297
|
-
}, { entries: this.sessionManager.getEntries(), leafId: this.sessionManager.getLeafId() }, {
|
|
298
|
-
signal: persistenceSignal,
|
|
299
|
-
onHistoryReconciled: (snapshot) => this.reconcilePiServerHistory(snapshot),
|
|
300
|
-
});
|
|
301
|
-
this.sessionManager.flushSessionFile();
|
|
302
|
-
await acknowledgePiServerRunMessage(this.sessionId, message, runStatePath, persistenceSignal);
|
|
303
|
-
}
|
|
304
|
-
catch (error) {
|
|
305
|
-
releasePiServerRunLease(this.sessionId, runStatePath);
|
|
306
|
-
throw error;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
_acquirePiServerOperationLease(reentrantOwner) {
|
|
310
|
-
if (!isPiServerMode())
|
|
311
|
-
return { path: undefined, acquired: false, owner: undefined };
|
|
312
|
-
const sessionFile = this.sessionManager.getSessionFile();
|
|
313
|
-
const path = sessionFile ? getPiServerRunStatePath(sessionFile) : undefined;
|
|
314
|
-
if (this._piServerSessionLeaseOwner) {
|
|
315
|
-
if (reentrantOwner !== this._piServerSessionLeaseOwner) {
|
|
316
|
-
throw new Error(`Cannot start a concurrent durable pi-server operation for session ${this.sessionId}`);
|
|
317
|
-
}
|
|
318
|
-
return { path, acquired: false, owner: this._piServerSessionLeaseOwner };
|
|
319
|
-
}
|
|
320
|
-
const owner = Symbol("pi-server-session-lease");
|
|
321
|
-
if (path)
|
|
322
|
-
acquirePiServerSessionLease(this.sessionId, path);
|
|
323
|
-
this._piServerSessionLeaseOwner = owner;
|
|
324
|
-
return { path, acquired: true, owner };
|
|
325
|
-
}
|
|
326
|
-
_releasePiServerOperationLease(path, acquired, owner) {
|
|
327
|
-
if (!acquired)
|
|
328
|
-
return;
|
|
329
|
-
if (!owner || this._piServerSessionLeaseOwner !== owner) {
|
|
330
|
-
throw new Error(`Cannot release a durable pi-server operation lease owned by another operation`);
|
|
331
|
-
}
|
|
332
|
-
if (path)
|
|
333
|
-
releasePiServerSessionLease(this.sessionId, path);
|
|
334
|
-
this._piServerSessionLeaseOwner = undefined;
|
|
335
|
-
}
|
|
336
|
-
async _recoverPendingPiServerRunBeforeControlOperation(signal) {
|
|
337
|
-
if (!isPiServerMode())
|
|
338
|
-
return;
|
|
339
|
-
const sessionFile = this.sessionManager.getSessionFile();
|
|
340
|
-
if (!sessionFile) {
|
|
341
|
-
throw new Error("Durable pi-server operations require a persisted session file");
|
|
342
|
-
}
|
|
343
|
-
const runStatePath = getPiServerRunStatePath(sessionFile);
|
|
344
|
-
const pending = readPiServerPendingRun(runStatePath);
|
|
345
|
-
if (!pending)
|
|
346
|
-
return;
|
|
347
|
-
let terminal;
|
|
348
|
-
const entries = this.sessionManager.getEntries();
|
|
349
|
-
for (let index = entries.length - 1; index >= 0; index--) {
|
|
350
|
-
const entry = entries[index];
|
|
351
|
-
if (entry.type !== "message" || entry.message.role !== "assistant")
|
|
352
|
-
continue;
|
|
353
|
-
const message = entry.message;
|
|
354
|
-
const diagnostic = getPiServerRunDiagnostic(message);
|
|
355
|
-
if (!diagnostic || diagnostic.runId !== pending.runId)
|
|
356
|
-
continue;
|
|
357
|
-
if (diagnostic.sessionId !== pending.sessionId ||
|
|
358
|
-
diagnostic.requestMac !== pending.requestHash ||
|
|
359
|
-
pending.sessionId !== this.sessionId) {
|
|
360
|
-
throw new Error("Pending pi-server run terminal does not match its durable client marker");
|
|
361
|
-
}
|
|
362
|
-
terminal = message;
|
|
363
|
-
break;
|
|
364
|
-
}
|
|
365
|
-
if (!terminal) {
|
|
366
|
-
throw new Error(`Cannot start compaction while pi-server run ${pending.runId} is pending without a durable terminal assistant`);
|
|
367
|
-
}
|
|
368
|
-
await this._syncAndAcknowledgePiServerAssistantMessage(terminal, signal ?? new AbortController().signal);
|
|
369
|
-
}
|
|
370
|
-
async _recoverPendingPiServerCompaction(reason, willRetry, signal) {
|
|
371
|
-
if (!isPiServerMode())
|
|
372
|
-
return undefined;
|
|
373
|
-
const sessionFile = this.sessionManager.getSessionFile();
|
|
374
|
-
if (!sessionFile)
|
|
375
|
-
return undefined;
|
|
376
|
-
const compactStatePath = getPiServerCompactStatePath(sessionFile);
|
|
377
|
-
if (!readPiServerPendingCompact(compactStatePath))
|
|
378
|
-
return undefined;
|
|
379
|
-
const result = await recoverPendingPiServerCompaction(this.sessionId, { entries: this.sessionManager.getEntries(), leafId: this.sessionManager.getLeafId() }, compactStatePath, {
|
|
380
|
-
signal,
|
|
381
|
-
onHistoryReconciled: (snapshot) => this.reconcilePiServerHistory(snapshot),
|
|
382
|
-
});
|
|
383
|
-
if (!result)
|
|
384
|
-
return undefined;
|
|
385
|
-
return this._applyPiServerCompactionResult(result, reason, willRetry);
|
|
386
|
-
}
|
|
387
263
|
async _getRequiredRequestAuth(model) {
|
|
388
264
|
let result;
|
|
389
265
|
try {
|
|
@@ -412,7 +288,7 @@ export class AgentSession {
|
|
|
412
288
|
throw new Error(formatNoApiKeyFoundMessage(model.provider));
|
|
413
289
|
}
|
|
414
290
|
async _getSummarizationRequestAuth(model) {
|
|
415
|
-
if (this.
|
|
291
|
+
if (this.agent.streamFunction === streamSimple) {
|
|
416
292
|
return this._getRequiredRequestAuth(model);
|
|
417
293
|
}
|
|
418
294
|
try {
|
|
@@ -604,33 +480,18 @@ export class AgentSession {
|
|
|
604
480
|
}
|
|
605
481
|
async _emitAgentSettled() {
|
|
606
482
|
this._isAgentRunActive = false;
|
|
607
|
-
|
|
608
|
-
|
|
483
|
+
try {
|
|
484
|
+
await this._extensionRunner.emit({ type: "agent_settled" });
|
|
485
|
+
this._emit({ type: "agent_settled" });
|
|
486
|
+
}
|
|
487
|
+
finally {
|
|
488
|
+
this._resolveIdleWaitIfIdle();
|
|
489
|
+
}
|
|
609
490
|
}
|
|
610
491
|
// Track last assistant message for auto-compaction check
|
|
611
492
|
_lastAssistantMessage = undefined;
|
|
612
493
|
/** Internal handler for agent events - shared by subscribe and reconnect */
|
|
613
494
|
_handleAgentEvent = async (event, signal) => {
|
|
614
|
-
if (event.type === "tool_execution_start") {
|
|
615
|
-
beginSessionToolEffect(this.sessionManager, event);
|
|
616
|
-
}
|
|
617
|
-
else if (event.type === "tool_execution_end") {
|
|
618
|
-
writeSessionToolEffectResult(this.sessionManager, event.toolResult, { finalizationPending: true });
|
|
619
|
-
this._toolResultsInFinalization.add(event.toolResult);
|
|
620
|
-
}
|
|
621
|
-
else if (event.type === "message_start" &&
|
|
622
|
-
event.message.role === "toolResult" &&
|
|
623
|
-
!this._toolResultsInFinalization.has(event.message)) {
|
|
624
|
-
beginSessionToolEffectFinalization(this.sessionManager, event.message);
|
|
625
|
-
this._toolResultsInFinalization.add(event.message);
|
|
626
|
-
}
|
|
627
|
-
else if (event.type === "message_end" &&
|
|
628
|
-
event.message.role === "toolResult" &&
|
|
629
|
-
!this._toolResultsInFinalization.has(event.message)) {
|
|
630
|
-
beginSessionToolEffectFinalization(this.sessionManager, event.message);
|
|
631
|
-
this._toolResultsInFinalization.add(event.message);
|
|
632
|
-
}
|
|
633
|
-
const finalizingToolResult = event.type === "message_end" && this._toolResultsInFinalization.has(event.message);
|
|
634
495
|
// When a user message starts, check if it's from either queue and remove it BEFORE emitting
|
|
635
496
|
// This ensures the UI sees the updated queue state
|
|
636
497
|
if (event.type === "message_start" && event.message.role === "user") {
|
|
@@ -657,13 +518,6 @@ export class AgentSession {
|
|
|
657
518
|
await this._emitExtensionEvent(event);
|
|
658
519
|
// Notify all listeners
|
|
659
520
|
this._emit(event.type === "agent_end" ? { ...event, willRetry: this._willRetryAfterAgentEnd(event) } : event);
|
|
660
|
-
if (finalizingToolResult) {
|
|
661
|
-
if (event.message.role !== "toolResult") {
|
|
662
|
-
throw new Error("A toolResult message_end replacement must remain a toolResult");
|
|
663
|
-
}
|
|
664
|
-
writeSessionToolEffectFinalResult(this.sessionManager, event.message);
|
|
665
|
-
this._toolResultsInFinalization.delete(event.message);
|
|
666
|
-
}
|
|
667
521
|
// Handle session persistence
|
|
668
522
|
if (event.type === "message_end") {
|
|
669
523
|
// Check if this is a custom message from extensions
|
|
@@ -675,11 +529,7 @@ export class AgentSession {
|
|
|
675
529
|
event.message.role === "assistant" ||
|
|
676
530
|
event.message.role === "toolResult") {
|
|
677
531
|
// Regular LLM message - persist as SessionMessageEntry
|
|
678
|
-
|
|
679
|
-
if (event.message.role === "toolResult") {
|
|
680
|
-
this.sessionManager.flushSessionFile();
|
|
681
|
-
commitSessionToolEffect(this.sessionManager, event.message, sessionEntryId);
|
|
682
|
-
}
|
|
532
|
+
this.sessionManager.appendMessage(event.message);
|
|
683
533
|
}
|
|
684
534
|
// Other message types (bashExecution, compactionSummary, branchSummary) are persisted elsewhere
|
|
685
535
|
// Track assistant message for auto-compaction (checked on agent_end)
|
|
@@ -699,10 +549,12 @@ export class AgentSession {
|
|
|
699
549
|
});
|
|
700
550
|
this._retryAttempt = 0;
|
|
701
551
|
}
|
|
702
|
-
if (isPiServerMode() &&
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
552
|
+
if (isPiServerMode() && !this._isTerminalAssistantFailure(assistantMsg)) {
|
|
553
|
+
await syncPiServerTree(this.sessionId, {
|
|
554
|
+
systemPrompt: this.systemPrompt,
|
|
555
|
+
messages: this.agent.state.messages,
|
|
556
|
+
tools: this.agent.state.tools,
|
|
557
|
+
}, { entries: this.sessionManager.getEntries(), leafId: this.sessionManager.getLeafId() }, { signal, onHistoryReconciled: (snapshot) => this.reconcilePiServerHistory(snapshot) });
|
|
706
558
|
}
|
|
707
559
|
}
|
|
708
560
|
}
|
|
@@ -968,7 +820,7 @@ export class AgentSession {
|
|
|
968
820
|
}
|
|
969
821
|
/** Whether the session has no active agent run, retry, auto-compaction, or queued continuation. */
|
|
970
822
|
get isIdle() {
|
|
971
|
-
return !this._isAgentRunActive
|
|
823
|
+
return !this._isAgentRunActive;
|
|
972
824
|
}
|
|
973
825
|
/** Current effective system prompt (includes any per-turn extension modifications) */
|
|
974
826
|
get systemPrompt() {
|
|
@@ -1120,11 +972,9 @@ export class AgentSession {
|
|
|
1120
972
|
// Prompting
|
|
1121
973
|
// =========================================================================
|
|
1122
974
|
async _runAgentPrompt(messages) {
|
|
1123
|
-
const piServerLease = this._acquirePiServerOperationLease();
|
|
1124
975
|
this._resetValidationHintState();
|
|
1125
976
|
this._isAgentRunActive = true;
|
|
1126
977
|
try {
|
|
1127
|
-
await this._recoverPendingPiServerCompaction("threshold", false);
|
|
1128
978
|
await this.agent.prompt(messages);
|
|
1129
979
|
while (await this._handlePostAgentRun()) {
|
|
1130
980
|
try {
|
|
@@ -1147,15 +997,9 @@ export class AgentSession {
|
|
|
1147
997
|
await this._maybeGenerateSessionName();
|
|
1148
998
|
}
|
|
1149
999
|
finally {
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
await this._emitAgentSettled();
|
|
1154
|
-
}
|
|
1155
|
-
finally {
|
|
1156
|
-
this._releasePiServerOperationLease(piServerLease.path, piServerLease.acquired, piServerLease.owner);
|
|
1157
|
-
this._resolveIdleWaitIfIdle();
|
|
1158
|
-
}
|
|
1000
|
+
this._systemPromptOverride = undefined;
|
|
1001
|
+
this._flushPendingBashMessages();
|
|
1002
|
+
await this._emitAgentSettled();
|
|
1159
1003
|
}
|
|
1160
1004
|
}
|
|
1161
1005
|
_sessionHasInfoEntry() {
|
|
@@ -1192,7 +1036,7 @@ export class AgentSession {
|
|
|
1192
1036
|
if (!model || !transcript)
|
|
1193
1037
|
return;
|
|
1194
1038
|
try {
|
|
1195
|
-
const stream = await this.
|
|
1039
|
+
const stream = await this.agent.streamFunction(model, {
|
|
1196
1040
|
systemPrompt: this.systemPrompt,
|
|
1197
1041
|
messages: [
|
|
1198
1042
|
{
|
|
@@ -1205,7 +1049,7 @@ export class AgentSession {
|
|
|
1205
1049
|
}, {
|
|
1206
1050
|
maxTokens: 32,
|
|
1207
1051
|
reasoning: undefined,
|
|
1208
|
-
sessionId:
|
|
1052
|
+
sessionId: this.sessionId,
|
|
1209
1053
|
transport: this.agent.transport,
|
|
1210
1054
|
thinkingBudgets: this.agent.thinkingBudgets,
|
|
1211
1055
|
maxRetryDelayMs: this.agent.maxRetryDelayMs,
|
|
@@ -1838,26 +1682,9 @@ export class AgentSession {
|
|
|
1838
1682
|
// Compaction
|
|
1839
1683
|
// =========================================================================
|
|
1840
1684
|
async _applyPiServerCompactionResult(result, reason, willRetry) {
|
|
1841
|
-
|
|
1842
|
-
const operation = compactionEntry.piServerCompactOperation;
|
|
1843
|
-
if (!operation ||
|
|
1844
|
-
!Number.isSafeInteger(operation.baseEntryCount) ||
|
|
1845
|
-
operation.baseEntryCount < 0 ||
|
|
1846
|
-
(operation.baseLeafId !== null &&
|
|
1847
|
-
(typeof operation.baseLeafId !== "string" || operation.baseLeafId.length === 0)) ||
|
|
1848
|
-
typeof operation.baseTreeHash !== "string" ||
|
|
1849
|
-
!/^[a-f0-9]{64}$/u.test(operation.baseTreeHash)) {
|
|
1850
|
-
throw new Error("Pi-server compaction result is missing a valid durable base identity");
|
|
1851
|
-
}
|
|
1852
|
-
this.sessionManager.appendCompactionEntry(compactionEntry, {
|
|
1853
|
-
baseEntryCount: operation.baseEntryCount,
|
|
1854
|
-
baseLeafId: operation.baseLeafId,
|
|
1855
|
-
baseTreeHash: operation.baseTreeHash,
|
|
1856
|
-
});
|
|
1857
|
-
recordPiServerCompactionApplied(result);
|
|
1685
|
+
this.sessionManager.replaceTree(result.entries, result.leafId);
|
|
1858
1686
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
1859
1687
|
this.agent.state.messages = sessionContext.messages;
|
|
1860
|
-
await acknowledgePiServerCompaction(result);
|
|
1861
1688
|
const firstKeptEntryId = result.compaction.firstKeptEntryId;
|
|
1862
1689
|
if (!firstKeptEntryId) {
|
|
1863
1690
|
throw new Error("Pi-server compaction result is missing firstKeptEntryId");
|
|
@@ -1876,7 +1703,7 @@ export class AgentSession {
|
|
|
1876
1703
|
await this._extensionRunner.emit({
|
|
1877
1704
|
type: "session_compact",
|
|
1878
1705
|
compactionEntry: savedCompactionEntry,
|
|
1879
|
-
fromExtension:
|
|
1706
|
+
fromExtension: false,
|
|
1880
1707
|
reason,
|
|
1881
1708
|
willRetry,
|
|
1882
1709
|
});
|
|
@@ -1893,31 +1720,38 @@ export class AgentSession {
|
|
|
1893
1720
|
await this.abort();
|
|
1894
1721
|
this._compactionAbortController = new AbortController();
|
|
1895
1722
|
this._emit({ type: "compaction_start", reason: "manual" });
|
|
1896
|
-
let piServerLease = {
|
|
1897
|
-
path: undefined,
|
|
1898
|
-
acquired: false,
|
|
1899
|
-
owner: undefined,
|
|
1900
|
-
};
|
|
1901
1723
|
try {
|
|
1902
|
-
piServerLease = this._acquirePiServerOperationLease();
|
|
1903
|
-
await this._recoverPendingPiServerRunBeforeControlOperation(this._compactionAbortController.signal);
|
|
1904
|
-
const recoveredCompaction = await this._recoverPendingPiServerCompaction("manual", false, this._compactionAbortController.signal);
|
|
1905
|
-
if (recoveredCompaction) {
|
|
1906
|
-
this._emit({
|
|
1907
|
-
type: "compaction_end",
|
|
1908
|
-
reason: "manual",
|
|
1909
|
-
result: recoveredCompaction,
|
|
1910
|
-
aborted: false,
|
|
1911
|
-
willRetry: false,
|
|
1912
|
-
});
|
|
1913
|
-
return recoveredCompaction;
|
|
1914
|
-
}
|
|
1915
1724
|
if (!this.model) {
|
|
1916
1725
|
throw new Error(formatNoModelSelectedMessage());
|
|
1917
1726
|
}
|
|
1918
1727
|
const { apiKey, headers, env } = await this._getSummarizationRequestAuth(this.model);
|
|
1919
1728
|
if (isPiServerMode()) {
|
|
1920
1729
|
this._detachPiServerTerminalAssistantFailure();
|
|
1730
|
+
const piServerResult = await compactPiServer(this.model, {
|
|
1731
|
+
systemPrompt: this.systemPrompt,
|
|
1732
|
+
messages: this.agent.state.messages,
|
|
1733
|
+
tools: this.agent.state.tools,
|
|
1734
|
+
}, {
|
|
1735
|
+
sessionId: this.sessionId,
|
|
1736
|
+
apiKey,
|
|
1737
|
+
headers,
|
|
1738
|
+
customInstructions,
|
|
1739
|
+
settings: this.settingsManager.getCompactionSettings(),
|
|
1740
|
+
sessionTree: { entries: this.sessionManager.getEntries(), leafId: this.sessionManager.getLeafId() },
|
|
1741
|
+
signal: this._compactionAbortController.signal,
|
|
1742
|
+
reasoning: toProviderReasoning(this.thinkingLevel),
|
|
1743
|
+
onHistoryReconciled: (snapshot) => this.reconcilePiServerHistory(snapshot),
|
|
1744
|
+
});
|
|
1745
|
+
const result = await this._applyPiServerCompactionResult(piServerResult, "manual", false);
|
|
1746
|
+
this._lastServerCompactionTimestamp = Date.now();
|
|
1747
|
+
this._emit({
|
|
1748
|
+
type: "compaction_end",
|
|
1749
|
+
reason: "manual",
|
|
1750
|
+
result,
|
|
1751
|
+
aborted: false,
|
|
1752
|
+
willRetry: false,
|
|
1753
|
+
});
|
|
1754
|
+
return result;
|
|
1921
1755
|
}
|
|
1922
1756
|
const pathEntries = this.sessionManager.getBranch();
|
|
1923
1757
|
const settings = this.settingsManager.getCompactionSettings();
|
|
@@ -1950,42 +1784,6 @@ export class AgentSession {
|
|
|
1950
1784
|
fromExtension = true;
|
|
1951
1785
|
}
|
|
1952
1786
|
}
|
|
1953
|
-
if (isPiServerMode()) {
|
|
1954
|
-
const sessionFile = this.sessionManager.getSessionFile();
|
|
1955
|
-
if (!sessionFile) {
|
|
1956
|
-
throw new Error("Durable pi-server compaction requires a persisted session file");
|
|
1957
|
-
}
|
|
1958
|
-
const piServerResult = await compactPiServer(this.model, {
|
|
1959
|
-
systemPrompt: this.systemPrompt,
|
|
1960
|
-
messages: this.agent.state.messages,
|
|
1961
|
-
tools: this.agent.state.tools,
|
|
1962
|
-
}, {
|
|
1963
|
-
sessionId: this.sessionId,
|
|
1964
|
-
apiKey,
|
|
1965
|
-
headers,
|
|
1966
|
-
env,
|
|
1967
|
-
customInstructions,
|
|
1968
|
-
settings,
|
|
1969
|
-
preparation: { firstKeptEntryId: preparation.firstKeptEntryId },
|
|
1970
|
-
extensionCompaction,
|
|
1971
|
-
retry: this.settingsManager.getRetrySettings(),
|
|
1972
|
-
sessionTree: { entries: this.sessionManager.getEntries(), leafId: this.sessionManager.getLeafId() },
|
|
1973
|
-
piServerCompactStatePath: getPiServerCompactStatePath(sessionFile),
|
|
1974
|
-
signal: this._compactionAbortController.signal,
|
|
1975
|
-
reasoning: toProviderReasoning(this.thinkingLevel),
|
|
1976
|
-
onHistoryReconciled: (snapshot) => this.reconcilePiServerHistory(snapshot),
|
|
1977
|
-
});
|
|
1978
|
-
const result = await this._applyPiServerCompactionResult(piServerResult, "manual", false);
|
|
1979
|
-
this._lastServerCompactionTimestamp = Date.now();
|
|
1980
|
-
this._emit({
|
|
1981
|
-
type: "compaction_end",
|
|
1982
|
-
reason: "manual",
|
|
1983
|
-
result,
|
|
1984
|
-
aborted: false,
|
|
1985
|
-
willRetry: false,
|
|
1986
|
-
});
|
|
1987
|
-
return result;
|
|
1988
|
-
}
|
|
1989
1787
|
let summary;
|
|
1990
1788
|
let firstKeptEntryId;
|
|
1991
1789
|
let tokensBefore;
|
|
@@ -2001,7 +1799,7 @@ export class AgentSession {
|
|
|
2001
1799
|
}
|
|
2002
1800
|
else {
|
|
2003
1801
|
// Generate compaction result
|
|
2004
|
-
const result = await compact(preparation, this.model, apiKey, headers, customInstructions, this._compactionAbortController.signal, this.thinkingLevel, this.
|
|
1802
|
+
const result = await compact(preparation, this.model, apiKey, headers, customInstructions, this._compactionAbortController.signal, this.thinkingLevel, this.agent.streamFunction, env, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason: "manual" }));
|
|
2005
1803
|
summary = result.summary;
|
|
2006
1804
|
firstKeptEntryId = result.firstKeptEntryId;
|
|
2007
1805
|
tokensBefore = result.tokensBefore;
|
|
@@ -2058,7 +1856,6 @@ export class AgentSession {
|
|
|
2058
1856
|
throw error;
|
|
2059
1857
|
}
|
|
2060
1858
|
finally {
|
|
2061
|
-
this._releasePiServerOperationLease(piServerLease.path, piServerLease.acquired, piServerLease.owner);
|
|
2062
1859
|
this._compactionAbortController = undefined;
|
|
2063
1860
|
this._reconnectToAgent();
|
|
2064
1861
|
}
|
|
@@ -2182,33 +1979,45 @@ export class AgentSession {
|
|
|
2182
1979
|
*/
|
|
2183
1980
|
async _runAutoCompaction(reason, willRetry, preparationOverride, preparationOptions) {
|
|
2184
1981
|
const settings = this.settingsManager.getCompactionSettings();
|
|
2185
|
-
const model = this.model;
|
|
2186
1982
|
let started = false;
|
|
2187
|
-
let piServerLease = {
|
|
2188
|
-
path: undefined,
|
|
2189
|
-
acquired: false,
|
|
2190
|
-
owner: undefined,
|
|
2191
|
-
};
|
|
2192
1983
|
try {
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
await this._recoverPendingPiServerRunBeforeControlOperation();
|
|
1984
|
+
if (!this.model) {
|
|
1985
|
+
return false;
|
|
2196
1986
|
}
|
|
2197
|
-
|
|
2198
|
-
|
|
1987
|
+
let apiKey;
|
|
1988
|
+
let headers;
|
|
1989
|
+
let env;
|
|
1990
|
+
if (this.agent.streamFunction === streamSimple) {
|
|
1991
|
+
({ apiKey, headers, env } = await this._getRequiredRequestAuth(this.model));
|
|
1992
|
+
}
|
|
1993
|
+
else {
|
|
1994
|
+
({ apiKey, headers, env } = await this._getSummarizationRequestAuth(this.model));
|
|
1995
|
+
}
|
|
1996
|
+
if (isPiServerMode()) {
|
|
2199
1997
|
this._emit({ type: "compaction_start", reason });
|
|
1998
|
+
this._autoCompactionAbortController = new AbortController();
|
|
2200
1999
|
started = true;
|
|
2000
|
+
const signal = this._autoCompactionAbortController.signal;
|
|
2001
|
+
const piServerResult = await compactPiServer(this.model, {
|
|
2002
|
+
systemPrompt: this.systemPrompt,
|
|
2003
|
+
messages: this.agent.state.messages,
|
|
2004
|
+
tools: this.agent.state.tools,
|
|
2005
|
+
}, {
|
|
2006
|
+
sessionId: this.sessionId,
|
|
2007
|
+
apiKey,
|
|
2008
|
+
headers,
|
|
2009
|
+
settings,
|
|
2010
|
+
preparation: preparationOptions,
|
|
2011
|
+
sessionTree: { entries: this.sessionManager.getEntries(), leafId: this.sessionManager.getLeafId() },
|
|
2012
|
+
signal,
|
|
2013
|
+
reasoning: toProviderReasoning(this.thinkingLevel),
|
|
2014
|
+
onHistoryReconciled: (snapshot) => this.reconcilePiServerHistory(snapshot),
|
|
2015
|
+
});
|
|
2016
|
+
const result = await this._applyPiServerCompactionResult(piServerResult, reason, willRetry);
|
|
2201
2017
|
this._lastServerCompactionTimestamp = Date.now();
|
|
2202
|
-
this._emit({ type: "compaction_end", reason, result
|
|
2018
|
+
this._emit({ type: "compaction_end", reason, result, aborted: false, willRetry });
|
|
2203
2019
|
return willRetry ? true : this.agent.hasQueuedMessages();
|
|
2204
2020
|
}
|
|
2205
|
-
if (!model) {
|
|
2206
|
-
return false;
|
|
2207
|
-
}
|
|
2208
|
-
let apiKey;
|
|
2209
|
-
let headers;
|
|
2210
|
-
let env;
|
|
2211
|
-
({ apiKey, headers, env } = await this._getSummarizationRequestAuth(model));
|
|
2212
2021
|
const pathEntries = this.sessionManager.getBranch();
|
|
2213
2022
|
const preparation = preparationOverride ?? prepareCompaction(pathEntries, settings);
|
|
2214
2023
|
if (!preparation) {
|
|
@@ -2217,7 +2026,6 @@ export class AgentSession {
|
|
|
2217
2026
|
this._emit({ type: "compaction_start", reason });
|
|
2218
2027
|
this._autoCompactionAbortController = new AbortController();
|
|
2219
2028
|
started = true;
|
|
2220
|
-
const signal = this._autoCompactionAbortController.signal;
|
|
2221
2029
|
let extensionCompaction;
|
|
2222
2030
|
let fromExtension = false;
|
|
2223
2031
|
if (this._extensionRunner.hasHandlers("session_before_compact")) {
|
|
@@ -2228,7 +2036,7 @@ export class AgentSession {
|
|
|
2228
2036
|
customInstructions: undefined,
|
|
2229
2037
|
reason,
|
|
2230
2038
|
willRetry,
|
|
2231
|
-
signal,
|
|
2039
|
+
signal: this._autoCompactionAbortController.signal,
|
|
2232
2040
|
}));
|
|
2233
2041
|
if (extensionResult?.cancel) {
|
|
2234
2042
|
this._emit({
|
|
@@ -2245,35 +2053,6 @@ export class AgentSession {
|
|
|
2245
2053
|
fromExtension = true;
|
|
2246
2054
|
}
|
|
2247
2055
|
}
|
|
2248
|
-
if (isPiServerMode()) {
|
|
2249
|
-
const sessionFile = this.sessionManager.getSessionFile();
|
|
2250
|
-
if (!sessionFile) {
|
|
2251
|
-
throw new Error("Durable pi-server compaction requires a persisted session file");
|
|
2252
|
-
}
|
|
2253
|
-
const piServerResult = await compactPiServer(model, {
|
|
2254
|
-
systemPrompt: this.systemPrompt,
|
|
2255
|
-
messages: this.agent.state.messages,
|
|
2256
|
-
tools: this.agent.state.tools,
|
|
2257
|
-
}, {
|
|
2258
|
-
sessionId: this.sessionId,
|
|
2259
|
-
apiKey,
|
|
2260
|
-
headers,
|
|
2261
|
-
env,
|
|
2262
|
-
settings,
|
|
2263
|
-
retry: this.settingsManager.getRetrySettings(),
|
|
2264
|
-
preparation: preparationOptions ?? { firstKeptEntryId: preparation.firstKeptEntryId },
|
|
2265
|
-
extensionCompaction,
|
|
2266
|
-
sessionTree: { entries: this.sessionManager.getEntries(), leafId: this.sessionManager.getLeafId() },
|
|
2267
|
-
piServerCompactStatePath: getPiServerCompactStatePath(sessionFile),
|
|
2268
|
-
signal,
|
|
2269
|
-
reasoning: toProviderReasoning(this.thinkingLevel),
|
|
2270
|
-
onHistoryReconciled: (snapshot) => this.reconcilePiServerHistory(snapshot),
|
|
2271
|
-
});
|
|
2272
|
-
const result = await this._applyPiServerCompactionResult(piServerResult, reason, willRetry);
|
|
2273
|
-
this._lastServerCompactionTimestamp = Date.now();
|
|
2274
|
-
this._emit({ type: "compaction_end", reason, result, aborted: false, willRetry });
|
|
2275
|
-
return willRetry ? true : this.agent.hasQueuedMessages();
|
|
2276
|
-
}
|
|
2277
2056
|
let summary;
|
|
2278
2057
|
let firstKeptEntryId;
|
|
2279
2058
|
let tokensBefore;
|
|
@@ -2289,7 +2068,7 @@ export class AgentSession {
|
|
|
2289
2068
|
}
|
|
2290
2069
|
else {
|
|
2291
2070
|
// Generate compaction result
|
|
2292
|
-
const compactResult = await compact(preparation, model, apiKey, headers, undefined, this._autoCompactionAbortController.signal, this.thinkingLevel, this.
|
|
2071
|
+
const compactResult = await compact(preparation, this.model, apiKey, headers, undefined, this._autoCompactionAbortController.signal, this.thinkingLevel, this.agent.streamFunction, env, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason }));
|
|
2293
2072
|
summary = compactResult.summary;
|
|
2294
2073
|
firstKeptEntryId = compactResult.firstKeptEntryId;
|
|
2295
2074
|
tokensBefore = compactResult.tokensBefore;
|
|
@@ -2360,7 +2139,6 @@ export class AgentSession {
|
|
|
2360
2139
|
return false;
|
|
2361
2140
|
}
|
|
2362
2141
|
finally {
|
|
2363
|
-
this._releasePiServerOperationLease(piServerLease.path, piServerLease.acquired, piServerLease.owner);
|
|
2364
2142
|
this._autoCompactionAbortController = undefined;
|
|
2365
2143
|
}
|
|
2366
2144
|
}
|
|
@@ -2776,12 +2554,8 @@ export class AgentSession {
|
|
|
2776
2554
|
return false;
|
|
2777
2555
|
if (this._isPostAssistantPiServerSyncFailure(message))
|
|
2778
2556
|
return false;
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
const piServerFailure = getPiServerFailureMetadata(message);
|
|
2782
|
-
if (piServerFailure?.phase && piServerFailure.phase !== "provider_stream")
|
|
2783
|
-
return false;
|
|
2784
|
-
if (piServerFailure?.retryable === false)
|
|
2557
|
+
const piServerPhase = getPiServerFailurePhase(message);
|
|
2558
|
+
if (piServerPhase && piServerPhase !== "provider_stream")
|
|
2785
2559
|
return false;
|
|
2786
2560
|
if (message.errorMessage && this._isNonRetryableProviderLimitError(message.errorMessage))
|
|
2787
2561
|
return false;
|
|
@@ -3048,7 +2822,6 @@ export class AgentSession {
|
|
|
3048
2822
|
replaceInstructions,
|
|
3049
2823
|
label,
|
|
3050
2824
|
};
|
|
3051
|
-
const piServerLease = this._acquirePiServerOperationLease();
|
|
3052
2825
|
// Set up abort controller for summarization
|
|
3053
2826
|
this._branchSummaryAbortController = new AbortController();
|
|
3054
2827
|
try {
|
|
@@ -3096,7 +2869,7 @@ export class AgentSession {
|
|
|
3096
2869
|
customInstructions,
|
|
3097
2870
|
replaceInstructions,
|
|
3098
2871
|
reserveTokens: branchSummarySettings.reserveTokens,
|
|
3099
|
-
streamFn: this.
|
|
2872
|
+
streamFn: this.agent.streamFunction,
|
|
3100
2873
|
retry: this.settingsManager.getRetrySettings(),
|
|
3101
2874
|
callbacks: this._summarizationRetryCallbacks({ source: "branchSummary" }),
|
|
3102
2875
|
});
|
|
@@ -3181,7 +2954,6 @@ export class AgentSession {
|
|
|
3181
2954
|
return { editorText, cancelled: false, summaryEntry };
|
|
3182
2955
|
}
|
|
3183
2956
|
finally {
|
|
3184
|
-
this._releasePiServerOperationLease(piServerLease.path, piServerLease.acquired, piServerLease.owner);
|
|
3185
2957
|
this._branchSummaryAbortController = undefined;
|
|
3186
2958
|
}
|
|
3187
2959
|
}
|