@superdurable/dex-agents 0.1.0 → 0.2.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 (149) hide show
  1. package/README.md +1568 -62
  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 +108 -0
  6. package/dist/src/agent-context-compaction.js +39 -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 +342 -8
  19. package/dist/src/agent-session-codecs.js.map +1 -1
  20. package/dist/src/agent-session-flow.d.ts +295 -27
  21. package/dist/src/agent-session-flow.js +368 -21
  22. package/dist/src/agent-session-flow.js.map +1 -1
  23. package/dist/src/agent-session-persistence.d.ts +81 -4
  24. package/dist/src/agent-session-persistence.js +33 -2
  25. package/dist/src/agent-session-persistence.js.map +1 -1
  26. package/dist/src/agent-session-settings.d.ts +58 -0
  27. package/dist/src/agent-session-settings.js +81 -0
  28. package/dist/src/agent-session-settings.js.map +1 -0
  29. package/dist/src/agent-session-step-options.d.ts +27 -0
  30. package/dist/src/agent-session-step-options.js +39 -0
  31. package/dist/src/agent-session-step-options.js.map +1 -0
  32. package/dist/src/agent-session-step-types.d.ts +20 -0
  33. package/dist/src/agent-session-step-types.js +28 -0
  34. package/dist/src/agent-session-step-types.js.map +1 -0
  35. package/dist/src/agent-session-steps.d.ts +101 -8
  36. package/dist/src/agent-session-steps.js +936 -197
  37. package/dist/src/agent-session-steps.js.map +1 -1
  38. package/dist/src/agent-session-tracer.d.ts +61 -0
  39. package/dist/src/agent-session-tracer.js +608 -0
  40. package/dist/src/agent-session-tracer.js.map +1 -0
  41. package/dist/src/agent-session-transitions.d.ts +189 -26
  42. package/dist/src/agent-session-transitions.js +680 -32
  43. package/dist/src/agent-session-transitions.js.map +1 -1
  44. package/dist/src/agent-session-values.d.ts +690 -29
  45. package/dist/src/agent-session-values.js +39 -4
  46. package/dist/src/agent-session-values.js.map +1 -1
  47. package/dist/src/agent-session-wait-steps.d.ts +53 -0
  48. package/dist/src/agent-session-wait-steps.js +389 -0
  49. package/dist/src/agent-session-wait-steps.js.map +1 -0
  50. package/dist/src/agent-tracing-options.d.ts +107 -0
  51. package/dist/src/agent-tracing-options.js +20 -0
  52. package/dist/src/agent-tracing-options.js.map +1 -0
  53. package/dist/src/ai-sdk/ai-sdk-model-client.d.ts +40 -0
  54. package/dist/src/ai-sdk/ai-sdk-model-client.js +235 -0
  55. package/dist/src/ai-sdk/ai-sdk-model-client.js.map +1 -0
  56. package/dist/src/ai-sdk/index.d.ts +1 -0
  57. package/dist/src/ai-sdk/index.js +9 -0
  58. package/dist/src/ai-sdk/index.js.map +1 -0
  59. package/dist/src/index.d.ts +9 -3
  60. package/dist/src/index.js +7 -2
  61. package/dist/src/index.js.map +1 -1
  62. package/dist/src/mcp/index.d.ts +3 -0
  63. package/dist/src/mcp/index.js +10 -0
  64. package/dist/src/mcp/index.js.map +1 -0
  65. package/dist/src/mcp/mcp-resource-and-prompt-tools.d.ts +29 -0
  66. package/dist/src/mcp/mcp-resource-and-prompt-tools.js +185 -0
  67. package/dist/src/mcp/mcp-resource-and-prompt-tools.js.map +1 -0
  68. package/dist/src/mcp/mcp-server-config.d.ts +86 -0
  69. package/dist/src/mcp/mcp-server-config.js +38 -0
  70. package/dist/src/mcp/mcp-server-config.js.map +1 -0
  71. package/dist/src/mcp/mcp-tool-source.d.ts +470 -0
  72. package/dist/src/mcp/mcp-tool-source.js +1204 -0
  73. package/dist/src/mcp/mcp-tool-source.js.map +1 -0
  74. package/dist/src/stepwise/agent-definition.d.ts +158 -0
  75. package/dist/src/stepwise/agent-definition.js +9 -0
  76. package/dist/src/stepwise/agent-definition.js.map +1 -0
  77. package/dist/src/stepwise/function-tool.d.ts +130 -0
  78. package/dist/src/stepwise/function-tool.js +75 -0
  79. package/dist/src/stepwise/function-tool.js.map +1 -0
  80. package/dist/src/stepwise/index.d.ts +7 -0
  81. package/dist/src/stepwise/index.js +12 -0
  82. package/dist/src/stepwise/index.js.map +1 -0
  83. package/dist/src/stepwise/json-schema-validation.d.ts +9 -0
  84. package/dist/src/stepwise/json-schema-validation.js +141 -0
  85. package/dist/src/stepwise/json-schema-validation.js.map +1 -0
  86. package/dist/src/stepwise/model-client.d.ts +194 -0
  87. package/dist/src/stepwise/model-client.js +9 -0
  88. package/dist/src/stepwise/model-client.js.map +1 -0
  89. package/dist/src/stepwise/scripted-model-client.d.ts +99 -0
  90. package/dist/src/stepwise/scripted-model-client.js +156 -0
  91. package/dist/src/stepwise/scripted-model-client.js.map +1 -0
  92. package/dist/src/stepwise/stepwise-agent-runner.d.ts +189 -0
  93. package/dist/src/stepwise/stepwise-agent-runner.js +804 -0
  94. package/dist/src/stepwise/stepwise-agent-runner.js.map +1 -0
  95. package/dist/src/stepwise/stepwise-agent-session-flow.d.ts +35 -0
  96. package/dist/src/stepwise/stepwise-agent-session-flow.js +56 -0
  97. package/dist/src/stepwise/stepwise-agent-session-flow.js.map +1 -0
  98. package/dist/src/stepwise/stepwise-input-items.d.ts +12 -0
  99. package/dist/src/stepwise/stepwise-input-items.js +172 -0
  100. package/dist/src/stepwise/stepwise-input-items.js.map +1 -0
  101. package/dist/src/stepwise/tool-source.d.ts +103 -0
  102. package/dist/src/stepwise/tool-source.js +9 -0
  103. package/dist/src/stepwise/tool-source.js.map +1 -0
  104. package/dist/src/testing/agent-session-test-client.d.ts +65 -8
  105. package/dist/src/testing/agent-session-test-client.js +95 -22
  106. package/dist/src/testing/agent-session-test-client.js.map +1 -1
  107. package/dist/src/testing/index.d.ts +1 -0
  108. package/dist/src/testing/index.js +1 -0
  109. package/dist/src/testing/index.js.map +1 -1
  110. package/dist/src/testing/private-dex-engine.d.ts +9 -0
  111. package/dist/src/testing/private-dex-engine.js +9 -1
  112. package/dist/src/testing/private-dex-engine.js.map +1 -1
  113. package/dist/src/testing/scripted-model-client.d.ts +1 -0
  114. package/dist/src/testing/scripted-model-client.js +10 -0
  115. package/dist/src/testing/scripted-model-client.js.map +1 -0
  116. package/dist/src/ui-stream/agent-event-json.d.ts +30 -0
  117. package/dist/src/ui-stream/agent-event-json.js +64 -0
  118. package/dist/src/ui-stream/agent-event-json.js.map +1 -0
  119. package/dist/src/ui-stream/agent-event-sse.d.ts +154 -0
  120. package/dist/src/ui-stream/agent-event-sse.js +159 -0
  121. package/dist/src/ui-stream/agent-event-sse.js.map +1 -0
  122. package/dist/src/ui-stream/agent-event-stream-positions.d.ts +42 -0
  123. package/dist/src/ui-stream/agent-event-stream-positions.js +153 -0
  124. package/dist/src/ui-stream/agent-event-stream-positions.js.map +1 -0
  125. package/dist/src/ui-stream/agent-session-record-reader.d.ts +72 -0
  126. package/dist/src/ui-stream/agent-session-record-reader.js +241 -0
  127. package/dist/src/ui-stream/agent-session-record-reader.js.map +1 -0
  128. package/dist/src/ui-stream/agent-ui-message-stream-responses.d.ts +219 -0
  129. package/dist/src/ui-stream/agent-ui-message-stream-responses.js +440 -0
  130. package/dist/src/ui-stream/agent-ui-message-stream-responses.js.map +1 -0
  131. package/dist/src/ui-stream/agent-ui-message-stream.d.ts +138 -0
  132. package/dist/src/ui-stream/agent-ui-message-stream.js +681 -0
  133. package/dist/src/ui-stream/agent-ui-message-stream.js.map +1 -0
  134. package/dist/src/ui-stream/agent-ui-message-types.d.ts +238 -0
  135. package/dist/src/ui-stream/agent-ui-message-types.js +57 -0
  136. package/dist/src/ui-stream/agent-ui-message-types.js.map +1 -0
  137. package/dist/src/ui-stream/agent-ui-messages.d.ts +66 -0
  138. package/dist/src/ui-stream/agent-ui-messages.js +220 -0
  139. package/dist/src/ui-stream/agent-ui-messages.js.map +1 -0
  140. package/dist/src/ui-stream/agent-ui-stream-cursor.d.ts +64 -0
  141. package/dist/src/ui-stream/agent-ui-stream-cursor.js +186 -0
  142. package/dist/src/ui-stream/agent-ui-stream-cursor.js.map +1 -0
  143. package/dist/src/ui-stream/index.d.ts +14 -0
  144. package/dist/src/ui-stream/index.js +22 -0
  145. package/dist/src/ui-stream/index.js.map +1 -0
  146. package/dist/src/ui-stream/server-sent-event-responses.d.ts +6 -0
  147. package/dist/src/ui-stream/server-sent-event-responses.js +34 -0
  148. package/dist/src/ui-stream/server-sent-event-responses.js.map +1 -0
  149. package/package.json +41 -5
