@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.
- package/README.md +1608 -64
- package/dist/src/agent-built-in-tools.d.ts +81 -0
- package/dist/src/agent-built-in-tools.js +246 -0
- package/dist/src/agent-built-in-tools.js.map +1 -0
- package/dist/src/agent-context-compaction.d.ts +254 -0
- package/dist/src/agent-context-compaction.js +287 -0
- package/dist/src/agent-context-compaction.js.map +1 -0
- package/dist/src/agent-framework-runner.d.ts +456 -16
- package/dist/src/agent-framework-runner.js +4 -3
- package/dist/src/agent-framework-runner.js.map +1 -1
- package/dist/src/agent-plans.d.ts +48 -0
- package/dist/src/agent-plans.js +86 -0
- package/dist/src/agent-plans.js.map +1 -0
- package/dist/src/agent-session-cancellation-steps.d.ts +28 -0
- package/dist/src/agent-session-cancellation-steps.js +154 -0
- package/dist/src/agent-session-cancellation-steps.js.map +1 -0
- package/dist/src/agent-session-codecs.d.ts +65 -4
- package/dist/src/agent-session-codecs.js +343 -8
- package/dist/src/agent-session-codecs.js.map +1 -1
- package/dist/src/agent-session-failure.d.ts +58 -0
- package/dist/src/agent-session-failure.js +126 -0
- package/dist/src/agent-session-failure.js.map +1 -0
- package/dist/src/agent-session-flow-graph-cli.d.ts +2 -0
- package/dist/src/agent-session-flow-graph-cli.js +47 -0
- package/dist/src/agent-session-flow-graph-cli.js.map +1 -0
- package/dist/src/agent-session-flow-graph.d.ts +38 -0
- package/dist/src/agent-session-flow-graph.js +54 -0
- package/dist/src/agent-session-flow-graph.js.map +1 -0
- package/dist/src/agent-session-flow-graph.json +2187 -0
- package/dist/src/agent-session-flow.d.ts +317 -28
- package/dist/src/agent-session-flow.js +373 -21
- package/dist/src/agent-session-flow.js.map +1 -1
- package/dist/src/agent-session-persistence.d.ts +81 -4
- package/dist/src/agent-session-persistence.js +33 -2
- package/dist/src/agent-session-persistence.js.map +1 -1
- package/dist/src/agent-session-settings.d.ts +58 -0
- package/dist/src/agent-session-settings.js +81 -0
- package/dist/src/agent-session-settings.js.map +1 -0
- package/dist/src/agent-session-spend-limit.d.ts +156 -0
- package/dist/src/agent-session-spend-limit.js +42 -0
- package/dist/src/agent-session-spend-limit.js.map +1 -0
- package/dist/src/agent-session-start.d.ts +49 -0
- package/dist/src/agent-session-start.js +67 -0
- package/dist/src/agent-session-start.js.map +1 -0
- package/dist/src/agent-session-step-options.d.ts +78 -0
- package/dist/src/agent-session-step-options.js +71 -0
- package/dist/src/agent-session-step-options.js.map +1 -0
- package/dist/src/agent-session-step-types.d.ts +20 -0
- package/dist/src/agent-session-step-types.js +28 -0
- package/dist/src/agent-session-step-types.js.map +1 -0
- package/dist/src/agent-session-steps.d.ts +103 -8
- package/dist/src/agent-session-steps.js +997 -197
- package/dist/src/agent-session-steps.js.map +1 -1
- package/dist/src/agent-session-tracer.d.ts +61 -0
- package/dist/src/agent-session-tracer.js +608 -0
- package/dist/src/agent-session-tracer.js.map +1 -0
- package/dist/src/agent-session-transitions.d.ts +200 -26
- package/dist/src/agent-session-transitions.js +732 -32
- package/dist/src/agent-session-transitions.js.map +1 -1
- package/dist/src/agent-session-values.d.ts +696 -30
- package/dist/src/agent-session-values.js +39 -4
- package/dist/src/agent-session-values.js.map +1 -1
- package/dist/src/agent-session-wait-steps.d.ts +53 -0
- package/dist/src/agent-session-wait-steps.js +389 -0
- package/dist/src/agent-session-wait-steps.js.map +1 -0
- package/dist/src/agent-tracing-options.d.ts +107 -0
- package/dist/src/agent-tracing-options.js +20 -0
- package/dist/src/agent-tracing-options.js.map +1 -0
- package/dist/src/ai-sdk/ai-sdk-model-client.d.ts +40 -0
- package/dist/src/ai-sdk/ai-sdk-model-client.js +235 -0
- package/dist/src/ai-sdk/ai-sdk-model-client.js.map +1 -0
- package/dist/src/ai-sdk/index.d.ts +1 -0
- package/dist/src/ai-sdk/index.js +9 -0
- package/dist/src/ai-sdk/index.js.map +1 -0
- package/dist/src/index.d.ts +14 -3
- package/dist/src/index.js +12 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/index.d.ts +3 -0
- package/dist/src/mcp/index.js +10 -0
- package/dist/src/mcp/index.js.map +1 -0
- package/dist/src/mcp/mcp-resource-and-prompt-tools.d.ts +29 -0
- package/dist/src/mcp/mcp-resource-and-prompt-tools.js +185 -0
- package/dist/src/mcp/mcp-resource-and-prompt-tools.js.map +1 -0
- package/dist/src/mcp/mcp-server-config.d.ts +86 -0
- package/dist/src/mcp/mcp-server-config.js +38 -0
- package/dist/src/mcp/mcp-server-config.js.map +1 -0
- package/dist/src/mcp/mcp-tool-source.d.ts +470 -0
- package/dist/src/mcp/mcp-tool-source.js +1204 -0
- package/dist/src/mcp/mcp-tool-source.js.map +1 -0
- package/dist/src/stepwise/agent-definition.d.ts +166 -0
- package/dist/src/stepwise/agent-definition.js +9 -0
- package/dist/src/stepwise/agent-definition.js.map +1 -0
- package/dist/src/stepwise/function-tool.d.ts +130 -0
- package/dist/src/stepwise/function-tool.js +75 -0
- package/dist/src/stepwise/function-tool.js.map +1 -0
- package/dist/src/stepwise/index.d.ts +8 -0
- package/dist/src/stepwise/index.js +13 -0
- package/dist/src/stepwise/index.js.map +1 -0
- package/dist/src/stepwise/json-schema-validation.d.ts +9 -0
- package/dist/src/stepwise/json-schema-validation.js +141 -0
- package/dist/src/stepwise/json-schema-validation.js.map +1 -0
- package/dist/src/stepwise/model-client.d.ts +194 -0
- package/dist/src/stepwise/model-client.js +9 -0
- package/dist/src/stepwise/model-client.js.map +1 -0
- package/dist/src/stepwise/scripted-model-client.d.ts +99 -0
- package/dist/src/stepwise/scripted-model-client.js +156 -0
- package/dist/src/stepwise/scripted-model-client.js.map +1 -0
- package/dist/src/stepwise/stepwise-agent-runner.d.ts +171 -0
- package/dist/src/stepwise/stepwise-agent-runner.js +777 -0
- package/dist/src/stepwise/stepwise-agent-runner.js.map +1 -0
- package/dist/src/stepwise/stepwise-agent-session-flow.d.ts +35 -0
- package/dist/src/stepwise/stepwise-agent-session-flow.js +57 -0
- package/dist/src/stepwise/stepwise-agent-session-flow.js.map +1 -0
- package/dist/src/stepwise/stepwise-input-items.d.ts +12 -0
- package/dist/src/stepwise/stepwise-input-items.js +172 -0
- package/dist/src/stepwise/stepwise-input-items.js.map +1 -0
- package/dist/src/stepwise/tool-source.d.ts +103 -0
- package/dist/src/stepwise/tool-source.js +9 -0
- package/dist/src/stepwise/tool-source.js.map +1 -0
- package/dist/src/testing/agent-session-test-client.d.ts +65 -8
- package/dist/src/testing/agent-session-test-client.js +92 -22
- package/dist/src/testing/agent-session-test-client.js.map +1 -1
- package/dist/src/testing/context-window.d.ts +194 -0
- package/dist/src/testing/context-window.js +360 -0
- package/dist/src/testing/context-window.js.map +1 -0
- package/dist/src/testing/index.d.ts +2 -0
- package/dist/src/testing/index.js +2 -0
- package/dist/src/testing/index.js.map +1 -1
- package/dist/src/testing/private-dex-engine.d.ts +9 -0
- package/dist/src/testing/private-dex-engine.js +9 -1
- package/dist/src/testing/private-dex-engine.js.map +1 -1
- package/dist/src/testing/scripted-model-client.d.ts +1 -0
- package/dist/src/testing/scripted-model-client.js +10 -0
- package/dist/src/testing/scripted-model-client.js.map +1 -0
- package/dist/src/ui-stream/agent-event-json.d.ts +30 -0
- package/dist/src/ui-stream/agent-event-json.js +64 -0
- package/dist/src/ui-stream/agent-event-json.js.map +1 -0
- package/dist/src/ui-stream/agent-event-sse.d.ts +155 -0
- package/dist/src/ui-stream/agent-event-sse.js +167 -0
- package/dist/src/ui-stream/agent-event-sse.js.map +1 -0
- package/dist/src/ui-stream/agent-event-stream-positions.d.ts +42 -0
- package/dist/src/ui-stream/agent-event-stream-positions.js +153 -0
- package/dist/src/ui-stream/agent-event-stream-positions.js.map +1 -0
- package/dist/src/ui-stream/agent-session-record-reader.d.ts +74 -0
- package/dist/src/ui-stream/agent-session-record-reader.js +246 -0
- package/dist/src/ui-stream/agent-session-record-reader.js.map +1 -0
- package/dist/src/ui-stream/agent-ui-message-stream-responses.d.ts +219 -0
- package/dist/src/ui-stream/agent-ui-message-stream-responses.js +441 -0
- package/dist/src/ui-stream/agent-ui-message-stream-responses.js.map +1 -0
- package/dist/src/ui-stream/agent-ui-message-stream.d.ts +138 -0
- package/dist/src/ui-stream/agent-ui-message-stream.js +695 -0
- package/dist/src/ui-stream/agent-ui-message-stream.js.map +1 -0
- package/dist/src/ui-stream/agent-ui-message-types.d.ts +238 -0
- package/dist/src/ui-stream/agent-ui-message-types.js +57 -0
- package/dist/src/ui-stream/agent-ui-message-types.js.map +1 -0
- package/dist/src/ui-stream/agent-ui-messages.d.ts +68 -0
- package/dist/src/ui-stream/agent-ui-messages.js +222 -0
- package/dist/src/ui-stream/agent-ui-messages.js.map +1 -0
- package/dist/src/ui-stream/agent-ui-stream-cursor.d.ts +64 -0
- package/dist/src/ui-stream/agent-ui-stream-cursor.js +186 -0
- package/dist/src/ui-stream/agent-ui-stream-cursor.js.map +1 -0
- package/dist/src/ui-stream/index.d.ts +14 -0
- package/dist/src/ui-stream/index.js +22 -0
- package/dist/src/ui-stream/index.js.map +1 -0
- package/dist/src/ui-stream/server-sent-event-responses.d.ts +6 -0
- package/dist/src/ui-stream/server-sent-event-responses.js +34 -0
- package/dist/src/ui-stream/server-sent-event-responses.js.map +1 -0
- package/package.json +44 -5
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Attribute, AttributeMap, Channel, ChannelMap, Stream } from "@superdurable/dex";
|
|
2
|
-
import type { AgentEvent, AgentInterrupt, AgentInterruptResolution, AgentMessage, AgentState,
|
|
2
|
+
import type { AgentEvent, AgentInterrupt, AgentInterruptResolution, AgentMessage, AgentMessageChunk, AgentMessageIndex, AgentPlan, AgentState, AgentToolCallRecord, AgentUsage, AgentUserMessage, PlanExecutionRequest, ContextSummary, SessionSettings, TurnReplySequence, TurnSessionSettings, ToolCallCancellation, ToolCallCompleted, TurnCancellationRequest, TurnControlRequest } from "./agent-session-values.js";
|
|
3
3
|
/** Default byte budget of the `AgentEvents` Stream: 10 MiB. */
|
|
4
4
|
export declare const defaultAgentEventsCapacityBytes: number;
|
|
5
5
|
/**
|
|
@@ -19,12 +19,25 @@ export declare const defaultAgentEventsCapacityBytes: number;
|
|
|
19
19
|
export interface AgentSessionPersistence {
|
|
20
20
|
/** The `AgentState` Attribute. It is always set after `StartAgentSession`. */
|
|
21
21
|
readonly agentState: Attribute<AgentState>;
|
|
22
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* The `AgentMessages` AttributeMap: the window of the newest messages, one instance per message, keyed by
|
|
24
|
+
* {@link messageSequenceKey}. Older messages are in {@link agentMessageChunks}; see {@link agentMessageIndex}.
|
|
25
|
+
*/
|
|
23
26
|
readonly agentMessages: AttributeMap<AgentMessage>;
|
|
27
|
+
/**
|
|
28
|
+
* The `AgentMessageChunks` AttributeMap: immutable archive chunks of older messages, keyed by
|
|
29
|
+
* {@link messageSequenceKey} of each chunk's first sequence.
|
|
30
|
+
*/
|
|
31
|
+
readonly agentMessageChunks: AttributeMap<AgentMessageChunk>;
|
|
32
|
+
/**
|
|
33
|
+
* The `AgentMessageIndex` Attribute: where the window and the retained chunks start. A session that a 0.1.0
|
|
34
|
+
* Worker wrote has none until its first write on this version.
|
|
35
|
+
*/
|
|
36
|
+
readonly agentMessageIndex: Attribute<AgentMessageIndex>;
|
|
24
37
|
/** The `FrameworkRunState` Attribute: opaque framework JSON, set only while a turn is suspended. */
|
|
25
38
|
readonly frameworkRunState: Attribute<string>;
|
|
26
39
|
/** The `AgentToolCalls` AttributeMap, keyed by tool call ID; holds only the active turn's records. */
|
|
27
|
-
readonly agentToolCalls: AttributeMap<
|
|
40
|
+
readonly agentToolCalls: AttributeMap<AgentToolCallRecord>;
|
|
28
41
|
/** The `PendingInterrupts` Attribute: interrupts that `resolve_interrupt` still accepts. */
|
|
29
42
|
readonly pendingInterrupts: Attribute<readonly AgentInterrupt[]>;
|
|
30
43
|
/** The `AgentUsage` Attribute: cumulative usage of every turn. */
|
|
@@ -38,12 +51,68 @@ export interface AgentSessionPersistence {
|
|
|
38
51
|
* record becomes final, and `ResumeTurn` consumes them. Applications never publish to it.
|
|
39
52
|
*/
|
|
40
53
|
readonly toolCallResults: Channel<ToolCallCompleted>;
|
|
54
|
+
/** The `SteeredUserMessages` Channel; `steer_user_message` publishes and `ApplyTurnControl` consumes. */
|
|
55
|
+
readonly steeredUserMessages: Channel<AgentUserMessage>;
|
|
56
|
+
/**
|
|
57
|
+
* The internal `TurnControlRequests` Channel. `steer_user_message` and `cancel_turn` publish to it, and its
|
|
58
|
+
* messages only wake `ResumeTurn` or `AwaitUserMessage`.
|
|
59
|
+
*/
|
|
60
|
+
readonly turnControlRequests: Channel<TurnControlRequest>;
|
|
61
|
+
/** The `TurnCancellationRequest` Attribute: the latest `cancel_turn` request. Only `cancel_turn` writes it. */
|
|
62
|
+
readonly turnCancellationRequest: Attribute<TurnCancellationRequest>;
|
|
63
|
+
/**
|
|
64
|
+
* The internal `ToolCallCancellations` ChannelMap, keyed by tool call ID. `ResumeTurn` publishes to it to wake
|
|
65
|
+
* the Step that waits on a call of a steered or cancelled turn.
|
|
66
|
+
*/
|
|
67
|
+
readonly toolCallCancellations: ChannelMap<ToolCallCancellation>;
|
|
41
68
|
/** The best-effort `AgentEvents` Stream. Rebuild durable state with `get_agent_snapshot`. */
|
|
42
69
|
readonly agentEvents: Stream<AgentEvent>;
|
|
70
|
+
/**
|
|
71
|
+
* The `AgentTraceContext` Attribute: the W3C `traceparent` of the current activation's root span when
|
|
72
|
+
* that span has a valid context, sampled or not; an activation whose root has none, such as one without
|
|
73
|
+
* an OpenTelemetry SDK, deletes it. `RunModel` reads it to join the activation's trace.
|
|
74
|
+
*/
|
|
75
|
+
readonly agentTraceContext: Attribute<string>;
|
|
76
|
+
/** The `AgentPlan` Attribute: the session's plan, unset until `write_todos` first succeeds. */
|
|
77
|
+
readonly agentPlan: Attribute<AgentPlan>;
|
|
78
|
+
/**
|
|
79
|
+
* The `PlanExecutions` ChannelMap, keyed by {@link planExecutionKey}: approved plan executions that
|
|
80
|
+
* `execute_plan` publishes and `AwaitUserMessage` consumes.
|
|
81
|
+
*/
|
|
82
|
+
readonly planExecutions: ChannelMap<PlanExecutionRequest>;
|
|
83
|
+
/**
|
|
84
|
+
* The `PendingPlanExecution` Attribute: the execution `execute_plan` accepted and `AwaitUserMessage` has
|
|
85
|
+
* not consumed yet.
|
|
86
|
+
*/
|
|
87
|
+
readonly pendingPlanExecution: Attribute<PlanExecutionRequest>;
|
|
88
|
+
/**
|
|
89
|
+
* The `ContextSummary` Attribute: the summary that replaces the earlier messages in the model input,
|
|
90
|
+
* set once the session compacts. Only `CompactContext` writes it.
|
|
91
|
+
*/
|
|
92
|
+
readonly contextSummary: Attribute<ContextSummary>;
|
|
93
|
+
/**
|
|
94
|
+
* The `SessionSettings` Attribute: the settings the next turn starts with, from the start input and then each
|
|
95
|
+
* `update_session_settings`. Unset when the session has none.
|
|
96
|
+
*/
|
|
97
|
+
readonly sessionSettings: Attribute<SessionSettings>;
|
|
98
|
+
/**
|
|
99
|
+
* The `TurnSessionSettings` Attribute: the settings a turn started with, tagged with its turn, copied from
|
|
100
|
+
* `SessionSettings` when the turn began. A copy from an earlier turn reads as no settings.
|
|
101
|
+
*/
|
|
102
|
+
readonly turnSessionSettings: Attribute<TurnSessionSettings>;
|
|
103
|
+
/**
|
|
104
|
+
* The `TurnReplySequence` Attribute: where the latest turn's replies start, tagged with its turn. The Step
|
|
105
|
+
* that starts a turn writes it; turn events count the replies from it.
|
|
106
|
+
*/
|
|
107
|
+
readonly turnReplySequence: Attribute<TurnReplySequence>;
|
|
43
108
|
}
|
|
44
109
|
export declare function createAgentSessionPersistence(agentEventsCapacityBytes: number): AgentSessionPersistence;
|
|
45
110
|
/**
|
|
46
|
-
* Returns the `AgentMessages` map instance of a message sequence
|
|
111
|
+
* Returns the `AgentMessages` map instance of a message sequence, which is also the `AgentMessageChunks`
|
|
112
|
+
* instance of a chunk that starts at that sequence.
|
|
113
|
+
*
|
|
114
|
+
* A message stays in `AgentMessages` only while it is in the window; read older ones from their chunk, or
|
|
115
|
+
* page through all of them with `list_agent_messages`.
|
|
47
116
|
*
|
|
48
117
|
* @example
|
|
49
118
|
* ```ts
|
|
@@ -54,3 +123,11 @@ export declare function createAgentSessionPersistence(agentEventsCapacityBytes:
|
|
|
54
123
|
* @throws {RangeError} When `sequence` is not a positive safe integer.
|
|
55
124
|
*/
|
|
56
125
|
export declare function messageSequenceKey(sequence: number): string;
|
|
126
|
+
/**
|
|
127
|
+
* Returns the `PlanExecutions` map instance of a plan revision.
|
|
128
|
+
*
|
|
129
|
+
* @param revision - Positive {@link AgentPlan.revision}.
|
|
130
|
+
* @returns The revision as a decimal, such as `"3"`.
|
|
131
|
+
* @throws {RangeError} When `revision` is not a positive safe integer.
|
|
132
|
+
*/
|
|
133
|
+
export declare function planExecutionKey(revision: number): string;
|
|
@@ -6,13 +6,15 @@
|
|
|
6
6
|
//
|
|
7
7
|
// SPDX-License-Identifier: LicenseRef-Sustainable-Use-1.0
|
|
8
8
|
import { Attribute, AttributeMap, Channel, ChannelMap, Stream, stringCodec } from "@superdurable/dex";
|
|
9
|
-
import { agentEventCodec, agentInterruptListCodec, agentInterruptResolutionCodec, agentMessageCodec, agentStateCodec, agentToolCallCodec, agentUsageCodec, agentUserMessageCodec, toolCallCompletedCodec, } from "./agent-session-codecs.js";
|
|
9
|
+
import { agentEventCodec, agentInterruptListCodec, agentInterruptResolutionCodec, agentMessageChunkCodec, agentMessageCodec, agentMessageIndexCodec, agentPlanCodec, agentStateCodec, agentToolCallCodec, agentUsageCodec, agentUserMessageCodec, planExecutionRequestCodec, contextSummaryCodec, sessionSettingsCodec, turnSessionSettingsCodec, turnReplySequenceCodec, toolCallCancellationCodec, toolCallCompletedCodec, turnCancellationRequestCodec, turnControlRequestCodec, } from "./agent-session-codecs.js";
|
|
10
10
|
/** Default byte budget of the `AgentEvents` Stream: 10 MiB. */
|
|
11
11
|
export const defaultAgentEventsCapacityBytes = 10 * 1024 * 1024;
|
|
12
12
|
export function createAgentSessionPersistence(agentEventsCapacityBytes) {
|
|
13
13
|
return {
|
|
14
14
|
agentState: new Attribute("AgentState", agentStateCodec),
|
|
15
15
|
agentMessages: new AttributeMap("AgentMessages", agentMessageCodec),
|
|
16
|
+
agentMessageChunks: new AttributeMap("AgentMessageChunks", agentMessageChunkCodec),
|
|
17
|
+
agentMessageIndex: new Attribute("AgentMessageIndex", agentMessageIndexCodec),
|
|
16
18
|
frameworkRunState: new Attribute("FrameworkRunState", stringCodec),
|
|
17
19
|
agentToolCalls: new AttributeMap("AgentToolCalls", agentToolCallCodec),
|
|
18
20
|
pendingInterrupts: new Attribute("PendingInterrupts", agentInterruptListCodec),
|
|
@@ -20,11 +22,27 @@ export function createAgentSessionPersistence(agentEventsCapacityBytes) {
|
|
|
20
22
|
queuedUserMessages: new Channel("QueuedUserMessages", agentUserMessageCodec),
|
|
21
23
|
interruptResolutions: new ChannelMap("InterruptResolutions", agentInterruptResolutionCodec),
|
|
22
24
|
toolCallResults: new Channel("ToolCallResults", toolCallCompletedCodec),
|
|
25
|
+
steeredUserMessages: new Channel("SteeredUserMessages", agentUserMessageCodec),
|
|
26
|
+
turnControlRequests: new Channel("TurnControlRequests", turnControlRequestCodec),
|
|
27
|
+
turnCancellationRequest: new Attribute("TurnCancellationRequest", turnCancellationRequestCodec),
|
|
28
|
+
toolCallCancellations: new ChannelMap("ToolCallCancellations", toolCallCancellationCodec),
|
|
23
29
|
agentEvents: new Stream("AgentEvents", agentEventCodec, agentEventsCapacityBytes),
|
|
30
|
+
agentTraceContext: new Attribute("AgentTraceContext", stringCodec),
|
|
31
|
+
agentPlan: new Attribute("AgentPlan", agentPlanCodec),
|
|
32
|
+
planExecutions: new ChannelMap("PlanExecutions", planExecutionRequestCodec),
|
|
33
|
+
pendingPlanExecution: new Attribute("PendingPlanExecution", planExecutionRequestCodec),
|
|
34
|
+
contextSummary: new Attribute("ContextSummary", contextSummaryCodec),
|
|
35
|
+
sessionSettings: new Attribute("SessionSettings", sessionSettingsCodec),
|
|
36
|
+
turnSessionSettings: new Attribute("TurnSessionSettings", turnSessionSettingsCodec),
|
|
37
|
+
turnReplySequence: new Attribute("TurnReplySequence", turnReplySequenceCodec),
|
|
24
38
|
};
|
|
25
39
|
}
|
|
26
40
|
/**
|
|
27
|
-
* Returns the `AgentMessages` map instance of a message sequence
|
|
41
|
+
* Returns the `AgentMessages` map instance of a message sequence, which is also the `AgentMessageChunks`
|
|
42
|
+
* instance of a chunk that starts at that sequence.
|
|
43
|
+
*
|
|
44
|
+
* A message stays in `AgentMessages` only while it is in the window; read older ones from their chunk, or
|
|
45
|
+
* page through all of them with `list_agent_messages`.
|
|
28
46
|
*
|
|
29
47
|
* @example
|
|
30
48
|
* ```ts
|
|
@@ -40,4 +58,17 @@ export function messageSequenceKey(sequence) {
|
|
|
40
58
|
}
|
|
41
59
|
return String(sequence).padStart(12, "0");
|
|
42
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Returns the `PlanExecutions` map instance of a plan revision.
|
|
63
|
+
*
|
|
64
|
+
* @param revision - Positive {@link AgentPlan.revision}.
|
|
65
|
+
* @returns The revision as a decimal, such as `"3"`.
|
|
66
|
+
* @throws {RangeError} When `revision` is not a positive safe integer.
|
|
67
|
+
*/
|
|
68
|
+
export function planExecutionKey(revision) {
|
|
69
|
+
if (!Number.isSafeInteger(revision) || revision <= 0) {
|
|
70
|
+
throw new RangeError(`plan revision must be a positive integer: ${revision}`);
|
|
71
|
+
}
|
|
72
|
+
return String(revision);
|
|
73
|
+
}
|
|
43
74
|
//# sourceMappingURL=agent-session-persistence.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-session-persistence.js","sourceRoot":"","sources":["../../src/agent-session-persistence.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,kDAAkD;AAClD,mEAAmE;AACnE,+CAA+C;AAC/C,EAAE;AACF,0DAA0D;AAE1D,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEtG,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,6BAA6B,EAC7B,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,sBAAsB,
|
|
1
|
+
{"version":3,"file":"agent-session-persistence.js","sourceRoot":"","sources":["../../src/agent-session-persistence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { SessionSettings } from "./agent-session-values.js";
|
|
2
|
+
/** Largest {@link SessionSettings}, as the UTF-8 bytes of their compact JSON text: 16 KiB. Same in every core. */
|
|
3
|
+
export declare const MAX_SESSION_SETTINGS_BYTES: number;
|
|
4
|
+
/**
|
|
5
|
+
* Extra bytes the session's own Steps and RPC accept over {@link MAX_SESSION_SETTINGS_BYTES}.
|
|
6
|
+
*
|
|
7
|
+
* The cores write some numbers and characters differently, so settings that one core's Client accepted can
|
|
8
|
+
* measure a few bytes more in another core's Worker. The tolerance keeps that from failing a session.
|
|
9
|
+
* {@link validateSessionSettings} checks the exact limit.
|
|
10
|
+
*/
|
|
11
|
+
export declare const SESSION_SETTINGS_SIZE_TOLERANCE_BYTES = 1024;
|
|
12
|
+
/**
|
|
13
|
+
* Returns the size of session settings that {@link MAX_SESSION_SETTINGS_BYTES} limits.
|
|
14
|
+
*
|
|
15
|
+
* The size is the UTF-8 byte length of `JSON.stringify(sessionSettings)`: compact, with characters outside ASCII
|
|
16
|
+
* written as themselves. The Python and Go cores measure their own JSON text, which is the same for strings,
|
|
17
|
+
* integers, booleans, `null`, objects, and arrays, with two exceptions: Python writes floats in their shortest
|
|
18
|
+
* form, such as `1.0` and `1e+16`, where this core writes `1` and `10000000000000000`, and Go escapes U+2028
|
|
19
|
+
* and U+2029. So sizes can differ by a few bytes per float or per such character. The session's Steps and RPC
|
|
20
|
+
* accept {@link SESSION_SETTINGS_SIZE_TOLERANCE_BYTES} more than the limit, so settings that another core's
|
|
21
|
+
* Client accepted never fail a session.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* sessionSettingsSize({ model: "gpt-5-mini" }); // 22
|
|
26
|
+
* ```
|
|
27
|
+
* @param sessionSettings - The settings.
|
|
28
|
+
* @returns The size in bytes.
|
|
29
|
+
* @throws {TypeError} When the settings cannot be written as JSON, such as with a cycle or a `bigint`.
|
|
30
|
+
*/
|
|
31
|
+
export declare function sessionSettingsSize(sessionSettings: SessionSettings): number;
|
|
32
|
+
/**
|
|
33
|
+
* Checks that a value can be a session's settings: a JSON object whose compact JSON text fits in
|
|
34
|
+
* {@link MAX_SESSION_SETTINGS_BYTES}.
|
|
35
|
+
*
|
|
36
|
+
* Call it before `Client.startFlow` or the `update_session_settings` RPC, such as in a form handler. A start whose
|
|
37
|
+
* settings the session refuses fails the session at once, and the RPC returns `false`.
|
|
38
|
+
* `AgentSessionTestClient.startSession` calls it.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* validateSessionSettings({ model: "gpt-5-mini" });
|
|
43
|
+
* await client.startFlow(flow, sessionId, { initialMessage: null, sessionSettings: { model: "gpt-5-mini" } });
|
|
44
|
+
* ```
|
|
45
|
+
* @param sessionSettings - The candidate settings.
|
|
46
|
+
* @throws {TypeError} When the value is not a plain JSON object or cannot be written as JSON.
|
|
47
|
+
* @throws {RangeError} When its compact JSON text is larger than {@link MAX_SESSION_SETTINGS_BYTES}.
|
|
48
|
+
*/
|
|
49
|
+
export declare function validateSessionSettings(sessionSettings: unknown): asserts sessionSettings is SessionSettings;
|
|
50
|
+
/**
|
|
51
|
+
* Checks settings as the session's Steps and RPC do: {@link validateSessionSettings} with a limit of
|
|
52
|
+
* {@link MAX_SESSION_SETTINGS_BYTES} plus {@link SESSION_SETTINGS_SIZE_TOLERANCE_BYTES}.
|
|
53
|
+
*
|
|
54
|
+
* @param sessionSettings - The candidate settings.
|
|
55
|
+
* @throws {TypeError} When the value is not a plain JSON object or cannot be written as JSON.
|
|
56
|
+
* @throws {RangeError} When its compact JSON text is larger than the session's limit.
|
|
57
|
+
*/
|
|
58
|
+
export declare function checkStoredSessionSettings(sessionSettings: unknown): asserts sessionSettings is SessionSettings;
|
|
@@ -0,0 +1,81 @@
|
|
|
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
|
+
/** Largest {@link SessionSettings}, as the UTF-8 bytes of their compact JSON text: 16 KiB. Same in every core. */
|
|
9
|
+
export const MAX_SESSION_SETTINGS_BYTES = 16 * 1024;
|
|
10
|
+
/**
|
|
11
|
+
* Extra bytes the session's own Steps and RPC accept over {@link MAX_SESSION_SETTINGS_BYTES}.
|
|
12
|
+
*
|
|
13
|
+
* The cores write some numbers and characters differently, so settings that one core's Client accepted can
|
|
14
|
+
* measure a few bytes more in another core's Worker. The tolerance keeps that from failing a session.
|
|
15
|
+
* {@link validateSessionSettings} checks the exact limit.
|
|
16
|
+
*/
|
|
17
|
+
export const SESSION_SETTINGS_SIZE_TOLERANCE_BYTES = 1024;
|
|
18
|
+
const utf8Encoder = new TextEncoder();
|
|
19
|
+
/**
|
|
20
|
+
* Returns the size of session settings that {@link MAX_SESSION_SETTINGS_BYTES} limits.
|
|
21
|
+
*
|
|
22
|
+
* The size is the UTF-8 byte length of `JSON.stringify(sessionSettings)`: compact, with characters outside ASCII
|
|
23
|
+
* written as themselves. The Python and Go cores measure their own JSON text, which is the same for strings,
|
|
24
|
+
* integers, booleans, `null`, objects, and arrays, with two exceptions: Python writes floats in their shortest
|
|
25
|
+
* form, such as `1.0` and `1e+16`, where this core writes `1` and `10000000000000000`, and Go escapes U+2028
|
|
26
|
+
* and U+2029. So sizes can differ by a few bytes per float or per such character. The session's Steps and RPC
|
|
27
|
+
* accept {@link SESSION_SETTINGS_SIZE_TOLERANCE_BYTES} more than the limit, so settings that another core's
|
|
28
|
+
* Client accepted never fail a session.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* sessionSettingsSize({ model: "gpt-5-mini" }); // 22
|
|
33
|
+
* ```
|
|
34
|
+
* @param sessionSettings - The settings.
|
|
35
|
+
* @returns The size in bytes.
|
|
36
|
+
* @throws {TypeError} When the settings cannot be written as JSON, such as with a cycle or a `bigint`.
|
|
37
|
+
*/
|
|
38
|
+
export function sessionSettingsSize(sessionSettings) {
|
|
39
|
+
return utf8Encoder.encode(JSON.stringify(sessionSettings)).length;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Checks that a value can be a session's settings: a JSON object whose compact JSON text fits in
|
|
43
|
+
* {@link MAX_SESSION_SETTINGS_BYTES}.
|
|
44
|
+
*
|
|
45
|
+
* Call it before `Client.startFlow` or the `update_session_settings` RPC, such as in a form handler. A start whose
|
|
46
|
+
* settings the session refuses fails the session at once, and the RPC returns `false`.
|
|
47
|
+
* `AgentSessionTestClient.startSession` calls it.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* validateSessionSettings({ model: "gpt-5-mini" });
|
|
52
|
+
* await client.startFlow(flow, sessionId, { initialMessage: null, sessionSettings: { model: "gpt-5-mini" } });
|
|
53
|
+
* ```
|
|
54
|
+
* @param sessionSettings - The candidate settings.
|
|
55
|
+
* @throws {TypeError} When the value is not a plain JSON object or cannot be written as JSON.
|
|
56
|
+
* @throws {RangeError} When its compact JSON text is larger than {@link MAX_SESSION_SETTINGS_BYTES}.
|
|
57
|
+
*/
|
|
58
|
+
export function validateSessionSettings(sessionSettings) {
|
|
59
|
+
checkSessionSettings(sessionSettings, MAX_SESSION_SETTINGS_BYTES);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Checks settings as the session's Steps and RPC do: {@link validateSessionSettings} with a limit of
|
|
63
|
+
* {@link MAX_SESSION_SETTINGS_BYTES} plus {@link SESSION_SETTINGS_SIZE_TOLERANCE_BYTES}.
|
|
64
|
+
*
|
|
65
|
+
* @param sessionSettings - The candidate settings.
|
|
66
|
+
* @throws {TypeError} When the value is not a plain JSON object or cannot be written as JSON.
|
|
67
|
+
* @throws {RangeError} When its compact JSON text is larger than the session's limit.
|
|
68
|
+
*/
|
|
69
|
+
export function checkStoredSessionSettings(sessionSettings) {
|
|
70
|
+
checkSessionSettings(sessionSettings, MAX_SESSION_SETTINGS_BYTES + SESSION_SETTINGS_SIZE_TOLERANCE_BYTES);
|
|
71
|
+
}
|
|
72
|
+
function checkSessionSettings(sessionSettings, limitBytes) {
|
|
73
|
+
if (typeof sessionSettings !== "object" || sessionSettings === null || Array.isArray(sessionSettings)) {
|
|
74
|
+
throw new TypeError("session settings must be a JSON object");
|
|
75
|
+
}
|
|
76
|
+
const size = sessionSettingsSize(sessionSettings);
|
|
77
|
+
if (size > limitBytes) {
|
|
78
|
+
throw new RangeError(`session settings are ${size} bytes, more than the ${limitBytes} allowed`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=agent-session-settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-session-settings.js","sourceRoot":"","sources":["../../src/agent-session-settings.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,kDAAkD;AAClD,mEAAmE;AACnE,+CAA+C;AAC/C,EAAE;AACF,0DAA0D;AAI1D,kHAAkH;AAClH,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,GAAG,IAAI,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,qCAAqC,GAAG,IAAI,CAAC;AAE1D,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;AAEtC;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,mBAAmB,CAAC,eAAgC;IAClE,OAAO,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC;AACpE,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,uBAAuB,CAAC,eAAwB;IAC9D,oBAAoB,CAAC,eAAe,EAAE,0BAA0B,CAAC,CAAC;AACpE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,0BAA0B,CAAC,eAAwB;IACjE,oBAAoB,CAAC,eAAe,EAAE,0BAA0B,GAAG,qCAAqC,CAAC,CAAC;AAC5G,CAAC;AAED,SAAS,oBAAoB,CAAC,eAAwB,EAAE,UAAkB;IACxE,IAAI,OAAO,eAAe,KAAK,QAAQ,IAAI,eAAe,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;QACtG,MAAM,IAAI,SAAS,CAAC,wCAAwC,CAAC,CAAC;IAChE,CAAC;IACD,MAAM,IAAI,GAAG,mBAAmB,CAAC,eAAkC,CAAC,CAAC;IACrE,IAAI,IAAI,GAAG,UAAU,EAAE,CAAC;QACtB,MAAM,IAAI,UAAU,CAAC,wBAAwB,IAAI,yBAAyB,UAAU,UAAU,CAAC,CAAC;IAClG,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import type { AgentUsage, SessionSettings } from "./agent-session-values.js";
|
|
2
|
+
/**
|
|
3
|
+
* How long the session waits for {@link ModelSpendLimit.checkModelCall} or {@link ModelSpendLimit.reportModelUsage},
|
|
4
|
+
* in milliseconds. Bound your own calls below it. A check that takes longer counts as a check that threw. A report
|
|
5
|
+
* that takes longer is dropped.
|
|
6
|
+
*
|
|
7
|
+
* @since 0.3.0
|
|
8
|
+
*/
|
|
9
|
+
export declare const spendLimitCallTimeoutMs = 30000;
|
|
10
|
+
/**
|
|
11
|
+
* Starts `AgentState.lastTurnError` of a turn that a spend limit ended. The text goes on with `": "` and the reason
|
|
12
|
+
* from {@link ModelCallDecision}. Test for it to tell a refused call from a failed one.
|
|
13
|
+
*
|
|
14
|
+
* @since 0.3.0
|
|
15
|
+
*/
|
|
16
|
+
export declare const modelCallRefusedErrorPrefix = "the model call was refused";
|
|
17
|
+
/**
|
|
18
|
+
* Describes one model call that is about to run. The session builds one for every attempt of `RunModel` and
|
|
19
|
+
* `CompactContext`, because every attempt can cost money.
|
|
20
|
+
*
|
|
21
|
+
* @since 0.3.0
|
|
22
|
+
*/
|
|
23
|
+
export interface ModelCallCheck {
|
|
24
|
+
/** The session's Flow ID. */
|
|
25
|
+
readonly flowId: string;
|
|
26
|
+
/** The turn that makes the call. */
|
|
27
|
+
readonly turnId: string;
|
|
28
|
+
/** `"RunModel"` or `"CompactContext"`. */
|
|
29
|
+
readonly stepType: string;
|
|
30
|
+
/** One-based attempt of the Step. */
|
|
31
|
+
readonly attempt: number;
|
|
32
|
+
/** The turn's session settings. Put the account or API key reference that the limit applies to here. Never a secret. */
|
|
33
|
+
readonly sessionSettings: SessionSettings;
|
|
34
|
+
/** Committed usage of this session so far. */
|
|
35
|
+
readonly sessionUsage: AgentUsage;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Says whether a model call may run. `reason` reaches `AgentState.lastTurnError`, so people read it, and it is stored.
|
|
39
|
+
* Never put a secret in it.
|
|
40
|
+
*
|
|
41
|
+
* @since 0.3.0
|
|
42
|
+
*/
|
|
43
|
+
export type ModelCallDecision = {
|
|
44
|
+
readonly isAllowed: true;
|
|
45
|
+
} | {
|
|
46
|
+
readonly isAllowed: false;
|
|
47
|
+
readonly reason: string;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Reports what one finished model call used.
|
|
51
|
+
*
|
|
52
|
+
* @since 0.3.0
|
|
53
|
+
*/
|
|
54
|
+
export interface ModelUsageReport {
|
|
55
|
+
/**
|
|
56
|
+
* Stable ID of this attempt's call: `<flow>/<turn>/<step execution>/<attempt>`. Count each ID once. A retry has a new
|
|
57
|
+
* ID because it is a new paid call.
|
|
58
|
+
*/
|
|
59
|
+
readonly reportId: string;
|
|
60
|
+
/** The session's Flow ID. */
|
|
61
|
+
readonly flowId: string;
|
|
62
|
+
/** The turn that made the call. */
|
|
63
|
+
readonly turnId: string;
|
|
64
|
+
/** `"RunModel"` or `"CompactContext"`. */
|
|
65
|
+
readonly stepType: string;
|
|
66
|
+
/** One-based attempt of the Step. */
|
|
67
|
+
readonly attempt: number;
|
|
68
|
+
/** The turn's session settings. */
|
|
69
|
+
readonly sessionSettings: SessionSettings;
|
|
70
|
+
/**
|
|
71
|
+
* What the runner reported. A harness runner, such as the Claude Agent SDK adapter, reports a whole segment here:
|
|
72
|
+
* several model calls in `usage.modelCalls`. Zero tokens with `modelCalls` above zero mean the framework did not
|
|
73
|
+
* expose token counts, not that the call was free.
|
|
74
|
+
*/
|
|
75
|
+
readonly usage: AgentUsage;
|
|
76
|
+
/**
|
|
77
|
+
* `usage` added to the committed session usage. It includes a call whose report threw or timed out, for an
|
|
78
|
+
* application that counts per session.
|
|
79
|
+
*/
|
|
80
|
+
readonly sessionUsage: AgentUsage;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Lets an application decide whether a session may spend on a model call.
|
|
84
|
+
*
|
|
85
|
+
* A spend limit is usually per account or per API key, across many sessions, so the counters and the limit belong to
|
|
86
|
+
* the application. Pass an implementation as `AgentSessionOptions.spendLimit`. Without one, the session makes no
|
|
87
|
+
* checks. The object lives in the Worker and is not stored.
|
|
88
|
+
*
|
|
89
|
+
* The session calls {@link checkModelCall} before each attempt of `RunModel` and `CompactContext`, and
|
|
90
|
+
* {@link reportModelUsage} after the attempt's model call returns. Both run inside the Step, on the Worker, so keep
|
|
91
|
+
* them fast and bound them below {@link spendLimitCallTimeoutMs}.
|
|
92
|
+
*
|
|
93
|
+
* A refused call ends the turn: the session records {@link modelCallRefusedErrorPrefix} and the reason in
|
|
94
|
+
* `AgentState.lastTurnError`, keeps the turn's finished tool results, and waits for the next user message, which is
|
|
95
|
+
* checked again. A check that throws or times out fails closed. It fails the attempt, Dex retries it under the Step's
|
|
96
|
+
* retry policy, and no model call runs without a passed check. When the retries run out the turn fails. To fail open,
|
|
97
|
+
* catch your own errors in `checkModelCall` and return `{ isAllowed: true }`.
|
|
98
|
+
*
|
|
99
|
+
* A report that throws or times out is logged and dropped, because failing the attempt would repeat a call that was
|
|
100
|
+
* already paid for.
|
|
101
|
+
*
|
|
102
|
+
* Limits to design for:
|
|
103
|
+
*
|
|
104
|
+
* - A check bounds the next call, not its cost. Sessions that pass together can overshoot a limit. A harness runner is
|
|
105
|
+
* checked once per segment, so the overshoot can be a whole segment. Set the harness's own budget option too, such
|
|
106
|
+
* as `maxBudgetUsd` for the Claude Agent SDK.
|
|
107
|
+
* - A call that fails, is cancelled, or is lost with its Worker reports nothing, though the provider may bill it. So
|
|
108
|
+
* the reports can be lower than the bill. They can also exceed `AgentUsage`: a call whose Step did not commit reports
|
|
109
|
+
* here and again on its retry, under a new `reportId`, while `AgentUsage` keeps only the committed attempt.
|
|
110
|
+
* - Reports are not durable. A report runs inside the Step, so a Worker that dies between the model's answer and the
|
|
111
|
+
* report loses it. That attempt never commits, so `AgentUsage` does not hold the call either, and only the provider's
|
|
112
|
+
* bill does. A report that threw or timed out is different: its attempt commits, so the next report's `sessionUsage`
|
|
113
|
+
* includes it.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```ts
|
|
117
|
+
* const spendLimit: ModelSpendLimit = {
|
|
118
|
+
* async checkModelCall(check) {
|
|
119
|
+
* const account = check.sessionSettings.account as string;
|
|
120
|
+
* return (await spentThisMonth(account)) >= limitOf(account)
|
|
121
|
+
* ? { isAllowed: false, reason: "account over its monthly limit" }
|
|
122
|
+
* : { isAllowed: true };
|
|
123
|
+
* },
|
|
124
|
+
* async reportModelUsage(report) {
|
|
125
|
+
* await recordOnce(report.reportId, report.usage);
|
|
126
|
+
* },
|
|
127
|
+
* };
|
|
128
|
+
* const flow = createAgentSessionFlow(runner, "SupportAgent", { spendLimit });
|
|
129
|
+
* ```
|
|
130
|
+
*
|
|
131
|
+
* @since 0.3.0
|
|
132
|
+
*/
|
|
133
|
+
export interface ModelSpendLimit {
|
|
134
|
+
/**
|
|
135
|
+
* Decides whether one model call may run.
|
|
136
|
+
* @param check - The call that is about to run.
|
|
137
|
+
* @returns The decision.
|
|
138
|
+
* @throws Any error fails the attempt, so the call does not run.
|
|
139
|
+
*/
|
|
140
|
+
checkModelCall(check: ModelCallCheck): Promise<ModelCallDecision>;
|
|
141
|
+
/**
|
|
142
|
+
* Records what one finished model call used.
|
|
143
|
+
* @param report - The call's usage. Count each `reportId` once.
|
|
144
|
+
* @returns A Promise that settles when the usage is recorded.
|
|
145
|
+
* @throws Any error is logged and dropped.
|
|
146
|
+
*/
|
|
147
|
+
reportModelUsage(report: ModelUsageReport): Promise<void>;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Settles with `operation`, or rejects after {@link spendLimitCallTimeoutMs}.
|
|
151
|
+
* @param description - What is running, for the timeout message.
|
|
152
|
+
* @param operation - The application's call.
|
|
153
|
+
* @returns The call's result.
|
|
154
|
+
* @throws {Error} When the call takes too long, or what the call threw.
|
|
155
|
+
*/
|
|
156
|
+
export declare function withinSpendLimitCallTimeout<Result>(description: string, operation: Promise<Result>): Promise<Result>;
|
|
@@ -0,0 +1,42 @@
|
|
|
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
|
+
* How long the session waits for {@link ModelSpendLimit.checkModelCall} or {@link ModelSpendLimit.reportModelUsage},
|
|
10
|
+
* in milliseconds. Bound your own calls below it. A check that takes longer counts as a check that threw. A report
|
|
11
|
+
* that takes longer is dropped.
|
|
12
|
+
*
|
|
13
|
+
* @since 0.3.0
|
|
14
|
+
*/
|
|
15
|
+
export const spendLimitCallTimeoutMs = 30_000;
|
|
16
|
+
/**
|
|
17
|
+
* Starts `AgentState.lastTurnError` of a turn that a spend limit ended. The text goes on with `": "` and the reason
|
|
18
|
+
* from {@link ModelCallDecision}. Test for it to tell a refused call from a failed one.
|
|
19
|
+
*
|
|
20
|
+
* @since 0.3.0
|
|
21
|
+
*/
|
|
22
|
+
export const modelCallRefusedErrorPrefix = "the model call was refused";
|
|
23
|
+
/**
|
|
24
|
+
* Settles with `operation`, or rejects after {@link spendLimitCallTimeoutMs}.
|
|
25
|
+
* @param description - What is running, for the timeout message.
|
|
26
|
+
* @param operation - The application's call.
|
|
27
|
+
* @returns The call's result.
|
|
28
|
+
* @throws {Error} When the call takes too long, or what the call threw.
|
|
29
|
+
*/
|
|
30
|
+
export async function withinSpendLimitCallTimeout(description, operation) {
|
|
31
|
+
let timer;
|
|
32
|
+
const timeout = new Promise((_, reject) => {
|
|
33
|
+
timer = setTimeout(() => reject(new Error(`${description} took more than ${spendLimitCallTimeoutMs} ms`)), spendLimitCallTimeoutMs);
|
|
34
|
+
});
|
|
35
|
+
try {
|
|
36
|
+
return await Promise.race([operation, timeout]);
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
clearTimeout(timer);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=agent-session-spend-limit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-session-spend-limit.js","sourceRoot":"","sources":["../../src/agent-session-spend-limit.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,kDAAkD;AAClD,mEAAmE;AACnE,+CAA+C;AAC/C,EAAE;AACF,0DAA0D;AAI1D;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,MAAM,CAAC;AAE9C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,4BAA4B,CAAC;AAqIxE;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,WAAmB,EACnB,SAA0B;IAE1B,IAAI,KAAiC,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;QAC/C,KAAK,GAAG,UAAU,CAChB,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,WAAW,mBAAmB,uBAAuB,KAAK,CAAC,CAAC,EACtF,uBAAuB,CACxB,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;IAClD,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ActiveStepSearchMode, type Client, type StartFlowOptions } from "@superdurable/dex";
|
|
2
|
+
import type { AgentFrameworkRunner, DeferredToolOutcome } from "./agent-framework-runner.js";
|
|
3
|
+
import type { AgentSessionFlow } from "./agent-session-flow.js";
|
|
4
|
+
import type { AgentSessionStartInput } from "./agent-session-values.js";
|
|
5
|
+
/**
|
|
6
|
+
* The search mode {@link startAgentSession} gives a new session.
|
|
7
|
+
*
|
|
8
|
+
* It indexes the Steps that wait, such as `AwaitToolApproval`, `AwaitQuestionAnswer`, and `AwaitUserMessage`, and
|
|
9
|
+
* leaves out Steps that run straight away, such as `RunModel`. So a session's search entry changes when it enters or
|
|
10
|
+
* leaves a wait, not on every Step.
|
|
11
|
+
*
|
|
12
|
+
* Pass it as `activeStepSearchMode` in `StartFlowOptions.configOverride` to `Client.startFlow`, in a SubFlow's
|
|
13
|
+
* `configOverride`, or to `Client.updateFlowConfig` for a running session.
|
|
14
|
+
*
|
|
15
|
+
* The value is `ActiveStepSearchMode.DEFAULT` because the Dex SDK this core supports has no `WITH_WAIT_FOR` value.
|
|
16
|
+
* It sends the unspecified mode, which the server stores on the Flow and treats as Steps with a wait.
|
|
17
|
+
*
|
|
18
|
+
* @since 0.3.0
|
|
19
|
+
*/
|
|
20
|
+
export declare const agentSessionActiveStepSearchMode: ActiveStepSearchMode;
|
|
21
|
+
/**
|
|
22
|
+
* Starts one agent session, searchable by the Steps it waits in.
|
|
23
|
+
*
|
|
24
|
+
* `ActiveStepTypes = "AwaitToolApproval"` then finds the session while a tool call waits for a person. Prefer this to
|
|
25
|
+
* `Client.startFlow`, which leaves the session out of that search unless `configOverride` sets
|
|
26
|
+
* {@link agentSessionActiveStepSearchMode}.
|
|
27
|
+
*
|
|
28
|
+
* Set `configOverride.activeStepSearchMode` to choose another mode. To leave a session out of the search, start it
|
|
29
|
+
* with `Client.startFlow` and no mode: the Dex SDK this core supports cannot send the disabled mode. A session started
|
|
30
|
+
* as a SubFlow inherits its parent's mode unless its `configOverride` sets one.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* await startAgentSession(client, flow, "session-42", { initialMessage: "Refund order 7" });
|
|
35
|
+
* const page = await client.searchFlows('ActiveStepTypes = "AwaitToolApproval"', 50);
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @param client - An open Client whose Registry contains `flow`.
|
|
39
|
+
* @param flow - The registered agent session Flow.
|
|
40
|
+
* @param sessionId - Flow ID of the new session.
|
|
41
|
+
* @param input - The first user message and the session's settings.
|
|
42
|
+
* @param options - Start options, such as a Request ID for an idempotent start. `configOverride` keeps every field
|
|
43
|
+
* it sets.
|
|
44
|
+
* @returns The server-assigned run ID.
|
|
45
|
+
* @throws {TypeError | RangeError} From `validateSessionSettings`, before anything is sent.
|
|
46
|
+
* @throws {FlowAlreadyStartedError} When the Flow ID is already in use.
|
|
47
|
+
* @since 0.3.0
|
|
48
|
+
*/
|
|
49
|
+
export declare function startAgentSession(client: Client, flow: AgentSessionFlow<AgentFrameworkRunner<DeferredToolOutcome>>, sessionId: string, input?: Partial<AgentSessionStartInput>, options?: StartFlowOptions): Promise<string>;
|