@caupulican/pi-adaptative 0.81.16 → 0.81.17
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/bundled-resources/skills/tool-call-repair/references/repair-catalogue.md +18 -0
- package/dist/core/agent-session.d.ts +6 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +109 -9
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/models/adaptation-store.d.ts +3 -0
- package/dist/core/models/adaptation-store.d.ts.map +1 -1
- package/dist/core/models/adaptation-store.js +12 -0
- package/dist/core/models/adaptation-store.js.map +1 -1
- package/dist/core/models/context-sizing.d.ts +30 -0
- package/dist/core/models/context-sizing.d.ts.map +1 -0
- package/dist/core/models/context-sizing.js +90 -0
- package/dist/core/models/context-sizing.js.map +1 -0
- package/dist/core/models/local-runtime.d.ts +19 -0
- package/dist/core/models/local-runtime.d.ts.map +1 -1
- package/dist/core/models/local-runtime.js +43 -0
- package/dist/core/models/local-runtime.js.map +1 -1
- package/dist/core/models/perf-profile.d.ts +36 -0
- package/dist/core/models/perf-profile.d.ts.map +1 -0
- package/dist/core/models/perf-profile.js +163 -0
- package/dist/core/models/perf-profile.js.map +1 -0
- package/dist/core/models/runtime-arbiter.d.ts +57 -0
- package/dist/core/models/runtime-arbiter.d.ts.map +1 -0
- package/dist/core/models/runtime-arbiter.js +49 -0
- package/dist/core/models/runtime-arbiter.js.map +1 -0
- package/dist/modes/interactive/local-model-commands.d.ts.map +1 -1
- package/dist/modes/interactive/local-model-commands.js +30 -3
- package/dist/modes/interactive/local-model-commands.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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { basename, dirname, join } from "node:path";
|
|
4
|
-
import { classifyFailure, compactToolResultDetailsForRetention, computeRetryDelayMs, createCustomMessage, DEFAULT_RETRY_POLICY, RetryController, sleepAbortable, withStreamIdleWatchdog, } from "@caupulican/pi-agent-core";
|
|
4
|
+
import { classifyFailure, compactToolResultDetailsForRetention, computeRetryDelayMs, createCustomMessage, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE, RetryController, sleepAbortable, withStreamIdleWatchdog, } from "@caupulican/pi-agent-core";
|
|
5
5
|
import { calculateContextTokens, compact, createDeterministicCompaction, estimateContextTokens, getLatestCompactionEntry, prepareCompaction, runCompactionLoop, shouldCompact, } from "@caupulican/pi-agent-core/node";
|
|
6
6
|
import { cleanupSessionResources, formatToolRepairStandingRule, generateTextToolProtocolPrimer, isContextOverflow, parseTextToolCalls, streamSimple, } from "@caupulican/pi-ai";
|
|
7
7
|
import { Type } from "typebox";
|
|
@@ -31,6 +31,7 @@ import { deriveModelCapabilityProfile, filterToolNamesForCapability, } from "./m
|
|
|
31
31
|
import { formatModelRouterModel, ModelRouterController } from "./model-router-controller.js";
|
|
32
32
|
import { ModelSelectionController } from "./model-selection-controller.js";
|
|
33
33
|
import { ModelAdaptationStore } from "./models/adaptation-store.js";
|
|
34
|
+
import { DEFAULT_ADAPTIVE_STREAM_IDLE_CEILING_MS, estimateContextPromptTokens, resolveAdaptiveStreamIdleOptions, withModelPerfProfile, } from "./models/perf-profile.js";
|
|
34
35
|
import { ProfileFilterController } from "./profile-filter-controller.js";
|
|
35
36
|
import { expandPromptTemplate } from "./prompt-templates.js";
|
|
36
37
|
import { ReflectionController } from "./reflection-controller.js";
|
|
@@ -159,6 +160,8 @@ export class AgentSession {
|
|
|
159
160
|
_collectWorkspaceSources;
|
|
160
161
|
_localRuntimeController;
|
|
161
162
|
_modelAdaptationStore;
|
|
163
|
+
_prefixWarmer;
|
|
164
|
+
_completedPrefixWarms = new Set();
|
|
162
165
|
_repairModeSessionCounts = new Map();
|
|
163
166
|
_textProtocolParseFailures = new Map();
|
|
164
167
|
_textProtocolParseObservedThisTurn = false;
|
|
@@ -240,14 +243,35 @@ export class AgentSession {
|
|
|
240
243
|
// withStreamIdleWatchdog's contract), so no extra drain is added at this wiring site.
|
|
241
244
|
// Wrapping also breaks the `streamFn === streamSimple` identity the auth-injection checks
|
|
242
245
|
// use, so the wrapper carries a rawness marker that _isRawStreamSimple reads.
|
|
246
|
+
const agentDir = config.agentDir ?? getAgentDir();
|
|
247
|
+
const modelAdaptationStore = ModelAdaptationStore.forAgentDir(agentDir);
|
|
243
248
|
const baseStreamFn = this.agent.streamFn;
|
|
249
|
+
const profiledStreamFn = withModelPerfProfile(baseStreamFn, {
|
|
250
|
+
modelKey: (model) => formatModelRouterModel(model),
|
|
251
|
+
recordSample: (modelKey, sample) => {
|
|
252
|
+
modelAdaptationStore.recordPerfSample(modelKey, sample);
|
|
253
|
+
},
|
|
254
|
+
});
|
|
244
255
|
// `this.settingsManager` is assigned below; the resolver closes over the config reference
|
|
245
256
|
// because the wrapper must be installed before that assignment runs.
|
|
246
257
|
const stallSettingsSource = config.settingsManager;
|
|
247
|
-
this.agent.streamFn = tagRawness(withStreamIdleWatchdog(
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
258
|
+
this.agent.streamFn = tagRawness(withStreamIdleWatchdog(profiledStreamFn, (model, context) => {
|
|
259
|
+
const configured = {
|
|
260
|
+
...stallSettingsSource.getStreamStallSettings(),
|
|
261
|
+
...streamIdleOptionsOverride,
|
|
262
|
+
};
|
|
263
|
+
const httpIdleTimeoutMs = stallSettingsSource.getHttpIdleTimeoutMs();
|
|
264
|
+
const profile = modelAdaptationStore.get(formatModelRouterModel(model)).perf;
|
|
265
|
+
const adaptive = resolveAdaptiveStreamIdleOptions({
|
|
266
|
+
base: { ...DEFAULT_STREAM_IDLE, ...configured },
|
|
267
|
+
profile,
|
|
268
|
+
promptTokens: estimateContextPromptTokens(context),
|
|
269
|
+
ceilingMs: httpIdleTimeoutMs === 0
|
|
270
|
+
? DEFAULT_ADAPTIVE_STREAM_IDLE_CEILING_MS
|
|
271
|
+
: Math.max(DEFAULT_STREAM_IDLE.quietIdleMs, httpIdleTimeoutMs - 60_000),
|
|
272
|
+
});
|
|
273
|
+
return { ...configured, ...adaptive };
|
|
274
|
+
}), baseStreamFn === streamSimple);
|
|
251
275
|
this.sessionManager = config.sessionManager;
|
|
252
276
|
this.settingsManager = config.settingsManager;
|
|
253
277
|
// Auto-retry rides the reliability kernel: the controller owns the attempt counter and the
|
|
@@ -271,8 +295,8 @@ export class AgentSession {
|
|
|
271
295
|
this._resourceLoader = config.resourceLoader;
|
|
272
296
|
this._customTools = config.customTools ?? [];
|
|
273
297
|
this._cwd = config.cwd;
|
|
274
|
-
this._agentDir =
|
|
275
|
-
this._modelAdaptationStore =
|
|
298
|
+
this._agentDir = agentDir;
|
|
299
|
+
this._modelAdaptationStore = modelAdaptationStore;
|
|
276
300
|
this.agent.onTextToolProtocolParse = (event) => this._handleTextToolProtocolParse(event);
|
|
277
301
|
this._applyToolRepairLayerSettings();
|
|
278
302
|
this._collectWorkspaceSources = config.collectWorkspaceSources ?? collectWorkspaceSources;
|
|
@@ -589,11 +613,82 @@ export class AgentSession {
|
|
|
589
613
|
activeToolNames: this._initialActiveToolNames,
|
|
590
614
|
includeAllExtensionTools: true,
|
|
591
615
|
});
|
|
616
|
+
this._scheduleLocalPrefixWarm(this.agent.state.model, "session-start");
|
|
592
617
|
}
|
|
593
618
|
/** Model registry for API key resolution and model discovery */
|
|
594
619
|
get modelRegistry() {
|
|
595
620
|
return this._modelRegistry;
|
|
596
621
|
}
|
|
622
|
+
_scheduleLocalPrefixWarm(model, _reason) {
|
|
623
|
+
if (!model || !this._isWarmableLocalModel(model))
|
|
624
|
+
return;
|
|
625
|
+
const modelKey = formatModelRouterModel(model);
|
|
626
|
+
if (this._completedPrefixWarms.has(modelKey) || this._prefixWarmer?.modelKey === modelKey)
|
|
627
|
+
return;
|
|
628
|
+
this._cancelPrefixWarm();
|
|
629
|
+
const controller = new AbortController();
|
|
630
|
+
const timer = setTimeout(() => {
|
|
631
|
+
const warmer = this._prefixWarmer;
|
|
632
|
+
if (!warmer || warmer.controller !== controller || controller.signal.aborted)
|
|
633
|
+
return;
|
|
634
|
+
warmer.timer = undefined;
|
|
635
|
+
void this._runLocalPrefixWarm(model, modelKey, controller);
|
|
636
|
+
}, 0);
|
|
637
|
+
timer.unref?.();
|
|
638
|
+
this._prefixWarmer = { modelKey, controller, timer };
|
|
639
|
+
}
|
|
640
|
+
_cancelPrefixWarm() {
|
|
641
|
+
const warmer = this._prefixWarmer;
|
|
642
|
+
if (!warmer)
|
|
643
|
+
return;
|
|
644
|
+
if (warmer.timer)
|
|
645
|
+
clearTimeout(warmer.timer);
|
|
646
|
+
warmer.controller.abort(new Error("prefix warmer preempted"));
|
|
647
|
+
this._prefixWarmer = undefined;
|
|
648
|
+
}
|
|
649
|
+
async _runLocalPrefixWarm(model, modelKey, controller) {
|
|
650
|
+
try {
|
|
651
|
+
const options = {
|
|
652
|
+
maxTokens: 1,
|
|
653
|
+
signal: controller.signal,
|
|
654
|
+
onPayload: this.agent.onPayload,
|
|
655
|
+
onResponse: this.agent.onResponse,
|
|
656
|
+
};
|
|
657
|
+
if (this._isRawStreamSimple(this.agent.streamFn)) {
|
|
658
|
+
const auth = await this._getRequiredRequestAuth(model);
|
|
659
|
+
options.apiKey = auth.apiKey;
|
|
660
|
+
options.headers = auth.headers;
|
|
661
|
+
}
|
|
662
|
+
if (controller.signal.aborted)
|
|
663
|
+
return;
|
|
664
|
+
const stream = await this.agent.streamFn(model, {
|
|
665
|
+
systemPrompt: this._baseSystemPrompt,
|
|
666
|
+
tools: this.agent.state.tools,
|
|
667
|
+
messages: [],
|
|
668
|
+
}, options);
|
|
669
|
+
await stream.result();
|
|
670
|
+
if (!controller.signal.aborted)
|
|
671
|
+
this._completedPrefixWarms.add(modelKey);
|
|
672
|
+
}
|
|
673
|
+
catch {
|
|
674
|
+
// Best-effort cache warm only; a miss must never affect the real turn.
|
|
675
|
+
}
|
|
676
|
+
finally {
|
|
677
|
+
if (this._prefixWarmer?.controller === controller)
|
|
678
|
+
this._prefixWarmer = undefined;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
_isWarmableLocalModel(model) {
|
|
682
|
+
if (model.api !== "openai-completions")
|
|
683
|
+
return false;
|
|
684
|
+
try {
|
|
685
|
+
const hostname = new URL(model.baseUrl).hostname.toLowerCase();
|
|
686
|
+
return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "[::1]";
|
|
687
|
+
}
|
|
688
|
+
catch {
|
|
689
|
+
return false;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
597
692
|
/**
|
|
598
693
|
* True when the session's stream fn is the raw `streamSimple` provider entry (directly, or as the
|
|
599
694
|
* base wrapped by the idle watchdog at construction). Callers use this to decide whether request
|
|
@@ -1760,6 +1855,7 @@ export class AgentSession {
|
|
|
1760
1855
|
this.abortCompaction();
|
|
1761
1856
|
this.abortBranchSummary();
|
|
1762
1857
|
this.abortBash();
|
|
1858
|
+
this._cancelPrefixWarm();
|
|
1763
1859
|
this.agent.abort();
|
|
1764
1860
|
// R8: stop any deployment-registered gateway channels / schedulers.
|
|
1765
1861
|
void this._gatewayRegistry.stop().catch(() => { });
|
|
@@ -2086,6 +2182,7 @@ export class AgentSession {
|
|
|
2086
2182
|
}
|
|
2087
2183
|
async _promptUnserialized(text, options) {
|
|
2088
2184
|
this._applyToolRepairLayerSettings();
|
|
2185
|
+
this._cancelPrefixWarm();
|
|
2089
2186
|
const expandPromptTemplates = options?.expandPromptTemplates ?? true;
|
|
2090
2187
|
const processSlashCommands = options?.processSlashCommands ?? expandPromptTemplates;
|
|
2091
2188
|
const preflightResult = options?.preflightResult;
|
|
@@ -2597,10 +2694,13 @@ export class AgentSession {
|
|
|
2597
2694
|
// Model Management
|
|
2598
2695
|
// =========================================================================
|
|
2599
2696
|
async setModel(model, options = {}) {
|
|
2600
|
-
|
|
2697
|
+
await this._modelSelection.setModel(model, options);
|
|
2698
|
+
this._scheduleLocalPrefixWarm(this.agent.state.model, "selection");
|
|
2601
2699
|
}
|
|
2602
2700
|
async cycleModel(direction = "forward") {
|
|
2603
|
-
|
|
2701
|
+
const result = await this._modelSelection.cycleModel(direction);
|
|
2702
|
+
this._scheduleLocalPrefixWarm(result?.model, "selection");
|
|
2703
|
+
return result;
|
|
2604
2704
|
}
|
|
2605
2705
|
// =========================================================================
|
|
2606
2706
|
// Thinking Level Management
|