@@ -0,0 +1,81 @@
1
+ import type { AgentPlanTask } from "./agent-session-values.js";
2
+ /**
3
+ * Name of a built-in tool that the session itself handles.
4
+ *
5
+ * - `ask_user`: asks the user a question. The session raises a `question` interrupt, waits in
6
+ * `AwaitQuestionAnswer`, and the answer becomes the tool result, so the model continues the same turn.
7
+ * - `durable_wait`: suspends the turn on a Dex Timer in `AwaitTimer`. No model call, coroutine, or
8
+ * Worker holds the wait.
9
+ * - `write_todos`: replaces the session's {@link AgentPlan} with a new revision. `RunModel` records the
10
+ * call in its own commit; no tool Step runs.
11
+ *
12
+ * Enable built-in tools with {@link AgentSessionOptions.builtInTools}. A runner offers the enabled ones
13
+ * to its model, from {@link builtInToolDefinitions}, like any other tool, and returns their calls in
14
+ * {@link ToolCallsRequested} like any other call. The session routes a call whose name is an enabled
15
+ * built-in tool to that tool's handling instead of a tool Step. An enabled built-in name is reserved.
16
+ * A disabled built-in name is an ordinary tool name.
17
+ */
18
+ export type BuiltInTool = "ask_user" | "durable_wait" | "write_todos";
19
+ /** Model-visible definition of one built-in tool, from {@link builtInToolDefinitions}. */
20
+ export interface BuiltInToolDefinition {
21
+ /** Tool name as the model calls it. */
22
+ readonly name: BuiltInTool;
23
+ /** Tool description for the model; the same text as the Python core. */
24
+ readonly description: string;
25
+ /** JSON Schema of the tool arguments; the same schema as the Python core. */
26
+ readonly parameters: Readonly<Record<string, unknown>>;
27
+ }
28
+ /**
29
+ * Definitions of every built-in tool, with the same names, descriptions, and JSON Schemas as the Python
30
+ * core's `BUILT_IN_TOOL_DEFINITIONS`.
31
+ *
32
+ * A runner offers the definitions of {@link AgentTurnContext.enabledBuiltInTools} to its model. Adapters
33
+ * register them as tools without an implementation, which every adapter already does for deferred
34
+ * application tools.
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * const offeredBuiltInTools = builtInToolDefinitions.filter((definition) =>
39
+ * turn.enabledBuiltInTools?.has(definition.name) === true);
40
+ * ```
41
+ */
42
+ export declare const builtInToolDefinitions: readonly BuiltInToolDefinition[];
43
+ /** Every built-in tool name, in definition order. */
44
+ export declare const builtInToolNames: readonly BuiltInTool[];
45
+ /** Parsed arguments of an `ask_user` call. */
46
+ export interface AskUserArguments {
47
+ readonly question: string;
48
+ readonly choices: readonly string[];
49
+ readonly allowsFreeText: boolean;
50
+ }
51
+ /** Parsed arguments of a `durable_wait` call. */
52
+ export interface DurableWaitArguments {
53
+ readonly durationSeconds: number;
54
+ readonly reason: string;
55
+ }
56
+ /** Error of every `write_todos` call of a model response that has more than one; the same text as the Python core. */
57
+ export declare const writeTodosCalledMoreThanOnce = "write_todos was called more than once in one response";
58
+ /** Result of validating a built-in call's arguments: the parsed arguments or the model-visible error. */
59
+ export type BuiltInArgumentsValidation<Arguments> = {
60
+ readonly isValid: true;
61
+ readonly arguments: Arguments;
62
+ } | {
63
+ readonly isValid: false;
64
+ readonly error: string;
65
+ };
66
+ /** Reports whether text is empty or only whitespace, as Python's `not text.strip()` does. */
67
+ export declare function isBlankText(text: string): boolean;
68
+ export declare function isBuiltInTool(name: string): name is BuiltInTool;
69
+ export declare function validateAskUserArguments(argumentsText: string): BuiltInArgumentsValidation<AskUserArguments>;
70
+ /** A JSON number without a fraction, such as `2.0`, counts as an integer, as JSON Schema defines it. */
71
+ export declare function validateDurableWaitArguments(argumentsText: string, maxDurableWaitSeconds: number): BuiltInArgumentsValidation<DurableWaitArguments>;
72
+ /** Validates `write_todos` arguments; the error is `invalid todos: <reason>`, as in the Python core. */
73
+ export declare function validateWriteTodosArguments(argumentsText: string): BuiltInArgumentsValidation<readonly AgentPlanTask[]>;
74
+ /** Tool output after `write_todos` wrote tasks: `{"status":"updated","revision":<n>,"task_count":<k>}`. */
75
+ export declare function buildPlanUpdatedOutput(revision: number, taskCount: number): string;
76
+ /** Tool output after `write_todos` cleared the plan: `{"status":"cleared","revision":<n>}`. */
77
+ export declare function buildPlanClearedOutput(revision: number): string;
78
+ /** Tool output after the user answered `ask_user`: `{"status":"answered","answer":"<answer>"}`. */
79
+ export declare function buildQuestionAnsweredOutput(answer: string): string;
80
+ /** Tool output after a `durable_wait` Timer ended: `{"status":"completed","waited_seconds":<n>,"reason":"<reason>"}`. */
81
+ export declare function buildDurableWaitCompletedOutput(waitedSeconds: number, reason: string): string;
@@ -0,0 +1,246 @@
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
+ /**
9
+ * Definitions of every built-in tool, with the same names, descriptions, and JSON Schemas as the Python
10
+ * core's `BUILT_IN_TOOL_DEFINITIONS`.
11
+ *
12
+ * A runner offers the definitions of {@link AgentTurnContext.enabledBuiltInTools} to its model. Adapters
13
+ * register them as tools without an implementation, which every adapter already does for deferred
14
+ * application tools.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * const offeredBuiltInTools = builtInToolDefinitions.filter((definition) =>
19
+ * turn.enabledBuiltInTools?.has(definition.name) === true);
20
+ * ```
21
+ */
22
+ export const builtInToolDefinitions = Object.freeze([
23
+ Object.freeze({
24
+ name: "ask_user",
25
+ description: "Ask the user one question and wait for the answer, which becomes this tool's result. Use it only " +
26
+ "when you cannot continue without information or a decision from the user. The wait can last hours " +
27
+ "or days.",
28
+ parameters: Object.freeze({
29
+ type: "object",
30
+ properties: {
31
+ question: { type: "string", description: "One concise question for the user." },
32
+ choices: {
33
+ type: "array",
34
+ items: { type: "string" },
35
+ description: "Answers the user can pick. Omit for a free-text answer.",
36
+ },
37
+ allows_free_text: {
38
+ type: "boolean",
39
+ description: "Whether the user may answer with text that is not one of the choices. Defaults to true.",
40
+ },
41
+ },
42
+ required: ["question"],
43
+ additionalProperties: false,
44
+ }),
45
+ }),
46
+ Object.freeze({
47
+ name: "durable_wait",
48
+ description: "Pause this turn for a number of whole seconds, then continue. Nothing runs during the wait. Use it " +
49
+ "to wait for something outside the conversation, such as a job that needs time to finish.",
50
+ parameters: Object.freeze({
51
+ type: "object",
52
+ properties: {
53
+ duration_seconds: { type: "integer", minimum: 1, description: "Whole seconds to wait." },
54
+ reason: { type: "string", description: "Why the turn waits, shown to the user." },
55
+ },
56
+ required: ["duration_seconds", "reason"],
57
+ additionalProperties: false,
58
+ }),
59
+ }),
60
+ Object.freeze({
61
+ name: "write_todos",
62
+ description: "Replace the plan with a complete, ordered list of tasks. Send every task each time, with its " +
63
+ "status. An empty list clears the plan. Keep the statuses current: mark a task in_progress when you " +
64
+ "start it and completed when it is done.",
65
+ parameters: Object.freeze({
66
+ type: "object",
67
+ properties: {
68
+ todos: {
69
+ type: "array",
70
+ description: "Every task of the plan, in order.",
71
+ items: {
72
+ type: "object",
73
+ properties: {
74
+ content: { type: "string", description: "What the task does, in one short sentence." },
75
+ status: {
76
+ type: "string",
77
+ enum: ["pending", "in_progress", "completed"],
78
+ description: "Where the task stands.",
79
+ },
80
+ },
81
+ required: ["content", "status"],
82
+ additionalProperties: false,
83
+ },
84
+ },
85
+ },
86
+ required: ["todos"],
87
+ additionalProperties: false,
88
+ }),
89
+ }),
90
+ ]);
91
+ /** Every built-in tool name, in definition order. */
92
+ export const builtInToolNames = Object.freeze(builtInToolDefinitions.map((definition) => definition.name));
93
+ /** Error of every `write_todos` call of a model response that has more than one; the same text as the Python core. */
94
+ export const writeTodosCalledMoreThanOnce = "write_todos was called more than once in one response";
95
+ const planTaskStatuses = ["pending", "in_progress", "completed"];
96
+ // The characters Python's str.isspace() accepts, so blank checks match the Python core exactly.
97
+ const pythonWhitespaceOnly = /^[\t\n\v\f\r\x1c-\x1f \x85\xa0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]*$/u;
98
+ /** Reports whether text is empty or only whitespace, as Python's `not text.strip()` does. */
99
+ export function isBlankText(text) {
100
+ return pythonWhitespaceOnly.test(text);
101
+ }
102
+ export function isBuiltInTool(name) {
103
+ return builtInToolNames.includes(name);
104
+ }
105
+ export function validateAskUserArguments(argumentsText) {
106
+ const parsed = parseArgumentsObject("ask_user", argumentsText);
107
+ if (!parsed.isValid) {
108
+ return parsed;
109
+ }
110
+ const record = parsed.arguments;
111
+ const question = record["question"];
112
+ if (typeof question !== "string" || isBlankText(question)) {
113
+ return invalidArguments("ask_user", "question must be a non-empty string");
114
+ }
115
+ const choices = record["choices"] ?? [];
116
+ if (!Array.isArray(choices) || !choices.every((choice) => typeof choice === "string" && !isBlankText(choice))) {
117
+ return invalidArguments("ask_user", "choices must be a list of non-empty strings");
118
+ }
119
+ const allowsFreeText = record["allows_free_text"] ?? true;
120
+ if (typeof allowsFreeText !== "boolean") {
121
+ return invalidArguments("ask_user", "allows_free_text must be a boolean");
122
+ }
123
+ return {
124
+ isValid: true,
125
+ arguments: { question, choices: choices, allowsFreeText: allowsFreeText || choices.length === 0 },
126
+ };
127
+ }
128
+ /** A JSON number without a fraction, such as `2.0`, counts as an integer, as JSON Schema defines it. */
129
+ export function validateDurableWaitArguments(argumentsText, maxDurableWaitSeconds) {
130
+ const parsed = parseArgumentsObject("durable_wait", argumentsText);
131
+ if (!parsed.isValid) {
132
+ return parsed;
133
+ }
134
+ const record = parsed.arguments;
135
+ const durationSeconds = record["duration_seconds"];
136
+ if (typeof durationSeconds !== "number" || !Number.isInteger(durationSeconds)) {
137
+ return invalidArguments("durable_wait", "duration_seconds must be an integer");
138
+ }
139
+ if (durationSeconds < 1 || durationSeconds > maxDurableWaitSeconds) {
140
+ return invalidArguments("durable_wait", `duration_seconds must be between 1 and ${maxDurableWaitSeconds}`);
141
+ }
142
+ const reason = record["reason"];
143
+ if (typeof reason !== "string") {
144
+ return invalidArguments("durable_wait", "reason must be a string");
145
+ }
146
+ return { isValid: true, arguments: { durationSeconds, reason } };
147
+ }
148
+ /** Validates `write_todos` arguments; the error is `invalid todos: <reason>`, as in the Python core. */
149
+ export function validateWriteTodosArguments(argumentsText) {
150
+ let parsed;
151
+ try {
152
+ parsed = JSON.parse(argumentsText);
153
+ }
154
+ catch {
155
+ return invalidTodos("arguments must be a JSON object");
156
+ }
157
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
158
+ return invalidTodos("arguments must be a JSON object");
159
+ }
160
+ const [unknownName] = sortByCodePoint(Object.keys(parsed).filter((name) => name !== "todos"));
161
+ if (unknownName !== undefined) {
162
+ return invalidTodos(`unknown argument ${unknownName}`);
163
+ }
164
+ const todos = parsed["todos"];
165
+ if (!Array.isArray(todos)) {
166
+ return invalidTodos("todos must be a list");
167
+ }
168
+ const tasks = [];
169
+ for (const [index, todo] of todos.entries()) {
170
+ if (typeof todo !== "object" || todo === null || Array.isArray(todo)) {
171
+ return invalidTodos(`todos[${index}] must be an object`);
172
+ }
173
+ const [unknownField] = sortByCodePoint(Object.keys(todo).filter((name) => name !== "content" && name !== "status"));
174
+ if (unknownField !== undefined) {
175
+ return invalidTodos(`todos[${index}] has unknown field ${unknownField}`);
176
+ }
177
+ const { content, status } = todo;
178
+ if (typeof content !== "string" || isBlankText(content)) {
179
+ return invalidTodos(`todos[${index}].content must be a non-empty string`);
180
+ }
181
+ if (typeof status !== "string" || !planTaskStatuses.includes(status)) {
182
+ return invalidTodos(`todos[${index}].status must be pending, in_progress, or completed`);
183
+ }
184
+ tasks.push({ content, status: status });
185
+ }
186
+ return { isValid: true, arguments: tasks };
187
+ }
188
+ /** Tool output after `write_todos` wrote tasks: `{"status":"updated","revision":<n>,"task_count":<k>}`. */
189
+ export function buildPlanUpdatedOutput(revision, taskCount) {
190
+ return JSON.stringify({ status: "updated", revision, task_count: taskCount });
191
+ }
192
+ /** Tool output after `write_todos` cleared the plan: `{"status":"cleared","revision":<n>}`. */
193
+ export function buildPlanClearedOutput(revision) {
194
+ return JSON.stringify({ status: "cleared", revision });
195
+ }
196
+ /** Tool output after the user answered `ask_user`: `{"status":"answered","answer":"<answer>"}`. */
197
+ export function buildQuestionAnsweredOutput(answer) {
198
+ return JSON.stringify({ status: "answered", answer });
199
+ }
200
+ /** Tool output after a `durable_wait` Timer ended: `{"status":"completed","waited_seconds":<n>,"reason":"<reason>"}`. */
201
+ export function buildDurableWaitCompletedOutput(waitedSeconds, reason) {
202
+ return JSON.stringify({ status: "completed", waited_seconds: waitedSeconds, reason });
203
+ }
204
+ function invalidTodos(reason) {
205
+ return { isValid: false, error: `invalid todos: ${reason}` };
206
+ }
207
+ /** Sorted by code point, as Python's `sorted` orders strings, so both cores report the same name. */
208
+ function sortByCodePoint(names) {
209
+ return [...names].sort(compareByCodePoint);
210
+ }
211
+ /** JavaScript's `<` compares UTF-16 code units, which orders characters above U+FFFF before U+E000. */
212
+ function compareByCodePoint(left, right) {
213
+ const leftCodePoints = Array.from(left, (character) => character.codePointAt(0) ?? 0);
214
+ const rightCodePoints = Array.from(right, (character) => character.codePointAt(0) ?? 0);
215
+ const sharedLength = Math.min(leftCodePoints.length, rightCodePoints.length);
216
+ for (let index = 0; index < sharedLength; index += 1) {
217
+ const difference = (leftCodePoints[index] ?? 0) - (rightCodePoints[index] ?? 0);
218
+ if (difference !== 0) {
219
+ return difference;
220
+ }
221
+ }
222
+ return leftCodePoints.length - rightCodePoints.length;
223
+ }
224
+ function parseArgumentsObject(builtInTool, argumentsText) {
225
+ let parsed;
226
+ try {
227
+ parsed = JSON.parse(argumentsText);
228
+ }
229
+ catch {
230
+ return invalidArguments(builtInTool, "arguments must be a JSON object");
231
+ }
232
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
233
+ return invalidArguments(builtInTool, "arguments must be a JSON object");
234
+ }
235
+ const definition = builtInToolDefinitions.find((candidate) => candidate.name === builtInTool);
236
+ const allowedNames = Object.keys((definition?.parameters["properties"] ?? {}));
237
+ const [unknownName] = sortByCodePoint(Object.keys(parsed).filter((name) => !allowedNames.includes(name)));
238
+ if (unknownName !== undefined) {
239
+ return invalidArguments(builtInTool, `unknown argument ${unknownName}`);
240
+ }
241
+ return { isValid: true, arguments: parsed };
242
+ }
243
+ function invalidArguments(builtInTool, reason) {
244
+ return { isValid: false, error: `invalid ${builtInTool} arguments: ${reason}` };
245
+ }
246
+ //# sourceMappingURL=agent-built-in-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-built-in-tools.js","sourceRoot":"","sources":["../../src/agent-built-in-tools.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,kDAAkD;AAClD,mEAAmE;AACnE,+CAA+C;AAC/C,EAAE;AACF,0DAA0D;AAgC1D;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAqC,MAAM,CAAC,MAAM,CAAC;IACpF,MAAM,CAAC,MAAM,CAAC;QACZ,IAAI,EAAE,UAAU;QAChB,WAAW,EACT,mGAAmG;YACnG,oGAAoG;YACpG,UAAU;QACZ,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC;YACxB,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oCAAoC,EAAE;gBAC/E,OAAO,EAAE;oBACP,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBACzB,WAAW,EAAE,yDAAyD;iBACvE;gBACD,gBAAgB,EAAE;oBAChB,IAAI,EAAE,SAAS;oBACf,WAAW,EAAE,yFAAyF;iBACvG;aACF;YACD,QAAQ,EAAE,CAAC,UAAU,CAAC;YACtB,oBAAoB,EAAE,KAAK;SAC5B,CAAC;KACH,CAAC;IACF,MAAM,CAAC,MAAM,CAAC;QACZ,IAAI,EAAE,cAAc;QACpB,WAAW,EACT,qGAAqG;YACrG,0FAA0F;QAC5F,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC;YACxB,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,gBAAgB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,WAAW,EAAE,wBAAwB,EAAE;gBACxF,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,wCAAwC,EAAE;aAClF;YACD,QAAQ,EAAE,CAAC,kBAAkB,EAAE,QAAQ,CAAC;YACxC,oBAAoB,EAAE,KAAK;SAC5B,CAAC;KACH,CAAC;IACF,MAAM,CAAC,MAAM,CAAC;QACZ,IAAI,EAAE,aAAa;QACnB,WAAW,EACT,+FAA+F;YAC/F,qGAAqG;YACrG,yCAAyC;QAC3C,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC;YACxB,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,KAAK,EAAE;oBACL,IAAI,EAAE,OAAO;oBACb,WAAW,EAAE,mCAAmC;oBAChD,KAAK,EAAE;wBACL,IAAI,EAAE,QAAQ;wBACd,UAAU,EAAE;4BACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,4CAA4C,EAAE;4BACtF,MAAM,EAAE;gCACN,IAAI,EAAE,QAAQ;gCACd,IAAI,EAAE,CAAC,SAAS,EAAE,aAAa,EAAE,WAAW,CAAC;gCAC7C,WAAW,EAAE,wBAAwB;6BACtC;yBACF;wBACD,QAAQ,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC;wBAC/B,oBAAoB,EAAE,KAAK;qBAC5B;iBACF;aACF;YACD,QAAQ,EAAE,CAAC,OAAO,CAAC;YACnB,oBAAoB,EAAE,KAAK;SAC5B,CAAC;KACH,CAAC;CACH,CAAC,CAAC;AAEH,qDAAqD;AACrD,MAAM,CAAC,MAAM,gBAAgB,GAA2B,MAAM,CAAC,MAAM,CACnE,sBAAsB,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAC5D,CAAC;AAeF,sHAAsH;AACtH,MAAM,CAAC,MAAM,4BAA4B,GAAG,uDAAuD,CAAC;AAEpG,MAAM,gBAAgB,GAA8B,CAAC,SAAS,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;AAO5F,gGAAgG;AAChG,MAAM,oBAAoB,GAAG,qFAAqF,CAAC;AAEnH,6FAA6F;AAC7F,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAQ,gBAAsC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,aAAqB;IAC5D,MAAM,MAAM,GAAG,oBAAoB,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IAC/D,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC;IAChC,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IACpC,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1D,OAAO,gBAAgB,CAAC,UAAU,EAAE,qCAAqC,CAAC,CAAC;IAC7E,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IACxC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QAC9G,OAAO,gBAAgB,CAAC,UAAU,EAAE,6CAA6C,CAAC,CAAC;IACrF,CAAC;IACD,MAAM,cAAc,GAAG,MAAM,CAAC,kBAAkB,CAAC,IAAI,IAAI,CAAC;IAC1D,IAAI,OAAO,cAAc,KAAK,SAAS,EAAE,CAAC;QACxC,OAAO,gBAAgB,CAAC,UAAU,EAAE,oCAAoC,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO;QACL,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAmB,EAAE,cAAc,EAAE,cAAc,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;KAC9G,CAAC;AACJ,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,4BAA4B,CAC1C,aAAqB,EACrB,qBAA6B;IAE7B,MAAM,MAAM,GAAG,oBAAoB,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;IACnE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC;IAChC,MAAM,eAAe,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACnD,IAAI,OAAO,eAAe,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,CAAC;QAC9E,OAAO,gBAAgB,CAAC,cAAc,EAAE,qCAAqC,CAAC,CAAC;IACjF,CAAC;IACD,IAAI,eAAe,GAAG,CAAC,IAAI,eAAe,GAAG,qBAAqB,EAAE,CAAC;QACnE,OAAO,gBAAgB,CAAC,cAAc,EAAE,0CAA0C,qBAAqB,EAAE,CAAC,CAAC;IAC7G,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChC,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,gBAAgB,CAAC,cAAc,EAAE,yBAAyB,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,EAAE,CAAC;AACnE,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,2BAA2B,CAAC,aAAqB;IAC/D,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,YAAY,CAAC,iCAAiC,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3E,OAAO,YAAY,CAAC,iCAAiC,CAAC,CAAC;IACzD,CAAC;IACD,MAAM,CAAC,WAAW,CAAC,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC;IAC9F,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,YAAY,CAAC,oBAAoB,WAAW,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,MAAM,KAAK,GAAI,MAA4C,CAAC,OAAO,CAAC,CAAC;IACrE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,YAAY,CAAC,sBAAsB,CAAC,CAAC;IAC9C,CAAC;IACD,MAAM,KAAK,GAAoB,EAAE,CAAC;IAClC,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC5C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACrE,OAAO,YAAY,CAAC,SAAS,KAAK,qBAAqB,CAAC,CAAC;QAC3D,CAAC;QACD,MAAM,CAAC,YAAY,CAAC,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC;QACpH,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,YAAY,CAAC,SAAS,KAAK,uBAAuB,YAAY,EAAE,CAAC,CAAC;QAC3E,CAAC;QACD,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAyC,CAAC;QACtE,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;YACxD,OAAO,YAAY,CAAC,SAAS,KAAK,sCAAsC,CAAC,CAAC;QAC5E,CAAC;QACD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAE,gBAAsC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5F,OAAO,YAAY,CAAC,SAAS,KAAK,qDAAqD,CAAC,CAAC;QAC3F,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAwB,EAAE,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AAC7C,CAAC;AAED,2GAA2G;AAC3G,MAAM,UAAU,sBAAsB,CAAC,QAAgB,EAAE,SAAiB;IACxE,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC;AAChF,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,sBAAsB,CAAC,QAAgB;IACrD,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;AACzD,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,2BAA2B,CAAC,MAAc;IACxD,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC;AACxD,CAAC;AAED,yHAAyH;AACzH,MAAM,UAAU,+BAA+B,CAAC,aAAqB,EAAE,MAAc;IACnF,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC;AACxF,CAAC;AAED,SAAS,YAAY,CAAC,MAAc;IAClC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,kBAAkB,MAAM,EAAE,EAAE,CAAC;AAC/D,CAAC;AAED,qGAAqG;AACrG,SAAS,eAAe,CAAC,KAAwB;IAC/C,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;AAC7C,CAAC;AAED,uGAAuG;AACvG,SAAS,kBAAkB,CAAC,IAAY,EAAE,KAAa;IACrD,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACtF,MAAM,eAAe,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACxF,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;IAC7E,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,YAAY,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACrD,MAAM,UAAU,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAChF,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO,UAAU,CAAC;QACpB,CAAC;IACH,CAAC;IACD,OAAO,cAAc,CAAC,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC;AACxD,CAAC;AAED,SAAS,oBAAoB,CAC3B,WAAwB,EACxB,aAAqB;IAErB,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,gBAAgB,CAAC,WAAW,EAAE,iCAAiC,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3E,OAAO,gBAAgB,CAAC,WAAW,EAAE,iCAAiC,CAAC,CAAC;IAC1E,CAAC;IACD,MAAM,UAAU,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;IAC9F,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,YAAY,CAAC,IAAI,EAAE,CAAW,CAAC,CAAC;IACzF,MAAM,CAAC,WAAW,CAAC,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1G,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,gBAAgB,CAAC,WAAW,EAAE,oBAAoB,WAAW,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAA2C,EAAE,CAAC;AACnF,CAAC;AAED,SAAS,gBAAgB,CAAC,WAAwB,EAAE,MAAc;IAChE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,WAAW,eAAe,MAAM,EAAE,EAAE,CAAC;AAClF,CAAC"}
@@ -0,0 +1,108 @@
1
+ import type { AgentEventWriter, AgentFrameworkRunner, DeferredToolOutcome, ModelCallMetadata } from "./agent-framework-runner.js";
2
+ import type { AgentMessage, AgentUsage, ContextSummary, SessionSettings } from "./agent-session-values.js";
3
+ /**
4
+ * When a session summarizes its earlier messages so the model input stays under the context window, passed
5
+ * as {@link AgentSessionOptions.compaction} or as `AgentDefinition.compaction` for a Stepwise agent.
6
+ *
7
+ * Before each model call, `RunModel` asks the runner for the size of the next model input. When it reaches
8
+ * {@link triggerRatio} of {@link contextWindowTokens}, `RunModel` makes no model call and moves to
9
+ * `CompactContext`, which folds the earlier messages into a {@link ContextSummary}, then back to
10
+ * `RunModel`. The runner must implement {@link AgentFrameworkRunner.estimateInputTokens},
11
+ * {@link AgentFrameworkRunner.selectCompactionCutoff}, and {@link AgentFrameworkRunner.summarizeContext};
12
+ * `createAgentSessionFlow` throws otherwise. Summarized messages stay stored until
13
+ * `AgentSessionOptions.retainedMessageLimit` deletes them; only the model input changes. Enable
14
+ * compaction only after every Worker of the Flow type runs a release with the `CompactContext` Step.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * const flow = createAgentSessionFlow(runner, "SupportAgent", {
19
+ * compaction: { contextWindowTokens: 400_000 },
20
+ * });
21
+ * ```
22
+ */
23
+ export interface CompactionPolicy {
24
+ /** The model's context window, in the tokens that the runner's `estimateInputTokens` counts. */
25
+ readonly contextWindowTokens: number;
26
+ /** Share of the window at which the session compacts before the next model call. Defaults to 0.85. */
27
+ readonly triggerRatio?: number;
28
+ /** Share of the window that the newest messages may keep unsummarized. Defaults to 0.3. */
29
+ readonly retainedRatio?: number;
30
+ }
31
+ /** A {@link CompactionPolicy} with every default filled in. */
32
+ export interface ResolvedCompactionPolicy {
33
+ /** The model's context window in tokens. */
34
+ readonly contextWindowTokens: number;
35
+ /** Share of the window at which the session compacts. */
36
+ readonly triggerRatio: number;
37
+ /** Share of the window that the newest messages may keep. */
38
+ readonly retainedRatio: number;
39
+ }
40
+ /** What {@link AgentFrameworkRunner.summarizeContext} receives: the messages to fold into a new summary. */
41
+ export interface ContextSummaryRequest {
42
+ /** Flow ID, which is the session ID. */
43
+ readonly flowId: string;
44
+ /** Turn ID of the running turn. */
45
+ readonly turnId: string;
46
+ /** One-based `CompactContext` attempt. */
47
+ readonly attempt: number;
48
+ /** Dex Step execution ID of the `CompactContext` Step, shared by all of its attempts. */
49
+ readonly stepExecutionId: string;
50
+ /** The summary so far, or `null` for the first one. Fold its text into the new summary. */
51
+ readonly previousSummary: ContextSummary | null;
52
+ /**
53
+ * The messages after the previous summary through {@link throughSequence}, in sequence order. No tool
54
+ * call is separated from its result.
55
+ */
56
+ readonly messages: readonly AgentMessage[];
57
+ /** Sequence of the last message to summarize. */
58
+ readonly throughSequence: number;
59
+ /** Events writer bound to the turn and attempt. Write no model text to it: the summary is not an answer. */
60
+ readonly events: AgentEventWriter;
61
+ /** Signal aborted when Dex cancels the attempt; pass it to the model call. */
62
+ readonly cancellationSignal: AbortSignal;
63
+ /** Absolute deadline of the current attempt, or `undefined` when Dex supplied none. */
64
+ readonly deadline: Date | undefined;
65
+ /**
66
+ * Tokens the summary call may use, the policy's `contextWindowTokens`, or `undefined` for no limit. A runner
67
+ * keeps the input below it, less what it reserves for the summary, such as its `maxOutputTokens`. The range
68
+ * can be larger after the window shrank or when compaction starts on a long session;
69
+ * leave out its oldest part rather than send an over-window request that fails every turn.
70
+ */
71
+ readonly inputTokenBudget?: number;
72
+ /**
73
+ * The {@link SessionSettings} the running turn started with, as `AgentTurnContext.sessionSettings` has them.
74
+ * Use them to choose the model that writes the summary. The session always sets it; treat `undefined` as `{}`.
75
+ */
76
+ readonly sessionSettings?: SessionSettings;
77
+ /**
78
+ * Records a heartbeat. The session already records one every 20 seconds while the summary runs.
79
+ * @returns A Promise that resolves when the Worker accepted the heartbeat.
80
+ */
81
+ heartbeat(): Promise<void>;
82
+ }
83
+ /** What {@link AgentFrameworkRunner.summarizeContext} returns. */
84
+ export interface ContextSummaryResult {
85
+ /** Summary text; it must not be blank. It replaces the previous summary, so it includes what that one said. */
86
+ readonly text: string;
87
+ /** Usage of the summary model call; the session adds it to the session's usage. */
88
+ readonly usage: AgentUsage;
89
+ /**
90
+ * Model and response of the summary call, for the `CompactContext` attempt's `chat` span. When omitted,
91
+ * the span is named `chat`.
92
+ */
93
+ readonly modelCallMetadata?: ModelCallMetadata;
94
+ }
95
+ /** A runner that implements the three optional compaction methods. */
96
+ export type ContextCompactionRunner = AgentFrameworkRunner<DeferredToolOutcome> & Required<Pick<AgentFrameworkRunner<DeferredToolOutcome>, "estimateInputTokens" | "selectCompactionCutoff" | "summarizeContext">>;
97
+ /** Reports whether a runner implements every compaction method. */
98
+ export declare function isContextCompactionRunner(runner: AgentFrameworkRunner<DeferredToolOutcome>): runner is ContextCompactionRunner;
99
+ /**
100
+ * Fills in a compaction policy's defaults and checks it.
101
+ * @throws {RangeError} When `contextWindowTokens` is not a positive integer, or unless
102
+ * `0 < retainedRatio < triggerRatio <= 1`.
103
+ */
104
+ export declare function resolveCompactionPolicy(policy: CompactionPolicy): ResolvedCompactionPolicy;
105
+ /** Reports whether a model input of this size makes the session compact before the model call. */
106
+ export declare function isCompactionTriggered(policy: ResolvedCompactionPolicy, estimatedInputTokens: number): boolean;
107
+ /** Tokens that the newest messages may keep after compaction: the retained share of the window, rounded down. */
108
+ export declare function readRetainedTokenBudget(policy: ResolvedCompactionPolicy): number;
@@ -0,0 +1,39 @@
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
+ /** Reports whether a runner implements every compaction method. */
9
+ export function isContextCompactionRunner(runner) {
10
+ return (typeof runner.estimateInputTokens === "function" &&
11
+ typeof runner.selectCompactionCutoff === "function" &&
12
+ typeof runner.summarizeContext === "function");
13
+ }
14
+ /**
15
+ * Fills in a compaction policy's defaults and checks it.
16
+ * @throws {RangeError} When `contextWindowTokens` is not a positive integer, or unless
17
+ * `0 < retainedRatio < triggerRatio <= 1`.
18
+ */
19
+ export function resolveCompactionPolicy(policy) {
20
+ const contextWindowTokens = policy.contextWindowTokens;
21
+ if (!Number.isSafeInteger(contextWindowTokens) || contextWindowTokens <= 0) {
22
+ throw new RangeError("compaction.contextWindowTokens must be a positive integer");
23
+ }
24
+ const triggerRatio = policy.triggerRatio ?? 0.85;
25
+ const retainedRatio = policy.retainedRatio ?? 0.3;
26
+ if (!(retainedRatio > 0 && retainedRatio < triggerRatio && triggerRatio <= 1)) {
27
+ throw new RangeError("compaction needs 0 < retainedRatio < triggerRatio <= 1");
28
+ }
29
+ return Object.freeze({ contextWindowTokens, triggerRatio, retainedRatio });
30
+ }
31
+ /** Reports whether a model input of this size makes the session compact before the model call. */
32
+ export function isCompactionTriggered(policy, estimatedInputTokens) {
33
+ return estimatedInputTokens >= policy.triggerRatio * policy.contextWindowTokens;
34
+ }
35
+ /** Tokens that the newest messages may keep after compaction: the retained share of the window, rounded down. */
36
+ export function readRetainedTokenBudget(policy) {
37
+ return Math.floor(policy.retainedRatio * policy.contextWindowTokens);
38
+ }
39
+ //# 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":"AAAA,yCAAyC;AACzC,EAAE;AACF,kDAAkD;AAClD,mEAAmE;AACnE,+CAA+C;AAC/C,EAAE;AACF,0DAA0D;AAgH1D,mEAAmE;AACnE,MAAM,UAAU,yBAAyB,CACvC,MAAiD;IAEjD,OAAO,CACL,OAAO,MAAM,CAAC,mBAAmB,KAAK,UAAU;QAChD,OAAO,MAAM,CAAC,sBAAsB,KAAK,UAAU;QACnD,OAAO,MAAM,CAAC,gBAAgB,KAAK,UAAU,CAC9C,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAwB;IAC9D,MAAM,mBAAmB,GAAG,MAAM,CAAC,mBAAmB,CAAC;IACvD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,mBAAmB,CAAC,IAAI,mBAAmB,IAAI,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,UAAU,CAAC,2DAA2D,CAAC,CAAC;IACpF,CAAC;IACD,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,IAAI,CAAC;IACjD,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,IAAI,GAAG,CAAC;IAClD,IAAI,CAAC,CAAC,aAAa,GAAG,CAAC,IAAI,aAAa,GAAG,YAAY,IAAI,YAAY,IAAI,CAAC,CAAC,EAAE,CAAC;QAC9E,MAAM,IAAI,UAAU,CAAC,wDAAwD,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,mBAAmB,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC,CAAC;AAC7E,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,qBAAqB,CAAC,MAAgC,EAAE,oBAA4B;IAClG,OAAO,oBAAoB,IAAI,MAAM,CAAC,YAAY,GAAG,MAAM,CAAC,mBAAmB,CAAC;AAClF,CAAC;AAED,iHAAiH;AACjH,MAAM,UAAU,uBAAuB,CAAC,MAAgC;IACtE,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC;AACvE,CAAC"}