@alexkroman1/aai 1.2.3 → 1.3.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 (65) hide show
  1. package/.turbo/turbo-build.log +14 -12
  2. package/CHANGELOG.md +14 -0
  3. package/dist/host/_pipeline-test-fakes.d.ts +107 -0
  4. package/dist/host/pipeline-session-ctx.d.ts +24 -0
  5. package/dist/host/pipeline-session.d.ts +48 -0
  6. package/dist/host/providers/llm.d.ts +2 -0
  7. package/dist/host/providers/stt/assemblyai.d.ts +31 -0
  8. package/dist/host/providers/stt-barrel.d.ts +8 -0
  9. package/dist/host/providers/stt-barrel.js +92 -0
  10. package/dist/host/providers/stt.d.ts +2 -0
  11. package/dist/host/providers/tts/cartesia.d.ts +39 -0
  12. package/dist/host/providers/tts-barrel.d.ts +8 -0
  13. package/dist/host/providers/tts-barrel.js +182 -0
  14. package/dist/host/providers/tts.d.ts +2 -0
  15. package/dist/host/runtime-barrel.js +498 -80
  16. package/dist/host/runtime.d.ts +17 -0
  17. package/dist/host/s2s.d.ts +5 -0
  18. package/dist/host/session-ctx.d.ts +22 -4
  19. package/dist/host/to-vercel-tools.d.ts +44 -0
  20. package/dist/index.js +5 -0
  21. package/dist/sdk/_internal-types.d.ts +15 -1
  22. package/dist/sdk/define.d.ts +21 -0
  23. package/dist/sdk/manifest.d.ts +22 -0
  24. package/dist/sdk/protocol.d.ts +3 -3
  25. package/dist/sdk/providers.d.ts +70 -0
  26. package/dist/sdk/types.d.ts +16 -0
  27. package/exports-no-dev-deps.test.ts +39 -14
  28. package/host/_pipeline-test-fakes.ts +323 -0
  29. package/host/_test-utils.ts +1 -0
  30. package/host/integration/fixtures/README.md +49 -0
  31. package/host/integration/pipeline-reference.integration.test.ts +124 -0
  32. package/host/pipeline-session-ctx.test.ts +31 -0
  33. package/host/pipeline-session-ctx.ts +36 -0
  34. package/host/pipeline-session.test.ts +337 -0
  35. package/host/pipeline-session.ts +405 -0
  36. package/host/providers/llm.ts +3 -0
  37. package/host/providers/providers.test-d.ts +31 -0
  38. package/host/providers/stt/assemblyai.test.ts +100 -0
  39. package/host/providers/stt/assemblyai.ts +154 -0
  40. package/host/providers/stt/fixtures/assemblyai/basic-turn.json +30 -0
  41. package/host/providers/stt-barrel.ts +13 -0
  42. package/host/providers/stt.ts +3 -0
  43. package/host/providers/tts/cartesia.test.ts +210 -0
  44. package/host/providers/tts/cartesia.ts +251 -0
  45. package/host/providers/tts-barrel.ts +13 -0
  46. package/host/providers/tts.ts +3 -0
  47. package/host/runtime.test.ts +81 -1
  48. package/host/runtime.ts +61 -0
  49. package/host/s2s.test.ts +19 -0
  50. package/host/s2s.ts +10 -0
  51. package/host/session-ctx.ts +35 -8
  52. package/host/to-vercel-tools.test.ts +153 -0
  53. package/host/to-vercel-tools.ts +70 -0
  54. package/package.json +15 -1
  55. package/sdk/__snapshots__/exports.test.ts.snap +1 -0
  56. package/sdk/_internal-types.ts +16 -0
  57. package/sdk/define.test-d.ts +21 -0
  58. package/sdk/define.test.ts +33 -0
  59. package/sdk/define.ts +21 -0
  60. package/sdk/manifest.test-d.ts +14 -0
  61. package/sdk/manifest.test.ts +51 -0
  62. package/sdk/manifest.ts +39 -0
  63. package/sdk/providers.ts +90 -0
  64. package/sdk/types.ts +16 -0
  65. package/vitest.config.ts +1 -0
