@rudderjs/ai 1.12.0 → 1.14.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.
@@ -0,0 +1,161 @@
1
+ import type { AiMessage, ToolCall } from './types.js';
2
+ /**
3
+ * Discriminator for the kind of pause a standalone run is parked on.
4
+ * Mirrors {@link SubAgentPauseKind} — the two run-store families share a
5
+ * vocabulary so a host can persist sub-agent and top-level pauses the same way.
6
+ *
7
+ * - `'client_tool'` — the run surfaced one or more client tools; resume must
8
+ * carry one tool-result per id in `pendingToolCallIds`. The default when the
9
+ * field is absent (older snapshots stay readable after an upgrade).
10
+ * - `'approval'` — the run stopped on an approval gate; resume must carry an
11
+ * approve/reject decision covering the single id in `pendingToolCallIds`.
12
+ */
13
+ export type AgentPauseKind = 'client_tool' | 'approval';
14
+ /**
15
+ * Snapshot of a paused **standalone** (top-level) agent run — the state a host
16
+ * persists between an `agent.stream()` that parks on a client tool or approval
17
+ * gate and the follow-up request that resumes it.
18
+ *
19
+ * This is the standalone sibling of {@link SubAgentRunSnapshot}: same idea, but
20
+ * for a top-level `stream()` rather than an `Agent.asTool` sub-run. The shape is
21
+ * intentionally replay-ready — `messages` is the full conversation up to the
22
+ * pause point, so resume only appends the incoming client-tool results (or
23
+ * injects the approval decision) and re-enters `stream()` in `messages` mode.
24
+ */
25
+ export interface AgentRunState {
26
+ /** Full conversation history at suspend time (system + user + every interleaved assistant/tool message). */
27
+ messages: AiMessage[];
28
+ /**
29
+ * Tool-call ids the run is waiting on.
30
+ *
31
+ * - `pauseKind === 'client_tool'` (default): one entry per client tool the
32
+ * loop surfaced; resume appends one result per id.
33
+ * - `pauseKind === 'approval'`: a single entry for the approval-gated tool
34
+ * call; resume injects the id into the approve or reject set.
35
+ */
36
+ pendingToolCallIds: string[];
37
+ /** Total steps the run has executed across all suspends so far. */
38
+ stepsSoFar: number;
39
+ /** Total prompt+completion tokens accumulated across all suspends. */
40
+ tokensSoFar: number;
41
+ /**
42
+ * Discriminator for the resume contract. Defaults to `'client_tool'` when
43
+ * absent so snapshots written before approval-pause support stay readable.
44
+ */
45
+ pauseKind?: AgentPauseKind;
46
+ /**
47
+ * Approval pauses only. The full pending tool-call payload (name + args + id)
48
+ * so a renderer can show "approve `delete_user(id=42)`?" without re-running
49
+ * the agent. Mirrors `AgentResponse.pendingApprovalToolCall`.
50
+ */
51
+ pendingApprovalToolCall?: {
52
+ toolCall: ToolCall;
53
+ isClientTool: boolean;
54
+ };
55
+ /**
56
+ * Opaque metadata the host can pass through. The framework treats this as
57
+ * JSON and never reads it — useful for rehydrating request context
58
+ * (e.g. `{ userId, threadId, agentSlug }`) around the resume call.
59
+ */
60
+ meta?: unknown;
61
+ }
62
+ /**
63
+ * Pluggable persistence backend for paused standalone agent runs. The framework
64
+ * ships two reference implementations:
65
+ *
66
+ * - {@link InMemoryAgentRunStore} — a `Map`-backed store. Single-process only;
67
+ * fine for unit tests and small dev setups, lossy across worker processes and
68
+ * restarts.
69
+ * - {@link CachedAgentRunStore} — lazy adapter on top of `@rudderjs/cache`.
70
+ * Cross-process / cross-restart when the cache is configured with redis or any
71
+ * non-memory driver.
72
+ *
73
+ * Hosts may implement their own (Redis directly, Prisma, etc.) by satisfying
74
+ * this interface.
75
+ *
76
+ * The split between {@link load} (non-destructive peek) and {@link consume}
77
+ * (atomic single-use read+delete) matters: a host can `load()` to render a
78
+ * "waiting for approval" view on a GET without burning the run, then `consume()`
79
+ * on the resume POST so a forged or replayed `runId` cannot read data twice.
80
+ */
81
+ export interface AgentRunStore {
82
+ /** Persist a snapshot under `runId`. Implementations MAY apply a TTL. */
83
+ store(runId: string, state: AgentRunState): Promise<void>;
84
+ /**
85
+ * Non-destructive read. Returns `null` if the id is unknown or the snapshot
86
+ * has expired. Leaves the snapshot in place — use for read-only peeks
87
+ * (rendering a pending-run view); use {@link consume} when resuming.
88
+ */
89
+ load(runId: string): Promise<AgentRunState | null>;
90
+ /**
91
+ * Atomic read + delete. Returns `null` if the id is unknown or the snapshot
92
+ * has expired. Single-use semantics matter: a forged or replayed `runId` must
93
+ * not return data twice.
94
+ */
95
+ consume(runId: string): Promise<AgentRunState | null>;
96
+ }
97
+ /**
98
+ * Generate a fresh, hard-to-guess run id. Uses `crypto.randomUUID()` where the
99
+ * runtime exposes it (Node ≥ 16.7, every modern browser, Deno, Bun), falling
100
+ * back to a timestamp + random suffix. Run ids are unguessable on purpose — a
101
+ * `runId` is a capability handle to a parked conversation, so a predictable id
102
+ * would let a third party `consume()` someone else's run.
103
+ */
104
+ export declare function newAgentRunId(): string;
105
+ /**
106
+ * `Map`-backed implementation suitable for tests and single-process dev.
107
+ * Loses state across restarts and worker processes — for any multi-worker
108
+ * deployment, use {@link CachedAgentRunStore} or a custom backend.
109
+ */
110
+ export declare class InMemoryAgentRunStore implements AgentRunStore {
111
+ private readonly states;
112
+ store(runId: string, state: AgentRunState): Promise<void>;
113
+ load(runId: string): Promise<AgentRunState | null>;
114
+ consume(runId: string): Promise<AgentRunState | null>;
115
+ /** Test helper — clears all snapshots without consuming. */
116
+ clear(): void;
117
+ }
118
+ /**
119
+ * Minimal structural shape of a cache adapter (the methods this store touches).
120
+ * Mirrors `@rudderjs/cache`'s `CacheAdapter` so the dep stays structural — the
121
+ * framework's main entry stays runtime-agnostic.
122
+ */
123
+ interface CacheStoreLike {
124
+ get<T = unknown>(key: string): Promise<T | null>;
125
+ set(key: string, value: unknown, ttlSeconds?: number): Promise<void>;
126
+ forget(key: string): Promise<void>;
127
+ }
128
+ export interface CachedAgentRunStoreOptions {
129
+ /**
130
+ * Cache adapter to use. When omitted, the store loads `@rudderjs/cache`
131
+ * lazily and falls back to the registered global adapter
132
+ * (`CacheRegistry.get()`); throws if neither resolves.
133
+ */
134
+ cache?: CacheStoreLike;
135
+ /** Key namespace prefix. Default `'rudderjs:ai:agent-run:'`. */
136
+ keyPrefix?: string;
137
+ /** Time-to-live in seconds. Default 5 minutes. */
138
+ ttlSeconds?: number;
139
+ }
140
+ /**
141
+ * Standalone agent run store backed by `@rudderjs/cache`. Loads the cache
142
+ * adapter lazily so `@rudderjs/ai`'s main entry stays runtime-agnostic (no
143
+ * static import on the cache package).
144
+ *
145
+ * Default TTL is 5 minutes — long enough for a browser to round-trip a few
146
+ * client tool calls or an approval decision, short enough that abandoned runs
147
+ * garbage-collect promptly and the storage bill stays bounded.
148
+ */
149
+ export declare class CachedAgentRunStore implements AgentRunStore {
150
+ private readonly explicitCache?;
151
+ private readonly keyPrefix;
152
+ private readonly ttlSeconds;
153
+ private resolvedCache?;
154
+ constructor(opts?: CachedAgentRunStoreOptions);
155
+ private getCache;
156
+ store(runId: string, state: AgentRunState): Promise<void>;
157
+ load(runId: string): Promise<AgentRunState | null>;
158
+ consume(runId: string): Promise<AgentRunState | null>;
159
+ }
160
+ export {};
161
+ //# sourceMappingURL=agent-run-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-run-store.d.ts","sourceRoot":"","sources":["../src/agent-run-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Generate a fresh, hard-to-guess run id. Uses `crypto.randomUUID()` where the
3
+ * runtime exposes it (Node ≥ 16.7, every modern browser, Deno, Bun), falling
4
+ * back to a timestamp + random suffix. Run ids are unguessable on purpose — a
5
+ * `runId` is a capability handle to a parked conversation, so a predictable id
6
+ * would let a third party `consume()` someone else's run.
7
+ */
8
+ export function newAgentRunId() {
9
+ if (typeof globalThis.crypto?.randomUUID === 'function')
10
+ return globalThis.crypto.randomUUID();
11
+ return `run-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;
12
+ }
13
+ // ─── In-memory ─────────────────────────────────────────────
14
+ /**
15
+ * `Map`-backed implementation suitable for tests and single-process dev.
16
+ * Loses state across restarts and worker processes — for any multi-worker
17
+ * deployment, use {@link CachedAgentRunStore} or a custom backend.
18
+ */
19
+ export class InMemoryAgentRunStore {
20
+ states = new Map();
21
+ async store(runId, state) {
22
+ this.states.set(runId, state);
23
+ }
24
+ async load(runId) {
25
+ return this.states.get(runId) ?? null;
26
+ }
27
+ async consume(runId) {
28
+ const state = this.states.get(runId);
29
+ if (!state)
30
+ return null;
31
+ this.states.delete(runId);
32
+ return state;
33
+ }
34
+ /** Test helper — clears all snapshots without consuming. */
35
+ clear() {
36
+ this.states.clear();
37
+ }
38
+ }
39
+ /**
40
+ * Standalone agent run store backed by `@rudderjs/cache`. Loads the cache
41
+ * adapter lazily so `@rudderjs/ai`'s main entry stays runtime-agnostic (no
42
+ * static import on the cache package).
43
+ *
44
+ * Default TTL is 5 minutes — long enough for a browser to round-trip a few
45
+ * client tool calls or an approval decision, short enough that abandoned runs
46
+ * garbage-collect promptly and the storage bill stays bounded.
47
+ */
48
+ export class CachedAgentRunStore {
49
+ explicitCache;
50
+ keyPrefix;
51
+ ttlSeconds;
52
+ resolvedCache;
53
+ constructor(opts = {}) {
54
+ if (opts.cache)
55
+ this.explicitCache = opts.cache;
56
+ this.keyPrefix = opts.keyPrefix ?? 'rudderjs:ai:agent-run:';
57
+ this.ttlSeconds = opts.ttlSeconds ?? 5 * 60;
58
+ }
59
+ async getCache() {
60
+ if (this.resolvedCache)
61
+ return this.resolvedCache;
62
+ if (this.explicitCache) {
63
+ this.resolvedCache = this.explicitCache;
64
+ return this.resolvedCache;
65
+ }
66
+ // Lazy-import @rudderjs/cache and ask the registry for the active adapter.
67
+ // This keeps the static import surface zero — the import only fires when the
68
+ // host actually opts into suspendable standalone runs. We dodge static
69
+ // module-resolution by using an indirected specifier so `@rudderjs/cache`
70
+ // doesn't need to be a declared dep of `@rudderjs/ai` (optional runtime peer).
71
+ const cacheSpecifier = '@rudderjs/cache';
72
+ const mod = await import(/* @vite-ignore */ cacheSpecifier);
73
+ const adapter = mod.CacheRegistry?.get?.();
74
+ if (!adapter) {
75
+ throw new Error('[RudderJS AI] CachedAgentRunStore needs a cache adapter. Install `@rudderjs/cache`, register a driver, or pass `{ cache }` explicitly.');
76
+ }
77
+ this.resolvedCache = adapter;
78
+ return adapter;
79
+ }
80
+ async store(runId, state) {
81
+ const cache = await this.getCache();
82
+ await cache.set(this.keyPrefix + runId, state, this.ttlSeconds);
83
+ }
84
+ async load(runId) {
85
+ const cache = await this.getCache();
86
+ return (await cache.get(this.keyPrefix + runId)) ?? null;
87
+ }
88
+ async consume(runId) {
89
+ const cache = await this.getCache();
90
+ const key = this.keyPrefix + runId;
91
+ const state = await cache.get(key);
92
+ if (!state)
93
+ return null;
94
+ await cache.forget(key);
95
+ return state;
96
+ }
97
+ }
98
+ //# sourceMappingURL=agent-run-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-run-store.js","sourceRoot":"","sources":["../src/agent-run-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Named-event SSE protocol for streaming an agent loop to a browser.
3
+ *
4
+ * `@rudderjs/ai` already ships the Vercel AI SDK data-stream protocol
5
+ * ({@link toVercelDataStream}) - the numeric-prefix wire (`0:` / `9:` / `a:`
6
+ * ...). This is the alternative for apps that want a plain
7
+ * `text/event-stream` with self-describing event names that mirror the agent
8
+ * loop's own lifecycle (`text`, `tool_call`, `tool_update`, `tool_result`,
9
+ * `pending_client_tools`, `tool_approval_required`, `handoff`, `complete`,
10
+ * `error`).
11
+ *
12
+ * Both ends live here so the wire vocabulary can never drift:
13
+ *
14
+ * - Server: {@link toAgentSseStream} / {@link toAgentSseResponse} project an
15
+ * `agent.stream()` result onto the named events and frame them as SSE.
16
+ * - Browser: {@link readAgentStream} decodes the same events back into an
17
+ * {@link AgentStreamTurn} and fires per-event callbacks for UI side effects.
18
+ * {@link applyAgentSseEvent} is exposed so the per-event reducer can be
19
+ * unit-tested against a synthetic turn.
20
+ *
21
+ * Runtime-agnostic: uses only web globals (`ReadableStream`, `Response`,
22
+ * `TextEncoder` / `TextDecoder`, `crypto.randomUUID`), no `node:` imports, so
23
+ * the module is safe in the main entry and runs server-side (Node / edge) and
24
+ * client-side alike.
25
+ *
26
+ * This ships the framework-generic core. App-specific events (conversation
27
+ * ids, billing, sub-run fan-out bookkeeping, server-authoritative history
28
+ * sync) are not part of it - emit and decode those alongside this protocol on
29
+ * your own channel.
30
+ */
31
+ import type { AgentStreamResponse, AiMessage, FinishReason, TokenUsage, ToolCall } from './types.js';
32
+ /** The named SSE events this protocol emits, in agent-loop order. */
33
+ export type AgentSseEventName = 'text' | 'tool_call' | 'tool_update' | 'tool_result' | 'pending_client_tools' | 'tool_approval_required' | 'handoff' | 'complete' | 'error';
34
+ /** What the loop parked on when it paused, surfaced on the `complete` event. */
35
+ export type AgentAwaiting = 'client_tools' | 'approval';
36
+ export interface AgentSseTextPayload {
37
+ text: string;
38
+ }
39
+ export interface AgentSseToolCallPayload {
40
+ id?: string;
41
+ tool: string;
42
+ input?: Record<string, unknown>;
43
+ }
44
+ export interface AgentSseToolUpdatePayload {
45
+ id?: string;
46
+ tool?: string;
47
+ update: unknown;
48
+ }
49
+ export interface AgentSseToolResultPayload {
50
+ id?: string;
51
+ toolCallId?: string;
52
+ tool?: string;
53
+ /** String passthrough when the tool returned a string, else JSON-encoded. */
54
+ content: string;
55
+ }
56
+ export interface AgentSsePendingClientToolsPayload {
57
+ toolCalls: ToolCall[];
58
+ }
59
+ export interface AgentSseApprovalPayload {
60
+ toolCall: ToolCall;
61
+ isClientTool: boolean;
62
+ }
63
+ export interface AgentSseHandoffPayload {
64
+ from: string;
65
+ to: string;
66
+ message?: string;
67
+ }
68
+ export interface AgentSseCompletePayload {
69
+ done: true;
70
+ finishReason?: FinishReason;
71
+ awaiting?: AgentAwaiting;
72
+ /** Number of model steps the run took (`response.steps.length`). */
73
+ steps?: number;
74
+ usage?: TokenUsage;
75
+ }
76
+ export interface AgentSseErrorPayload {
77
+ message: string;
78
+ }
79
+ /**
80
+ * Project an `agent.stream()` result onto the named-event SSE wire as a
81
+ * `ReadableStream<Uint8Array>`.
82
+ *
83
+ * Iterates the chunk stream, emits one named event per loop chunk, then
84
+ * awaits the `response` promise and emits a terminal `complete` event
85
+ * carrying `done`, `finishReason`, the `awaiting` pause (if any), step count,
86
+ * and usage. If iteration or the response throws, an `error` event is emitted
87
+ * and the stream closes cleanly so the browser reader's `onError` fires.
88
+ */
89
+ export declare function toAgentSseStream(streaming: AgentStreamResponse): ReadableStream<Uint8Array>;
90
+ /**
91
+ * Wrap {@link toAgentSseStream} in a `Response` with the standard
92
+ * `text/event-stream` headers (no caching, no proxy buffering). Return it
93
+ * directly from a route handler.
94
+ */
95
+ export declare function toAgentSseResponse(streaming: AgentStreamResponse, init?: ResponseInit): Response;
96
+ /**
97
+ * The accumulated state of one streamed agent turn, built up event by event
98
+ * by {@link readAgentStream}. Mirrors {@link AgentResponse} fields the browser
99
+ * needs to render the turn and build the next continuation request.
100
+ */
101
+ export interface AgentStreamTurn {
102
+ /** Concatenated `text` event deltas. */
103
+ assistantText: string;
104
+ /** Tool calls stamped by `tool_call` events (for the next continuation). */
105
+ assistantToolCalls: ToolCall[];
106
+ /** Server-side `role:'tool'` result messages from `tool_result` events. */
107
+ serverToolResults: AiMessage[];
108
+ /** Client tool calls from a `pending_client_tools` event to run locally. */
109
+ pendingClientTools: ToolCall[];
110
+ /** Approval pause from a `tool_approval_required` event. */
111
+ pendingApproval: AgentSseApprovalPayload | null;
112
+ /** Chain of agent class names traversed via `handoff` events. */
113
+ handoffPath: string[];
114
+ /** `true` once a `complete` event with `done: true` arrived. */
115
+ done: boolean;
116
+ /** What the run paused on, from the `complete` event. */
117
+ awaiting: AgentAwaiting | undefined;
118
+ }
119
+ /** A fresh, empty {@link AgentStreamTurn}. */
120
+ export declare function newAgentStreamTurn(): AgentStreamTurn;
121
+ /** Per-event callbacks fired by {@link readAgentStream} for UI side effects. */
122
+ export interface AgentStreamCallbacks {
123
+ onText?: (text: string) => void;
124
+ onToolCall?: (call: AgentSseToolCallPayload) => void;
125
+ onToolUpdate?: (update: AgentSseToolUpdatePayload) => void;
126
+ onToolResult?: (result: AgentSseToolResultPayload) => void;
127
+ onPendingClientTools?: (toolCalls: ToolCall[]) => void;
128
+ onToolApprovalRequired?: (approval: AgentSseApprovalPayload) => void;
129
+ onHandoff?: (handoff: AgentSseHandoffPayload) => void;
130
+ onComplete?: (data: AgentSseCompletePayload) => void;
131
+ onError?: (error: AgentSseErrorPayload) => void;
132
+ }
133
+ /**
134
+ * Read a named-event agent-SSE response body, applying each event to a fresh
135
+ * {@link AgentStreamTurn} and firing the matching callback. Resolves with the
136
+ * accumulated turn once the stream closes.
137
+ *
138
+ * The caller owns the `fetch` and the `!resp.ok` branch (so a rich error body
139
+ * can be read for non-2xx responses); pass an already-OK response. A missing
140
+ * body resolves to an empty turn. Malformed event JSON is skipped.
141
+ */
142
+ export declare function readAgentStream(resp: Response, callbacks?: AgentStreamCallbacks): Promise<AgentStreamTurn>;
143
+ /**
144
+ * Apply a single parsed SSE event to the turn state and fire the matching
145
+ * callback. Mutates `turn`; otherwise pure. Exposed for unit-testing the
146
+ * reducer against a synthetic turn without a live stream.
147
+ */
148
+ export declare function applyAgentSseEvent(event: string, data: unknown, turn: AgentStreamTurn, callbacks?: AgentStreamCallbacks): void;
149
+ //# sourceMappingURL=agent-sse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-sse.d.ts","sourceRoot":"","sources":["../src/agent-sse.ts"],"names":[],"mappings":"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"}