@alexkroman1/aai 0.10.2 → 0.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/_embeddings.d.ts +31 -0
  2. package/dist/_internal-types-IfPcaJd5.js +61 -0
  3. package/dist/_internal-types.js +1 -60
  4. package/dist/_ssrf-DCp_27V4.js +123 -0
  5. package/dist/_ssrf.js +1 -122
  6. package/dist/_utils-DgzpOMSV.js +61 -0
  7. package/dist/_utils.js +1 -60
  8. package/dist/{direct-executor-Ca0wt5H0.js → direct-executor-B-5mq3cu.js} +15 -17
  9. package/dist/index.js +1 -1
  10. package/dist/kv-iXtikQmR.js +32 -0
  11. package/dist/kv.js +1 -31
  12. package/dist/matchers.js +1 -1
  13. package/dist/middleware-core-BwyBIPed.js +107 -0
  14. package/dist/middleware-core.js +1 -106
  15. package/dist/protocol-B-H2Q4ox.js +162 -0
  16. package/dist/protocol.js +1 -161
  17. package/dist/runtime-CxcwaK68.js +58 -0
  18. package/dist/runtime.js +1 -52
  19. package/dist/s2s-M7JqtgFw.js +272 -0
  20. package/dist/s2s.js +1 -271
  21. package/dist/server.d.ts +6 -6
  22. package/dist/server.js +47 -43
  23. package/dist/{session-BkN9u0ni.js → session-BYlwcrya.js} +6 -6
  24. package/dist/session.js +1 -1
  25. package/dist/telemetry-CJlaDFNc.js +95 -0
  26. package/dist/telemetry.js +1 -94
  27. package/dist/{testing-MRl3SXsI.js → testing-BbitshLb.js} +7 -9
  28. package/dist/testing.js +1 -1
  29. package/dist/types-D8ZBxTL_.js +192 -0
  30. package/dist/types.js +1 -191
  31. package/dist/unstorage-kv-CDgP-frt.js +64 -0
  32. package/dist/unstorage-kv.d.ts +33 -0
  33. package/dist/unstorage-kv.js +2 -0
  34. package/dist/unstorage-vector-Cj5llNhg.js +172 -0
  35. package/dist/unstorage-vector.d.ts +47 -0
  36. package/dist/unstorage-vector.js +2 -0
  37. package/dist/vector.d.ts +3 -2
  38. package/dist/worker-entry-2jaiqIj0.js +70 -0
  39. package/dist/worker-entry.js +1 -69
  40. package/dist/ws-handler-C0Q6eSay.js +207 -0
  41. package/dist/ws-handler.js +1 -206
  42. package/package.json +14 -9
  43. package/dist/sqlite-kv.d.ts +0 -34
  44. package/dist/sqlite-kv.js +0 -133
  45. package/dist/sqlite-vector.d.ts +0 -58
  46. package/dist/sqlite-vector.js +0 -149