@@ -12,11 +12,18 @@ describe("parseManifest", () => {
12
12
  name: "Simple Agent",
13
13
  systemPrompt: expect.any(String),
14
14
  greeting: expect.any(String),
15
+ sttPrompt: undefined,
15
16
  maxSteps: 5,
16
17
  toolChoice: "auto",
18
+ idleTimeoutMs: undefined,
19
+ theme: undefined,
17
20
  builtinTools: [],
18
21
  allowedHosts: [],
19
22
  tools: {},
23
+ stt: undefined,
24
+ llm: undefined,
25
+ tts: undefined,
26
+ mode: "s2s",
20
27
  });
21
28
  });
22
29
 
@@ -155,3 +162,47 @@ describe("manifest type contracts", () => {
155
162
  expectTypeOf(result.allowedHosts).toEqualTypeOf<string[]>();
156
163
  });
157
164
  });
165
+
166
+ describe("parseManifest — mode classification", () => {
167
+ const stubStt = { name: "stub-stt", open: async () => ({}) };
168
+ const stubTts = { name: "stub-tts", open: async () => ({}) };
169
+ const stubLlm = { modelId: "stub-llm" };
170
+
171
+ test("no stt/llm/tts ⇒ mode: 's2s'", () => {
172
+ const parsed = parseManifest({
173
+ name: "hello",
174
+ systemPrompt: "hi",
175
+ });
176
+ expect(parsed.mode).toBe("s2s");
177
+ });
178
+
179
+ test("all three of stt/llm/tts set ⇒ mode: 'pipeline'", () => {
180
+ const parsed = parseManifest({
181
+ name: "hello",
182
+ systemPrompt: "hi",
183
+ stt: stubStt,
184
+ llm: stubLlm,
185
+ tts: stubTts,
186
+ } as never);
187
+ expect(parsed.mode).toBe("pipeline");
188
+ });
189
+
190
+ test("only stt set ⇒ throws", () => {
191
+ expect(() =>
192
+ parseManifest({
193
+ name: "hello",
194
+ stt: stubStt,
195
+ } as never),
196
+ ).toThrow(/stt, llm, and tts must be set together/);
197
+ });
198
+
199
+ test("stt + tts without llm ⇒ throws", () => {
200
+ expect(() =>
201
+ parseManifest({
202
+ name: "hello",
203
+ stt: stubStt,
204
+ tts: stubTts,
205
+ } as never),
206
+ ).toThrow(/stt, llm, and tts must be set together/);
207
+ });
208
+ });
package/sdk/manifest.ts CHANGED
@@ -8,6 +8,7 @@
8
8
 
9
9
  import { z } from "zod";
10
10
  import { validateAllowedHostPattern } from "./allowed-hosts.ts";
11
+ import type { LlmProvider, SttProvider, TtsProvider } from "./providers.ts";
11
12
  import { BuiltinToolSchema, DEFAULT_GREETING, DEFAULT_SYSTEM_PROMPT } from "./types.ts";
12
13
 
13
14
  /**
@@ -46,6 +47,27 @@ export type Manifest = {
46
47
  tools: Record<string, ToolManifest>;
47
48
  /** Hostnames the agent is allowed to fetch. Empty = no fetch access. */
48
49
  allowedHosts: string[];
