@averyyy/pi-coding-agent 0.82.1-piclient.2 → 0.82.1-piclient.4
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 +12 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +2 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/tool-effects.d.ts +6 -0
- package/dist/cli/tool-effects.d.ts.map +1 -0
- package/dist/cli/tool-effects.js +164 -0
- package/dist/cli/tool-effects.js.map +1 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +5 -0
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session.d.ts +13 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +340 -89
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/model-runtime.d.ts +7 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +66 -0
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/pi-server-client.d.ts +56 -2
- package/dist/core/pi-server-client.d.ts.map +1 -1
- package/dist/core/pi-server-client.js +2090 -288
- package/dist/core/pi-server-client.js.map +1 -1
- package/dist/core/pi-server-compact-state.d.ts +81 -0
- package/dist/core/pi-server-compact-state.d.ts.map +1 -0
- package/dist/core/pi-server-compact-state.js +438 -0
- package/dist/core/pi-server-compact-state.js.map +1 -0
- package/dist/core/pi-server-protocol.d.ts +2 -0
- package/dist/core/pi-server-protocol.d.ts.map +1 -1
- package/dist/core/pi-server-protocol.js +24 -1
- package/dist/core/pi-server-protocol.js.map +1 -1
- package/dist/core/pi-server-provider-execution.d.ts +19 -0
- package/dist/core/pi-server-provider-execution.d.ts.map +1 -0
- package/dist/core/pi-server-provider-execution.js +43 -0
- package/dist/core/pi-server-provider-execution.js.map +1 -0
- package/dist/core/pi-server-request.d.ts +28 -0
- package/dist/core/pi-server-request.d.ts.map +1 -1
- package/dist/core/pi-server-request.js +492 -75
- package/dist/core/pi-server-request.js.map +1 -1
- package/dist/core/pi-server-run-state.d.ts +41 -0
- package/dist/core/pi-server-run-state.d.ts.map +1 -0
- package/dist/core/pi-server-run-state.js +318 -0
- package/dist/core/pi-server-run-state.js.map +1 -0
- package/dist/core/provider-execution-contract.d.ts +36 -0
- package/dist/core/provider-execution-contract.d.ts.map +1 -0
- package/dist/core/provider-execution-contract.js +30 -0
- package/dist/core/provider-execution-contract.js.map +1 -0
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +74 -53
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +86 -2
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +737 -144
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/tool-effect-journal.d.ts +103 -0
- package/dist/core/tool-effect-journal.d.ts.map +1 -0
- package/dist/core/tool-effect-journal.js +1442 -0
- package/dist/core/tool-effect-journal.js.map +1 -0
- package/dist/core/tools/output-accumulator.d.ts +3 -1
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +46 -26
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +13 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +15 -0
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +98 -29
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/package.json +4 -4
|
@@ -12,6 +12,7 @@
|
|
|
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";
|
|
15
16
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
16
17
|
import { basename, dirname } from "node:path";
|
|
17
18
|
import { contentText } from "@earendil-works/pi-ai";
|
|
@@ -29,11 +30,15 @@ import { createToolHtmlRenderer } from "./export-html/tool-renderer.js";
|
|
|
29
30
|
import { ExtensionRunner, wrapRegisteredTools, } from "./extensions/index.js";
|
|
30
31
|
import { emitSessionShutdownEvent } from "./extensions/runner.js";
|
|
31
32
|
import { ModelRegistry } from "./model-registry.js";
|
|
32
|
-
import { compactPiServer, syncPiServerTree, } from "./pi-server-client.js";
|
|
33
|
+
import { acknowledgePiServerCompaction, acknowledgePiServerRunMessage, acquirePiServerSessionLease, compactPiServer, getPiServerRunDiagnostic, recordPiServerCompactionApplied, recoverPendingPiServerCompaction, releasePiServerRunLease, releasePiServerSessionLease, syncPiServerTree, } from "./pi-server-client.js";
|
|
34
|
+
import { getPiServerCompactStatePath, readPiServerPendingCompact } from "./pi-server-compact-state.js";
|
|
35
|
+
import { assertPiServerProviderExecution, } from "./pi-server-provider-execution.js";
|
|
36
|
+
import { getPiServerRunStatePath, readPiServerPendingRun } from "./pi-server-run-state.js";
|
|
33
37
|
import { expandPromptTemplate } from "./prompt-templates.js";
|
|
34
38
|
import { CURRENT_SESSION_VERSION, getLatestCompactionEntry } from "./session-manager.js";
|
|
35
39
|
import { createSyntheticSourceInfo } from "./source-info.js";
|
|
36
40
|
import { buildSystemPrompt } from "./system-prompt.js";
|
|
41
|
+
import { beginSessionToolEffect, beginSessionToolEffectFinalization, commitSessionToolEffect, recoverToolEffects, writeSessionToolEffectFinalResult, writeSessionToolEffectResult, } from "./tool-effect-journal.js";
|
|
37
42
|
import { createLocalBashOperations } from "./tools/bash.js";
|
|
38
43
|
import { createAllToolDefinitions } from "./tools/index.js";
|
|
39
44
|
import { createToolDefinitionFromAgentTool } from "./tools/tool-definition-wrapper.js";
|
|
@@ -93,16 +98,26 @@ function getStringField(input, key) {
|
|
|
93
98
|
const value = input[key];
|
|
94
99
|
return typeof value === "string" && value.trim().length > 0 ? value : undefined;
|
|
95
100
|
}
|
|
96
|
-
function
|
|
101
|
+
function getPiServerFailureMetadata(message) {
|
|
97
102
|
for (const diagnostic of message.diagnostics ?? []) {
|
|
98
103
|
if (diagnostic.type !== "pi_server_failure")
|
|
99
104
|
continue;
|
|
100
105
|
const phase = diagnostic.details?.phase;
|
|
101
|
-
|
|
102
|
-
|
|
106
|
+
const retryable = diagnostic.details?.retryable;
|
|
107
|
+
return {
|
|
108
|
+
phase: typeof phase === "string" ? phase : undefined,
|
|
109
|
+
retryable: typeof retryable === "boolean" ? retryable : undefined,
|
|
110
|
+
};
|
|
103
111
|
}
|
|
104
112
|
return undefined;
|
|
105
113
|
}
|
|
114
|
+
function isPiServerControlPlaneFailure(message) {
|
|
115
|
+
const hasFailure = message.diagnostics?.some((diagnostic) => diagnostic.type === "pi_server_failure") === true;
|
|
116
|
+
return hasFailure && getPiServerRunDiagnostic(message) === undefined;
|
|
117
|
+
}
|
|
118
|
+
function isPiServerRestartUncertainty(message) {
|
|
119
|
+
return getPiServerRunDiagnostic(message)?.restartUnknown === true;
|
|
120
|
+
}
|
|
106
121
|
function toolTextContent(content) {
|
|
107
122
|
return content
|
|
108
123
|
.filter((part) => part.type === "text")
|
|
@@ -165,6 +180,7 @@ export class AgentSession {
|
|
|
165
180
|
_isAgentRunActive = false;
|
|
166
181
|
_idleWaitPromise;
|
|
167
182
|
_resolveIdleWait;
|
|
183
|
+
_toolResultsInFinalization = new WeakSet();
|
|
168
184
|
/** Tracks pending steering messages for UI display. Removed when delivered. */
|
|
169
185
|
_steeringMessages = [];
|
|
170
186
|
/** Tracks pending follow-up messages for UI display. Removed when delivered. */
|
|
@@ -176,6 +192,7 @@ export class AgentSession {
|
|
|
176
192
|
_autoCompactionAbortController = undefined;
|
|
177
193
|
_overflowRecoveryAttempted = false;
|
|
178
194
|
_lastServerCompactionTimestamp = undefined;
|
|
195
|
+
_piServerSessionLeaseOwner;
|
|
179
196
|
// Branch summarization state
|
|
180
197
|
_branchSummaryAbortController = undefined;
|
|
181
198
|
// Retry state
|
|
@@ -208,6 +225,7 @@ export class AgentSession {
|
|
|
208
225
|
_extensionErrorUnsubscriber;
|
|
209
226
|
_autoSessionNameEnabled;
|
|
210
227
|
_autoSessionNameAttempted = false;
|
|
228
|
+
_auxiliaryStreamFunction;
|
|
211
229
|
_modelRuntime;
|
|
212
230
|
// Tool registry for extension getTools/setTools
|
|
213
231
|
_toolRegistry = new Map();
|
|
@@ -227,6 +245,7 @@ export class AgentSession {
|
|
|
227
245
|
this._customTools = config.customTools ?? [];
|
|
228
246
|
this._cwd = config.cwd;
|
|
229
247
|
this._modelRuntime = config.modelRuntime;
|
|
248
|
+
this._auxiliaryStreamFunction = config.auxiliaryStreamFunction;
|
|
230
249
|
this._extensionRunnerRef = config.extensionRunnerRef;
|
|
231
250
|
this._initialActiveToolNames = config.initialActiveToolNames;
|
|
232
251
|
this._allowedToolNames = config.allowedToolNames ? new Set(config.allowedToolNames) : undefined;
|
|
@@ -234,6 +253,10 @@ export class AgentSession {
|
|
|
234
253
|
this._baseToolsOverride = config.baseToolsOverride;
|
|
235
254
|
this._sessionStartEvent = config.sessionStartEvent ?? { type: "session_start", reason: "startup" };
|
|
236
255
|
this._autoSessionNameEnabled = config.autoSessionName ?? true;
|
|
256
|
+
const toolEffectRecovery = recoverToolEffects(this.sessionManager);
|
|
257
|
+
if (toolEffectRecovery.recoveredToolCallIds.length > 0) {
|
|
258
|
+
this.agent.state.messages = this.sessionManager.buildSessionContext().messages;
|
|
259
|
+
}
|
|
237
260
|
if (isPiServerMode()) {
|
|
238
261
|
this._detachPiServerTerminalAssistantFailure();
|
|
239
262
|
}
|
|
@@ -250,6 +273,9 @@ export class AgentSession {
|
|
|
250
273
|
get modelRuntime() {
|
|
251
274
|
return this._modelRuntime;
|
|
252
275
|
}
|
|
276
|
+
_getAuxiliaryStreamFunction() {
|
|
277
|
+
return this._auxiliaryStreamFunction ?? this.agent.streamFunction;
|
|
278
|
+
}
|
|
253
279
|
reconcilePiServerHistory(snapshot) {
|
|
254
280
|
this.sessionManager.replaceTree(snapshot.entries, snapshot.leafId);
|
|
255
281
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
@@ -260,6 +286,105 @@ export class AgentSession {
|
|
|
260
286
|
messageCount: snapshot.messages.length,
|
|
261
287
|
});
|
|
262
288
|
}
|
|
289
|
+
async _syncAndAcknowledgePiServerAssistantMessage(message, signal) {
|
|
290
|
+
const persistenceSignal = signal.aborted ? undefined : signal;
|
|
291
|
+
const sessionFile = this.sessionManager.getSessionFile();
|
|
292
|
+
const runStatePath = sessionFile ? getPiServerRunStatePath(sessionFile) : undefined;
|
|
293
|
+
try {
|
|
294
|
+
await syncPiServerTree(this.sessionId, {
|
|
295
|
+
systemPrompt: this.systemPrompt,
|
|
296
|
+
messages: this.agent.state.messages,
|
|
297
|
+
tools: this.agent.state.tools,
|
|
298
|
+
}, { entries: this.sessionManager.getEntries(), leafId: this.sessionManager.getLeafId() }, {
|
|
299
|
+
signal: persistenceSignal,
|
|
300
|
+
onHistoryReconciled: (snapshot) => this.reconcilePiServerHistory(snapshot),
|
|
301
|
+
});
|
|
302
|
+
this.sessionManager.flushSessionFile();
|
|
303
|
+
await acknowledgePiServerRunMessage(this.sessionId, message, runStatePath, persistenceSignal);
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
releasePiServerRunLease(this.sessionId, runStatePath);
|
|
307
|
+
throw error;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
_acquirePiServerOperationLease(reentrantOwner) {
|
|
311
|
+
if (!isPiServerMode())
|
|
312
|
+
return { path: undefined, acquired: false, owner: undefined };
|
|
313
|
+
const sessionFile = this.sessionManager.getSessionFile();
|
|
314
|
+
const path = sessionFile ? getPiServerRunStatePath(sessionFile) : undefined;
|
|
315
|
+
if (this._piServerSessionLeaseOwner) {
|
|
316
|
+
if (reentrantOwner !== this._piServerSessionLeaseOwner) {
|
|
317
|
+
throw new Error(`Cannot start a concurrent durable pi-server operation for session ${this.sessionId}`);
|
|
318
|
+
}
|
|
319
|
+
return { path, acquired: false, owner: this._piServerSessionLeaseOwner };
|
|
320
|
+
}
|
|
321
|
+
const owner = Symbol("pi-server-session-lease");
|
|
322
|
+
if (path)
|
|
323
|
+
acquirePiServerSessionLease(this.sessionId, path);
|
|
324
|
+
this._piServerSessionLeaseOwner = owner;
|
|
325
|
+
return { path, acquired: true, owner };
|
|
326
|
+
}
|
|
327
|
+
_releasePiServerOperationLease(path, acquired, owner) {
|
|
328
|
+
if (!acquired)
|
|
329
|
+
return;
|
|
330
|
+
if (!owner || this._piServerSessionLeaseOwner !== owner) {
|
|
331
|
+
throw new Error(`Cannot release a durable pi-server operation lease owned by another operation`);
|
|
332
|
+
}
|
|
333
|
+
if (path)
|
|
334
|
+
releasePiServerSessionLease(this.sessionId, path);
|
|
335
|
+
this._piServerSessionLeaseOwner = undefined;
|
|
336
|
+
}
|
|
337
|
+
async _recoverPendingPiServerRunBeforeControlOperation(signal) {
|
|
338
|
+
if (!isPiServerMode())
|
|
339
|
+
return;
|
|
340
|
+
const sessionFile = this.sessionManager.getSessionFile();
|
|
341
|
+
if (!sessionFile) {
|
|
342
|
+
throw new Error("Durable pi-server operations require a persisted session file");
|
|
343
|
+
}
|
|
344
|
+
const runStatePath = getPiServerRunStatePath(sessionFile);
|
|
345
|
+
const pending = readPiServerPendingRun(runStatePath);
|
|
346
|
+
if (!pending)
|
|
347
|
+
return;
|
|
348
|
+
let terminal;
|
|
349
|
+
const entries = this.sessionManager.getEntries();
|
|
350
|
+
for (let index = entries.length - 1; index >= 0; index--) {
|
|
351
|
+
const entry = entries[index];
|
|
352
|
+
if (entry.type !== "message" || entry.message.role !== "assistant")
|
|
353
|
+
continue;
|
|
354
|
+
const message = entry.message;
|
|
355
|
+
const diagnostic = getPiServerRunDiagnostic(message);
|
|
356
|
+
if (!diagnostic || diagnostic.runId !== pending.runId)
|
|
357
|
+
continue;
|
|
358
|
+
if (diagnostic.sessionId !== pending.sessionId ||
|
|
359
|
+
diagnostic.requestMac !== pending.requestHash ||
|
|
360
|
+
pending.sessionId !== this.sessionId) {
|
|
361
|
+
throw new Error("Pending pi-server run terminal does not match its durable client marker");
|
|
362
|
+
}
|
|
363
|
+
terminal = message;
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
if (!terminal) {
|
|
367
|
+
throw new Error(`Cannot start compaction while pi-server run ${pending.runId} is pending without a durable terminal assistant`);
|
|
368
|
+
}
|
|
369
|
+
await this._syncAndAcknowledgePiServerAssistantMessage(terminal, signal ?? new AbortController().signal);
|
|
370
|
+
}
|
|
371
|
+
async _recoverPendingPiServerCompaction(reason, willRetry, signal) {
|
|
372
|
+
if (!isPiServerMode())
|
|
373
|
+
return undefined;
|
|
374
|
+
const sessionFile = this.sessionManager.getSessionFile();
|
|
375
|
+
if (!sessionFile)
|
|
376
|
+
return undefined;
|
|
377
|
+
const compactStatePath = getPiServerCompactStatePath(sessionFile);
|
|
378
|
+
if (!readPiServerPendingCompact(compactStatePath))
|
|
379
|
+
return undefined;
|
|
380
|
+
const result = await recoverPendingPiServerCompaction(this.sessionId, { entries: this.sessionManager.getEntries(), leafId: this.sessionManager.getLeafId() }, compactStatePath, { signal });
|
|
381
|
+
if (!result)
|
|
382
|
+
return undefined;
|
|
383
|
+
return this._applyPiServerCompactionResult(result, reason, willRetry);
|
|
384
|
+
}
|
|
385
|
+
_assertPiServerProviderExecution(model) {
|
|
386
|
+
return assertPiServerProviderExecution(this._modelRuntime, model, this._extensionRunner);
|
|
387
|
+
}
|
|
263
388
|
async _getRequiredRequestAuth(model) {
|
|
264
389
|
let result;
|
|
265
390
|
try {
|
|
@@ -288,7 +413,7 @@ export class AgentSession {
|
|
|
288
413
|
throw new Error(formatNoApiKeyFoundMessage(model.provider));
|
|
289
414
|
}
|
|
290
415
|
async _getSummarizationRequestAuth(model) {
|
|
291
|
-
if (this.
|
|
416
|
+
if (this._getAuxiliaryStreamFunction() === streamSimple) {
|
|
292
417
|
return this._getRequiredRequestAuth(model);
|
|
293
418
|
}
|
|
294
419
|
try {
|
|
@@ -480,18 +605,33 @@ export class AgentSession {
|
|
|
480
605
|
}
|
|
481
606
|
async _emitAgentSettled() {
|
|
482
607
|
this._isAgentRunActive = false;
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
this._emit({ type: "agent_settled" });
|
|
486
|
-
}
|
|
487
|
-
finally {
|
|
488
|
-
this._resolveIdleWaitIfIdle();
|
|
489
|
-
}
|
|
608
|
+
await this._extensionRunner.emit({ type: "agent_settled" });
|
|
609
|
+
this._emit({ type: "agent_settled" });
|
|
490
610
|
}
|
|
491
611
|
// Track last assistant message for auto-compaction check
|
|
492
612
|
_lastAssistantMessage = undefined;
|
|
493
613
|
/** Internal handler for agent events - shared by subscribe and reconnect */
|
|
494
614
|
_handleAgentEvent = async (event, signal) => {
|
|
615
|
+
if (event.type === "tool_execution_start") {
|
|
616
|
+
beginSessionToolEffect(this.sessionManager, event);
|
|
617
|
+
}
|
|
618
|
+
else if (event.type === "tool_execution_end") {
|
|
619
|
+
writeSessionToolEffectResult(this.sessionManager, event.toolResult, { finalizationPending: true });
|
|
620
|
+
this._toolResultsInFinalization.add(event.toolResult);
|
|
621
|
+
}
|
|
622
|
+
else if (event.type === "message_start" &&
|
|
623
|
+
event.message.role === "toolResult" &&
|
|
624
|
+
!this._toolResultsInFinalization.has(event.message)) {
|
|
625
|
+
beginSessionToolEffectFinalization(this.sessionManager, event.message);
|
|
626
|
+
this._toolResultsInFinalization.add(event.message);
|
|
627
|
+
}
|
|
628
|
+
else if (event.type === "message_end" &&
|
|
629
|
+
event.message.role === "toolResult" &&
|
|
630
|
+
!this._toolResultsInFinalization.has(event.message)) {
|
|
631
|
+
beginSessionToolEffectFinalization(this.sessionManager, event.message);
|
|
632
|
+
this._toolResultsInFinalization.add(event.message);
|
|
633
|
+
}
|
|
634
|
+
const finalizingToolResult = event.type === "message_end" && this._toolResultsInFinalization.has(event.message);
|
|
495
635
|
// When a user message starts, check if it's from either queue and remove it BEFORE emitting
|
|
496
636
|
// This ensures the UI sees the updated queue state
|
|
497
637
|
if (event.type === "message_start" && event.message.role === "user") {
|
|
@@ -518,6 +658,13 @@ export class AgentSession {
|
|
|
518
658
|
await this._emitExtensionEvent(event);
|
|
519
659
|
// Notify all listeners
|
|
520
660
|
this._emit(event.type === "agent_end" ? { ...event, willRetry: this._willRetryAfterAgentEnd(event) } : event);
|
|
661
|
+
if (finalizingToolResult) {
|
|
662
|
+
if (event.message.role !== "toolResult") {
|
|
663
|
+
throw new Error("A toolResult message_end replacement must remain a toolResult");
|
|
664
|
+
}
|
|
665
|
+
writeSessionToolEffectFinalResult(this.sessionManager, event.message);
|
|
666
|
+
this._toolResultsInFinalization.delete(event.message);
|
|
667
|
+
}
|
|
521
668
|
// Handle session persistence
|
|
522
669
|
if (event.type === "message_end") {
|
|
523
670
|
// Check if this is a custom message from extensions
|
|
@@ -529,7 +676,11 @@ export class AgentSession {
|
|
|
529
676
|
event.message.role === "assistant" ||
|
|
530
677
|
event.message.role === "toolResult") {
|
|
531
678
|
// Regular LLM message - persist as SessionMessageEntry
|
|
532
|
-
this.sessionManager.appendMessage(event.message);
|
|
679
|
+
const sessionEntryId = this.sessionManager.appendMessage(event.message);
|
|
680
|
+
if (event.message.role === "toolResult") {
|
|
681
|
+
this.sessionManager.flushSessionFile();
|
|
682
|
+
commitSessionToolEffect(this.sessionManager, event.message, sessionEntryId);
|
|
683
|
+
}
|
|
533
684
|
}
|
|
534
685
|
// Other message types (bashExecution, compactionSummary, branchSummary) are persisted elsewhere
|
|
535
686
|
// Track assistant message for auto-compaction (checked on agent_end)
|
|
@@ -549,12 +700,10 @@ export class AgentSession {
|
|
|
549
700
|
});
|
|
550
701
|
this._retryAttempt = 0;
|
|
551
702
|
}
|
|
552
|
-
if (isPiServerMode() &&
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
tools: this.agent.state.tools,
|
|
557
|
-
}, { entries: this.sessionManager.getEntries(), leafId: this.sessionManager.getLeafId() }, { signal, onHistoryReconciled: (snapshot) => this.reconcilePiServerHistory(snapshot) });
|
|
703
|
+
if (isPiServerMode() &&
|
|
704
|
+
!this._isPostAssistantPiServerSyncFailure(assistantMsg) &&
|
|
705
|
+
!isPiServerControlPlaneFailure(assistantMsg)) {
|
|
706
|
+
await this._syncAndAcknowledgePiServerAssistantMessage(assistantMsg, signal);
|
|
558
707
|
}
|
|
559
708
|
}
|
|
560
709
|
}
|
|
@@ -820,7 +969,7 @@ export class AgentSession {
|
|
|
820
969
|
}
|
|
821
970
|
/** Whether the session has no active agent run, retry, auto-compaction, or queued continuation. */
|
|
822
971
|
get isIdle() {
|
|
823
|
-
return !this._isAgentRunActive;
|
|
972
|
+
return !this._isAgentRunActive && !this._piServerSessionLeaseOwner;
|
|
824
973
|
}
|
|
825
974
|
/** Current effective system prompt (includes any per-turn extension modifications) */
|
|
826
975
|
get systemPrompt() {
|
|
@@ -972,9 +1121,14 @@ export class AgentSession {
|
|
|
972
1121
|
// Prompting
|
|
973
1122
|
// =========================================================================
|
|
974
1123
|
async _runAgentPrompt(messages) {
|
|
1124
|
+
if (isPiServerMode() && this.model) {
|
|
1125
|
+
this._assertPiServerProviderExecution(this.model);
|
|
1126
|
+
}
|
|
1127
|
+
const piServerLease = this._acquirePiServerOperationLease();
|
|
975
1128
|
this._resetValidationHintState();
|
|
976
1129
|
this._isAgentRunActive = true;
|
|
977
1130
|
try {
|
|
1131
|
+
await this._recoverPendingPiServerCompaction("threshold", false);
|
|
978
1132
|
await this.agent.prompt(messages);
|
|
979
1133
|
while (await this._handlePostAgentRun()) {
|
|
980
1134
|
try {
|
|
@@ -997,9 +1151,15 @@ export class AgentSession {
|
|
|
997
1151
|
await this._maybeGenerateSessionName();
|
|
998
1152
|
}
|
|
999
1153
|
finally {
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1154
|
+
try {
|
|
1155
|
+
this._systemPromptOverride = undefined;
|
|
1156
|
+
this._flushPendingBashMessages();
|
|
1157
|
+
await this._emitAgentSettled();
|
|
1158
|
+
}
|
|
1159
|
+
finally {
|
|
1160
|
+
this._releasePiServerOperationLease(piServerLease.path, piServerLease.acquired, piServerLease.owner);
|
|
1161
|
+
this._resolveIdleWaitIfIdle();
|
|
1162
|
+
}
|
|
1003
1163
|
}
|
|
1004
1164
|
}
|
|
1005
1165
|
_sessionHasInfoEntry() {
|
|
@@ -1036,7 +1196,7 @@ export class AgentSession {
|
|
|
1036
1196
|
if (!model || !transcript)
|
|
1037
1197
|
return;
|
|
1038
1198
|
try {
|
|
1039
|
-
const stream = await this.
|
|
1199
|
+
const stream = await this._getAuxiliaryStreamFunction()(model, {
|
|
1040
1200
|
systemPrompt: this.systemPrompt,
|
|
1041
1201
|
messages: [
|
|
1042
1202
|
{
|
|
@@ -1049,7 +1209,7 @@ export class AgentSession {
|
|
|
1049
1209
|
}, {
|
|
1050
1210
|
maxTokens: 32,
|
|
1051
1211
|
reasoning: undefined,
|
|
1052
|
-
sessionId:
|
|
1212
|
+
sessionId: randomUUID(),
|
|
1053
1213
|
transport: this.agent.transport,
|
|
1054
1214
|
thinkingBudgets: this.agent.thinkingBudgets,
|
|
1055
1215
|
maxRetryDelayMs: this.agent.maxRetryDelayMs,
|
|
@@ -1160,6 +1320,9 @@ export class AgentSession {
|
|
|
1160
1320
|
if (!this.model) {
|
|
1161
1321
|
throw new Error(formatNoModelSelectedMessage());
|
|
1162
1322
|
}
|
|
1323
|
+
if (isPiServerMode()) {
|
|
1324
|
+
this._assertPiServerProviderExecution(this.model);
|
|
1325
|
+
}
|
|
1163
1326
|
const hasConfiguredAuth = this._modelRuntime.hasConfiguredAuth(this.model.provider) ||
|
|
1164
1327
|
(await this._modelRuntime.checkAuth(this.model.provider)) !== undefined;
|
|
1165
1328
|
if (!hasConfiguredAuth) {
|
|
@@ -1682,9 +1845,26 @@ export class AgentSession {
|
|
|
1682
1845
|
// Compaction
|
|
1683
1846
|
// =========================================================================
|
|
1684
1847
|
async _applyPiServerCompactionResult(result, reason, willRetry) {
|
|
1685
|
-
|
|
1848
|
+
const compactionEntry = result.compactionEntry;
|
|
1849
|
+
const operation = compactionEntry.piServerCompactOperation;
|
|
1850
|
+
if (!operation ||
|
|
1851
|
+
!Number.isSafeInteger(operation.baseEntryCount) ||
|
|
1852
|
+
operation.baseEntryCount < 0 ||
|
|
1853
|
+
(operation.baseLeafId !== null &&
|
|
1854
|
+
(typeof operation.baseLeafId !== "string" || operation.baseLeafId.length === 0)) ||
|
|
1855
|
+
typeof operation.baseTreeHash !== "string" ||
|
|
1856
|
+
!/^[a-f0-9]{64}$/u.test(operation.baseTreeHash)) {
|
|
1857
|
+
throw new Error("Pi-server compaction result is missing a valid durable base identity");
|
|
1858
|
+
}
|
|
1859
|
+
this.sessionManager.appendCompactionEntry(compactionEntry, {
|
|
1860
|
+
baseEntryCount: operation.baseEntryCount,
|
|
1861
|
+
baseLeafId: operation.baseLeafId,
|
|
1862
|
+
baseTreeHash: operation.baseTreeHash,
|
|
1863
|
+
});
|
|
1864
|
+
recordPiServerCompactionApplied(result);
|
|
1686
1865
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
1687
1866
|
this.agent.state.messages = sessionContext.messages;
|
|
1867
|
+
await acknowledgePiServerCompaction(result);
|
|
1688
1868
|
const firstKeptEntryId = result.compaction.firstKeptEntryId;
|
|
1689
1869
|
if (!firstKeptEntryId) {
|
|
1690
1870
|
throw new Error("Pi-server compaction result is missing firstKeptEntryId");
|
|
@@ -1703,7 +1883,7 @@ export class AgentSession {
|
|
|
1703
1883
|
await this._extensionRunner.emit({
|
|
1704
1884
|
type: "session_compact",
|
|
1705
1885
|
compactionEntry: savedCompactionEntry,
|
|
1706
|
-
fromExtension:
|
|
1886
|
+
fromExtension: savedCompactionEntry.fromHook === true,
|
|
1707
1887
|
reason,
|
|
1708
1888
|
willRetry,
|
|
1709
1889
|
});
|
|
@@ -1716,42 +1896,36 @@ export class AgentSession {
|
|
|
1716
1896
|
* @param customInstructions Optional instructions for the compaction summary
|
|
1717
1897
|
*/
|
|
1718
1898
|
async compact(customInstructions) {
|
|
1899
|
+
const piServerExecution = isPiServerMode() && this.model ? this._assertPiServerProviderExecution(this.model) : undefined;
|
|
1719
1900
|
this._disconnectFromAgent();
|
|
1720
1901
|
await this.abort();
|
|
1721
1902
|
this._compactionAbortController = new AbortController();
|
|
1722
1903
|
this._emit({ type: "compaction_start", reason: "manual" });
|
|
1904
|
+
let piServerLease = {
|
|
1905
|
+
path: undefined,
|
|
1906
|
+
acquired: false,
|
|
1907
|
+
owner: undefined,
|
|
1908
|
+
};
|
|
1723
1909
|
try {
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
if (isPiServerMode()) {
|
|
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();
|
|
1910
|
+
piServerLease = this._acquirePiServerOperationLease();
|
|
1911
|
+
await this._recoverPendingPiServerRunBeforeControlOperation(this._compactionAbortController.signal);
|
|
1912
|
+
const recoveredCompaction = await this._recoverPendingPiServerCompaction("manual", false, this._compactionAbortController.signal);
|
|
1913
|
+
if (recoveredCompaction) {
|
|
1747
1914
|
this._emit({
|
|
1748
1915
|
type: "compaction_end",
|
|
1749
1916
|
reason: "manual",
|
|
1750
|
-
result,
|
|
1917
|
+
result: recoveredCompaction,
|
|
1751
1918
|
aborted: false,
|
|
1752
1919
|
willRetry: false,
|
|
1753
1920
|
});
|
|
1754
|
-
return
|
|
1921
|
+
return recoveredCompaction;
|
|
1922
|
+
}
|
|
1923
|
+
if (!this.model) {
|
|
1924
|
+
throw new Error(formatNoModelSelectedMessage());
|
|
1925
|
+
}
|
|
1926
|
+
const { apiKey, headers, env } = await this._getSummarizationRequestAuth(this.model);
|
|
1927
|
+
if (isPiServerMode()) {
|
|
1928
|
+
this._detachPiServerTerminalAssistantFailure();
|
|
1755
1929
|
}
|
|
1756
1930
|
const pathEntries = this.sessionManager.getBranch();
|
|
1757
1931
|
const settings = this.settingsManager.getCompactionSettings();
|
|
@@ -1784,6 +1958,43 @@ export class AgentSession {
|
|
|
1784
1958
|
fromExtension = true;
|
|
1785
1959
|
}
|
|
1786
1960
|
}
|
|
1961
|
+
if (isPiServerMode()) {
|
|
1962
|
+
const sessionFile = this.sessionManager.getSessionFile();
|
|
1963
|
+
if (!sessionFile) {
|
|
1964
|
+
throw new Error("Durable pi-server compaction requires a persisted session file");
|
|
1965
|
+
}
|
|
1966
|
+
const piServerResult = await compactPiServer(this.model, {
|
|
1967
|
+
systemPrompt: this.systemPrompt,
|
|
1968
|
+
messages: this.agent.state.messages,
|
|
1969
|
+
tools: this.agent.state.tools,
|
|
1970
|
+
}, {
|
|
1971
|
+
sessionId: this.sessionId,
|
|
1972
|
+
apiKey,
|
|
1973
|
+
headers,
|
|
1974
|
+
env,
|
|
1975
|
+
customInstructions,
|
|
1976
|
+
settings,
|
|
1977
|
+
preparation: { firstKeptEntryId: preparation.firstKeptEntryId },
|
|
1978
|
+
extensionCompaction,
|
|
1979
|
+
retry: this.settingsManager.getRetrySettings(),
|
|
1980
|
+
sessionTree: { entries: this.sessionManager.getEntries(), leafId: this.sessionManager.getLeafId() },
|
|
1981
|
+
providerExecutionFingerprint: piServerExecution?.providerExecutionFingerprint,
|
|
1982
|
+
piServerCompactStatePath: getPiServerCompactStatePath(sessionFile),
|
|
1983
|
+
signal: this._compactionAbortController.signal,
|
|
1984
|
+
reasoning: toProviderReasoning(this.thinkingLevel),
|
|
1985
|
+
onHistoryReconciled: (snapshot) => this.reconcilePiServerHistory(snapshot),
|
|
1986
|
+
});
|
|
1987
|
+
const result = await this._applyPiServerCompactionResult(piServerResult, "manual", false);
|
|
1988
|
+
this._lastServerCompactionTimestamp = Date.now();
|
|
1989
|
+
this._emit({
|
|
1990
|
+
type: "compaction_end",
|
|
1991
|
+
reason: "manual",
|
|
1992
|
+
result,
|
|
1993
|
+
aborted: false,
|
|
1994
|
+
willRetry: false,
|
|
1995
|
+
});
|
|
1996
|
+
return result;
|
|
1997
|
+
}
|
|
1787
1998
|
let summary;
|
|
1788
1999
|
let firstKeptEntryId;
|
|
1789
2000
|
let tokensBefore;
|
|
@@ -1799,7 +2010,7 @@ export class AgentSession {
|
|
|
1799
2010
|
}
|
|
1800
2011
|
else {
|
|
1801
2012
|
// Generate compaction result
|
|
1802
|
-
const result = await compact(preparation, this.model, apiKey, headers, customInstructions, this._compactionAbortController.signal, this.thinkingLevel, this.
|
|
2013
|
+
const result = await compact(preparation, this.model, apiKey, headers, customInstructions, this._compactionAbortController.signal, this.thinkingLevel, this._getAuxiliaryStreamFunction(), env, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason: "manual" }));
|
|
1803
2014
|
summary = result.summary;
|
|
1804
2015
|
firstKeptEntryId = result.firstKeptEntryId;
|
|
1805
2016
|
tokensBefore = result.tokensBefore;
|
|
@@ -1856,6 +2067,7 @@ export class AgentSession {
|
|
|
1856
2067
|
throw error;
|
|
1857
2068
|
}
|
|
1858
2069
|
finally {
|
|
2070
|
+
this._releasePiServerOperationLease(piServerLease.path, piServerLease.acquired, piServerLease.owner);
|
|
1859
2071
|
this._compactionAbortController = undefined;
|
|
1860
2072
|
this._reconnectToAgent();
|
|
1861
2073
|
}
|
|
@@ -1912,6 +2124,9 @@ export class AgentSession {
|
|
|
1912
2124
|
// but must not retry: the assistant answer already completed and agent.continue() cannot
|
|
1913
2125
|
// continue from an assistant message.
|
|
1914
2126
|
if (sameModel && isContextOverflow(assistantMessage, contextWindow)) {
|
|
2127
|
+
if (isPiServerMode() && this.model) {
|
|
2128
|
+
this._assertPiServerProviderExecution(this.model);
|
|
2129
|
+
}
|
|
1915
2130
|
const willRetry = assistantMessage.stopReason !== "stop";
|
|
1916
2131
|
if (!willRetry) {
|
|
1917
2132
|
return await this._runAutoCompaction("overflow", false);
|
|
@@ -1970,6 +2185,9 @@ export class AgentSession {
|
|
|
1970
2185
|
contextTokens = directContextTokens;
|
|
1971
2186
|
}
|
|
1972
2187
|
if (shouldCompact(contextTokens, contextWindow, settings)) {
|
|
2188
|
+
if (isPiServerMode() && this.model) {
|
|
2189
|
+
this._assertPiServerProviderExecution(this.model);
|
|
2190
|
+
}
|
|
1973
2191
|
return await this._runAutoCompaction("threshold", false);
|
|
1974
2192
|
}
|
|
1975
2193
|
return false;
|
|
@@ -1979,45 +2197,34 @@ export class AgentSession {
|
|
|
1979
2197
|
*/
|
|
1980
2198
|
async _runAutoCompaction(reason, willRetry, preparationOverride, preparationOptions) {
|
|
1981
2199
|
const settings = this.settingsManager.getCompactionSettings();
|
|
2200
|
+
const model = this.model;
|
|
2201
|
+
const piServerExecution = isPiServerMode() && model ? this._assertPiServerProviderExecution(model) : undefined;
|
|
1982
2202
|
let started = false;
|
|
2203
|
+
let piServerLease = {
|
|
2204
|
+
path: undefined,
|
|
2205
|
+
acquired: false,
|
|
2206
|
+
owner: undefined,
|
|
2207
|
+
};
|
|
1983
2208
|
try {
|
|
1984
|
-
|
|
1985
|
-
|
|
2209
|
+
piServerLease = this._acquirePiServerOperationLease(this._isAgentRunActive ? this._piServerSessionLeaseOwner : undefined);
|
|
2210
|
+
if (!this._isAgentRunActive) {
|
|
2211
|
+
await this._recoverPendingPiServerRunBeforeControlOperation();
|
|
1986
2212
|
}
|
|
1987
|
-
|
|
1988
|
-
|
|
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()) {
|
|
2213
|
+
const recoveredCompaction = await this._recoverPendingPiServerCompaction(reason, willRetry);
|
|
2214
|
+
if (recoveredCompaction) {
|
|
1997
2215
|
this._emit({ type: "compaction_start", reason });
|
|
1998
|
-
this._autoCompactionAbortController = new AbortController();
|
|
1999
2216
|
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);
|
|
2017
2217
|
this._lastServerCompactionTimestamp = Date.now();
|
|
2018
|
-
this._emit({ type: "compaction_end", reason, result, aborted: false, willRetry });
|
|
2218
|
+
this._emit({ type: "compaction_end", reason, result: recoveredCompaction, aborted: false, willRetry });
|
|
2019
2219
|
return willRetry ? true : this.agent.hasQueuedMessages();
|
|
2020
2220
|
}
|
|
2221
|
+
if (!model) {
|
|
2222
|
+
return false;
|
|
2223
|
+
}
|
|
2224
|
+
let apiKey;
|
|
2225
|
+
let headers;
|
|
2226
|
+
let env;
|
|
2227
|
+
({ apiKey, headers, env } = await this._getSummarizationRequestAuth(model));
|
|
2021
2228
|
const pathEntries = this.sessionManager.getBranch();
|
|
2022
2229
|
const preparation = preparationOverride ?? prepareCompaction(pathEntries, settings);
|
|
2023
2230
|
if (!preparation) {
|
|
@@ -2026,6 +2233,7 @@ export class AgentSession {
|
|
|
2026
2233
|
this._emit({ type: "compaction_start", reason });
|
|
2027
2234
|
this._autoCompactionAbortController = new AbortController();
|
|
2028
2235
|
started = true;
|
|
2236
|
+
const signal = this._autoCompactionAbortController.signal;
|
|
2029
2237
|
let extensionCompaction;
|
|
2030
2238
|
let fromExtension = false;
|
|
2031
2239
|
if (this._extensionRunner.hasHandlers("session_before_compact")) {
|
|
@@ -2036,7 +2244,7 @@ export class AgentSession {
|
|
|
2036
2244
|
customInstructions: undefined,
|
|
2037
2245
|
reason,
|
|
2038
2246
|
willRetry,
|
|
2039
|
-
signal
|
|
2247
|
+
signal,
|
|
2040
2248
|
}));
|
|
2041
2249
|
if (extensionResult?.cancel) {
|
|
2042
2250
|
this._emit({
|
|
@@ -2053,6 +2261,36 @@ export class AgentSession {
|
|
|
2053
2261
|
fromExtension = true;
|
|
2054
2262
|
}
|
|
2055
2263
|
}
|
|
2264
|
+
if (isPiServerMode()) {
|
|
2265
|
+
const sessionFile = this.sessionManager.getSessionFile();
|
|
2266
|
+
if (!sessionFile) {
|
|
2267
|
+
throw new Error("Durable pi-server compaction requires a persisted session file");
|
|
2268
|
+
}
|
|
2269
|
+
const piServerResult = await compactPiServer(model, {
|
|
2270
|
+
systemPrompt: this.systemPrompt,
|
|
2271
|
+
messages: this.agent.state.messages,
|
|
2272
|
+
tools: this.agent.state.tools,
|
|
2273
|
+
}, {
|
|
2274
|
+
sessionId: this.sessionId,
|
|
2275
|
+
apiKey,
|
|
2276
|
+
headers,
|
|
2277
|
+
env,
|
|
2278
|
+
settings,
|
|
2279
|
+
retry: this.settingsManager.getRetrySettings(),
|
|
2280
|
+
preparation: preparationOptions ?? { firstKeptEntryId: preparation.firstKeptEntryId },
|
|
2281
|
+
extensionCompaction,
|
|
2282
|
+
sessionTree: { entries: this.sessionManager.getEntries(), leafId: this.sessionManager.getLeafId() },
|
|
2283
|
+
providerExecutionFingerprint: piServerExecution?.providerExecutionFingerprint,
|
|
2284
|
+
piServerCompactStatePath: getPiServerCompactStatePath(sessionFile),
|
|
2285
|
+
signal,
|
|
2286
|
+
reasoning: toProviderReasoning(this.thinkingLevel),
|
|
2287
|
+
onHistoryReconciled: (snapshot) => this.reconcilePiServerHistory(snapshot),
|
|
2288
|
+
});
|
|
2289
|
+
const result = await this._applyPiServerCompactionResult(piServerResult, reason, willRetry);
|
|
2290
|
+
this._lastServerCompactionTimestamp = Date.now();
|
|
2291
|
+
this._emit({ type: "compaction_end", reason, result, aborted: false, willRetry });
|
|
2292
|
+
return willRetry ? true : this.agent.hasQueuedMessages();
|
|
2293
|
+
}
|
|
2056
2294
|
let summary;
|
|
2057
2295
|
let firstKeptEntryId;
|
|
2058
2296
|
let tokensBefore;
|
|
@@ -2068,7 +2306,7 @@ export class AgentSession {
|
|
|
2068
2306
|
}
|
|
2069
2307
|
else {
|
|
2070
2308
|
// Generate compaction result
|
|
2071
|
-
const compactResult = await compact(preparation,
|
|
2309
|
+
const compactResult = await compact(preparation, model, apiKey, headers, undefined, this._autoCompactionAbortController.signal, this.thinkingLevel, this._getAuxiliaryStreamFunction(), env, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason }));
|
|
2072
2310
|
summary = compactResult.summary;
|
|
2073
2311
|
firstKeptEntryId = compactResult.firstKeptEntryId;
|
|
2074
2312
|
tokensBefore = compactResult.tokensBefore;
|
|
@@ -2139,6 +2377,7 @@ export class AgentSession {
|
|
|
2139
2377
|
return false;
|
|
2140
2378
|
}
|
|
2141
2379
|
finally {
|
|
2380
|
+
this._releasePiServerOperationLease(piServerLease.path, piServerLease.acquired, piServerLease.owner);
|
|
2142
2381
|
this._autoCompactionAbortController = undefined;
|
|
2143
2382
|
}
|
|
2144
2383
|
}
|
|
@@ -2189,6 +2428,9 @@ export class AgentSession {
|
|
|
2189
2428
|
}
|
|
2190
2429
|
const settings = this.settingsManager.getCompactionSettings();
|
|
2191
2430
|
const markerParentId = this.sessionManager.getLeafId();
|
|
2431
|
+
if (isPiServerMode() && this.model) {
|
|
2432
|
+
this._assertPiServerProviderExecution(this.model);
|
|
2433
|
+
}
|
|
2192
2434
|
const markerId = this._appendIntraTurnCompactionMarker();
|
|
2193
2435
|
const preparationOptions = { firstKeptEntryId: markerId };
|
|
2194
2436
|
const branchWithMarker = this.sessionManager.getBranch();
|
|
@@ -2554,8 +2796,12 @@ export class AgentSession {
|
|
|
2554
2796
|
return false;
|
|
2555
2797
|
if (this._isPostAssistantPiServerSyncFailure(message))
|
|
2556
2798
|
return false;
|
|
2557
|
-
|
|
2558
|
-
|
|
2799
|
+
if (isPiServerRestartUncertainty(message))
|
|
2800
|
+
return false;
|
|
2801
|
+
const piServerFailure = getPiServerFailureMetadata(message);
|
|
2802
|
+
if (piServerFailure?.phase && piServerFailure.phase !== "provider_stream")
|
|
2803
|
+
return false;
|
|
2804
|
+
if (piServerFailure?.retryable === false)
|
|
2559
2805
|
return false;
|
|
2560
2806
|
if (message.errorMessage && this._isNonRetryableProviderLimitError(message.errorMessage))
|
|
2561
2807
|
return false;
|
|
@@ -2793,6 +3039,9 @@ export class AgentSession {
|
|
|
2793
3039
|
* @returns Result with editorText (if user message) and cancelled status
|
|
2794
3040
|
*/
|
|
2795
3041
|
async navigateTree(targetId, options = {}) {
|
|
3042
|
+
if (isPiServerMode() && options.summarize && this.model) {
|
|
3043
|
+
this._assertPiServerProviderExecution(this.model);
|
|
3044
|
+
}
|
|
2796
3045
|
const oldLeafId = this.sessionManager.getLeafId();
|
|
2797
3046
|
// No-op if already at target
|
|
2798
3047
|
if (targetId === oldLeafId) {
|
|
@@ -2822,6 +3071,7 @@ export class AgentSession {
|
|
|
2822
3071
|
replaceInstructions,
|
|
2823
3072
|
label,
|
|
2824
3073
|
};
|
|
3074
|
+
const piServerLease = this._acquirePiServerOperationLease();
|
|
2825
3075
|
// Set up abort controller for summarization
|
|
2826
3076
|
this._branchSummaryAbortController = new AbortController();
|
|
2827
3077
|
try {
|
|
@@ -2869,7 +3119,7 @@ export class AgentSession {
|
|
|
2869
3119
|
customInstructions,
|
|
2870
3120
|
replaceInstructions,
|
|
2871
3121
|
reserveTokens: branchSummarySettings.reserveTokens,
|
|
2872
|
-
streamFn: this.
|
|
3122
|
+
streamFn: this._getAuxiliaryStreamFunction(),
|
|
2873
3123
|
retry: this.settingsManager.getRetrySettings(),
|
|
2874
3124
|
callbacks: this._summarizationRetryCallbacks({ source: "branchSummary" }),
|
|
2875
3125
|
});
|
|
@@ -2954,6 +3204,7 @@ export class AgentSession {
|
|
|
2954
3204
|
return { editorText, cancelled: false, summaryEntry };
|
|
2955
3205
|
}
|
|
2956
3206
|
finally {
|
|
3207
|
+
this._releasePiServerOperationLease(piServerLease.path, piServerLease.acquired, piServerLease.owner);
|
|
2957
3208
|
this._branchSummaryAbortController = undefined;
|
|
2958
3209
|
}
|
|
2959
3210
|
}
|