@@ -0,0 +1,272 @@
1
+ import { n as consoleLogger } from "./runtime-CxcwaK68.js";
2
+ import { c as s2sConnectionDuration, h as tracer, l as s2sErrorCounter } from "./telemetry-CJlaDFNc.js";
3
+ import { createNanoEvents } from "nanoevents";
4
+ import { WebSocket } from "ws";
5
+ //#region s2s.ts
6
+ const uint8ToBase64 = (bytes) => Buffer.from(bytes).toString("base64");
7
+ const base64ToUint8 = (base64) => new Uint8Array(Buffer.from(base64, "base64"));
8
+ const WS_OPEN = 1;
9
+ const defaultCreateS2sWebSocket = (url, opts) => new WebSocket(url, { headers: opts.headers });
10
+ function hasStringFields(obj, ...keys) {
11
+ for (const k of keys) if (typeof obj[k] !== "string") return false;
12
+ return true;
13
+ }
14
+ function parseAgentTranscript(obj) {
15
+ if (typeof obj.text !== "string") return;
16
+ return {
17
+ type: "transcript.agent",
18
+ text: obj.text,
19
+ reply_id: typeof obj.reply_id === "string" ? obj.reply_id : "",
20
+ item_id: typeof obj.item_id === "string" ? obj.item_id : "",
21
+ interrupted: obj.interrupted === true
22
+ };
23
+ }
24
+ function parseToolCall(obj) {
25
+ if (typeof obj.call_id !== "string" || typeof obj.name !== "string") return;
26
+ const args = obj.args != null && typeof obj.args === "object" && !Array.isArray(obj.args) ? obj.args : {};
27
+ return {
28
+ type: "tool.call",
29
+ call_id: obj.call_id,
30
+ name: obj.name,
31
+ args
32
+ };
33
+ }
34
+ function passthrough(obj) {
35
+ return obj;
36
+ }
37
+ function requireFields(...keys) {
38
+ return (obj) => hasStringFields(obj, ...keys) ? obj : void 0;
39
+ }
40
+ const MESSAGE_VALIDATORS = new Map([
41
+ ["session.ready", requireFields("session_id")],
42
+ ["session.updated", passthrough],
43
+ ["input.speech.started", passthrough],
44
+ ["input.speech.stopped", passthrough],
45
+ ["reply.content_part.started", passthrough],
46
+ ["reply.content_part.done", passthrough],
47
+ ["transcript.user.delta", requireFields("text")],
48
+ ["transcript.user", requireFields("item_id", "text")],
49
+ ["reply.started", requireFields("reply_id")],
50
+ ["transcript.agent.delta", requireFields("delta")],
51
+ ["transcript.agent", parseAgentTranscript],
52
+ ["tool.call", parseToolCall],
53
+ ["reply.done", (obj) => ({
54
+ type: "reply.done",
55
+ ...typeof obj.status === "string" ? { status: obj.status } : {}
56
+ })],
57
+ ["session.error", requireFields("code", "message")],
58
+ ["error", requireFields("message")]
59
+ ]);
60
+ function parseS2sMessage(obj) {
61
+ const type = obj.type;
62
+ if (typeof type !== "string") return;
63
+ return MESSAGE_VALIDATORS.get(type)?.(obj);
64
+ }
65
+ function dispatchS2sMessage(emitter, msg) {
66
+ switch (msg.type) {
67
+ case "session.ready":
68
+ emitter.emit("ready", { sessionId: msg.session_id });
69
+ break;
70
+ case "session.updated":
71
+ emitter.emit("sessionUpdated", msg);
72
+ break;
73
+ case "input.speech.started":
74
+ emitter.emit("speechStarted");
75
+ break;
76
+ case "input.speech.stopped":
77
+ emitter.emit("speechStopped");
78
+ break;
79
+ case "transcript.user.delta":
80
+ emitter.emit("userTranscriptDelta", { text: msg.text });
81
+ break;
82
+ case "transcript.user":
83
+ emitter.emit("userTranscript", {
84
+ itemId: msg.item_id,
85
+ text: msg.text
86
+ });
87
+ break;
88
+ case "reply.started":
89
+ emitter.emit("replyStarted", { replyId: msg.reply_id });
90
+ break;
91
+ case "transcript.agent.delta":
92
+ emitter.emit("agentTranscriptDelta", { text: msg.delta });
93
+ break;
94
+ case "transcript.agent":
95
+ emitter.emit("agentTranscript", {
96
+ text: msg.text,
97
+ replyId: msg.reply_id,
98
+ itemId: msg.item_id,
99
+ interrupted: msg.interrupted
100
+ });
101
+ break;
102
+ case "tool.call":
103
+ emitter.emit("toolCall", {
104
+ callId: msg.call_id,
105
+ name: msg.name,
106
+ args: msg.args
107
+ });
108
+ break;
109
+ case "reply.done":
110
+ emitter.emit("replyDone", msg.status ? { status: msg.status } : {});
111
+ break;
112
+ case "session.error":
113
+ if (msg.code === "session_not_found" || msg.code === "session_forbidden") emitter.emit("sessionExpired", {
114
+ code: msg.code,
115
+ message: msg.message
116
+ });
117
+ else emitter.emit("error", {
118
+ code: msg.code,
119
+ message: msg.message
120
+ });
121
+ break;
122
+ case "error":
123
+ emitter.emit("error", {
124
+ code: "connection",
125
+ message: msg.message
126
+ });
127
+ break;
128
+ case "reply.content_part.started":
129
+ case "reply.content_part.done": break;
130
+ default: break;
131
+ }
132
+ }
133
+ function connectS2s(opts) {
134
+ const { apiKey, config, createWebSocket, logger: log = consoleLogger } = opts;
135
+ return new Promise((resolve, reject) => {
136
+ log.info("S2S connecting", { url: config.wssUrl });
137
+ const connectionSpan = tracer.startSpan("s2s.connection", { attributes: { "aai.s2s.url": config.wssUrl } });
138
+ const connectStart = performance.now();
139
+ const ws = createWebSocket(config.wssUrl, { headers: { Authorization: `Bearer ${apiKey}` } });
140
+ const emitter = createNanoEvents();
141
+ let opened = false;
142
+ function send(msg) {
143
+ if (ws.readyState !== WS_OPEN) {
144
+ log.debug("S2S send dropped: socket not open", { type: msg.type });
145
+ return;
146
+ }
147
+ const json = JSON.stringify(msg);
148
+ if (msg.type !== "input.audio") log.info(`S2S >> ${msg.type}`, msg.type === "session.update" ? { payload: json } : void 0);
149
+ ws.send(json);
150
+ }
151
+ const handle = {
152
+ on: emitter.on.bind(emitter),
153
+ sendAudio(audio) {
154
+ if (ws.readyState !== WS_OPEN) {
155
+ log.debug("S2S sendAudio dropped: socket not open");
156
+ return;
157
+ }
158
+ ws.send(`{"type":"input.audio","audio":"${uint8ToBase64(audio)}"}`);
159
+ },
160
+ sendToolResult(callId, result) {
161
+ const msg = {
162
+ type: "tool.result",
163
+ call_id: callId,
164
+ result
165
+ };
166
+ log.info("S2S >> tool.result", {
167
+ call_id: callId,
168
+ resultLength: result.length
169
+ });
170
+ send(msg);
171
+ },
172
+ updateSession(sessionConfig) {
173
+ const { systemPrompt, ...rest } = sessionConfig;
174
+ send({
175
+ type: "session.update",
176
+ session: {
177
+ system_prompt: systemPrompt,
178
+ ...rest
179
+ }
180
+ });
181
+ },
182
+ resumeSession(sessionId) {
183
+ send({
184
+ type: "session.resume",
185
+ session_id: sessionId
186
+ });
187
+ },
188
+ close() {
189
+ log.info("S2S closing");
190
+ ws.close();
191
+ }
192
+ };
193
+ ws.addEventListener("open", () => {
194
+ opened = true;
195
+ log.info("S2S WebSocket open");
196
+ connectionSpan.addEvent("ws.open");
197
+ resolve(handle);
198
+ });
199
+ function tryParseJson(data) {
200
+ try {
201
+ return JSON.parse(String(data));
202
+ } catch {
203
+ log.warn("S2S << invalid JSON", { data: String(data).slice(0, 200) });
204
+ }
205
+ }
206
+ function handleAudioFastPath(obj) {
207
+ if (obj.type === "reply.audio" && typeof obj.data === "string") {
208
+ const audioBytes = base64ToUint8(obj.data);
209
+ emitter.emit("audio", { audio: audioBytes });
210
+ return true;
211
+ }
212
+ return false;
213
+ }
214
+ function logIncoming(obj) {
215
+ if (obj.type === "reply.audio" || obj.type === "input.audio") return;
216
+ log.info(`S2S << ${obj.type}`, obj.type === "transcript.agent.delta" ? { delta: obj.delta } : void 0);
217
+ }
218
+ function handleS2sMessage(ev) {
219
+ const raw = tryParseJson(ev.data);
220
+ if (raw === void 0) return;
221
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
222
+ log.warn("S2S << non-object JSON message", { type: typeof raw });
223
+ return;
224
+ }
225
+ const obj = raw;
226
+ logIncoming(obj);
227
+ if (handleAudioFastPath(obj)) return;
228
+ const parsed = parseS2sMessage(obj);
229
+ if (!parsed) {
230
+ log.warn(`S2S << unrecognised message type: ${obj.type ?? JSON.stringify(raw).slice(0, 200)}`);
231
+ return;
232
+ }
233
+ dispatchS2sMessage(emitter, parsed);
234
+ }
235
+ ws.addEventListener("message", handleS2sMessage);
236
+ ws.addEventListener("close", (ev) => {
237
+ log.info("S2S WebSocket closed", {
238
+ code: ev.code ?? 0,
239
+ reason: ev.reason ?? ""
240
+ });
241
+ const elapsed = (performance.now() - connectStart) / 1e3;
242
+ s2sConnectionDuration.record(elapsed);
243
+ connectionSpan.addEvent("ws.closed", {
244
+ "ws.close.code": ev.code ?? 0,
245
+ "ws.close.reason": ev.reason ?? ""
246
+ });
247
+ connectionSpan.end();
248
+ if (!opened) reject(/* @__PURE__ */ new Error(`WebSocket closed before open (code: ${ev.code ?? 0})`));
249
+ emitter.emit("close");
250
+ });
251
+ ws.addEventListener("error", (ev) => {
252
+ const message = typeof ev.message === "string" ? ev.message : "WebSocket error";
253
+ const errObj = new Error(message);
254
+ log.error("S2S WebSocket error", { error: errObj.message });
255
+ s2sErrorCounter.add(1);
256
+ connectionSpan.setStatus({
257
+ code: 2,
258
+ message: errObj.message
259
+ });
260
+ connectionSpan.recordException(errObj);
261
+ if (!opened) {
262
+ connectionSpan.end();
263
+ reject(errObj);
264
+ } else emitter.emit("error", {
265
+ code: "ws_error",
266
+ message: errObj.message
267
+ });
268
+ });
269
+ });
270
+ }
271
+ //#endregion
272
+ export { defaultCreateS2sWebSocket as n, connectS2s as t };
package/dist/s2s.js CHANGED
@@ -1,272 +1,2 @@
1
- import { consoleLogger } from "./runtime.js";
2
- import { s2sConnectionDuration, s2sErrorCounter, tracer } from "./telemetry.js";
3
- import { createNanoEvents } from "nanoevents";
4
- import { WebSocket } from "ws";
5
- //#region s2s.ts
6
- const uint8ToBase64 = (bytes) => Buffer.from(bytes).toString("base64");
7
- const base64ToUint8 = (base64) => new Uint8Array(Buffer.from(base64, "base64"));
8
- const WS_OPEN = 1;
9
- const defaultCreateS2sWebSocket = (url, opts) => new WebSocket(url, { headers: opts.headers });
10
- function hasStringFields(obj, ...keys) {
11
- for (const k of keys) if (typeof obj[k] !== "string") return false;
12
- return true;
13
- }
14
- function parseAgentTranscript(obj) {
15
- if (typeof obj.text !== "string") return;
16
- return {
17
- type: "transcript.agent",
18
- text: obj.text,
19
- reply_id: typeof obj.reply_id === "string" ? obj.reply_id : "",
20
- item_id: typeof obj.item_id === "string" ? obj.item_id : "",
21
- interrupted: obj.interrupted === true
22
- };
23
- }
24
- function parseToolCall(obj) {
25
- if (typeof obj.call_id !== "string" || typeof obj.name !== "string") return;
26
- const args = obj.args != null && typeof obj.args === "object" && !Array.isArray(obj.args) ? obj.args : {};
27
- return {
28
- type: "tool.call",
29
- call_id: obj.call_id,
30
- name: obj.name,
31
- args
32
- };
33
- }
34
- function passthrough(obj) {
35
- return obj;
36
- }
37
- function requireFields(...keys) {
38
- return (obj) => hasStringFields(obj, ...keys) ? obj : void 0;
39
- }
40
- const MESSAGE_VALIDATORS = new Map([
41
- ["session.ready", requireFields("session_id")],
42
- ["session.updated", passthrough],
43
- ["input.speech.started", passthrough],
44
- ["input.speech.stopped", passthrough],
45
- ["reply.content_part.started", passthrough],
46
- ["reply.content_part.done", passthrough],
47
- ["transcript.user.delta", requireFields("text")],
48
- ["transcript.user", requireFields("item_id", "text")],
49
- ["reply.started", requireFields("reply_id")],
50
- ["transcript.agent.delta", requireFields("delta")],
51
- ["transcript.agent", parseAgentTranscript],
52
- ["tool.call", parseToolCall],
53
- ["reply.done", (obj) => ({
54
- type: "reply.done",
55
- ...typeof obj.status === "string" ? { status: obj.status } : {}
56
- })],
57
- ["session.error", requireFields("code", "message")],
58
- ["error", requireFields("message")]
59
- ]);
60
- function parseS2sMessage(obj) {
61
- const type = obj.type;
62
- if (typeof type !== "string") return;
63
- return MESSAGE_VALIDATORS.get(type)?.(obj);
64
- }
65
- function dispatchS2sMessage(emitter, msg) {
66
- switch (msg.type) {
67
- case "session.ready":
68
- emitter.emit("ready", { sessionId: msg.session_id });
69
- break;
70
- case "session.updated":
71
- emitter.emit("sessionUpdated", msg);
72
- break;
73
- case "input.speech.started":
74
- emitter.emit("speechStarted");
75
- break;
76
- case "input.speech.stopped":
77
- emitter.emit("speechStopped");
78
- break;
79
- case "transcript.user.delta":
80
- emitter.emit("userTranscriptDelta", { text: msg.text });
81
- break;
82
- case "transcript.user":
83
- emitter.emit("userTranscript", {
84
- itemId: msg.item_id,
85
- text: msg.text
86
- });
87
- break;
88
- case "reply.started":
89
- emitter.emit("replyStarted", { replyId: msg.reply_id });
90
- break;
91
- case "transcript.agent.delta":
92
- emitter.emit("agentTranscriptDelta", { text: msg.delta });
93
- break;
94
- case "transcript.agent":
95
- emitter.emit("agentTranscript", {
96
- text: msg.text,
97
- replyId: msg.reply_id,
98
- itemId: msg.item_id,
99
- interrupted: msg.interrupted
100
- });
101
- break;
102
- case "tool.call":
103
- emitter.emit("toolCall", {
104
- callId: msg.call_id,
105
- name: msg.name,
106
- args: msg.args
107
- });
108
- break;
109
- case "reply.done":
110
- emitter.emit("replyDone", msg.status ? { status: msg.status } : {});
111
- break;
112
- case "session.error":
113
- if (msg.code === "session_not_found" || msg.code === "session_forbidden") emitter.emit("sessionExpired", {
114
- code: msg.code,
115
- message: msg.message
116
- });
117
- else emitter.emit("error", {
118
- code: msg.code,
119
- message: msg.message
120
- });
121
- break;
122
- case "error":
123
- emitter.emit("error", {
124
- code: "connection",
125
- message: msg.message
126
- });
127
- break;
128
- case "reply.content_part.started":
129
- case "reply.content_part.done": break;
130
- default: break;
131
- }
132
- }
133
- function connectS2s(opts) {
134
- const { apiKey, config, createWebSocket, logger: log = consoleLogger } = opts;
135
- return new Promise((resolve, reject) => {
136
- log.info("S2S connecting", { url: config.wssUrl });
137
- const connectionSpan = tracer.startSpan("s2s.connection", { attributes: { "aai.s2s.url": config.wssUrl } });
138
- const connectStart = performance.now();
139
- const ws = createWebSocket(config.wssUrl, { headers: { Authorization: `Bearer ${apiKey}` } });
140
- const emitter = createNanoEvents();
141
- let opened = false;
142
- function send(msg) {
143
- if (ws.readyState !== WS_OPEN) {
144
- log.debug("S2S send dropped: socket not open", { type: msg.type });
145
- return;
146
- }
147
- const json = JSON.stringify(msg);
148
- if (msg.type !== "input.audio") log.info(`S2S >> ${msg.type}`, msg.type === "session.update" ? { payload: json } : void 0);
149
- ws.send(json);
150
- }
151
- const handle = {
152
- on: emitter.on.bind(emitter),
153
- sendAudio(audio) {
154
- if (ws.readyState !== WS_OPEN) {
155
- log.debug("S2S sendAudio dropped: socket not open");
156
- return;
157
- }
158
- ws.send(`{"type":"input.audio","audio":"${uint8ToBase64(audio)}"}`);
159
- },
160
- sendToolResult(callId, result) {
161
- const msg = {
162
- type: "tool.result",
163
- call_id: callId,
164
- result
165
- };
166
- log.info("S2S >> tool.result", {
167
- call_id: callId,
168
- resultLength: result.length
169
- });
170
- send(msg);
171
- },
172
- updateSession(sessionConfig) {
173
- const { systemPrompt, ...rest } = sessionConfig;
174
- send({
175
- type: "session.update",
176
- session: {
177
- system_prompt: systemPrompt,
178
- ...rest
179
- }
180
- });
181
- },
182
- resumeSession(sessionId) {
183
- send({
184
- type: "session.resume",
185
- session_id: sessionId
186
- });
187
- },
188
- close() {
189
- log.info("S2S closing");
190
- ws.close();
191
- }
192
- };
193
- ws.addEventListener("open", () => {
194
- opened = true;
195
- log.info("S2S WebSocket open");
196
- connectionSpan.addEvent("ws.open");
197
- resolve(handle);
198
- });
199
- function tryParseJson(data) {
200
- try {
201
- return JSON.parse(String(data));
202
- } catch {
203
- log.warn("S2S << invalid JSON", { data: String(data).slice(0, 200) });
204
- }
205
- }
206
- function handleAudioFastPath(obj) {
207
- if (obj.type === "reply.audio" && typeof obj.data === "string") {
208
- const audioBytes = base64ToUint8(obj.data);
209
- emitter.emit("audio", { audio: audioBytes });
210
- return true;
211
- }
212
- return false;
213
- }
214
- function logIncoming(obj) {
215
- if (obj.type === "reply.audio" || obj.type === "input.audio") return;
216
- log.info(`S2S << ${obj.type}`, obj.type === "transcript.agent.delta" ? { delta: obj.delta } : void 0);
217
- }
218
- function handleS2sMessage(ev) {
219
- const raw = tryParseJson(ev.data);
220
- if (raw === void 0) return;
221
- if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
222
- log.warn("S2S << non-object JSON message", { type: typeof raw });
223
- return;
224
- }
225
- const obj = raw;
226
- logIncoming(obj);
227
- if (handleAudioFastPath(obj)) return;
228
- const parsed = parseS2sMessage(obj);
229
- if (!parsed) {
230
- log.warn(`S2S << unrecognised message type: ${obj.type ?? JSON.stringify(raw).slice(0, 200)}`);
231
- return;
232
- }
233
- dispatchS2sMessage(emitter, parsed);
234
- }
235
- ws.addEventListener("message", handleS2sMessage);
236
- ws.addEventListener("close", (ev) => {
237
- log.info("S2S WebSocket closed", {
238
- code: ev.code ?? 0,
239
- reason: ev.reason ?? ""
240
- });
241
- const elapsed = (performance.now() - connectStart) / 1e3;
242
- s2sConnectionDuration.record(elapsed);
243
- connectionSpan.addEvent("ws.closed", {
244
- "ws.close.code": ev.code ?? 0,
245
- "ws.close.reason": ev.reason ?? ""
246
- });
247
- connectionSpan.end();
248
- if (!opened) reject(/* @__PURE__ */ new Error(`WebSocket closed before open (code: ${ev.code ?? 0})`));
249
- emitter.emit("close");
250
- });
251
- ws.addEventListener("error", (ev) => {
252
- const message = typeof ev.message === "string" ? ev.message : "WebSocket error";
253
- const errObj = new Error(message);
254
- log.error("S2S WebSocket error", { error: errObj.message });
255
- s2sErrorCounter.add(1);
256
- connectionSpan.setStatus({
257
- code: 2,
258
- message: errObj.message
259
- });
260
- connectionSpan.recordException(errObj);
261
- if (!opened) {
262
- connectionSpan.end();
263
- reject(errObj);
264
- } else emitter.emit("error", {
265
- code: "ws_error",
266
- message: errObj.message
267
- });
268
- });
269
- });
270
- }
271
- //#endregion
1
+ import { n as defaultCreateS2sWebSocket, t as connectS2s } from "./s2s-M7JqtgFw.js";
272
2
  export { connectS2s, defaultCreateS2sWebSocket };
