@alexkroman1/aai 0.10.1 → 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
package/dist/server.js CHANGED
@@ -1,14 +1,17 @@
1
- import { filterEnv } from "./_utils.js";
2
- import { t as createDirectExecutor } from "./direct-executor-Ca0wt5H0.js";
3
- import { buildReadyConfig } from "./protocol.js";
4
- import { DEFAULT_S2S_CONFIG, consoleLogger } from "./runtime.js";
5
- import { createSqliteKv } from "./sqlite-kv.js";
6
- import { wireSessionSocket } from "./ws-handler.js";
7
- import { mkdirSync } from "node:fs";
8
- import { WebSocketServer } from "ws";
1
+ import { t as createUnstorageVectorStore } from "./unstorage-vector-Cj5llNhg.js";
2
+ import { i as filterEnv } from "./_utils-DgzpOMSV.js";
3
+ import { t as createDirectExecutor } from "./direct-executor-B-5mq3cu.js";
4
+ import { m as buildReadyConfig } from "./protocol-B-H2Q4ox.js";
5
+ import { n as consoleLogger, t as DEFAULT_S2S_CONFIG } from "./runtime-CxcwaK68.js";
6
+ import { t as createUnstorageKv } from "./unstorage-kv-CDgP-frt.js";
7
+ import { t as wireSessionSocket } from "./ws-handler-C0Q6eSay.js";
8
+ import { createStorage } from "unstorage";
9
9
  import { serve } from "@hono/node-server";
10
10
  import { serveStatic } from "@hono/node-server/serve-static";
11
+ import { createNodeWebSocket } from "@hono/node-ws";
11
12
  import { Hono } from "hono";
13
+ import { html } from "hono/html";
14
+ import { secureHeaders } from "hono/secure-headers";
12
15
  //#region server.ts
13
16
  /**
14
17
  * Self-hostable agent server.
@@ -17,16 +20,6 @@ import { Hono } from "hono";
17
20
  * Calls `createDirectExecutor` + `wireSessionSocket` directly — no
18
21
  * intermediary needed.
19
22
  */
20
- /** Escape HTML special characters to prevent XSS. */
21
- function escapeHtml(s) {
22
- return s.replace(/[&<>"']/g, (ch) => ({
23
- "&": "&amp;",
24
- "<": "&lt;",
25
- ">": "&gt;",
26
- "\"": "&quot;",
27
- "'": "&#39;"
28
- })[ch]);
29
- }
30
23
  /**
31
24
  * Create an HTTP + WebSocket server for self-hosted agent deployments.
32
25
  *
@@ -66,23 +59,20 @@ async function drainSessions(sessions, shutdownTimeoutMs, logger) {
66
59
  }
67
60
  function createServer(options) {
68
61
  if (options.clientHtml && options.clientDir) throw new Error("ServerOptions: clientHtml and clientDir are mutually exclusive — provide one or the other, not both.");
69
- const { agent, kv, vector, clientHtml, clientDir, logger = consoleLogger, s2sConfig = DEFAULT_S2S_CONFIG, shutdownTimeoutMs = 3e4 } = options;
62
+ const { agent, clientHtml, clientDir, logger = consoleLogger, s2sConfig = DEFAULT_S2S_CONFIG, shutdownTimeoutMs = 3e4 } = options;
70
63
  const env = filterEnv(options.env ?? (typeof process !== "undefined" ? process.env : {}));
71
- const resolvedKv = kv ?? (() => {
72
- mkdirSync(".aai", { recursive: true });
73
- return createSqliteKv();
74
- })();
64
+ const storage = options.storage ?? createStorage();
65
+ const kv = createUnstorageKv({ storage });
75
66
  const executor = createDirectExecutor({
76
67
  agent,
77
68
  env,
78
- kv: resolvedKv,
79
- ...vector ? { vector } : {},
69
+ kv,
70
+ vector: createUnstorageVectorStore({ storage }),
80
71
  logger,
81
72
  s2sConfig
82
73
  });
83
74
  const sessions = /* @__PURE__ */ new Map();
84
75
  const readyConfig = buildReadyConfig(s2sConfig);
