@superdurable/dex-agents 0.1.0 → 0.3.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.
Files changed (168) hide show
  1. package/README.md +1608 -64
  2. package/dist/src/agent-built-in-tools.d.ts +81 -0
  3. package/dist/src/agent-built-in-tools.js +246 -0
  4. package/dist/src/agent-built-in-tools.js.map +1 -0
  5. package/dist/src/agent-context-compaction.d.ts +254 -0
  6. package/dist/src/agent-context-compaction.js +287 -0
  7. package/dist/src/agent-context-compaction.js.map +1 -0
  8. package/dist/src/agent-framework-runner.d.ts +456 -16
  9. package/dist/src/agent-framework-runner.js +4 -3
  10. package/dist/src/agent-framework-runner.js.map +1 -1
  11. package/dist/src/agent-plans.d.ts +48 -0
  12. package/dist/src/agent-plans.js +86 -0
  13. package/dist/src/agent-plans.js.map +1 -0
  14. package/dist/src/agent-session-cancellation-steps.d.ts +28 -0
  15. package/dist/src/agent-session-cancellation-steps.js +154 -0
  16. package/dist/src/agent-session-cancellation-steps.js.map +1 -0
  17. package/dist/src/agent-session-codecs.d.ts +65 -4
  18. package/dist/src/agent-session-codecs.js +343 -8
  19. package/dist/src/agent-session-codecs.js.map +1 -1
  20. package/dist/src/agent-session-failure.d.ts +58 -0
  21. package/dist/src/agent-session-failure.js +126 -0
  22. package/dist/src/agent-session-failure.js.map +1 -0
  23. package/dist/src/agent-session-flow-graph-cli.d.ts +2 -0
  24. package/dist/src/agent-session-flow-graph-cli.js +47 -0
  25. package/dist/src/agent-session-flow-graph-cli.js.map +1 -0
  26. package/dist/src/agent-session-flow-graph.d.ts +38 -0
  27. package/dist/src/agent-session-flow-graph.js +54 -0
  28. package/dist/src/agent-session-flow-graph.js.map +1 -0
  29. package/dist/src/agent-session-flow-graph.json +2187 -0
  30. package/dist/src/agent-session-flow.d.ts +317 -28
  31. package/dist/src/agent-session-flow.js +373 -21
  32. package/dist/src/agent-session-flow.js.map +1 -1
  33. package/dist/src/agent-session-persistence.d.ts +81 -4
  34. package/dist/src/agent-session-persistence.js +33 -2
  35. package/dist/src/agent-session-persistence.js.map +1 -1
  36. package/dist/src/agent-session-settings.d.ts +58 -0
  37. package/dist/src/agent-session-settings.js +81 -0
  38. package/dist/src/agent-session-settings.js.map +1 -0
  39. package/dist/src/agent-session-spend-limit.d.ts +156 -0
  40. package/dist/src/agent-session-spend-limit.js +42 -0
  41. package/dist/src/agent-session-spend-limit.js.map +1 -0
  42. package/dist/src/agent-session-start.d.ts +49 -0
  43. package/dist/src/agent-session-start.js +67 -0
  44. package/dist/src/agent-session-start.js.map +1 -0
  45. package/dist/src/agent-session-step-options.d.ts +78 -0
  46. package/dist/src/agent-session-step-options.js +71 -0
  47. package/dist/src/agent-session-step-options.js.map +1 -0
  48. package/dist/src/agent-session-step-types.d.ts +20 -0
  49. package/dist/src/agent-session-step-types.js +28 -0
  50. package/dist/src/agent-session-step-types.js.map +1 -0
  51. package/dist/src/agent-session-steps.d.ts +103 -8
  52. package/dist/src/agent-session-steps.js +997 -197
  53. package/dist/src/agent-session-steps.js.map +1 -1
  54. package/dist/src/agent-session-tracer.d.ts +61 -0
  55. package/dist/src/agent-session-tracer.js +608 -0
  56. package/dist/src/agent-session-tracer.js.map +1 -0
  57. package/dist/src/agent-session-transitions.d.ts +200 -26
  58. package/dist/src/agent-session-transitions.js +732 -32
  59. package/dist/src/agent-session-transitions.js.map +1 -1
  60. package/dist/src/agent-session-values.d.ts +696 -30
  61. package/dist/src/agent-session-values.js +39 -4
  62. package/dist/src/agent-session-values.js.map +1 -1
  63. package/dist/src/agent-session-wait-steps.d.ts +53 -0
  64. package/dist/src/agent-session-wait-steps.js +389 -0
  65. package/dist/src/agent-session-wait-steps.js.map +1 -0
  66. package/dist/src/agent-tracing-options.d.ts +107 -0
  67. package/dist/src/agent-tracing-options.js +20 -0
  68. package/dist/src/agent-tracing-options.js.map +1 -0
  69. package/dist/src/ai-sdk/ai-sdk-model-client.d.ts +40 -0
  70. package/dist/src/ai-sdk/ai-sdk-model-client.js +235 -0
  71. package/dist/src/ai-sdk/ai-sdk-model-client.js.map +1 -0
  72. package/dist/src/ai-sdk/index.d.ts +1 -0
  73. package/dist/src/ai-sdk/index.js +9 -0
  74. package/dist/src/ai-sdk/index.js.map +1 -0
  75. package/dist/src/index.d.ts +14 -3
  76. package/dist/src/index.js +12 -2
  77. package/dist/src/index.js.map +1 -1
  78. package/dist/src/mcp/index.d.ts +3 -0
  79. package/dist/src/mcp/index.js +10 -0
  80. package/dist/src/mcp/index.js.map +1 -0
  81. package/dist/src/mcp/mcp-resource-and-prompt-tools.d.ts +29 -0
  82. package/dist/src/mcp/mcp-resource-and-prompt-tools.js +185 -0
  83. package/dist/src/mcp/mcp-resource-and-prompt-tools.js.map +1 -0
  84. package/dist/src/mcp/mcp-server-config.d.ts +86 -0
  85. package/dist/src/mcp/mcp-server-config.js +38 -0
  86. package/dist/src/mcp/mcp-server-config.js.map +1 -0
  87. package/dist/src/mcp/mcp-tool-source.d.ts +470 -0
  88. package/dist/src/mcp/mcp-tool-source.js +1204 -0
  89. package/dist/src/mcp/mcp-tool-source.js.map +1 -0
  90. package/dist/src/stepwise/agent-definition.d.ts +166 -0
  91. package/dist/src/stepwise/agent-definition.js +9 -0
  92. package/dist/src/stepwise/agent-definition.js.map +1 -0
  93. package/dist/src/stepwise/function-tool.d.ts +130 -0
  94. package/dist/src/stepwise/function-tool.js +75 -0
  95. package/dist/src/stepwise/function-tool.js.map +1 -0
  96. package/dist/src/stepwise/index.d.ts +8 -0
  97. package/dist/src/stepwise/index.js +13 -0
  98. package/dist/src/stepwise/index.js.map +1 -0
  99. package/dist/src/stepwise/json-schema-validation.d.ts +9 -0
  100. package/dist/src/stepwise/json-schema-validation.js +141 -0
  101. package/dist/src/stepwise/json-schema-validation.js.map +1 -0
  102. package/dist/src/stepwise/model-client.d.ts +194 -0
  103. package/dist/src/stepwise/model-client.js +9 -0
  104. package/dist/src/stepwise/model-client.js.map +1 -0
  105. package/dist/src/stepwise/scripted-model-client.d.ts +99 -0
  106. package/dist/src/stepwise/scripted-model-client.js +156 -0
  107. package/dist/src/stepwise/scripted-model-client.js.map +1 -0
  108. package/dist/src/stepwise/stepwise-agent-runner.d.ts +171 -0
  109. package/dist/src/stepwise/stepwise-agent-runner.js +777 -0
  110. package/dist/src/stepwise/stepwise-agent-runner.js.map +1 -0
  111. package/dist/src/stepwise/stepwise-agent-session-flow.d.ts +35 -0
  112. package/dist/src/stepwise/stepwise-agent-session-flow.js +57 -0
  113. package/dist/src/stepwise/stepwise-agent-session-flow.js.map +1 -0
  114. package/dist/src/stepwise/stepwise-input-items.d.ts +12 -0
  115. package/dist/src/stepwise/stepwise-input-items.js +172 -0
  116. package/dist/src/stepwise/stepwise-input-items.js.map +1 -0
  117. package/dist/src/stepwise/tool-source.d.ts +103 -0
  118. package/dist/src/stepwise/tool-source.js +9 -0
  119. package/dist/src/stepwise/tool-source.js.map +1 -0
  120. package/dist/src/testing/agent-session-test-client.d.ts +65 -8
  121. package/dist/src/testing/agent-session-test-client.js +92 -22
  122. package/dist/src/testing/agent-session-test-client.js.map +1 -1
  123. package/dist/src/testing/context-window.d.ts +194 -0
  124. package/dist/src/testing/context-window.js +360 -0
  125. package/dist/src/testing/context-window.js.map +1 -0
  126. package/dist/src/testing/index.d.ts +2 -0
  127. package/dist/src/testing/index.js +2 -0
  128. package/dist/src/testing/index.js.map +1 -1
  129. package/dist/src/testing/private-dex-engine.d.ts +9 -0
  130. package/dist/src/testing/private-dex-engine.js +9 -1
  131. package/dist/src/testing/private-dex-engine.js.map +1 -1
  132. package/dist/src/testing/scripted-model-client.d.ts +1 -0
  133. package/dist/src/testing/scripted-model-client.js +10 -0
  134. package/dist/src/testing/scripted-model-client.js.map +1 -0
  135. package/dist/src/ui-stream/agent-event-json.d.ts +30 -0
  136. package/dist/src/ui-stream/agent-event-json.js +64 -0
  137. package/dist/src/ui-stream/agent-event-json.js.map +1 -0
  138. package/dist/src/ui-stream/agent-event-sse.d.ts +155 -0
  139. package/dist/src/ui-stream/agent-event-sse.js +167 -0
  140. package/dist/src/ui-stream/agent-event-sse.js.map +1 -0
  141. package/dist/src/ui-stream/agent-event-stream-positions.d.ts +42 -0
  142. package/dist/src/ui-stream/agent-event-stream-positions.js +153 -0
  143. package/dist/src/ui-stream/agent-event-stream-positions.js.map +1 -0
  144. package/dist/src/ui-stream/agent-session-record-reader.d.ts +74 -0
  145. package/dist/src/ui-stream/agent-session-record-reader.js +246 -0
  146. package/dist/src/ui-stream/agent-session-record-reader.js.map +1 -0
  147. package/dist/src/ui-stream/agent-ui-message-stream-responses.d.ts +219 -0
  148. package/dist/src/ui-stream/agent-ui-message-stream-responses.js +441 -0
  149. package/dist/src/ui-stream/agent-ui-message-stream-responses.js.map +1 -0
  150. package/dist/src/ui-stream/agent-ui-message-stream.d.ts +138 -0
  151. package/dist/src/ui-stream/agent-ui-message-stream.js +695 -0
  152. package/dist/src/ui-stream/agent-ui-message-stream.js.map +1 -0
  153. package/dist/src/ui-stream/agent-ui-message-types.d.ts +238 -0
  154. package/dist/src/ui-stream/agent-ui-message-types.js +57 -0
  155. package/dist/src/ui-stream/agent-ui-message-types.js.map +1 -0
  156. package/dist/src/ui-stream/agent-ui-messages.d.ts +68 -0
  157. package/dist/src/ui-stream/agent-ui-messages.js +222 -0
  158. package/dist/src/ui-stream/agent-ui-messages.js.map +1 -0
  159. package/dist/src/ui-stream/agent-ui-stream-cursor.d.ts +64 -0
  160. package/dist/src/ui-stream/agent-ui-stream-cursor.js +186 -0
  161. package/dist/src/ui-stream/agent-ui-stream-cursor.js.map +1 -0
  162. package/dist/src/ui-stream/index.d.ts +14 -0
  163. package/dist/src/ui-stream/index.js +22 -0
  164. package/dist/src/ui-stream/index.js.map +1 -0
  165. package/dist/src/ui-stream/server-sent-event-responses.d.ts +6 -0
  166. package/dist/src/ui-stream/server-sent-event-responses.js +34 -0
  167. package/dist/src/ui-stream/server-sent-event-responses.js.map +1 -0
  168. package/package.json +44 -5
