@alexkroman1/aai 1.0.6 → 1.2.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.
Files changed (54) hide show
  1. package/.turbo/turbo-build.log +11 -11
  2. package/CHANGELOG.md +22 -0
  3. package/dist/_internal-types-CoDTiBd1.js +61 -0
  4. package/dist/host/_mock-ws.d.ts +0 -24
  5. package/dist/host/runtime-barrel.d.ts +0 -1
  6. package/dist/host/runtime-barrel.js +55 -5
  7. package/dist/host/runtime.d.ts +2 -0
  8. package/dist/host/tool-executor.d.ts +1 -0
  9. package/dist/host/ws-handler.d.ts +2 -0
  10. package/dist/index.d.ts +1 -0
  11. package/dist/index.js +90 -1
  12. package/dist/sdk/allowed-hosts.d.ts +34 -0
  13. package/dist/sdk/manifest-barrel.d.ts +3 -5
  14. package/dist/sdk/manifest-barrel.js +2 -52
  15. package/dist/sdk/manifest.d.ts +2 -0
  16. package/dist/sdk/protocol.d.ts +11 -28
  17. package/dist/sdk/protocol.js +6 -3
  18. package/dist/sdk/types.d.ts +2 -0
  19. package/host/_mock-ws.ts +0 -50
  20. package/host/_test-utils.ts +1 -0
  21. package/host/runtime-barrel.ts +0 -1
  22. package/host/runtime.ts +13 -1
  23. package/host/session-ctx.test.ts +387 -0
  24. package/host/session-fixture-replay.test.ts +2 -10
  25. package/host/session.test.ts +19 -41
  26. package/host/tool-executor.test.ts +36 -0
  27. package/host/tool-executor.ts +4 -0
  28. package/host/ws-handler.ts +3 -0
  29. package/index.ts +1 -0
  30. package/package.json +1 -1
  31. package/sdk/__snapshots__/exports.test.ts.snap +79 -0
  32. package/sdk/__snapshots__/schema-shapes.test.ts.snap +187 -0
  33. package/sdk/_test-matchers.test.ts +75 -0
  34. package/sdk/_test-matchers.ts +73 -0
  35. package/sdk/allowed-hosts.test.ts +236 -0
  36. package/sdk/allowed-hosts.ts +113 -0
  37. package/sdk/exports.test.ts +31 -0
  38. package/sdk/manifest-barrel.ts +13 -7
  39. package/sdk/manifest.test.ts +103 -2
  40. package/sdk/manifest.ts +19 -0
  41. package/sdk/protocol-compat.test.ts +0 -6
  42. package/sdk/protocol-snapshot.test.ts +7 -5
  43. package/sdk/protocol.test.ts +107 -21
  44. package/sdk/protocol.ts +7 -15
  45. package/sdk/schema-alignment.test.ts +1 -27
  46. package/sdk/schema-shapes.test.ts +103 -0
  47. package/sdk/tsconfig.json +1 -1
  48. package/sdk/types.test.ts +56 -1
  49. package/sdk/types.ts +2 -0
  50. package/sdk/ws-upgrade.test.ts +8 -8
  51. package/tsconfig.build.json +8 -1
  52. package/tsconfig.json +1 -1
  53. package/vitest.config.ts +1 -0
  54. package/dist/system-prompt-nik_iavo.js +0 -92
@@ -1,5 +1,5 @@
1
1
 
2
- > @alexkroman1/aai@1.0.6 build /home/runner/work/agent/agent/packages/aai
2
+ > @alexkroman1/aai@1.2.0 build /home/runner/work/agent/agent/packages/aai
3
3
  > tsdown && tsc -p tsconfig.build.json
4
4
 
5
5
  ℹ tsdown v0.21.7 powered by rolldown v1.0.0-rc.12
@@ -8,13 +8,13 @@
8
8
  ℹ target: node22
9
9
  ℹ tsconfig: tsconfig.json
10
10
  ℹ Build start
11
- ℹ dist/host/runtime-barrel.js 47.10 kB │ gzip: 14.49 kB
12
- ℹ dist/sdk/protocol.js  4.83 kB │ gzip: 1.77 kB
13
- ℹ dist/index.js  2.49 kB │ gzip: 1.04 kB
14
- ℹ dist/sdk/manifest-barrel.js  2.19 kB │ gzip: 0.99 kB
15
- ℹ dist/system-prompt-nik_iavo.js  4.77 kB │ gzip: 2.09 kB
16
- ℹ dist/constants-VTFoymJ-.js  2.75 kB │ gzip: 1.23 kB
17
- ℹ dist/types-Cfx_4QDK.js  1.74 kB │ gzip: 0.93 kB
18
- ℹ dist/ws-upgrade-BeOQ7fXL.js  1.14 kB │ gzip: 0.54 kB
19
- ℹ 8 files, total: 67.02 kB
20
- ✔ Build complete in 46ms
11
+ ℹ dist/host/runtime-barrel.js 50.02 kB │ gzip: 15.70 kB
12
+ ℹ dist/index.js  6.38 kB │ gzip: 2.49 kB
13
+ ℹ dist/sdk/protocol.js  4.75 kB │ gzip: 1.76 kB
14
+ ℹ dist/sdk/manifest-barrel.js  0.26 kB │ gzip: 0.17 kB
15
+ ℹ dist/constants-VTFoymJ-.js  2.75 kB │ gzip: 1.23 kB
16
+ ℹ dist/_internal-types-CoDTiBd1.js  2.33 kB │ gzip: 0.99 kB
17
+ ℹ dist/types-Cfx_4QDK.js  1.74 kB │ gzip: 0.93 kB
18
+ ℹ dist/ws-upgrade-BeOQ7fXL.js  1.14 kB │ gzip: 0.54 kB
19
+ ℹ 8 files, total: 69.36 kB
20
+ ✔ Build complete in 34ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @alexkroman1/aai
2
2
 
