@averyyy/pi-coding-agent 0.82.1-piclient.5 → 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 -314
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/pi-server-client.d.ts +2 -53
- package/dist/core/pi-server-client.d.ts.map +1 -1
- package/dist/core/pi-server-client.js +271 -2063
- 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 -438
- package/dist/core/pi-server-compact-state.js.map +0 -1
- package/dist/core/pi-server-run-state.d.ts +0 -41
- package/dist/core/pi-server-run-state.d.ts.map +0 -1
- package/dist/core/pi-server-run-state.js +0 -318
- 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,102 +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, { signal });
|
|
380
|
-
if (!result)
|
|
381
|
-
return undefined;
|
|
382
|
-
return this._applyPiServerCompactionResult(result, reason, willRetry);
|
|
383
|
-
}
|
|
384
263
|
async _getRequiredRequestAuth(model) {
|
|
385
264
|
let result;
|
|
386
265
|
try {
|
|
@@ -409,7 +288,7 @@ export class AgentSession {
|
|
|
409
288
|
throw new Error(formatNoApiKeyFoundMessage(model.provider));
|
|
410
289
|
}
|
|
411
290
|
async _getSummarizationRequestAuth(model) {
|
|
412
|
-
if (this.
|
|
291
|
+
if (this.agent.streamFunction === streamSimple) {
|
|
413
292
|
return this._getRequiredRequestAuth(model);
|
|
414
293
|
}
|
|
415
294
|
try {
|
|
@@ -601,33 +480,18 @@ export class AgentSession {
|
|
|
601
480
|
}
|
|
602
481
|
async _emitAgentSettled() {
|
|
603
482
|
this._isAgentRunActive = false;
|
|
604
|
-
|
|
605
|
-
|
|
483
|
+
try {
|
|
484
|
+
await this._extensionRunner.emit({ type: "agent_settled" });
|
|
485
|
+
this._emit({ type: "agent_settled" });
|
|
486
|
+
}
|
|
487
|
+
finally {
|
|
488
|
+
this._resolveIdleWaitIfIdle();
|
|
489
|
+
}
|
|
606
490
|
}
|
|
607
491
|
// Track last assistant message for auto-compaction check
|
|
608
492
|
_lastAssistantMessage = undefined;
|
|
609
493
|
/** Internal handler for agent events - shared by subscribe and reconnect */
|
|
610
494
|
_handleAgentEvent = async (event, signal) => {
|
|
611
|
-
if (event.type === "tool_execution_start") {
|
|
612
|
-
beginSessionToolEffect(this.sessionManager, event);
|
|
613
|
-
}
|
|
614
|
-
else if (event.type === "tool_execution_end") {
|
|
615
|
-
writeSessionToolEffectResult(this.sessionManager, event.toolResult, { finalizationPending: true });
|
|
616
|
-
this._toolResultsInFinalization.add(event.toolResult);
|
|
617
|
-
}
|
|
618
|
-
else if (event.type === "message_start" &&
|
|
619
|
-
event.message.role === "toolResult" &&
|
|
620
|
-
!this._toolResultsInFinalization.has(event.message)) {
|
|
621
|
-
beginSessionToolEffectFinalization(this.sessionManager, event.message);
|
|
622
|
-
this._toolResultsInFinalization.add(event.message);
|
|
623
|
-
}
|
|
624
|
-
else if (event.type === "message_end" &&
|
|
625
|
-
event.message.role === "toolResult" &&
|
|
626
|
-
!this._toolResultsInFinalization.has(event.message)) {
|
|
627
|
-
beginSessionToolEffectFinalization(this.sessionManager, event.message);
|
|
628
|
-
this._toolResultsInFinalization.add(event.message);
|
|
629
|
-
}
|
|
630
|
-
const finalizingToolResult = event.type === "message_end" && this._toolResultsInFinalization.has(event.message);
|
|
631
495
|
// When a user message starts, check if it's from either queue and remove it BEFORE emitting
|
|
632
496
|
// This ensures the UI sees the updated queue state
|
|
633
497
|
if (event.type === "message_start" && event.message.role === "user") {
|
|
@@ -654,13 +518,6 @@ export class AgentSession {
|
|
|
654
518
|
await this._emitExtensionEvent(event);
|
|
655
519
|
// Notify all listeners
|
|
656
520
|
this._emit(event.type === "agent_end" ? { ...event, willRetry: this._willRetryAfterAgentEnd(event) } : event);
|
|
657
|
-
if (finalizingToolResult) {
|
|
658
|
-
if (event.message.role !== "toolResult") {
|
|
659
|
-
throw new Error("A toolResult message_end replacement must remain a toolResult");
|
|
660
|
-
}
|
|
661
|
-
writeSessionToolEffectFinalResult(this.sessionManager, event.message);
|
|
662
|
-
this._toolResultsInFinalization.delete(event.message);
|
|
663
|
-
}
|
|
664
521
|
// Handle session persistence
|
|
665
522
|
if (event.type === "message_end") {
|
|
666
523
|
// Check if this is a custom message from extensions
|
|
@@ -672,11 +529,7 @@ export class AgentSession {
|
|
|
672
529
|
event.message.role === "assistant" ||
|
|
673
530
|
event.message.role === "toolResult") {
|
|
674
531
|
// Regular LLM message - persist as SessionMessageEntry
|
|
675
|
-
|
|
676
|
-
if (event.message.role === "toolResult") {
|
|
677
|
-
this.sessionManager.flushSessionFile();
|
|
678
|
-
commitSessionToolEffect(this.sessionManager, event.message, sessionEntryId);
|
|
679
|
-
}
|
|
532
|
+
this.sessionManager.appendMessage(event.message);
|
|
680
533
|
}
|
|
681
534
|
// Other message types (bashExecution, compactionSummary, branchSummary) are persisted elsewhere
|
|
682
535
|
// Track assistant message for auto-compaction (checked on agent_end)
|
|
@@ -696,10 +549,12 @@ export class AgentSession {
|
|
|
696
549
|
});
|
|
697
550
|
this._retryAttempt = 0;
|
|
698
551
|
}
|
|
699
|
-
if (isPiServerMode() &&
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
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) });
|
|
703
558
|
}
|
|
704
559
|
}
|
|
705
560
|
}
|
|
@@ -965,7 +820,7 @@ export class AgentSession {
|
|
|
965
820
|
}
|
|
966
821
|
/** Whether the session has no active agent run, retry, auto-compaction, or queued continuation. */
|
|
967
822
|
get isIdle() {
|
|
968
|
-
return !this._isAgentRunActive
|
|
823
|
+
return !this._isAgentRunActive;
|
|
969
824
|
}
|
|
970
825
|
/** Current effective system prompt (includes any per-turn extension modifications) */
|
|
971
826
|
get systemPrompt() {
|
|
@@ -1117,11 +972,9 @@ export class AgentSession {
|
|
|
1117
972
|
// Prompting
|
|
1118
973
|
// =========================================================================
|
|
1119
974
|
async _runAgentPrompt(messages) {
|
|
1120
|
-
const piServerLease = this._acquirePiServerOperationLease();
|
|
1121
975
|
this._resetValidationHintState();
|
|
1122
976
|
this._isAgentRunActive = true;
|
|
1123
977
|
try {
|
|
1124
|
-
await this._recoverPendingPiServerCompaction("threshold", false);
|
|
1125
978
|
await this.agent.prompt(messages);
|
|
1126
979
|
while (await this._handlePostAgentRun()) {
|
|
1127
980
|
try {
|
|
@@ -1144,15 +997,9 @@ export class AgentSession {
|
|
|
1144
997
|
await this._maybeGenerateSessionName();
|
|
1145
998
|
}
|
|
1146
999
|
finally {
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
await this._emitAgentSettled();
|
|
1151
|
-
}
|
|
1152
|
-
finally {
|
|
1153
|
-
this._releasePiServerOperationLease(piServerLease.path, piServerLease.acquired, piServerLease.owner);
|
|
1154
|
-
this._resolveIdleWaitIfIdle();
|
|
1155
|
-
}
|
|
1000
|
+
this._systemPromptOverride = undefined;
|
|
1001
|
+
this._flushPendingBashMessages();
|
|
1002
|
+
await this._emitAgentSettled();
|
|
1156
1003
|
}
|
|
1157
1004
|
}
|
|
1158
1005
|
_sessionHasInfoEntry() {
|
|
@@ -1189,7 +1036,7 @@ export class AgentSession {
|
|
|
1189
1036
|
if (!model || !transcript)
|
|
1190
1037
|
return;
|
|
1191
1038
|
try {
|
|
1192
|
-
const stream = await this.
|
|
1039
|
+
const stream = await this.agent.streamFunction(model, {
|
|
1193
1040
|
systemPrompt: this.systemPrompt,
|
|
1194
1041
|
messages: [
|
|
1195
1042
|
{
|
|
@@ -1202,7 +1049,7 @@ export class AgentSession {
|
|
|
1202
1049
|
}, {
|
|
1203
1050
|
maxTokens: 32,
|
|
1204
1051
|
reasoning: undefined,
|
|
1205
|
-
sessionId:
|
|
1052
|
+
sessionId: this.sessionId,
|
|
1206
1053
|
transport: this.agent.transport,
|
|
1207
1054
|
thinkingBudgets: this.agent.thinkingBudgets,
|
|
1208
1055
|
maxRetryDelayMs: this.agent.maxRetryDelayMs,
|
|
@@ -1835,26 +1682,9 @@ export class AgentSession {
|
|
|
1835
1682
|
// Compaction
|
|
1836
1683
|
// =========================================================================
|
|
1837
1684
|
async _applyPiServerCompactionResult(result, reason, willRetry) {
|
|
1838
|
-
|
|
1839
|
-
const operation = compactionEntry.piServerCompactOperation;
|
|
1840
|
-
if (!operation ||
|
|
1841
|
-
!Number.isSafeInteger(operation.baseEntryCount) ||
|
|
1842
|
-
operation.baseEntryCount < 0 ||
|
|
1843
|
-
(operation.baseLeafId !== null &&
|
|
1844
|
-
(typeof operation.baseLeafId !== "string" || operation.baseLeafId.length === 0)) ||
|
|
1845
|
-
typeof operation.baseTreeHash !== "string" ||
|
|
1846
|
-
!/^[a-f0-9]{64}$/u.test(operation.baseTreeHash)) {
|
|
1847
|
-
throw new Error("Pi-server compaction result is missing a valid durable base identity");
|
|
1848
|
-
}
|
|
1849
|
-
this.sessionManager.appendCompactionEntry(compactionEntry, {
|
|
1850
|
-
baseEntryCount: operation.baseEntryCount,
|
|
1851
|
-
baseLeafId: operation.baseLeafId,
|
|
1852
|
-
baseTreeHash: operation.baseTreeHash,
|
|
1853
|
-
});
|
|
1854
|
-
recordPiServerCompactionApplied(result);
|
|
1685
|
+
this.sessionManager.replaceTree(result.entries, result.leafId);
|
|
1855
1686
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
1856
1687
|
this.agent.state.messages = sessionContext.messages;
|
|
1857
|
-
await acknowledgePiServerCompaction(result);
|
|
1858
1688
|
const firstKeptEntryId = result.compaction.firstKeptEntryId;
|
|
1859
1689
|
if (!firstKeptEntryId) {
|
|
1860
1690
|
throw new Error("Pi-server compaction result is missing firstKeptEntryId");
|
|
@@ -1873,7 +1703,7 @@ export class AgentSession {
|
|
|
1873
1703
|
await this._extensionRunner.emit({
|
|
1874
1704
|
type: "session_compact",
|
|
1875
1705
|
compactionEntry: savedCompactionEntry,
|
|
1876
|
-
fromExtension:
|
|
1706
|
+
fromExtension: false,
|
|
1877
1707
|
reason,
|
|
1878
1708
|
willRetry,
|
|
1879
1709
|
});
|
|
@@ -1890,31 +1720,38 @@ export class AgentSession {
|
|
|
1890
1720
|
await this.abort();
|
|
1891
1721
|
this._compactionAbortController = new AbortController();
|
|
1892
1722
|
this._emit({ type: "compaction_start", reason: "manual" });
|
|
1893
|
-
let piServerLease = {
|
|
1894
|
-
path: undefined,
|
|
1895
|
-
acquired: false,
|
|
1896
|
-
owner: undefined,
|
|
1897
|
-
};
|
|
1898
1723
|
try {
|
|
1899
|
-
piServerLease = this._acquirePiServerOperationLease();
|
|
1900
|
-
await this._recoverPendingPiServerRunBeforeControlOperation(this._compactionAbortController.signal);
|
|
1901
|
-
const recoveredCompaction = await this._recoverPendingPiServerCompaction("manual", false, this._compactionAbortController.signal);
|
|
1902
|
-
if (recoveredCompaction) {
|
|
1903
|
-
this._emit({
|
|
1904
|
-
type: "compaction_end",
|
|
1905
|
-
reason: "manual",
|
|
1906
|
-
result: recoveredCompaction,
|
|
1907
|
-
aborted: false,
|
|
1908
|
-
willRetry: false,
|
|
1909
|
-
});
|
|
1910
|
-
return recoveredCompaction;
|
|
1911
|
-
}
|
|
1912
1724
|
if (!this.model) {
|
|
1913
1725
|
throw new Error(formatNoModelSelectedMessage());
|
|
1914
1726
|
}
|
|
1915
1727
|
const { apiKey, headers, env } = await this._getSummarizationRequestAuth(this.model);
|
|
1916
1728
|
if (isPiServerMode()) {
|
|
1917
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;
|
|
1918
1755
|
}
|
|
1919
1756
|
const pathEntries = this.sessionManager.getBranch();
|
|
1920
1757
|
const settings = this.settingsManager.getCompactionSettings();
|
|
@@ -1947,42 +1784,6 @@ export class AgentSession {
|
|
|
1947
1784
|
fromExtension = true;
|
|
1948
1785
|
}
|
|
1949
1786
|
}
|
|
1950
|
-
if (isPiServerMode()) {
|
|
1951
|
-
const sessionFile = this.sessionManager.getSessionFile();
|
|
1952
|
-
if (!sessionFile) {
|
|
1953
|
-
throw new Error("Durable pi-server compaction requires a persisted session file");
|
|
1954
|
-
}
|
|
1955
|
-
const piServerResult = await compactPiServer(this.model, {
|
|
1956
|
-
systemPrompt: this.systemPrompt,
|
|
1957
|
-
messages: this.agent.state.messages,
|
|
1958
|
-
tools: this.agent.state.tools,
|
|
1959
|
-
}, {
|
|
1960
|
-
sessionId: this.sessionId,
|
|
1961
|
-
apiKey,
|
|
1962
|
-
headers,
|
|
1963
|
-
env,
|
|
1964
|
-
customInstructions,
|
|
1965
|
-
settings,
|
|
1966
|
-
preparation: { firstKeptEntryId: preparation.firstKeptEntryId },
|
|
1967
|
-
extensionCompaction,
|
|
1968
|
-
retry: this.settingsManager.getRetrySettings(),
|
|
1969
|
-
sessionTree: { entries: this.sessionManager.getEntries(), leafId: this.sessionManager.getLeafId() },
|
|
1970
|
-
piServerCompactStatePath: getPiServerCompactStatePath(sessionFile),
|
|
1971
|
-
signal: this._compactionAbortController.signal,
|
|
1972
|
-
reasoning: toProviderReasoning(this.thinkingLevel),
|
|
1973
|
-
onHistoryReconciled: (snapshot) => this.reconcilePiServerHistory(snapshot),
|
|
1974
|
-
});
|
|
1975
|
-
const result = await this._applyPiServerCompactionResult(piServerResult, "manual", false);
|
|
1976
|
-
this._lastServerCompactionTimestamp = Date.now();
|
|
1977
|
-
this._emit({
|
|
1978
|
-
type: "compaction_end",
|
|
1979
|
-
reason: "manual",
|
|
1980
|
-
result,
|
|
1981
|
-
aborted: false,
|
|
1982
|
-
willRetry: false,
|
|
1983
|
-
});
|
|
1984
|
-
return result;
|
|
1985
|
-
}
|
|
1986
1787
|
let summary;
|
|
1987
1788
|
let firstKeptEntryId;
|
|
1988
1789
|
let tokensBefore;
|
|
@@ -1998,7 +1799,7 @@ export class AgentSession {
|
|
|
1998
1799
|
}
|
|
1999
1800
|
else {
|
|
2000
1801
|
// Generate compaction result
|
|
2001
|
-
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" }));
|
|
2002
1803
|
summary = result.summary;
|
|
2003
1804
|
firstKeptEntryId = result.firstKeptEntryId;
|
|
2004
1805
|
tokensBefore = result.tokensBefore;
|
|
@@ -2055,7 +1856,6 @@ export class AgentSession {
|
|
|
2055
1856
|
throw error;
|
|
2056
1857
|
}
|
|
2057
1858
|
finally {
|
|
2058
|
-
this._releasePiServerOperationLease(piServerLease.path, piServerLease.acquired, piServerLease.owner);
|
|
2059
1859
|
this._compactionAbortController = undefined;
|
|
2060
1860
|
this._reconnectToAgent();
|
|
2061
1861
|
}
|
|
@@ -2179,33 +1979,45 @@ export class AgentSession {
|
|
|
2179
1979
|
*/
|
|
2180
1980
|
async _runAutoCompaction(reason, willRetry, preparationOverride, preparationOptions) {
|
|
2181
1981
|
const settings = this.settingsManager.getCompactionSettings();
|
|
2182
|
-
const model = this.model;
|
|
2183
1982
|
let started = false;
|
|
2184
|
-
let piServerLease = {
|
|
2185
|
-
path: undefined,
|
|
2186
|
-
acquired: false,
|
|
2187
|
-
owner: undefined,
|
|
2188
|
-
};
|
|
2189
1983
|
try {
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
await this._recoverPendingPiServerRunBeforeControlOperation();
|
|
1984
|
+
if (!this.model) {
|
|
1985
|
+
return false;
|
|
2193
1986
|
}
|
|
2194
|
-
|
|
2195
|
-
|
|
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()) {
|
|
2196
1997
|
this._emit({ type: "compaction_start", reason });
|
|
1998
|
+
this._autoCompactionAbortController = new AbortController();
|
|
2197
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);
|
|
2198
2017
|
this._lastServerCompactionTimestamp = Date.now();
|
|
2199
|
-
this._emit({ type: "compaction_end", reason, result
|
|
2018
|
+
this._emit({ type: "compaction_end", reason, result, aborted: false, willRetry });
|
|
2200
2019
|
return willRetry ? true : this.agent.hasQueuedMessages();
|
|
2201
2020
|
}
|
|
2202
|
-
if (!model) {
|
|
2203
|
-
return false;
|
|
2204
|
-
}
|
|
2205
|
-
let apiKey;
|
|
2206
|
-
let headers;
|
|
2207
|
-
let env;
|
|
2208
|
-
({ apiKey, headers, env } = await this._getSummarizationRequestAuth(model));
|
|
2209
2021
|
const pathEntries = this.sessionManager.getBranch();
|
|
2210
2022
|
const preparation = preparationOverride ?? prepareCompaction(pathEntries, settings);
|
|
2211
2023
|
if (!preparation) {
|
|
@@ -2214,7 +2026,6 @@ export class AgentSession {
|
|
|
2214
2026
|
this._emit({ type: "compaction_start", reason });
|
|
2215
2027
|
this._autoCompactionAbortController = new AbortController();
|
|
2216
2028
|
started = true;
|
|
2217
|
-
const signal = this._autoCompactionAbortController.signal;
|
|
2218
2029
|
let extensionCompaction;
|
|
2219
2030
|
let fromExtension = false;
|
|
2220
2031
|
if (this._extensionRunner.hasHandlers("session_before_compact")) {
|
|
@@ -2225,7 +2036,7 @@ export class AgentSession {
|
|
|
2225
2036
|
customInstructions: undefined,
|
|
2226
2037
|
reason,
|
|
2227
2038
|
willRetry,
|
|
2228
|
-
signal,
|
|
2039
|
+
signal: this._autoCompactionAbortController.signal,
|
|
2229
2040
|
}));
|
|
2230
2041
|
if (extensionResult?.cancel) {
|
|
2231
2042
|
this._emit({
|
|
@@ -2242,35 +2053,6 @@ export class AgentSession {
|
|
|
2242
2053
|
fromExtension = true;
|
|
2243
2054
|
}
|
|
2244
2055
|
}
|
|
2245
|
-
if (isPiServerMode()) {
|
|
2246
|
-
const sessionFile = this.sessionManager.getSessionFile();
|
|
2247
|
-
if (!sessionFile) {
|
|
2248
|
-
throw new Error("Durable pi-server compaction requires a persisted session file");
|
|
2249
|
-
}
|
|
2250
|
-
const piServerResult = await compactPiServer(model, {
|
|
2251
|
-
systemPrompt: this.systemPrompt,
|
|
2252
|
-
messages: this.agent.state.messages,
|
|
2253
|
-
tools: this.agent.state.tools,
|
|
2254
|
-
}, {
|
|
2255
|
-
sessionId: this.sessionId,
|
|
2256
|
-
apiKey,
|
|
2257
|
-
headers,
|
|
2258
|
-
env,
|
|
2259
|
-
settings,
|
|
2260
|
-
retry: this.settingsManager.getRetrySettings(),
|
|
2261
|
-
preparation: preparationOptions ?? { firstKeptEntryId: preparation.firstKeptEntryId },
|
|
2262
|
-
extensionCompaction,
|
|
2263
|
-
sessionTree: { entries: this.sessionManager.getEntries(), leafId: this.sessionManager.getLeafId() },
|
|
2264
|
-
piServerCompactStatePath: getPiServerCompactStatePath(sessionFile),
|
|
2265
|
-
signal,
|
|
2266
|
-
reasoning: toProviderReasoning(this.thinkingLevel),
|
|
2267
|
-
onHistoryReconciled: (snapshot) => this.reconcilePiServerHistory(snapshot),
|
|
2268
|
-
});
|
|
2269
|
-
const result = await this._applyPiServerCompactionResult(piServerResult, reason, willRetry);
|
|
2270
|
-
this._lastServerCompactionTimestamp = Date.now();
|
|
2271
|
-
this._emit({ type: "compaction_end", reason, result, aborted: false, willRetry });
|
|
2272
|
-
return willRetry ? true : this.agent.hasQueuedMessages();
|
|
2273
|
-
}
|
|
2274
2056
|
let summary;
|
|
2275
2057
|
let firstKeptEntryId;
|
|
2276
2058
|
let tokensBefore;
|
|
@@ -2286,7 +2068,7 @@ export class AgentSession {
|
|
|
2286
2068
|
}
|
|
2287
2069
|
else {
|
|
2288
2070
|
// Generate compaction result
|
|
2289
|
-
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 }));
|
|
2290
2072
|
summary = compactResult.summary;
|
|
2291
2073
|
firstKeptEntryId = compactResult.firstKeptEntryId;
|
|
2292
2074
|
tokensBefore = compactResult.tokensBefore;
|
|
@@ -2357,7 +2139,6 @@ export class AgentSession {
|
|
|
2357
2139
|
return false;
|
|
2358
2140
|
}
|
|
2359
2141
|
finally {
|
|
2360
|
-
this._releasePiServerOperationLease(piServerLease.path, piServerLease.acquired, piServerLease.owner);
|
|
2361
2142
|
this._autoCompactionAbortController = undefined;
|
|
2362
2143
|
}
|
|
2363
2144
|
}
|
|
@@ -2773,12 +2554,8 @@ export class AgentSession {
|
|
|
2773
2554
|
return false;
|
|
2774
2555
|
if (this._isPostAssistantPiServerSyncFailure(message))
|
|
2775
2556
|
return false;
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
const piServerFailure = getPiServerFailureMetadata(message);
|
|
2779
|
-
if (piServerFailure?.phase && piServerFailure.phase !== "provider_stream")
|
|
2780
|
-
return false;
|
|
2781
|
-
if (piServerFailure?.retryable === false)
|
|
2557
|
+
const piServerPhase = getPiServerFailurePhase(message);
|
|
2558
|
+
if (piServerPhase && piServerPhase !== "provider_stream")
|
|
2782
2559
|
return false;
|
|
2783
2560
|
if (message.errorMessage && this._isNonRetryableProviderLimitError(message.errorMessage))
|
|
2784
2561
|
return false;
|
|
@@ -3045,7 +2822,6 @@ export class AgentSession {
|
|
|
3045
2822
|
replaceInstructions,
|
|
3046
2823
|
label,
|
|
3047
2824
|
};
|
|
3048
|
-
const piServerLease = this._acquirePiServerOperationLease();
|
|
3049
2825
|
// Set up abort controller for summarization
|
|
3050
2826
|
this._branchSummaryAbortController = new AbortController();
|
|
3051
2827
|
try {
|
|
@@ -3093,7 +2869,7 @@ export class AgentSession {
|
|
|
3093
2869
|
customInstructions,
|
|
3094
2870
|
replaceInstructions,
|
|
3095
2871
|
reserveTokens: branchSummarySettings.reserveTokens,
|
|
3096
|
-
streamFn: this.
|
|
2872
|
+
streamFn: this.agent.streamFunction,
|
|
3097
2873
|
retry: this.settingsManager.getRetrySettings(),
|
|
3098
2874
|
callbacks: this._summarizationRetryCallbacks({ source: "branchSummary" }),
|
|
3099
2875
|
});
|
|
@@ -3178,7 +2954,6 @@ export class AgentSession {
|
|
|
3178
2954
|
return { editorText, cancelled: false, summaryEntry };
|
|
3179
2955
|
}
|
|
3180
2956
|
finally {
|
|
3181
|
-
this._releasePiServerOperationLease(piServerLease.path, piServerLease.acquired, piServerLease.owner);
|
|
3182
2957
|
this._branchSummaryAbortController = undefined;
|
|
3183
2958
|
}
|
|
3184
2959
|
}
|