@demicodes/agent 0.15.0 → 0.17.0
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/dist/client-entry.d.mts +2 -2
- package/dist/client-entry.mjs +1 -1
- package/dist/index.d.mts +29 -19
- package/dist/index.mjs +80 -32
- package/dist/stdio-transport.d.mts +1 -1
- package/dist/{transport-gkyOzXn-.d.mts → transport-DtBCCS_A.d.mts} +16 -1
- package/dist/{websocket-transport-C6bu3Ufc.d.mts → websocket-transport-DdfGgBjO.d.mts} +9 -4
- package/dist/{websocket-transport-BjSj3U0I.mjs → websocket-transport-c6P3NBuf.mjs} +8 -4
- package/package.json +5 -5
package/dist/client-entry.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { b as AgentMetadata, d as TranscriptPatch, l as ServerFrame, n as AgentServerTransport, o as ClientFrame, r as AgentTransport, s as ClientSessionEvent, t as AgentClientTransport, u as ShellCommandStatusLike } from "./transport-
|
|
2
|
-
import { a as AgentClient, i as AgentActionOptions, n as createWebSocketClientTransport, o as AgentClientListener, r as createWebSocketServerTransport, t as JsonWebSocket } from "./websocket-transport-
|
|
1
|
+
import { b as AgentMetadata, d as TranscriptPatch, l as ServerFrame, n as AgentServerTransport, o as ClientFrame, r as AgentTransport, s as ClientSessionEvent, t as AgentClientTransport, u as ShellCommandStatusLike } from "./transport-DtBCCS_A.mjs";
|
|
2
|
+
import { a as AgentClient, i as AgentActionOptions, n as createWebSocketClientTransport, o as AgentClientListener, r as createWebSocketServerTransport, t as JsonWebSocket } from "./websocket-transport-DdfGgBjO.mjs";
|
|
3
3
|
import { ProviderSelection } from "@demicodes/provider";
|
|
4
4
|
export { type AgentActionOptions, AgentClient, type AgentClientListener, type AgentClientTransport, type AgentMetadata, type AgentServerTransport, type AgentTransport, type ClientFrame, type ClientSessionEvent, type JsonWebSocket, type ProviderSelection, type ServerFrame, type ShellCommandStatusLike, type TranscriptPatch, createWebSocketClientTransport, createWebSocketServerTransport };
|
package/dist/client-entry.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as createWebSocketServerTransport, r as AgentClient, t as createWebSocketClientTransport } from "./websocket-transport-
|
|
1
|
+
import { n as createWebSocketServerTransport, r as AgentClient, t as createWebSocketClientTransport } from "./websocket-transport-c6P3NBuf.mjs";
|
|
2
2
|
export { AgentClient, createWebSocketClientTransport, createWebSocketServerTransport };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as AgentTool, B as
|
|
2
|
-
import { a as AgentClient, i as AgentActionOptions, n as createWebSocketClientTransport, o as AgentClientListener, r as createWebSocketServerTransport, t as JsonWebSocket } from "./websocket-transport-
|
|
1
|
+
import { A as AgentTool, B as TranscriptLog, C as AgentSessionCheckpoint, D as AgentSessionRestoreParams, E as AgentSessionParams, F as ModelSwitchApply, G as isRetryableCode, H as estimateTranscriptBlockTokens, I as SessionEvent, K as resolveRetryPolicy, L as SessionEventListener, M as AgentToolInvokeContext, N as AgentToolInvokeResult, O as AgentSessionStore, P as ExternalMutationReservation, R as CompactionWindow, S as AgentReferenceResolveContext, T as AgentSessionOptions, U as DEFAULT_TURN_RETRY_POLICY, V as TranscriptOptions, W as TurnRetryPolicy, _ as AgentHarnessRuntime, a as createInProcessTransportPair, b as AgentMetadata, c as ConversationSummary, d as TranscriptPatch, f as AbortResult, g as AgentHarnessContext, h as AgentHarness, i as InProcessTransportPair, j as AgentToolContext, k as AgentSystemPromptContext, l as ServerFrame, m as AgentDisposeContext, n as AgentServerTransport, o as ClientFrame, p as AbortTarget, q as retryDelayMs, r as AgentTransport, s as ClientSessionEvent, t as AgentClientTransport, u as ShellCommandStatusLike, v as AgentHostContext, w as AgentSessionCloneParams, x as AgentPromptContext, y as AgentLifecycleEvent, z as DrainedTranscriptPatches } from "./transport-DtBCCS_A.mjs";
|
|
2
|
+
import { a as AgentClient, i as AgentActionOptions, n as createWebSocketClientTransport, o as AgentClientListener, r as createWebSocketServerTransport, t as JsonWebSocket } from "./websocket-transport-DdfGgBjO.mjs";
|
|
3
3
|
import { BashAuditEvent, BashEnvironment, BashEnvironmentOptions, CommandMetadataRecord, Host, ShellCommandStatus, ShellOutputChunk } from "@demicodes/shell";
|
|
4
4
|
import { AgentProvider, Provider } from "@demicodes/provider";
|
|
5
5
|
import { Block, Model, ModelMediaKind, ModelSelection, ProviderErrorDiagnostics, QueuedMessage, SessionPhase, UserContentBlock } from "@demicodes/core";
|
|
@@ -48,6 +48,7 @@ declare class AgentSession<State> {
|
|
|
48
48
|
private readonly store?;
|
|
49
49
|
private readonly compactionKeepRecentTokens;
|
|
50
50
|
private readonly compactionThresholdRatio;
|
|
51
|
+
private readonly compactionThresholdTokens;
|
|
51
52
|
private readonly listeners;
|
|
52
53
|
private readonly pendingActions;
|
|
53
54
|
private readonly queued;
|
|
@@ -122,18 +123,19 @@ declare class AgentSession<State> {
|
|
|
122
123
|
}): Promise<void>;
|
|
123
124
|
cancelPendingSteer(id: string): boolean;
|
|
124
125
|
/**
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
126
|
+
* Records a model/provider switch for the rest of the session. A non-null `provider`
|
|
127
|
+
* replaces the current one (its predecessor is disposed); pass null to keep the same
|
|
128
|
+
* provider instance and only change the model.
|
|
129
|
+
*
|
|
130
|
+
* `apply` picks the boundary the switch lands on: 'next_turn' (default) waits for the
|
|
131
|
+
* start of the next queued action, so a running turn finishes entirely on the old model;
|
|
132
|
+
* 'immediate' also applies mid-turn at the next sampling/tool continuation, so the very
|
|
133
|
+
* next request already runs on the new model (the same "as soon as possible" semantics
|
|
134
|
+
* steering has). Either way, if the new model can't hold the history, compaction runs
|
|
135
|
+
* first with the current (pre-switch) model, then the swap happens. Recording is cheap
|
|
136
|
+
* and non-blocking so it never holds up an in-flight turn or other frames.
|
|
135
137
|
*/
|
|
136
|
-
updateModel(provider: AgentProvider | null, model: ModelSelection): void;
|
|
138
|
+
updateModel(provider: AgentProvider | null, model: ModelSelection, apply?: ModelSwitchApply): void;
|
|
137
139
|
abort(): Promise<AbortResult>;
|
|
138
140
|
scheduleYieldWakeup(durationMs: number, metadata?: AgentMetadata | null): AgentToolInvokeResult;
|
|
139
141
|
waitUntilDone(): Promise<void>;
|
|
@@ -169,13 +171,20 @@ declare class AgentSession<State> {
|
|
|
169
171
|
private runWorker;
|
|
170
172
|
private executeAction;
|
|
171
173
|
/**
|
|
172
|
-
* Applies a queued model/provider switch at
|
|
173
|
-
* context window can't hold the current history, compaction runs FIRST with
|
|
174
|
-
* (pre-switch) model + provider — which can still load it to summarize — and
|
|
175
|
-
* swap. Doing it the other way would ask the smaller model to summarize
|
|
176
|
-
* be able to load.
|
|
174
|
+
* Applies a queued model/provider switch at an action boundary (turn preflight). If the
|
|
175
|
+
* new model's context window can't hold the current history, compaction runs FIRST with
|
|
176
|
+
* the current (pre-switch) model + provider — which can still load it to summarize — and
|
|
177
|
+
* only then do we swap. Doing it the other way would ask the smaller model to summarize
|
|
178
|
+
* a history it may not be able to load. Returns whether that compaction actually ran
|
|
179
|
+
* (false when no switch was pending).
|
|
177
180
|
*/
|
|
178
181
|
private applyPendingModelSwitch;
|
|
182
|
+
/**
|
|
183
|
+
* Turn-loop variant for mid-turn continuation boundaries: only switches recorded with
|
|
184
|
+
* apply 'immediate' land here; 'next_turn' switches stay pending until the running turn
|
|
185
|
+
* finishes and the next action starts.
|
|
186
|
+
*/
|
|
187
|
+
private applyImmediateModelSwitch;
|
|
179
188
|
private runWithCompactingPhase;
|
|
180
189
|
private executeSend;
|
|
181
190
|
private resolveReferences;
|
|
@@ -231,6 +240,7 @@ interface AgentServerSessionOptions {
|
|
|
231
240
|
compaction?: {
|
|
232
241
|
keepRecentTokens?: number;
|
|
233
242
|
preflightThresholdRatio?: number;
|
|
243
|
+
preflightThresholdTokens?: number;
|
|
234
244
|
};
|
|
235
245
|
persistIntervalMs?: number;
|
|
236
246
|
}
|
|
@@ -375,4 +385,4 @@ interface ShellToolView {
|
|
|
375
385
|
declare function finishShellToolResult<State>(environment: BashEnvironment, result: ShellCommandStatus, ctx: AgentToolInvokeContext<State>): Promise<AgentToolInvokeResult>;
|
|
376
386
|
declare function shellCommandHandleRequired(result: ShellCommandStatus, budgetTokens: number): boolean;
|
|
377
387
|
//#endregion
|
|
378
|
-
export { AbortResult, AbortTarget, ActiveTurnPhase, AgentActionOptions, AgentClient, AgentClientListener, AgentClientTransport, AgentDisposeContext, AgentHarness, AgentHarnessContext, AgentHarnessRuntime, AgentHostContext, AgentLifecycleEvent, AgentMetadata, AgentPromptContext, AgentReferenceResolveContext, AgentServer, AgentServerOptions, AgentServerSessionOptions, AgentServerTransport, AgentSession, AgentSessionCheckpoint, AgentSessionCloneParams, AgentSessionOptions, AgentSessionParams, AgentSessionRestoreParams, AgentSessionStore, AgentSystemPromptContext, AgentTool, AgentToolContext, AgentToolInvokeContext, AgentToolInvokeResult, AgentTransport, AgentTransportBinding, ClientFrame, ClientSessionEvent, CompactionWindow, ConversationSummary, DEFAULT_MAX_MEDIA_BYTES, DEFAULT_TURN_RETRY_POLICY, DrainedTranscriptPatches, ExternalMutationReservation, InProcessTransportPair, JsonWebSocket, PrepareShell, PrepareShellContext, ProviderStreamError, ResumePoint, RunCommandLineCommandNotRegisteredError, RunCommandLineOptions, RunCommandLineResult, RunCommandLineShellNotFoundError, RunCommandLineTimeoutError, SHELL_VIEW_MAX_CHARS, ServerFrame, SessionEvent, SessionEventListener, ShellCommandStatusLike, ShellToolResultOptions, ShellToolView, StandardAgentToolOptions, TranscriptLog, TranscriptOptions, TranscriptPatch, TurnRetryPolicy, applyTranscriptPatches, cloneBlocks, createInProcessTransportPair, createStandardAgentTools, createWebSocketClientTransport, createWebSocketServerTransport, estimateTranscriptBlockTokens, findResumePoint, finishShellToolResult, isContextLengthExceeded, isRetryableCode, resolveRetryPolicy, retryDelayMs, shellCommandHandleRequired, shellPreviewBudgetTokens, toShellToolResult };
|
|
388
|
+
export { AbortResult, AbortTarget, ActiveTurnPhase, AgentActionOptions, AgentClient, AgentClientListener, AgentClientTransport, AgentDisposeContext, AgentHarness, AgentHarnessContext, AgentHarnessRuntime, AgentHostContext, AgentLifecycleEvent, AgentMetadata, AgentPromptContext, AgentReferenceResolveContext, AgentServer, AgentServerOptions, AgentServerSessionOptions, AgentServerTransport, AgentSession, AgentSessionCheckpoint, AgentSessionCloneParams, AgentSessionOptions, AgentSessionParams, AgentSessionRestoreParams, AgentSessionStore, AgentSystemPromptContext, AgentTool, AgentToolContext, AgentToolInvokeContext, AgentToolInvokeResult, AgentTransport, AgentTransportBinding, ClientFrame, ClientSessionEvent, CompactionWindow, ConversationSummary, DEFAULT_MAX_MEDIA_BYTES, DEFAULT_TURN_RETRY_POLICY, DrainedTranscriptPatches, ExternalMutationReservation, InProcessTransportPair, JsonWebSocket, ModelSwitchApply, PrepareShell, PrepareShellContext, ProviderStreamError, ResumePoint, RunCommandLineCommandNotRegisteredError, RunCommandLineOptions, RunCommandLineResult, RunCommandLineShellNotFoundError, RunCommandLineTimeoutError, SHELL_VIEW_MAX_CHARS, ServerFrame, SessionEvent, SessionEventListener, ShellCommandStatusLike, ShellToolResultOptions, ShellToolView, StandardAgentToolOptions, TranscriptLog, TranscriptOptions, TranscriptPatch, TurnRetryPolicy, applyTranscriptPatches, cloneBlocks, createInProcessTransportPair, createStandardAgentTools, createWebSocketClientTransport, createWebSocketServerTransport, estimateTranscriptBlockTokens, findResumePoint, finishShellToolResult, isContextLengthExceeded, isRetryableCode, resolveRetryPolicy, retryDelayMs, shellCommandHandleRequired, shellPreviewBudgetTokens, toShellToolResult };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as cloneBlocks, i as applyTranscriptPatches, n as createWebSocketServerTransport, o as ProviderStreamError, r as AgentClient, s as isContextLengthExceeded, t as createWebSocketClientTransport } from "./websocket-transport-
|
|
1
|
+
import { a as cloneBlocks, i as applyTranscriptPatches, n as createWebSocketServerTransport, o as ProviderStreamError, r as AgentClient, s as isContextLengthExceeded, t as createWebSocketClientTransport } from "./websocket-transport-c6P3NBuf.mjs";
|
|
2
2
|
import { AbortError, abortable, asError, asRecord, asString, bytesToBase64, createId, delay, isAbortError, isRecord, noop, parseJsonOrString, safeJsonStringify, sliceHead, sliceTail, throwIfAborted, toWellFormedText, truncate } from "@demicodes/utils";
|
|
3
3
|
import { BashEnvironment, CommandRegistry, MAX_TIMEOUT_MS, heredocDelimiter, shellQuote } from "@demicodes/shell";
|
|
4
4
|
import { providerRuntime } from "@demicodes/provider";
|
|
@@ -793,6 +793,20 @@ var PendingSteerQueue = class {
|
|
|
793
793
|
function estimateTokens(text) {
|
|
794
794
|
return Math.ceil(text.length / 4);
|
|
795
795
|
}
|
|
796
|
+
/**
|
|
797
|
+
* Resolves the token count at which auto-compaction fires.
|
|
798
|
+
*
|
|
799
|
+
* - A non-finite `thresholdRatio` disables auto-compaction (used by summary clones).
|
|
800
|
+
* - When `thresholdTokens` is a finite number, it is used as an absolute threshold,
|
|
801
|
+
* clamped to `[0, contextWindow]`.
|
|
802
|
+
* - Otherwise the threshold is `floor(contextWindow * thresholdRatio)`.
|
|
803
|
+
*/
|
|
804
|
+
function resolveCompactionThreshold(contextWindow, thresholdRatio, thresholdTokens) {
|
|
805
|
+
if (contextWindow <= 0) return 0;
|
|
806
|
+
if (!Number.isFinite(thresholdRatio)) return Number.POSITIVE_INFINITY;
|
|
807
|
+
if (thresholdTokens != null && Number.isFinite(thresholdTokens)) return Math.min(Math.max(0, Math.floor(thresholdTokens)), contextWindow);
|
|
808
|
+
return Math.floor(contextWindow * thresholdRatio);
|
|
809
|
+
}
|
|
796
810
|
/** The next (smaller) cut point to retry compaction with, or null when nothing more can be compacted. */
|
|
797
811
|
function nextSmallerCompactionCutPoint(startIndex, cutPoint) {
|
|
798
812
|
const compactedBlockCount = cutPoint - startIndex;
|
|
@@ -821,21 +835,29 @@ var CompactionController = class {
|
|
|
821
835
|
constructor(host) {
|
|
822
836
|
this.host = host;
|
|
823
837
|
}
|
|
824
|
-
/**
|
|
838
|
+
/**
|
|
839
|
+
* Compacts (up to 8 passes) until the history fits `targetModel`'s context, if over
|
|
840
|
+
* threshold. Returns whether anything was compacted.
|
|
841
|
+
*/
|
|
825
842
|
async compactToFit(targetModel) {
|
|
826
843
|
const contextWindow = targetModel.model.contextWindow;
|
|
827
|
-
if (contextWindow <= 0) return;
|
|
828
|
-
const threshold =
|
|
829
|
-
if (this.host.transcript.estimateContextTokens(contextWindow) < threshold) return;
|
|
830
|
-
|
|
831
|
-
|
|
844
|
+
if (contextWindow <= 0) return false;
|
|
845
|
+
const threshold = resolveCompactionThreshold(contextWindow, this.host.thresholdRatio, this.host.thresholdTokens);
|
|
846
|
+
if (this.host.transcript.estimateContextTokens(contextWindow) < threshold) return false;
|
|
847
|
+
return this.host.runWithCompactingPhase(async () => {
|
|
848
|
+
let compacted = false;
|
|
849
|
+
for (let attempt = 0; attempt < 8 && this.host.transcript.estimateContextTokens(contextWindow) >= threshold; attempt += 1) {
|
|
850
|
+
if (!await this.run()) break;
|
|
851
|
+
compacted = true;
|
|
852
|
+
}
|
|
853
|
+
return compacted;
|
|
832
854
|
});
|
|
833
855
|
}
|
|
834
856
|
/** Runs one compaction pass before a turn when the current model is over threshold. */
|
|
835
857
|
async preflight() {
|
|
836
858
|
const contextWindow = this.host.model.model.contextWindow;
|
|
837
859
|
if (contextWindow <= 0) return;
|
|
838
|
-
const threshold =
|
|
860
|
+
const threshold = resolveCompactionThreshold(contextWindow, this.host.thresholdRatio, this.host.thresholdTokens);
|
|
839
861
|
if (this.host.transcript.estimateContextTokens(contextWindow) < threshold) return;
|
|
840
862
|
await this.host.runWithCompactingPhase(() => this.run());
|
|
841
863
|
}
|
|
@@ -922,6 +944,10 @@ var ProviderTurnLoop = class {
|
|
|
922
944
|
let autoCompactions = 0;
|
|
923
945
|
while (true) {
|
|
924
946
|
throwIfAborted(this.host.currentSignal());
|
|
947
|
+
if (await this.host.applyImmediateModelSwitch()) {
|
|
948
|
+
this.host.transcript.pushResumeTurn(this.host.currentTurnId(), this.host.model);
|
|
949
|
+
await this.host.commitTranscript();
|
|
950
|
+
}
|
|
925
951
|
await this.host.materializePendingSteers();
|
|
926
952
|
const steerContinuationBeforeStream = this.host.steerContinuationCount;
|
|
927
953
|
const shouldAutoRecover = await this.streamProviderOnce();
|
|
@@ -1146,7 +1172,7 @@ var ProviderTurnLoop = class {
|
|
|
1146
1172
|
isUsageNearLimit(usage) {
|
|
1147
1173
|
const contextWindow = this.host.model.model.contextWindow;
|
|
1148
1174
|
if (contextWindow <= 0) return false;
|
|
1149
|
-
return usage.inputTokens + usage.outputTokens + usage.cacheReadTokens + usage.cacheWriteTokens >=
|
|
1175
|
+
return usage.inputTokens + usage.outputTokens + usage.cacheReadTokens + usage.cacheWriteTokens >= resolveCompactionThreshold(contextWindow, this.host.thresholdRatio, this.host.thresholdTokens);
|
|
1150
1176
|
}
|
|
1151
1177
|
};
|
|
1152
1178
|
function toToolDefinition(tool) {
|
|
@@ -1172,6 +1198,7 @@ var AgentSession = class AgentSession {
|
|
|
1172
1198
|
store;
|
|
1173
1199
|
compactionKeepRecentTokens;
|
|
1174
1200
|
compactionThresholdRatio;
|
|
1201
|
+
compactionThresholdTokens;
|
|
1175
1202
|
listeners = /* @__PURE__ */ new Set();
|
|
1176
1203
|
pendingActions = [];
|
|
1177
1204
|
queued = [];
|
|
@@ -1237,6 +1264,7 @@ var AgentSession = class AgentSession {
|
|
|
1237
1264
|
this.retryPolicy = resolveRetryPolicy(options.retry);
|
|
1238
1265
|
this.compactionKeepRecentTokens = options.compaction?.keepRecentTokens ?? DEFAULT_KEEP_RECENT_TOKENS;
|
|
1239
1266
|
this.compactionThresholdRatio = options.compaction?.preflightThresholdRatio ?? DEFAULT_PREFLIGHT_THRESHOLD_RATIO;
|
|
1267
|
+
this.compactionThresholdTokens = options.compaction?.preflightThresholdTokens === void 0 ? null : options.compaction.preflightThresholdTokens;
|
|
1240
1268
|
const transcriptOptions = {
|
|
1241
1269
|
idFactory: this.idFactory,
|
|
1242
1270
|
now: options.now
|
|
@@ -1256,6 +1284,9 @@ var AgentSession = class AgentSession {
|
|
|
1256
1284
|
get thresholdRatio() {
|
|
1257
1285
|
return self.compactionThresholdRatio;
|
|
1258
1286
|
},
|
|
1287
|
+
get thresholdTokens() {
|
|
1288
|
+
return self.compactionThresholdTokens;
|
|
1289
|
+
},
|
|
1259
1290
|
currentSignal: () => self.currentSignal(),
|
|
1260
1291
|
clone: (transcript) => self.clone({
|
|
1261
1292
|
transcript,
|
|
@@ -1294,6 +1325,9 @@ var AgentSession = class AgentSession {
|
|
|
1294
1325
|
get thresholdRatio() {
|
|
1295
1326
|
return self.compactionThresholdRatio;
|
|
1296
1327
|
},
|
|
1328
|
+
get thresholdTokens() {
|
|
1329
|
+
return self.compactionThresholdTokens;
|
|
1330
|
+
},
|
|
1297
1331
|
get steerContinuationCount() {
|
|
1298
1332
|
return self.steerQueue.continuationCount;
|
|
1299
1333
|
},
|
|
@@ -1316,6 +1350,7 @@ var AgentSession = class AgentSession {
|
|
|
1316
1350
|
self.activeProviderRun = run;
|
|
1317
1351
|
},
|
|
1318
1352
|
streamProvider: (request, run) => self.providerEvents(request, run),
|
|
1353
|
+
applyImmediateModelSwitch: () => self.applyImmediateModelSwitch(),
|
|
1319
1354
|
runCompaction: () => self.compaction.run(),
|
|
1320
1355
|
runWithCompactingPhase: (fn) => self.runWithCompactingPhase(fn),
|
|
1321
1356
|
commitTranscript: () => self.commitTranscript(),
|
|
@@ -1449,21 +1484,23 @@ var AgentSession = class AgentSession {
|
|
|
1449
1484
|
return false;
|
|
1450
1485
|
}
|
|
1451
1486
|
/**
|
|
1452
|
-
*
|
|
1453
|
-
*
|
|
1454
|
-
*
|
|
1455
|
-
*
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
*
|
|
1459
|
-
*
|
|
1460
|
-
*
|
|
1461
|
-
*
|
|
1487
|
+
* Records a model/provider switch for the rest of the session. A non-null `provider`
|
|
1488
|
+
* replaces the current one (its predecessor is disposed); pass null to keep the same
|
|
1489
|
+
* provider instance and only change the model.
|
|
1490
|
+
*
|
|
1491
|
+
* `apply` picks the boundary the switch lands on: 'next_turn' (default) waits for the
|
|
1492
|
+
* start of the next queued action, so a running turn finishes entirely on the old model;
|
|
1493
|
+
* 'immediate' also applies mid-turn at the next sampling/tool continuation, so the very
|
|
1494
|
+
* next request already runs on the new model (the same "as soon as possible" semantics
|
|
1495
|
+
* steering has). Either way, if the new model can't hold the history, compaction runs
|
|
1496
|
+
* first with the current (pre-switch) model, then the swap happens. Recording is cheap
|
|
1497
|
+
* and non-blocking so it never holds up an in-flight turn or other frames.
|
|
1462
1498
|
*/
|
|
1463
|
-
updateModel(provider, model) {
|
|
1499
|
+
updateModel(provider, model, apply = "next_turn") {
|
|
1464
1500
|
this.pendingModelSwitch = {
|
|
1465
1501
|
provider,
|
|
1466
|
-
model
|
|
1502
|
+
model,
|
|
1503
|
+
apply
|
|
1467
1504
|
};
|
|
1468
1505
|
}
|
|
1469
1506
|
async abort() {
|
|
@@ -1835,23 +1872,34 @@ var AgentSession = class AgentSession {
|
|
|
1835
1872
|
}
|
|
1836
1873
|
}
|
|
1837
1874
|
/**
|
|
1838
|
-
* Applies a queued model/provider switch at
|
|
1839
|
-
* context window can't hold the current history, compaction runs FIRST with
|
|
1840
|
-
* (pre-switch) model + provider — which can still load it to summarize — and
|
|
1841
|
-
* swap. Doing it the other way would ask the smaller model to summarize
|
|
1842
|
-
* be able to load.
|
|
1875
|
+
* Applies a queued model/provider switch at an action boundary (turn preflight). If the
|
|
1876
|
+
* new model's context window can't hold the current history, compaction runs FIRST with
|
|
1877
|
+
* the current (pre-switch) model + provider — which can still load it to summarize — and
|
|
1878
|
+
* only then do we swap. Doing it the other way would ask the smaller model to summarize
|
|
1879
|
+
* a history it may not be able to load. Returns whether that compaction actually ran
|
|
1880
|
+
* (false when no switch was pending).
|
|
1843
1881
|
*/
|
|
1844
1882
|
async applyPendingModelSwitch() {
|
|
1845
1883
|
const pending = this.pendingModelSwitch;
|
|
1846
|
-
if (!pending) return;
|
|
1884
|
+
if (!pending) return false;
|
|
1847
1885
|
this.pendingModelSwitch = null;
|
|
1848
|
-
await this.compaction.compactToFit(pending.model);
|
|
1886
|
+
const compacted = await this.compaction.compactToFit(pending.model);
|
|
1849
1887
|
if (pending.provider && pending.provider !== this.provider) {
|
|
1850
1888
|
const previous = this.provider;
|
|
1851
1889
|
this.provider = pending.provider;
|
|
1852
1890
|
await previous.dispose?.();
|
|
1853
1891
|
}
|
|
1854
1892
|
this.model = pending.model;
|
|
1893
|
+
return compacted;
|
|
1894
|
+
}
|
|
1895
|
+
/**
|
|
1896
|
+
* Turn-loop variant for mid-turn continuation boundaries: only switches recorded with
|
|
1897
|
+
* apply 'immediate' land here; 'next_turn' switches stay pending until the running turn
|
|
1898
|
+
* finishes and the next action starts.
|
|
1899
|
+
*/
|
|
1900
|
+
async applyImmediateModelSwitch() {
|
|
1901
|
+
if (this.pendingModelSwitch?.apply !== "immediate") return false;
|
|
1902
|
+
return this.applyPendingModelSwitch();
|
|
1855
1903
|
}
|
|
1856
1904
|
async runWithCompactingPhase(fn) {
|
|
1857
1905
|
const previousPhase = this.currentPhase;
|
|
@@ -2834,7 +2882,7 @@ var AgentTransportBindingImpl = class {
|
|
|
2834
2882
|
this.session?.cancelPendingSteer(frame.steerId);
|
|
2835
2883
|
return;
|
|
2836
2884
|
case "set_provider":
|
|
2837
|
-
await this.setProvider(frame.provider);
|
|
2885
|
+
await this.setProvider(frame.provider, frame.apply);
|
|
2838
2886
|
return;
|
|
2839
2887
|
case "retry": {
|
|
2840
2888
|
const session = this.sessionFor("retry");
|
|
@@ -3024,7 +3072,7 @@ var AgentTransportBindingImpl = class {
|
|
|
3024
3072
|
return;
|
|
3025
3073
|
}
|
|
3026
3074
|
}
|
|
3027
|
-
async setProvider(provider) {
|
|
3075
|
+
async setProvider(provider, apply) {
|
|
3028
3076
|
const session = this.session;
|
|
3029
3077
|
if (!session) {
|
|
3030
3078
|
this.send({
|
|
@@ -3035,11 +3083,11 @@ var AgentTransportBindingImpl = class {
|
|
|
3035
3083
|
return;
|
|
3036
3084
|
}
|
|
3037
3085
|
if (provider.providerId === this.currentProviderId) {
|
|
3038
|
-
|
|
3086
|
+
session.updateModel(null, provider.model, apply);
|
|
3039
3087
|
return;
|
|
3040
3088
|
}
|
|
3041
3089
|
const next = await this.createRuntime(provider);
|
|
3042
|
-
|
|
3090
|
+
session.updateModel(next, provider.model, apply);
|
|
3043
3091
|
this.currentProviderId = provider.providerId;
|
|
3044
3092
|
}
|
|
3045
3093
|
async createRuntime(selection) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as AgentServerTransport, t as AgentClientTransport } from "./transport-
|
|
1
|
+
import { n as AgentServerTransport, t as AgentClientTransport } from "./transport-DtBCCS_A.mjs";
|
|
2
2
|
import { Readable, Writable } from "node:stream";
|
|
3
3
|
//#region src/stdio-transport.d.ts
|
|
4
4
|
declare function createStdioClientTransport(readable: Readable, writable: Writable): AgentClientTransport;
|
|
@@ -209,6 +209,14 @@ interface AgentToolInvokeResult {
|
|
|
209
209
|
view?: unknown | null;
|
|
210
210
|
stopAfterToolResult?: boolean;
|
|
211
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* When a recorded model/provider switch is applied:
|
|
214
|
+
* - 'next_turn' (default): the start of the next queued action — a running turn, if any,
|
|
215
|
+
* finishes entirely on the old model.
|
|
216
|
+
* - 'immediate': the next inference boundary — mid-turn that is the next sampling/tool
|
|
217
|
+
* continuation, so the very next request already runs on the new model.
|
|
218
|
+
*/
|
|
219
|
+
type ModelSwitchApply = 'immediate' | 'next_turn';
|
|
212
220
|
type AbortTarget = 'active_provider_stream' | 'active_tool' | 'active_compaction' | 'active_turn' | 'queued_action' | 'queued_message' | 'pending_yield_wakeup';
|
|
213
221
|
interface AbortResult {
|
|
214
222
|
aborted: boolean;
|
|
@@ -308,6 +316,12 @@ interface AgentSessionOptions<State = unknown> {
|
|
|
308
316
|
compaction?: {
|
|
309
317
|
keepRecentTokens?: number;
|
|
310
318
|
preflightThresholdRatio?: number;
|
|
319
|
+
/**
|
|
320
|
+
* Absolute token threshold for auto-compaction. When set, replaces the
|
|
321
|
+
* ratio-derived threshold (still clamped to the model context window).
|
|
322
|
+
* A non-finite `preflightThresholdRatio` still disables auto-compaction.
|
|
323
|
+
*/
|
|
324
|
+
preflightThresholdTokens?: number;
|
|
311
325
|
};
|
|
312
326
|
/**
|
|
313
327
|
* Maximum interval between checkpoint writes while a turn is streaming. Writes
|
|
@@ -388,6 +402,7 @@ type ClientFrame = {
|
|
|
388
402
|
} | {
|
|
389
403
|
type: 'set_provider';
|
|
390
404
|
provider: ProviderSelection;
|
|
405
|
+
apply?: ModelSwitchApply;
|
|
391
406
|
} | {
|
|
392
407
|
type: 'abort';
|
|
393
408
|
} | {
|
|
@@ -580,4 +595,4 @@ interface InProcessTransportPair {
|
|
|
580
595
|
}
|
|
581
596
|
declare function createInProcessTransportPair(): InProcessTransportPair;
|
|
582
597
|
//#endregion
|
|
583
|
-
export { AgentTool as A,
|
|
598
|
+
export { AgentTool as A, TranscriptLog as B, AgentSessionCheckpoint as C, AgentSessionRestoreParams as D, AgentSessionParams as E, ModelSwitchApply as F, isRetryableCode as G, estimateTranscriptBlockTokens as H, SessionEvent as I, resolveRetryPolicy as K, SessionEventListener as L, AgentToolInvokeContext as M, AgentToolInvokeResult as N, AgentSessionStore as O, ExternalMutationReservation as P, CompactionWindow as R, AgentReferenceResolveContext as S, AgentSessionOptions as T, DEFAULT_TURN_RETRY_POLICY as U, TranscriptOptions as V, TurnRetryPolicy as W, AgentHarnessRuntime as _, createInProcessTransportPair as a, AgentMetadata as b, ConversationSummary as c, TranscriptPatch as d, AbortResult as f, AgentHarnessContext as g, AgentHarness as h, InProcessTransportPair as i, AgentToolContext as j, AgentSystemPromptContext as k, ServerFrame as l, AgentDisposeContext as m, AgentServerTransport as n, ClientFrame as o, AbortTarget as p, retryDelayMs as q, AgentTransport as r, ClientSessionEvent as s, AgentClientTransport as t, ShellCommandStatusLike as u, AgentHostContext as v, AgentSessionCloneParams as w, AgentPromptContext as x, AgentLifecycleEvent as y, DrainedTranscriptPatches as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { b as AgentMetadata, c as ConversationSummary, f as AbortResult, n as AgentServerTransport, s as ClientSessionEvent, t as AgentClientTransport } from "./transport-
|
|
1
|
+
import { F as ModelSwitchApply, b as AgentMetadata, c as ConversationSummary, f as AbortResult, n as AgentServerTransport, s as ClientSessionEvent, t as AgentClientTransport } from "./transport-DtBCCS_A.mjs";
|
|
2
2
|
import { ProviderSelection } from "@demicodes/provider";
|
|
3
3
|
import { Block, UserContentBlock } from "@demicodes/core";
|
|
4
4
|
//#region src/client.d.ts
|
|
@@ -35,10 +35,15 @@ declare class AgentClient {
|
|
|
35
35
|
}): Promise<void>;
|
|
36
36
|
cancelPendingSteer(steerId: string): void;
|
|
37
37
|
/**
|
|
38
|
-
* Switches the provider/model for an open session.
|
|
39
|
-
*
|
|
38
|
+
* Switches the provider/model for an open session. Fire-and-forget: the server records
|
|
39
|
+
* the switch and applies it per `options.apply` — 'next_turn' (default) waits for the
|
|
40
|
+
* next queued action, so a running turn finishes on the old model; 'immediate' applies
|
|
41
|
+
* at the next inference boundary, so mid-turn the very next sampling/tool continuation
|
|
42
|
+
* already runs on the new model.
|
|
40
43
|
*/
|
|
41
|
-
setProvider(provider: ProviderSelection
|
|
44
|
+
setProvider(provider: ProviderSelection, options?: {
|
|
45
|
+
apply?: ModelSwitchApply;
|
|
46
|
+
}): void;
|
|
42
47
|
/**
|
|
43
48
|
* Discards the whole latest turn and runs it again from the user's input —
|
|
44
49
|
* "regenerate". NOT a recovery path: it drops text the turn already emitted and
|
|
@@ -156,13 +156,17 @@ var AgentClient = class {
|
|
|
156
156
|
});
|
|
157
157
|
}
|
|
158
158
|
/**
|
|
159
|
-
* Switches the provider/model for an open session.
|
|
160
|
-
*
|
|
159
|
+
* Switches the provider/model for an open session. Fire-and-forget: the server records
|
|
160
|
+
* the switch and applies it per `options.apply` — 'next_turn' (default) waits for the
|
|
161
|
+
* next queued action, so a running turn finishes on the old model; 'immediate' applies
|
|
162
|
+
* at the next inference boundary, so mid-turn the very next sampling/tool continuation
|
|
163
|
+
* already runs on the new model.
|
|
161
164
|
*/
|
|
162
|
-
setProvider(provider) {
|
|
165
|
+
setProvider(provider, options = {}) {
|
|
163
166
|
this.sendFrame({
|
|
164
167
|
type: "set_provider",
|
|
165
|
-
provider
|
|
168
|
+
provider,
|
|
169
|
+
apply: options.apply
|
|
166
170
|
});
|
|
167
171
|
}
|
|
168
172
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@demicodes/agent",
|
|
3
3
|
"description": "Session runtime and transport-neutral client and server protocol for Demi.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.17.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
7
7
|
"exports": {
|
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@demicodes/core": "^0.
|
|
23
|
-
"@demicodes/provider": "^0.
|
|
24
|
-
"@demicodes/shell": "^0.
|
|
25
|
-
"@demicodes/utils": "^0.
|
|
22
|
+
"@demicodes/core": "^0.17.0",
|
|
23
|
+
"@demicodes/provider": "^0.17.0",
|
|
24
|
+
"@demicodes/shell": "^0.17.0",
|
|
25
|
+
"@demicodes/utils": "^0.17.0"
|
|
26
26
|
},
|
|
27
27
|
"license": "Apache-2.0",
|
|
28
28
|
"main": "./dist/index.mjs",
|