50
+ /**
51
+ * Pluggable STT provider. Must be set together with `llm` and `tts` to
52
+ * enable pipeline mode, or all three left unset for s2s mode.
53
+ */
54
+ stt?: SttProvider | undefined;
55
+ /**
56
+ * Pluggable LLM provider (Vercel AI SDK `LanguageModel`). Must be set
57
+ * together with `stt` and `tts` to enable pipeline mode.
58
+ */
59
+ llm?: LlmProvider | undefined;
60
+ /**
61
+ * Pluggable TTS provider. Must be set together with `stt` and `llm` to
62
+ * enable pipeline mode.
63
+ */
64
+ tts?: TtsProvider | undefined;
65
+ /**
66
+ * Session mode derived from provider fields:
67
+ * - `"s2s"` (default): AssemblyAI Streaming Speech-to-Speech path (no stt/llm/tts set).
68
+ * - `"pipeline"`: pluggable STT → LLM → TTS path (stt + llm + tts all set).
69
+ */
70
+ mode: "s2s" | "pipeline";
49
71
  };
50
72
 
51
73
  const ToolManifestSchema = z.object({
@@ -92,6 +114,19 @@ const ManifestSchema = z.object({
92
114
  */
93
115
  export function parseManifest(input: unknown): Manifest {
94
116
  const parsed = ManifestSchema.parse(input);
117
+ // stt/llm/tts are runtime objects (functions/classes) that can't be
118
+ // validated by the JSON-oriented Zod schema. Pull them straight from
119
+ // the raw input and enforce all-or-nothing presence here.
120
+ const raw = (input ?? {}) as {
121
+ stt?: SttProvider;
122
+ llm?: LlmProvider;
123
+ tts?: TtsProvider;
124
+ };
125
+ const providerCount = [raw.stt, raw.llm, raw.tts].filter((x) => x != null).length;
126
+ if (providerCount !== 0 && providerCount !== 3) {
127
+ throw new Error("stt, llm, and tts must be set together");
128
+ }
129
+ const mode: "s2s" | "pipeline" = providerCount === 3 ? "pipeline" : "s2s";
95
130
  return {
96
131
  name: parsed.name,
97
132
  systemPrompt: parsed.systemPrompt ?? DEFAULT_SYSTEM_PROMPT,
@@ -104,5 +139,9 @@ export function parseManifest(input: unknown): Manifest {
104
139
  theme: parsed.theme,
105
140
  tools: parsed.tools ?? {},
106
141
  allowedHosts: parsed.allowedHosts ?? [],
142
+ stt: raw.stt,
143
+ llm: raw.llm,
144
+ tts: raw.tts,
145
+ mode,
107
146
  };
108
147
  }
@@ -0,0 +1,90 @@
1
+ // Copyright 2025 the AAI authors. MIT license.
2
+ /**
3
+ * Pluggable provider interfaces — normalized seams over streaming STT / TTS
4
+ * SDKs, plus the LLM provider type.
5
+ *
6
+ * These are zero-runtime **type** declarations with no Node.js dependencies,
7
+ * so they live in `sdk/` alongside the `Manifest` type that references them.
8
+ * Concrete adapters (e.g. AssemblyAI STT, Cartesia TTS) live under
9
+ * `host/providers/` because they depend on Node-only SDKs.
10
+ */
11
+
12
+ import type { LanguageModel } from "ai";
13
+
14
+ /** Unsubscribe callback returned by `.on()` event subscriptions. */
15
+ export type Unsubscribe = () => void;
16
+
17
+ // -------- STT --------
18
+
19
+ export interface SttError extends Error {
20
+ readonly code: "stt_connect_failed" | "stt_auth_failed" | "stt_stream_error";
21
+ }
22
+
23
+ export type SttEvents = {
24
+ /** Interim transcript; drives barge-in detection. */
25
+ partial: (text: string) => void;
26
+ /** End-of-turn final transcript; cue to run the LLM. */
27
+ final: (text: string) => void;
28
+ /** Terminal error. The session is expected to end after this fires. */
29
+ error: (err: SttError) => void;
30
+ };
31
+
32
+ export interface SttSession {
33
+ sendAudio(pcm: Int16Array): void;
34
+ on<E extends keyof SttEvents>(event: E, fn: SttEvents[E]): Unsubscribe;
35
+ close(): Promise<void>;
36
+ }
37
+
38
+ export interface SttOpenOptions {
39
+ sampleRate: number;
40
+ apiKey: string;
41
+ sttPrompt?: string | undefined;
42
+ signal: AbortSignal;
43
+ }
44
+
45
+ export interface SttProvider {
46
+ readonly name: string;
47
+ open(opts: SttOpenOptions): Promise<SttSession>;
48
+ }
49
+
50
+ // -------- TTS --------
51
+
52
+ export interface TtsError extends Error {
53
+ readonly code: "tts_connect_failed" | "tts_auth_failed" | "tts_stream_error";
54
+ }
55
+
56
+ export type TtsEvents = {
57
+ /** One PCM16 audio chunk. Orchestrator forwards to the client. */
58
+ audio: (pcm: Int16Array) => void;
59
+ /** Synthesis drained after flush() or cancel(). Emitted exactly once per turn. */
60
+ done: () => void;
61
+ /** Terminal error. The session is expected to end after this fires. */
62
+ error: (err: TtsError) => void;
63
+ };
64
+
65
+ export interface TtsSession {
66
+ /** Push text deltas from the LLM. Provider may synthesize as chunks arrive. */
67
+ sendText(text: string): void;
68
+ /** Signal "no more text this turn". Emits `done` when fully synthesized. */
69
+ flush(): void;
70
+ /** Interrupt immediately (barge-in). Emits `done` synchronously. */
71
+ cancel(): void;
72
+ on<E extends keyof TtsEvents>(event: E, fn: TtsEvents[E]): Unsubscribe;
73
+ close(): Promise<void>;
74
+ }
75
+
76
+ export interface TtsOpenOptions {
77
+ sampleRate: number;
78
+ apiKey: string;
79
+ signal: AbortSignal;
80
+ }
81
+
82
+ export interface TtsProvider {
83
+ readonly name: string;
84
+ open(opts: TtsOpenOptions): Promise<TtsSession>;
85
+ }
86
+
87
+ // -------- LLM --------
88
+
89
+ /** LLM provider — Vercel AI SDK's `LanguageModel`; no wrapping. */
90
+ export type LlmProvider = LanguageModel;
package/sdk/types.ts CHANGED
@@ -5,6 +5,7 @@
5
5
 
6
6
  import { z } from "zod";
7
7
  import type { Kv } from "./kv.ts";
8
+ import type { LlmProvider, SttProvider, TtsProvider } from "./providers.ts";
8
9
 
9
10
  /**
10
11
  * Identifier for a built-in server-side tool.
@@ -217,6 +218,21 @@ export type AgentDef<S = Record<string, unknown>> = {
217
218
  tools: Readonly<Record<string, ToolDef<z.ZodObject<z.ZodRawShape>, S>>>;
218
219
  state?: () => S;
219
220
  idleTimeoutMs?: number;
221
+ /**
222
+ * Pluggable STT provider. Set together with `llm` and `tts` to enable
223
+ * pipeline mode; all three unset means S2S mode.
224
+ */
225
+ stt?: SttProvider;
226
+ /**
227
+ * Pluggable LLM provider (Vercel AI SDK `LanguageModel`). Set together
228
+ * with `stt` and `tts` for pipeline mode.
229
+ */
230
+ llm?: LlmProvider;
231
+ /**
232
+ * Pluggable TTS provider. Set together with `stt` and `llm` for
233
+ * pipeline mode.
234
+ */
235
+ tts?: TtsProvider;
220
236
  };
221
237
 
222
238
  // ─── Zod schemas ────────────────────────────────────────────────────────────
package/vitest.config.ts CHANGED
@@ -10,6 +10,7 @@ export default defineConfig({
10
10
  "**/pentest.test.ts",
11
11
  "**/run-code-sandbox.test.ts",
12
12
  "**/integration.test.ts",
13
+ "**/*.integration.test.ts",
13
14
  "node_modules",
14
15
  "dist",
15
16
  ],