@kuralle-agents/cf-agent 0.3.20 → 0.4.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/StreamAdapter.d.ts +10 -0
- package/dist/StreamAdapter.js +27 -31
- package/package.json +6 -6
package/dist/StreamAdapter.d.ts
CHANGED
|
@@ -15,4 +15,14 @@ import type { StreamAdapterConfig } from './types.js';
|
|
|
15
15
|
* CF's applyChunkToParts() then builds UIMessage parts from these chunks.
|
|
16
16
|
* CF handles persistence, broadcasting, and resumability.
|
|
17
17
|
*/
|
|
18
|
+
type SSETextState = {
|
|
19
|
+
open: boolean;
|
|
20
|
+
canceledIds: Set<string>;
|
|
21
|
+
};
|
|
18
22
|
export declare function createSSEResponse(stream: AsyncGenerator<HarnessStreamPart>, config?: StreamAdapterConfig): Response;
|
|
23
|
+
/**
|
|
24
|
+
* Convert a single HarnessStreamPart to SSE data lines.
|
|
25
|
+
* Returns 0+ formatted SSE lines ("data: {...}\n\n").
|
|
26
|
+
*/
|
|
27
|
+
export declare function convertToSSELines(part: HarnessStreamPart, config: StreamAdapterConfig, textState: SSETextState): string[];
|
|
28
|
+
export {};
|
package/dist/StreamAdapter.js
CHANGED
|
@@ -1,38 +1,18 @@
|
|
|
1
1
|
import { DEFAULT_STREAM_CONFIG } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* Convert Kuralle's HarnessStreamPart generator into an SSE Response
|
|
4
|
-
* that CF's AIChatAgent._reply() can parse.
|
|
5
|
-
*
|
|
6
|
-
* CF's _streamSSEReply reads lines in the format:
|
|
7
|
-
* data: {"type":"text-start"}\n\n
|
|
8
|
-
* data: {"type":"text-delta","delta":"Hello"}\n\n
|
|
9
|
-
* data: {"type":"tool-input-available","toolCallId":"...","toolName":"...","input":{...}}\n\n
|
|
10
|
-
* data: {"type":"tool-output-available","toolCallId":"...","output":{...}}\n\n
|
|
11
|
-
* data: {"type":"data-handoff","data":{...}}\n\n
|
|
12
|
-
* data: {"type":"text-end"}\n\n
|
|
13
|
-
*
|
|
14
|
-
* CF's applyChunkToParts() then builds UIMessage parts from these chunks.
|
|
15
|
-
* CF handles persistence, broadcasting, and resumability.
|
|
16
|
-
*/
|
|
17
2
|
export function createSSEResponse(stream, config = DEFAULT_STREAM_CONFIG) {
|
|
18
3
|
const encoder = new TextEncoder();
|
|
19
|
-
|
|
4
|
+
const textState = { open: false, canceledIds: new Set() };
|
|
20
5
|
const body = new ReadableStream({
|
|
21
6
|
async start(controller) {
|
|
22
7
|
try {
|
|
23
8
|
for await (const part of stream) {
|
|
24
|
-
const lines = convertToSSELines(part, config,
|
|
9
|
+
const lines = convertToSSELines(part, config, textState);
|
|
25
10
|
for (const line of lines) {
|
|
26
|
-
// Track whether we've emitted text-start
|
|
27
|
-
if (line.includes('"text-start"'))
|
|
28
|
-
textStarted = true;
|
|
29
|
-
if (line.includes('"text-end"'))
|
|
30
|
-
textStarted = false;
|
|
31
11
|
controller.enqueue(encoder.encode(line));
|
|
32
12
|
}
|
|
33
13
|
}
|
|
34
14
|
// Ensure text is closed if still open
|
|
35
|
-
if (
|
|
15
|
+
if (textState.open) {
|
|
36
16
|
controller.enqueue(encoder.encode(`data: ${JSON.stringify({ type: 'text-end' })}\n\n`));
|
|
37
17
|
}
|
|
38
18
|
controller.close();
|
|
@@ -53,23 +33,39 @@ export function createSSEResponse(stream, config = DEFAULT_STREAM_CONFIG) {
|
|
|
53
33
|
* Convert a single HarnessStreamPart to SSE data lines.
|
|
54
34
|
* Returns 0+ formatted SSE lines ("data: {...}\n\n").
|
|
55
35
|
*/
|
|
56
|
-
function convertToSSELines(part, config,
|
|
36
|
+
export function convertToSSELines(part, config, textState) {
|
|
57
37
|
const lines = [];
|
|
58
38
|
const sse = (obj) => `data: ${JSON.stringify(obj)}\n\n`;
|
|
39
|
+
const closeTextSegment = () => {
|
|
40
|
+
if (!textState.open)
|
|
41
|
+
return;
|
|
42
|
+
lines.push(sse({ type: 'text-end' }));
|
|
43
|
+
textState.open = false;
|
|
44
|
+
};
|
|
59
45
|
switch (part.type) {
|
|
46
|
+
case 'text-start':
|
|
47
|
+
break;
|
|
48
|
+
case 'text-end':
|
|
49
|
+
closeTextSegment();
|
|
50
|
+
break;
|
|
51
|
+
case 'text-cancel': {
|
|
52
|
+
textState.canceledIds.add(part.id);
|
|
53
|
+
closeTextSegment();
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
60
56
|
case 'text-delta': {
|
|
61
|
-
|
|
62
|
-
|
|
57
|
+
if (textState.canceledIds.has(part.id)) {
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
if (!textState.open) {
|
|
63
61
|
lines.push(sse({ type: 'text-start' }));
|
|
62
|
+
textState.open = true;
|
|
64
63
|
}
|
|
65
|
-
lines.push(sse({ type: 'text-delta', delta: part.
|
|
64
|
+
lines.push(sse({ type: 'text-delta', delta: part.delta }));
|
|
66
65
|
break;
|
|
67
66
|
}
|
|
68
67
|
case 'tool-call': {
|
|
69
|
-
|
|
70
|
-
if (textStarted) {
|
|
71
|
-
lines.push(sse({ type: 'text-end' }));
|
|
72
|
-
}
|
|
68
|
+
closeTextSegment();
|
|
73
69
|
// CF expects tool-input-available with toolCallId, toolName, input
|
|
74
70
|
lines.push(sse({
|
|
75
71
|
type: 'tool-input-available',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kuralle-agents/cf-agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Kuralle agent integration for Cloudflare Workers with AIChatAgent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,18 +22,18 @@
|
|
|
22
22
|
"@cloudflare/ai-chat": "^0.1.8",
|
|
23
23
|
"ai": "^6.0.90",
|
|
24
24
|
"zod-to-json-schema": "^3.24.0",
|
|
25
|
-
"@kuralle-agents/core": "0.
|
|
26
|
-
"@kuralle-agents/realtime-audio": "0.
|
|
25
|
+
"@kuralle-agents/core": "0.4.0",
|
|
26
|
+
"@kuralle-agents/realtime-audio": "0.4.0"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"agents": "^0.11.5",
|
|
30
30
|
"zod": "^3.0.0",
|
|
31
|
-
"@kuralle-agents/voice-protocol": "0.
|
|
31
|
+
"@kuralle-agents/voice-protocol": "0.4.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"agents": "^0.11.5",
|
|
35
35
|
"typescript": "^5.7.0",
|
|
36
|
-
"@kuralle-agents/voice-protocol": "0.
|
|
36
|
+
"@kuralle-agents/voice-protocol": "0.4.0"
|
|
37
37
|
},
|
|
38
38
|
"engines": {
|
|
39
39
|
"node": ">=20"
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"prebuild": "rm -rf dist",
|
|
58
58
|
"build": "tsc",
|
|
59
59
|
"dev": "tsc --watch",
|
|
60
|
-
"test": "bun test src/voice/__tests__",
|
|
60
|
+
"test": "bun test src/voice/__tests__ src/__tests__",
|
|
61
61
|
"typecheck": "tsc --noEmit",
|
|
62
62
|
"clean": "rm -rf dist"
|
|
63
63
|
}
|