@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.
- package/.turbo/turbo-build.log +14 -12
- package/CHANGELOG.md +14 -0
- package/dist/host/_pipeline-test-fakes.d.ts +107 -0
- package/dist/host/pipeline-session-ctx.d.ts +24 -0
- package/dist/host/pipeline-session.d.ts +48 -0
- package/dist/host/providers/llm.d.ts +2 -0
- package/dist/host/providers/stt/assemblyai.d.ts +31 -0
- package/dist/host/providers/stt-barrel.d.ts +8 -0
- package/dist/host/providers/stt-barrel.js +92 -0
- package/dist/host/providers/stt.d.ts +2 -0
- package/dist/host/providers/tts/cartesia.d.ts +39 -0
- package/dist/host/providers/tts-barrel.d.ts +8 -0
- package/dist/host/providers/tts-barrel.js +182 -0
- package/dist/host/providers/tts.d.ts +2 -0
- package/dist/host/runtime-barrel.js +498 -80
- package/dist/host/runtime.d.ts +17 -0
- package/dist/host/s2s.d.ts +5 -0
- package/dist/host/session-ctx.d.ts +22 -4
- package/dist/host/to-vercel-tools.d.ts +44 -0
- package/dist/index.js +5 -0
- package/dist/sdk/_internal-types.d.ts +15 -1
- package/dist/sdk/define.d.ts +21 -0
- package/dist/sdk/manifest.d.ts +22 -0
- package/dist/sdk/protocol.d.ts +3 -3
- package/dist/sdk/providers.d.ts +70 -0
- package/dist/sdk/types.d.ts +16 -0
- package/exports-no-dev-deps.test.ts +39 -14
- package/host/_pipeline-test-fakes.ts +323 -0
- package/host/_test-utils.ts +1 -0
- package/host/integration/fixtures/README.md +49 -0
- package/host/integration/pipeline-reference.integration.test.ts +124 -0
- package/host/pipeline-session-ctx.test.ts +31 -0
- package/host/pipeline-session-ctx.ts +36 -0
- package/host/pipeline-session.test.ts +337 -0
- package/host/pipeline-session.ts +405 -0
- package/host/providers/llm.ts +3 -0
- package/host/providers/providers.test-d.ts +31 -0
- package/host/providers/stt/assemblyai.test.ts +100 -0
- package/host/providers/stt/assemblyai.ts +154 -0
- package/host/providers/stt/fixtures/assemblyai/basic-turn.json +30 -0
- package/host/providers/stt-barrel.ts +13 -0
- package/host/providers/stt.ts +3 -0
- package/host/providers/tts/cartesia.test.ts +210 -0
- package/host/providers/tts/cartesia.ts +251 -0
- package/host/providers/tts-barrel.ts +13 -0
- package/host/providers/tts.ts +3 -0
- package/host/runtime.test.ts +81 -1
- package/host/runtime.ts +61 -0
- package/host/s2s.test.ts +19 -0
- package/host/s2s.ts +10 -0
- package/host/session-ctx.ts +35 -8
- package/host/to-vercel-tools.test.ts +153 -0
- package/host/to-vercel-tools.ts +70 -0
- package/package.json +15 -1
- package/sdk/__snapshots__/exports.test.ts.snap +1 -0
- package/sdk/_internal-types.ts +16 -0
- package/sdk/define.test-d.ts +21 -0
- package/sdk/define.test.ts +33 -0
- package/sdk/define.ts +21 -0
- package/sdk/manifest.test-d.ts +14 -0
- package/sdk/manifest.test.ts +51 -0
- package/sdk/manifest.ts +39 -0
- package/sdk/providers.ts +90 -0
- package/sdk/types.ts +16 -0
- package/vitest.config.ts +1 -0
package/sdk/manifest.test.ts
CHANGED
|
@@ -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
|
}
|
package/sdk/providers.ts
ADDED
|
@@ -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 ────────────────────────────────────────────────────────────
|