@inkeep/agents-run-api 0.1.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 +117 -0
- package/dist/AgentExecutionServer.d.ts +23 -0
- package/dist/AgentExecutionServer.d.ts.map +1 -0
- package/dist/AgentExecutionServer.js +32 -0
- package/dist/__tests__/setup.d.ts +4 -0
- package/dist/__tests__/setup.d.ts.map +1 -0
- package/dist/__tests__/setup.js +50 -0
- package/dist/__tests__/utils/testProject.d.ts +18 -0
- package/dist/__tests__/utils/testProject.d.ts.map +1 -0
- package/dist/__tests__/utils/testProject.js +26 -0
- package/dist/__tests__/utils/testRequest.d.ts +8 -0
- package/dist/__tests__/utils/testRequest.d.ts.map +1 -0
- package/dist/__tests__/utils/testRequest.js +32 -0
- package/dist/__tests__/utils/testTenant.d.ts +64 -0
- package/dist/__tests__/utils/testTenant.d.ts.map +1 -0
- package/dist/__tests__/utils/testTenant.js +71 -0
- package/dist/a2a/client.d.ts +182 -0
- package/dist/a2a/client.d.ts.map +1 -0
- package/dist/a2a/client.js +645 -0
- package/dist/a2a/handlers.d.ts +4 -0
- package/dist/a2a/handlers.d.ts.map +1 -0
- package/dist/a2a/handlers.js +657 -0
- package/dist/a2a/transfer.d.ts +18 -0
- package/dist/a2a/transfer.d.ts.map +1 -0
- package/dist/a2a/transfer.js +22 -0
- package/dist/a2a/types.d.ts +63 -0
- package/dist/a2a/types.d.ts.map +1 -0
- package/dist/a2a/types.js +1 -0
- package/dist/agents/Agent.d.ts +154 -0
- package/dist/agents/Agent.d.ts.map +1 -0
- package/dist/agents/Agent.js +1105 -0
- package/dist/agents/ModelFactory.d.ts +62 -0
- package/dist/agents/ModelFactory.d.ts.map +1 -0
- package/dist/agents/ModelFactory.js +208 -0
- package/dist/agents/SystemPromptBuilder.d.ts +14 -0
- package/dist/agents/SystemPromptBuilder.d.ts.map +1 -0
- package/dist/agents/SystemPromptBuilder.js +62 -0
- package/dist/agents/ToolSessionManager.d.ts +61 -0
- package/dist/agents/ToolSessionManager.d.ts.map +1 -0
- package/dist/agents/ToolSessionManager.js +143 -0
- package/dist/agents/artifactTools.d.ts +30 -0
- package/dist/agents/artifactTools.d.ts.map +1 -0
- package/dist/agents/artifactTools.js +463 -0
- package/dist/agents/generateTaskHandler.d.ts +41 -0
- package/dist/agents/generateTaskHandler.d.ts.map +1 -0
- package/dist/agents/generateTaskHandler.js +350 -0
- package/dist/agents/relationTools.d.ts +33 -0
- package/dist/agents/relationTools.d.ts.map +1 -0
- package/dist/agents/relationTools.js +245 -0
- package/dist/agents/types.d.ts +23 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +1 -0
- package/dist/agents/versions/V1Config.d.ts +21 -0
- package/dist/agents/versions/V1Config.d.ts.map +1 -0
- package/dist/agents/versions/V1Config.js +285 -0
- package/dist/app.d.ts +4 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +194 -0
- package/dist/data/agentGraph.d.ts +4 -0
- package/dist/data/agentGraph.d.ts.map +1 -0
- package/dist/data/agentGraph.js +73 -0
- package/dist/data/agents.d.ts +4 -0
- package/dist/data/agents.d.ts.map +1 -0
- package/dist/data/agents.js +73 -0
- package/dist/data/conversations.d.ts +59 -0
- package/dist/data/conversations.d.ts.map +1 -0
- package/dist/data/conversations.js +216 -0
- package/dist/data/db/clean.d.ts +6 -0
- package/dist/data/db/clean.d.ts.map +1 -0
- package/dist/data/db/clean.js +77 -0
- package/dist/data/db/dbClient.d.ts +3 -0
- package/dist/data/db/dbClient.d.ts.map +1 -0
- package/dist/data/db/dbClient.js +13 -0
- package/dist/env.d.ts +43 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +63 -0
- package/dist/handlers/executionHandler.d.ts +36 -0
- package/dist/handlers/executionHandler.d.ts.map +1 -0
- package/dist/handlers/executionHandler.js +402 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/instrumentation.d.ts +13 -0
- package/dist/instrumentation.d.ts.map +1 -0
- package/dist/instrumentation.js +66 -0
- package/dist/logger.d.ts +4 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +32 -0
- package/dist/middleware/api-key-auth.d.ts +22 -0
- package/dist/middleware/api-key-auth.d.ts.map +1 -0
- package/dist/middleware/api-key-auth.js +139 -0
- package/dist/middleware/index.d.ts +2 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +1 -0
- package/dist/openapi.d.ts +2 -0
- package/dist/openapi.d.ts.map +1 -0
- package/dist/openapi.js +36 -0
- package/dist/routes/agents.d.ts +4 -0
- package/dist/routes/agents.d.ts.map +1 -0
- package/dist/routes/agents.js +155 -0
- package/dist/routes/chat.d.ts +4 -0
- package/dist/routes/chat.d.ts.map +1 -0
- package/dist/routes/chat.js +308 -0
- package/dist/routes/chatDataStream.d.ts +4 -0
- package/dist/routes/chatDataStream.d.ts.map +1 -0
- package/dist/routes/chatDataStream.js +179 -0
- package/dist/routes/mcp.d.ts +4 -0
- package/dist/routes/mcp.d.ts.map +1 -0
- package/dist/routes/mcp.js +500 -0
- package/dist/tracer.d.ts +24 -0
- package/dist/tracer.d.ts.map +1 -0
- package/dist/tracer.js +97 -0
- package/dist/types/chat.d.ts +25 -0
- package/dist/types/chat.d.ts.map +1 -0
- package/dist/types/chat.js +1 -0
- package/dist/types/execution-context.d.ts +14 -0
- package/dist/types/execution-context.d.ts.map +1 -0
- package/dist/types/execution-context.js +14 -0
- package/dist/utils/agent-operations.d.ts +79 -0
- package/dist/utils/agent-operations.d.ts.map +1 -0
- package/dist/utils/agent-operations.js +67 -0
- package/dist/utils/artifact-component-schema.d.ts +29 -0
- package/dist/utils/artifact-component-schema.d.ts.map +1 -0
- package/dist/utils/artifact-component-schema.js +119 -0
- package/dist/utils/artifact-parser.d.ts +71 -0
- package/dist/utils/artifact-parser.d.ts.map +1 -0
- package/dist/utils/artifact-parser.js +251 -0
- package/dist/utils/cleanup.d.ts +19 -0
- package/dist/utils/cleanup.d.ts.map +1 -0
- package/dist/utils/cleanup.js +66 -0
- package/dist/utils/data-component-schema.d.ts +6 -0
- package/dist/utils/data-component-schema.d.ts.map +1 -0
- package/dist/utils/data-component-schema.js +43 -0
- package/dist/utils/graph-session.d.ts +200 -0
- package/dist/utils/graph-session.d.ts.map +1 -0
- package/dist/utils/graph-session.js +1009 -0
- package/dist/utils/incremental-stream-parser.d.ts +57 -0
- package/dist/utils/incremental-stream-parser.d.ts.map +1 -0
- package/dist/utils/incremental-stream-parser.js +287 -0
- package/dist/utils/response-formatter.d.ts +27 -0
- package/dist/utils/response-formatter.d.ts.map +1 -0
- package/dist/utils/response-formatter.js +160 -0
- package/dist/utils/stream-helpers.d.ts +162 -0
- package/dist/utils/stream-helpers.d.ts.map +1 -0
- package/dist/utils/stream-helpers.js +385 -0
- package/dist/utils/stream-registry.d.ts +18 -0
- package/dist/utils/stream-registry.d.ts.map +1 -0
- package/dist/utils/stream-registry.js +33 -0
- package/package.json +88 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import type { OperationEvent } from './agent-operations.js';
|
|
2
|
+
export interface StreamHelper {
|
|
3
|
+
writeRole(role?: string): Promise<void>;
|
|
4
|
+
writeContent(content: string): Promise<void>;
|
|
5
|
+
streamData(data: any): Promise<void>;
|
|
6
|
+
streamText(text: string, delayMs?: number): Promise<void>;
|
|
7
|
+
writeError(errorMessage: string): Promise<void>;
|
|
8
|
+
complete(): Promise<void>;
|
|
9
|
+
writeData(type: string, data: any): Promise<void>;
|
|
10
|
+
writeOperation(operation: OperationEvent): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export interface HonoSSEStream {
|
|
13
|
+
writeSSE(message: {
|
|
14
|
+
data: string;
|
|
15
|
+
event?: string;
|
|
16
|
+
id?: string;
|
|
17
|
+
}): Promise<void>;
|
|
18
|
+
sleep(ms: number): Promise<unknown>;
|
|
19
|
+
}
|
|
20
|
+
export interface ChatCompletionChunk {
|
|
21
|
+
id: string;
|
|
22
|
+
object: string;
|
|
23
|
+
created: number;
|
|
24
|
+
model: string;
|
|
25
|
+
choices: Array<{
|
|
26
|
+
index: number;
|
|
27
|
+
delta: {
|
|
28
|
+
role?: string;
|
|
29
|
+
content?: string;
|
|
30
|
+
};
|
|
31
|
+
finish_reason: string | null;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
export declare class SSEStreamHelper implements StreamHelper {
|
|
35
|
+
private stream;
|
|
36
|
+
private requestId;
|
|
37
|
+
private timestamp;
|
|
38
|
+
constructor(stream: HonoSSEStream, requestId: string, timestamp: number);
|
|
39
|
+
private get sessionId();
|
|
40
|
+
/**
|
|
41
|
+
* Write the initial role message
|
|
42
|
+
*/
|
|
43
|
+
writeRole(role?: string): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Write content chunk
|
|
46
|
+
*/
|
|
47
|
+
writeContent(content: string): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Stream text word by word with optional delay
|
|
50
|
+
*/
|
|
51
|
+
streamText(text: string, delayMs?: number): Promise<void>;
|
|
52
|
+
streamData(data: any): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Write error message
|
|
55
|
+
*/
|
|
56
|
+
writeError(errorMessage: string): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Write the final completion message
|
|
59
|
+
*/
|
|
60
|
+
writeCompletion(finishReason?: string): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Write the final [DONE] message
|
|
63
|
+
*/
|
|
64
|
+
writeDone(): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Complete the stream with finish reason and done message
|
|
67
|
+
*/
|
|
68
|
+
complete(finishReason?: string): Promise<void>;
|
|
69
|
+
writeData(type: string, data: any): Promise<void>;
|
|
70
|
+
writeOperation(operation: OperationEvent): Promise<void>;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Factory function to create SSE stream helper
|
|
74
|
+
*/
|
|
75
|
+
export declare function createSSEStreamHelper(stream: HonoSSEStream, requestId: string, timestamp: number): SSEStreamHelper;
|
|
76
|
+
export interface VercelUIWriter {
|
|
77
|
+
write(chunk: any): void;
|
|
78
|
+
merge(stream: any): void;
|
|
79
|
+
onError?: (error: Error) => void;
|
|
80
|
+
}
|
|
81
|
+
export declare class VercelDataStreamHelper implements StreamHelper {
|
|
82
|
+
private writer;
|
|
83
|
+
private textId;
|
|
84
|
+
private jsonBuffer;
|
|
85
|
+
private sentItems;
|
|
86
|
+
private completedItems;
|
|
87
|
+
private sessionId;
|
|
88
|
+
private static readonly MAX_BUFFER_SIZE;
|
|
89
|
+
private isCompleted;
|
|
90
|
+
constructor(writer: VercelUIWriter);
|
|
91
|
+
setSessionId(sessionId: string): void;
|
|
92
|
+
writeRole(_?: string): Promise<void>;
|
|
93
|
+
writeContent(content: string): Promise<void>;
|
|
94
|
+
streamText(text: string, delayMs?: number): Promise<void>;
|
|
95
|
+
writeData(type: 'operation', data: {
|
|
96
|
+
type: string;
|
|
97
|
+
ctx: any;
|
|
98
|
+
}): Promise<void>;
|
|
99
|
+
writeError(errorMessage: string): Promise<void>;
|
|
100
|
+
streamData(data: any): Promise<void>;
|
|
101
|
+
mergeStream(stream: any): Promise<void>;
|
|
102
|
+
writeCompletion(_finishReason?: string): Promise<void>;
|
|
103
|
+
writeDone(): Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* Complete the stream and clean up all memory
|
|
106
|
+
* This is the primary cleanup point to prevent memory leaks between requests
|
|
107
|
+
*/
|
|
108
|
+
complete(): Promise<void>;
|
|
109
|
+
/**
|
|
110
|
+
* Clean up all memory allocations
|
|
111
|
+
* Should be called when the stream helper is no longer needed
|
|
112
|
+
*/
|
|
113
|
+
cleanup(): void;
|
|
114
|
+
/**
|
|
115
|
+
* Check if the stream has been completed and cleaned up
|
|
116
|
+
*/
|
|
117
|
+
isStreamCompleted(): boolean;
|
|
118
|
+
/**
|
|
119
|
+
* Get current memory usage stats (for debugging/monitoring)
|
|
120
|
+
*/
|
|
121
|
+
getMemoryStats(): {
|
|
122
|
+
bufferSize: number;
|
|
123
|
+
sentItemsCount: number;
|
|
124
|
+
completedItemsCount: number;
|
|
125
|
+
isCompleted: boolean;
|
|
126
|
+
};
|
|
127
|
+
writeOperation(operation: OperationEvent): Promise<void>;
|
|
128
|
+
}
|
|
129
|
+
export declare function createVercelStreamHelper(writer: VercelUIWriter): VercelDataStreamHelper;
|
|
130
|
+
/**
|
|
131
|
+
* MCP Stream Helper that captures content instead of streaming
|
|
132
|
+
* Used for MCP tool responses which require a single response message
|
|
133
|
+
*/
|
|
134
|
+
export declare class MCPStreamHelper implements StreamHelper {
|
|
135
|
+
private capturedText;
|
|
136
|
+
private capturedData;
|
|
137
|
+
private capturedOperations;
|
|
138
|
+
private hasError;
|
|
139
|
+
private errorMessage;
|
|
140
|
+
private sessionId;
|
|
141
|
+
setSessionId(sessionId: string): void;
|
|
142
|
+
writeRole(_role?: string): Promise<void>;
|
|
143
|
+
writeContent(content: string): Promise<void>;
|
|
144
|
+
streamText(text: string, _delayMs?: number): Promise<void>;
|
|
145
|
+
streamData(data: any): Promise<void>;
|
|
146
|
+
writeData(_type: string, data: any): Promise<void>;
|
|
147
|
+
writeError(errorMessage: string): Promise<void>;
|
|
148
|
+
complete(): Promise<void>;
|
|
149
|
+
writeOperation(operation: OperationEvent): Promise<void>;
|
|
150
|
+
/**
|
|
151
|
+
* Get the captured response for MCP tool result
|
|
152
|
+
*/
|
|
153
|
+
getCapturedResponse(): {
|
|
154
|
+
text: string;
|
|
155
|
+
data: any[];
|
|
156
|
+
operations: OperationEvent[];
|
|
157
|
+
hasError: boolean;
|
|
158
|
+
errorMessage: string;
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
export declare function createMCPStreamHelper(): MCPStreamHelper;
|
|
162
|
+
//# sourceMappingURL=stream-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-helpers.d.ts","sourceRoot":"","sources":["../../src/utils/stream-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
import { parsePartialJson } from 'ai';
|
|
2
|
+
export class SSEStreamHelper {
|
|
3
|
+
stream;
|
|
4
|
+
requestId;
|
|
5
|
+
timestamp;
|
|
6
|
+
constructor(stream, requestId, timestamp) {
|
|
7
|
+
this.stream = stream;
|
|
8
|
+
this.requestId = requestId;
|
|
9
|
+
this.timestamp = timestamp;
|
|
10
|
+
}
|
|
11
|
+
get sessionId() {
|
|
12
|
+
return this.requestId;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Write the initial role message
|
|
16
|
+
*/
|
|
17
|
+
async writeRole(role = 'assistant') {
|
|
18
|
+
await this.stream.writeSSE({
|
|
19
|
+
data: JSON.stringify({
|
|
20
|
+
id: this.requestId,
|
|
21
|
+
object: 'chat.completion.chunk',
|
|
22
|
+
created: this.timestamp,
|
|
23
|
+
choices: [
|
|
24
|
+
{
|
|
25
|
+
index: 0,
|
|
26
|
+
delta: {
|
|
27
|
+
role,
|
|
28
|
+
},
|
|
29
|
+
finish_reason: null,
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
}),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Write content chunk
|
|
37
|
+
*/
|
|
38
|
+
async writeContent(content) {
|
|
39
|
+
await this.stream.writeSSE({
|
|
40
|
+
data: JSON.stringify({
|
|
41
|
+
id: this.requestId,
|
|
42
|
+
object: 'chat.completion.chunk',
|
|
43
|
+
created: this.timestamp,
|
|
44
|
+
choices: [
|
|
45
|
+
{
|
|
46
|
+
index: 0,
|
|
47
|
+
delta: {
|
|
48
|
+
content,
|
|
49
|
+
},
|
|
50
|
+
finish_reason: null,
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
}),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Stream text word by word with optional delay
|
|
58
|
+
*/
|
|
59
|
+
async streamText(text, delayMs = 100) {
|
|
60
|
+
const words = text.split(' ');
|
|
61
|
+
for (let i = 0; i < words.length; i++) {
|
|
62
|
+
await this.stream.sleep(delayMs);
|
|
63
|
+
const content = i === 0 ? words[i] : ` ${words[i]}`;
|
|
64
|
+
await this.writeContent(content);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async streamData(data) {
|
|
68
|
+
await this.writeContent(JSON.stringify(data));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Write error message
|
|
72
|
+
*/
|
|
73
|
+
async writeError(errorMessage) {
|
|
74
|
+
await this.writeContent(`\n\n${errorMessage}`);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Write the final completion message
|
|
78
|
+
*/
|
|
79
|
+
async writeCompletion(finishReason = 'stop') {
|
|
80
|
+
await this.stream.writeSSE({
|
|
81
|
+
data: JSON.stringify({
|
|
82
|
+
id: this.requestId,
|
|
83
|
+
object: 'chat.completion.chunk',
|
|
84
|
+
created: this.timestamp,
|
|
85
|
+
choices: [
|
|
86
|
+
{
|
|
87
|
+
index: 0,
|
|
88
|
+
delta: {},
|
|
89
|
+
finish_reason: finishReason,
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
}),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Write the final [DONE] message
|
|
97
|
+
*/
|
|
98
|
+
async writeDone() {
|
|
99
|
+
await this.stream.writeSSE({
|
|
100
|
+
data: '[DONE]',
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Complete the stream with finish reason and done message
|
|
105
|
+
*/
|
|
106
|
+
async complete(finishReason = 'stop') {
|
|
107
|
+
await this.writeCompletion(finishReason);
|
|
108
|
+
await this.writeDone();
|
|
109
|
+
}
|
|
110
|
+
async writeData(type, data) {
|
|
111
|
+
await this.stream.writeSSE({
|
|
112
|
+
data: JSON.stringify({
|
|
113
|
+
id: this.requestId,
|
|
114
|
+
object: 'chat.completion.chunk',
|
|
115
|
+
created: this.timestamp,
|
|
116
|
+
choices: [
|
|
117
|
+
{
|
|
118
|
+
index: 0,
|
|
119
|
+
delta: {
|
|
120
|
+
content: JSON.stringify({ type, data }),
|
|
121
|
+
},
|
|
122
|
+
finish_reason: null,
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
}),
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
async writeOperation(operation) {
|
|
129
|
+
await this.writeData('data-operation', operation);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Factory function to create SSE stream helper
|
|
134
|
+
*/
|
|
135
|
+
export function createSSEStreamHelper(stream, requestId, timestamp) {
|
|
136
|
+
return new SSEStreamHelper(stream, requestId, timestamp);
|
|
137
|
+
}
|
|
138
|
+
export class VercelDataStreamHelper {
|
|
139
|
+
writer;
|
|
140
|
+
textId = null;
|
|
141
|
+
jsonBuffer = '';
|
|
142
|
+
sentItems = new Map(); // Track what we've sent for each index
|
|
143
|
+
completedItems = new Set(); // Track completed items
|
|
144
|
+
sessionId = null;
|
|
145
|
+
// Memory management - focused on connection completion cleanup
|
|
146
|
+
static MAX_BUFFER_SIZE = 5 * 1024 * 1024; // 5MB limit (more generous during request)
|
|
147
|
+
isCompleted = false;
|
|
148
|
+
constructor(writer) {
|
|
149
|
+
this.writer = writer;
|
|
150
|
+
}
|
|
151
|
+
setSessionId(sessionId) {
|
|
152
|
+
this.sessionId = sessionId;
|
|
153
|
+
}
|
|
154
|
+
// This mirrors SSEStreamHelper API but outputs using Vercel AI SDK writer
|
|
155
|
+
async writeRole(_ = 'assistant') {
|
|
156
|
+
// noop
|
|
157
|
+
}
|
|
158
|
+
async writeContent(content) {
|
|
159
|
+
if (this.isCompleted) {
|
|
160
|
+
console.warn('Attempted to write content to completed stream');
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (!this.textId)
|
|
164
|
+
this.textId = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
165
|
+
// Only prevent catastrophic buffer growth during request
|
|
166
|
+
if (this.jsonBuffer.length + content.length > VercelDataStreamHelper.MAX_BUFFER_SIZE) {
|
|
167
|
+
// Keep more context since we're not cleaning up during request
|
|
168
|
+
const keepSize = Math.floor(VercelDataStreamHelper.MAX_BUFFER_SIZE * 0.8);
|
|
169
|
+
this.jsonBuffer = this.jsonBuffer.slice(-keepSize);
|
|
170
|
+
}
|
|
171
|
+
this.jsonBuffer += content;
|
|
172
|
+
const { value, state } = await parsePartialJson(this.jsonBuffer);
|
|
173
|
+
if (!['repaired-parse', 'successful-parse'].includes(state))
|
|
174
|
+
return;
|
|
175
|
+
if (!Array.isArray(value))
|
|
176
|
+
return;
|
|
177
|
+
for (let i = 0; i < value.length; i++) {
|
|
178
|
+
const { type, ...data } = value[i];
|
|
179
|
+
// TODO: Check for kind data and JSON.stringify
|
|
180
|
+
// Create a content hash to check if this item has changed
|
|
181
|
+
const currentContent = JSON.stringify(data);
|
|
182
|
+
const lastSentContent = this.sentItems.get(i);
|
|
183
|
+
// Only send if content has changed or is new
|
|
184
|
+
if (currentContent !== lastSentContent) {
|
|
185
|
+
const chunk = {
|
|
186
|
+
type: 'data-component',
|
|
187
|
+
id: `${this.textId}-${i}`,
|
|
188
|
+
data: { type, ...data },
|
|
189
|
+
};
|
|
190
|
+
this.writer.write(chunk);
|
|
191
|
+
this.sentItems.set(i, currentContent);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
async streamText(text, delayMs = 100) {
|
|
196
|
+
if (this.isCompleted) {
|
|
197
|
+
console.warn('Attempted to stream text to completed stream');
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
// For plain text, write directly to the stream as text chunks
|
|
201
|
+
if (!this.textId)
|
|
202
|
+
this.textId = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
203
|
+
const words = text.split(' ');
|
|
204
|
+
// ------------------------------
|
|
205
|
+
// New Vercel data-stream v2 format
|
|
206
|
+
// ------------------------------
|
|
207
|
+
// Emit "text-start" once at the beginning, followed by "text-delta" chunks
|
|
208
|
+
// for each word (with preceding space when necessary) and finish with
|
|
209
|
+
// a single "text-end".
|
|
210
|
+
const id = this.textId;
|
|
211
|
+
// Start - notify GraphSession that text streaming is starting
|
|
212
|
+
// Import is at the top of the file, we need to call it here
|
|
213
|
+
if (this.sessionId) {
|
|
214
|
+
const { graphSessionManager } = await import('./graph-session.js');
|
|
215
|
+
graphSessionManager.setTextStreaming(this.sessionId, true);
|
|
216
|
+
}
|
|
217
|
+
this.writer.write({
|
|
218
|
+
type: 'text-start',
|
|
219
|
+
id,
|
|
220
|
+
});
|
|
221
|
+
// Deltas (optionally throttled)
|
|
222
|
+
for (let i = 0; i < words.length; i++) {
|
|
223
|
+
if (delayMs > 0) {
|
|
224
|
+
await new Promise((r) => setTimeout(r, delayMs));
|
|
225
|
+
}
|
|
226
|
+
const delta = i === 0 ? words[i] : ` ${words[i]}`;
|
|
227
|
+
this.writer.write({
|
|
228
|
+
type: 'text-delta',
|
|
229
|
+
id,
|
|
230
|
+
delta,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
// End
|
|
234
|
+
this.writer.write({
|
|
235
|
+
type: 'text-end',
|
|
236
|
+
id,
|
|
237
|
+
});
|
|
238
|
+
// Notify GraphSession that text streaming has finished
|
|
239
|
+
if (this.sessionId) {
|
|
240
|
+
const { graphSessionManager } = await import('./graph-session.js');
|
|
241
|
+
graphSessionManager.setTextStreaming(this.sessionId, false);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
async writeData(type, data) {
|
|
245
|
+
if (this.isCompleted) {
|
|
246
|
+
console.warn('Attempted to write data to completed stream');
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
this.writer.write({
|
|
250
|
+
type: `${type}`,
|
|
251
|
+
data,
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
async writeError(errorMessage) {
|
|
255
|
+
if (this.isCompleted) {
|
|
256
|
+
console.warn('Attempted to write error to completed stream');
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
this.writer.write({
|
|
260
|
+
type: 'error',
|
|
261
|
+
errorText: errorMessage,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
async streamData(data) {
|
|
265
|
+
await this.writeContent(JSON.stringify(data));
|
|
266
|
+
}
|
|
267
|
+
async mergeStream(stream) {
|
|
268
|
+
if (this.isCompleted) {
|
|
269
|
+
console.warn('Attempted to merge stream to completed stream');
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
this.writer.merge(stream);
|
|
273
|
+
}
|
|
274
|
+
async writeCompletion(_finishReason = 'stop') {
|
|
275
|
+
// Completion is handled automatically by Vercel's writer
|
|
276
|
+
}
|
|
277
|
+
async writeDone() {
|
|
278
|
+
// Done is handled automatically by Vercel's writer
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Complete the stream and clean up all memory
|
|
282
|
+
* This is the primary cleanup point to prevent memory leaks between requests
|
|
283
|
+
*/
|
|
284
|
+
async complete() {
|
|
285
|
+
if (this.isCompleted)
|
|
286
|
+
return;
|
|
287
|
+
// Mark as completed to prevent further writes
|
|
288
|
+
this.isCompleted = true;
|
|
289
|
+
// Clean up all buffers and references
|
|
290
|
+
this.cleanup();
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Clean up all memory allocations
|
|
294
|
+
* Should be called when the stream helper is no longer needed
|
|
295
|
+
*/
|
|
296
|
+
cleanup() {
|
|
297
|
+
this.jsonBuffer = '';
|
|
298
|
+
this.sentItems.clear();
|
|
299
|
+
this.completedItems.clear();
|
|
300
|
+
this.textId = null;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Check if the stream has been completed and cleaned up
|
|
304
|
+
*/
|
|
305
|
+
isStreamCompleted() {
|
|
306
|
+
return this.isCompleted;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Get current memory usage stats (for debugging/monitoring)
|
|
310
|
+
*/
|
|
311
|
+
getMemoryStats() {
|
|
312
|
+
return {
|
|
313
|
+
bufferSize: this.jsonBuffer.length,
|
|
314
|
+
sentItemsCount: this.sentItems.size,
|
|
315
|
+
completedItemsCount: this.completedItems.size,
|
|
316
|
+
isCompleted: this.isCompleted,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
async writeOperation(operation) {
|
|
320
|
+
this.writer.write({
|
|
321
|
+
id: 'id' in operation ? operation.id : undefined,
|
|
322
|
+
type: 'data-operation',
|
|
323
|
+
data: operation,
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
export function createVercelStreamHelper(writer) {
|
|
328
|
+
return new VercelDataStreamHelper(writer);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* MCP Stream Helper that captures content instead of streaming
|
|
332
|
+
* Used for MCP tool responses which require a single response message
|
|
333
|
+
*/
|
|
334
|
+
export class MCPStreamHelper {
|
|
335
|
+
capturedText = '';
|
|
336
|
+
capturedData = [];
|
|
337
|
+
capturedOperations = [];
|
|
338
|
+
hasError = false;
|
|
339
|
+
errorMessage = '';
|
|
340
|
+
sessionId = null;
|
|
341
|
+
setSessionId(sessionId) {
|
|
342
|
+
this.sessionId = sessionId;
|
|
343
|
+
}
|
|
344
|
+
async writeRole(_role) {
|
|
345
|
+
// No-op for MCP
|
|
346
|
+
}
|
|
347
|
+
async writeContent(content) {
|
|
348
|
+
this.capturedText += content;
|
|
349
|
+
}
|
|
350
|
+
async streamText(text, _delayMs) {
|
|
351
|
+
// Capture text without streaming delay
|
|
352
|
+
this.capturedText += text;
|
|
353
|
+
}
|
|
354
|
+
async streamData(data) {
|
|
355
|
+
this.capturedData.push(data);
|
|
356
|
+
}
|
|
357
|
+
async writeData(_type, data) {
|
|
358
|
+
this.capturedData.push(data);
|
|
359
|
+
}
|
|
360
|
+
async writeError(errorMessage) {
|
|
361
|
+
this.hasError = true;
|
|
362
|
+
this.errorMessage = errorMessage;
|
|
363
|
+
}
|
|
364
|
+
async complete() {
|
|
365
|
+
// No-op for MCP
|
|
366
|
+
}
|
|
367
|
+
async writeOperation(operation) {
|
|
368
|
+
this.capturedOperations.push(operation);
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Get the captured response for MCP tool result
|
|
372
|
+
*/
|
|
373
|
+
getCapturedResponse() {
|
|
374
|
+
return {
|
|
375
|
+
text: this.capturedText,
|
|
376
|
+
data: this.capturedData,
|
|
377
|
+
operations: this.capturedOperations,
|
|
378
|
+
hasError: this.hasError,
|
|
379
|
+
errorMessage: this.errorMessage,
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
export function createMCPStreamHelper() {
|
|
384
|
+
return new MCPStreamHelper();
|
|
385
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { StreamHelper } from './stream-helpers.js';
|
|
2
|
+
/**
|
|
3
|
+
* Register a StreamHelper for a specific request ID
|
|
4
|
+
*/
|
|
5
|
+
export declare function registerStreamHelper(requestId: string, streamHelper: StreamHelper): void;
|
|
6
|
+
/**
|
|
7
|
+
* Get a StreamHelper by request ID
|
|
8
|
+
*/
|
|
9
|
+
export declare function getStreamHelper(requestId: string): StreamHelper | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* Unregister a StreamHelper for a specific request ID
|
|
12
|
+
*/
|
|
13
|
+
export declare function unregisterStreamHelper(requestId: string): void;
|
|
14
|
+
/**
|
|
15
|
+
* Get registry size (for debugging)
|
|
16
|
+
*/
|
|
17
|
+
export declare function getRegistrySize(): number;
|
|
18
|
+
//# sourceMappingURL=stream-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-registry.d.ts","sourceRoot":"","sources":["../../src/utils/stream-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAQxD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,GAAG,IAAI,CAOxF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAE3E;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAE9D;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global registry for StreamHelper instances
|
|
3
|
+
* Allows agents to access streamHelper via requestId across A2A boundaries
|
|
4
|
+
*/
|
|
5
|
+
const streamHelperRegistry = new Map();
|
|
6
|
+
/**
|
|
7
|
+
* Register a StreamHelper for a specific request ID
|
|
8
|
+
*/
|
|
9
|
+
export function registerStreamHelper(requestId, streamHelper) {
|
|
10
|
+
streamHelperRegistry.set(requestId, streamHelper);
|
|
11
|
+
// Set sessionId for stream helpers that support it
|
|
12
|
+
if ('setSessionId' in streamHelper && typeof streamHelper.setSessionId === 'function') {
|
|
13
|
+
streamHelper.setSessionId(requestId);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Get a StreamHelper by request ID
|
|
18
|
+
*/
|
|
19
|
+
export function getStreamHelper(requestId) {
|
|
20
|
+
return streamHelperRegistry.get(requestId);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Unregister a StreamHelper for a specific request ID
|
|
24
|
+
*/
|
|
25
|
+
export function unregisterStreamHelper(requestId) {
|
|
26
|
+
streamHelperRegistry.delete(requestId);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get registry size (for debugging)
|
|
30
|
+
*/
|
|
31
|
+
export function getRegistrySize() {
|
|
32
|
+
return streamHelperRegistry.size;
|
|
33
|
+
}
|