3
+ ## 1.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - ed0dfbb: Add allowedHosts manifest field and host-proxied fetch for sandbox agents
8
+
9
+ ### Patch Changes
10
+
11
+ - 231ebc1: Fix Docker build (missing unzip, CI=true for pnpm) and add test:adversarial command with CI integration
12
+
13
+ ## 1.1.0
14
+
15
+ ### Minor Changes
16
+
17
+ - 5cda7c5: Add ctx.send for real-time tool-to-client events
18
+
19
+ Tools can now push arbitrary events to the browser client via `ctx.send(event, data)`. Events flow over the existing WebSocket as `custom_event` messages. The new `useEvent` React hook subscribes to named events. Migrated solo-rpg, pizza-ordering, dispatch-center, and night-owl templates from `useToolResult` to `ctx.send` + `useEvent`.
20
+
21
+ ### Patch Changes
22
+
23
+ - 41fab1a: Remove dead code: unused exports, wrappers, and test hooks
24
+
3
25
  ## 1.0.6
4
26
 
5
27
  ## 1.0.5
@@ -0,0 +1,61 @@
1
+ import { i as ToolChoiceSchema, t as BuiltinToolSchema } from "./types-Cfx_4QDK.js";
2
+ import { z } from "zod";
3
+ //#region sdk/_internal-types.ts
4
+ /**
5
+ * Zod schema for serializable agent configuration sent over the wire.
6
+ *
7
+ * This is the JSON-safe subset of the agent definition that can be
8
+ * transmitted between the worker and the host process via structured clone.
9
+ */
10
+ const AgentConfigSchema = z.object({
11
+ name: z.string().min(1),
12
+ systemPrompt: z.string(),
13
+ greeting: z.string(),
14
+ sttPrompt: z.string().optional(),
15
+ maxSteps: z.number().int().positive().optional(),
16
+ toolChoice: ToolChoiceSchema.optional(),
17
+ builtinTools: z.array(BuiltinToolSchema).readonly().optional(),
18
+ idleTimeoutMs: z.number().nonnegative().optional()
19
+ });
20
+ /** Extract the serializable {@link AgentConfig} subset from a source object. */
21
+ function toAgentConfig(src) {
22
+ const config = {
23
+ name: src.name,
24
+ systemPrompt: src.systemPrompt,
25
+ greeting: src.greeting
26
+ };
27
+ if (src.sttPrompt !== void 0) config.sttPrompt = src.sttPrompt;
28
+ if (src.maxSteps !== void 0) config.maxSteps = src.maxSteps;
29
+ if (src.toolChoice !== void 0) config.toolChoice = src.toolChoice;
30
+ if (src.builtinTools) config.builtinTools = [...src.builtinTools];
31
+ if (src.idleTimeoutMs !== void 0) config.idleTimeoutMs = src.idleTimeoutMs;
32
+ return config;
33
+ }
34
+ /**
35
+ * Zod schema for serialized tool definitions sent over the wire.
36
+ *
37
+ * `parameters` must be a valid JSON Schema object (with `type`, `properties`,
38
+ * etc.) — the Vercel AI SDK wraps it via `jsonSchema()`.
39
+ */
40
+ const ToolSchemaSchema = z.object({
41
+ name: z.string().min(1),
42
+ description: z.string().min(1),
43
+ parameters: z.record(z.string(), z.unknown())
44
+ });
45
+ /** Empty Zod object schema used as default when tools have no parameters. */
46
+ const EMPTY_PARAMS = z.object({});
47
+ /**
48
+ * Convert agent tool definitions to JSON Schema format for wire transport.
49
+ *
50
+ * Transforms the Zod-based `parameters` of each tool into a plain JSON Schema
51
+ * object suitable for structured clone / JSON serialization.
52
+ */
53
+ function agentToolsToSchemas(tools) {
54
+ return Object.entries(tools).map(([name, def]) => ({
55
+ name,
56
+ description: def.description,
57
+ parameters: z.toJSONSchema(def.parameters ?? EMPTY_PARAMS)
58
+ }));
59
+ }
60
+ //#endregion
61
+ export { toAgentConfig as a, agentToolsToSchemas as i, EMPTY_PARAMS as n, ToolSchemaSchema as r, AgentConfigSchema as t };
@@ -89,27 +89,3 @@ export declare class MockWebSocket extends EventTarget {
89
89
  */
90
90
  sentJson(): Record<string, unknown>[];
91
91
  }
