@astralyn/pi 0.82.0 → 0.82.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/LICENSE +21 -0
- package/README.md +14 -3
- package/dist/core/agent-session.d.ts +4 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +193 -43
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +22 -4
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +6 -13
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +4 -3
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts +13 -3
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +36 -6
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts +7 -2
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +25 -12
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/utils/output-decoder.d.ts +52 -0
- package/dist/utils/output-decoder.d.ts.map +1 -0
- package/dist/utils/output-decoder.js +134 -0
- package/dist/utils/output-decoder.js.map +1 -0
- package/dist/utils/shell.d.ts +1 -0
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +21 -0
- package/dist/utils/shell.js.map +1 -1
- package/docs/compaction.md +8 -2
- package/docs/containerization.md +1 -1
- package/docs/development.md +32 -35
- package/docs/distribution/README.md +34 -0
- package/docs/distribution/architecture.md +102 -0
- package/docs/distribution/extensions/README.md +17 -0
- package/docs/distribution/extensions/deepwiki.md +62 -0
- package/docs/distribution/extensions/question.md +59 -0
- package/docs/distribution/extensions/rewind.md +85 -0
- package/docs/distribution/extensions/router.md +139 -0
- package/docs/distribution/extensions/statusline.md +110 -0
- package/docs/distribution/extensions/subagent.md +102 -0
- package/docs/distribution/maintenance.md +121 -0
- package/docs/distribution/release.md +85 -0
- package/docs/distribution/themes.md +58 -0
- package/docs/distribution/tool-presentation.md +91 -0
- package/docs/extensions.md +4 -2
- package/docs/index.md +1 -1
- package/docs/rpc.md +2 -2
- package/docs/themes.md +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +3 -3
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +1 -1
- package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
- package/examples/extensions/doom-overlay/doom/build.sh +0 -0
- package/examples/extensions/sandbox/package-lock.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/npm-shrinkwrap.json +3481 -640
- package/package.json +30 -18
|
@@ -70,6 +70,8 @@ function estimateMessagesTokens(messages) {
|
|
|
70
70
|
// ============================================================================
|
|
71
71
|
// Constants
|
|
72
72
|
// ============================================================================
|
|
73
|
+
const CONTEXT_REMAINS_OVER_COMPACTION_THRESHOLD = "Estimated retained context remains above the configured auto-compaction threshold. Reduce compaction.keepRecentTokens, remove large retained content, or switch to a model with a larger context window before continuing.";
|
|
74
|
+
const AUTO_COMPACTION_STOPPED_BEFORE_NEXT_PROVIDER = "Stopped before the next provider request because auto-compaction did not produce a safe context. Review the compaction warning before continuing.";
|
|
73
75
|
/** Standard thinking levels */
|
|
74
76
|
const THINKING_LEVELS = ["off", "minimal", "low", "medium", "high"];
|
|
75
77
|
// ============================================================================
|
|
@@ -95,6 +97,7 @@ export class AgentSession {
|
|
|
95
97
|
// Compaction state
|
|
96
98
|
_compactionAbortController = undefined;
|
|
97
99
|
_autoCompactionAbortController = undefined;
|
|
100
|
+
_stopAfterTurnRequested = false;
|
|
98
101
|
_overflowRecoveryAttempted = false;
|
|
99
102
|
// Branch summarization state
|
|
100
103
|
_branchSummaryAbortController = undefined;
|
|
@@ -189,8 +192,8 @@ export class AgentSession {
|
|
|
189
192
|
}
|
|
190
193
|
throw new Error(formatNoApiKeyFoundMessage(model.provider));
|
|
191
194
|
}
|
|
192
|
-
async _getSummarizationRequestAuth(model) {
|
|
193
|
-
if (
|
|
195
|
+
async _getSummarizationRequestAuth(model, streamFunction = this.agent.streamFunction) {
|
|
196
|
+
if (streamFunction === streamSimple) {
|
|
194
197
|
return this._getRequiredRequestAuth(model);
|
|
195
198
|
}
|
|
196
199
|
try {
|
|
@@ -264,8 +267,25 @@ export class AgentSession {
|
|
|
264
267
|
? async (_turn, signal) => await this.agent.prepareNextTurn?.(signal)
|
|
265
268
|
: undefined);
|
|
266
269
|
this.agent.prepareNextTurnWithContext = async (turn, signal) => {
|
|
267
|
-
const
|
|
268
|
-
|
|
270
|
+
const compaction = await this._maybeCompactBeforeNextToolTurn(turn, signal);
|
|
271
|
+
if (compaction.stopErrorMessage) {
|
|
272
|
+
// Agent does not expose the low-level graceful turn-stop hook. Throwing here
|
|
273
|
+
// exits before queue polling or another provider request; the run records a
|
|
274
|
+
// normal error/aborted lifecycle instead of risking an oversized context.
|
|
275
|
+
this._stopAfterTurnRequested = true;
|
|
276
|
+
throw new Error(compaction.stopErrorMessage);
|
|
277
|
+
}
|
|
278
|
+
const effectiveTurn = compaction.messages === undefined
|
|
279
|
+
? turn
|
|
280
|
+
: {
|
|
281
|
+
...turn,
|
|
282
|
+
context: {
|
|
283
|
+
...turn.context,
|
|
284
|
+
messages: compaction.messages,
|
|
285
|
+
},
|
|
286
|
+
};
|
|
287
|
+
const previousSnapshot = await previousPrepareNextTurnWithContext?.(effectiveTurn, signal);
|
|
288
|
+
const previousContext = previousSnapshot?.context ?? effectiveTurn.context;
|
|
269
289
|
return {
|
|
270
290
|
...previousSnapshot,
|
|
271
291
|
context: {
|
|
@@ -743,6 +763,7 @@ export class AgentSession {
|
|
|
743
763
|
// =========================================================================
|
|
744
764
|
async _runAgentPrompt(messages) {
|
|
745
765
|
this._isAgentRunActive = true;
|
|
766
|
+
this._stopAfterTurnRequested = false;
|
|
746
767
|
try {
|
|
747
768
|
await this.agent.prompt(messages);
|
|
748
769
|
while (await this._handlePostAgentRun()) {
|
|
@@ -759,6 +780,12 @@ export class AgentSession {
|
|
|
759
780
|
const msg = this._lastAssistantMessage;
|
|
760
781
|
this._lastAssistantMessage = undefined;
|
|
761
782
|
if (!msg) {
|
|
783
|
+
this._stopAfterTurnRequested = false;
|
|
784
|
+
return false;
|
|
785
|
+
}
|
|
786
|
+
const stopAfterTurnRequested = this._stopAfterTurnRequested;
|
|
787
|
+
this._stopAfterTurnRequested = false;
|
|
788
|
+
if (stopAfterTurnRequested) {
|
|
762
789
|
return false;
|
|
763
790
|
}
|
|
764
791
|
if (this._isRetryableError(msg) && (await this._prepareRetry(msg))) {
|
|
@@ -776,6 +803,10 @@ export class AgentSession {
|
|
|
776
803
|
if (await this._checkCompaction(msg)) {
|
|
777
804
|
return true;
|
|
778
805
|
}
|
|
806
|
+
if (this._stopAfterTurnRequested) {
|
|
807
|
+
this._stopAfterTurnRequested = false;
|
|
808
|
+
return false;
|
|
809
|
+
}
|
|
779
810
|
// The agent loop drains both queues before emitting agent_end. Any messages
|
|
780
811
|
// here were queued by agent_end extension handlers and need a continuation.
|
|
781
812
|
return this.agent.hasQueuedMessages();
|
|
@@ -861,6 +892,13 @@ export class AgentSession {
|
|
|
861
892
|
if (lastAssistant) {
|
|
862
893
|
await this._checkCompaction(lastAssistant, false);
|
|
863
894
|
}
|
|
895
|
+
const compactionSettings = this.settingsManager.getCompactionSettings();
|
|
896
|
+
// A compaction entry can be valid while its retained suffix is still too large.
|
|
897
|
+
// Refuse the existing context here rather than discovering that via provider overflow.
|
|
898
|
+
if (compactionSettings.enabled &&
|
|
899
|
+
shouldCompact(this._estimateContextTokensForCompaction(this.agent.state.messages), this.model.contextWindow, compactionSettings)) {
|
|
900
|
+
throw new Error(CONTEXT_REMAINS_OVER_COMPACTION_THRESHOLD);
|
|
901
|
+
}
|
|
864
902
|
// Build messages array (custom message if any, then user message)
|
|
865
903
|
messages = [];
|
|
866
904
|
// Add user message
|
|
@@ -1164,6 +1202,7 @@ export class AgentSession {
|
|
|
1164
1202
|
*/
|
|
1165
1203
|
async abort() {
|
|
1166
1204
|
this.abortRetry();
|
|
1205
|
+
this.abortCompaction();
|
|
1167
1206
|
this.agent.abort();
|
|
1168
1207
|
await this.waitForIdle();
|
|
1169
1208
|
}
|
|
@@ -1494,6 +1533,49 @@ export class AgentSession {
|
|
|
1494
1533
|
abortBranchSummary() {
|
|
1495
1534
|
this._branchSummaryAbortController?.abort();
|
|
1496
1535
|
}
|
|
1536
|
+
_estimateContextTokensForCompaction(messages) {
|
|
1537
|
+
const estimate = estimateContextTokens(messages);
|
|
1538
|
+
const compactionEntry = getLatestCompactionEntry(this.sessionManager.getBranch());
|
|
1539
|
+
if (compactionEntry && estimate.lastUsageIndex !== null) {
|
|
1540
|
+
const usageMessage = messages[estimate.lastUsageIndex];
|
|
1541
|
+
if (usageMessage?.role === "assistant" &&
|
|
1542
|
+
usageMessage.timestamp <= new Date(compactionEntry.timestamp).getTime()) {
|
|
1543
|
+
// A retained pre-compaction usage describes the old, larger context. Fall back
|
|
1544
|
+
// to message estimates rather than immediately compacting again from stale data.
|
|
1545
|
+
return estimateMessagesTokens(messages);
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
return estimate.tokens;
|
|
1549
|
+
}
|
|
1550
|
+
async _maybeCompactBeforeNextToolTurn(turn, signal) {
|
|
1551
|
+
if (signal?.aborted) {
|
|
1552
|
+
return { stopErrorMessage: AUTO_COMPACTION_STOPPED_BEFORE_NEXT_PROVIDER };
|
|
1553
|
+
}
|
|
1554
|
+
if (turn.toolResults.length === 0) {
|
|
1555
|
+
return {};
|
|
1556
|
+
}
|
|
1557
|
+
const settings = this.settingsManager.getCompactionSettings();
|
|
1558
|
+
if (!settings.enabled) {
|
|
1559
|
+
return {};
|
|
1560
|
+
}
|
|
1561
|
+
const contextTokens = this._estimateContextTokensForCompaction(turn.context.messages);
|
|
1562
|
+
const contextWindow = this.model?.contextWindow ?? 0;
|
|
1563
|
+
if (!shouldCompact(contextTokens, contextWindow, settings)) {
|
|
1564
|
+
return {};
|
|
1565
|
+
}
|
|
1566
|
+
const outcome = await this._runAutoCompactionWithOutcome("threshold", false, signal);
|
|
1567
|
+
if (!outcome.compacted) {
|
|
1568
|
+
return { stopErrorMessage: AUTO_COMPACTION_STOPPED_BEFORE_NEXT_PROVIDER };
|
|
1569
|
+
}
|
|
1570
|
+
return {
|
|
1571
|
+
messages: this.agent.state.messages.slice(),
|
|
1572
|
+
...(signal?.aborted === true
|
|
1573
|
+
? { stopErrorMessage: AUTO_COMPACTION_STOPPED_BEFORE_NEXT_PROVIDER }
|
|
1574
|
+
: outcome.mustStop === true
|
|
1575
|
+
? { stopErrorMessage: CONTEXT_REMAINS_OVER_COMPACTION_THRESHOLD }
|
|
1576
|
+
: {}),
|
|
1577
|
+
};
|
|
1578
|
+
}
|
|
1497
1579
|
/**
|
|
1498
1580
|
* Check if compaction is needed and run it.
|
|
1499
1581
|
* Called after agent_end and before prompt submission.
|
|
@@ -1536,6 +1618,7 @@ export class AgentSession {
|
|
|
1536
1618
|
return await this._runAutoCompaction("overflow", false);
|
|
1537
1619
|
}
|
|
1538
1620
|
if (this._overflowRecoveryAttempted) {
|
|
1621
|
+
this._stopAfterTurnRequested = true;
|
|
1539
1622
|
this._emit({
|
|
1540
1623
|
type: "compaction_end",
|
|
1541
1624
|
reason: "overflow",
|
|
@@ -1589,31 +1672,57 @@ export class AgentSession {
|
|
|
1589
1672
|
* Internal: Run auto-compaction with events.
|
|
1590
1673
|
*/
|
|
1591
1674
|
async _runAutoCompaction(reason, willRetry) {
|
|
1675
|
+
const outcome = await this._runAutoCompactionWithOutcome(reason, willRetry);
|
|
1676
|
+
if (!outcome.compacted || outcome.mustStop) {
|
|
1677
|
+
this._stopAfterTurnRequested = true;
|
|
1678
|
+
}
|
|
1679
|
+
return outcome.shouldContinue;
|
|
1680
|
+
}
|
|
1681
|
+
async _runAutoCompactionWithOutcome(reason, willRetry, parentSignal) {
|
|
1592
1682
|
const settings = this.settingsManager.getCompactionSettings();
|
|
1593
1683
|
let started = false;
|
|
1684
|
+
let controller;
|
|
1685
|
+
let removeParentAbortListener;
|
|
1594
1686
|
try {
|
|
1595
|
-
if (!this.model
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1687
|
+
if (!this.model ||
|
|
1688
|
+
this._autoCompactionAbortController ||
|
|
1689
|
+
this._compactionAbortController ||
|
|
1690
|
+
parentSignal?.aborted) {
|
|
1691
|
+
return { compacted: false, shouldContinue: false };
|
|
1692
|
+
}
|
|
1693
|
+
const model = this.model;
|
|
1694
|
+
const streamFunction = this.agent.streamFunction;
|
|
1695
|
+
const thinkingLevel = this.thinkingLevel;
|
|
1696
|
+
const retrySettings = this.settingsManager.getRetrySettings();
|
|
1697
|
+
controller = new AbortController();
|
|
1698
|
+
if (parentSignal) {
|
|
1699
|
+
const abortFromParent = () => controller?.abort();
|
|
1700
|
+
parentSignal.addEventListener("abort", abortFromParent, { once: true });
|
|
1701
|
+
removeParentAbortListener = () => parentSignal.removeEventListener("abort", abortFromParent);
|
|
1702
|
+
}
|
|
1703
|
+
if (controller.signal.aborted) {
|
|
1704
|
+
return { compacted: false, shouldContinue: false };
|
|
1705
|
+
}
|
|
1706
|
+
this._autoCompactionAbortController = controller;
|
|
1707
|
+
started = true;
|
|
1708
|
+
this._emit({ type: "compaction_start", reason });
|
|
1709
|
+
if (controller.signal.aborted) {
|
|
1710
|
+
this._emit({
|
|
1711
|
+
type: "compaction_end",
|
|
1712
|
+
reason,
|
|
1713
|
+
result: undefined,
|
|
1714
|
+
aborted: true,
|
|
1715
|
+
willRetry: false,
|
|
1716
|
+
});
|
|
1717
|
+
return { compacted: false, shouldContinue: false };
|
|
1606
1718
|
}
|
|
1719
|
+
let extensionCompaction;
|
|
1720
|
+
let fromExtension = false;
|
|
1607
1721
|
const pathEntries = this.sessionManager.getBranch();
|
|
1608
1722
|
const preparation = prepareCompaction(pathEntries, settings);
|
|
1609
1723
|
if (!preparation) {
|
|
1610
|
-
|
|
1724
|
+
throw new Error("Nothing to compact while preserving the configured recent context.");
|
|
1611
1725
|
}
|
|
1612
|
-
this._emit({ type: "compaction_start", reason });
|
|
1613
|
-
this._autoCompactionAbortController = new AbortController();
|
|
1614
|
-
started = true;
|
|
1615
|
-
let extensionCompaction;
|
|
1616
|
-
let fromExtension = false;
|
|
1617
1726
|
if (this._extensionRunner.hasHandlers("session_before_compact")) {
|
|
1618
1727
|
const extensionResult = (await this._extensionRunner.emit({
|
|
1619
1728
|
type: "session_before_compact",
|
|
@@ -1622,7 +1731,7 @@ export class AgentSession {
|
|
|
1622
1731
|
customInstructions: undefined,
|
|
1623
1732
|
reason,
|
|
1624
1733
|
willRetry,
|
|
1625
|
-
signal:
|
|
1734
|
+
signal: controller.signal,
|
|
1626
1735
|
}));
|
|
1627
1736
|
if (extensionResult?.cancel) {
|
|
1628
1737
|
this._emit({
|
|
@@ -1632,7 +1741,7 @@ export class AgentSession {
|
|
|
1632
1741
|
aborted: true,
|
|
1633
1742
|
willRetry: false,
|
|
1634
1743
|
});
|
|
1635
|
-
return false;
|
|
1744
|
+
return { compacted: false, shouldContinue: false };
|
|
1636
1745
|
}
|
|
1637
1746
|
if (extensionResult?.compaction) {
|
|
1638
1747
|
extensionCompaction = extensionResult.compaction;
|
|
@@ -1653,15 +1762,34 @@ export class AgentSession {
|
|
|
1653
1762
|
details = extensionCompaction.details;
|
|
1654
1763
|
}
|
|
1655
1764
|
else {
|
|
1765
|
+
let apiKey;
|
|
1766
|
+
let headers;
|
|
1767
|
+
let env;
|
|
1768
|
+
if (streamFunction === streamSimple) {
|
|
1769
|
+
({ apiKey, headers, env } = await this._getRequiredRequestAuth(model));
|
|
1770
|
+
}
|
|
1771
|
+
else {
|
|
1772
|
+
({ apiKey, headers, env } = await this._getSummarizationRequestAuth(model, streamFunction));
|
|
1773
|
+
}
|
|
1774
|
+
if (controller.signal.aborted) {
|
|
1775
|
+
this._emit({
|
|
1776
|
+
type: "compaction_end",
|
|
1777
|
+
reason,
|
|
1778
|
+
result: undefined,
|
|
1779
|
+
aborted: true,
|
|
1780
|
+
willRetry: false,
|
|
1781
|
+
});
|
|
1782
|
+
return { compacted: false, shouldContinue: false };
|
|
1783
|
+
}
|
|
1656
1784
|
// Generate compaction result
|
|
1657
|
-
const compactResult = await compact(preparation,
|
|
1785
|
+
const compactResult = await compact(preparation, model, apiKey, headers, undefined, controller.signal, thinkingLevel, streamFunction, env, retrySettings, this._summarizationRetryCallbacks({ source: "compaction", reason }));
|
|
1658
1786
|
summary = compactResult.summary;
|
|
1659
1787
|
firstKeptEntryId = compactResult.firstKeptEntryId;
|
|
1660
1788
|
tokensBefore = compactResult.tokensBefore;
|
|
1661
1789
|
usage = compactResult.usage;
|
|
1662
1790
|
details = compactResult.details;
|
|
1663
1791
|
}
|
|
1664
|
-
if (
|
|
1792
|
+
if (controller.signal.aborted) {
|
|
1665
1793
|
this._emit({
|
|
1666
1794
|
type: "compaction_end",
|
|
1667
1795
|
reason,
|
|
@@ -1669,13 +1797,22 @@ export class AgentSession {
|
|
|
1669
1797
|
aborted: true,
|
|
1670
1798
|
willRetry: false,
|
|
1671
1799
|
});
|
|
1672
|
-
return false;
|
|
1800
|
+
return { compacted: false, shouldContinue: false };
|
|
1673
1801
|
}
|
|
1674
1802
|
this.sessionManager.appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromExtension, usage);
|
|
1675
1803
|
const newEntries = this.sessionManager.getEntries();
|
|
1676
1804
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
1677
1805
|
this.agent.state.messages = sessionContext.messages;
|
|
1678
|
-
|
|
1806
|
+
if (willRetry) {
|
|
1807
|
+
const messages = this.agent.state.messages;
|
|
1808
|
+
const lastMsg = messages[messages.length - 1];
|
|
1809
|
+
if (lastMsg?.role === "assistant" && lastMsg.stopReason === "error") {
|
|
1810
|
+
this.agent.state.messages = messages.slice(0, -1);
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
const estimatedTokensAfter = this._estimateContextTokensForCompaction(this.agent.state.messages);
|
|
1814
|
+
const contextStillOverThreshold = shouldCompact(estimatedTokensAfter, model.contextWindow, settings);
|
|
1815
|
+
const effectiveWillRetry = willRetry && !contextStillOverThreshold;
|
|
1679
1816
|
// Get the saved compaction entry for the extension event
|
|
1680
1817
|
const savedCompactionEntry = newEntries.find((e) => e.type === "compaction" && e.summary === summary);
|
|
1681
1818
|
if (this._extensionRunner && savedCompactionEntry) {
|
|
@@ -1684,7 +1821,7 @@ export class AgentSession {
|
|
|
1684
1821
|
compactionEntry: savedCompactionEntry,
|
|
1685
1822
|
fromExtension,
|
|
1686
1823
|
reason,
|
|
1687
|
-
willRetry,
|
|
1824
|
+
willRetry: effectiveWillRetry,
|
|
1688
1825
|
});
|
|
1689
1826
|
}
|
|
1690
1827
|
const result = {
|
|
@@ -1695,37 +1832,50 @@ export class AgentSession {
|
|
|
1695
1832
|
usage,
|
|
1696
1833
|
details,
|
|
1697
1834
|
};
|
|
1698
|
-
this._emit({
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
}
|
|
1705
|
-
|
|
1835
|
+
this._emit({
|
|
1836
|
+
type: "compaction_end",
|
|
1837
|
+
reason,
|
|
1838
|
+
result,
|
|
1839
|
+
aborted: false,
|
|
1840
|
+
willRetry: effectiveWillRetry,
|
|
1841
|
+
...(contextStillOverThreshold ? { errorMessage: CONTEXT_REMAINS_OVER_COMPACTION_THRESHOLD } : {}),
|
|
1842
|
+
});
|
|
1843
|
+
if (contextStillOverThreshold) {
|
|
1844
|
+
return { compacted: true, shouldContinue: false, mustStop: true };
|
|
1845
|
+
}
|
|
1846
|
+
if (effectiveWillRetry) {
|
|
1847
|
+
return { compacted: true, shouldContinue: true };
|
|
1706
1848
|
}
|
|
1707
1849
|
// Auto-compaction can complete while follow-up/steering/custom messages are waiting.
|
|
1708
1850
|
// Continue once so queued messages are delivered.
|
|
1709
|
-
return this.agent.hasQueuedMessages();
|
|
1851
|
+
return { compacted: true, shouldContinue: this.agent.hasQueuedMessages() };
|
|
1710
1852
|
}
|
|
1711
1853
|
catch (error) {
|
|
1854
|
+
const aborted = controller?.signal.aborted || (error instanceof Error && error.name === "AbortError");
|
|
1712
1855
|
const errorMessage = error instanceof Error ? error.message : "compaction failed";
|
|
1713
1856
|
if (started) {
|
|
1714
1857
|
this._emit({
|
|
1715
1858
|
type: "compaction_end",
|
|
1716
1859
|
reason,
|
|
1717
1860
|
result: undefined,
|
|
1718
|
-
aborted
|
|
1861
|
+
aborted,
|
|
1719
1862
|
willRetry: false,
|
|
1720
|
-
|
|
1721
|
-
?
|
|
1722
|
-
:
|
|
1863
|
+
...(aborted
|
|
1864
|
+
? {}
|
|
1865
|
+
: {
|
|
1866
|
+
errorMessage: reason === "overflow"
|
|
1867
|
+
? `Context overflow recovery failed: ${errorMessage}`
|
|
1868
|
+
: `Auto-compaction failed: ${errorMessage}`,
|
|
1869
|
+
}),
|
|
1723
1870
|
});
|
|
1724
1871
|
}
|
|
1725
|
-
return false;
|
|
1872
|
+
return { compacted: false, shouldContinue: false };
|
|
1726
1873
|
}
|
|
1727
1874
|
finally {
|
|
1728
|
-
|
|
1875
|
+
removeParentAbortListener?.();
|
|
1876
|
+
if (this._autoCompactionAbortController === controller) {
|
|
1877
|
+
this._autoCompactionAbortController = undefined;
|
|
1878
|
+
}
|
|
1729
1879
|
}
|
|
1730
1880
|
}
|
|
1731
1881
|
/**
|