@alexkroman1/aai 0.10.2 → 0.10.4
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/_internal-types.d.ts +8 -1
- package/dist/_runtime-conformance.d.ts +64 -0
- package/dist/_test-utils.d.ts +70 -0
- package/dist/_utils.d.ts +1 -8
- package/dist/_utils.js +1 -13
- package/dist/builtin-tools.d.ts +1 -5
- package/dist/constants-BbAOvKl_.js +47 -0
- package/dist/constants.d.ts +44 -0
- package/dist/direct-executor-BfHrDdPL.js +1589 -0
- package/dist/direct-executor.d.ts +90 -31
- package/dist/hooks.d.ts +44 -0
- package/dist/hooks.js +58 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.js +2 -2
- package/dist/internal.d.ts +19 -0
- package/dist/internal.js +209 -0
- package/dist/kv.d.ts +1 -1
- package/dist/kv.js +5 -4
- package/dist/matchers.js +1 -1
- package/dist/protocol.d.ts +3 -29
- package/dist/protocol.js +2 -24
- package/dist/server.d.ts +25 -38
- package/dist/server.js +114 -138
- package/dist/session.d.ts +65 -44
- package/dist/{testing-MRl3SXsI.js → testing-BonJtfHJ.js} +26 -46
- package/dist/testing.d.ts +9 -14
- package/dist/testing.js +2 -2
- package/dist/types.d.ts +24 -226
- package/dist/types.js +6 -22
- package/dist/types.test-d.d.ts +7 -0
- package/dist/unstorage-kv.d.ts +33 -0
- package/dist/vite-plugin.d.ts +15 -0
- package/dist/vite-plugin.js +82 -0
- package/dist/ws-handler.d.ts +1 -2
- package/package.json +29 -84
- package/dist/_internal-types.js +0 -61
- package/dist/_session-ctx.d.ts +0 -73
- package/dist/_session-otel.d.ts +0 -43
- package/dist/_session-persist.d.ts +0 -30
- package/dist/_ssrf.d.ts +0 -30
- package/dist/_ssrf.js +0 -123
- package/dist/direct-executor-Ca0wt5H0.js +0 -572
- package/dist/middleware-core.d.ts +0 -47
- package/dist/middleware-core.js +0 -107
- package/dist/middleware.d.ts +0 -37
- package/dist/runtime.js +0 -53
- package/dist/s2s.js +0 -272
- package/dist/session-BkN9u0ni.js +0 -683
- package/dist/session.js +0 -2
- package/dist/sqlite-kv.d.ts +0 -34
- package/dist/sqlite-kv.js +0 -133
- package/dist/sqlite-vector.d.ts +0 -58
- package/dist/sqlite-vector.js +0 -149
- package/dist/telemetry.d.ts +0 -49
- package/dist/telemetry.js +0 -95
- package/dist/vector.d.ts +0 -85
- package/dist/vector.js +0 -49
- package/dist/worker-entry.d.ts +0 -47
- package/dist/worker-entry.js +0 -70
- package/dist/ws-handler.js +0 -207
package/dist/worker-entry.d.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Worker entry point — shared tool execution logic.
|
|
3
|
-
*/
|
|
4
|
-
import type { Kv } from "./kv.ts";
|
|
5
|
-
import type { Logger } from "./runtime.ts";
|
|
6
|
-
import type { Message, ToolDef } from "./types.ts";
|
|
7
|
-
import type { VectorStore } from "./vector.ts";
|
|
8
|
-
/**
|
|
9
|
-
* Function signature for executing a tool by name.
|
|
10
|
-
*
|
|
11
|
-
* @param name - The tool name to execute.
|
|
12
|
-
* @param args - Key-value arguments to pass to the tool handler.
|
|
13
|
-
* @param sessionId - Optional session identifier for stateful tools.
|
|
14
|
-
* @param messages - Optional conversation history for context-aware tools.
|
|
15
|
-
* @returns The tool's string result, or an error message string.
|
|
16
|
-
*/
|
|
17
|
-
export type ExecuteTool = (name: string, args: Readonly<Record<string, unknown>>, sessionId?: string, messages?: readonly Message[], onUpdate?: (data: unknown) => void) => Promise<string>;
|
|
18
|
-
/** Options for {@link executeToolCall}. */
|
|
19
|
-
export type ExecuteToolCallOptions = {
|
|
20
|
-
tool: ToolDef;
|
|
21
|
-
env: Readonly<Record<string, string>>;
|
|
22
|
-
state?: Record<string, unknown>;
|
|
23
|
-
sessionId?: string | undefined;
|
|
24
|
-
kv?: Kv | undefined;
|
|
25
|
-
vector?: VectorStore | undefined;
|
|
26
|
-
messages?: readonly Message[] | undefined;
|
|
27
|
-
logger?: Logger | undefined;
|
|
28
|
-
/** Callback for intermediate UI updates from `ctx.sendUpdate()`. */
|
|
29
|
-
onUpdate?: ((data: unknown) => void) | undefined;
|
|
30
|
-
/** Override fetch implementation for the tool context. */
|
|
31
|
-
fetch?: typeof globalThis.fetch | undefined;
|
|
32
|
-
};
|
|
33
|
-
/**
|
|
34
|
-
* Execute a tool call with argument validation and error handling.
|
|
35
|
-
*
|
|
36
|
-
* Validates the provided arguments against the tool's Zod parameter schema,
|
|
37
|
-
* constructs a {@link ToolContext}, invokes the tool's `execute` function,
|
|
38
|
-
* and serializes the result to a string. Errors (validation failures,
|
|
39
|
-
* execution throws, timeouts) are caught and returned as JSON strings
|
|
40
|
-
* via {@link toolError} (`'{"error":"<message>"}'`) rather than thrown.
|
|
41
|
-
*
|
|
42
|
-
* @param name - The name of the tool being invoked.
|
|
43
|
-
* @param args - Raw arguments from the LLM to validate and pass to the tool.
|
|
44
|
-
* @param options - Tool definition, environment, and optional context.
|
|
45
|
-
* @returns The tool's result serialized as a string, or an error message.
|
|
46
|
-
*/
|
|
47
|
-
export declare function executeToolCall(name: string, args: Readonly<Record<string, unknown>>, options: ExecuteToolCallOptions): Promise<string>;
|
package/dist/worker-entry.js
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { EMPTY_PARAMS } from "./_internal-types.js";
|
|
2
|
-
import { errorDetail, errorMessage, toolError } from "./_utils.js";
|
|
3
|
-
import { TOOL_EXECUTION_TIMEOUT_MS } from "./protocol.js";
|
|
4
|
-
//#region worker-entry.ts
|
|
5
|
-
/** Yield to the event loop so pending I/O (e.g. WebSocket frames) can be processed. */
|
|
6
|
-
const yieldTick = () => new Promise((r) => setTimeout(r, 0));
|
|
7
|
-
function buildToolContext(opts) {
|
|
8
|
-
const { env, state, kv, vector, messages, onUpdate, fetch: fetchFn, sessionId } = opts;
|
|
9
|
-
return {
|
|
10
|
-
env: { ...env },
|
|
11
|
-
state: state ?? {},
|
|
12
|
-
get kv() {
|
|
13
|
-
if (!kv) throw new Error("KV not available");
|
|
14
|
-
return kv;
|
|
15
|
-
},
|
|
16
|
-
get vector() {
|
|
17
|
-
if (!vector) throw new Error("Vector store not available");
|
|
18
|
-
return vector;
|
|
19
|
-
},
|
|
20
|
-
messages: messages ?? [],
|
|
21
|
-
sendUpdate(data) {
|
|
22
|
-
onUpdate?.(data);
|
|
23
|
-
},
|
|
24
|
-
fetch: fetchFn ?? globalThis.fetch,
|
|
25
|
-
sessionId: sessionId ?? ""
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Execute a tool call with argument validation and error handling.
|
|
30
|
-
*
|
|
31
|
-
* Validates the provided arguments against the tool's Zod parameter schema,
|
|
32
|
-
* constructs a {@link ToolContext}, invokes the tool's `execute` function,
|
|
33
|
-
* and serializes the result to a string. Errors (validation failures,
|
|
34
|
-
* execution throws, timeouts) are caught and returned as JSON strings
|
|
35
|
-
* via {@link toolError} (`'{"error":"<message>"}'`) rather than thrown.
|
|
36
|
-
*
|
|
37
|
-
* @param name - The name of the tool being invoked.
|
|
38
|
-
* @param args - Raw arguments from the LLM to validate and pass to the tool.
|
|
39
|
-
* @param options - Tool definition, environment, and optional context.
|
|
40
|
-
* @returns The tool's result serialized as a string, or an error message.
|
|
41
|
-
*/
|
|
42
|
-
async function executeToolCall(name, args, options) {
|
|
43
|
-
const { tool } = options;
|
|
44
|
-
const parsed = (tool.parameters ?? EMPTY_PARAMS).safeParse(args);
|
|
45
|
-
if (!parsed.success) return toolError(`Invalid arguments for tool "${name}": ${(parsed.error?.issues ?? []).map((i) => `${i.path.map(String).join(".")}: ${i.message}`).join(", ")}`);
|
|
46
|
-
let timer;
|
|
47
|
-
try {
|
|
48
|
-
const ctx = buildToolContext(options);
|
|
49
|
-
await yieldTick();
|
|
50
|
-
const timeout = new Promise((_, reject) => {
|
|
51
|
-
timer = setTimeout(() => reject(/* @__PURE__ */ new Error(`Tool "${name}" timed out after ${TOOL_EXECUTION_TIMEOUT_MS}ms`)), TOOL_EXECUTION_TIMEOUT_MS);
|
|
52
|
-
});
|
|
53
|
-
const result = await Promise.race([Promise.resolve(tool.execute(parsed.data, ctx)), timeout]);
|
|
54
|
-
await yieldTick();
|
|
55
|
-
if (result == null) return "null";
|
|
56
|
-
return typeof result === "string" ? result : JSON.stringify(result);
|
|
57
|
-
} catch (err) {
|
|
58
|
-
const log = options.logger;
|
|
59
|
-
if (log) log.warn("Tool execution failed", {
|
|
60
|
-
tool: name,
|
|
61
|
-
error: errorDetail(err)
|
|
62
|
-
});
|
|
63
|
-
else console.warn(`[tool-executor] Tool execution failed: ${name}`, err);
|
|
64
|
-
return toolError(errorMessage(err));
|
|
65
|
-
} finally {
|
|
66
|
-
clearTimeout(timer);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
//#endregion
|
|
70
|
-
export { executeToolCall };
|
package/dist/ws-handler.js
DELETED
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import { errorDetail, errorMessage } from "./_utils.js";
|
|
2
|
-
import { ClientMessageSchema } from "./protocol.js";
|
|
3
|
-
import { consoleLogger } from "./runtime.js";
|
|
4
|
-
import { tracer, wsSendDroppedCounter } from "./telemetry.js";
|
|
5
|
-
//#region ws-handler.ts
|
|
6
|
-
/**
|
|
7
|
-
* WebSocket session lifecycle handler.
|
|
8
|
-
*
|
|
9
|
-
* Audio validation is handled at the host transport layer (see server.ts).
|
|
10
|
-
*/
|
|
11
|
-
/** Default timeout for session.start() in milliseconds. */
|
|
12
|
-
const DEFAULT_SESSION_START_TIMEOUT_MS = 1e4;
|
|
13
|
-
/**
|
|
14
|
-
* Creates a {@link ClientSink} backed by a plain WebSocket.
|
|
15
|
-
*
|
|
16
|
-
* Text events are sent as JSON text frames; audio chunks are sent as
|
|
17
|
-
* binary frames (zero-copy).
|
|
18
|
-
*/
|
|
19
|
-
function createClientSink(ws, log) {
|
|
20
|
-
/** Send data over ws, silently dropping if the socket is not open. */
|
|
21
|
-
function safeSend(data) {
|
|
22
|
-
try {
|
|
23
|
-
if (ws.readyState !== 1) return;
|
|
24
|
-
ws.send(data);
|
|
25
|
-
} catch (err) {
|
|
26
|
-
log.debug?.("safeSend: socket closed between readyState check and send", { error: err instanceof Error ? err.message : String(err) });
|
|
27
|
-
wsSendDroppedCounter.add(1);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return {
|
|
31
|
-
get open() {
|
|
32
|
-
return ws.readyState === 1;
|
|
33
|
-
},
|
|
34
|
-
event(e) {
|
|
35
|
-
safeSend(JSON.stringify(e));
|
|
36
|
-
},
|
|
37
|
-
playAudioChunk(chunk) {
|
|
38
|
-
safeSend(chunk);
|
|
39
|
-
},
|
|
40
|
-
playAudioDone() {
|
|
41
|
-
safeSend(JSON.stringify({ type: "audio_done" }));
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
function handleBinaryAudio(data, session) {
|
|
46
|
-
if (data instanceof Uint8Array) {
|
|
47
|
-
session.onAudio(data);
|
|
48
|
-
return true;
|
|
49
|
-
}
|
|
50
|
-
if (data instanceof ArrayBuffer) {
|
|
51
|
-
session.onAudio(new Uint8Array(data));
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
function handleTextMessage(data, session, log, ctx, sid) {
|
|
57
|
-
if (typeof data !== "string") return;
|
|
58
|
-
let json;
|
|
59
|
-
try {
|
|
60
|
-
json = JSON.parse(data);
|
|
61
|
-
} catch {
|
|
62
|
-
log.warn("Invalid JSON from client", {
|
|
63
|
-
...ctx,
|
|
64
|
-
sid
|
|
65
|
-
});
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
const parsed = ClientMessageSchema.safeParse(json);
|
|
69
|
-
if (!parsed.success) {
|
|
70
|
-
log.warn("Invalid client message", {
|
|
71
|
-
...ctx,
|
|
72
|
-
sid,
|
|
73
|
-
error: parsed.error.message
|
|
74
|
-
});
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
const msg = parsed.data;
|
|
78
|
-
switch (msg.type) {
|
|
79
|
-
case "audio_ready":
|
|
80
|
-
session.onAudioReady();
|
|
81
|
-
break;
|
|
82
|
-
case "cancel":
|
|
83
|
-
session.onCancel();
|
|
84
|
-
break;
|
|
85
|
-
case "reset":
|
|
86
|
-
session.onReset();
|
|
87
|
-
break;
|
|
88
|
-
case "history":
|
|
89
|
-
session.onHistory(msg.messages);
|
|
90
|
-
break;
|
|
91
|
-
default: break;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Attaches session lifecycle handlers to a native WebSocket using
|
|
96
|
-
* plain JSON text frames and binary audio frames.
|
|
97
|
-
*
|
|
98
|
-
* Connection flow:
|
|
99
|
-
* 1. WebSocket opens → server sends `{ type: "config", ...ReadyConfig }`
|
|
100
|
-
* 2. Client sets up audio → sends `{ type: "audio_ready" }`
|
|
101
|
-
* 3. If reconnecting → client sends `{ type: "history", messages: [...] }`
|
|
102
|
-
*/
|
|
103
|
-
function wireSessionSocket(ws, opts) {
|
|
104
|
-
const { sessions, logger: log = consoleLogger } = opts;
|
|
105
|
-
const sessionId = opts.resumeFrom ?? crypto.randomUUID();
|
|
106
|
-
const sid = sessionId.slice(0, 8);
|
|
107
|
-
const ctx = opts.logContext ?? {};
|
|
108
|
-
let session = null;
|
|
109
|
-
/** Set to true once session.start() resolves. Messages arriving before
|
|
110
|
-
* this flag is set are buffered and replayed once the session is ready,
|
|
111
|
-
* preventing audio/text from being dispatched to a half-initialized session. */
|
|
112
|
-
let sessionReady = false;
|
|
113
|
-
let messageBuffer = [];
|
|
114
|
-
const sessionSpan = tracer.startSpan("ws.session", { attributes: { "aai.session.id": sessionId } });
|
|
115
|
-
function drainBuffer() {
|
|
116
|
-
if (!(session && messageBuffer)) return;
|
|
117
|
-
const buf = messageBuffer;
|
|
118
|
-
messageBuffer = null;
|
|
119
|
-
for (const event of buf) {
|
|
120
|
-
const { data } = event;
|
|
121
|
-
if (handleBinaryAudio(data, session)) continue;
|
|
122
|
-
handleTextMessage(data, session, log, ctx, sid);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
function onOpen() {
|
|
126
|
-
opts.onOpen?.();
|
|
127
|
-
log.info("Session connected", {
|
|
128
|
-
...ctx,
|
|
129
|
-
sid
|
|
130
|
-
});
|
|
131
|
-
sessionSpan.addEvent("ws.open");
|
|
132
|
-
const client = createClientSink(ws, log);
|
|
133
|
-
session = opts.createSession(sessionId, client);
|
|
134
|
-
sessions.set(sessionId, session);
|
|
135
|
-
ws.send(JSON.stringify({
|
|
136
|
-
type: "config",
|
|
137
|
-
...opts.readyConfig,
|
|
138
|
-
sessionId
|
|
139
|
-
}));
|
|
140
|
-
const timeoutMs = opts.sessionStartTimeoutMs ?? DEFAULT_SESSION_START_TIMEOUT_MS;
|
|
141
|
-
Promise.race([session.start(), new Promise((_resolve, reject) => {
|
|
142
|
-
setTimeout(() => reject(/* @__PURE__ */ new Error(`session.start() timed out after ${timeoutMs}ms`)), timeoutMs);
|
|
143
|
-
})]).then(() => {
|
|
144
|
-
log.info("Session ready", {
|
|
145
|
-
...ctx,
|
|
146
|
-
sid
|
|
147
|
-
});
|
|
148
|
-
sessionSpan.addEvent("session.ready");
|
|
149
|
-
sessionReady = true;
|
|
150
|
-
drainBuffer();
|
|
151
|
-
}).catch((err) => {
|
|
152
|
-
log.error("Session start failed", {
|
|
153
|
-
...ctx,
|
|
154
|
-
sid,
|
|
155
|
-
error: errorDetail(err)
|
|
156
|
-
});
|
|
157
|
-
sessionSpan.setStatus({
|
|
158
|
-
code: 2,
|
|
159
|
-
message: errorMessage(err)
|
|
160
|
-
});
|
|
161
|
-
sessions.delete(sessionId);
|
|
162
|
-
session = null;
|
|
163
|
-
messageBuffer = null;
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
if (ws.readyState === 1) onOpen();
|
|
167
|
-
else ws.addEventListener("open", onOpen);
|
|
168
|
-
ws.addEventListener("message", (event) => {
|
|
169
|
-
if (!session) return;
|
|
170
|
-
if (!sessionReady) {
|
|
171
|
-
messageBuffer?.push(event);
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
const { data } = event;
|
|
175
|
-
if (handleBinaryAudio(data, session)) return;
|
|
176
|
-
handleTextMessage(data, session, log, ctx, sid);
|
|
177
|
-
});
|
|
178
|
-
ws.addEventListener("close", () => {
|
|
179
|
-
log.info("Session disconnected", {
|
|
180
|
-
...ctx,
|
|
181
|
-
sid
|
|
182
|
-
});
|
|
183
|
-
sessionSpan.addEvent("ws.close");
|
|
184
|
-
sessionSpan.end();
|
|
185
|
-
if (session) session.stop().catch((err) => {
|
|
186
|
-
log.error("Session stop failed", {
|
|
187
|
-
...ctx,
|
|
188
|
-
sid,
|
|
189
|
-
error: errorDetail(err)
|
|
190
|
-
});
|
|
191
|
-
}).finally(() => {
|
|
192
|
-
sessions.delete(sessionId);
|
|
193
|
-
});
|
|
194
|
-
opts.onClose?.();
|
|
195
|
-
});
|
|
196
|
-
ws.addEventListener("error", (ev) => {
|
|
197
|
-
const msg = typeof ev.message === "string" ? ev.message : "WebSocket error";
|
|
198
|
-
log.error("WebSocket error", {
|
|
199
|
-
...ctx,
|
|
200
|
-
sid,
|
|
201
|
-
error: msg
|
|
202
|
-
});
|
|
203
|
-
sessionSpan.recordException(new Error(msg));
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
//#endregion
|
|
207
|
-
export { wireSessionSocket };
|