@caupulican/pi-adaptative 0.80.84 → 0.80.86
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 +29 -0
- package/dist/core/agent-session.d.ts +20 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +113 -6
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/cost-guard.d.ts +1 -1
- package/dist/core/cost-guard.d.ts.map +1 -1
- package/dist/core/cost-guard.js +2 -2
- package/dist/core/cost-guard.js.map +1 -1
- package/dist/core/profile-registry.d.ts +2 -1
- package/dist/core/profile-registry.d.ts.map +1 -1
- package/dist/core/profile-registry.js +32 -2
- package/dist/core/profile-registry.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +3 -1
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/settings-manager.d.ts +2 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +33 -3
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/modes/interactive/components/profile-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/profile-selector.js +2 -0
- package/dist/modes/interactive/components/profile-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +3 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +3 -0
- package/dist/modes/print-mode.js.map +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
|
@@ -153,6 +153,7 @@ export class AgentSession {
|
|
|
153
153
|
_activeModelRouterIntent;
|
|
154
154
|
_modelRouterSessionBuffer;
|
|
155
155
|
_modelRouterEscalationRequested = false;
|
|
156
|
+
_isModelRouterRetry = false;
|
|
156
157
|
_lastModelRouterDecision;
|
|
157
158
|
_lastModelRouterSkipReason;
|
|
158
159
|
_lastModelRouterIntent;
|
|
@@ -295,7 +296,7 @@ export class AgentSession {
|
|
|
295
296
|
const authoritativeMessages = this.agent.state.messages.length > 0 ? this.agent.state.messages : transformed;
|
|
296
297
|
let currentMessages = authoritativeMessages;
|
|
297
298
|
try {
|
|
298
|
-
const settings = this.
|
|
299
|
+
const settings = this._getAdaptedCompactionSettings();
|
|
299
300
|
const contextWindow = this.model?.contextWindow ?? 0;
|
|
300
301
|
if (settings.enabled && contextWindow > 0 && !this.isCompacting) {
|
|
301
302
|
const contextTokens = this._estimateCurrentContextTokens(authoritativeMessages);
|
|
@@ -584,8 +585,13 @@ export class AgentSession {
|
|
|
584
585
|
}
|
|
585
586
|
// Emit to extensions first
|
|
586
587
|
await this._emitExtensionEvent(event);
|
|
588
|
+
const suppressRetryPromptEvent = this._isModelRouterRetry &&
|
|
589
|
+
(event.type === "message_start" || event.type === "message_end") &&
|
|
590
|
+
(event.message.role === "user" || event.message.role === "custom");
|
|
587
591
|
// Notify all listeners
|
|
588
|
-
|
|
592
|
+
if (!suppressRetryPromptEvent) {
|
|
593
|
+
this._emit(event.type === "agent_end" ? { ...event, willRetry: this._willRetryAfterAgentEnd(event) } : event);
|
|
594
|
+
}
|
|
589
595
|
// Handle session/context retention. Tool result details are UI/log metadata,
|
|
590
596
|
// not provider-visible content, and large graph/search payloads can otherwise
|
|
591
597
|
// accumulate until the interactive Node process hits the V8 heap limit.
|
|
@@ -926,6 +932,7 @@ export class AgentSession {
|
|
|
926
932
|
// Rebuild base system prompt with new tool set
|
|
927
933
|
this._baseSystemPrompt = this._rebuildSystemPrompt(validToolNames);
|
|
928
934
|
this.agent.state.systemPrompt = this._baseSystemPrompt;
|
|
935
|
+
this._checkContextWindowUsageWarning();
|
|
929
936
|
}
|
|
930
937
|
/** Whether compaction or branch summarization is currently running */
|
|
931
938
|
get isCompacting() {
|
|
@@ -1243,8 +1250,11 @@ export class AgentSession {
|
|
|
1243
1250
|
this._modelRouterEscalationRequested = previousModelRouterEscalationRequested;
|
|
1244
1251
|
}
|
|
1245
1252
|
if (retryModel && !thrownError) {
|
|
1253
|
+
const previousIsModelRouterRetry = this._isModelRouterRetry;
|
|
1246
1254
|
try {
|
|
1255
|
+
this._isModelRouterRetry = true;
|
|
1247
1256
|
await this._runAgentPromptWithModelRouter(messages, retryModel, "modify", false);
|
|
1257
|
+
this._lastModelRouterDecision = completedDecision;
|
|
1248
1258
|
}
|
|
1249
1259
|
catch (error) {
|
|
1250
1260
|
thrownError = error;
|
|
@@ -1253,6 +1263,9 @@ export class AgentSession {
|
|
|
1253
1263
|
this._lastModelRouterDecision = completedDecision;
|
|
1254
1264
|
}
|
|
1255
1265
|
}
|
|
1266
|
+
finally {
|
|
1267
|
+
this._isModelRouterRetry = previousIsModelRouterRetry;
|
|
1268
|
+
}
|
|
1256
1269
|
}
|
|
1257
1270
|
if (persistDecision && completedDecision) {
|
|
1258
1271
|
persistModelRouterDecision(this.sessionManager, completedDecision);
|
|
@@ -1404,6 +1417,7 @@ export class AgentSession {
|
|
|
1404
1417
|
}
|
|
1405
1418
|
throw new Error(formatNoApiKeyFoundMessage(requestModel.provider));
|
|
1406
1419
|
}
|
|
1420
|
+
this._checkContextWindowUsageWarning();
|
|
1407
1421
|
// Check if we need to compact before sending (catches aborted responses).
|
|
1408
1422
|
// Do not call agent.continue() here: the next model turn must include the
|
|
1409
1423
|
// user's pending prompt, not an empty continuation after compaction.
|
|
@@ -1814,6 +1828,7 @@ export class AgentSession {
|
|
|
1814
1828
|
// Re-clamp thinking level for new model's capabilities
|
|
1815
1829
|
this.setThinkingLevel(thinkingLevel, { persistSettings });
|
|
1816
1830
|
await this._emitModelSelect(model, previousModel, "set");
|
|
1831
|
+
this._checkContextWindowUsageWarning();
|
|
1817
1832
|
}
|
|
1818
1833
|
/**
|
|
1819
1834
|
* Cycle to next/previous model.
|
|
@@ -1849,6 +1864,7 @@ export class AgentSession {
|
|
|
1849
1864
|
// setThinkingLevel clamps to model capabilities.
|
|
1850
1865
|
this.setThinkingLevel(thinkingLevel);
|
|
1851
1866
|
await this._emitModelSelect(next.model, currentModel, "cycle");
|
|
1867
|
+
this._checkContextWindowUsageWarning();
|
|
1852
1868
|
return { model: next.model, thinkingLevel: this.thinkingLevel, isScoped: true };
|
|
1853
1869
|
}
|
|
1854
1870
|
async _cycleAvailableModel(direction) {
|
|
@@ -1869,6 +1885,7 @@ export class AgentSession {
|
|
|
1869
1885
|
// Re-clamp thinking level for new model's capabilities
|
|
1870
1886
|
this.setThinkingLevel(thinkingLevel);
|
|
1871
1887
|
await this._emitModelSelect(nextModel, currentModel, "cycle");
|
|
1888
|
+
this._checkContextWindowUsageWarning();
|
|
1872
1889
|
return { model: nextModel, thinkingLevel: this.thinkingLevel, isScoped: false };
|
|
1873
1890
|
}
|
|
1874
1891
|
// =========================================================================
|
|
@@ -1980,7 +1997,7 @@ export class AgentSession {
|
|
|
1980
1997
|
const compactionModel = this._resolveCompactionModel(this.model);
|
|
1981
1998
|
const { apiKey, headers } = await this._getCompactionRequestAuth(compactionModel);
|
|
1982
1999
|
const pathEntries = this.sessionManager.getBranch();
|
|
1983
|
-
const settings = this.
|
|
2000
|
+
const settings = this._getAdaptedCompactionSettings();
|
|
1984
2001
|
const preparation = prepareCompaction(pathEntries, settings);
|
|
1985
2002
|
if (!preparation) {
|
|
1986
2003
|
// Check why we can't compact
|
|
@@ -2100,8 +2117,57 @@ export class AgentSession {
|
|
|
2100
2117
|
* @param assistantMessage The assistant message to check
|
|
2101
2118
|
* @param skipAbortedCheck If false, include aborted messages (for pre-prompt check). Default: true
|
|
2102
2119
|
*/
|
|
2103
|
-
|
|
2120
|
+
_getAdaptedCompactionSettings() {
|
|
2104
2121
|
const settings = this.settingsManager.getCompactionSettings();
|
|
2122
|
+
if (!this.model)
|
|
2123
|
+
return settings;
|
|
2124
|
+
const contextWindow = this.model.contextWindow ?? 0;
|
|
2125
|
+
if (contextWindow <= 0)
|
|
2126
|
+
return settings;
|
|
2127
|
+
// Adapt reserveTokens: at most 25% of context window
|
|
2128
|
+
const maxReserve = Math.floor(contextWindow * 0.25);
|
|
2129
|
+
const reserveTokens = Math.min(settings.reserveTokens, maxReserve);
|
|
2130
|
+
// Adapt keepRecentTokens: at most 50% of context window
|
|
2131
|
+
const maxKeepRecent = Math.floor(contextWindow * 0.5);
|
|
2132
|
+
const keepRecentTokens = Math.min(settings.keepRecentTokens, maxKeepRecent);
|
|
2133
|
+
return {
|
|
2134
|
+
...settings,
|
|
2135
|
+
reserveTokens,
|
|
2136
|
+
keepRecentTokens,
|
|
2137
|
+
};
|
|
2138
|
+
}
|
|
2139
|
+
_checkContextWindowUsageWarning() {
|
|
2140
|
+
if (!this.model)
|
|
2141
|
+
return;
|
|
2142
|
+
const contextWindow = this.model.contextWindow ?? 0;
|
|
2143
|
+
if (contextWindow <= 0)
|
|
2144
|
+
return;
|
|
2145
|
+
const systemPromptTokens = Math.ceil((this.agent.state.systemPrompt ?? "").length / 4);
|
|
2146
|
+
let toolsChars = 0;
|
|
2147
|
+
for (const tool of this.agent.state.tools || []) {
|
|
2148
|
+
toolsChars += tool.name.length;
|
|
2149
|
+
toolsChars += tool.description?.length ?? 0;
|
|
2150
|
+
if (tool.parameters) {
|
|
2151
|
+
toolsChars += JSON.stringify(tool.parameters).length;
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
const toolsTokens = Math.ceil(toolsChars / 4);
|
|
2155
|
+
const baseTokens = systemPromptTokens + toolsTokens;
|
|
2156
|
+
if (baseTokens >= contextWindow) {
|
|
2157
|
+
this._emit({
|
|
2158
|
+
type: "warning",
|
|
2159
|
+
message: `Base configuration (system prompt and active tools) consumes ${baseTokens} tokens, which exceeds the model's context window of ${contextWindow} tokens. The model cannot process any prompts in this state.`,
|
|
2160
|
+
});
|
|
2161
|
+
}
|
|
2162
|
+
else if (baseTokens >= contextWindow * 0.7) {
|
|
2163
|
+
this._emit({
|
|
2164
|
+
type: "warning",
|
|
2165
|
+
message: `Base configuration (system prompt and active tools) consumes ${baseTokens} tokens (${Math.round((baseTokens / contextWindow) * 100)}% of the ${contextWindow} context window). This leaves very little room for conversation history and may cause immediate compaction or context overflow.`,
|
|
2166
|
+
});
|
|
2167
|
+
}
|
|
2168
|
+
}
|
|
2169
|
+
async _checkCompaction(assistantMessage, skipAbortedCheck = true) {
|
|
2170
|
+
const settings = this._getAdaptedCompactionSettings();
|
|
2105
2171
|
if (!settings.enabled)
|
|
2106
2172
|
return false;
|
|
2107
2173
|
// Skip if message was aborted (user cancelled) - unless skipAbortedCheck is false
|
|
@@ -2185,7 +2251,7 @@ export class AgentSession {
|
|
|
2185
2251
|
* Internal: Run auto-compaction with events.
|
|
2186
2252
|
*/
|
|
2187
2253
|
async _runAutoCompaction(reason, willRetry) {
|
|
2188
|
-
const settings = this.
|
|
2254
|
+
const settings = this._getAdaptedCompactionSettings();
|
|
2189
2255
|
this._emit({ type: "compaction_start", reason });
|
|
2190
2256
|
this._autoCompactionAbortController = new AbortController();
|
|
2191
2257
|
try {
|
|
@@ -2565,6 +2631,43 @@ export class AgentSession {
|
|
|
2565
2631
|
const filter = this.settingsManager.getResourceProfileFilter("tools");
|
|
2566
2632
|
return { allow: filter.allow ?? [], block: filter.block ?? [] };
|
|
2567
2633
|
}
|
|
2634
|
+
_isToolOrCommandAllowedByProfile(name) {
|
|
2635
|
+
if (this._allowedToolNames && !this._allowedToolNames.has(name))
|
|
2636
|
+
return false;
|
|
2637
|
+
if (this._excludedToolNames?.has(name))
|
|
2638
|
+
return false;
|
|
2639
|
+
const filter = this._toolProfileFilter;
|
|
2640
|
+
if (!filter)
|
|
2641
|
+
return true;
|
|
2642
|
+
if (filter.allow.length > 0 && !matchesResourceProfilePattern(name, filter.allow))
|
|
2643
|
+
return false;
|
|
2644
|
+
if (matchesResourceProfilePattern(name, filter.block))
|
|
2645
|
+
return false;
|
|
2646
|
+
return true;
|
|
2647
|
+
}
|
|
2648
|
+
_hasToolOrCommandProfileGate() {
|
|
2649
|
+
return Boolean(this._allowedToolNames ||
|
|
2650
|
+
this._excludedToolNames ||
|
|
2651
|
+
(this._toolProfileFilter &&
|
|
2652
|
+
(this._toolProfileFilter.allow.length > 0 || this._toolProfileFilter.block.length > 0)));
|
|
2653
|
+
}
|
|
2654
|
+
_filterExtensionsForRuntime(extensions) {
|
|
2655
|
+
if (this.settingsManager.getActiveResourceProfileNames().length === 0) {
|
|
2656
|
+
return this.settingsManager.hasExplicitActiveResourceProfileSelection()
|
|
2657
|
+
? []
|
|
2658
|
+
: extensions.filter((extension) => extension.sourceInfo.source === "inline");
|
|
2659
|
+
}
|
|
2660
|
+
const hasToolOrCommandGate = this._hasToolOrCommandProfileGate();
|
|
2661
|
+
return extensions
|
|
2662
|
+
.filter((extension) => this.settingsManager.isResourceAllowedByProfile("extensions", extension.path, extension.sourceInfo.baseDir))
|
|
2663
|
+
.map((extension) => {
|
|
2664
|
+
if (!hasToolOrCommandGate)
|
|
2665
|
+
return extension;
|
|
2666
|
+
const tools = new Map(Array.from(extension.tools.entries()).filter(([name]) => this._isToolOrCommandAllowedByProfile(name)));
|
|
2667
|
+
const commands = new Map(Array.from(extension.commands.entries()).filter(([name]) => this._isToolOrCommandAllowedByProfile(name)));
|
|
2668
|
+
return { ...extension, tools, commands };
|
|
2669
|
+
});
|
|
2670
|
+
}
|
|
2568
2671
|
/**
|
|
2569
2672
|
* Re-resolve the active resource profile's model/thinking from current settings and apply it.
|
|
2570
2673
|
* Only acts when the profile actually binds model/thinking AND that field was not set by an
|
|
@@ -2826,7 +2929,11 @@ export class AgentSession {
|
|
|
2826
2929
|
extensionsResult.runtime.flagValues.set(name, value);
|
|
2827
2930
|
}
|
|
2828
2931
|
}
|
|
2829
|
-
|
|
2932
|
+
const extensions = this._filterExtensionsForRuntime(extensionsResult.extensions);
|
|
2933
|
+
const runtimeExtensionPaths = new Set(extensions.map((extension) => extension.path));
|
|
2934
|
+
extensionsResult.runtime.pendingProviderRegistrations =
|
|
2935
|
+
extensionsResult.runtime.pendingProviderRegistrations.filter((registration) => runtimeExtensionPaths.has(registration.extensionPath));
|
|
2936
|
+
this._extensionRunner = new ExtensionRunner(extensions, extensionsResult.runtime, this._cwd, this.sessionManager, this._modelRegistry);
|
|
2830
2937
|
if (this._extensionRunnerRef) {
|
|
2831
2938
|
this._extensionRunnerRef.current = this._extensionRunner;
|
|
2832
2939
|
}
|