92
- /**
93
- * Replace `globalThis.WebSocket` with {@link MockWebSocket} for testing.
94
- *
95
- * Returns a handle that tracks all created mock sockets and can restore the
96
- * original `WebSocket` constructor. Supports the `using` declaration via
97
- * `Symbol.dispose` for automatic cleanup.
98
- *
99
- * @returns An object with `created` array, `lastWs` getter, `restore()`, and `[Symbol.dispose]()`.
100
- *
101
- * @example
102
- * ```ts
103
- * using mock = installMockWebSocket();
104
- * const session = new Session("wss://example.com");
105
- * const ws = mock.lastWs!;
106
- * ws.simulateMessage(JSON.stringify({ type: "ready" }));
107
- * // mock automatically restores WebSocket when disposed
108
- * ```
109
- */
110
- export declare function installMockWebSocket(): {
111
- restore: () => void;
112
- created: MockWebSocket[];
113
- get lastWs(): MockWebSocket | null;
114
- [Symbol.dispose]: () => void;
115
- };
@@ -6,7 +6,6 @@
6
6
  export * from "./builtin-tools.ts";
7
7
  export * from "./runtime.ts";
8
8
  export * from "./runtime-config.ts";
9
- export * from "./s2s.ts";
10
9
  export * from "./server.ts";
11
10
  export * from "./session.ts";
12
11
  export * from "./session-ctx.ts";
@@ -1,7 +1,8 @@
1
1
  import { a as DEFAULT_SHUTDOWN_TIMEOUT_MS, c as FETCH_TIMEOUT_MS, d as MAX_PAGE_CHARS, f as MAX_TOOL_RESULT_CHARS, g as TOOL_EXECUTION_TIMEOUT_MS, h as RUN_CODE_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-VTFoymJ-.js";
2
+ import { r as DEFAULT_SYSTEM_PROMPT } from "../types-Cfx_4QDK.js";
2
3
  import { i as toolError, n as errorDetail, r as errorMessage, t as parseWsUpgradeParams } from "../ws-upgrade-BeOQ7fXL.js";
3
4
  import { ClientMessageSchema, buildReadyConfig, lenientParse } from "../sdk/protocol.js";
4
- import { a as agentToolsToSchemas, o as toAgentConfig, r as EMPTY_PARAMS, t as buildSystemPrompt } from "../system-prompt-nik_iavo.js";
5
+ import { a as toAgentConfig, i as agentToolsToSchemas, n as EMPTY_PARAMS } from "../_internal-types-CoDTiBd1.js";
5
6
  import { z } from "zod";
6
7
  import { convert } from "html-to-text";
7
8
  import vm from "node:vm";
@@ -384,6 +385,37 @@ const DEFAULT_S2S_CONFIG = {
384
385
  outputSampleRate: DEFAULT_TTS_SAMPLE_RATE
385
386
  };
386
387
  //#endregion
388
+ //#region sdk/system-prompt.ts
389
+ function getFormattedDate() {
390
+ return (/* @__PURE__ */ new Date()).toLocaleDateString("en-US", {
391
+ weekday: "long",
392
+ year: "numeric",
393
+ month: "long",
394
+ day: "numeric"
395
+ });
396
+ }
397
+ 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";
398
+ /**
399
+ * Build the system prompt sent to the LLM from the agent configuration.
400
+ *
401
+ * Assembles the default system prompt, today's date, agent-specific instructions,
402
+ * and optional sections for tool usage preamble and voice output rules.
403
+ *
404
+ * @param config - The serializable agent configuration (name, systemPrompt, etc.).
405
+ * @param opts.hasTools - When `true`, appends a preamble instructing the LLM to
406
+ * speak a brief phrase before each tool call to fill silence.
407
+ * @param opts.voice - When `true`, appends strict voice-specific output rules
408
+ * (no markdown, no bullet points, conversational tone, concise responses).
409
+ * @returns The assembled system prompt string.
410
+ */
411
+ function buildSystemPrompt(config, opts) {
412
+ const { hasTools } = opts;
413
+ const agentInstructions = config.systemPrompt && config.systemPrompt !== DEFAULT_SYSTEM_PROMPT ? `\n\nAgent-Specific Instructions:\n${config.systemPrompt}` : "";
414
+ 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." : "";
415
+ const guidance = opts.toolGuidance && opts.toolGuidance.length > 0 ? `\n\nBuilt-in Tool Usage:\n${opts.toolGuidance.join("\n")}` : "";
416
+ return DEFAULT_SYSTEM_PROMPT + `\n\nToday's date is ${getFormattedDate()}.` + agentInstructions + toolPreamble + guidance + (opts.voice ? VOICE_RULES : "");
417
+ }
418
+ //#endregion
387
419
  //#region host/s2s.ts
388
420
  const uint8ToBase64 = (bytes) => Buffer.from(bytes).toString("base64");
389
421
  const base64ToUint8 = (base64) => new Uint8Array(Buffer.from(base64, "base64"));
@@ -976,7 +1008,10 @@ function buildToolContext(opts) {
976
1008
  return kv;
977
1009
  },
978
1010
  messages: messages ?? [],
979
- sessionId: sessionId ?? ""
1011
+ sessionId: sessionId ?? "",
1012
+ send(event, data) {
1013
+ opts.send?.(event, data);
1014
+ }
980
1015
  };
981
1016
  }
