@alexkroman1/aai 0.10.3 → 0.11.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/dist/_internal-types.d.ts +8 -1
- package/dist/_run-code.d.ts +16 -12
- package/dist/_runtime-conformance.d.ts +55 -0
- package/dist/_test-utils.d.ts +73 -0
- package/dist/_utils.d.ts +0 -19
- package/dist/_utils.js +28 -2
- package/dist/builtin-tools.d.ts +1 -5
- package/dist/constants-CwotjpJR.js +45 -0
- package/dist/constants.d.ts +42 -0
- package/dist/direct-executor-DAGCZOAN.js +1530 -0
- package/dist/direct-executor.d.ts +90 -31
- package/dist/hooks.d.ts +44 -0
- package/dist/hooks.js +58 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.js +2 -2
- package/dist/internal.d.ts +19 -0
- package/dist/internal.js +164 -0
- package/dist/kv.d.ts +1 -1
- package/dist/kv.js +32 -1
- package/dist/matchers.js +1 -1
- package/dist/protocol.d.ts +3 -29
- package/dist/protocol.js +140 -2
- package/dist/server.d.ts +27 -40
- package/dist/server.js +117 -145
- package/dist/session.d.ts +65 -44
- package/dist/{testing-BbitshLb.js → testing-Dmx-dudh.js} +39 -43
- package/dist/testing.d.ts +9 -14
- package/dist/testing.js +2 -2
- package/dist/types.d.ts +24 -226
- package/dist/types.js +176 -2
- package/dist/types.test-d.d.ts +7 -0
- package/dist/vite-plugin.d.ts +15 -0
- package/dist/vite-plugin.js +82 -0
- package/dist/ws-handler.d.ts +1 -2
- package/package.json +34 -95
- package/dist/_embeddings.d.ts +0 -31
- package/dist/_internal-types-IfPcaJd5.js +0 -61
- package/dist/_internal-types.js +0 -2
- package/dist/_session-ctx.d.ts +0 -73
- package/dist/_session-otel.d.ts +0 -43
- package/dist/_session-persist.d.ts +0 -30
- package/dist/_ssrf-DCp_27V4.js +0 -123
- package/dist/_ssrf.d.ts +0 -30
- package/dist/_ssrf.js +0 -2
- package/dist/_utils-DgzpOMSV.js +0 -61
- package/dist/direct-executor-B-5mq3cu.js +0 -570
- package/dist/kv-iXtikQmR.js +0 -32
- package/dist/middleware-core-BwyBIPed.js +0 -107
- package/dist/middleware-core.d.ts +0 -47
- package/dist/middleware-core.js +0 -2
- package/dist/middleware.d.ts +0 -37
- package/dist/protocol-B-H2Q4ox.js +0 -162
- package/dist/runtime-CxcwaK68.js +0 -58
- package/dist/runtime.js +0 -2
- package/dist/s2s-M7JqtgFw.js +0 -272
- package/dist/s2s.js +0 -2
- package/dist/session-BYlwcrya.js +0 -683
- package/dist/session.js +0 -2
- package/dist/telemetry-CJlaDFNc.js +0 -95
- package/dist/telemetry.d.ts +0 -49
- package/dist/telemetry.js +0 -2
- package/dist/types-D8ZBxTL_.js +0 -192
- package/dist/unstorage-kv-CDgP-frt.js +0 -64
- package/dist/unstorage-kv.js +0 -2
- package/dist/unstorage-vector-Cj5llNhg.js +0 -172
- package/dist/unstorage-vector.d.ts +0 -47
- package/dist/unstorage-vector.js +0 -2
- package/dist/vector.d.ts +0 -86
- package/dist/vector.js +0 -49
- package/dist/worker-entry-2jaiqIj0.js +0 -70
- package/dist/worker-entry.d.ts +0 -47
- package/dist/worker-entry.js +0 -2
- package/dist/ws-handler-C0Q6eSay.js +0 -207
- package/dist/ws-handler.js +0 -2
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { t as
|
|
3
|
-
import {
|
|
1
|
+
import "./types.js";
|
|
2
|
+
import { i as createUnstorageKv, t as createRuntime } from "./direct-executor-DAGCZOAN.js";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
4
|
import { createStorage } from "unstorage";
|
|
5
|
+
import "nanoevents";
|
|
6
|
+
import { vi } from "vitest";
|
|
5
7
|
//#region _mock-ws.ts
|
|
6
8
|
/**
|
|
7
9
|
* A mock WebSocket implementation for testing.
|
|
@@ -155,6 +157,28 @@ function installMockWebSocket() {
|
|
|
155
157
|
};
|
|
156
158
|
}
|
|
157
159
|
//#endregion
|
|
160
|
+
//#region _test-utils.ts
|
|
161
|
+
/** Yield to the microtask queue so pending promises settle. */
|
|
162
|
+
function flush() {
|
|
163
|
+
return new Promise((r) => queueMicrotask(r));
|
|
164
|
+
}
|
|
165
|
+
/** Create a stub Session with all methods as vi.fn() spies. */
|
|
166
|
+
function makeStubSession(overrides) {
|
|
167
|
+
return {
|
|
168
|
+
start: vi.fn(() => Promise.resolve()),
|
|
169
|
+
stop: vi.fn(() => Promise.resolve()),
|
|
170
|
+
onAudio: vi.fn(),
|
|
171
|
+
onAudioReady: vi.fn(),
|
|
172
|
+
onCancel: vi.fn(),
|
|
173
|
+
onReset: vi.fn(),
|
|
174
|
+
onHistory: vi.fn(),
|
|
175
|
+
waitForTurn: vi.fn(() => Promise.resolve()),
|
|
176
|
+
...overrides
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
vi.fn(), vi.fn(), vi.fn(), vi.fn();
|
|
180
|
+
resolve(import.meta.dirname, "__fixtures__");
|
|
181
|
+
//#endregion
|
|
158
182
|
//#region testing.ts
|
|
159
183
|
/**
|
|
160
184
|
* Testing utilities for AAI agents.
|
|
@@ -315,7 +339,6 @@ var TestHarness = class {
|
|
|
315
339
|
/** @internal */
|
|
316
340
|
_sessionId;
|
|
317
341
|
_messages = [];
|
|
318
|
-
_onStepCalls = [];
|
|
319
342
|
_onTurnCalls = [];
|
|
320
343
|
_connected = false;
|
|
321
344
|
/** @internal */
|
|
@@ -327,10 +350,6 @@ var TestHarness = class {
|
|
|
327
350
|
get messages() {
|
|
328
351
|
return this._messages;
|
|
329
352
|
}
|
|
330
|
-
/** All `onStep` hook invocations recorded so far. */
|
|
331
|
-
get steps() {
|
|
332
|
-
return this._onStepCalls;
|
|
333
|
-
}
|
|
334
353
|
/** All `onTurn` hook invocations (the text argument) recorded so far. */
|
|
335
354
|
get turns() {
|
|
336
355
|
return this._onTurnCalls;
|
|
@@ -343,7 +362,7 @@ var TestHarness = class {
|
|
|
343
362
|
async connect() {
|
|
344
363
|
if (this._connected) return;
|
|
345
364
|
this._connected = true;
|
|
346
|
-
await this._executor.
|
|
365
|
+
await this._executor.hooks.callHook("connect", this._sessionId);
|
|
347
366
|
}
|
|
348
367
|
/**
|
|
349
368
|
* Fire the `onDisconnect` lifecycle hook and clean up session state.
|
|
@@ -351,12 +370,12 @@ var TestHarness = class {
|
|
|
351
370
|
async disconnect() {
|
|
352
371
|
if (!this._connected) return;
|
|
353
372
|
this._connected = false;
|
|
354
|
-
await this._executor.
|
|
373
|
+
await this._executor.hooks.callHook("disconnect", this._sessionId);
|
|
355
374
|
}
|
|
356
375
|
/**
|
|
357
376
|
* Execute a single tool by name with the given arguments.
|
|
358
377
|
*
|
|
359
|
-
* The tool runs with full agent context (env, state, kv,
|
|
378
|
+
* The tool runs with full agent context (env, state, kv, messages).
|
|
360
379
|
* The call is **not** recorded in conversation history — use {@link turn}
|
|
361
380
|
* for that.
|
|
362
381
|
*
|
|
@@ -382,7 +401,7 @@ var TestHarness = class {
|
|
|
382
401
|
* 1. Fires `onConnect` if this is the first turn
|
|
383
402
|
* 2. Adds the user message to conversation history
|
|
384
403
|
* 3. Fires the `onTurn` hook
|
|
385
|
-
* 4. Executes each tool call in order
|
|
404
|
+
* 4. Executes each tool call in order
|
|
386
405
|
* 5. Returns a {@link TurnResult} with assertion helpers
|
|
387
406
|
*
|
|
388
407
|
* @param text - The user's spoken/typed input.
|
|
@@ -405,10 +424,9 @@ var TestHarness = class {
|
|
|
405
424
|
content: text
|
|
406
425
|
});
|
|
407
426
|
this._onTurnCalls.push(text);
|
|
408
|
-
await this._executor.
|
|
427
|
+
await this._executor.hooks.callHook("turn", this._sessionId, text);
|
|
409
428
|
const recorded = [];
|
|
410
|
-
for (
|
|
411
|
-
const tc = toolCalls[i];
|
|
429
|
+
for (const tc of toolCalls) {
|
|
412
430
|
const result = await this._executor.executeTool(tc.tool, tc.args, this._sessionId, this._messages);
|
|
413
431
|
recorded.push({
|
|
414
432
|
toolName: tc.tool,
|
|
@@ -419,16 +437,6 @@ var TestHarness = class {
|
|
|
419
437
|
role: "tool",
|
|
420
438
|
content: result
|
|
421
439
|
});
|
|
422
|
-
const step = {
|
|
423
|
-
stepNumber: i + 1,
|
|
424
|
-
toolCalls: [{
|
|
425
|
-
toolName: tc.tool,
|
|
426
|
-
args: tc.args
|
|
427
|
-
}],
|
|
428
|
-
text: ""
|
|
429
|
-
};
|
|
430
|
-
this._onStepCalls.push(step);
|
|
431
|
-
await this._executor.hookInvoker.onStep(this._sessionId, step);
|
|
432
440
|
}
|
|
433
441
|
return new TurnResult(text, recorded);
|
|
434
442
|
}
|
|
@@ -457,25 +465,14 @@ var TestHarness = class {
|
|
|
457
465
|
/**
|
|
458
466
|
* Reset conversation state: clears messages, step/turn history.
|
|
459
467
|
*
|
|
460
|
-
* Does **not** reset KV
|
|
468
|
+
* Does **not** reset KV store — create a new harness for that.
|
|
461
469
|
*/
|
|
462
470
|
reset() {
|
|
463
471
|
this._messages = [];
|
|
464
|
-
this._onStepCalls = [];
|
|
465
472
|
this._onTurnCalls = [];
|
|
466
473
|
}
|
|
467
474
|
};
|
|
468
475
|
/**
|
|
469
|
-
* Create a SQLite-vec backed vector store with deterministic test embeddings.
|
|
470
|
-
* Uses a temp directory that is unique per call for test isolation.
|
|
471
|
-
*/
|
|
472
|
-
function createTestVectorStore() {
|
|
473
|
-
return createUnstorageVectorStore({
|
|
474
|
-
storage: createStorage(),
|
|
475
|
-
embedFn: createTestEmbedFn()
|
|
476
|
-
});
|
|
477
|
-
}
|
|
478
|
-
/**
|
|
479
476
|
* Create a test harness for unit-testing an agent.
|
|
480
477
|
*
|
|
481
478
|
* The harness wraps the agent's tool definitions and lifecycle hooks,
|
|
@@ -483,7 +480,7 @@ function createTestVectorStore() {
|
|
|
483
480
|
* conversations — all without audio, network, or an LLM.
|
|
484
481
|
*
|
|
485
482
|
* @param agent - The agent definition returned by `defineAgent()`.
|
|
486
|
-
* @param options - Optional environment
|
|
483
|
+
* @param options - Optional environment and KV store overrides.
|
|
487
484
|
* @returns A {@link TestHarness} instance.
|
|
488
485
|
*
|
|
489
486
|
* @example
|
|
@@ -505,13 +502,12 @@ function createTestVectorStore() {
|
|
|
505
502
|
* @public
|
|
506
503
|
*/
|
|
507
504
|
function createTestHarness(agent, options = {}) {
|
|
508
|
-
const { env = {}, kv = createUnstorageKv({ storage: createStorage() })
|
|
509
|
-
return new TestHarness(
|
|
505
|
+
const { env = {}, kv = createUnstorageKv({ storage: createStorage() }) } = options;
|
|
506
|
+
return new TestHarness(createRuntime({
|
|
510
507
|
agent,
|
|
511
508
|
env,
|
|
512
|
-
kv
|
|
513
|
-
vector
|
|
509
|
+
kv
|
|
514
510
|
}), `test-${Date.now()}`);
|
|
515
511
|
}
|
|
516
512
|
//#endregion
|
|
517
|
-
export {
|
|
513
|
+
export { makeStubSession as a, flush as i, TurnResult as n, MockWebSocket as o, createTestHarness as r, installMockWebSocket as s, TestHarness as t };
|
package/dist/testing.d.ts
CHANGED
|
@@ -35,11 +35,11 @@
|
|
|
35
35
|
*
|
|
36
36
|
* @packageDocumentation
|
|
37
37
|
*/
|
|
38
|
-
import { type
|
|
38
|
+
import { type Runtime } from "./direct-executor.ts";
|
|
39
39
|
import type { Kv } from "./kv.ts";
|
|
40
|
-
import type { AgentDef, Message
|
|
41
|
-
import type { VectorStore } from "./vector.ts";
|
|
40
|
+
import type { AgentDef, Message } from "./types.ts";
|
|
42
41
|
export { installMockWebSocket, MockWebSocket } from "./_mock-ws.ts";
|
|
42
|
+
export { flush, makeStubSession } from "./_test-utils.ts";
|
|
43
43
|
/**
|
|
44
44
|
* A single tool call recorded during a turn.
|
|
45
45
|
*
|
|
@@ -137,8 +137,6 @@ export type TestHarnessOptions = {
|
|
|
137
137
|
env?: Record<string, string>;
|
|
138
138
|
/** KV store instance. Defaults to an in-memory SQLite store. */
|
|
139
139
|
kv?: Kv;
|
|
140
|
-
/** Vector store instance. Defaults to an in-memory SQLite store. */
|
|
141
|
-
vector?: VectorStore;
|
|
142
140
|
};
|
|
143
141
|
/**
|
|
144
142
|
* A tool call to execute during a simulated turn.
|
|
@@ -179,19 +177,16 @@ export type TurnToolCall = {
|
|
|
179
177
|
*/
|
|
180
178
|
export declare class TestHarness {
|
|
181
179
|
/** @internal */
|
|
182
|
-
readonly _executor:
|
|
180
|
+
readonly _executor: Runtime;
|
|
183
181
|
/** @internal */
|
|
184
182
|
readonly _sessionId: string;
|
|
185
183
|
private _messages;
|
|
186
|
-
private _onStepCalls;
|
|
187
184
|
private _onTurnCalls;
|
|
188
185
|
private _connected;
|
|
189
186
|
/** @internal */
|
|
190
|
-
constructor(executor:
|
|
187
|
+
constructor(executor: Runtime, sessionId: string);
|
|
191
188
|
/** Conversation messages accumulated across turns. */
|
|
192
189
|
get messages(): readonly Message[];
|
|
193
|
-
/** All `onStep` hook invocations recorded so far. */
|
|
194
|
-
get steps(): readonly StepInfo[];
|
|
195
190
|
/** All `onTurn` hook invocations (the text argument) recorded so far. */
|
|
196
191
|
get turns(): readonly string[];
|
|
197
192
|
/**
|
|
@@ -207,7 +202,7 @@ export declare class TestHarness {
|
|
|
207
202
|
/**
|
|
208
203
|
* Execute a single tool by name with the given arguments.
|
|
209
204
|
*
|
|
210
|
-
* The tool runs with full agent context (env, state, kv,
|
|
205
|
+
* The tool runs with full agent context (env, state, kv, messages).
|
|
211
206
|
* The call is **not** recorded in conversation history — use {@link turn}
|
|
212
207
|
* for that.
|
|
213
208
|
*
|
|
@@ -231,7 +226,7 @@ export declare class TestHarness {
|
|
|
231
226
|
* 1. Fires `onConnect` if this is the first turn
|
|
232
227
|
* 2. Adds the user message to conversation history
|
|
233
228
|
* 3. Fires the `onTurn` hook
|
|
234
|
-
* 4. Executes each tool call in order
|
|
229
|
+
* 4. Executes each tool call in order
|
|
235
230
|
* 5. Returns a {@link TurnResult} with assertion helpers
|
|
236
231
|
*
|
|
237
232
|
* @param text - The user's spoken/typed input.
|
|
@@ -263,7 +258,7 @@ export declare class TestHarness {
|
|
|
263
258
|
/**
|
|
264
259
|
* Reset conversation state: clears messages, step/turn history.
|
|
265
260
|
*
|
|
266
|
-
* Does **not** reset KV
|
|
261
|
+
* Does **not** reset KV store — create a new harness for that.
|
|
267
262
|
*/
|
|
268
263
|
reset(): void;
|
|
269
264
|
}
|
|
@@ -275,7 +270,7 @@ export declare class TestHarness {
|
|
|
275
270
|
* conversations — all without audio, network, or an LLM.
|
|
276
271
|
*
|
|
277
272
|
* @param agent - The agent definition returned by `defineAgent()`.
|
|
278
|
-
* @param options - Optional environment
|
|
273
|
+
* @param options - Optional environment and KV store overrides.
|
|
279
274
|
* @returns A {@link TestHarness} instance.
|
|
280
275
|
*
|
|
281
276
|
* @example
|
package/dist/testing.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { MockWebSocket, TestHarness, TurnResult, createTestHarness, installMockWebSocket };
|
|
1
|
+
import { a as makeStubSession, i as flush, n as TurnResult, o as MockWebSocket, r as createTestHarness, s as installMockWebSocket, t as TestHarness } from "./testing-Dmx-dudh.js";
|
|
2
|
+
export { MockWebSocket, TestHarness, TurnResult, createTestHarness, flush, installMockWebSocket, makeStubSession };
|
package/dist/types.d.ts
CHANGED
|
@@ -3,154 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import type { Kv } from "./kv.ts";
|
|
6
|
-
import type { VectorStore } from "./vector.ts";
|
|
7
|
-
/**
|
|
8
|
-
* Result returned by a `beforeTurn` middleware to block a turn.
|
|
9
|
-
* @public
|
|
10
|
-
*/
|
|
11
|
-
export type MiddlewareBlockResult = {
|
|
12
|
-
block: true;
|
|
13
|
-
reason: string;
|
|
14
|
-
};
|
|
15
|
-
/**
|
|
16
|
-
* Result returned by a `beforeToolCall` middleware hook to short-circuit tool execution.
|
|
17
|
-
*
|
|
18
|
-
* Return `{ result: string }` to skip execution and use a cached/synthetic result.
|
|
19
|
-
* Return `{ block: true; reason: string }` to deny the tool call.
|
|
20
|
-
* Return `{ args: Record<string, unknown> }` to transform the arguments.
|
|
21
|
-
* Return `undefined` to proceed normally.
|
|
22
|
-
*
|
|
23
|
-
* @public
|
|
24
|
-
*/
|
|
25
|
-
export type ToolCallInterceptResult = {
|
|
26
|
-
result: string;
|
|
27
|
-
} | {
|
|
28
|
-
block: true;
|
|
29
|
-
reason: string;
|
|
30
|
-
} | {
|
|
31
|
-
args: Record<string, unknown>;
|
|
32
|
-
} | undefined;
|
|
33
|
-
/**
|
|
34
|
-
* Composable middleware for the agent lifecycle.
|
|
35
|
-
*
|
|
36
|
-
* Middleware can intercept turns, tool calls, and output at well-defined
|
|
37
|
-
* points. Multiple middleware compose in array order: the first middleware
|
|
38
|
-
* in the array runs first for "before" hooks and last for "after" hooks.
|
|
39
|
-
*
|
|
40
|
-
* ## Middleware Composition Order
|
|
41
|
-
*
|
|
42
|
-
* **"Before" hooks** run in array order (first middleware → last):
|
|
43
|
-
* `beforeInput` → `beforeTurn` → `beforeToolCall` → `beforeOutput`
|
|
44
|
-
*
|
|
45
|
-
* **"After" hooks** run in reverse array order (last middleware → first):
|
|
46
|
-
* `afterToolCall` → `afterTurn`
|
|
47
|
-
*
|
|
48
|
-
* ### Execution flow for a user turn
|
|
49
|
-
*
|
|
50
|
-
* ```
|
|
51
|
-
* User text arrives
|
|
52
|
-
* │
|
|
53
|
-
* ▼
|
|
54
|
-
* beforeInput — transform/redact input text (piped through each middleware)
|
|
55
|
-
* │
|
|
56
|
-
* ▼
|
|
57
|
-
* beforeTurn — block or allow the turn (short-circuits on first block)
|
|
58
|
-
* │
|
|
59
|
-
* ▼ (if not blocked)
|
|
60
|
-
* LLM reasoning + tool calls
|
|
61
|
-
* │ ┌─ beforeToolCall (per call, short-circuits on block/result)
|
|
62
|
-
* │ └─ afterToolCall (per call, reverse order)
|
|
63
|
-
* │
|
|
64
|
-
* ▼
|
|
65
|
-
* beforeOutput — transform/redact LLM output text (piped through each middleware)
|
|
66
|
-
* │
|
|
67
|
-
* ▼
|
|
68
|
-
* afterTurn — cleanup/logging (reverse order)
|
|
69
|
-
* ```
|
|
70
|
-
*
|
|
71
|
-
* ### Short-circuit behavior
|
|
72
|
-
*
|
|
73
|
-
* - **`beforeTurn`**: If *any* middleware returns `{ block: true, reason }`,
|
|
74
|
-
* the turn is blocked and subsequent `beforeTurn` hooks do **not** run.
|
|
75
|
-
* When a turn is blocked, `afterTurn` hooks do **not** fire (the turn
|
|
76
|
-
* never started).
|
|
77
|
-
* - **`beforeToolCall`**: If *any* middleware blocks or returns a cached
|
|
78
|
-
* result, subsequent `beforeToolCall` hooks do **not** run. Arg transforms
|
|
79
|
-
* accumulate across middleware.
|
|
80
|
-
* - **`beforeInput`** / **`beforeOutput`**: These *always* run all middleware
|
|
81
|
-
* in sequence (no short-circuit). Each receives the output of the previous.
|
|
82
|
-
*
|
|
83
|
-
* ### Ordering example
|
|
84
|
-
*
|
|
85
|
-
* ```ts
|
|
86
|
-
* middleware: [auditTrail, hipaaGuardrails]
|
|
87
|
-
* ```
|
|
88
|
-
* - `beforeInput`: auditTrail runs first, then hipaaGuardrails
|
|
89
|
-
* - `beforeTurn`: auditTrail runs first; if it blocks, hipaaGuardrails is skipped
|
|
90
|
-
* - `afterTurn`: hipaaGuardrails runs first (reverse), then auditTrail
|
|
91
|
-
*
|
|
92
|
-
* If you want the guardrail to run *before* the audit trail logs, place it
|
|
93
|
-
* first in the array: `[hipaaGuardrails, auditTrail]`.
|
|
94
|
-
*
|
|
95
|
-
* @typeParam S - The shape of per-session state. Defaults to `any` so that
|
|
96
|
-
* reusable, state-agnostic middleware (e.g. loggers, rate-limiters) can be
|
|
97
|
-
* authored without threading a state generic. Use an explicit generic
|
|
98
|
-
* (`Middleware<MyState>`) when the middleware reads or writes session state.
|
|
99
|
-
*
|
|
100
|
-
* @public
|
|
101
|
-
*/
|
|
102
|
-
export type Middleware<S = any> = {
|
|
103
|
-
/** Human-readable name for logging and debugging. */
|
|
104
|
-
name: string;
|
|
105
|
-
/**
|
|
106
|
-
* Filters user input text before it reaches the LLM. Return the
|
|
107
|
-
* (possibly modified) text. Runs on every user transcript, before
|
|
108
|
-
* `beforeTurn`.
|
|
109
|
-
*
|
|
110
|
-
* Use this to redact PII (SSNs, emails, patient IDs) from speech
|
|
111
|
-
* transcripts so the LLM never sees sensitive data.
|
|
112
|
-
*
|
|
113
|
-
* Middleware is piped in array order: the output of one filter becomes
|
|
114
|
-
* the input of the next.
|
|
115
|
-
*
|
|
116
|
-
* @example
|
|
117
|
-
* ```ts
|
|
118
|
-
* beforeInput: (text) =>
|
|
119
|
-
* text.replace(/\b\d{3}[-.]?\d{2}[-.]?\d{4}\b/g, "[SSN REDACTED]")
|
|
120
|
-
* ```
|
|
121
|
-
*/
|
|
122
|
-
beforeInput?: (text: string, ctx: HookContext<S>) => string | Promise<string>;
|
|
123
|
-
/**
|
|
124
|
-
* Runs before each user turn. Can block the turn by returning
|
|
125
|
-
* `{ block: true, reason: "..." }`. Return `undefined` to proceed.
|
|
126
|
-
*
|
|
127
|
-
* Receives the text *after* `beforeInput` filtering has been applied.
|
|
128
|
-
*
|
|
129
|
-
* When a turn is blocked, subsequent `beforeTurn` middleware is skipped,
|
|
130
|
-
* and `afterTurn` hooks do **not** fire.
|
|
131
|
-
*/
|
|
132
|
-
beforeTurn?: (text: string, ctx: HookContext<S>) => MiddlewareBlockResult | void | undefined | Promise<MiddlewareBlockResult | void | undefined>;
|
|
133
|
-
/**
|
|
134
|
-
* Runs after each user turn completes (after all steps finish).
|
|
135
|
-
* Runs in reverse array order.
|
|
136
|
-
*/
|
|
137
|
-
afterTurn?: (text: string, ctx: HookContext<S>) => void | Promise<void>;
|
|
138
|
-
/**
|
|
139
|
-
* Runs before each tool call. Can approve, deny, transform args, or
|
|
140
|
-
* return a cached result.
|
|
141
|
-
*/
|
|
142
|
-
beforeToolCall?: (toolName: string, args: Readonly<Record<string, unknown>>, ctx: HookContext<S>) => ToolCallInterceptResult | undefined | Promise<ToolCallInterceptResult | undefined>;
|
|
143
|
-
/**
|
|
144
|
-
* Runs after each tool call completes. Useful for caching results,
|
|
145
|
-
* logging, or analytics. Runs in reverse array order.
|
|
146
|
-
*/
|
|
147
|
-
afterToolCall?: (toolName: string, args: Readonly<Record<string, unknown>>, result: string, ctx: HookContext<S>) => void | Promise<void>;
|
|
148
|
-
/**
|
|
149
|
-
* Filters agent text output before it is sent to TTS. Return the
|
|
150
|
-
* (possibly modified) text. Runs on every agent transcript chunk.
|
|
151
|
-
*/
|
|
152
|
-
beforeOutput?: (text: string, ctx: HookContext<S>) => string | Promise<string>;
|
|
153
|
-
};
|
|
154
6
|
/**
|
|
155
7
|
* Identifier for a built-in server-side tool.
|
|
156
8
|
*
|
|
@@ -161,12 +13,11 @@ export type Middleware<S = any> = {
|
|
|
161
13
|
* - `"visit_webpage"` — Fetch a URL and return its content as clean text.
|
|
162
14
|
* - `"fetch_json"` — Call a REST API endpoint and return the JSON response.
|
|
163
15
|
* - `"run_code"` — Execute JavaScript in a sandbox for calculations and data processing.
|
|
164
|
-
* - `"vector_search"` — Search the agent's RAG knowledge base for relevant documents.
|
|
165
16
|
* - `"memory"` — Persistent KV memory: save_memory, recall_memory, list_memories, forget_memory.
|
|
166
17
|
*
|
|
167
18
|
* @public
|
|
168
19
|
*/
|
|
169
|
-
export type BuiltinTool = "web_search" | "visit_webpage" | "fetch_json" | "run_code" | "
|
|
20
|
+
export type BuiltinTool = "web_search" | "visit_webpage" | "fetch_json" | "run_code" | "memory";
|
|
170
21
|
/**
|
|
171
22
|
* How the LLM should select tools during a turn.
|
|
172
23
|
*
|
|
@@ -228,23 +79,8 @@ export type ToolContext<S = Record<string, unknown>> = {
|
|
|
228
79
|
state: S;
|
|
229
80
|
/** Key-value store scoped to this agent deployment. */
|
|
230
81
|
kv: Kv;
|
|
231
|
-
/** Vector store scoped to this agent deployment. */
|
|
232
|
-
vector: VectorStore;
|
|
233
82
|
/** Read-only snapshot of conversation messages so far. */
|
|
234
83
|
messages: readonly Message[];
|
|
235
|
-
/**
|
|
236
|
-
* Push an intermediate update to the client UI before the tool finishes.
|
|
237
|
-
*
|
|
238
|
-
* Use this to send progressive data so the UI can render partial results
|
|
239
|
-
* immediately (e.g. a loading card, preview, or streaming data) instead
|
|
240
|
-
* of waiting for the full tool result.
|
|
241
|
-
*
|
|
242
|
-
* The data is serialized to JSON and delivered as a `tool_call_update`
|
|
243
|
-
* event on the client. Use `useToolCallUpdate` in the UI to consume it.
|
|
244
|
-
*
|
|
245
|
-
* No-op in sandbox (platform) mode.
|
|
246
|
-
*/
|
|
247
|
-
sendUpdate(data: unknown): void;
|
|
248
84
|
/**
|
|
249
85
|
* SSRF-safe fetch function.
|
|
250
86
|
*
|
|
@@ -258,17 +94,29 @@ export type ToolContext<S = Record<string, unknown>> = {
|
|
|
258
94
|
sessionId: string;
|
|
259
95
|
};
|
|
260
96
|
/**
|
|
261
|
-
* Context passed to lifecycle hooks
|
|
262
|
-
*
|
|
263
|
-
* Same as {@link ToolContext} but without `messages`, since hooks
|
|
264
|
-
* run outside the tool execution flow.
|
|
97
|
+
* Context passed to lifecycle hooks.
|
|
265
98
|
*
|
|
266
99
|
* @typeParam S - The shape of per-session state created by the agent's
|
|
267
100
|
* `state` factory. Defaults to `Record<string, unknown>`.
|
|
268
101
|
*
|
|
269
102
|
* @public
|
|
270
103
|
*/
|
|
271
|
-
export type HookContext<S = Record<string, unknown>> =
|
|
104
|
+
export type HookContext<S = Record<string, unknown>> = {
|
|
105
|
+
/** Environment variables declared in the agent config. */
|
|
106
|
+
env: Readonly<Record<string, string>>;
|
|
107
|
+
/** Mutable per-session state created by the agent's `state` factory. */
|
|
108
|
+
state: S;
|
|
109
|
+
/** Key-value store scoped to this agent deployment. */
|
|
110
|
+
kv: Kv;
|
|
111
|
+
/**
|
|
112
|
+
* SSRF-safe fetch function.
|
|
113
|
+
* In self-hosted mode this calls the network directly (with SSRF protection).
|
|
114
|
+
* In platform mode this is proxied through the sidecar.
|
|
115
|
+
*/
|
|
116
|
+
fetch: typeof globalThis.fetch;
|
|
117
|
+
/** Unique identifier for the current session. */
|
|
118
|
+
sessionId: string;
|
|
119
|
+
};
|
|
272
120
|
/**
|
|
273
121
|
* Definition of a custom tool that the agent can invoke.
|
|
274
122
|
*
|
|
@@ -344,17 +192,17 @@ export { defineTool as tool };
|
|
|
344
192
|
* Create a typed `defineTool` helper with the session state type baked in.
|
|
345
193
|
*
|
|
346
194
|
* When tools need access to typed session state, you'd normally have to write
|
|
347
|
-
* verbose generics on every `defineTool` call. `
|
|
195
|
+
* verbose generics on every `defineTool` call. `defineToolFactory` eliminates
|
|
348
196
|
* that boilerplate by returning a `defineTool` variant that already knows `S`.
|
|
349
197
|
*
|
|
350
198
|
* @example
|
|
351
199
|
* ```ts
|
|
352
|
-
* import {
|
|
200
|
+
* import { defineToolFactory, defineAgent } from "aai";
|
|
353
201
|
* import { z } from "zod";
|
|
354
202
|
*
|
|
355
203
|
* interface PortfolioState { holdings: Map<string, number> }
|
|
356
204
|
*
|
|
357
|
-
* const tool =
|
|
205
|
+
* const tool = defineToolFactory<PortfolioState>();
|
|
358
206
|
*
|
|
359
207
|
* export default defineAgent<PortfolioState>({
|
|
360
208
|
* name: "portfolio",
|
|
@@ -374,7 +222,7 @@ export { defineTool as tool };
|
|
|
374
222
|
*
|
|
375
223
|
* @public
|
|
376
224
|
*/
|
|
377
|
-
export declare function
|
|
225
|
+
export declare function defineToolFactory<S = Record<string, unknown>>(): <P extends z.ZodObject<z.ZodRawShape>>(def: ToolDef<P, S>) => ToolDef<P, S>;
|
|
378
226
|
/**
|
|
379
227
|
* A mapping of tool names to their result types.
|
|
380
228
|
*
|
|
@@ -413,25 +261,6 @@ export declare function createToolFactory<S = Record<string, unknown>>(): <P ext
|
|
|
413
261
|
* @public
|
|
414
262
|
*/
|
|
415
263
|
export type ToolResultMap<T extends Record<string, unknown> = Record<string, unknown>> = T;
|
|
416
|
-
/**
|
|
417
|
-
* Information about a completed agentic step, passed to the `onStep` hook.
|
|
418
|
-
*
|
|
419
|
-
* Each turn may consist of multiple steps (up to `maxSteps`). A step
|
|
420
|
-
* represents one LLM invocation that may include tool calls and text output.
|
|
421
|
-
*
|
|
422
|
-
* @public
|
|
423
|
-
*/
|
|
424
|
-
export type StepInfo = {
|
|
425
|
-
/** 1-based step index within the current turn. */
|
|
426
|
-
stepNumber: number;
|
|
427
|
-
/** Tool calls made during this step. */
|
|
428
|
-
toolCalls: readonly {
|
|
429
|
-
toolName: string;
|
|
430
|
-
args: Readonly<Record<string, unknown>>;
|
|
431
|
-
}[];
|
|
432
|
-
/** LLM text output for this step. */
|
|
433
|
-
text: string;
|
|
434
|
-
};
|
|
435
264
|
/**
|
|
436
265
|
* Options passed to {@link defineAgent} to configure an agent.
|
|
437
266
|
*
|
|
@@ -485,21 +314,6 @@ export type AgentOptions<S = Record<string, unknown>> = {
|
|
|
485
314
|
tools?: Readonly<Record<string, ToolDef<z.ZodObject<z.ZodRawShape>, NoInfer<S>>>>;
|
|
486
315
|
/** Factory that creates fresh per-session state. Called once per connection. */
|
|
487
316
|
state?: () => S;
|
|
488
|
-
/**
|
|
489
|
-
* Enable automatic session state persistence across reconnects.
|
|
490
|
-
*
|
|
491
|
-
* When enabled, session state, conversation history, and the S2S session ID
|
|
492
|
-
* are saved to KV on disconnect and restored when the client reconnects with
|
|
493
|
-
* `?sessionId=<old-session-id>` in the WebSocket URL.
|
|
494
|
-
*
|
|
495
|
-
* - `true` — enable with default TTL (1 hour)
|
|
496
|
-
* - `{ ttl: number }` — enable with custom TTL in milliseconds
|
|
497
|
-
*
|
|
498
|
-
* Requires the agent's `state` return value to be JSON-serializable.
|
|
499
|
-
*/
|
|
500
|
-
persistence?: boolean | {
|
|
501
|
-
ttl?: number;
|
|
502
|
-
};
|
|
503
317
|
/** Called when a new session connects. */
|
|
504
318
|
onConnect?: (ctx: HookContext<S>) => void | Promise<void>;
|
|
505
319
|
/** Called when a session disconnects. */
|
|
@@ -508,15 +322,6 @@ export type AgentOptions<S = Record<string, unknown>> = {
|
|
|
508
322
|
onError?: (error: Error, ctx?: HookContext<S>) => void;
|
|
509
323
|
/** Called after a complete turn (all steps finished). */
|
|
510
324
|
onTurn?: (text: string, ctx: HookContext<S>) => void | Promise<void>;
|
|
511
|
-
/** Called after each agentic step completes. */
|
|
512
|
-
onStep?: (step: StepInfo, ctx: HookContext<S>) => void | Promise<void>;
|
|
513
|
-
/**
|
|
514
|
-
* Composable middleware that intercepts turns, tool calls, and output.
|
|
515
|
-
*
|
|
516
|
-
* Middleware runs in array order for "before" hooks (first to last)
|
|
517
|
-
* and reverse order for "after" hooks (last to first).
|
|
518
|
-
*/
|
|
519
|
-
middleware?: readonly Middleware<S>[];
|
|
520
325
|
/**
|
|
521
326
|
* Close the S2S connection after this many milliseconds of inactivity.
|
|
522
327
|
* Inactivity means no audio, transcripts, or tool calls in either direction.
|
|
@@ -543,8 +348,8 @@ export declare const DEFAULT_GREETING: string;
|
|
|
543
348
|
*
|
|
544
349
|
* Core fields (`name`, `instructions`, `greeting`, `maxSteps`, `tools`)
|
|
545
350
|
* are resolved to their final values with defaults applied. Optional
|
|
546
|
-
* behavioral fields (hooks,
|
|
547
|
-
*
|
|
351
|
+
* behavioral fields (hooks, `sttPrompt`, etc.) remain optional —
|
|
352
|
+
* `undefined` means "not configured."
|
|
548
353
|
*
|
|
549
354
|
* @public
|
|
550
355
|
*/
|
|
@@ -558,16 +363,10 @@ export type AgentDef<S = Record<string, unknown>> = {
|
|
|
558
363
|
builtinTools?: readonly BuiltinTool[];
|
|
559
364
|
tools: Readonly<Record<string, ToolDef<z.ZodObject<z.ZodRawShape>, S>>>;
|
|
560
365
|
state?: () => S;
|
|
561
|
-
/** Resolved persistence config, or `undefined` if disabled. */
|
|
562
|
-
persistence?: {
|
|
563
|
-
ttl: number;
|
|
564
|
-
};
|
|
565
366
|
onConnect?: (ctx: HookContext<S>) => void | Promise<void>;
|
|
566
367
|
onDisconnect?: (ctx: HookContext<S>) => void | Promise<void>;
|
|
567
368
|
onError?: (error: Error, ctx?: HookContext<S>) => void;
|
|
568
369
|
onTurn?: (text: string, ctx: HookContext<S>) => void | Promise<void>;
|
|
569
|
-
onStep?: (step: StepInfo, ctx: HookContext<S>) => void | Promise<void>;
|
|
570
|
-
middleware?: readonly Middleware<S>[];
|
|
571
370
|
idleTimeoutMs?: number;
|
|
572
371
|
};
|
|
573
372
|
/** @internal Zod schema for {@link BuiltinTool}. Exported for reuse in internal schemas. */
|
|
@@ -576,7 +375,6 @@ export declare const BuiltinToolSchema: z.ZodEnum<{
|
|
|
576
375
|
visit_webpage: "visit_webpage";
|
|
577
376
|
fetch_json: "fetch_json";
|
|
578
377
|
run_code: "run_code";
|
|
579
|
-
vector_search: "vector_search";
|
|
580
378
|
memory: "memory";
|
|
581
379
|
}>;
|
|
582
380
|
/** @internal Zod schema for {@link ToolChoice}. Exported for reuse in internal schemas. */
|