@rudderjs/ai 1.13.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.
- package/dist/agent-sse.d.ts +149 -0
- package/dist/agent-sse.d.ts.map +1 -0
- package/dist/agent-sse.js +280 -0
- package/dist/agent-sse.js.map +1 -0
- package/dist/conversation-orm/index.d.ts.map +1 -1
- package/dist/conversation-orm/index.js +5 -1
- package/dist/conversation-orm/index.js.map +1 -1
- package/dist/gateway/http-gateway-adapter.d.ts +94 -0
- package/dist/gateway/http-gateway-adapter.d.ts.map +1 -0
- package/dist/gateway/http-gateway-adapter.js +106 -0
- package/dist/gateway/http-gateway-adapter.js.map +1 -0
- package/dist/gateway/index.d.ts +11 -0
- package/dist/gateway/index.d.ts.map +1 -0
- package/dist/gateway/index.js +11 -0
- package/dist/gateway/index.js.map +1 -0
- package/dist/gateway/sse.d.ts +28 -0
- package/dist/gateway/sse.d.ts.map +1 -0
- package/dist/gateway/sse.js +78 -0
- package/dist/gateway/sse.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/sanitize-conversation.d.ts +43 -0
- package/dist/sanitize-conversation.d.ts.map +1 -0
- package/dist/sanitize-conversation.js +85 -0
- package/dist/sanitize-conversation.js.map +1 -0
- package/package.json +5 -1
|
@@ -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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"}
|
|
@@ -0,0 +1,280 @@
|
|
|
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
|
+
// ─── Server: project a stream onto SSE ────────────────────
|
|
32
|
+
/** Map a finish reason to the pause it represents, if any. */
|
|
33
|
+
function awaitingFor(reason) {
|
|
34
|
+
if (reason === 'client_tool_calls')
|
|
35
|
+
return 'client_tools';
|
|
36
|
+
if (reason === 'tool_approval_required')
|
|
37
|
+
return 'approval';
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
function frame(event, data) {
|
|
41
|
+
return `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Project an `agent.stream()` result onto the named-event SSE wire as a
|
|
45
|
+
* `ReadableStream<Uint8Array>`.
|
|
46
|
+
*
|
|
47
|
+
* Iterates the chunk stream, emits one named event per loop chunk, then
|
|
48
|
+
* awaits the `response` promise and emits a terminal `complete` event
|
|
49
|
+
* carrying `done`, `finishReason`, the `awaiting` pause (if any), step count,
|
|
50
|
+
* and usage. If iteration or the response throws, an `error` event is emitted
|
|
51
|
+
* and the stream closes cleanly so the browser reader's `onError` fires.
|
|
52
|
+
*/
|
|
53
|
+
export function toAgentSseStream(streaming) {
|
|
54
|
+
const { stream, response } = streaming;
|
|
55
|
+
const encoder = new TextEncoder();
|
|
56
|
+
return new ReadableStream({
|
|
57
|
+
async start(controller) {
|
|
58
|
+
const emit = (event, data) => controller.enqueue(encoder.encode(frame(event, data)));
|
|
59
|
+
try {
|
|
60
|
+
for await (const chunk of stream) {
|
|
61
|
+
emitChunk(chunk, emit);
|
|
62
|
+
}
|
|
63
|
+
const res = await response;
|
|
64
|
+
const awaiting = awaitingFor(res.finishReason);
|
|
65
|
+
const complete = {
|
|
66
|
+
done: true,
|
|
67
|
+
steps: res.steps.length,
|
|
68
|
+
usage: res.usage,
|
|
69
|
+
};
|
|
70
|
+
if (res.finishReason)
|
|
71
|
+
complete.finishReason = res.finishReason;
|
|
72
|
+
if (awaiting)
|
|
73
|
+
complete.awaiting = awaiting;
|
|
74
|
+
emit('complete', complete);
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
78
|
+
emit('error', { message });
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
controller.close();
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
function emitChunk(chunk, emit) {
|
|
87
|
+
switch (chunk.type) {
|
|
88
|
+
case 'text-delta':
|
|
89
|
+
if (chunk.text)
|
|
90
|
+
emit('text', { text: chunk.text });
|
|
91
|
+
return;
|
|
92
|
+
case 'tool-call':
|
|
93
|
+
emit('tool_call', {
|
|
94
|
+
...(chunk.toolCall?.id ? { id: chunk.toolCall.id } : {}),
|
|
95
|
+
tool: chunk.toolCall?.name ?? '',
|
|
96
|
+
input: chunk.toolCall?.arguments ?? {},
|
|
97
|
+
});
|
|
98
|
+
return;
|
|
99
|
+
case 'tool-update':
|
|
100
|
+
emit('tool_update', {
|
|
101
|
+
...(chunk.toolCall?.id ? { id: chunk.toolCall.id } : {}),
|
|
102
|
+
...(chunk.toolCall?.name ? { tool: chunk.toolCall.name } : {}),
|
|
103
|
+
update: chunk.update,
|
|
104
|
+
});
|
|
105
|
+
return;
|
|
106
|
+
case 'tool-result': {
|
|
107
|
+
const id = chunk.toolCall?.id;
|
|
108
|
+
emit('tool_result', {
|
|
109
|
+
...(id ? { id, toolCallId: id } : {}),
|
|
110
|
+
...(chunk.toolCall?.name ? { tool: chunk.toolCall.name } : {}),
|
|
111
|
+
content: typeof chunk.result === 'string' ? chunk.result : JSON.stringify(chunk.result),
|
|
112
|
+
});
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
case 'pending-client-tools':
|
|
116
|
+
emit('pending_client_tools', { toolCalls: chunk.toolCalls ?? [] });
|
|
117
|
+
return;
|
|
118
|
+
case 'pending-approval':
|
|
119
|
+
if (chunk.toolCall) {
|
|
120
|
+
emit('tool_approval_required', {
|
|
121
|
+
toolCall: chunk.toolCall,
|
|
122
|
+
isClientTool: chunk.isClientTool ?? false,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
return;
|
|
126
|
+
case 'handoff':
|
|
127
|
+
if (chunk.handoff)
|
|
128
|
+
emit('handoff', chunk.handoff);
|
|
129
|
+
return;
|
|
130
|
+
// 'tool-call-delta' | 'usage' | 'finish' carry no named event - the
|
|
131
|
+
// terminal `complete` event reports finish reason + usage from the
|
|
132
|
+
// resolved AgentResponse.
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Wrap {@link toAgentSseStream} in a `Response` with the standard
|
|
137
|
+
* `text/event-stream` headers (no caching, no proxy buffering). Return it
|
|
138
|
+
* directly from a route handler.
|
|
139
|
+
*/
|
|
140
|
+
export function toAgentSseResponse(streaming, init) {
|
|
141
|
+
const headers = new Headers(init?.headers);
|
|
142
|
+
headers.set('Content-Type', 'text/event-stream; charset=utf-8');
|
|
143
|
+
headers.set('Cache-Control', 'no-cache, no-transform');
|
|
144
|
+
headers.set('Connection', 'keep-alive');
|
|
145
|
+
// Disable nginx response buffering so events flush as they're produced.
|
|
146
|
+
headers.set('X-Accel-Buffering', 'no');
|
|
147
|
+
return new Response(toAgentSseStream(streaming), { ...init, headers });
|
|
148
|
+
}
|
|
149
|
+
/** A fresh, empty {@link AgentStreamTurn}. */
|
|
150
|
+
export function newAgentStreamTurn() {
|
|
151
|
+
return {
|
|
152
|
+
assistantText: '',
|
|
153
|
+
assistantToolCalls: [],
|
|
154
|
+
serverToolResults: [],
|
|
155
|
+
pendingClientTools: [],
|
|
156
|
+
pendingApproval: null,
|
|
157
|
+
handoffPath: [],
|
|
158
|
+
done: false,
|
|
159
|
+
awaiting: undefined,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function randomId() {
|
|
163
|
+
return typeof crypto !== 'undefined' && crypto.randomUUID
|
|
164
|
+
? crypto.randomUUID()
|
|
165
|
+
: `tc-${Date.now()}-${Math.round(Math.random() * 1e9)}`;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Read a named-event agent-SSE response body, applying each event to a fresh
|
|
169
|
+
* {@link AgentStreamTurn} and firing the matching callback. Resolves with the
|
|
170
|
+
* accumulated turn once the stream closes.
|
|
171
|
+
*
|
|
172
|
+
* The caller owns the `fetch` and the `!resp.ok` branch (so a rich error body
|
|
173
|
+
* can be read for non-2xx responses); pass an already-OK response. A missing
|
|
174
|
+
* body resolves to an empty turn. Malformed event JSON is skipped.
|
|
175
|
+
*/
|
|
176
|
+
export async function readAgentStream(resp, callbacks = {}) {
|
|
177
|
+
const turn = newAgentStreamTurn();
|
|
178
|
+
if (!resp.body)
|
|
179
|
+
return turn;
|
|
180
|
+
const reader = resp.body.getReader();
|
|
181
|
+
const decoder = new TextDecoder();
|
|
182
|
+
let buffer = '';
|
|
183
|
+
// Hoisted across reads: an `event:` line and its `data:` line can land in
|
|
184
|
+
// separate `read()` chunks when the body is sliced mid-frame.
|
|
185
|
+
let currentEvent = '';
|
|
186
|
+
for (;;) {
|
|
187
|
+
const { done, value } = await reader.read();
|
|
188
|
+
if (done)
|
|
189
|
+
break;
|
|
190
|
+
buffer += decoder.decode(value, { stream: true });
|
|
191
|
+
const lines = buffer.split('\n');
|
|
192
|
+
buffer = lines.pop() ?? '';
|
|
193
|
+
for (const line of lines) {
|
|
194
|
+
if (line.startsWith('event: ')) {
|
|
195
|
+
currentEvent = line.slice(7);
|
|
196
|
+
}
|
|
197
|
+
else if (line.startsWith('data: ') && currentEvent) {
|
|
198
|
+
try {
|
|
199
|
+
applyAgentSseEvent(currentEvent, JSON.parse(line.slice(6)), turn, callbacks);
|
|
200
|
+
}
|
|
201
|
+
catch { /* skip malformed JSON */ }
|
|
202
|
+
currentEvent = '';
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return turn;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Apply a single parsed SSE event to the turn state and fire the matching
|
|
210
|
+
* callback. Mutates `turn`; otherwise pure. Exposed for unit-testing the
|
|
211
|
+
* reducer against a synthetic turn without a live stream.
|
|
212
|
+
*/
|
|
213
|
+
export function applyAgentSseEvent(event, data, turn, callbacks = {}) {
|
|
214
|
+
switch (event) {
|
|
215
|
+
case 'text': {
|
|
216
|
+
const d = data;
|
|
217
|
+
turn.assistantText += d.text;
|
|
218
|
+
callbacks.onText?.(d.text);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
case 'tool_call': {
|
|
222
|
+
const d = data;
|
|
223
|
+
turn.assistantToolCalls.push({
|
|
224
|
+
id: d.id ?? randomId(),
|
|
225
|
+
name: d.tool,
|
|
226
|
+
arguments: d.input ?? {},
|
|
227
|
+
});
|
|
228
|
+
callbacks.onToolCall?.(d);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
case 'tool_update': {
|
|
232
|
+
callbacks.onToolUpdate?.(data);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
case 'tool_result': {
|
|
236
|
+
const d = data;
|
|
237
|
+
const toolCallId = d.toolCallId ?? d.id;
|
|
238
|
+
if (toolCallId) {
|
|
239
|
+
turn.serverToolResults.push({ role: 'tool', content: d.content, toolCallId });
|
|
240
|
+
}
|
|
241
|
+
callbacks.onToolResult?.(d);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
case 'pending_client_tools': {
|
|
245
|
+
const d = data;
|
|
246
|
+
turn.pendingClientTools = d.toolCalls ?? [];
|
|
247
|
+
callbacks.onPendingClientTools?.(turn.pendingClientTools);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
case 'tool_approval_required': {
|
|
251
|
+
const d = data;
|
|
252
|
+
turn.pendingApproval = { toolCall: d.toolCall, isClientTool: d.isClientTool };
|
|
253
|
+
callbacks.onToolApprovalRequired?.(d);
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
case 'handoff': {
|
|
257
|
+
const d = data;
|
|
258
|
+
if (turn.handoffPath.length === 0 && d.from)
|
|
259
|
+
turn.handoffPath.push(d.from);
|
|
260
|
+
if (d.to)
|
|
261
|
+
turn.handoffPath.push(d.to);
|
|
262
|
+
callbacks.onHandoff?.(d);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
case 'complete': {
|
|
266
|
+
const d = data;
|
|
267
|
+
if (d.done === true)
|
|
268
|
+
turn.done = true;
|
|
269
|
+
turn.awaiting = d.awaiting;
|
|
270
|
+
callbacks.onComplete?.(d);
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
case 'error': {
|
|
274
|
+
const d = data;
|
|
275
|
+
callbacks.onError?.(d);
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
//# sourceMappingURL=agent-sse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-sse.js","sourceRoot":"","sources":["../src/agent-sse.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/conversation-orm/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/conversation-orm/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAErC,OAAO,KAAK,EACV,SAAS,EACT,iBAAiB,EACjB,0BAA0B,EAC1B,qBAAqB,EAEtB,MAAM,aAAa,CAAA;AAIpB;;;;;;;;GAQG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,OAAgB,KAAK,SAAsB;IAC3C,OAAgB,QAAQ,WAA4C;IAE5D,EAAE,EAAS,MAAM,CAAA;IACjB,KAAK,EAAM,MAAM,CAAA;IACjB,MAAM,EAAK,MAAM,GAAG,IAAI,CAAA;IACxB,KAAK,EAAM,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,EAAE,IAAI,CAAA;IACf,SAAS,EAAE,IAAI,GAAG,IAAI,CAAA;CAC/B;AAED;;;;GAIG;AACH,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,OAAgB,KAAK,SAA6B;IAClD,OAAgB,QAAQ,WAA+E;IAE/F,EAAE,EAAc,MAAM,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,QAAQ,EAAQ,MAAM,CAAA;IACtB,IAAI,EAAY,MAAM,CAAA;IAC9B,6CAA6C;IACrC,OAAO,EAAS,MAAM,CAAA;IACtB,UAAU,EAAM,MAAM,GAAG,IAAI,CAAA;IACrC,yCAAyC;IACjC,SAAS,EAAO,MAAM,GAAG,IAAI,CAAA;IAC7B,SAAS,EAAO,IAAI,CAAA;CAC7B;AAID;;;;GAIG;AACH,qBAAa,oBAAqB,YAAW,iBAAiB;IACtD,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC;IASrE,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAYlD,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAapE,QAAQ,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9D,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,EAAE,CAAC;IAO5D,MAAM,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKnD,yEAAyE;YAC3D,aAAa;IAK3B,6DAA6D;YAC/C,YAAY;CAO3B;AAED,4EAA4E;AAC5E,wBAAgB,oBAAoB,IAAI,oBAAoB,CAE3D;AAID;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,+tBA2BvC,CAAA"}
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
* it; strict ordering needs a serializable transaction or a DB sequence.
|
|
42
42
|
*/
|
|
43
43
|
import { Model } from '@rudderjs/orm';
|
|
44
|
+
import { sanitizeConversation } from '../sanitize-conversation.js';
|
|
44
45
|
// ─── ORM Models ───────────────────────────────────────────
|
|
45
46
|
/**
|
|
46
47
|
* The thread row backing {@link OrmConversationStore}. Exposed so apps that
|
|
@@ -86,7 +87,10 @@ export class OrmConversationStore {
|
|
|
86
87
|
.where('conversationId', conversationId)
|
|
87
88
|
.orderBy('position', 'ASC')
|
|
88
89
|
.get();
|
|
89
|
-
|
|
90
|
+
// A thread persisted mid-turn (crash between the assistant row and its
|
|
91
|
+
// tool-result rows) would otherwise replay into a provider 400. Drop the
|
|
92
|
+
// incomplete turns at the load boundary so the history is replay-safe.
|
|
93
|
+
return sanitizeConversation(rows.map(rowToMessage));
|
|
90
94
|
}
|
|
91
95
|
async append(conversationId, messages) {
|
|
92
96
|
await this.requireThread(conversationId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/conversation-orm/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/conversation-orm/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { ProviderAdapter, ProviderRequestOptions, ProviderResponse, StreamChunk } from '../types.js';
|
|
2
|
+
import { type SseEvent } from './sse.js';
|
|
3
|
+
/**
|
|
4
|
+
* Connection config shared by every gateway adapter. Subclasses may extend
|
|
5
|
+
* this with gateway-specific fields (region, project id, ...).
|
|
6
|
+
*/
|
|
7
|
+
export interface GatewayAdapterConfig {
|
|
8
|
+
/** Base URL of the gateway endpoint. */
|
|
9
|
+
baseUrl: string;
|
|
10
|
+
/** Optional API key — surfaced for {@link HttpGatewayAdapter.buildHeaders}. */
|
|
11
|
+
apiKey?: string | undefined;
|
|
12
|
+
/** Static headers merged into every request (auth from `buildHeaders` wins). */
|
|
13
|
+
headers?: Record<string, string> | undefined;
|
|
14
|
+
}
|
|
15
|
+
/** Context passed to the request-shaping hooks. */
|
|
16
|
+
export interface GatewayRequestContext {
|
|
17
|
+
/** `true` for the streaming (`stream()`) path, `false` for `generate()`. */
|
|
18
|
+
stream: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Abstract template for normalizing an upstream LLM gateway behind the
|
|
22
|
+
* framework's {@link ProviderAdapter} contract.
|
|
23
|
+
*
|
|
24
|
+
* This is the Laravel custom-driver pattern (Template Method): the base class
|
|
25
|
+
* owns the reusable lifecycle — `fetch`, JSON / SSE handling, `AbortSignal`
|
|
26
|
+
* wiring, and error mapping — and leaves four `protected abstract` hooks for
|
|
27
|
+
* the gateway's wire format:
|
|
28
|
+
*
|
|
29
|
+
* - {@link buildHeaders} — the gateway's auth scheme.
|
|
30
|
+
* - {@link buildRequestBody} — map {@link ProviderRequestOptions} → the
|
|
31
|
+
* gateway's request envelope.
|
|
32
|
+
* - {@link parseResponse} — map a non-streaming response → {@link ProviderResponse}.
|
|
33
|
+
* - {@link parseStreamEvent} — map one {@link SseEvent} → zero or more
|
|
34
|
+
* {@link StreamChunk}s.
|
|
35
|
+
*
|
|
36
|
+
* Reach for this only when the gateway's wire format matches no built-in
|
|
37
|
+
* provider. An OpenAI- or Anthropic-compatible gateway needs no subclass:
|
|
38
|
+
* register the `openai` / `anthropic` driver with a `baseUrl` override instead.
|
|
39
|
+
*
|
|
40
|
+
* Register a subclass through the usual factory path — `AiRegistry.register()`
|
|
41
|
+
* (the framework's `extend()` equivalent).
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* class AcmeGatewayAdapter extends HttpGatewayAdapter {
|
|
46
|
+
* protected buildHeaders() {
|
|
47
|
+
* return { authorization: `Bearer ${this.config.apiKey}` }
|
|
48
|
+
* }
|
|
49
|
+
* protected buildRequestBody(o: ProviderRequestOptions, ctx: GatewayRequestContext) {
|
|
50
|
+
* return { model: this.model, messages: o.messages, stream: ctx.stream }
|
|
51
|
+
* }
|
|
52
|
+
* protected parseResponse(json: any): ProviderResponse {
|
|
53
|
+
* return {
|
|
54
|
+
* message: { role: 'assistant', content: json.text },
|
|
55
|
+
* usage: { promptTokens: json.usage.in, completionTokens: json.usage.out, totalTokens: json.usage.total },
|
|
56
|
+
* finishReason: 'stop',
|
|
57
|
+
* }
|
|
58
|
+
* }
|
|
59
|
+
* protected parseStreamEvent(e: SseEvent): StreamChunk[] {
|
|
60
|
+
* if (e.data === '[DONE]') return [{ type: 'finish', finishReason: 'stop' }]
|
|
61
|
+
* const { delta } = JSON.parse(e.data)
|
|
62
|
+
* return delta ? [{ type: 'text-delta', text: delta }] : []
|
|
63
|
+
* }
|
|
64
|
+
* }
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export declare abstract class HttpGatewayAdapter implements ProviderAdapter {
|
|
68
|
+
protected readonly config: GatewayAdapterConfig;
|
|
69
|
+
protected readonly model: string;
|
|
70
|
+
constructor(config: GatewayAdapterConfig, model: string);
|
|
71
|
+
generate(options: ProviderRequestOptions): Promise<ProviderResponse>;
|
|
72
|
+
stream(options: ProviderRequestOptions): AsyncIterable<StreamChunk>;
|
|
73
|
+
/** Perform the POST, wire the abort signal, and map error responses. */
|
|
74
|
+
private send;
|
|
75
|
+
/**
|
|
76
|
+
* Resolve the request URL. Defaults to {@link GatewayAdapterConfig.baseUrl}
|
|
77
|
+
* for both paths; override to append a path or branch on `ctx.stream`.
|
|
78
|
+
*/
|
|
79
|
+
protected endpoint(_ctx: GatewayRequestContext): string;
|
|
80
|
+
/**
|
|
81
|
+
* Map a non-2xx response to an error. Override to parse a gateway-specific
|
|
82
|
+
* error envelope. The default reads the body as text and throws.
|
|
83
|
+
*/
|
|
84
|
+
protected onErrorResponse(res: Response): Promise<never>;
|
|
85
|
+
/** Auth/identity headers for every request (merged over `config.headers`). */
|
|
86
|
+
protected abstract buildHeaders(): Record<string, string>;
|
|
87
|
+
/** Map the framework request to the gateway's request envelope. */
|
|
88
|
+
protected abstract buildRequestBody(options: ProviderRequestOptions, ctx: GatewayRequestContext): unknown;
|
|
89
|
+
/** Map a complete (non-streaming) gateway response to a {@link ProviderResponse}. */
|
|
90
|
+
protected abstract parseResponse(json: unknown): ProviderResponse;
|
|
91
|
+
/** Map one parsed {@link SseEvent} to zero or more {@link StreamChunk}s. */
|
|
92
|
+
protected abstract parseStreamEvent(event: SseEvent): StreamChunk[];
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=http-gateway-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-gateway-adapter.d.ts","sourceRoot":"","sources":["../../src/gateway/http-gateway-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,sBAAsB,EACtB,gBAAgB,EAChB,WAAW,EACZ,MAAM,aAAa,CAAA;AACpB,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAA;AAExD;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAA;IACf,+EAA+E;IAC/E,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAA;CAC7C;AAED,mDAAmD;AACnD,MAAM,WAAW,qBAAqB;IACpC,4EAA4E;IAC5E,MAAM,EAAE,OAAO,CAAA;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,8BAAsB,kBAAmB,YAAW,eAAe;IAE/D,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,oBAAoB;IAC/C,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM;gBADb,MAAM,EAAE,oBAAoB,EAC5B,KAAK,EAAE,MAAM;IAG5B,QAAQ,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAMnE,MAAM,CAAC,OAAO,EAAE,sBAAsB,GAAG,aAAa,CAAC,WAAW,CAAC;IAY1E,wEAAwE;YAC1D,IAAI;IAiBlB;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,qBAAqB,GAAG,MAAM;IAIvD;;;OAGG;cACa,eAAe,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAS9D,8EAA8E;IAC9E,SAAS,CAAC,QAAQ,CAAC,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAEzD,mEAAmE;IACnE,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CACjC,OAAO,EAAE,sBAAsB,EAC/B,GAAG,EAAE,qBAAqB,GACzB,OAAO;IAEV,qFAAqF;IACrF,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB;IAEjE,4EAA4E;IAC5E,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,KAAK,EAAE,QAAQ,GAAG,WAAW,EAAE;CACpE"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { parseSseStream } from './sse.js';
|
|
2
|
+
/**
|
|
3
|
+
* Abstract template for normalizing an upstream LLM gateway behind the
|
|
4
|
+
* framework's {@link ProviderAdapter} contract.
|
|
5
|
+
*
|
|
6
|
+
* This is the Laravel custom-driver pattern (Template Method): the base class
|
|
7
|
+
* owns the reusable lifecycle — `fetch`, JSON / SSE handling, `AbortSignal`
|
|
8
|
+
* wiring, and error mapping — and leaves four `protected abstract` hooks for
|
|
9
|
+
* the gateway's wire format:
|
|
10
|
+
*
|
|
11
|
+
* - {@link buildHeaders} — the gateway's auth scheme.
|
|
12
|
+
* - {@link buildRequestBody} — map {@link ProviderRequestOptions} → the
|
|
13
|
+
* gateway's request envelope.
|
|
14
|
+
* - {@link parseResponse} — map a non-streaming response → {@link ProviderResponse}.
|
|
15
|
+
* - {@link parseStreamEvent} — map one {@link SseEvent} → zero or more
|
|
16
|
+
* {@link StreamChunk}s.
|
|
17
|
+
*
|
|
18
|
+
* Reach for this only when the gateway's wire format matches no built-in
|
|
19
|
+
* provider. An OpenAI- or Anthropic-compatible gateway needs no subclass:
|
|
20
|
+
* register the `openai` / `anthropic` driver with a `baseUrl` override instead.
|
|
21
|
+
*
|
|
22
|
+
* Register a subclass through the usual factory path — `AiRegistry.register()`
|
|
23
|
+
* (the framework's `extend()` equivalent).
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* class AcmeGatewayAdapter extends HttpGatewayAdapter {
|
|
28
|
+
* protected buildHeaders() {
|
|
29
|
+
* return { authorization: `Bearer ${this.config.apiKey}` }
|
|
30
|
+
* }
|
|
31
|
+
* protected buildRequestBody(o: ProviderRequestOptions, ctx: GatewayRequestContext) {
|
|
32
|
+
* return { model: this.model, messages: o.messages, stream: ctx.stream }
|
|
33
|
+
* }
|
|
34
|
+
* protected parseResponse(json: any): ProviderResponse {
|
|
35
|
+
* return {
|
|
36
|
+
* message: { role: 'assistant', content: json.text },
|
|
37
|
+
* usage: { promptTokens: json.usage.in, completionTokens: json.usage.out, totalTokens: json.usage.total },
|
|
38
|
+
* finishReason: 'stop',
|
|
39
|
+
* }
|
|
40
|
+
* }
|
|
41
|
+
* protected parseStreamEvent(e: SseEvent): StreamChunk[] {
|
|
42
|
+
* if (e.data === '[DONE]') return [{ type: 'finish', finishReason: 'stop' }]
|
|
43
|
+
* const { delta } = JSON.parse(e.data)
|
|
44
|
+
* return delta ? [{ type: 'text-delta', text: delta }] : []
|
|
45
|
+
* }
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export class HttpGatewayAdapter {
|
|
50
|
+
config;
|
|
51
|
+
model;
|
|
52
|
+
constructor(config, model) {
|
|
53
|
+
this.config = config;
|
|
54
|
+
this.model = model;
|
|
55
|
+
}
|
|
56
|
+
async generate(options) {
|
|
57
|
+
const res = await this.send(options, { stream: false });
|
|
58
|
+
const json = (await res.json());
|
|
59
|
+
return this.parseResponse(json);
|
|
60
|
+
}
|
|
61
|
+
async *stream(options) {
|
|
62
|
+
const res = await this.send(options, { stream: true });
|
|
63
|
+
if (!res.body) {
|
|
64
|
+
throw new Error('[RudderJS AI] Gateway stream response had no body');
|
|
65
|
+
}
|
|
66
|
+
for await (const event of parseSseStream(res.body, options.signal)) {
|
|
67
|
+
for (const chunk of this.parseStreamEvent(event))
|
|
68
|
+
yield chunk;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// ─── reusable plumbing ─────────────────────────────────────
|
|
72
|
+
/** Perform the POST, wire the abort signal, and map error responses. */
|
|
73
|
+
async send(options, ctx) {
|
|
74
|
+
const headers = {
|
|
75
|
+
'content-type': 'application/json',
|
|
76
|
+
accept: ctx.stream ? 'text/event-stream' : 'application/json',
|
|
77
|
+
...this.config.headers,
|
|
78
|
+
...this.buildHeaders(),
|
|
79
|
+
};
|
|
80
|
+
const res = await fetch(this.endpoint(ctx), {
|
|
81
|
+
method: 'POST',
|
|
82
|
+
headers,
|
|
83
|
+
body: JSON.stringify(this.buildRequestBody(options, ctx)),
|
|
84
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
85
|
+
});
|
|
86
|
+
if (!res.ok)
|
|
87
|
+
await this.onErrorResponse(res);
|
|
88
|
+
return res;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Resolve the request URL. Defaults to {@link GatewayAdapterConfig.baseUrl}
|
|
92
|
+
* for both paths; override to append a path or branch on `ctx.stream`.
|
|
93
|
+
*/
|
|
94
|
+
endpoint(_ctx) {
|
|
95
|
+
return this.config.baseUrl;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Map a non-2xx response to an error. Override to parse a gateway-specific
|
|
99
|
+
* error envelope. The default reads the body as text and throws.
|
|
100
|
+
*/
|
|
101
|
+
async onErrorResponse(res) {
|
|
102
|
+
const body = await res.text().catch(() => '');
|
|
103
|
+
throw new Error(`[RudderJS AI] Gateway request failed: ${res.status} ${res.statusText}${body ? ` — ${body}` : ''}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=http-gateway-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-gateway-adapter.js","sourceRoot":"","sources":["../../src/gateway/http-gateway-adapter.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAiB,MAAM,UAAU,CAAA;AAqBxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,MAAM,OAAgB,kBAAkB;IAEjB;IACA;IAFrB,YACqB,MAA4B,EAC5B,KAAa;QADb,WAAM,GAAN,MAAM,CAAsB;QAC5B,UAAK,GAAL,KAAK,CAAQ;IAC/B,CAAC;IAEJ,KAAK,CAAC,QAAQ,CAAC,OAA+B;QAC5C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;QACvD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAY,CAAA;QAC1C,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAA;IACjC,CAAC;IAED,KAAK,CAAC,CAAC,MAAM,CAAC,OAA+B;QAC3C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;QACtD,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAA;QACtE,CAAC;QACD,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnE,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC;gBAAE,MAAM,KAAK,CAAA;QAC/D,CAAC;IACH,CAAC;IAED,8DAA8D;IAE9D,wEAAwE;IAChE,KAAK,CAAC,IAAI,CAAC,OAA+B,EAAE,GAA0B;QAC5E,MAAM,OAAO,GAA2B;YACtC,cAAc,EAAE,kBAAkB;YAClC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,kBAAkB;YAC7D,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO;YACtB,GAAG,IAAI,CAAC,YAAY,EAAE;SACvB,CAAA;QACD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;YAC1C,MAAM,EAAE,MAAM;YACd,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACzD,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACtD,CAAC,CAAA;QACF,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAA;QAC5C,OAAO,GAAG,CAAA;IACZ,CAAC;IAED;;;OAGG;IACO,QAAQ,CAAC,IAA2B;QAC5C,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAA;IAC5B,CAAC;IAED;;;OAGG;IACO,KAAK,CAAC,eAAe,CAAC,GAAa;QAC3C,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;QAC7C,MAAM,IAAI,KAAK,CACb,yCAAyC,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACnG,CAAA;IACH,CAAC;CAkBF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@rudderjs/ai/gateway` — abstract template for normalizing an upstream LLM
|
|
3
|
+
* gateway (its own auth scheme + request/response/SSE envelope) behind the
|
|
4
|
+
* framework's {@link ProviderAdapter} contract.
|
|
5
|
+
*
|
|
6
|
+
* See {@link HttpGatewayAdapter} for when to reach for this versus a `baseUrl`
|
|
7
|
+
* override on an OpenAI/Anthropic-compatible provider.
|
|
8
|
+
*/
|
|
9
|
+
export { HttpGatewayAdapter, type GatewayAdapterConfig, type GatewayRequestContext, } from './http-gateway-adapter.js';
|
|
10
|
+
export { parseSseStream, type SseEvent } from './sse.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/gateway/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,kBAAkB,EAClB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@rudderjs/ai/gateway` — abstract template for normalizing an upstream LLM
|
|
3
|
+
* gateway (its own auth scheme + request/response/SSE envelope) behind the
|
|
4
|
+
* framework's {@link ProviderAdapter} contract.
|
|
5
|
+
*
|
|
6
|
+
* See {@link HttpGatewayAdapter} for when to reach for this versus a `baseUrl`
|
|
7
|
+
* override on an OpenAI/Anthropic-compatible provider.
|
|
8
|
+
*/
|
|
9
|
+
export { HttpGatewayAdapter, } from './http-gateway-adapter.js';
|
|
10
|
+
export { parseSseStream } from './sse.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/gateway/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,kBAAkB,GAGnB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAE,cAAc,EAAiB,MAAM,UAAU,CAAA"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A single Server-Sent Event frame, parsed from a `text/event-stream` body.
|
|
3
|
+
*
|
|
4
|
+
* Only the two fields LLM gateways use in practice are surfaced: the optional
|
|
5
|
+
* `event:` name and the (possibly multi-line) `data:` payload. Comment lines
|
|
6
|
+
* (`:`-prefixed) and `id:` / `retry:` fields are consumed and ignored.
|
|
7
|
+
*/
|
|
8
|
+
export interface SseEvent {
|
|
9
|
+
/** The `event:` field, if the frame declared one. */
|
|
10
|
+
event?: string | undefined;
|
|
11
|
+
/** The concatenated `data:` payload (multiple `data:` lines joined by `\n`). */
|
|
12
|
+
data: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Frame a `text/event-stream` response body into {@link SseEvent}s.
|
|
16
|
+
*
|
|
17
|
+
* Standalone and dependency-free so the gateway template ships its own
|
|
18
|
+
* framing — every built-in chat provider streams through a vendor SDK, so
|
|
19
|
+
* there is no shared framer to reuse. Handles `\n` and `\r\n` line endings,
|
|
20
|
+
* multi-line `data:` payloads, and back-pressure-friendly chunk boundaries
|
|
21
|
+
* (an event split across two network reads is buffered until complete).
|
|
22
|
+
*
|
|
23
|
+
* Aborts cleanly: when `signal` fires, the reader is cancelled and iteration
|
|
24
|
+
* ends. A trailing event with no terminating blank line is still yielded once
|
|
25
|
+
* the stream closes.
|
|
26
|
+
*/
|
|
27
|
+
export declare function parseSseStream(body: ReadableStream<Uint8Array>, signal?: AbortSignal): AsyncGenerator<SseEvent>;
|
|
28
|
+
//# sourceMappingURL=sse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../src/gateway/sse.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACvB,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;;;;;;;;;;;GAYG;AACH,wBAAuB,cAAc,CACnC,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,EAChC,MAAM,CAAC,EAAE,WAAW,GACnB,cAAc,CAAC,QAAQ,CAAC,CAuC1B"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frame a `text/event-stream` response body into {@link SseEvent}s.
|
|
3
|
+
*
|
|
4
|
+
* Standalone and dependency-free so the gateway template ships its own
|
|
5
|
+
* framing — every built-in chat provider streams through a vendor SDK, so
|
|
6
|
+
* there is no shared framer to reuse. Handles `\n` and `\r\n` line endings,
|
|
7
|
+
* multi-line `data:` payloads, and back-pressure-friendly chunk boundaries
|
|
8
|
+
* (an event split across two network reads is buffered until complete).
|
|
9
|
+
*
|
|
10
|
+
* Aborts cleanly: when `signal` fires, the reader is cancelled and iteration
|
|
11
|
+
* ends. A trailing event with no terminating blank line is still yielded once
|
|
12
|
+
* the stream closes.
|
|
13
|
+
*/
|
|
14
|
+
export async function* parseSseStream(body, signal) {
|
|
15
|
+
const reader = body.getReader();
|
|
16
|
+
const decoder = new TextDecoder();
|
|
17
|
+
let buffer = '';
|
|
18
|
+
const onAbort = () => {
|
|
19
|
+
void reader.cancel().catch(() => { });
|
|
20
|
+
};
|
|
21
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
22
|
+
try {
|
|
23
|
+
while (true) {
|
|
24
|
+
if (signal?.aborted)
|
|
25
|
+
return;
|
|
26
|
+
const { done, value } = await reader.read();
|
|
27
|
+
if (done)
|
|
28
|
+
break;
|
|
29
|
+
buffer += decoder.decode(value, { stream: true });
|
|
30
|
+
// Events are separated by a blank line. Normalize CRLF to LF first so a
|
|
31
|
+
// single split handles both endings.
|
|
32
|
+
let sep;
|
|
33
|
+
buffer = buffer.replace(/\r\n/g, '\n');
|
|
34
|
+
while ((sep = buffer.indexOf('\n\n')) !== -1) {
|
|
35
|
+
const raw = buffer.slice(0, sep);
|
|
36
|
+
buffer = buffer.slice(sep + 2);
|
|
37
|
+
const event = parseFrame(raw);
|
|
38
|
+
if (event)
|
|
39
|
+
yield event;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Flush a final frame that arrived without a trailing blank line.
|
|
43
|
+
const tail = (buffer + decoder.decode()).replace(/\r\n/g, '\n').trim();
|
|
44
|
+
if (tail) {
|
|
45
|
+
const event = parseFrame(tail);
|
|
46
|
+
if (event)
|
|
47
|
+
yield event;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
signal?.removeEventListener('abort', onAbort);
|
|
52
|
+
reader.releaseLock();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** Parse one raw SSE frame (the text between blank-line separators). */
|
|
56
|
+
function parseFrame(raw) {
|
|
57
|
+
let event;
|
|
58
|
+
const dataLines = [];
|
|
59
|
+
for (const line of raw.split('\n')) {
|
|
60
|
+
if (line === '' || line.startsWith(':'))
|
|
61
|
+
continue; // blank or comment
|
|
62
|
+
const colon = line.indexOf(':');
|
|
63
|
+
const field = colon === -1 ? line : line.slice(0, colon);
|
|
64
|
+
// Per spec, a single leading space after the colon is stripped.
|
|
65
|
+
let value = colon === -1 ? '' : line.slice(colon + 1);
|
|
66
|
+
if (value.startsWith(' '))
|
|
67
|
+
value = value.slice(1);
|
|
68
|
+
if (field === 'event')
|
|
69
|
+
event = value;
|
|
70
|
+
else if (field === 'data')
|
|
71
|
+
dataLines.push(value);
|
|
72
|
+
// id / retry / unknown fields ignored
|
|
73
|
+
}
|
|
74
|
+
if (dataLines.length === 0 && event === undefined)
|
|
75
|
+
return null;
|
|
76
|
+
return { ...(event !== undefined ? { event } : {}), data: dataLines.join('\n') };
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=sse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../../src/gateway/sse.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export { QueuedPromptBuilder } from './queue-job.js';
|
|
|
27
27
|
export { runOnConfig, runOnChunk, runOnBeforeToolCall, runOnAfterToolCall, runSequential, runOnUsage, runOnAbort, runOnError } from './middleware.js';
|
|
28
28
|
export { Output, type OutputWrapper } from './output.js';
|
|
29
29
|
export { MemoryConversationStore } from './conversation.js';
|
|
30
|
+
export { sanitizeConversation } from './sanitize-conversation.js';
|
|
30
31
|
export { validateContinuation, assertValidContinuation, defaultContinuationValidator, ContinuationValidationError, } from './continuation-validation.js';
|
|
31
32
|
export type { ContinuationValidationResult, ContinuationRejectionCode, ContinuationValidator, ValidateContinuationOptions, } from './continuation-validation.js';
|
|
32
33
|
export { MemoryUserMemory, resolveRemembersSpec } from './memory.js';
|
|
@@ -43,6 +44,8 @@ export { AudioGenerator } from './audio.js';
|
|
|
43
44
|
export { Transcription } from './transcription.js';
|
|
44
45
|
export { WebSearch, WebFetch, CodeExecution } from './provider-tools.js';
|
|
45
46
|
export { toVercelDataStream, toVercelResponse } from './vercel-protocol.js';
|
|
47
|
+
export { toAgentSseStream, toAgentSseResponse, readAgentStream, applyAgentSseEvent, newAgentStreamTurn, } from './agent-sse.js';
|
|
48
|
+
export type { AgentSseEventName, AgentAwaiting, AgentSseTextPayload, AgentSseToolCallPayload, AgentSseToolUpdatePayload, AgentSseToolResultPayload, AgentSsePendingClientToolsPayload, AgentSseApprovalPayload, AgentSseHandoffPayload, AgentSseCompletePayload, AgentSseErrorPayload, AgentStreamTurn, AgentStreamCallbacks, } from './agent-sse.js';
|
|
46
49
|
export { Reranker } from './rerank.js';
|
|
47
50
|
export { FileManager } from './files.js';
|
|
48
51
|
export { VectorStores, VectorStore } from './vector-stores/index.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,7 @@ export { runOnConfig, runOnChunk, runOnBeforeToolCall, runOnAfterToolCall, runSe
|
|
|
33
33
|
export { Output } from './output.js';
|
|
34
34
|
// Conversation
|
|
35
35
|
export { MemoryConversationStore } from './conversation.js';
|
|
36
|
+
export { sanitizeConversation } from './sanitize-conversation.js';
|
|
36
37
|
export { validateContinuation, assertValidContinuation, defaultContinuationValidator, ContinuationValidationError, } from './continuation-validation.js';
|
|
37
38
|
// User Memory (#A4)
|
|
38
39
|
export { MemoryUserMemory, resolveRemembersSpec } from './memory.js';
|
|
@@ -53,6 +54,7 @@ export { Transcription } from './transcription.js';
|
|
|
53
54
|
export { WebSearch, WebFetch, CodeExecution } from './provider-tools.js';
|
|
54
55
|
// Vercel AI Protocol
|
|
55
56
|
export { toVercelDataStream, toVercelResponse } from './vercel-protocol.js';
|
|
57
|
+
export { toAgentSseStream, toAgentSseResponse, readAgentStream, applyAgentSseEvent, newAgentStreamTurn, } from './agent-sse.js';
|
|
56
58
|
// Reranking
|
|
57
59
|
export { Reranker } from './rerank.js';
|
|
58
60
|
// File Management
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Make a loaded conversation history safe to replay against any provider by
|
|
3
|
+
* enforcing the tool-call / tool-result invariant in BOTH directions.
|
|
4
|
+
*
|
|
5
|
+
* Anthropic's Messages API requires every `tool_use` block to be followed by
|
|
6
|
+
* `tool_result` blocks for all of its ids. OpenAI-compatible providers
|
|
7
|
+
* (DeepSeek, OpenRouter, Azure) are stricter still: a `role:'tool'` message
|
|
8
|
+
* must immediately follow the `assistant` + `tool_calls` that declared its id,
|
|
9
|
+
* and an unanswered `tool_calls` is equally rejected, surfacing as
|
|
10
|
+
* `400 Messages with role 'tool' must be a response to a preceding message
|
|
11
|
+
* with 'tool_calls'`. A conversation interrupted mid-turn (a crash after the
|
|
12
|
+
* assistant message persisted but before all tool results landed; a client
|
|
13
|
+
* failure that never replayed the results) leaves a malformed graph in the
|
|
14
|
+
* store, and replaying it 400s.
|
|
15
|
+
*
|
|
16
|
+
* {@link sanitizeConversation} walks the messages in order:
|
|
17
|
+
*
|
|
18
|
+
* - **Complete tool turn** (every declared id has a matching result in the
|
|
19
|
+
* immediately-following tool run) is kept, with the results re-emitted in
|
|
20
|
+
* `toolCalls` order, exactly one per call. Any extra / duplicate / orphan
|
|
21
|
+
* tool message interleaved in that run is dropped.
|
|
22
|
+
* - **Dangling tool turn** (one or more declared ids unanswered) has its
|
|
23
|
+
* assistant `toolCalls` stripped; the text `content` is preserved as a
|
|
24
|
+
* plain assistant message (an empty one is dropped entirely); the partial
|
|
25
|
+
* tool results are dropped.
|
|
26
|
+
* - **Orphan tool result** (a `role:'tool'` message whose parent assistant
|
|
27
|
+
* is missing or was dropped as dangling) is dropped. Replaying it trips
|
|
28
|
+
* the 400 above on OpenAI-compatible providers and a BadRequestError on
|
|
29
|
+
* Anthropic.
|
|
30
|
+
*
|
|
31
|
+
* Unlike the wire-level normalizer the provider adapters apply (which
|
|
32
|
+
* SYNTHESIZES stub results so an in-flight request stays well-formed), the
|
|
33
|
+
* load boundary DROPS incomplete turns: an interrupted turn is abandoned
|
|
34
|
+
* history, and a fake "result missing" message would pollute the model's
|
|
35
|
+
* future context.
|
|
36
|
+
*
|
|
37
|
+
* Pure and idempotent: safe to apply at any load boundary, and re-running over
|
|
38
|
+
* an already-sanitized array is a no-op. {@link OrmConversationStore} applies
|
|
39
|
+
* it in `load()` so persisted histories are replay-safe by default.
|
|
40
|
+
*/
|
|
41
|
+
import type { AiMessage } from './types.js';
|
|
42
|
+
export declare function sanitizeConversation(messages: AiMessage[]): AiMessage[];
|
|
43
|
+
//# sourceMappingURL=sanitize-conversation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize-conversation.d.ts","sourceRoot":"","sources":["../src/sanitize-conversation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE3C,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAgDvE"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Make a loaded conversation history safe to replay against any provider by
|
|
3
|
+
* enforcing the tool-call / tool-result invariant in BOTH directions.
|
|
4
|
+
*
|
|
5
|
+
* Anthropic's Messages API requires every `tool_use` block to be followed by
|
|
6
|
+
* `tool_result` blocks for all of its ids. OpenAI-compatible providers
|
|
7
|
+
* (DeepSeek, OpenRouter, Azure) are stricter still: a `role:'tool'` message
|
|
8
|
+
* must immediately follow the `assistant` + `tool_calls` that declared its id,
|
|
9
|
+
* and an unanswered `tool_calls` is equally rejected, surfacing as
|
|
10
|
+
* `400 Messages with role 'tool' must be a response to a preceding message
|
|
11
|
+
* with 'tool_calls'`. A conversation interrupted mid-turn (a crash after the
|
|
12
|
+
* assistant message persisted but before all tool results landed; a client
|
|
13
|
+
* failure that never replayed the results) leaves a malformed graph in the
|
|
14
|
+
* store, and replaying it 400s.
|
|
15
|
+
*
|
|
16
|
+
* {@link sanitizeConversation} walks the messages in order:
|
|
17
|
+
*
|
|
18
|
+
* - **Complete tool turn** (every declared id has a matching result in the
|
|
19
|
+
* immediately-following tool run) is kept, with the results re-emitted in
|
|
20
|
+
* `toolCalls` order, exactly one per call. Any extra / duplicate / orphan
|
|
21
|
+
* tool message interleaved in that run is dropped.
|
|
22
|
+
* - **Dangling tool turn** (one or more declared ids unanswered) has its
|
|
23
|
+
* assistant `toolCalls` stripped; the text `content` is preserved as a
|
|
24
|
+
* plain assistant message (an empty one is dropped entirely); the partial
|
|
25
|
+
* tool results are dropped.
|
|
26
|
+
* - **Orphan tool result** (a `role:'tool'` message whose parent assistant
|
|
27
|
+
* is missing or was dropped as dangling) is dropped. Replaying it trips
|
|
28
|
+
* the 400 above on OpenAI-compatible providers and a BadRequestError on
|
|
29
|
+
* Anthropic.
|
|
30
|
+
*
|
|
31
|
+
* Unlike the wire-level normalizer the provider adapters apply (which
|
|
32
|
+
* SYNTHESIZES stub results so an in-flight request stays well-formed), the
|
|
33
|
+
* load boundary DROPS incomplete turns: an interrupted turn is abandoned
|
|
34
|
+
* history, and a fake "result missing" message would pollute the model's
|
|
35
|
+
* future context.
|
|
36
|
+
*
|
|
37
|
+
* Pure and idempotent: safe to apply at any load boundary, and re-running over
|
|
38
|
+
* an already-sanitized array is a no-op. {@link OrmConversationStore} applies
|
|
39
|
+
* it in `load()` so persisted histories are replay-safe by default.
|
|
40
|
+
*/
|
|
41
|
+
export function sanitizeConversation(messages) {
|
|
42
|
+
const result = [];
|
|
43
|
+
for (let i = 0; i < messages.length; i++) {
|
|
44
|
+
const msg = messages[i];
|
|
45
|
+
// A `tool` message reaching the top level was not consumed by a complete
|
|
46
|
+
// assistant turn below (those advance `i` past their results), so its
|
|
47
|
+
// parent is missing or was dropped as dangling. It is an orphan; drop it.
|
|
48
|
+
if (msg.role === 'tool')
|
|
49
|
+
continue;
|
|
50
|
+
if (msg.role !== 'assistant' || !msg.toolCalls?.length) {
|
|
51
|
+
result.push(msg);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const wanted = msg.toolCalls.map(tc => tc.id).filter(Boolean);
|
|
55
|
+
// Map the immediately-following tool run by id (first result per id wins).
|
|
56
|
+
const resultsById = new Map();
|
|
57
|
+
let j = i + 1;
|
|
58
|
+
while (j < messages.length && messages[j].role === 'tool') {
|
|
59
|
+
const t = messages[j];
|
|
60
|
+
const tid = t.toolCallId;
|
|
61
|
+
if (tid && !resultsById.has(tid))
|
|
62
|
+
resultsById.set(tid, t);
|
|
63
|
+
j++;
|
|
64
|
+
}
|
|
65
|
+
const allCovered = wanted.every(id => resultsById.has(id));
|
|
66
|
+
if (allCovered) {
|
|
67
|
+
// Emit the assistant followed by exactly one result per call, in
|
|
68
|
+
// `toolCalls` order. This normalizes ordering and drops any extra /
|
|
69
|
+
// orphan tool message that was interleaved in the run.
|
|
70
|
+
result.push(msg);
|
|
71
|
+
for (const tc of msg.toolCalls)
|
|
72
|
+
result.push(resultsById.get(tc.id));
|
|
73
|
+
i = j - 1;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
// Dangling: strip toolCalls, drop the partial tool results, keep any text.
|
|
77
|
+
const text = typeof msg.content === 'string' ? msg.content : '';
|
|
78
|
+
if (text.trim() !== '') {
|
|
79
|
+
result.push({ role: 'assistant', content: msg.content });
|
|
80
|
+
}
|
|
81
|
+
i = j - 1;
|
|
82
|
+
}
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=sanitize-conversation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize-conversation.js","sourceRoot":"","sources":["../src/sanitize-conversation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAIH,MAAM,UAAU,oBAAoB,CAAC,QAAqB;IACxD,MAAM,MAAM,GAAgB,EAAE,CAAA;IAE9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAE,CAAA;QAExB,yEAAyE;QACzE,sEAAsE;QACtE,0EAA0E;QAC1E,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM;YAAE,SAAQ;QAEjC,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;YACvD,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAChB,SAAQ;QACV,CAAC;QAED,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QAE7D,2EAA2E;QAC3E,MAAM,WAAW,GAAG,IAAI,GAAG,EAAqB,CAAA;QAChD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACb,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAE,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC3D,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAE,CAAA;YACtB,MAAM,GAAG,GAAG,CAAC,CAAC,UAAU,CAAA;YACxB,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;YACzD,CAAC,EAAE,CAAA;QACL,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;QAC1D,IAAI,UAAU,EAAE,CAAC;YACf,iEAAiE;YACjE,oEAAoE;YACpE,uDAAuD;YACvD,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAChB,KAAK,MAAM,EAAE,IAAI,GAAG,CAAC,SAAS;gBAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAE,CAAC,CAAA;YACpE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACT,SAAQ;QACV,CAAC;QAED,2EAA2E;QAC3E,MAAM,IAAI,GAAG,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;QAC/D,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACvB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAA;QAC1D,CAAC;QACD,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACX,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rudderjs/ai",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
4
4
|
"description": "AI engine — providers, agents, tools, streaming, middleware",
|
|
5
5
|
"rudderjs": {
|
|
6
6
|
"provider": "AiProvider",
|
|
@@ -64,6 +64,10 @@
|
|
|
64
64
|
"import": "./dist/conversation-orm/index.js",
|
|
65
65
|
"types": "./dist/conversation-orm/index.d.ts"
|
|
66
66
|
},
|
|
67
|
+
"./gateway": {
|
|
68
|
+
"import": "./dist/gateway/index.js",
|
|
69
|
+
"types": "./dist/gateway/index.d.ts"
|
|
70
|
+
},
|
|
67
71
|
"./memory-orm": {
|
|
68
72
|
"import": "./dist/memory-orm/index.js",
|
|
69
73
|
"types": "./dist/memory-orm/index.d.ts"
|