package/dist/server.d.ts CHANGED
@@ -5,10 +5,9 @@
5
5
  * Calls `createDirectExecutor` + `wireSessionSocket` directly — no
6
6
  * intermediary needed.
7
7
  */
8
- import type { Kv } from "./kv.ts";
8
+ import { type Storage } from "unstorage";
9
9
  import type { Logger, S2SConfig } from "./runtime.ts";
10
10
  import type { AgentDef } from "./types.ts";
11
- import type { VectorStore } from "./vector.ts";
12
11
  /**
13
12
  * Configuration for a self-hosted agent server created by {@link createServer}.
14
13
  *
@@ -19,10 +18,11 @@ export type ServerOptions = {
19
18
  agent: AgentDef<any>;
20
19
  /** Environment variables. Defaults to `process.env`. */
21
20
  env?: Record<string, string>;
22
- /** KV store. Defaults to SQLite-backed (`.aai/local.db`). */
23
- kv?: Kv;
24
- /** Vector store. Defaults to SQLite-backed (`.aai/local.db`). */
25
- vector?: VectorStore;
21
+ /**
22
+ * Unstorage instance for KV and vector storage. Defaults to in-memory.
23
+ * Configure with an S3/R2/filesystem driver for persistence.
24
+ */
25
+ storage?: Storage;
26
26
  /** HTML to serve at `GET /`. */
27
27
  clientHtml?: string;
28
28
  /** Directory containing built client files (index.html + assets/). */