982
1017
  async function executeToolCall(name, args, options) {
@@ -1173,6 +1208,7 @@ function wireSessionSocket(ws, opts) {
1173
1208
  const client = createClientSink(ws, log);
1174
1209
  session = opts.createSession(sessionId, client);
1175
1210
  sessions.set(sessionId, session);
1211
+ opts.onSinkCreated?.(sessionId, client);
1176
1212
  ws.send(JSON.stringify({
1177
1213
  type: "config",
1178
1214
  ...opts.readyConfig,
@@ -1267,6 +1303,7 @@ function createRuntime(opts) {
1267
1303
  const { agent, env, kv = createLocalKv(), createWebSocket, logger = consoleLogger, s2sConfig = DEFAULT_S2S_CONFIG, sessionStartTimeoutMs, shutdownTimeoutMs = DEFAULT_SHUTDOWN_TIMEOUT_MS } = opts;
1268
1304
  const agentConfig = toAgentConfig(agent);
1269
1305
  const sessions = /* @__PURE__ */ new Map();
1306
+ const sinkMap = /* @__PURE__ */ new Map();
1270
1307
  const readyConfig = buildReadyConfig(s2sConfig);
1271
1308
  let executeTool;
1272
1309
  let toolSchemas;
@@ -1309,6 +1346,7 @@ function createRuntime(opts) {
1309
1346
  executeTool = async (name, args, sessionId, messages) => {
1310
1347
  const tool = allTools[name];
1311
1348
  if (!tool) return toolError(`Unknown tool: ${name}`);
1349
+ const sink = sinkMap.get(sessionId ?? "");
1312
1350
  return executeToolCall(name, args, {
1313
1351
  tool,
1314
1352
  env: frozenEnv,
@@ -1316,11 +1354,17 @@ function createRuntime(opts) {
1316
1354
  sessionId: sessionId ?? "",
1317
1355
  kv,
1318
1356
  messages,
1319
- logger
1357
+ logger,
1358
+ send: sink ? (event, data) => sink.event({
1359
+ type: "custom_event",
1360
+ event,
1361
+ data
1362
+ }) : void 0
1320
1363
  });
1321
1364
  };
1322
1365
  }
1323
1366
  function createSession(sessionOpts) {
1367
+ sinkMap.set(sessionOpts.id, sessionOpts.client);
1324
1368
  const apiKey = env.ASSEMBLYAI_API_KEY ?? "";
1325
1369
  return createS2sSession({
1326
1370
  id: sessionOpts.id,
@@ -1340,6 +1384,7 @@ function createRuntime(opts) {
1340
1384
  }
1341
1385
  function startSession(ws, startOpts) {
1342
1386
  const resumeFrom = startOpts?.resumeFrom;
1387
+ const userOnSessionEnd = startOpts?.onSessionEnd;
1343
1388
  wireSessionSocket(ws, {
1344
1389
  sessions,
1345
1390
  createSession: (sid, client) => createSession({
@@ -1354,7 +1399,11 @@ function createRuntime(opts) {
1354
1399
  ...startOpts?.logContext ? { logContext: startOpts.logContext } : {},
1355
1400
  ...startOpts?.onOpen ? { onOpen: startOpts.onOpen } : {},
1356
1401
  ...startOpts?.onClose ? { onClose: startOpts.onClose } : {},
1357
- ...startOpts?.onSessionEnd ? { onSessionEnd: startOpts.onSessionEnd } : {},
1402
+ ...startOpts?.onSinkCreated ? { onSinkCreated: startOpts.onSinkCreated } : {},
1403
+ onSessionEnd: (sid) => {
1404
+ sinkMap.delete(sid);
1405
+ userOnSessionEnd?.(sid);
1406
+ },
1358
1407
  ...sessionStartTimeoutMs !== void 0 ? { sessionStartTimeoutMs } : {},
1359
1408
  ...resumeFrom ? { resumeFrom } : {}
1360
1409
  });
@@ -1368,6 +1417,7 @@ function createRuntime(opts) {
1368
1417
  logger.warn(`Shutdown timeout (${shutdownTimeoutMs}ms) exceeded — force-closing ${sessions.size} remaining session(s)`);
1369
1418
  }
1370
1419
  sessions.clear();
1420
+ sinkMap.clear();
1371
1421
  }
1372
1422
  return {
1373
1423
  executeTool,
@@ -1515,4 +1565,4 @@ function createServer(options) {
1515
1565
  };
1516
1566
  }
1517
1567
  //#endregion
1518
- export { DEFAULT_S2S_CONFIG, _internals, buildCtx, connectS2s, consoleLogger, createRuntime, createS2sSession, createServer, createUnstorageKv, defaultCreateS2sWebSocket, executeInIsolate, executeToolCall, jsonLogger, resolveAllBuiltins, wireSessionSocket };
1568
+ export { DEFAULT_S2S_CONFIG, _internals, buildCtx, consoleLogger, createRuntime, createS2sSession, createServer, createUnstorageKv, executeInIsolate, executeToolCall, jsonLogger, resolveAllBuiltins, wireSessionSocket };
@@ -24,6 +24,8 @@ export type SessionStartOptions = {
24
24
  onClose?: () => void;
25
25
  /** Called with session ID after session cleanup, for guest state cleanup. */
26
26
  onSessionEnd?: (sessionId: string) => void;
27
+ /** Called with session ID and client sink after session setup. Used by sandbox to route custom events. */
28
+ onSinkCreated?: (sessionId: string, sink: ClientSink) => void;
27
29
  };
28
30
  /**
29
31
  * Common interface for agent runtimes.
@@ -16,5 +16,6 @@ export type ExecuteToolCallOptions = {
16
16
  kv?: Kv | undefined;
17
17
  messages?: readonly Message[] | undefined;
18
18
  logger?: Logger | undefined;
19
+ send?: ((event: string, data: unknown) => void) | undefined;
19
20
  };
20
21
  export declare function executeToolCall(name: string, args: Readonly<Record<string, unknown>>, options: ExecuteToolCallOptions): Promise<string>;
@@ -38,6 +38,8 @@ export type WsSessionOptions = {
38
38
  onClose?: () => void;
39
39
  /** Callback invoked with the session ID after session cleanup. */
40
40
  onSessionEnd?: (sessionId: string) => void;
41
+ /** Callback invoked with the session ID and client sink after session setup. */
42
+ onSinkCreated?: (sessionId: string, sink: ClientSink) => void;
41
43
  /** Logger instance. Defaults to console. */
42
44
  logger?: Logger;
43
45
  /** Timeout in ms for session.start(). Defaults to 10 000 (10s). */
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  * Types, KV interface, utils, and constants used across
5
5
  * aai-cli, aai-server, and aai-ui.
6
6
  */
7
+ export * from "./sdk/allowed-hosts.ts";
7
8
  export * from "./sdk/constants.ts";
8
9
  export * from "./sdk/define.ts";
9
10
  export * from "./sdk/kv.ts";
package/dist/index.js CHANGED
@@ -1,6 +1,95 @@
1
1
  import { _ as WS_OPEN, a as DEFAULT_SHUTDOWN_TIMEOUT_MS, c as FETCH_TIMEOUT_MS, d as MAX_PAGE_CHARS, f as MAX_TOOL_RESULT_CHARS, g as TOOL_EXECUTION_TIMEOUT_MS, h as RUN_CODE_TIMEOUT_MS, i as DEFAULT_SESSION_START_TIMEOUT_MS, l as MAX_HTML_BYTES, m as MAX_WS_PAYLOAD_BYTES, n as DEFAULT_IDLE_TIMEOUT_MS, o as DEFAULT_STT_SAMPLE_RATE, p as MAX_VALUE_SIZE, r as DEFAULT_MAX_HISTORY, s as DEFAULT_TTS_SAMPLE_RATE, t as AGENT_CSP, u as MAX_MESSAGE_BUFFER_SIZE } from "./constants-VTFoymJ-.js";
2
2
  import { i as ToolChoiceSchema, n as DEFAULT_GREETING, r as DEFAULT_SYSTEM_PROMPT, t as BuiltinToolSchema } from "./types-Cfx_4QDK.js";
3
3
  import { i as toolError, n as errorDetail, r as errorMessage, t as parseWsUpgradeParams } from "./ws-upgrade-BeOQ7fXL.js";
4
+ //#region sdk/allowed-hosts.ts
5
+ /**
6
+ * Allowlist matching for outbound host validation.
7
+ *
8
+ * Used at deploy time (manifest validation) and at runtime (SSRF enforcement)
9
+ * to restrict which external hosts an agent is permitted to contact.
10
+ *
11
+ * Lives in sdk/ because it has zero Node.js dependencies and can run in any
12
+ * environment (browser, Deno, Node.js sandboxes).
13
+ */
14
+ /** Private/special-use TLDs that must never appear in allowedHosts patterns. */
15
+ const BLOCKED_TLDS = [
16
+ "local",
17
+ "internal",
18
+ "localhost"
19
+ ];
20
+ /**
21
+ * Regex that matches an IPv4 address (four decimal octets separated by dots).
22
+ * Anchored so partial matches like "192.168.1.1.example.com" don't trigger it.
23
+ */
24
+ const IPV4_RE = /^(\d{1,3}\.){3}\d{1,3}$/;
25
+ function fail(reason) {
26
+ return {
27
+ valid: false,
28
+ reason
29
+ };
30
+ }
31
+ function checkStructural(pattern) {
32
+ if (pattern === "") return fail("Pattern must not be empty.");
33
+ if (pattern.includes("://")) return fail("Pattern must not include a protocol (e.g. remove 'https://').");
34
+ if (pattern.includes("/")) return fail("Pattern must not include a path component (remove '/').");
35
+ if (pattern.includes("?")) return fail("Pattern must not include a query string (remove '?').");
36
+ if (pattern.startsWith("[") || pattern.includes("::")) return fail("IP address literals are not allowed in allowedHosts patterns.");
37
+ if (pattern.includes(":")) return fail("Pattern must not include a port number (e.g. remove ':8080').");
38
+ return null;
39
+ }
40
+ function checkWildcard(pattern) {
41
+ if (!pattern.includes("*")) return null;
42
+ if (pattern === "*" || pattern === "**") return fail("Bare wildcard '*' is not allowed. Use '*.example.com' to allow all subdomains.");
43
+ if (pattern.indexOf("*") !== 0 || pattern[1] !== ".") return fail("Wildcard '*' may only appear as the leading segment (e.g. '*.example.com').");
44
+ if (pattern.lastIndexOf("*") !== 0) return fail("Only a single leading wildcard segment is supported.");
45
+ return null;
46
+ }
47
+ function checkHostPart(hostPart) {
48
+ if (IPV4_RE.test(hostPart)) return fail("IP address literals are not allowed in allowedHosts patterns.");
49
+ const tld = hostPart.split(".").at(-1)?.toLowerCase() ?? "";
50
+ if (BLOCKED_TLDS.includes(tld)) return fail(`Patterns ending in '.${tld}' are not allowed (private/special-use TLD).`);
51
+ return null;
52
+ }
53
+ /**
54
+ * Validate a single `allowedHosts` pattern at deploy time.
55
+ *
56
+ * Returns `{ valid: true }` for acceptable patterns or
57
+ * `{ valid: false; reason: string }` with a human-readable rejection reason.
58
+ */
59
+ function validateAllowedHostPattern(pattern) {
60
+ const structural = checkStructural(pattern);
61
+ if (structural !== null) return structural;
62
+ const wildcard = checkWildcard(pattern);
63
+ if (wildcard !== null) return wildcard;
64
+ const hostCheck = checkHostPart(pattern.startsWith("*.") ? pattern.slice(2) : pattern);
65
+ if (hostCheck !== null) return hostCheck;
66
+ return { valid: true };
67
+ }
68
+ /**
69
+ * Test whether `hostname` matches any pattern in `patterns`.
70
+ *
71
+ * - Exact match is case-insensitive; trailing dots on the hostname are stripped.
72
+ * - Wildcard pattern `*.example.com` matches any hostname ending with
73
+ * `.example.com` (one or more labels), but does NOT match `example.com` itself.
74
+ * - A port suffix on `hostname` (e.g. `api.example.com:8080`) is stripped before
75
+ * matching.
76
+ * - Returns `false` when `patterns` is empty.
77
+ */
78
+ function matchesAllowedHost(hostname, patterns) {
79
+ if (patterns.length === 0) return false;
80
+ const portIndex = hostname.lastIndexOf(":");
81
+ let host = portIndex !== -1 && !hostname.includes("[") ? hostname.slice(0, portIndex) : hostname;
82
+ host = host.toLowerCase().replace(/\.$/, "");
83
+ for (const pattern of patterns) {
84
+ const p = pattern.toLowerCase();
85
+ if (p.startsWith("*.")) {
86
+ const suffix = p.slice(1);
87
+ if (host.endsWith(suffix) && host.length > suffix.length) return true;
88
+ } else if (host === p) return true;
89
+ }
90
+ return false;
91
+ }
92
+ //#endregion
4
93
  //#region sdk/define.ts
5
94
  /**
6
95
  * Define a tool with typed parameters and execute function.
@@ -60,4 +149,4 @@ function agent(def) {
60
149
  };
61
150
  }
62
151
  //#endregion
63
- export { AGENT_CSP, BuiltinToolSchema, DEFAULT_GREETING, DEFAULT_IDLE_TIMEOUT_MS, DEFAULT_MAX_HISTORY, DEFAULT_SESSION_START_TIMEOUT_MS, DEFAULT_SHUTDOWN_TIMEOUT_MS, DEFAULT_STT_SAMPLE_RATE, DEFAULT_SYSTEM_PROMPT, DEFAULT_TTS_SAMPLE_RATE, FETCH_TIMEOUT_MS, MAX_HTML_BYTES, MAX_MESSAGE_BUFFER_SIZE, MAX_PAGE_CHARS, MAX_TOOL_RESULT_CHARS, MAX_VALUE_SIZE, MAX_WS_PAYLOAD_BYTES, RUN_CODE_TIMEOUT_MS, TOOL_EXECUTION_TIMEOUT_MS, ToolChoiceSchema, WS_OPEN, agent, errorDetail, errorMessage, parseWsUpgradeParams, tool, toolError };
152
+ export { AGENT_CSP, BuiltinToolSchema, DEFAULT_GREETING, DEFAULT_IDLE_TIMEOUT_MS, DEFAULT_MAX_HISTORY, DEFAULT_SESSION_START_TIMEOUT_MS, DEFAULT_SHUTDOWN_TIMEOUT_MS, DEFAULT_STT_SAMPLE_RATE, DEFAULT_SYSTEM_PROMPT, DEFAULT_TTS_SAMPLE_RATE, FETCH_TIMEOUT_MS, MAX_HTML_BYTES, MAX_MESSAGE_BUFFER_SIZE, MAX_PAGE_CHARS, MAX_TOOL_RESULT_CHARS, MAX_VALUE_SIZE, MAX_WS_PAYLOAD_BYTES, RUN_CODE_TIMEOUT_MS, TOOL_EXECUTION_TIMEOUT_MS, ToolChoiceSchema, WS_OPEN, agent, errorDetail, errorMessage, matchesAllowedHost, parseWsUpgradeParams, tool, toolError, validateAllowedHostPattern };
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Allowlist matching for outbound host validation.
3
+ *
4
+ * Used at deploy time (manifest validation) and at runtime (SSRF enforcement)
5
+ * to restrict which external hosts an agent is permitted to contact.
6
+ *
7
+ * Lives in sdk/ because it has zero Node.js dependencies and can run in any
8
+ * environment (browser, Deno, Node.js sandboxes).
9
+ */
10
+ type ValidationResult = {
11
+ valid: true;
12
+ } | {
13
+ valid: false;
14
+ reason: string;
15
+ };
16
+ /**
17
+ * Validate a single `allowedHosts` pattern at deploy time.
18
+ *
19
+ * Returns `{ valid: true }` for acceptable patterns or
20
+ * `{ valid: false; reason: string }` with a human-readable rejection reason.
21
+ */
22
+ export declare function validateAllowedHostPattern(pattern: string): ValidationResult;
23
+ /**
24
+ * Test whether `hostname` matches any pattern in `patterns`.
25
+ *
26
+ * - Exact match is case-insensitive; trailing dots on the hostname are stripped.
27
+ * - Wildcard pattern `*.example.com` matches any hostname ending with
28
+ * `.example.com` (one or more labels), but does NOT match `example.com` itself.
29
+ * - A port suffix on `hostname` (e.g. `api.example.com:8080`) is stripped before
30
+ * matching.
31
+ * - Returns `false` when `patterns` is empty.
32
+ */
33
+ export declare function matchesAllowedHost(hostname: string, patterns: string[]): boolean;
34
+ export {};
@@ -1,8 +1,6 @@
1
1
  /**
2
- * Manifest barrel — agent manifest parsing and tool schema conversion.
2
+ * Manifest barrel — agent config conversion and tool schema handling.
3
3
  *
4
- * Used by aai-cli (scanner, bundler) and aai-server (tests).
4
+ * Used by aai-cli (bundler) and aai-server (rpc-schemas).
5
5
  */
6
- export * from "./_internal-types.ts";
7
- export * from "./manifest.ts";
8
- export * from "./system-prompt.ts";
6
+ export { type AgentConfig, AgentConfigSchema, type AgentConfigSource, agentToolsToSchemas, EMPTY_PARAMS, type ExecuteTool, type ToolSchema, ToolSchemaSchema, toAgentConfig, } from "./_internal-types.ts";
@@ -1,52 +1,2 @@
1
- import { r as DEFAULT_SYSTEM_PROMPT, t as BuiltinToolSchema } from "../types-Cfx_4QDK.js";
2
- import { a as agentToolsToSchemas, i as ToolSchemaSchema, n as AgentConfigSchema, o as toAgentConfig, r as EMPTY_PARAMS, t as buildSystemPrompt } from "../system-prompt-nik_iavo.js";
3
- import { z } from "zod";
4
- //#region sdk/manifest.ts
5
- /**
6
- * Canonical manifest format for directory-based agents.
7
- *
8
- * Flows from build → host → sdk. Validated via Zod at the boundary,
9
- * then used as a plain typed object throughout the runtime.
10
- */
11
- const ToolManifestSchema = z.object({
12
- description: z.string(),
13
- parameters: z.record(z.string(), z.unknown()).optional()
14
- });
15
- const ManifestSchema = z.object({
16
- name: z.string().min(1),
17
- systemPrompt: z.string().optional(),
18
- greeting: z.string().optional(),
19
- sttPrompt: z.string().optional(),
20
- builtinTools: z.array(BuiltinToolSchema).optional(),
21
- maxSteps: z.number().int().positive().optional(),
22
- toolChoice: z.enum(["auto", "required"]).optional(),
23
- idleTimeoutMs: z.number().int().positive().optional(),
24
- theme: z.record(z.string(), z.string()).optional(),
25
- tools: z.record(z.string(), ToolManifestSchema).optional()
26
- });
27
- /**
28
- * Parse and normalize a raw agent manifest, applying defaults for all
29
- * optional fields. Input is typically the JSON from a bundled agent.ts.
30
- *
31
- * Key defaults:
32
- * - `maxSteps`: 5 — prevents runaway tool-call loops in a single reply
33
- * - `toolChoice`: "auto" — LLM decides when to use tools vs respond directly
34
- * - `builtinTools`: [] — no built-in tools unless explicitly opted in
35
- */
36
- function parseManifest(input) {
37
- const parsed = ManifestSchema.parse(input);
38
- return {
39
- name: parsed.name,
40
- systemPrompt: parsed.systemPrompt ?? DEFAULT_SYSTEM_PROMPT,
41
- greeting: parsed.greeting ?? "Hey there. I'm a voice assistant. What can I help you with?",
42
- sttPrompt: parsed.sttPrompt,
43
- builtinTools: parsed.builtinTools ?? [],
44
- maxSteps: parsed.maxSteps ?? 5,
45
- toolChoice: parsed.toolChoice ?? "auto",
46
- idleTimeoutMs: parsed.idleTimeoutMs,
47
- theme: parsed.theme,
48
- tools: parsed.tools ?? {}
49
- };
50
- }
51
- //#endregion
52
- export { AgentConfigSchema, EMPTY_PARAMS, ToolSchemaSchema, agentToolsToSchemas, buildSystemPrompt, parseManifest, toAgentConfig };
1
+ import { a as toAgentConfig, i as agentToolsToSchemas, n as EMPTY_PARAMS, r as ToolSchemaSchema, t as AgentConfigSchema } from "../_internal-types-CoDTiBd1.js";
2
+ export { AgentConfigSchema, EMPTY_PARAMS, ToolSchemaSchema, agentToolsToSchemas, toAgentConfig };
@@ -37,6 +37,8 @@ export type Manifest = {
37
37
  theme?: Record<string, string> | undefined;
38
38
  /** Custom tool definitions keyed by tool name. */
39
39
  tools: Record<string, ToolManifest>;
40
+ /** Hostnames the agent is allowed to fetch. Empty = no fetch access. */
41
+ allowedHosts: string[];
40
42
  };
41
43
  /**
42
44
  * Parse and normalize a raw agent manifest, applying defaults for all
@@ -4,23 +4,6 @@
4
4
  * Note: this module is for internal use only and should not be used directly.
5
5
  */
6
6
  import { z } from "zod";
7
- /**
8
- * Audio codec identifier used in the wire protocol.
9
- *
10
- * All audio frames are 16-bit signed PCM, little-endian, mono.
11
- */
12
- export declare const AUDIO_FORMAT = "pcm16";
13
- /**
14
- * Minimal envelope schema for two-phase message parsing.
15
- *
16
- * When a strict schema (ServerMessageSchema / ClientMessageSchema) rejects a
17
- * message, this schema determines whether the message is a valid but
18
- * *unrecognised* type (safe to ignore during rolling upgrades) or genuinely
19
- * malformed (should be warned about).
20
- */
21
- export declare const MessageEnvelopeSchema: z.ZodObject<{
22
- type: z.ZodString;
23
- }, z.core.$loose>;
24
7
  /**
25
8
  * Two-phase message parse: tries the strict schema first, then falls back to
26
9
  * the envelope to distinguish unknown-but-valid types (safe to ignore during
@@ -77,6 +60,7 @@ export type KvRequest = z.infer<typeof KvRequestSchema>;
77
60
  * @public
78
61
  */
79
62
  export declare const SessionErrorCodeSchema: z.ZodEnum<{
63
+ internal: "internal";
80
64
  tool: "tool";
81
65
  connection: "connection";
82
66
  stt: "stt";
@@ -84,7 +68,6 @@ export declare const SessionErrorCodeSchema: z.ZodEnum<{
84
68
  tts: "tts";
85
69
  protocol: "protocol";
86
70
  audio: "audio";
87
- internal: "internal";
88
71
  }>;
89
72
  /**
90
73
  * Error codes for categorizing session errors on the wire.
@@ -124,6 +107,7 @@ export declare const ClientEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
124
107
  }, z.core.$strip>, z.ZodObject<{
125
108
  type: z.ZodLiteral<"error">;
126
109
  code: z.ZodEnum<{
110
+ internal: "internal";
127
111
  tool: "tool";
128
112
  connection: "connection";
129
113
  stt: "stt";
@@ -131,9 +115,12 @@ export declare const ClientEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
131
115
  tts: "tts";
132
116
  protocol: "protocol";
133
117
  audio: "audio";
134
- internal: "internal";
135
118
  }>;
136
119
  message: z.ZodString;
120
+ }, z.core.$strip>, z.ZodObject<{
121
+ type: z.ZodLiteral<"custom_event">;
122
+ event: z.ZodString;
123
+ data: z.ZodUnknown;
137
124
  }, z.core.$strip>], "type">;
138
125
  /** Discriminated union of all server→client session events. */
139
126
  export type ClientEvent = z.infer<typeof ClientEventSchema>;
@@ -152,8 +139,6 @@ export interface ClientSink {
152
139
  /** Signal that TTS audio is complete. */
153
140
  playAudioDone(): void;
154
141
  }
155
- /** Supported audio formats for the wire protocol. */
156
- export type AudioFormatId = "pcm16";
157
142
  /** Zod schema for {@link ReadyConfig}. */
158
143
  export declare const ReadyConfigSchema: z.ZodObject<{
159
144
  audioFormat: z.ZodEnum<{
@@ -204,6 +189,7 @@ export declare const ServerMessageSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
204
189
  }, z.core.$strip>, z.ZodObject<{
205
190
  type: z.ZodLiteral<"error">;
206
191
  code: z.ZodEnum<{
192
+ internal: "internal";
207
193
  tool: "tool";
208
194
  connection: "connection";
209
195
  stt: "stt";
@@ -211,9 +197,12 @@ export declare const ServerMessageSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
211
197
  tts: "tts";
212
198
  protocol: "protocol";
213
199
  audio: "audio";
214
- internal: "internal";
215
200
  }>;
216
201
  message: z.ZodString;
202
+ }, z.core.$strip>, z.ZodObject<{
203
+ type: z.ZodLiteral<"custom_event">;
204
+ event: z.ZodString;
205
+ data: z.ZodUnknown;
217
206
  }, z.core.$strip>], "type">;
218
207
  /** Server→client text messages (binary frames carry raw PCM16 audio). */
219
208
  export type ServerMessage = z.infer<typeof ServerMessageSchema>;
@@ -241,9 +230,3 @@ export declare function buildReadyConfig(s2sConfig: {
241
230
  inputSampleRate: number;
242
231
  outputSampleRate: number;
243
232
  }): ReadyConfig;
244
- /** Zod schema for {@link TurnConfig}. */
245
- export declare const TurnConfigSchema: z.ZodObject<{
246
- maxSteps: z.ZodOptional<z.ZodNumber>;
247
- }, z.core.$strip>;
248
- /** Combined turn configuration resolved from the worker before a turn starts. */
249
- export type TurnConfig = z.infer<typeof TurnConfigSchema>;