@alexkroman1/aai 1.6.0 → 1.7.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/.turbo/turbo-build.log +22 -18
- package/CHANGELOG.md +16 -0
- package/dist/{_internal-types-DFL07G3f.js → _internal-types-CrnTi9Ew.js} +8 -2
- package/dist/host/memory-vector.d.ts +17 -0
- package/dist/host/pinecone-vector.d.ts +19 -0
- package/dist/host/providers/resolve-kv.d.ts +10 -0
- package/dist/host/providers/resolve-vector.d.ts +11 -0
- package/dist/host/providers/resolve.d.ts +7 -7
- package/dist/host/runtime-barrel.d.ts +5 -0
- package/dist/host/runtime-barrel.js +416 -149
- package/dist/host/runtime.d.ts +6 -0
- package/dist/host/server.d.ts +2 -0
- package/dist/host/tool-executor.d.ts +2 -0
- package/dist/pinecone-CeJ69aRs.js +19 -0
- package/dist/{cartesia-BfQPOQ7Y.js → rime-58p9mDR8.js} +19 -19
- package/dist/s3-BtCMvCod.js +37 -0
- package/dist/sdk/_internal-types.d.ts +11 -1
- package/dist/sdk/define.d.ts +5 -1
- package/dist/sdk/manifest-barrel.js +1 -1
- package/dist/sdk/manifest.d.ts +5 -1
- package/dist/sdk/protocol.d.ts +36 -0
- package/dist/sdk/protocol.js +26 -1
- package/dist/sdk/providers/kv/fs.d.ts +12 -0
- package/dist/sdk/providers/kv/memory.d.ts +9 -0
- package/dist/sdk/providers/kv/redis.d.ts +17 -0
- package/dist/sdk/providers/kv/s3.d.ts +25 -0
- package/dist/sdk/providers/kv-barrel.d.ts +13 -0
- package/dist/sdk/providers/kv-barrel.js +2 -0
- package/dist/sdk/providers/llm-barrel.js +1 -1
- package/dist/sdk/providers/stt-barrel.js +1 -1
- package/dist/sdk/providers/tts-barrel.js +1 -1
- package/dist/sdk/providers/vector/in-memory.d.ts +15 -0
- package/dist/sdk/providers/vector/pinecone.d.ts +19 -0
- package/dist/sdk/providers/vector-barrel.d.ts +11 -0
- package/dist/sdk/providers/vector-barrel.js +2 -0
- package/dist/sdk/providers.d.ts +4 -0
- package/dist/sdk/types.d.ts +8 -1
- package/dist/sdk/vector.d.ts +29 -0
- package/dist/{soniox-DCQ3GqJq.js → soniox-BQdL0mB5.js} +13 -13
- package/host/_runtime-conformance.ts +21 -0
- package/host/_test-utils.ts +1 -0
- package/host/memory-vector.test.ts +87 -0
- package/host/memory-vector.ts +108 -0
- package/host/pinecone-vector.test.ts +79 -0
- package/host/pinecone-vector.ts +79 -0
- package/host/providers/resolve-kv.test.ts +48 -0
- package/host/providers/resolve-kv.ts +128 -0
- package/host/providers/resolve-vector.test.ts +26 -0
- package/host/providers/resolve-vector.ts +42 -0
- package/host/providers/resolve.ts +28 -55
- package/host/runtime-barrel.ts +5 -0
- package/host/runtime-config.ts +1 -1
- package/host/runtime.ts +28 -2
- package/host/server.ts +57 -1
- package/host/tool-executor.ts +7 -1
- package/package.json +20 -29
- package/sdk/__snapshots__/exports.test.ts.snap +8 -0
- package/sdk/__snapshots__/schema-shapes.test.ts.snap +2 -0
- package/sdk/_internal-types.ts +8 -0
- package/sdk/define.ts +11 -1
- package/sdk/manifest.test.ts +20 -0
- package/sdk/manifest.ts +10 -0
- package/sdk/protocol-snapshot.test.ts +53 -0
- package/sdk/protocol.test.ts +54 -0
- package/sdk/protocol.ts +32 -0
- package/sdk/providers/kv/fs.ts +20 -0
- package/sdk/providers/kv/memory.ts +17 -0
- package/sdk/providers/kv/redis.ts +25 -0
- package/sdk/providers/kv/s3.ts +33 -0
- package/sdk/providers/kv-barrel.ts +19 -0
- package/sdk/providers/vector/in-memory.ts +23 -0
- package/sdk/providers/vector/pinecone.ts +27 -0
- package/sdk/providers/vector-barrel.ts +15 -0
- package/sdk/providers.ts +6 -0
- package/sdk/types.ts +14 -1
- package/sdk/vector.ts +32 -0
- /package/dist/{xai-jfQsxxPZ.js → xai-BDI61Y2M.js} +0 -0
|
@@ -1,25 +1,33 @@
|
|
|
1
1
|
import { r as DEFAULT_SYSTEM_PROMPT } from "../types-KUgezM6u.js";
|
|
2
2
|
import { _ as TOOL_EXECUTION_TIMEOUT_MS, a as DEFAULT_SHUTDOWN_TIMEOUT_MS, c as FETCH_TIMEOUT_MS, d as MAX_PAGE_CHARS, g as RUN_CODE_TIMEOUT_MS, h as PIPELINE_FLUSH_TIMEOUT_MS, l as MAX_HTML_BYTES, m as MAX_WS_PAYLOAD_BYTES, o as DEFAULT_STT_SAMPLE_RATE, p as MAX_VALUE_SIZE, s as DEFAULT_TTS_SAMPLE_RATE, t as AGENT_CSP } from "../constants-C2nirZUI.js";
|
|
3
3
|
import { i as toolError, n as errorDetail, r as errorMessage, t as parseWsUpgradeParams } from "../ws-upgrade-BeOQ7fXL.js";
|
|
4
|
-
import { ClientMessageSchema, buildReadyConfig, lenientParse } from "../sdk/protocol.js";
|
|
5
|
-
import { a as toAgentConfig, c as makeSttError, i as agentToolsToSchemas, l as makeTtsError, n as EMPTY_PARAMS, s as assertProviderTriple } from "../_internal-types-
|
|
6
|
-
import { a as
|
|
7
|
-
import { a as
|
|
8
|
-
import { a as
|
|
4
|
+
import { ClientMessageSchema, VectorRequestSchema, buildReadyConfig, lenientParse } from "../sdk/protocol.js";
|
|
5
|
+
import { a as toAgentConfig, c as makeSttError, i as agentToolsToSchemas, l as makeTtsError, n as EMPTY_PARAMS, s as assertProviderTriple } from "../_internal-types-CrnTi9Ew.js";
|
|
6
|
+
import { a as MISTRAL_KIND, d as ANTHROPIC_KIND, l as GOOGLE_KIND, r as OPENAI_KIND, s as GROQ_KIND } from "../xai-BDI61Y2M.js";
|
|
7
|
+
import { a as DEEPGRAM_KIND, r as ELEVENLABS_KIND, s as ASSEMBLYAI_KIND, t as SONIOX_KIND } from "../soniox-BQdL0mB5.js";
|
|
8
|
+
import { a as CARTESIA_KIND, n as RIME_KIND } from "../rime-58p9mDR8.js";
|
|
9
|
+
import { a as MEMORY_KV_KIND, r as REDIS_KV_KIND } from "../s3-BtCMvCod.js";
|
|
10
|
+
import { r as IN_MEMORY_VECTOR_KIND, t as PINECONE_VECTOR_KIND } from "../pinecone-CeJ69aRs.js";
|
|
9
11
|
import { createRequire } from "node:module";
|
|
10
12
|
import { z } from "zod";
|
|
11
13
|
import { convert } from "html-to-text";
|
|
12
14
|
import vm from "node:vm";
|
|
13
|
-
import
|
|
14
|
-
import {
|
|
15
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
16
|
+
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
17
|
+
import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
18
|
+
import { createGroq } from "@ai-sdk/groq";
|
|
19
|
+
import { createMistral } from "@ai-sdk/mistral";
|
|
20
|
+
import { createOpenAI } from "@ai-sdk/openai";
|
|
21
|
+
import { createXai } from "@ai-sdk/xai";
|
|
15
22
|
import { AssemblyAI } from "assemblyai";
|
|
16
23
|
import { createNanoEvents } from "nanoevents";
|
|
17
24
|
import { DeepgramClient } from "@deepgram/sdk";
|
|
18
25
|
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
|
|
19
26
|
import { AudioFormat, CommitStrategy, RealtimeEvents } from "@elevenlabs/elevenlabs-js/wrapper/realtime/index.js";
|
|
20
|
-
import
|
|
21
|
-
import { randomUUID } from "node:crypto";
|
|
27
|
+
import WebSocket, { WebSocketServer } from "ws";
|
|
22
28
|
import { Cartesia } from "@cartesia/cartesia-js";
|
|
29
|
+
import { createStorage, prefixStorage } from "unstorage";
|
|
30
|
+
import pTimeout from "p-timeout";
|
|
23
31
|
import { jsonSchema, stepCountIs, streamText, tool } from "ai";
|
|
24
32
|
import fs from "node:fs";
|
|
25
33
|
import http from "node:http";
|
|
@@ -351,35 +359,84 @@ function resolveAllBuiltins(names, opts) {
|
|
|
351
359
|
};
|
|
352
360
|
}
|
|
353
361
|
//#endregion
|
|
354
|
-
//#region
|
|
355
|
-
function getFormattedDate() {
|
|
356
|
-
return (/* @__PURE__ */ new Date()).toLocaleDateString("en-US", {
|
|
357
|
-
weekday: "long",
|
|
358
|
-
year: "numeric",
|
|
359
|
-
month: "long",
|
|
360
|
-
day: "numeric"
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
const VOICE_RULES = "\n\nCRITICAL OUTPUT RULES — you MUST follow these for EVERY response:\nYour response will be spoken aloud by a TTS system and displayed as plain text.\n- NEVER use markdown: no **, no *, no _, no #, no `, no [](), no ---\n- NEVER use bullet points (-, *, •) or numbered lists (1., 2.)\n- NEVER use code blocks or inline code\n- NEVER mention tools, search, APIs, or technical failures to the user. If a tool returns no results, just answer naturally without explaining why.\n- Write exactly as you would say it out loud to a friend\n- Use short conversational sentences. To list things, say \"First,\" \"Next,\" \"Finally,\"\n- Keep responses concise — 1 to 3 sentences max";
|
|
362
|
+
//#region host/memory-vector.ts
|
|
364
363
|
/**
|
|
365
|
-
*
|
|
364
|
+
* In-memory Vector implementation.
|
|
366
365
|
*
|
|
367
|
-
*
|
|
368
|
-
*
|
|
369
|
-
*
|
|
370
|
-
*
|
|
371
|
-
*
|
|
372
|
-
*
|
|
373
|
-
* @param opts.voice - When `true`, appends strict voice-specific output rules
|
|
374
|
-
* (no markdown, no bullet points, conversational tone, concise responses).
|
|
375
|
-
* @returns The assembled system prompt string.
|
|
366
|
+
* INTENTIONALLY BAD QUALITY. Pseudo-embedding hashes the text into a
|
|
367
|
+
* 64-dim Float32Array of values in [-1, ~0.99], then L2-normalizes
|
|
368
|
+
* the result. Because both stored and probe vectors are unit-length,
|
|
369
|
+
* cosine similarity reduces to a plain dot product — that's what
|
|
370
|
+
* `cosine()` computes. Used only for `aai dev` and tests — the goal
|
|
371
|
+
* is proving tool wiring, not retrieval ranking.
|
|
376
372
|
*/
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
373
|
+
const stores = /* @__PURE__ */ new Map();
|
|
374
|
+
function getStore(ns) {
|
|
375
|
+
let store = stores.get(ns);
|
|
376
|
+
if (!store) {
|
|
377
|
+
store = /* @__PURE__ */ new Map();
|
|
378
|
+
stores.set(ns, store);
|
|
379
|
+
}
|
|
380
|
+
return store;
|
|
381
|
+
}
|
|
382
|
+
const DIM = 64;
|
|
383
|
+
function pseudoEmbed(text) {
|
|
384
|
+
const out = new Float32Array(DIM);
|
|
385
|
+
const h1 = createHash("sha256").update(text).digest();
|
|
386
|
+
const h2 = createHash("sha256").update(h1).digest();
|
|
387
|
+
for (let i = 0; i < 32; i++) out[i] = (h1[i] - 128) / 128;
|
|
388
|
+
for (let i = 0; i < 32; i++) out[i + 32] = (h2[i] - 128) / 128;
|
|
389
|
+
let norm = 0;
|
|
390
|
+
for (let i = 0; i < DIM; i++) norm += out[i] * out[i];
|
|
391
|
+
norm = Math.sqrt(norm) || 1;
|
|
392
|
+
for (let i = 0; i < DIM; i++) out[i] = out[i] / norm;
|
|
393
|
+
return out;
|
|
394
|
+
}
|
|
395
|
+
function cosine(a, b) {
|
|
396
|
+
let dot = 0;
|
|
397
|
+
for (let i = 0; i < DIM; i++) dot += a[i] * b[i];
|
|
398
|
+
return dot;
|
|
399
|
+
}
|
|
400
|
+
function matches(metadata, filter) {
|
|
401
|
+
for (const [key, want] of Object.entries(filter)) {
|
|
402
|
+
if (want !== null && typeof want === "object") throw new Error(`In-memory Vector: filter operator unsupported (${key}). Only top-level exact-match is supported.`);
|
|
403
|
+
if (metadata?.[key] !== want) return false;
|
|
404
|
+
}
|
|
405
|
+
return true;
|
|
406
|
+
}
|
|
407
|
+
function createMemoryVector(opts) {
|
|
408
|
+
const ns = opts.namespace;
|
|
409
|
+
return {
|
|
410
|
+
async upsert(id, text, metadata) {
|
|
411
|
+
getStore(ns).set(id, {
|
|
412
|
+
text,
|
|
413
|
+
metadata,
|
|
414
|
+
vec: pseudoEmbed(text)
|
|
415
|
+
});
|
|
416
|
+
},
|
|
417
|
+
async query(text, queryOpts) {
|
|
418
|
+
const topK = queryOpts?.topK ?? 5;
|
|
419
|
+
const filter = queryOpts?.filter;
|
|
420
|
+
const probe = pseudoEmbed(text);
|
|
421
|
+
const scored = [];
|
|
422
|
+
for (const [id, rec] of getStore(ns)) {
|
|
423
|
+
if (filter && !matches(rec.metadata, filter)) continue;
|
|
424
|
+
scored.push({
|
|
425
|
+
id,
|
|
426
|
+
score: cosine(probe, rec.vec),
|
|
427
|
+
text: rec.text,
|
|
428
|
+
...rec.metadata !== void 0 ? { metadata: rec.metadata } : {}
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
scored.sort((a, b) => b.score - a.score);
|
|
432
|
+
return scored.slice(0, topK);
|
|
433
|
+
},
|
|
434
|
+
async delete(ids) {
|
|
435
|
+
const store = getStore(ns);
|
|
436
|
+
const list = Array.isArray(ids) ? ids : [ids];
|
|
437
|
+
for (const id of list) store.delete(id);
|
|
438
|
+
}
|
|
439
|
+
};
|
|
383
440
|
}
|
|
384
441
|
//#endregion
|
|
385
442
|
//#region host/providers/stt/assemblyai.ts
|
|
@@ -757,7 +814,7 @@ function openSoniox(opts = {}) {
|
|
|
757
814
|
async open(openOpts) {
|
|
758
815
|
const apiKey = openOpts.apiKey || process.env.SONIOX_API_KEY;
|
|
759
816
|
if (!apiKey) throw makeSttError("stt_auth_failed", "Soniox STT: missing API key. Set SONIOX_API_KEY in the agent env.");
|
|
760
|
-
const ws = new
|
|
817
|
+
const ws = new WebSocket(SONIOX_WS_URL);
|
|
761
818
|
const emitter = createNanoEvents();
|
|
762
819
|
let closed = false;
|
|
763
820
|
const finalBuf = { value: "" };
|
|
@@ -795,7 +852,7 @@ function openSoniox(opts = {}) {
|
|
|
795
852
|
else openOpts.signal.addEventListener("abort", () => void close(), { once: true });
|
|
796
853
|
return {
|
|
797
854
|
sendAudio(pcm) {
|
|
798
|
-
if (closed || ws.readyState !==
|
|
855
|
+
if (closed || ws.readyState !== WebSocket.OPEN) return;
|
|
799
856
|
ws.send(new Uint8Array(pcm.buffer, pcm.byteOffset, pcm.byteLength), { binary: true });
|
|
800
857
|
},
|
|
801
858
|
on(event, fn) {
|
|
@@ -1107,7 +1164,7 @@ function openRime(opts) {
|
|
|
1107
1164
|
const url = `wss://users-ws.rime.ai/ws2?speaker=${encodeURIComponent(voice)}&modelId=${encodeURIComponent(model)}&audioFormat=pcm&samplingRate=${sampleRate}&lang=${encodeURIComponent(lang)}`;
|
|
1108
1165
|
let ws;
|
|
1109
1166
|
try {
|
|
1110
|
-
ws = new
|
|
1167
|
+
ws = new WebSocket(url, { headers: { Authorization: `Bearer ${apiKey}` } });
|
|
1111
1168
|
} catch (cause) {
|
|
1112
1169
|
throw makeTtsError("tts_connect_failed", `Rime TTS: failed to create WebSocket: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
1113
1170
|
}
|
|
@@ -1167,19 +1224,19 @@ function openRime(opts) {
|
|
|
1167
1224
|
return {
|
|
1168
1225
|
sendText(text) {
|
|
1169
1226
|
if (closed || text.length === 0) return;
|
|
1170
|
-
if (ws.readyState !==
|
|
1227
|
+
if (ws.readyState !== WebSocket.OPEN) return;
|
|
1171
1228
|
doneEmitted = false;
|
|
1172
1229
|
ws.send(JSON.stringify({ text }));
|
|
1173
1230
|
},
|
|
1174
1231
|
flush() {
|
|
1175
1232
|
if (closed) return;
|
|
1176
|
-
if (ws.readyState !==
|
|
1233
|
+
if (ws.readyState !== WebSocket.OPEN) return;
|
|
1177
1234
|
ws.send(JSON.stringify({ text: "." }));
|
|
1178
1235
|
armFirstAudioTimer();
|
|
1179
1236
|
},
|
|
1180
1237
|
cancel() {
|
|
1181
1238
|
if (closed) return;
|
|
1182
|
-
if (ws.readyState ===
|
|
1239
|
+
if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ operation: "clear" }));
|
|
1183
1240
|
emitDoneOnce();
|
|
1184
1241
|
},
|
|
1185
1242
|
on(event, fn) {
|
|
@@ -1200,19 +1257,12 @@ function openRime(opts) {
|
|
|
1200
1257
|
* holds `SttProvider` / `LlmProvider` / `TtsProvider` **descriptors** —
|
|
1201
1258
|
* plain `{ kind, options }` data. At session start the runtime calls the
|
|
1202
1259
|
* resolvers here to turn each descriptor into its openable / callable
|
|
1203
|
-
* host-side counterpart
|
|
1260
|
+
* host-side counterpart.
|
|
1204
1261
|
*
|
|
1205
1262
|
* The guest sandbox never imports these functions, which is how the agent
|
|
1206
1263
|
* bundle stays free of `@ai-sdk/anthropic` / `assemblyai` /
|
|
1207
1264
|
* `@cartesia/cartesia-js`.
|
|
1208
|
-
*
|
|
1209
|
-
* `@ai-sdk/*` packages are loaded via `createRequire` lazily so self-hosted
|
|
1210
|
-
* users only need to install the providers they actually reference. A
|
|
1211
|
-
* missing package is reported as a friendly "package not installed" error
|
|
1212
|
-
* at first session start, not as a module-load failure when the host
|
|
1213
|
-
* package itself is imported.
|
|
1214
1265
|
*/
|
|
1215
|
-
const requireFromHere = createRequire(import.meta.url);
|
|
1216
1266
|
/**
|
|
1217
1267
|
* Look up a provider API key: agent env first (set via `aai secret put` or
|
|
1218
1268
|
* `.env`), then the host's `process.env` as a fallback for self-hosted mode.
|
|
@@ -1249,66 +1299,269 @@ function resolveTts(descriptor) {
|
|
|
1249
1299
|
*/
|
|
1250
1300
|
function resolveLlm(descriptor, env) {
|
|
1251
1301
|
switch (descriptor.kind) {
|
|
1252
|
-
case ANTHROPIC_KIND: {
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
}
|
|
1260
|
-
case
|
|
1261
|
-
const apiKey = requireKey(env, "OPENAI_API_KEY", "OpenAI");
|
|
1262
|
-
const { createOpenAI } = loadProviderPackage("@ai-sdk/openai", "OpenAI");
|
|
1263
|
-
return createOpenAI({ apiKey })(descriptor.options.model);
|
|
1264
|
-
}
|
|
1265
|
-
case GOOGLE_KIND: {
|
|
1266
|
-
const apiKey = requireKey(env, "GOOGLE_GENERATIVE_AI_API_KEY", "Google");
|
|
1267
|
-
const { createGoogleGenerativeAI } = loadProviderPackage("@ai-sdk/google", "Google");
|
|
1268
|
-
return createGoogleGenerativeAI({ apiKey })(descriptor.options.model);
|
|
1269
|
-
}
|
|
1270
|
-
case MISTRAL_KIND: {
|
|
1271
|
-
const apiKey = requireKey(env, "MISTRAL_API_KEY", "Mistral");
|
|
1272
|
-
const { createMistral } = loadProviderPackage("@ai-sdk/mistral", "Mistral");
|
|
1273
|
-
return createMistral({ apiKey })(descriptor.options.model);
|
|
1274
|
-
}
|
|
1275
|
-
case "xai": {
|
|
1276
|
-
const apiKey = requireKey(env, "XAI_API_KEY", "xAI");
|
|
1277
|
-
const { createXai } = loadProviderPackage("@ai-sdk/xai", "xAI");
|
|
1278
|
-
return createXai({ apiKey })(descriptor.options.model);
|
|
1279
|
-
}
|
|
1280
|
-
case GROQ_KIND: {
|
|
1281
|
-
const apiKey = requireKey(env, "GROQ_API_KEY", "Groq");
|
|
1282
|
-
const { createGroq } = loadProviderPackage("@ai-sdk/groq", "Groq");
|
|
1283
|
-
return createGroq({ apiKey })(descriptor.options.model);
|
|
1284
|
-
}
|
|
1302
|
+
case ANTHROPIC_KIND: return createAnthropic({
|
|
1303
|
+
apiKey: requireKey(env, "ANTHROPIC_API_KEY", "Anthropic"),
|
|
1304
|
+
baseURL: "https://api.anthropic.com/v1"
|
|
1305
|
+
})(descriptor.options.model);
|
|
1306
|
+
case OPENAI_KIND: return createOpenAI({ apiKey: requireKey(env, "OPENAI_API_KEY", "OpenAI") })(descriptor.options.model);
|
|
1307
|
+
case GOOGLE_KIND: return createGoogleGenerativeAI({ apiKey: requireKey(env, "GOOGLE_GENERATIVE_AI_API_KEY", "Google") })(descriptor.options.model);
|
|
1308
|
+
case MISTRAL_KIND: return createMistral({ apiKey: requireKey(env, "MISTRAL_API_KEY", "Mistral") })(descriptor.options.model);
|
|
1309
|
+
case "xai": return createXai({ apiKey: requireKey(env, "XAI_API_KEY", "xAI") })(descriptor.options.model);
|
|
1310
|
+
case GROQ_KIND: return createGroq({ apiKey: requireKey(env, "GROQ_API_KEY", "Groq") })(descriptor.options.model);
|
|
1285
1311
|
default: throw new Error(`Unknown LLM provider kind: "${descriptor.kind}". Supported: ${ANTHROPIC_KIND}, ${OPENAI_KIND}, ${GOOGLE_KIND}, ${MISTRAL_KIND}, xai, ${GROQ_KIND}.`);
|
|
1286
1312
|
}
|
|
1287
1313
|
}
|
|
1288
|
-
|
|
1289
|
-
const key = resolveApiKey(name, env);
|
|
1290
|
-
if (!key) throw new Error(`${label} LLM: missing API key. Set ${name} in the agent env.`);
|
|
1291
|
-
return key;
|
|
1292
|
-
}
|
|
1314
|
+
const requireFromHere = createRequire(import.meta.url);
|
|
1293
1315
|
/**
|
|
1294
|
-
*
|
|
1295
|
-
*
|
|
1296
|
-
*
|
|
1297
|
-
* Node module-resolution stack trace.
|
|
1316
|
+
* Lazy-load a package via createRequire so the package is a true optional
|
|
1317
|
+
* peer dependency — if it's not installed the error surfaces only when the
|
|
1318
|
+
* provider is actually used, not at module load time.
|
|
1298
1319
|
*/
|
|
1299
1320
|
function loadProviderPackage(name, label) {
|
|
1300
1321
|
try {
|
|
1301
1322
|
return requireFromHere(name);
|
|
1302
1323
|
} catch (err) {
|
|
1303
|
-
if (
|
|
1324
|
+
if (err instanceof Error && (err.code === "MODULE_NOT_FOUND" || err.code === "ERR_MODULE_NOT_FOUND") && err.message.includes(name)) throw new Error(`${label}: package \`${name}\` is not installed. Run \`pnpm add ${name}\`.`, { cause: err });
|
|
1304
1325
|
throw err;
|
|
1305
1326
|
}
|
|
1306
1327
|
}
|
|
1307
|
-
function
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1328
|
+
function requireKey(env, name, label) {
|
|
1329
|
+
const key = resolveApiKey(name, env);
|
|
1330
|
+
if (!key) throw new Error(`${label} LLM: missing API key. Set ${name} in the agent env.`);
|
|
1331
|
+
return key;
|
|
1332
|
+
}
|
|
1333
|
+
//#endregion
|
|
1334
|
+
//#region host/pinecone-vector.ts
|
|
1335
|
+
function createPineconeVector(opts) {
|
|
1336
|
+
const { Pinecone } = loadProviderPackage("@pinecone-database/pinecone", "Pinecone Vector");
|
|
1337
|
+
const client = new Pinecone({ apiKey: opts.apiKey });
|
|
1338
|
+
const ns = () => client.index(opts.index).namespace(opts.namespace);
|
|
1339
|
+
return {
|
|
1340
|
+
async upsert(id, text, metadata) {
|
|
1341
|
+
const record = {
|
|
1342
|
+
_id: id,
|
|
1343
|
+
text,
|
|
1344
|
+
...metadata ?? {}
|
|
1345
|
+
};
|
|
1346
|
+
await ns().upsertRecords([record]);
|
|
1347
|
+
},
|
|
1348
|
+
async query(text, queryOpts) {
|
|
1349
|
+
const topK = queryOpts?.topK ?? 5;
|
|
1350
|
+
const req = {
|
|
1351
|
+
query: {
|
|
1352
|
+
inputs: { text },
|
|
1353
|
+
topK,
|
|
1354
|
+
...queryOpts?.filter !== void 0 ? { filter: queryOpts.filter } : {}
|
|
1355
|
+
},
|
|
1356
|
+
fields: ["*"]
|
|
1357
|
+
};
|
|
1358
|
+
return (await ns().searchRecords(req)).result.hits.map((hit) => {
|
|
1359
|
+
const { text: hitText, ...rest } = hit.fields;
|
|
1360
|
+
const metadata = Object.keys(rest).length > 0 ? rest : void 0;
|
|
1361
|
+
return {
|
|
1362
|
+
id: hit._id,
|
|
1363
|
+
score: hit._score,
|
|
1364
|
+
text: typeof hitText === "string" ? hitText : "",
|
|
1365
|
+
...metadata !== void 0 ? { metadata } : {}
|
|
1366
|
+
};
|
|
1367
|
+
});
|
|
1368
|
+
},
|
|
1369
|
+
async delete(ids) {
|
|
1370
|
+
const list = Array.isArray(ids) ? ids : [ids];
|
|
1371
|
+
await ns().deleteMany(list);
|
|
1372
|
+
}
|
|
1373
|
+
};
|
|
1374
|
+
}
|
|
1375
|
+
//#endregion
|
|
1376
|
+
//#region host/unstorage-kv.ts
|
|
1377
|
+
/**
|
|
1378
|
+
* Key-value store backed by unstorage.
|
|
1379
|
+
*
|
|
1380
|
+
* Works with any unstorage driver (memory, fs, S3/R2, etc.).
|
|
1381
|
+
*/
|
|
1382
|
+
/**
|
|
1383
|
+
* Create a KV store backed by any unstorage driver.
|
|
1384
|
+
*
|
|
1385
|
+
* @param options - See {@link UnstorageKvOptions}.
|
|
1386
|
+
* @returns A {@link Kv} instance.
|
|
1387
|
+
*
|
|
1388
|
+
* @example
|
|
1389
|
+
* ```ts
|
|
1390
|
+
* import { createStorage } from "unstorage";
|
|
1391
|
+
* import { createUnstorageKv } from "@alexkroman1/aai/unstorage-kv";
|
|
1392
|
+
*
|
|
1393
|
+
* const kv = createUnstorageKv({ storage: createStorage() });
|
|
1394
|
+
* await kv.set("greeting", "hello");
|
|
1395
|
+
* const value = await kv.get<string>("greeting"); // "hello"
|
|
1396
|
+
* ```
|
|
1397
|
+
*/
|
|
1398
|
+
function createUnstorageKv(options) {
|
|
1399
|
+
const store = options.prefix ? prefixStorage(options.storage, options.prefix) : options.storage;
|
|
1400
|
+
return {
|
|
1401
|
+
async get(key) {
|
|
1402
|
+
return await store.getItem(key) ?? null;
|
|
1403
|
+
},
|
|
1404
|
+
async set(key, value, setOptions) {
|
|
1405
|
+
if (JSON.stringify(value).length > 65536) throw new Error(`Value exceeds max size of ${MAX_VALUE_SIZE} bytes`);
|
|
1406
|
+
const storable = value;
|
|
1407
|
+
if (setOptions?.expireIn && setOptions.expireIn > 0) await store.setItem(key, storable, { ttl: Math.ceil(setOptions.expireIn / 1e3) });
|
|
1408
|
+
else await store.setItem(key, storable);
|
|
1409
|
+
},
|
|
1410
|
+
async delete(keys) {
|
|
1411
|
+
const keyArray = Array.isArray(keys) ? keys : [keys];
|
|
1412
|
+
await Promise.all(keyArray.map((k) => store.removeItem(k)));
|
|
1413
|
+
},
|
|
1414
|
+
close() {
|
|
1415
|
+
store.dispose();
|
|
1416
|
+
}
|
|
1417
|
+
};
|
|
1418
|
+
}
|
|
1419
|
+
//#endregion
|
|
1420
|
+
//#region host/providers/resolve-kv.ts
|
|
1421
|
+
/**
|
|
1422
|
+
* Descriptor → concrete `Kv` resolver. Mirror of `resolveLlm` /
|
|
1423
|
+
* `resolveVector`. Always wraps the produced unstorage Storage in
|
|
1424
|
+
* `createUnstorageKv` with the provided per-tenant prefix so namespace
|
|
1425
|
+
* isolation is enforced regardless of backend choice.
|
|
1426
|
+
*/
|
|
1427
|
+
/**
|
|
1428
|
+
* Load a CJS unstorage driver factory. The CJS variants use
|
|
1429
|
+
* `module.exports = defineDriver(...)` so the require result is the
|
|
1430
|
+
* factory itself (not an object with `.default`).
|
|
1431
|
+
*
|
|
1432
|
+
* Delegates to loadProviderPackage (lazy-load via createRequire so the
|
|
1433
|
+
* driver is a true optional peer dep).
|
|
1434
|
+
*/
|
|
1435
|
+
function loadDriver(modulePath, label) {
|
|
1436
|
+
return loadProviderPackage(modulePath, `${label} KV: driver`);
|
|
1437
|
+
}
|
|
1438
|
+
/**
|
|
1439
|
+
* Build a lazy unstorage Driver that defers loading the real driver
|
|
1440
|
+
* factory until the first I/O operation. This is necessary for drivers
|
|
1441
|
+
* whose peer dependencies (e.g. `ioredis`) may not be installed on the
|
|
1442
|
+
* host at startup — the missing package will only surface when the agent
|
|
1443
|
+
* actually performs KV operations, not at session creation time.
|
|
1444
|
+
*/
|
|
1445
|
+
function makeLazyDriver(modulePath, label, opts) {
|
|
1446
|
+
let resolved = null;
|
|
1447
|
+
const get = () => {
|
|
1448
|
+
if (!resolved) resolved = loadDriver(modulePath, label)(opts);
|
|
1449
|
+
return resolved;
|
|
1450
|
+
};
|
|
1451
|
+
return {
|
|
1452
|
+
name: label.toLowerCase(),
|
|
1453
|
+
hasItem: (key, txOpts) => get().hasItem(key, txOpts),
|
|
1454
|
+
getItem: (key, txOpts) => get().getItem(key, txOpts),
|
|
1455
|
+
getItemRaw: (key, txOpts) => get().getItemRaw?.(key, txOpts) ?? null,
|
|
1456
|
+
setItem: (key, value, txOpts) => get().setItem?.(key, value, txOpts),
|
|
1457
|
+
setItemRaw: (key, value, txOpts) => get().setItemRaw?.(key, value, txOpts),
|
|
1458
|
+
removeItem: (key, txOpts) => get().removeItem?.(key, txOpts),
|
|
1459
|
+
getKeys: (base, txOpts) => get().getKeys(base, txOpts),
|
|
1460
|
+
clear: (base, txOpts) => get().clear?.(base, txOpts),
|
|
1461
|
+
dispose: () => resolved ? resolved.dispose?.() : void 0
|
|
1462
|
+
};
|
|
1463
|
+
}
|
|
1464
|
+
/** Resolve a {@link KvProvider} descriptor into a {@link Kv}. */
|
|
1465
|
+
function resolveKv(descriptor, env, prefix) {
|
|
1466
|
+
switch (descriptor.kind) {
|
|
1467
|
+
case MEMORY_KV_KIND: return createUnstorageKv({
|
|
1468
|
+
storage: createStorage(),
|
|
1469
|
+
prefix
|
|
1470
|
+
});
|
|
1471
|
+
case "fs": {
|
|
1472
|
+
const opts = descriptor.options;
|
|
1473
|
+
return createUnstorageKv({
|
|
1474
|
+
storage: createStorage({ driver: loadDriver("unstorage/drivers/fs", "fs")({ base: opts.base }) }),
|
|
1475
|
+
prefix
|
|
1476
|
+
});
|
|
1477
|
+
}
|
|
1478
|
+
case "s3": {
|
|
1479
|
+
const opts = descriptor.options;
|
|
1480
|
+
const accessKeyId = resolveApiKey("AWS_ACCESS_KEY_ID", env);
|
|
1481
|
+
const secretAccessKey = resolveApiKey("AWS_SECRET_ACCESS_KEY", env);
|
|
1482
|
+
if (!(accessKeyId && secretAccessKey)) throw new Error("S3 KV: missing AWS credentials. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY in the agent env.");
|
|
1483
|
+
return createUnstorageKv({
|
|
1484
|
+
storage: createStorage({ driver: loadDriver("unstorage/drivers/s3", "S3")({
|
|
1485
|
+
bucket: opts.bucket,
|
|
1486
|
+
...opts.endpoint !== void 0 ? { endpoint: opts.endpoint } : {},
|
|
1487
|
+
region: opts.region ?? "auto",
|
|
1488
|
+
accessKeyId,
|
|
1489
|
+
secretAccessKey
|
|
1490
|
+
}) }),
|
|
1491
|
+
prefix
|
|
1492
|
+
});
|
|
1493
|
+
}
|
|
1494
|
+
case REDIS_KV_KIND: {
|
|
1495
|
+
const opts = descriptor.options;
|
|
1496
|
+
const url = resolveApiKey("REDIS_URL", env);
|
|
1497
|
+
if (!url) throw new Error("Redis KV: missing connection URL. Set REDIS_URL in the agent env.");
|
|
1498
|
+
return createUnstorageKv({
|
|
1499
|
+
storage: createStorage({ driver: makeLazyDriver("unstorage/drivers/redis", "Redis", {
|
|
1500
|
+
url,
|
|
1501
|
+
...opts.tls !== void 0 ? { tls: opts.tls } : {}
|
|
1502
|
+
}) }),
|
|
1503
|
+
prefix
|
|
1504
|
+
});
|
|
1505
|
+
}
|
|
1506
|
+
default: throw new Error(`Unknown KV provider kind: "${descriptor.kind}". Supported: ${MEMORY_KV_KIND}, fs, s3, ${REDIS_KV_KIND}.`);
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
//#endregion
|
|
1510
|
+
//#region host/providers/resolve-vector.ts
|
|
1511
|
+
/**
|
|
1512
|
+
* Descriptor → concrete `Vector` resolver. Mirror of `resolveLlm`.
|
|
1513
|
+
*
|
|
1514
|
+
* Pulls API keys from the agent env so descriptors stay
|
|
1515
|
+
* secret-free. Lazy-loads provider SDKs via `createRequire` so
|
|
1516
|
+
* unused providers never enter the bundle.
|
|
1517
|
+
*/
|
|
1518
|
+
/** Resolve a {@link VectorProvider} descriptor into a {@link Vector}. */
|
|
1519
|
+
function resolveVector(descriptor, env, namespace) {
|
|
1520
|
+
switch (descriptor.kind) {
|
|
1521
|
+
case IN_MEMORY_VECTOR_KIND: return createMemoryVector({ namespace });
|
|
1522
|
+
case PINECONE_VECTOR_KIND: {
|
|
1523
|
+
const apiKey = resolveApiKey("PINECONE_API_KEY", env);
|
|
1524
|
+
if (!apiKey) throw new Error("Pinecone Vector: missing API key. Set PINECONE_API_KEY in the agent env.");
|
|
1525
|
+
const opts = descriptor.options;
|
|
1526
|
+
return createPineconeVector({
|
|
1527
|
+
apiKey,
|
|
1528
|
+
index: opts.index,
|
|
1529
|
+
namespace
|
|
1530
|
+
});
|
|
1531
|
+
}
|
|
1532
|
+
default: throw new Error(`Unknown Vector provider kind: "${descriptor.kind}". Supported: ${IN_MEMORY_VECTOR_KIND}, ${PINECONE_VECTOR_KIND}.`);
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
//#endregion
|
|
1536
|
+
//#region sdk/system-prompt.ts
|
|
1537
|
+
function getFormattedDate() {
|
|
1538
|
+
return (/* @__PURE__ */ new Date()).toLocaleDateString("en-US", {
|
|
1539
|
+
weekday: "long",
|
|
1540
|
+
year: "numeric",
|
|
1541
|
+
month: "long",
|
|
1542
|
+
day: "numeric"
|
|
1543
|
+
});
|
|
1544
|
+
}
|
|
1545
|
+
const VOICE_RULES = "\n\nCRITICAL OUTPUT RULES — you MUST follow these for EVERY response:\nYour response will be spoken aloud by a TTS system and displayed as plain text.\n- NEVER use markdown: no **, no *, no _, no #, no `, no [](), no ---\n- NEVER use bullet points (-, *, •) or numbered lists (1., 2.)\n- NEVER use code blocks or inline code\n- NEVER mention tools, search, APIs, or technical failures to the user. If a tool returns no results, just answer naturally without explaining why.\n- Write exactly as you would say it out loud to a friend\n- Use short conversational sentences. To list things, say \"First,\" \"Next,\" \"Finally,\"\n- Keep responses concise — 1 to 3 sentences max";
|
|
1546
|
+
/**
|
|
1547
|
+
* Build the system prompt sent to the LLM from the agent configuration.
|
|
1548
|
+
*
|
|
1549
|
+
* Assembles the default system prompt, today's date, agent-specific instructions,
|
|
1550
|
+
* and optional sections for tool usage preamble and voice output rules.
|
|
1551
|
+
*
|
|
1552
|
+
* @param config - The serializable agent configuration (name, systemPrompt, etc.).
|
|
1553
|
+
* @param opts.hasTools - When `true`, appends a preamble instructing the LLM to
|
|
1554
|
+
* speak a brief phrase before each tool call to fill silence.
|
|
1555
|
+
* @param opts.voice - When `true`, appends strict voice-specific output rules
|
|
1556
|
+
* (no markdown, no bullet points, conversational tone, concise responses).
|
|
1557
|
+
* @returns The assembled system prompt string.
|
|
1558
|
+
*/
|
|
1559
|
+
function buildSystemPrompt(config, opts) {
|
|
1560
|
+
const { hasTools } = opts;
|
|
1561
|
+
const agentInstructions = config.systemPrompt && config.systemPrompt !== DEFAULT_SYSTEM_PROMPT ? `\n\nAgent-Specific Instructions:\n${config.systemPrompt}` : "";
|
|
1562
|
+
const toolPreamble = hasTools ? "\n\nWhen you decide to use a tool, ALWAYS say a brief natural phrase BEFORE the tool call (e.g. \"Let me look that up\" or \"One moment while I check\"). This fills silence while the tool executes. Keep preambles to one short sentence." : "";
|
|
1563
|
+
const guidance = opts.toolGuidance && opts.toolGuidance.length > 0 ? `\n\nBuilt-in Tool Usage:\n${opts.toolGuidance.join("\n")}` : "";
|
|
1564
|
+
return DEFAULT_SYSTEM_PROMPT + `\n\nToday's date is ${getFormattedDate()}.` + agentInstructions + toolPreamble + guidance + (opts.voice ? VOICE_RULES : "");
|
|
1312
1565
|
}
|
|
1313
1566
|
//#endregion
|
|
1314
1567
|
//#region host/runtime-config.ts
|
|
@@ -1352,7 +1605,7 @@ const jsonLogger = {
|
|
|
1352
1605
|
};
|
|
1353
1606
|
/** Default S2S endpoint configuration. */
|
|
1354
1607
|
const DEFAULT_S2S_CONFIG = {
|
|
1355
|
-
wssUrl: "wss://agents.assemblyai.com/v1/
|
|
1608
|
+
wssUrl: "wss://agents.assemblyai.com/v1/ws",
|
|
1356
1609
|
inputSampleRate: DEFAULT_STT_SAMPLE_RATE,
|
|
1357
1610
|
outputSampleRate: DEFAULT_TTS_SAMPLE_RATE
|
|
1358
1611
|
};
|
|
@@ -1593,7 +1846,7 @@ function createSessionCore(opts) {
|
|
|
1593
1846
|
*/
|
|
1594
1847
|
const yieldTick = () => new Promise((r) => setTimeout(r, 0));
|
|
1595
1848
|
function buildToolContext(opts) {
|
|
1596
|
-
const { env, state, kv, messages, sessionId } = opts;
|
|
1849
|
+
const { env, state, kv, vector, messages, sessionId } = opts;
|
|
1597
1850
|
return {
|
|
1598
1851
|
env,
|
|
1599
1852
|
state: state ?? {},
|
|
@@ -1601,6 +1854,10 @@ function buildToolContext(opts) {
|
|
|
1601
1854
|
if (!kv) throw new Error("KV not available");
|
|
1602
1855
|
return kv;
|
|
1603
1856
|
},
|
|
1857
|
+
get vector() {
|
|
1858
|
+
if (!vector) throw new Error("Vector not available");
|
|
1859
|
+
return vector;
|
|
1860
|
+
},
|
|
1604
1861
|
messages: messages ?? [],
|
|
1605
1862
|
sessionId: sessionId ?? "",
|
|
1606
1863
|
send(event, data) {
|
|
@@ -2068,7 +2325,7 @@ function createPipelineTransport(opts) {
|
|
|
2068
2325
|
//#region host/s2s.ts
|
|
2069
2326
|
const uint8ToBase64 = (bytes) => Buffer.from(bytes).toString("base64");
|
|
2070
2327
|
const base64ToUint8 = (base64) => new Uint8Array(Buffer.from(base64, "base64"));
|
|
2071
|
-
const defaultCreateS2sWebSocket = (url, opts) => new
|
|
2328
|
+
const defaultCreateS2sWebSocket = (url, opts) => new WebSocket(url, { headers: opts.headers });
|
|
2072
2329
|
const S2sMessageSchema = z.discriminatedUnion("type", [
|
|
2073
2330
|
z.object({
|
|
2074
2331
|
type: z.literal("session.ready"),
|
|
@@ -2508,50 +2765,6 @@ function createS2sTransport(opts) {
|
|
|
2508
2765
|
};
|
|
2509
2766
|
}
|
|
2510
2767
|
//#endregion
|
|
2511
|
-
//#region host/unstorage-kv.ts
|
|
2512
|
-
/**
|
|
2513
|
-
* Key-value store backed by unstorage.
|
|
2514
|
-
*
|
|
2515
|
-
* Works with any unstorage driver (memory, fs, S3/R2, etc.).
|
|
2516
|
-
*/
|
|
2517
|
-
/**
|
|
2518
|
-
* Create a KV store backed by any unstorage driver.
|
|
2519
|
-
*
|
|
2520
|
-
* @param options - See {@link UnstorageKvOptions}.
|
|
2521
|
-
* @returns A {@link Kv} instance.
|
|
2522
|
-
*
|
|
2523
|
-
* @example
|
|
2524
|
-
* ```ts
|
|
2525
|
-
* import { createStorage } from "unstorage";
|
|
2526
|
-
* import { createUnstorageKv } from "@alexkroman1/aai/unstorage-kv";
|
|
2527
|
-
*
|
|
2528
|
-
* const kv = createUnstorageKv({ storage: createStorage() });
|
|
2529
|
-
* await kv.set("greeting", "hello");
|
|
2530
|
-
* const value = await kv.get<string>("greeting"); // "hello"
|
|
2531
|
-
* ```
|
|
2532
|
-
*/
|
|
2533
|
-
function createUnstorageKv(options) {
|
|
2534
|
-
const store = options.prefix ? prefixStorage(options.storage, options.prefix) : options.storage;
|
|
2535
|
-
return {
|
|
2536
|
-
async get(key) {
|
|
2537
|
-
return await store.getItem(key) ?? null;
|
|
2538
|
-
},
|
|
2539
|
-
async set(key, value, setOptions) {
|
|
2540
|
-
if (JSON.stringify(value).length > 65536) throw new Error(`Value exceeds max size of ${MAX_VALUE_SIZE} bytes`);
|
|
2541
|
-
const storable = value;
|
|
2542
|
-
if (setOptions?.expireIn && setOptions.expireIn > 0) await store.setItem(key, storable, { ttl: Math.ceil(setOptions.expireIn / 1e3) });
|
|
2543
|
-
else await store.setItem(key, storable);
|
|
2544
|
-
},
|
|
2545
|
-
async delete(keys) {
|
|
2546
|
-
const keyArray = Array.isArray(keys) ? keys : [keys];
|
|
2547
|
-
await Promise.all(keyArray.map((k) => store.removeItem(k)));
|
|
2548
|
-
},
|
|
2549
|
-
close() {
|
|
2550
|
-
store.dispose();
|
|
2551
|
-
}
|
|
2552
|
-
};
|
|
2553
|
-
}
|
|
2554
|
-
//#endregion
|
|
2555
2768
|
//#region host/ws-handler.ts
|
|
2556
2769
|
/**
|
|
2557
2770
|
* WebSocket session lifecycle handler.
|
|
@@ -2787,6 +3000,10 @@ function resolveLlmIfDescriptor(value, env) {
|
|
|
2787
3000
|
function createLocalKv() {
|
|
2788
3001
|
return createUnstorageKv({ storage: createStorage() });
|
|
2789
3002
|
}
|
|
3003
|
+
/** Create an in-memory Vector store (default for self-hosted). */
|
|
3004
|
+
function createLocalVector(slug) {
|
|
3005
|
+
return createMemoryVector({ namespace: slug });
|
|
3006
|
+
}
|
|
2790
3007
|
/**
|
|
2791
3008
|
* Create an agent runtime — the execution engine for a voice agent.
|
|
2792
3009
|
*
|
|
@@ -2800,8 +3017,11 @@ function createLocalKv() {
|
|
|
2800
3017
|
* @public
|
|
2801
3018
|
*/
|
|
2802
3019
|
function createRuntime(opts) {
|
|
2803
|
-
const { agent, env, kv = createLocalKv(), createWebSocket, logger = consoleLogger, s2sConfig = DEFAULT_S2S_CONFIG, sessionStartTimeoutMs, shutdownTimeoutMs = DEFAULT_SHUTDOWN_TIMEOUT_MS } = opts;
|
|
3020
|
+
const { agent, env, kv = createLocalKv(), vector, createWebSocket, logger = consoleLogger, s2sConfig = DEFAULT_S2S_CONFIG, sessionStartTimeoutMs, shutdownTimeoutMs = DEFAULT_SHUTDOWN_TIMEOUT_MS } = opts;
|
|
2804
3021
|
const mode = assertProviderTriple(opts.stt, opts.llm, opts.tts);
|
|
3022
|
+
const slug = agent.name ?? "local";
|
|
3023
|
+
const resolvedKv = agent.kv ? resolveKv(agent.kv, env, "") : kv;
|
|
3024
|
+
const resolvedVector = agent.vector ? resolveVector(agent.vector, env, slug) : vector ?? createLocalVector(slug);
|
|
2805
3025
|
const agentConfig = toAgentConfig(agent);
|
|
2806
3026
|
const sessions = /* @__PURE__ */ new Map();
|
|
2807
3027
|
const sinkMap = /* @__PURE__ */ new Map();
|
|
@@ -2821,7 +3041,8 @@ function createRuntime(opts) {
|
|
|
2821
3041
|
tool,
|
|
2822
3042
|
env: frozenEnv,
|
|
2823
3043
|
sessionId: sessionId ?? "",
|
|
2824
|
-
kv,
|
|
3044
|
+
kv: resolvedKv,
|
|
3045
|
+
vector: resolvedVector,
|
|
2825
3046
|
messages,
|
|
2826
3047
|
logger
|
|
2827
3048
|
});
|
|
@@ -2853,7 +3074,8 @@ function createRuntime(opts) {
|
|
|
2853
3074
|
env: frozenEnv,
|
|
2854
3075
|
state: getState(sessionId ?? ""),
|
|
2855
3076
|
sessionId: sessionId ?? "",
|
|
2856
|
-
kv,
|
|
3077
|
+
kv: resolvedKv,
|
|
3078
|
+
vector: resolvedVector,
|
|
2857
3079
|
messages,
|
|
2858
3080
|
logger,
|
|
2859
3081
|
send: sink ? (event, data) => sink.event({
|
|
@@ -3028,6 +3250,47 @@ async function serveStatic(dir, req, res) {
|
|
|
3028
3250
|
return false;
|
|
3029
3251
|
}
|
|
3030
3252
|
}
|
|
3253
|
+
function handleVectorPost(vector, req, res) {
|
|
3254
|
+
let body = "";
|
|
3255
|
+
req.on("data", (chunk) => {
|
|
3256
|
+
body += chunk;
|
|
3257
|
+
});
|
|
3258
|
+
req.on("end", async () => {
|
|
3259
|
+
try {
|
|
3260
|
+
const json = JSON.parse(body);
|
|
3261
|
+
const parsed = VectorRequestSchema.safeParse(json);
|
|
3262
|
+
if (!parsed.success) {
|
|
3263
|
+
res.statusCode = 400;
|
|
3264
|
+
res.end(JSON.stringify({ error: parsed.error.message }));
|
|
3265
|
+
return;
|
|
3266
|
+
}
|
|
3267
|
+
const op = parsed.data;
|
|
3268
|
+
let result;
|
|
3269
|
+
switch (op.op) {
|
|
3270
|
+
case "upsert":
|
|
3271
|
+
await vector.upsert(op.id, op.text, op.metadata);
|
|
3272
|
+
result = "OK";
|
|
3273
|
+
break;
|
|
3274
|
+
case "query":
|
|
3275
|
+
result = await vector.query(op.text, {
|
|
3276
|
+
...op.topK !== void 0 ? { topK: op.topK } : {},
|
|
3277
|
+
...op.filter !== void 0 ? { filter: op.filter } : {}
|
|
3278
|
+
});
|
|
3279
|
+
break;
|
|
3280
|
+
case "delete":
|
|
3281
|
+
await vector.delete(op.ids);
|
|
3282
|
+
result = "OK";
|
|
3283
|
+
break;
|
|
3284
|
+
default: break;
|
|
3285
|
+
}
|
|
3286
|
+
res.statusCode = 200;
|
|
3287
|
+
res.end(JSON.stringify({ result }));
|
|
3288
|
+
} catch (err) {
|
|
3289
|
+
res.statusCode = 500;
|
|
3290
|
+
res.end(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }));
|
|
3291
|
+
}
|
|
3292
|
+
});
|
|
3293
|
+
}
|
|
3031
3294
|
function handleKvGet(kv, req, res) {
|
|
3032
3295
|
const key = new URL(req.url ?? "/", "http://localhost").searchParams.get("key");
|
|
3033
3296
|
if (!key) {
|
|
@@ -3054,7 +3317,7 @@ function handleKvGet(kv, req, res) {
|
|
|
3054
3317
|
* @internal Used by aai-cli dev server.
|
|
3055
3318
|
*/
|
|
3056
3319
|
function createServer(options) {
|
|
3057
|
-
const { runtime, clientHtml, clientDir, logger = consoleLogger, kv } = options;
|
|
3320
|
+
const { runtime, clientHtml, clientDir, logger = consoleLogger, kv, vector } = options;
|
|
3058
3321
|
const name = options.name ?? "agent";
|
|
3059
3322
|
if (clientHtml && clientDir) throw new Error("clientHtml and clientDir are mutually exclusive");
|
|
3060
3323
|
const escapedName = escapeHtml(name);
|
|
@@ -3077,6 +3340,10 @@ function createServer(options) {
|
|
|
3077
3340
|
handleKvGet(kv, req, res);
|
|
3078
3341
|
return;
|
|
3079
3342
|
}
|
|
3343
|
+
if (vector && method === "POST" && url === "/vector") {
|
|
3344
|
+
handleVectorPost(vector, req, res);
|
|
3345
|
+
return;
|
|
3346
|
+
}
|
|
3080
3347
|
handleRequest(req, res, url, method);
|
|
3081
3348
|
});
|
|
3082
3349
|
async function handleRequest(req, res, url, method) {
|
|
@@ -3135,4 +3402,4 @@ function createServer(options) {
|
|
|
3135
3402
|
};
|
|
3136
3403
|
}
|
|
3137
3404
|
//#endregion
|
|
3138
|
-
export { DEFAULT_S2S_CONFIG, _internals, consoleLogger, createPipelineTransport, createRuntime, createS2sTransport, createServer, createSessionCore, createUnstorageKv, executeInIsolate, executeToolCall, jsonLogger, resolveAllBuiltins, wireSessionSocket };
|
|
3405
|
+
export { DEFAULT_S2S_CONFIG, _internals, consoleLogger, createMemoryVector, createPineconeVector, createPipelineTransport, createRuntime, createS2sTransport, createServer, createSessionCore, createUnstorageKv, executeInIsolate, executeToolCall, jsonLogger, resolveAllBuiltins, resolveKv, resolveVector, wireSessionSocket };
|