@kuralle-syrinx/cf-agents 4.0.0 → 4.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.
- package/README.md +1 -0
- package/package.json +31 -22
- package/src/build-session.ts +8 -0
- package/src/with-voice.ts +11 -0
package/README.md
CHANGED
|
@@ -97,6 +97,7 @@ comes with —
|
|
|
97
97
|
| `onDelegateQuery` / `onDelegateResult` | G2 observability hooks around the reasoner run. `onDelegateResult` is self-contained (`{ query, answer, durationMs, grounded, toolId?, toolName?, turnId, sessionId, connection }`) — the one hook for logging/persisting grounded Q&A pairs. Throwing never affects the call. |
|
|
98
98
|
| `durableHistory` | G4 durable session state over the Agent's SQLite (default `true`). Set `false` for ephemeral pre-G4 behavior. |
|
|
99
99
|
| `delayCueAfterMs` | G3: ms before a pending tool call fires the `tool_call_delayed` ("still working") cue. 0 disables. Default 2000. |
|
|
100
|
+
| `backgroundAudio` | `{ ambient?, thinking?, duckWhileSpeaking? }` — looped ambient bed + thinking loop (raw mono PCM16 sources), mixed (ducked) under assistant speech; on the `"twilio"` transport the bed also fills between-turn gaps as comfort noise. Thinking follows the G3 cues. |
|
|
100
101
|
| `inputSampleRateHz` / `outputSampleRateHz` | Edge audio rates (default 16000). |
|
|
101
102
|
| `resumeWindowMs` | How long a dropped connection can resume its session. |
|
|
102
103
|
| `sessionId` | `(request, agentName) => string`. Defaults to the `?sessionId=` query param (so a reconnecting client can resume), else a per-connection random id. (Not the Agent name — concurrent connections to one instance must not share a session.) |
|
package/package.json
CHANGED
|
@@ -1,10 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kuralle-syrinx/cf-agents",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"private": false,
|
|
5
|
-
"type": "module",
|
|
6
|
-
"license": "MIT",
|
|
7
5
|
"description": "withVoice(Agent) — add a Syrinx realtime or cascaded voice pipeline to a Cloudflare agents SDK Agent",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"kuralle",
|
|
8
|
+
"syrinx",
|
|
9
|
+
"voice",
|
|
10
|
+
"cloudflare",
|
|
11
|
+
"agents",
|
|
12
|
+
"durable-objects",
|
|
13
|
+
"realtime",
|
|
14
|
+
"cascaded",
|
|
15
|
+
"stt",
|
|
16
|
+
"tts"
|
|
17
|
+
],
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"homepage": "https://github.com/kuralle/syrinx#readme",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/kuralle/syrinx.git",
|
|
23
|
+
"directory": "packages/cf-agents"
|
|
24
|
+
},
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/kuralle/syrinx/issues"
|
|
27
|
+
},
|
|
28
|
+
"type": "module",
|
|
8
29
|
"main": "./src/index.ts",
|
|
9
30
|
"types": "./src/index.ts",
|
|
10
31
|
"exports": {
|
|
@@ -12,13 +33,13 @@
|
|
|
12
33
|
"./r2-recorder": "./src/r2-recorder.ts"
|
|
13
34
|
},
|
|
14
35
|
"dependencies": {
|
|
15
|
-
"@kuralle-syrinx/
|
|
16
|
-
"@kuralle-syrinx/
|
|
17
|
-
"@kuralle-syrinx/
|
|
18
|
-
"@kuralle-syrinx/
|
|
19
|
-
"@kuralle-syrinx/ws": "4.
|
|
20
|
-
"@kuralle-syrinx/
|
|
21
|
-
"@kuralle-syrinx/
|
|
36
|
+
"@kuralle-syrinx/kuralle": "4.2.0",
|
|
37
|
+
"@kuralle-syrinx/server-websocket": "4.2.0",
|
|
38
|
+
"@kuralle-syrinx/core": "4.2.0",
|
|
39
|
+
"@kuralle-syrinx/aisdk": "4.2.0",
|
|
40
|
+
"@kuralle-syrinx/ws": "4.2.0",
|
|
41
|
+
"@kuralle-syrinx/recorder": "4.2.0",
|
|
42
|
+
"@kuralle-syrinx/realtime": "4.2.0"
|
|
22
43
|
},
|
|
23
44
|
"peerDependencies": {
|
|
24
45
|
"agents": ">=0.14.0 <1.0.0"
|
|
@@ -29,18 +50,6 @@
|
|
|
29
50
|
"typescript": "^5.7.0",
|
|
30
51
|
"vitest": "^2.1.0"
|
|
31
52
|
},
|
|
32
|
-
"keywords": [
|
|
33
|
-
"kuralle",
|
|
34
|
-
"syrinx",
|
|
35
|
-
"voice",
|
|
36
|
-
"cloudflare",
|
|
37
|
-
"agents",
|
|
38
|
-
"durable-objects",
|
|
39
|
-
"realtime",
|
|
40
|
-
"cascaded",
|
|
41
|
-
"stt",
|
|
42
|
-
"tts"
|
|
43
|
-
],
|
|
44
53
|
"scripts": {
|
|
45
54
|
"typecheck": "tsc --noEmit",
|
|
46
55
|
"test": "vitest run"
|
package/src/build-session.ts
CHANGED
|
@@ -89,6 +89,13 @@ export interface CascadedPipeline<Env> {
|
|
|
89
89
|
* (engine default 7000). Set it when a provider-endpointed cascade tunes this (e.g. Deepgram at 3500).
|
|
90
90
|
*/
|
|
91
91
|
readonly sttForceFinalizeTimeoutMs?: number;
|
|
92
|
+
/**
|
|
93
|
+
* Speculative generation: start the reasoner on an eager end-of-turn signal
|
|
94
|
+
* (`eos.interim` — Deepgram Flux `eager_eot_threshold`, smart-turn interim) and
|
|
95
|
+
* commit/discard when the endpoint confirms. Trades extra LLM calls for
|
|
96
|
+
* parallelizing LLM TTFT with endpoint confirmation. @default false
|
|
97
|
+
*/
|
|
98
|
+
readonly speculative?: boolean;
|
|
92
99
|
}
|
|
93
100
|
|
|
94
101
|
export type VoicePipeline<Env> = RealtimePipeline<Env> | CascadedPipeline<Env>;
|
|
@@ -163,6 +170,7 @@ export function buildVoiceSession<Env>(
|
|
|
163
170
|
...(wiring.reasonerSessionStore
|
|
164
171
|
? { sessionStore: wiring.reasonerSessionStore, sessionId: ctx.sessionId }
|
|
165
172
|
: {}),
|
|
173
|
+
...(pipeline.speculative ? { speculative: true } : {}),
|
|
166
174
|
}),
|
|
167
175
|
);
|
|
168
176
|
session.registerPlugin("tts", tts.plugin);
|
package/src/with-voice.ts
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
import type { Agent, Connection, ConnectionContext, WSMessage } from "agents";
|
|
20
20
|
import {
|
|
21
21
|
runVoiceEdgeWebSocketConnection,
|
|
22
|
+
type BackgroundAudioConfig,
|
|
22
23
|
type EdgeRecorder,
|
|
23
24
|
} from "@kuralle-syrinx/server-websocket/edge";
|
|
24
25
|
import { runTwilioEdgeWebSocketConnection } from "@kuralle-syrinx/server-websocket/edge-twilio";
|
|
@@ -118,6 +119,14 @@ export interface WithVoiceOptions<Env> {
|
|
|
118
119
|
readonly reasoner?: (env: Env, ctx: VoicePipelineContext) => Reasoner | Promise<Reasoner>;
|
|
119
120
|
/** Optional per-call recorder (e.g. an R2-backed `EdgeRecorder`). Applies to the `"edge"` transport. */
|
|
120
121
|
readonly recorder?: (env: Env, ctx: VoicePipelineContext) => EdgeRecorder | undefined;
|
|
122
|
+
/**
|
|
123
|
+
* Ambient/thinking bed mixed (ducked) under assistant speech on both transports.
|
|
124
|
+
* On the `"twilio"` transport the bed also fills the gaps between turns as
|
|
125
|
+
* comfort noise — pure digital silence on a phone line reads as "the call died".
|
|
126
|
+
* The thinking loop follows the G3 tool-call cues. Sources are raw mono PCM16
|
|
127
|
+
* (e.g. `ffmpeg -i office.mp3 -ac 1 -ar 16000 -f s16le office.pcm`).
|
|
128
|
+
*/
|
|
129
|
+
readonly backgroundAudio?: BackgroundAudioConfig;
|
|
121
130
|
/**
|
|
122
131
|
* Fired when the front model starts a delegate tool call, before the reasoner runs — the seam
|
|
123
132
|
* for a deterministic latency-masking preamble / "thinking" earcon. Throwing here never affects
|
|
@@ -416,6 +425,7 @@ export function withVoice<Env, TBase extends AgentLike>(
|
|
|
416
425
|
? { engineSampleRateHz: options.inputSampleRateHz }
|
|
417
426
|
: {}),
|
|
418
427
|
...(options.resumeWindowMs !== undefined ? { resumeWindowMs: options.resumeWindowMs } : {}),
|
|
428
|
+
...(options.backgroundAudio ? { backgroundAudio: options.backgroundAudio } : {}),
|
|
419
429
|
}).catch(onRunnerSettled);
|
|
420
430
|
return;
|
|
421
431
|
}
|
|
@@ -441,6 +451,7 @@ export function withVoice<Env, TBase extends AgentLike>(
|
|
|
441
451
|
? { outputSampleRateHz: options.outputSampleRateHz }
|
|
442
452
|
: {}),
|
|
443
453
|
...(options.resumeWindowMs !== undefined ? { resumeWindowMs: options.resumeWindowMs } : {}),
|
|
454
|
+
...(options.backgroundAudio ? { backgroundAudio: options.backgroundAudio } : {}),
|
|
444
455
|
createSession,
|
|
445
456
|
}).catch(onRunnerSettled);
|
|
446
457
|
}
|