@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,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":"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"}
@@ -0,0 +1,254 @@
1
+ import type { AgentEventWriter, AgentFrameworkRunner, AgentTurnContext, 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
+ * Tokens of every model input that the runner's estimate cannot see, such as a system prompt that a
32
+ * framework builds, a dynamic instruction, or tools listed at run time. The session adds them to the
33
+ * estimate. Defaults to 0.
34
+ * @since 0.3.0
35
+ */
36
+ readonly reservedInputTokens?: number;
37
+ }
38
+ /** A {@link CompactionPolicy} with every default filled in. */
39
+ export interface ResolvedCompactionPolicy {
40
+ /** The model's context window in tokens. */
41
+ readonly contextWindowTokens: number;
42
+ /** Share of the window at which the session compacts. */
43
+ readonly triggerRatio: number;
44
+ /** Share of the window that the newest messages may keep. */
45
+ readonly retainedRatio: number;
46
+ /**
47
+ * Tokens added to every estimate. `undefined` reads as 0.
48
+ * @since 0.3.0
49
+ */
50
+ readonly reservedInputTokens?: number;
51
+ }
52
+ /** First line of the user text that carries the {@link ContextSummary} into the model input. */
53
+ export declare const contextSummaryNoteHeader = "[Dex] Summary of the earlier conversation:";
54
+ /** Instructions of the model call that writes a {@link ContextSummary}. */
55
+ export declare const contextSummaryInstructions: string;
56
+ /** Last user text of the model call that writes a {@link ContextSummary}. */
57
+ export declare const contextSummaryRequest = "[Dex] Summarize the conversation above. Reply with the summary only.";
58
+ /**
59
+ * First line of the transcript in the prompt of {@link buildContextSummaryPrompt}.
60
+ * @since 0.3.0
61
+ */
62
+ export declare const contextSummaryTranscriptHeader = "[Dex] The conversation to summarize:";
63
+ /**
64
+ * The most tokens {@link buildContextSummaryPrompt} leaves free for the summary it asks for.
65
+ * @since 0.3.0
66
+ */
67
+ export declare const contextSummaryOutputTokens = 4096;
68
+ /**
69
+ * Returns the user text that says how many of the oldest messages a summary request left out.
70
+ * @param omittedCount - Messages left out, at least 1.
71
+ * @returns `[Dex] <omittedCount> earlier messages did not fit in this request and are left out.`, or
72
+ * `[Dex] 1 earlier message did not fit in this request and is left out.` for one message.
73
+ */
74
+ export declare function buildContextSummaryOmissionNote(omittedCount: number): string;
75
+ /**
76
+ * Returns the user text that puts a summary before the newer messages in a model input.
77
+ * @param summary - The session's summary.
78
+ * @returns {@link contextSummaryNoteHeader}, a newline, and the summary text.
79
+ */
80
+ export declare function buildContextSummaryNote(summary: ContextSummary): string;
81
+ /**
82
+ * Estimates the tokens of a text without a tokenizer, rounding up.
83
+ *
84
+ * Use it where a framework assembles the prompt and offers no token counter. It counts one token per three UTF-8
85
+ * bytes. That is more than a provider counts for English text, and about one token per CJK character, so the
86
+ * estimate errs toward compacting early.
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * estimateTextTokens("twelve bytes"); // 4
91
+ * ```
92
+ * @param text - The text to measure.
93
+ * @returns The estimated tokens; 0 for an empty text.
94
+ * @since 0.3.0
95
+ */
96
+ export declare function estimateTextTokens(text: string): number;
97
+ /**
98
+ * Estimates a model input that a framework builds from the stored items.
99
+ *
100
+ * Call it from `estimateInputTokens` of a framework adapter. It measures each `frameworkItem` as stored, so JSON
101
+ * syntax and opaque provider items count too, plus the summary and any `frameworkRunState`.
102
+ *
103
+ * @example
104
+ * ```ts
105
+ * public estimateInputTokens(turn: AgentTurnContext): number {
106
+ * return estimateStoredInputTokens(turn, estimateTextTokens(this.instructions));
107
+ * }
108
+ * ```
109
+ * @param turn - The context of the next model call.
110
+ * @param fixedInputTokens - Tokens of what every request repeats, such as instructions and tool definitions.
111
+ * Measure what the framework shows; `CompactionPolicy.reservedInputTokens` covers the rest. Defaults to 0.
112
+ * @returns The estimated input tokens.
113
+ * @since 0.3.0
114
+ */
115
+ export declare function estimateStoredInputTokens(turn: AgentTurnContext, fixedInputTokens?: number): number;
116
+ /**
117
+ * Chooses the last message to summarize, cutting only between turns.
118
+ *
119
+ * Call it from `selectCompactionCutoff` of a framework adapter. A turn's messages are stored together, so a cut
120
+ * between turns never separates a tool call from its result and never splits a model response, whatever
121
+ * framework items the turn holds. The running turn is always kept, because the adapter reads its opening user
122
+ * message from `turn.messages`.
123
+ *
124
+ * It returns `null` while `turn.frameworkRunState` is set. A resumed model call continues from that value, which
125
+ * may already hold the older messages, so the summary could not replace them. Compaction waits for the next turn.
126
+ *
127
+ * @example
128
+ * ```ts
129
+ * public selectCompactionCutoff(turn: AgentTurnContext, retainedTokenBudget: number): number | null {
130
+ * return selectTurnBoundaryCutoff(turn, retainedTokenBudget);
131
+ * }
132
+ * ```
133
+ * @param turn - The context of the model call that crossed the threshold.
134
+ * @param retainedTokenBudget - Tokens that the kept messages may use.
135
+ * @returns The sequence of the last message to summarize: the earliest turn boundary whose kept messages fit the
136
+ * budget, else the boundary before the running turn. `null` when the turn is resuming, every message already
137
+ * fits, or no earlier turn is left to summarize.
138
+ * @since 0.3.0
139
+ */
140
+ export declare function selectTurnBoundaryCutoff(turn: AgentTurnContext, retainedTokenBudget: number): number | null;
141
+ /**
142
+ * Returns a stored message as the plain text a summary prompt shows.
143
+ *
144
+ * Wrap it in the `describeMessage` of {@link buildContextSummaryPrompt} to leave out items that only a provider can
145
+ * read.
146
+ *
147
+ * @param message - The stored message.
148
+ * @returns Its role and text, tool arguments, and tool output. A message with none of them returns its role and
149
+ * `frameworkItem`, such as a model response with several tool calls.
150
+ * @since 0.3.0
151
+ */
152
+ export declare function describeStoredMessage(message: AgentMessage): string;
153
+ /**
154
+ * Builds the one user prompt of a summary call for a framework adapter.
155
+ *
156
+ * Call it from `summarizeContext` and send the result with {@link contextSummaryInstructions} and no tools. The
157
+ * prompt holds the previous summary, the messages as plain text, and {@link contextSummaryRequest}. Plain text
158
+ * works with any framework: it needs no tool definitions, and no provider sees an item out of its place.
159
+ *
160
+ * The prompt fits `request.inputTokenBudget`, less room for the summary, as {@link estimateTextTokens} counts.
161
+ * When the range is too large, it leaves out the oldest messages and says so with
162
+ * {@link buildContextSummaryOmissionNote}. It shortens a single message only when that message alone is too
163
+ * large.
164
+ *
165
+ * @example
166
+ * ```ts
167
+ * public async summarizeContext(request: ContextSummaryRequest): Promise<ContextSummaryResult> {
168
+ * const result = await generateText({
169
+ * model,
170
+ * system: contextSummaryInstructions,
171
+ * prompt: buildContextSummaryPrompt(request),
172
+ * });
173
+ * return { text: result.text, usage: toAgentUsage(result.usage) };
174
+ * }
175
+ * ```
176
+ * @param request - The previous summary and the messages to summarize.
177
+ * @param describeMessage - Returns a message's text for the prompt, or `null` to leave it out, such as an
178
+ * encrypted reasoning item. Defaults to {@link describeStoredMessage}.
179
+ * @returns The prompt text.
180
+ * @since 0.3.0
181
+ */
182
+ export declare function buildContextSummaryPrompt(request: ContextSummaryRequest, describeMessage?: (message: AgentMessage) => string | null): string;
183
+ /** What {@link AgentFrameworkRunner.summarizeContext} receives: the messages to fold into a new summary. */
184
+ export interface ContextSummaryRequest {
185
+ /** Flow ID, which is the session ID. */
186
+ readonly flowId: string;
187
+ /** Turn ID of the running turn. */
188
+ readonly turnId: string;
189
+ /** One-based `CompactContext` attempt. */
190
+ readonly attempt: number;
191
+ /** Dex Step execution ID of the `CompactContext` Step, shared by all of its attempts. */
192
+ readonly stepExecutionId: string;
193
+ /** The summary so far, or `null` for the first one. Fold its text into the new summary. */
194
+ readonly previousSummary: ContextSummary | null;
195
+ /**
196
+ * The messages after the previous summary through {@link throughSequence}, in sequence order. No tool
197
+ * call is separated from its result.
198
+ */
199
+ readonly messages: readonly AgentMessage[];
200
+ /** Sequence of the last message to summarize. */
201
+ readonly throughSequence: number;
202
+ /** Events writer bound to the turn and attempt. Write no model text to it: the summary is not an answer. */
203
+ readonly events: AgentEventWriter;
204
+ /** Signal aborted when Dex cancels the attempt; pass it to the model call. */
205
+ readonly cancellationSignal: AbortSignal;
206
+ /** Absolute deadline of the current attempt, or `undefined` when Dex supplied none. */
207
+ readonly deadline: Date | undefined;
208
+ /**
209
+ * Tokens the summary call may use, the policy's `contextWindowTokens`, or `undefined` for no limit. A runner
210
+ * keeps the input below it, less what it reserves for the summary, such as its `maxOutputTokens`. The range
211
+ * can be larger after the window shrank or when compaction starts on a long session;
212
+ * leave out its oldest part rather than send an over-window request that fails every turn.
213
+ */
214
+ readonly inputTokenBudget?: number;
215
+ /**
216
+ * The {@link SessionSettings} the running turn started with, as `AgentTurnContext.sessionSettings` has them.
217
+ * Use them to choose the model that writes the summary. The session always sets it; treat `undefined` as `{}`.
218
+ */
219
+ readonly sessionSettings?: SessionSettings;
220
+ /**
221
+ * Records a heartbeat. The session already records one every 20 seconds while the summary runs.
222
+ * @returns A Promise that resolves when the Worker accepted the heartbeat.
223
+ */
224
+ heartbeat(): Promise<void>;
225
+ }
226
+ /** What {@link AgentFrameworkRunner.summarizeContext} returns. */
227
+ export interface ContextSummaryResult {
228
+ /** Summary text; it must not be blank. It replaces the previous summary, so it includes what that one said. */
229
+ readonly text: string;
230
+ /** Usage of the summary model call; the session adds it to the session's usage. */
231
+ readonly usage: AgentUsage;
232
+ /**
233
+ * Model and response of the summary call, for the `CompactContext` attempt's `chat` span. When omitted,
234
+ * the span is named `chat`.
235
+ */
236
+ readonly modelCallMetadata?: ModelCallMetadata;
237
+ }
238
+ /** A runner that implements the three optional compaction methods. */
239
+ export type ContextCompactionRunner = AgentFrameworkRunner<DeferredToolOutcome> & Required<Pick<AgentFrameworkRunner<DeferredToolOutcome>, "estimateInputTokens" | "selectCompactionCutoff" | "summarizeContext">>;
240
+ /** Reports whether a runner implements every compaction method. */
241
+ export declare function isContextCompactionRunner(runner: AgentFrameworkRunner<DeferredToolOutcome>): runner is ContextCompactionRunner;
242
+ /**
243
+ * Fills in a compaction policy's defaults and checks it.
244
+ * @throws {RangeError} When `contextWindowTokens` is not a positive integer, `reservedInputTokens` is not an
245
+ * integer from 0 to below the window, or unless `0 < retainedRatio < triggerRatio <= 1`.
246
+ */
247
+ export declare function resolveCompactionPolicy(policy: CompactionPolicy): ResolvedCompactionPolicy;
248
+ /**
249
+ * Reports whether a model input of this size makes the session compact before the model call: the estimate
250
+ * plus `reservedInputTokens` reaches `triggerRatio` of the window.
251
+ */
252
+ export declare function isCompactionTriggered(policy: ResolvedCompactionPolicy, estimatedInputTokens: number): boolean;
253
+ /** Tokens that the newest messages may keep after compaction: the retained share of the window, rounded down. */
254
+ export declare function readRetainedTokenBudget(policy: ResolvedCompactionPolicy): number;