@@ -0,0 +1,287 @@
1
+ // Copyright (c) 2026 Super Durable, Inc.
2
+ //
3
+ // Licensed under the Sustainable Use License 1.0.
4
+ // You may not use this file except in compliance with the License.
5
+ // See the LICENSE file in the repository root.
6
+ //
7
+ // SPDX-License-Identifier: LicenseRef-Sustainable-Use-1.0
8
+ /** First line of the user text that carries the {@link ContextSummary} into the model input. */
9
+ export const contextSummaryNoteHeader = "[Dex] Summary of the earlier conversation:";
10
+ /** Instructions of the model call that writes a {@link ContextSummary}. */
11
+ export const contextSummaryInstructions = "You summarize the earlier part of an agent conversation. The agent continues from your " +
12
+ "summary and the messages after it, so keep every fact, decision, user request and " +
13
+ "preference, open task, and tool result that it still needs, including what an earlier " +
14
+ "summary says. Write plain text.";
15
+ /** Last user text of the model call that writes a {@link ContextSummary}. */
16
+ export const contextSummaryRequest = "[Dex] Summarize the conversation above. Reply with the summary only.";
17
+ /**
18
+ * First line of the transcript in the prompt of {@link buildContextSummaryPrompt}.
19
+ * @since 0.3.0
20
+ */
21
+ export const contextSummaryTranscriptHeader = "[Dex] The conversation to summarize:";
22
+ /**
23
+ * The most tokens {@link buildContextSummaryPrompt} leaves free for the summary it asks for.
24
+ * @since 0.3.0
25
+ */
26
+ export const contextSummaryOutputTokens = 4096;
27
+ // Bytes per estimated token. Below the 4 of English text, and 1 token per CJK character.
28
+ const estimatedBytesPerToken = 3;
29
+ const textEncoder = new TextEncoder();
30
+ /**
31
+ * Returns the user text that says how many of the oldest messages a summary request left out.
32
+ * @param omittedCount - Messages left out, at least 1.
33
+ * @returns `[Dex] <omittedCount> earlier messages did not fit in this request and are left out.`, or
34
+ * `[Dex] 1 earlier message did not fit in this request and is left out.` for one message.
35
+ */
36
+ export function buildContextSummaryOmissionNote(omittedCount) {
37
+ if (omittedCount === 1) {
38
+ return "[Dex] 1 earlier message did not fit in this request and is left out.";
39
+ }
40
+ return `[Dex] ${omittedCount} earlier messages did not fit in this request and are left out.`;
41
+ }
42
+ /**
43
+ * Returns the user text that puts a summary before the newer messages in a model input.
44
+ * @param summary - The session's summary.
45
+ * @returns {@link contextSummaryNoteHeader}, a newline, and the summary text.
46
+ */
47
+ export function buildContextSummaryNote(summary) {
48
+ return `${contextSummaryNoteHeader}\n${summary.text}`;
49
+ }
50
+ /**
51
+ * Estimates the tokens of a text without a tokenizer, rounding up.
52
+ *
53
+ * Use it where a framework assembles the prompt and offers no token counter. It counts one token per three UTF-8
54
+ * bytes. That is more than a provider counts for English text, and about one token per CJK character, so the
55
+ * estimate errs toward compacting early.
56
+ *
57
+ * @example
58
+ * ```ts
59
+ * estimateTextTokens("twelve bytes"); // 4
60
+ * ```
61
+ * @param text - The text to measure.
62
+ * @returns The estimated tokens; 0 for an empty text.
63
+ * @since 0.3.0
64
+ */
65
+ export function estimateTextTokens(text) {
66
+ return Math.ceil(textEncoder.encode(text).length / estimatedBytesPerToken);
67
+ }
68
+ /**
69
+ * Estimates a model input that a framework builds from the stored items.
70
+ *
71
+ * Call it from `estimateInputTokens` of a framework adapter. It measures each `frameworkItem` as stored, so JSON
72
+ * syntax and opaque provider items count too, plus the summary and any `frameworkRunState`.
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * public estimateInputTokens(turn: AgentTurnContext): number {
77
+ * return estimateStoredInputTokens(turn, estimateTextTokens(this.instructions));
78
+ * }
79
+ * ```
80
+ * @param turn - The context of the next model call.
81
+ * @param fixedInputTokens - Tokens of what every request repeats, such as instructions and tool definitions.
82
+ * Measure what the framework shows; `CompactionPolicy.reservedInputTokens` covers the rest. Defaults to 0.
83
+ * @returns The estimated input tokens.
84
+ * @since 0.3.0
85
+ */
86
+ export function estimateStoredInputTokens(turn, fixedInputTokens = 0) {
87
+ let tokens = fixedInputTokens;
88
+ for (const message of turn.messages) {
89
+ tokens += estimateTextTokens(message.frameworkItem);
90
+ }
91
+ if (turn.contextSummary) {
92
+ tokens += estimateTextTokens(buildContextSummaryNote(turn.contextSummary));
93
+ }
94
+ if (turn.frameworkRunState !== null) {
95
+ tokens += estimateTextTokens(turn.frameworkRunState);
96
+ }
97
+ return tokens;
98
+ }
99
+ /**
100
+ * Chooses the last message to summarize, cutting only between turns.
101
+ *
102
+ * Call it from `selectCompactionCutoff` of a framework adapter. A turn's messages are stored together, so a cut
103
+ * between turns never separates a tool call from its result and never splits a model response, whatever
104
+ * framework items the turn holds. The running turn is always kept, because the adapter reads its opening user
105
+ * message from `turn.messages`.
106
+ *
107
+ * It returns `null` while `turn.frameworkRunState` is set. A resumed model call continues from that value, which
108
+ * may already hold the older messages, so the summary could not replace them. Compaction waits for the next turn.
109
+ *
110
+ * @example
111
+ * ```ts
112
+ * public selectCompactionCutoff(turn: AgentTurnContext, retainedTokenBudget: number): number | null {
113
+ * return selectTurnBoundaryCutoff(turn, retainedTokenBudget);
114
+ * }
115
+ * ```
116
+ * @param turn - The context of the model call that crossed the threshold.
117
+ * @param retainedTokenBudget - Tokens that the kept messages may use.
118
+ * @returns The sequence of the last message to summarize: the earliest turn boundary whose kept messages fit the
119
+ * budget, else the boundary before the running turn. `null` when the turn is resuming, every message already
120
+ * fits, or no earlier turn is left to summarize.
121
+ * @since 0.3.0
122
+ */
123
+ export function selectTurnBoundaryCutoff(turn, retainedTokenBudget) {
124
+ if (turn.frameworkRunState !== null) {
125
+ return null;
126
+ }
127
+ const messages = turn.messages;
128
+ const foundRunningTurnIndex = messages.findIndex((message) => message.turnId === turn.turnId);
129
+ const runningTurnIndex = foundRunningTurnIndex === -1 ? messages.length : foundRunningTurnIndex;
130
+ const cuts = [];
131
+ for (let index = 1; index < Math.min(runningTurnIndex + 1, messages.length); index += 1) {
132
+ if (messages[index]?.turnId !== messages[index - 1]?.turnId) {
133
+ cuts.push(index);
134
+ }
135
+ }
136
+ if (cuts.length === 0) {
137
+ return null;
138
+ }
139
+ const keptTokens = new Array(messages.length + 1).fill(0);
140
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
141
+ keptTokens[index] = (keptTokens[index + 1] ?? 0) + estimateTextTokens(messages[index]?.frameworkItem ?? "");
142
+ }
143
+ if ((keptTokens[0] ?? 0) <= retainedTokenBudget) {
144
+ return null;
145
+ }
146
+ const cut = cuts.find((candidate) => (keptTokens[candidate] ?? 0) <= retainedTokenBudget) ?? cuts.at(-1);
147
+ return cut === undefined ? null : (messages[cut - 1]?.sequence ?? null);
148
+ }
149
+ /**
150
+ * Returns a stored message as the plain text a summary prompt shows.
151
+ *
152
+ * Wrap it in the `describeMessage` of {@link buildContextSummaryPrompt} to leave out items that only a provider can
153
+ * read.
154
+ *
155
+ * @param message - The stored message.
156
+ * @returns Its role and text, tool arguments, and tool output. A message with none of them returns its role and
157
+ * `frameworkItem`, such as a model response with several tool calls.
158
+ * @since 0.3.0
159
+ */
160
+ export function describeStoredMessage(message) {
161
+ const lines = [];
162
+ if (message.text) {
163
+ lines.push(`${message.role}: ${message.text}`);
164
+ }
165
+ if (message.toolArguments !== null) {
166
+ lines.push(`tool call ${message.toolName ?? ""}: ${message.toolArguments}`);
167
+ }
168
+ if (message.toolOutput !== null) {
169
+ lines.push(`tool result ${message.toolName ?? ""}: ${message.toolOutput}`);
170
+ }
171
+ return lines.length > 0 ? lines.join("\n") : `${message.role}: ${message.frameworkItem}`;
172
+ }
173
+ /**
174
+ * Builds the one user prompt of a summary call for a framework adapter.
175
+ *
176
+ * Call it from `summarizeContext` and send the result with {@link contextSummaryInstructions} and no tools. The
177
+ * prompt holds the previous summary, the messages as plain text, and {@link contextSummaryRequest}. Plain text
178
+ * works with any framework: it needs no tool definitions, and no provider sees an item out of its place.
179
+ *
180
+ * The prompt fits `request.inputTokenBudget`, less room for the summary, as {@link estimateTextTokens} counts.
181
+ * When the range is too large, it leaves out the oldest messages and says so with
182
+ * {@link buildContextSummaryOmissionNote}. It shortens a single message only when that message alone is too
183
+ * large.
184
+ *
185
+ * @example
186
+ * ```ts
187
+ * public async summarizeContext(request: ContextSummaryRequest): Promise<ContextSummaryResult> {
188
+ * const result = await generateText({
189
+ * model,
190
+ * system: contextSummaryInstructions,
191
+ * prompt: buildContextSummaryPrompt(request),
192
+ * });
193
+ * return { text: result.text, usage: toAgentUsage(result.usage) };
194
+ * }
195
+ * ```
196
+ * @param request - The previous summary and the messages to summarize.
197
+ * @param describeMessage - Returns a message's text for the prompt, or `null` to leave it out, such as an
198
+ * encrypted reasoning item. Defaults to {@link describeStoredMessage}.
199
+ * @returns The prompt text.
200
+ * @since 0.3.0
201
+ */
202
+ export function buildContextSummaryPrompt(request, describeMessage = describeStoredMessage) {
203
+ const opening = request.previousSummary === null ? [] : [buildContextSummaryNote(request.previousSummary)];
204
+ const closing = [contextSummaryTranscriptHeader, contextSummaryRequest];
205
+ const descriptions = request.messages.flatMap((message) => {
206
+ const description = describeMessage(message);
207
+ return description === null ? [] : [description];
208
+ });
209
+ let remainingTokens;
210
+ if (request.inputTokenBudget !== undefined) {
211
+ const fixedTokens = estimateTextTokens([contextSummaryInstructions, ...opening, ...closing].join("\n\n"));
212
+ const roomForTranscript = request.inputTokenBudget - fixedTokens;
213
+ remainingTokens =
214
+ roomForTranscript - Math.min(contextSummaryOutputTokens, Math.floor(Math.max(roomForTranscript, 0) / 4));
215
+ }
216
+ const kept = [];
217
+ for (const description of [...descriptions].reverse()) {
218
+ if (remainingTokens === undefined) {
219
+ kept.push(description);
220
+ continue;
221
+ }
222
+ // Two newlines separate messages; they count toward the estimate.
223
+ const tokens = estimateTextTokens(`${description}\n\n`);
224
+ if (tokens <= remainingTokens) {
225
+ kept.push(description);
226
+ remainingTokens -= tokens;
227
+ continue;
228
+ }
229
+ if (kept.length === 0 && remainingTokens > 0) {
230
+ kept.push(shortenToTokens(description, remainingTokens));
231
+ }
232
+ break;
233
+ }
234
+ kept.reverse();
235
+ const omittedCount = descriptions.length - kept.length;
236
+ if (omittedCount > 0) {
237
+ opening.push(buildContextSummaryOmissionNote(omittedCount));
238
+ }
239
+ return [...opening, contextSummaryTranscriptHeader, ...kept, contextSummaryRequest].join("\n\n");
240
+ }
241
+ function shortenToTokens(text, tokens) {
242
+ const marker = "[Dex] The rest of this message is left out.";
243
+ const keptBytes = Math.max(tokens - estimateTextTokens(marker) - 1, 0) * estimatedBytesPerToken;
244
+ const kept = new TextDecoder().decode(textEncoder.encode(text).slice(0, keptBytes)).replace(/\uFFFD$/u, "");
245
+ return `${kept}\n${marker}`;
246
+ }
247
+ /** Reports whether a runner implements every compaction method. */
248
+ export function isContextCompactionRunner(runner) {
249
+ return (typeof runner.estimateInputTokens === "function" &&
250
+ typeof runner.selectCompactionCutoff === "function" &&
251
+ typeof runner.summarizeContext === "function");
252
+ }
253
+ /**
254
+ * Fills in a compaction policy's defaults and checks it.
255
+ * @throws {RangeError} When `contextWindowTokens` is not a positive integer, `reservedInputTokens` is not an
256
+ * integer from 0 to below the window, or unless `0 < retainedRatio < triggerRatio <= 1`.
257
+ */
258
+ export function resolveCompactionPolicy(policy) {
259
+ const contextWindowTokens = policy.contextWindowTokens;
260
+ if (!Number.isSafeInteger(contextWindowTokens) || contextWindowTokens <= 0) {
261
+ throw new RangeError("compaction.contextWindowTokens must be a positive integer");
262
+ }
263
+ const triggerRatio = policy.triggerRatio ?? 0.85;
264
+ const retainedRatio = policy.retainedRatio ?? 0.3;
265
+ if (!(retainedRatio > 0 && retainedRatio < triggerRatio && triggerRatio <= 1)) {
266
+ throw new RangeError("compaction needs 0 < retainedRatio < triggerRatio <= 1");
267
+ }
268
+ const reservedInputTokens = policy.reservedInputTokens ?? 0;
269
+ const isReservationValid = Number.isSafeInteger(reservedInputTokens) && reservedInputTokens >= 0 && reservedInputTokens < contextWindowTokens;
270
+ if (!isReservationValid) {
271
+ throw new RangeError("compaction.reservedInputTokens must be an integer from 0 to below contextWindowTokens");
272
+ }
273
+ return Object.freeze({ contextWindowTokens, triggerRatio, retainedRatio, reservedInputTokens });
274
+ }
275
+ /**
276
+ * Reports whether a model input of this size makes the session compact before the model call: the estimate
277
+ * plus `reservedInputTokens` reaches `triggerRatio` of the window.
278
+ */
279
+ export function isCompactionTriggered(policy, estimatedInputTokens) {
280
+ const estimatedTokens = estimatedInputTokens + (policy.reservedInputTokens ?? 0);
281
+ return estimatedTokens >= policy.triggerRatio * policy.contextWindowTokens;
282
+ }
283
+ /** Tokens that the newest messages may keep after compaction: the retained share of the window, rounded down. */
284
+ export function readRetainedTokenBudget(policy) {
285
+ return Math.floor(policy.retainedRatio * policy.contextWindowTokens);
286
+ }
287
+ //# sourceMappingURL=agent-context-compaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-context-compaction.js","sourceRoot":"","sources":["../../src/agent-context-compaction.ts"],"names":[],"mappings":"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"}