85
- const safeAgentName = escapeHtml(agent.name);
86
76
  function handleWs(ws, skipGreeting, resumeFrom) {
87
77
  wireSessionSocket(ws, {
88
78
  sessions,
@@ -108,6 +98,7 @@ function createServer(options) {
108
98
  async listen(port = 3e3) {
109
99
  if (serverHandle) throw new Error("Server is already listening");
110
100
  const app = new Hono();
101
+ const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app });
111
102
  app.onError((err, c) => {
112
103
  logger.error(`${c.req.method} ${c.req.path} error: ${err.message}`);
113
104
  return c.json({ error: "Internal Server Error" }, 500);
@@ -122,6 +113,24 @@ function createServer(options) {
122
113
  if (status >= 400) logger.error(`${method} ${path} ${status} ${ms}ms`);
123
114
  else logger.info(`${method} ${path} ${status} ${ms}ms`);
124
115
  });
116
+ app.use("*", secureHeaders({ contentSecurityPolicy: {
117
+ defaultSrc: ["'self'"],
118
+ scriptSrc: ["'self'", "blob:"],
119
+ styleSrc: [
120
+ "'self'",
121
+ "'unsafe-inline'",
122
+ "https://fonts.googleapis.com"
123
+ ],
124
+ connectSrc: [
125
+ "'self'",
126
+ "wss:",
127
+ "ws:"
128
+ ],
129
+ imgSrc: ["'self'", "data:"],
130
+ fontSrc: ["'self'", "https://fonts.gstatic.com"],
131
+ objectSrc: ["'none'"],
132
+ baseUri: ["'self'"]
133
+ } }));
125
134
  app.get("/health", (c) => c.json({
126
135
  status: "ok",
127
136
  name: agent.name
@@ -129,40 +138,35 @@ function createServer(options) {
129
138
  app.get("/kv", async (c) => {
130
139
  const key = c.req.query("key");
131
140
  if (!key) return c.json({ error: "Missing key query parameter" }, 400);
132
- const value = await resolvedKv.get(key);
141
+ const value = await kv.get(key);
133
142
  if (value === null) return c.json(null, 404);
134
143
  return c.json(value);
135
144
  });
136
145
  if (clientDir) app.use("/*", serveStatic({ root: clientDir }));
137
- const csp = "default-src 'self'; script-src 'self' blob:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; connect-src 'self' wss: ws:; img-src 'self' data:; font-src 'self' https://fonts.gstatic.com; object-src 'none'; base-uri 'self'";
138
146
  app.get("/", (c) => {
139
- if (clientHtml) return c.html(clientHtml, 200, { "Content-Security-Policy": csp });
140
- return c.html(`<!DOCTYPE html><html><body><h1>${safeAgentName}</h1><p>Agent server running.</p></body></html>`, 200, { "Content-Security-Policy": csp });
147
+ if (clientHtml) return c.html(clientHtml);
148
+ return c.html(html`<!DOCTYPE html><html><body><h1>${agent.name}</h1><p>Agent server running.</p></body></html>`);
141
149
  });
150
+ app.get("/websocket", upgradeWebSocket((c) => {
151
+ const resumeFrom = c.req.query("sessionId") ?? void 0;
152
+ const skipGreeting = c.req.query("resume") !== void 0 || resumeFrom !== void 0;
153
+ logger.info(`WS upgrade ${c.req.path}${skipGreeting ? " (resume)" : ""}`);
154
+ return { onOpen(_evt, ws) {
155
+ if (ws.raw) handleWs(ws.raw, skipGreeting, resumeFrom);
156
+ } };
157
+ }));
142
158
  const nodeServer = serve({
143
159
  fetch: app.fetch,
144
160
  port
145
161
  });
162
+ injectWebSocket(nodeServer);
146
163
  await new Promise((resolve, reject) => {
147
164
  nodeServer.on("listening", resolve);
148
165
  nodeServer.on("error", reject);
149
166
  });
150
167
  const addr = nodeServer.address();
151
168
  listenPort = typeof addr === "object" && addr ? addr.port : port;
152
- const wss = new WebSocketServer({ noServer: true });
153
- nodeServer.on("upgrade", (req, socket, head) => {
154
- const reqUrl = new URL(req.url ?? "/", `http://localhost:${listenPort}`);
155
- const resumeFrom = reqUrl.searchParams.get("sessionId") ?? void 0;
156
- const skipGreeting = reqUrl.searchParams.has("resume") || resumeFrom !== void 0;
157
- logger.info(`WS upgrade ${reqUrl.pathname}${skipGreeting ? " (resume)" : ""}`);
158
- wss.handleUpgrade(req, socket, head, (ws) => {
159
- handleWs(ws, skipGreeting, resumeFrom);
160
- });
161
- });
162
169
  serverHandle = { async shutdown() {
163
- await new Promise((resolve, reject) => {
164
- wss.close((err) => err ? reject(err) : resolve());
165
- });
166
170
  await new Promise((resolve, reject) => {
167
171
  nodeServer.close((err) => err ? reject(err) : resolve());
168
172
  });
@@ -1,9 +1,9 @@
1
- import { DEFAULT_INSTRUCTIONS } from "./types.js";
2
- import { errorDetail, errorMessage, toolError } from "./_utils.js";
3
- import { HOOK_TIMEOUT_MS, MAX_TOOL_RESULT_CHARS } from "./protocol.js";
4
- import { consoleLogger } from "./runtime.js";
5
- import { activeSessionsUpDown, bargeInCounter, idleTimeoutCounter, sessionCounter, toolCallCounter, toolCallDuration, toolCallErrorCounter, tracer, turnCounter, turnStepsHistogram } from "./telemetry.js";
6
- import { connectS2s, defaultCreateS2sWebSocket } from "./s2s.js";
1
+ import { r as DEFAULT_INSTRUCTIONS } from "./types-D8ZBxTL_.js";
2
+ import { n as errorDetail, r as errorMessage, s as toolError } from "./_utils-DgzpOMSV.js";
3
+ import { c as MAX_TOOL_RESULT_CHARS, o as HOOK_TIMEOUT_MS } from "./protocol-B-H2Q4ox.js";
4
+ import { n as consoleLogger } from "./runtime-CxcwaK68.js";
5
+ import { _ as turnStepsHistogram, a as idleTimeoutCounter, d as toolCallCounter, f as toolCallDuration, g as turnCounter, h as tracer, n as activeSessionsUpDown, p as toolCallErrorCounter, r as bargeInCounter, u as sessionCounter } from "./telemetry-CJlaDFNc.js";
6
+ import { n as defaultCreateS2sWebSocket, t as connectS2s } from "./s2s-M7JqtgFw.js";
7
7
  //#region _session-ctx.ts
8
8
  const DEFAULT_MAX_HISTORY = 200;
9
9
  function buildCtx(opts) {
package/dist/session.js CHANGED
@@ -1,2 +1,2 @@
1
- import { i as persistKey, n as createS2sSession, r as buildSystemPrompt, t as _internals } from "./session-BkN9u0ni.js";
1
+ import { i as persistKey, n as createS2sSession, r as buildSystemPrompt, t as _internals } from "./session-BYlwcrya.js";
2
2
  export { _internals, buildSystemPrompt, createS2sSession, persistKey };
@@ -0,0 +1,95 @@
1
+ import { createRequire } from "node:module";
2
+ import { SpanStatusCode, SpanStatusCode as SpanStatusCode$1, context, metrics, metrics as metrics$1, trace, trace as trace$1 } from "@opentelemetry/api";
3
+ //#region telemetry.ts
4
+ /**
5
+ * OpenTelemetry instrumentation helpers for the AAI SDK.
6
+ *
7
+ * Uses `@opentelemetry/api` only — consumers bring their own SDK and
8
+ * exporters. When no SDK is configured the API returns no-op instances,
9
+ * so the overhead in uninstrumented environments is negligible.
10
+ *
11
+ * Provides:
12
+ * - `tracer` — a pre-scoped `Tracer` for creating spans
13
+ * - `meter` — a pre-scoped `Meter` for recording metrics
14
+ * - Pre-built counters, histograms, and up/down counters covering the
15
+ * STT → LLM → TTS pipeline
16
+ */
17
+ const SCOPE = "aai";
18
+ const _require = createRequire(import.meta.url);
19
+ let VERSION = "0.0.0";
20
+ try {
21
+ VERSION = _require("./package.json").version;
22
+ } catch {
23
+ VERSION = _require("../package.json").version;
24
+ }
25
+ /** Tracer scoped to the AAI SDK. */
26
+ const tracer = trace.getTracer(SCOPE, VERSION);
27
+ /** Meter scoped to the AAI SDK. */
28
+ const meter = metrics.getMeter(SCOPE, VERSION);
29
+ /** Total sessions opened. */
30
+ const sessionCounter = meter.createCounter("aai.session.count", { description: "Total voice sessions opened" });
31
+ /** Currently active sessions. */
32
+ const activeSessionsUpDown = meter.createUpDownCounter("aai.session.active", { description: "Currently active voice sessions" });
33
+ /** Total user turns (speech → transcript). */
34
+ const turnCounter = meter.createCounter("aai.turn.count", { description: "Total user turns" });
35
+ /** Total tool calls executed. */
36
+ const toolCallCounter = meter.createCounter("aai.tool.call.count", { description: "Total tool calls executed" });
37
+ /** Tool call execution duration in seconds. */
38
+ const toolCallDuration = meter.createHistogram("aai.tool.call.duration", {
39
+ description: "Tool call execution duration in seconds",
40
+ unit: "s"
41
+ });
42
+ /** Total tool call errors. */
43
+ const toolCallErrorCounter = meter.createCounter("aai.tool.call.error.count", { description: "Total tool call errors" });
44
+ /** S2S WebSocket connection duration in seconds. */
45
+ const s2sConnectionDuration = meter.createHistogram("aai.s2s.connection.duration", {
46
+ description: "S2S WebSocket connection duration in seconds",
47
+ unit: "s"
48
+ });
49
+ /** Total S2S errors. */
50
+ const s2sErrorCounter = meter.createCounter("aai.s2s.error.count", { description: "Total S2S errors" });
51
+ /** Number of agentic loop steps (tool calls) per completed turn. */
52
+ const turnStepsHistogram = meter.createHistogram("aai.turn.steps", { description: "Number of agentic loop steps per completed turn" });
53
+ /** Total barge-in (reply interrupted) events. */
54
+ const bargeInCounter = meter.createCounter("aai.turn.bargein.count", { description: "Total barge-in (reply interrupted) events" });
55
+ /** Messages silently dropped because the WebSocket was closed. */
56
+ const wsSendDroppedCounter = meter.createCounter("aai.ws.send_dropped", { description: "Messages silently dropped because the WebSocket was closed" });
57
+ /** Sessions closed due to S2S idle timeout. */
58
+ const idleTimeoutCounter = meter.createCounter("aai.session.idle.timeout.count", { description: "Sessions closed due to S2S idle timeout" });
59
+ /**
60
+ * Run `fn` inside a new span. The span is automatically ended and its
61
+ * status set based on whether `fn` throws.
62
+ */
63
+ function withSpan(name, fn) {
64
+ return tracer.startActiveSpan(name, (span) => {
65
+ try {
66
+ const result = fn(span);
67
+ if (result instanceof Promise) return result.then((v) => {
68
+ span.setStatus({ code: SpanStatusCode.OK });
69
+ span.end();
70
+ return v;
71
+ }).catch((err) => {
72
+ span.setStatus({
73
+ code: SpanStatusCode.ERROR,
74
+ message: err instanceof Error ? err.message : String(err)
75
+ });
76
+ span.recordException(err instanceof Error ? err : new Error(String(err)));
77
+ span.end();
78
+ throw err;
79
+ });
80
+ span.setStatus({ code: SpanStatusCode.OK });
81
+ span.end();
82
+ return result;
83
+ } catch (err) {
84
+ span.setStatus({
85
+ code: SpanStatusCode.ERROR,
86
+ message: err instanceof Error ? err.message : String(err)
87
+ });
88
+ span.recordException(err instanceof Error ? err : new Error(String(err)));
89
+ span.end();
90
+ throw err;
91
+ }
92
+ });
93
+ }
94
+ //#endregion
95
+ export { turnStepsHistogram as _, idleTimeoutCounter as a, s2sConnectionDuration as c, toolCallCounter as d, toolCallDuration as f, turnCounter as g, tracer as h, context as i, s2sErrorCounter as l, trace$1 as m, activeSessionsUpDown as n, meter as o, toolCallErrorCounter as p, bargeInCounter as r, metrics$1 as s, SpanStatusCode$1 as t, sessionCounter as u, withSpan as v, wsSendDroppedCounter as y };
package/dist/telemetry.js CHANGED
@@ -1,95 +1,2 @@
1
- import { createRequire } from "node:module";
2
- import { SpanStatusCode, SpanStatusCode as SpanStatusCode$1, context, metrics, metrics as metrics$1, trace, trace as trace$1 } from "@opentelemetry/api";
3
- //#region telemetry.ts
4
- /**
5
- * OpenTelemetry instrumentation helpers for the AAI SDK.
6
- *
7
- * Uses `@opentelemetry/api` only — consumers bring their own SDK and
8
- * exporters. When no SDK is configured the API returns no-op instances,
9
- * so the overhead in uninstrumented environments is negligible.
10
- *
11
- * Provides:
12
- * - `tracer` — a pre-scoped `Tracer` for creating spans
13
- * - `meter` — a pre-scoped `Meter` for recording metrics
14
- * - Pre-built counters, histograms, and up/down counters covering the
15
- * STT → LLM → TTS pipeline
16
- */
17
- const SCOPE = "aai";
18
- const _require = createRequire(import.meta.url);
19
- let VERSION = "0.0.0";
20
- try {
21
- VERSION = _require("./package.json").version;
22
- } catch {
23
- VERSION = _require("../package.json").version;
24
- }
25
- /** Tracer scoped to the AAI SDK. */
26
- const tracer = trace$1.getTracer(SCOPE, VERSION);
27
- /** Meter scoped to the AAI SDK. */
28
- const meter = metrics$1.getMeter(SCOPE, VERSION);
29
- /** Total sessions opened. */
30
- const sessionCounter = meter.createCounter("aai.session.count", { description: "Total voice sessions opened" });
31
- /** Currently active sessions. */
32
- const activeSessionsUpDown = meter.createUpDownCounter("aai.session.active", { description: "Currently active voice sessions" });
33
- /** Total user turns (speech → transcript). */
34
- const turnCounter = meter.createCounter("aai.turn.count", { description: "Total user turns" });
35
- /** Total tool calls executed. */
36
- const toolCallCounter = meter.createCounter("aai.tool.call.count", { description: "Total tool calls executed" });
37
- /** Tool call execution duration in seconds. */
38
- const toolCallDuration = meter.createHistogram("aai.tool.call.duration", {
39
- description: "Tool call execution duration in seconds",
40
- unit: "s"
41
- });
42
- /** Total tool call errors. */
43
- const toolCallErrorCounter = meter.createCounter("aai.tool.call.error.count", { description: "Total tool call errors" });
44
- /** S2S WebSocket connection duration in seconds. */
45
- const s2sConnectionDuration = meter.createHistogram("aai.s2s.connection.duration", {
46
- description: "S2S WebSocket connection duration in seconds",
47
- unit: "s"
48
- });
49
- /** Total S2S errors. */
50
- const s2sErrorCounter = meter.createCounter("aai.s2s.error.count", { description: "Total S2S errors" });
51
- /** Number of agentic loop steps (tool calls) per completed turn. */
52
- const turnStepsHistogram = meter.createHistogram("aai.turn.steps", { description: "Number of agentic loop steps per completed turn" });
53
- /** Total barge-in (reply interrupted) events. */
54
- const bargeInCounter = meter.createCounter("aai.turn.bargein.count", { description: "Total barge-in (reply interrupted) events" });
55
- /** Messages silently dropped because the WebSocket was closed. */
56
- const wsSendDroppedCounter = meter.createCounter("aai.ws.send_dropped", { description: "Messages silently dropped because the WebSocket was closed" });
57
- /** Sessions closed due to S2S idle timeout. */
58
- const idleTimeoutCounter = meter.createCounter("aai.session.idle.timeout.count", { description: "Sessions closed due to S2S idle timeout" });
59
- /**
60
- * Run `fn` inside a new span. The span is automatically ended and its
61
- * status set based on whether `fn` throws.
62
- */
63
- function withSpan(name, fn) {
64
- return tracer.startActiveSpan(name, (span) => {
65
- try {
66
- const result = fn(span);
67
- if (result instanceof Promise) return result.then((v) => {
68
- span.setStatus({ code: SpanStatusCode$1.OK });
69
- span.end();
70
- return v;
71
- }).catch((err) => {
72
- span.setStatus({
73
- code: SpanStatusCode$1.ERROR,
74
- message: err instanceof Error ? err.message : String(err)
75
- });
76
- span.recordException(err instanceof Error ? err : new Error(String(err)));
77
- span.end();
78
- throw err;
79
- });
80
- span.setStatus({ code: SpanStatusCode$1.OK });
81
- span.end();
82
- return result;
83
- } catch (err) {
84
- span.setStatus({
85
- code: SpanStatusCode$1.ERROR,
86
- message: err instanceof Error ? err.message : String(err)
87
- });
88
- span.recordException(err instanceof Error ? err : new Error(String(err)));
89
- span.end();
90
- throw err;
91
- }
92
- });
93
- }
94
- //#endregion
1
+ import { _ as turnStepsHistogram, a as idleTimeoutCounter, c as s2sConnectionDuration, d as toolCallCounter, f as toolCallDuration, g as turnCounter, h as tracer, i as context, l as s2sErrorCounter, m as trace, n as activeSessionsUpDown, o as meter, p as toolCallErrorCounter, r as bargeInCounter, s as metrics, t as SpanStatusCode, u as sessionCounter, v as withSpan, y as wsSendDroppedCounter } from "./telemetry-CJlaDFNc.js";
95
2
  export { SpanStatusCode, activeSessionsUpDown, bargeInCounter, context, idleTimeoutCounter, meter, metrics, s2sConnectionDuration, s2sErrorCounter, sessionCounter, toolCallCounter, toolCallDuration, toolCallErrorCounter, trace, tracer, turnCounter, turnStepsHistogram, withSpan, wsSendDroppedCounter };
@@ -1,9 +1,7 @@
1
- import { t as createDirectExecutor } from "./direct-executor-Ca0wt5H0.js";
2
- import { createSqliteKv } from "./sqlite-kv.js";
3
- import { createSqliteVectorStore, createTestEmbedFn } from "./sqlite-vector.js";
4
- import { mkdtempSync } from "node:fs";
5
- import { tmpdir } from "node:os";
6
- import { join } from "node:path";
1
+ import { n as createTestEmbedFn, t as createUnstorageVectorStore } from "./unstorage-vector-Cj5llNhg.js";
2
+ import { t as createDirectExecutor } from "./direct-executor-B-5mq3cu.js";
3
+ import { t as createUnstorageKv } from "./unstorage-kv-CDgP-frt.js";
4
+ import { createStorage } from "unstorage";
7
5
  //#region _mock-ws.ts
8
6
  /**
9
7
  * A mock WebSocket implementation for testing.
@@ -472,8 +470,8 @@ var TestHarness = class {
472
470
  * Uses a temp directory that is unique per call for test isolation.
473
471
  */
474
472
  function createTestVectorStore() {
475
- return createSqliteVectorStore({
476
- path: join(mkdtempSync(join(tmpdir(), "aai-test-vec-")), "vectors.db"),
473
+ return createUnstorageVectorStore({
474
+ storage: createStorage(),
477
475
  embedFn: createTestEmbedFn()
478
476
  });
479
477
  }
@@ -507,7 +505,7 @@ function createTestVectorStore() {
507
505
  * @public
508
506
  */
509
507
  function createTestHarness(agent, options = {}) {
510
- const { env = {}, kv = createSqliteKv({ path: ":memory:" }), vector = createTestVectorStore() } = options;
508
+ const { env = {}, kv = createUnstorageKv({ storage: createStorage() }), vector = createTestVectorStore() } = options;
511
509
  return new TestHarness(createDirectExecutor({
512
510
  agent,
513
511
  env,
package/dist/testing.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as installMockWebSocket, i as MockWebSocket, n as TurnResult, r as createTestHarness, t as TestHarness } from "./testing-MRl3SXsI.js";
1
+ import { a as installMockWebSocket, i as MockWebSocket, n as TurnResult, r as createTestHarness, t as TestHarness } from "./testing-BbitshLb.js";
2
2
  export { MockWebSocket, TestHarness, TurnResult, createTestHarness, installMockWebSocket };
@@ -0,0 +1,192 @@
1
+ import { z } from "zod";
2
+ //#region types.ts
3
+ /**
4
+ * Core type definitions for the AAI agent SDK.
5
+ */
6
+ /**
7
+ * Identity helper that preserves the Zod schema generic for type inference.
8
+ *
9
+ * When tools are defined inline in `defineAgent({ tools: { ... } })`, the
10
+ * generic `P` gets widened to the base `ZodObject` type, so `args` in
11
+ * `execute` loses its specific shape. Wrapping a tool definition in
12
+ * `defineTool()` lets TypeScript infer `P` from `parameters` and type
13
+ * `args` correctly.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * import { defineAgent, defineTool } from "aai";
18
+ * import { z } from "zod";
19
+ *
20
+ * export default defineAgent({
21
+ * name: "my-agent",
22
+ * tools: {
23
+ * greet: defineTool({
24
+ * description: "Greet the user",
25
+ * parameters: z.object({ name: z.string() }),
26
+ * execute: ({ name }) => `Hello, ${name}!`, // name is string
27
+ * }),
28
+ * },
29
+ * });
30
+ * ```
31
+ *
32
+ * @public
33
+ */
34
+ function defineTool(def) {
35
+ return def;
36
+ }
37
+ /**
38
+ * Create a typed `defineTool` helper with the session state type baked in.
39
+ *
40
+ * When tools need access to typed session state, you'd normally have to write
41
+ * verbose generics on every `defineTool` call. `createToolFactory` eliminates
42
+ * that boilerplate by returning a `defineTool` variant that already knows `S`.
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * import { createToolFactory, defineAgent } from "aai";
47
+ * import { z } from "zod";
48
+ *
49
+ * interface PortfolioState { holdings: Map<string, number> }
50
+ *
51
+ * const tool = createToolFactory<PortfolioState>();
52
+ *
53
+ * export default defineAgent<PortfolioState>({
54
+ * name: "portfolio",
55
+ * state: () => ({ holdings: new Map() }),
56
+ * tools: {
57
+ * buy: tool({
58
+ * description: "Buy shares",
59
+ * parameters: z.object({ symbol: z.string(), qty: z.number() }),
60
+ * execute: (args, ctx) => {
61
+ * // args.symbol is string, ctx.state is PortfolioState
62
+ * ctx.state.holdings.set(args.symbol, args.qty);
63
+ * },
64
+ * }),
65
+ * },
66
+ * });
67
+ * ```
68
+ *
69
+ * @public
70
+ */
71
+ function createToolFactory() {
72
+ return (def) => def;
73
+ }
74
+ /**
75
+ * Default system prompt used when `instructions` is not provided.
76
+ *
77
+ * Optimized for voice-first interactions: short sentences, no visual
78
+ * formatting, confident tone, and concise answers.
79
+ */
80
+ const DEFAULT_INSTRUCTIONS = `\
81
+ You are AAI, a helpful AI assistant.
82
+
83
+ Voice-First Rules:
84
+ - Optimize for natural speech. Avoid jargon unless central to the answer. \
85
+ Use short, punchy sentences.
86
+ - Never mention "search results," "sources," or "the provided text." \
87
+ Speak as if the knowledge is your own.
88
+ - No visual formatting. Do not say "bullet point," "bold," or "bracketed one." \
89
+ If you need to list items, say "First," "Next," and "Finally."
90
+ - Start with the most important information. No introductory filler.
91
+ - Be concise. Keep answers to 1-3 sentences. For complex topics, provide a high-level summary.
92
+ - Be confident. Avoid hedging phrases like "It seems that" or "I believe."
93
+ - If you don't have enough information, say so directly rather than guessing.
94
+ - Never use exclamation points. Keep your tone calm and conversational.`;
95
+ /** Default greeting spoken when a session starts. */
96
+ const DEFAULT_GREETING = "Hey there. I'm a voice assistant. What can I help you with?";
97
+ /** @internal Zod schema for {@link BuiltinTool}. Exported for reuse in internal schemas. */
98
+ const BuiltinToolSchema = z.enum([
99
+ "web_search",
100
+ "visit_webpage",
101
+ "fetch_json",
102
+ "run_code",
103
+ "vector_search",
104
+ "memory"
105
+ ]);
106
+ /** @internal Zod schema for {@link ToolChoice}. Exported for reuse in internal schemas. */
107
+ const ToolChoiceSchema = z.union([z.enum([
108
+ "auto",
109
+ "required",
110
+ "none"
111
+ ]), z.object({
112
+ type: z.literal("tool"),
113
+ toolName: z.string().min(1)
114
+ })]);
115
+ const ToolDefSchema = z.object({
116
+ description: z.string().min(1, "Tool description must be non-empty"),
117
+ parameters: z.custom((val) => val === void 0 || val instanceof z.ZodType, "Expected a Zod schema").optional(),
118
+ execute: z.function()
119
+ });
120
+ /** Default TTL for persisted session data: 1 hour. */
121
+ const DEFAULT_PERSIST_TTL = 36e5;
122
+ const AgentOptionsSchema = z.object({
123
+ name: z.string().min(1, "Agent name must be non-empty"),
124
+ instructions: z.string().optional(),
125
+ greeting: z.string().optional(),
126
+ sttPrompt: z.string().optional(),
127
+ maxSteps: z.union([z.number().int().positive(), z.function()]).optional(),
128
+ toolChoice: ToolChoiceSchema.optional(),
129
+ builtinTools: z.array(BuiltinToolSchema).optional(),
130
+ tools: z.record(z.string(), ToolDefSchema).optional(),
131
+ state: z.function().optional(),
132
+ persistence: z.union([z.literal(true), z.object({ ttl: z.number().int().positive().optional() })]).optional(),
133
+ onConnect: z.function().optional(),
134
+ onDisconnect: z.function().optional(),
135
+ onError: z.function().optional(),
136
+ onTurn: z.function().optional(),
137
+ onStep: z.function().optional(),
138
+ middleware: z.array(z.object({
139
+ name: z.string().min(1, "Middleware name must be non-empty"),
140
+ beforeInput: z.function().optional(),
141
+ beforeTurn: z.function().optional(),
142
+ afterTurn: z.function().optional(),
143
+ beforeToolCall: z.function().optional(),
144
+ afterToolCall: z.function().optional(),
145
+ beforeOutput: z.function().optional()
146
+ })).optional(),
147
+ idleTimeoutMs: z.number().nonnegative().optional()
148
+ });
149
+ /**
150
+ * Create an agent definition from the given options, applying sensible defaults.
151
+ *
152
+ * This is the main entry point for defining a voice agent. The returned
153
+ * `AgentDef` is consumed by the AAI server at deploy time.
154
+ *
155
+ * @param options - Configuration for the agent including name, instructions,
156
+ * tools, hooks, and other settings.
157
+ * @returns A fully resolved agent definition with all defaults applied.
158
+ *
159
+ * @public
160
+ *
161
+ * @example Basic agent with a custom tool
162
+ * ```ts
163
+ * import { defineAgent } from "aai";
164
+ * import { z } from "zod";
165
+ *
166
+ * export default defineAgent({
167
+ * name: "greeter",
168
+ * instructions: "You greet people warmly.",
169
+ * tools: {
170
+ * greet: {
171
+ * description: "Greet a user by name",
172
+ * parameters: z.object({ name: z.string() }),
173
+ * execute: ({ name }) => `Hello, ${name}!`,
174
+ * },
175
+ * },
176
+ * });
177
+ * ```
178
+ */
179
+ function defineAgent(options) {
180
+ AgentOptionsSchema.parse(options);
181
+ const persistence = options.persistence ? { ttl: typeof options.persistence === "object" ? options.persistence.ttl ?? DEFAULT_PERSIST_TTL : DEFAULT_PERSIST_TTL } : void 0;
182
+ return {
183
+ ...options,
184
+ instructions: options.instructions ?? DEFAULT_INSTRUCTIONS,
185
+ greeting: options.greeting ?? "Hey there. I'm a voice assistant. What can I help you with?",
186
+ maxSteps: options.maxSteps ?? 5,
187
+ tools: options.tools ?? {},
188
+ persistence
189
+ };
190
+ }
191
+ //#endregion
192
+ export { createToolFactory as a, ToolChoiceSchema as i, DEFAULT_GREETING as n, defineAgent as o, DEFAULT_INSTRUCTIONS as r, defineTool as s, BuiltinToolSchema as t };