@stacknet/stacks 0.2.0 → 0.2.2
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 +136 -0
- package/dist/{billing-eQZIWeNW.d.cts → billing-cj0eSVrp.d.cts} +59 -1
- package/dist/{billing-eQZIWeNW.d.ts → billing-cj0eSVrp.d.ts} +59 -1
- package/dist/clients/index.cjs +4 -4
- package/dist/clients/index.d.cts +24 -1
- package/dist/clients/index.d.ts +24 -1
- package/dist/clients/index.js +4 -4
- package/dist/index.cjs +7 -7
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +7 -7
- package/dist/proxy/index.cjs +2 -2
- package/dist/proxy/index.js +2 -2
- package/dist/streaming/index.cjs +5 -5
- package/dist/streaming/index.js +5 -5
- package/dist/types/index.d.cts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/package.json +15 -13
- package/src/clients/agents.ts +0 -250
- package/src/clients/billing.ts +0 -197
- package/src/clients/coder.ts +0 -655
- package/src/clients/files.ts +0 -86
- package/src/clients/index.ts +0 -93
- package/src/clients/magma.ts +0 -299
- package/src/clients/mcp.ts +0 -208
- package/src/clients/network.ts +0 -118
- package/src/clients/points.ts +0 -403
- package/src/clients/skills.ts +0 -236
- package/src/clients/social.ts +0 -286
- package/src/clients/stack-management.ts +0 -279
- package/src/clients/task-network.ts +0 -303
- package/src/clients/user.ts +0 -84
- package/src/clients/widgets.ts +0 -171
- package/src/index.ts +0 -387
- package/src/managers/index.ts +0 -10
- package/src/managers/task-manager.ts +0 -332
- package/src/proxy/forwarder.ts +0 -235
- package/src/proxy/index.ts +0 -32
- package/src/proxy/route-handlers.ts +0 -1107
- package/src/streaming/component-stream.ts +0 -319
- package/src/streaming/index.ts +0 -21
- package/src/streaming/sse.ts +0 -266
- package/src/types/agent.ts +0 -108
- package/src/types/billing.ts +0 -121
- package/src/types/chat.ts +0 -58
- package/src/types/coder.ts +0 -345
- package/src/types/credential.ts +0 -111
- package/src/types/file.ts +0 -15
- package/src/types/imagination.ts +0 -50
- package/src/types/index.ts +0 -20
- package/src/types/mcp.ts +0 -35
- package/src/types/network.ts +0 -97
- package/src/types/points.ts +0 -250
- package/src/types/skill.ts +0 -107
- package/src/types/social.ts +0 -109
- package/src/types/stack.ts +0 -269
- package/src/types/task.ts +0 -41
- package/src/types/user.ts +0 -29
- package/src/types/widget.ts +0 -57
- package/src/utils/constants.ts +0 -26
- package/src/utils/errors.ts +0 -169
- package/src/utils/helpers.ts +0 -85
- package/src/utils/index.ts +0 -7
|
@@ -1,319 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Component Streaming - Artifact streaming adapter
|
|
3
|
-
*
|
|
4
|
-
* Converts tool call responses to artifact data stream format
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export interface DataStreamWriter {
|
|
8
|
-
write(data: { type: string; data: unknown; transient?: boolean }): void;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface ArtifactToolCall {
|
|
12
|
-
id: string;
|
|
13
|
-
type: 'function';
|
|
14
|
-
function: {
|
|
15
|
-
name: string;
|
|
16
|
-
arguments: string;
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface ArtifactToolResult {
|
|
21
|
-
type: string;
|
|
22
|
-
id?: string;
|
|
23
|
-
title?: string;
|
|
24
|
-
kind?: string;
|
|
25
|
-
content?: string;
|
|
26
|
-
message?: string;
|
|
27
|
-
[key: string]: unknown;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Artifact streaming adapter for AI SDK integration
|
|
32
|
-
*/
|
|
33
|
-
export class ComponentStreamAdapter {
|
|
34
|
-
constructor(private dataStream: DataStreamWriter) {}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Process tool calls and convert to artifact stream events
|
|
38
|
-
*/
|
|
39
|
-
processToolCalls(toolCalls: ArtifactToolCall[]): void {
|
|
40
|
-
if (!toolCalls || toolCalls.length === 0) return;
|
|
41
|
-
|
|
42
|
-
for (const toolCall of toolCalls) {
|
|
43
|
-
try {
|
|
44
|
-
const args = JSON.parse(toolCall.function.arguments);
|
|
45
|
-
const toolName = toolCall.function.name;
|
|
46
|
-
|
|
47
|
-
switch (toolName) {
|
|
48
|
-
case 'create_document':
|
|
49
|
-
this.handleCreateDocument(args, toolCall.id);
|
|
50
|
-
break;
|
|
51
|
-
case 'update_document':
|
|
52
|
-
this.handleUpdateDocument(args, toolCall.id);
|
|
53
|
-
break;
|
|
54
|
-
default:
|
|
55
|
-
console.log(`[ComponentStream] Unknown tool: ${toolName}`);
|
|
56
|
-
}
|
|
57
|
-
} catch (error) {
|
|
58
|
-
console.error('[ComponentStream] Error processing tool call:', error);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Process tool results
|
|
65
|
-
*/
|
|
66
|
-
processToolResult(result: ArtifactToolResult): void {
|
|
67
|
-
try {
|
|
68
|
-
if (result.type === 'artifact') {
|
|
69
|
-
this.handleArtifactResult(result);
|
|
70
|
-
} else if (result.type === 'artifact_update') {
|
|
71
|
-
this.handleArtifactUpdate(result);
|
|
72
|
-
}
|
|
73
|
-
} catch (error) {
|
|
74
|
-
console.error('[ComponentStream] Error processing tool result:', error);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Stream an artifact with metadata
|
|
80
|
-
*/
|
|
81
|
-
streamArtifact(artifact: {
|
|
82
|
-
id: string;
|
|
83
|
-
kind: string;
|
|
84
|
-
title: string;
|
|
85
|
-
content: string;
|
|
86
|
-
}): void {
|
|
87
|
-
this.dataStream.write({
|
|
88
|
-
type: 'data-kind',
|
|
89
|
-
data: artifact.kind,
|
|
90
|
-
transient: true,
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
this.dataStream.write({
|
|
94
|
-
type: 'data-id',
|
|
95
|
-
data: artifact.id,
|
|
96
|
-
transient: true,
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
this.dataStream.write({
|
|
100
|
-
type: 'data-title',
|
|
101
|
-
data: artifact.title,
|
|
102
|
-
transient: true,
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
this.dataStream.write({
|
|
106
|
-
type: 'data-clear',
|
|
107
|
-
data: null,
|
|
108
|
-
transient: true,
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
this.streamContent(artifact.content);
|
|
112
|
-
|
|
113
|
-
this.dataStream.write({
|
|
114
|
-
type: 'data-finish',
|
|
115
|
-
data: null,
|
|
116
|
-
transient: true,
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Stream a text delta
|
|
122
|
-
*/
|
|
123
|
-
streamTextDelta(delta: string): void {
|
|
124
|
-
this.dataStream.write({
|
|
125
|
-
type: 'data-textDelta',
|
|
126
|
-
data: delta,
|
|
127
|
-
transient: true,
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Stream content in chunks
|
|
133
|
-
*/
|
|
134
|
-
streamContent(content: string, chunkSize: number = 50): void {
|
|
135
|
-
const chunks = this.splitIntoChunks(content, chunkSize);
|
|
136
|
-
|
|
137
|
-
for (const chunk of chunks) {
|
|
138
|
-
this.dataStream.write({
|
|
139
|
-
type: 'data-textDelta',
|
|
140
|
-
data: chunk,
|
|
141
|
-
transient: true,
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Signal finish
|
|
148
|
-
*/
|
|
149
|
-
finish(): void {
|
|
150
|
-
this.dataStream.write({
|
|
151
|
-
type: 'data-finish',
|
|
152
|
-
data: null,
|
|
153
|
-
transient: true,
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
private handleCreateDocument(
|
|
158
|
-
args: { title: string; kind: string; content: string },
|
|
159
|
-
toolCallId: string
|
|
160
|
-
): void {
|
|
161
|
-
const { title, kind, content } = args;
|
|
162
|
-
const documentId = `doc_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
163
|
-
|
|
164
|
-
console.log(`[ComponentStream] Creating document: ${title} (${kind})`);
|
|
165
|
-
|
|
166
|
-
this.streamArtifact({
|
|
167
|
-
id: documentId,
|
|
168
|
-
kind,
|
|
169
|
-
title,
|
|
170
|
-
content,
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
this.dataStream.write({
|
|
174
|
-
type: 'tool-result',
|
|
175
|
-
data: {
|
|
176
|
-
toolCallId,
|
|
177
|
-
toolName: 'create_document',
|
|
178
|
-
result: {
|
|
179
|
-
id: documentId,
|
|
180
|
-
title,
|
|
181
|
-
kind,
|
|
182
|
-
message: 'Document created successfully',
|
|
183
|
-
},
|
|
184
|
-
},
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
private handleUpdateDocument(
|
|
189
|
-
args: { id: string; description: string; content: string },
|
|
190
|
-
toolCallId: string
|
|
191
|
-
): void {
|
|
192
|
-
const { id, description, content } = args;
|
|
193
|
-
|
|
194
|
-
console.log(`[ComponentStream] Updating document: ${id}`);
|
|
195
|
-
|
|
196
|
-
this.dataStream.write({
|
|
197
|
-
type: 'data-clear',
|
|
198
|
-
data: null,
|
|
199
|
-
transient: true,
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
this.streamContent(content);
|
|
203
|
-
|
|
204
|
-
this.dataStream.write({
|
|
205
|
-
type: 'data-finish',
|
|
206
|
-
data: null,
|
|
207
|
-
transient: true,
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
this.dataStream.write({
|
|
211
|
-
type: 'tool-result',
|
|
212
|
-
data: {
|
|
213
|
-
toolCallId,
|
|
214
|
-
toolName: 'update_document',
|
|
215
|
-
result: {
|
|
216
|
-
id,
|
|
217
|
-
message: `Document updated: ${description}`,
|
|
218
|
-
},
|
|
219
|
-
},
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
private handleArtifactResult(result: ArtifactToolResult): void {
|
|
224
|
-
const { id, title, kind, content } = result;
|
|
225
|
-
|
|
226
|
-
if (!id || !title || !kind || !content) {
|
|
227
|
-
console.error('[ComponentStream] Invalid artifact result:', result);
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
this.streamArtifact({ id, kind, title, content });
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
private handleArtifactUpdate(result: ArtifactToolResult): void {
|
|
235
|
-
const { content } = result;
|
|
236
|
-
|
|
237
|
-
if (!content) {
|
|
238
|
-
console.error('[ComponentStream] Invalid artifact update:', result);
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
this.dataStream.write({
|
|
243
|
-
type: 'data-clear',
|
|
244
|
-
data: null,
|
|
245
|
-
transient: true,
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
this.streamContent(content);
|
|
249
|
-
|
|
250
|
-
this.dataStream.write({
|
|
251
|
-
type: 'data-finish',
|
|
252
|
-
data: null,
|
|
253
|
-
transient: true,
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
private splitIntoChunks(content: string, chunkSize: number): string[] {
|
|
258
|
-
const chunks: string[] = [];
|
|
259
|
-
const words = content.split(' ');
|
|
260
|
-
let currentChunk = '';
|
|
261
|
-
|
|
262
|
-
for (let i = 0; i < words.length; i++) {
|
|
263
|
-
const word = i === 0 ? words[i] : ' ' + words[i];
|
|
264
|
-
|
|
265
|
-
if (currentChunk.length + word.length > chunkSize && currentChunk.length > 0) {
|
|
266
|
-
chunks.push(currentChunk);
|
|
267
|
-
currentChunk = word.trim();
|
|
268
|
-
} else {
|
|
269
|
-
currentChunk += word;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
if (currentChunk.length > 0) {
|
|
274
|
-
chunks.push(currentChunk);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
return chunks;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* Helper to detect tool calls in a message
|
|
283
|
-
*/
|
|
284
|
-
export function hasToolCalls(message: {
|
|
285
|
-
tool_calls?: unknown[];
|
|
286
|
-
}): boolean {
|
|
287
|
-
return !!(
|
|
288
|
-
message?.tool_calls &&
|
|
289
|
-
Array.isArray(message.tool_calls) &&
|
|
290
|
-
message.tool_calls.length > 0
|
|
291
|
-
);
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Helper to extract tool results from content
|
|
296
|
-
*/
|
|
297
|
-
export function extractToolResults(content: string): ArtifactToolResult[] {
|
|
298
|
-
try {
|
|
299
|
-
const parsed = JSON.parse(content);
|
|
300
|
-
if (
|
|
301
|
-
parsed.type &&
|
|
302
|
-
(parsed.type === 'artifact' || parsed.type === 'artifact_update')
|
|
303
|
-
) {
|
|
304
|
-
return [parsed];
|
|
305
|
-
}
|
|
306
|
-
} catch {
|
|
307
|
-
// Not JSON
|
|
308
|
-
}
|
|
309
|
-
return [];
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
/**
|
|
313
|
-
* Factory function
|
|
314
|
-
*/
|
|
315
|
-
export function createComponentStreamAdapter(
|
|
316
|
-
dataStream: DataStreamWriter
|
|
317
|
-
): ComponentStreamAdapter {
|
|
318
|
-
return new ComponentStreamAdapter(dataStream);
|
|
319
|
-
}
|
package/src/streaming/index.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @stacknet/stacks - Streaming utilities
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export {
|
|
6
|
-
parseSSEStream,
|
|
7
|
-
createSSEResponse,
|
|
8
|
-
SSEWriter,
|
|
9
|
-
createSSEWriter,
|
|
10
|
-
type SSEEvent,
|
|
11
|
-
} from './sse';
|
|
12
|
-
|
|
13
|
-
export {
|
|
14
|
-
ComponentStreamAdapter,
|
|
15
|
-
createComponentStreamAdapter,
|
|
16
|
-
hasToolCalls,
|
|
17
|
-
extractToolResults,
|
|
18
|
-
type DataStreamWriter,
|
|
19
|
-
type ArtifactToolCall,
|
|
20
|
-
type ArtifactToolResult,
|
|
21
|
-
} from './component-stream';
|
package/src/streaming/sse.ts
DELETED
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SSE (Server-Sent Events) streaming utilities
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { SSE_HEADERS } from '../utils/constants';
|
|
6
|
-
|
|
7
|
-
export interface SSEEvent {
|
|
8
|
-
event?: string;
|
|
9
|
-
data: unknown;
|
|
10
|
-
id?: string;
|
|
11
|
-
retry?: number;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/** Hard cap on the in-memory buffer used by `parseSSEStream`. A malicious
|
|
15
|
-
* or malfunctioning upstream that never emits a newline would otherwise
|
|
16
|
-
* grow the buffer until the process OOMs. 1 MiB is far beyond any real
|
|
17
|
-
* SSE event. */
|
|
18
|
-
const MAX_SSE_BUFFER_BYTES = 1024 * 1024;
|
|
19
|
-
|
|
20
|
-
/** SSE framing uses newlines as field separators; any `\r` or `\n` in
|
|
21
|
-
* `event`, `id`, or a string `data` value would let an untrusted caller
|
|
22
|
-
* inject additional SSE frames that the receiver would process as if
|
|
23
|
-
* they came from the server. Strip them. */
|
|
24
|
-
function stripCRLF(value: string): string {
|
|
25
|
-
// Replace CR/LF/LS/PS with a single space so the field remains
|
|
26
|
-
// structurally valid without carrying a frame separator.
|
|
27
|
-
return value.replace(/[\r\n\u2028\u2029]/g, ' ');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Parse SSE stream from a Response
|
|
32
|
-
*/
|
|
33
|
-
export async function* parseSSEStream(
|
|
34
|
-
response: Response
|
|
35
|
-
): AsyncIterable<SSEEvent> {
|
|
36
|
-
if (!response.body) {
|
|
37
|
-
throw new Error('Response body is null');
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const reader = response.body.getReader();
|
|
41
|
-
const decoder = new TextDecoder();
|
|
42
|
-
let buffer = '';
|
|
43
|
-
let currentEvent: Partial<SSEEvent> = {};
|
|
44
|
-
|
|
45
|
-
try {
|
|
46
|
-
while (true) {
|
|
47
|
-
const { done, value } = await reader.read();
|
|
48
|
-
if (done) break;
|
|
49
|
-
|
|
50
|
-
buffer += decoder.decode(value, { stream: true });
|
|
51
|
-
if (buffer.length > MAX_SSE_BUFFER_BYTES) {
|
|
52
|
-
throw new Error(
|
|
53
|
-
`SSE buffer exceeded ${MAX_SSE_BUFFER_BYTES} bytes without an event delimiter`,
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
const lines = buffer.split('\n');
|
|
57
|
-
buffer = lines.pop() || '';
|
|
58
|
-
|
|
59
|
-
for (const line of lines) {
|
|
60
|
-
if (line === '') {
|
|
61
|
-
// Empty line means end of event
|
|
62
|
-
if (currentEvent.data !== undefined) {
|
|
63
|
-
yield currentEvent as SSEEvent;
|
|
64
|
-
}
|
|
65
|
-
currentEvent = {};
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (line.startsWith(':')) {
|
|
70
|
-
// Comment, skip
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const colonIndex = line.indexOf(':');
|
|
75
|
-
if (colonIndex === -1) continue;
|
|
76
|
-
|
|
77
|
-
const field = line.slice(0, colonIndex);
|
|
78
|
-
const value = line.slice(colonIndex + 1).trimStart();
|
|
79
|
-
|
|
80
|
-
switch (field) {
|
|
81
|
-
case 'event':
|
|
82
|
-
currentEvent.event = value;
|
|
83
|
-
break;
|
|
84
|
-
case 'data':
|
|
85
|
-
try {
|
|
86
|
-
currentEvent.data = JSON.parse(value);
|
|
87
|
-
} catch {
|
|
88
|
-
currentEvent.data = value;
|
|
89
|
-
}
|
|
90
|
-
break;
|
|
91
|
-
case 'id':
|
|
92
|
-
currentEvent.id = value;
|
|
93
|
-
break;
|
|
94
|
-
case 'retry':
|
|
95
|
-
currentEvent.retry = parseInt(value, 10);
|
|
96
|
-
break;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Emit any remaining event
|
|
102
|
-
if (currentEvent.data !== undefined) {
|
|
103
|
-
yield currentEvent as SSEEvent;
|
|
104
|
-
}
|
|
105
|
-
} finally {
|
|
106
|
-
reader.releaseLock();
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/** Encode an SSE message safely — every field with CRLF stripped, data
|
|
111
|
-
* multi-line payloads split into repeated `data:` lines per the spec.
|
|
112
|
-
* Keeping this in one place lets both `createSSEResponse` and
|
|
113
|
-
* `SSEWriter.write` share exactly the same sanitization rules. */
|
|
114
|
-
function encodeEvent(event: SSEEvent): string {
|
|
115
|
-
let message = '';
|
|
116
|
-
|
|
117
|
-
if (event.event) {
|
|
118
|
-
message += `event: ${stripCRLF(event.event)}\n`;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (event.id) {
|
|
122
|
-
message += `id: ${stripCRLF(event.id)}\n`;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (event.retry !== undefined && Number.isFinite(event.retry)) {
|
|
126
|
-
// retry is numeric per the SSE spec — coerce defensively.
|
|
127
|
-
message += `retry: ${Math.floor(event.retry)}\n`;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const dataString =
|
|
131
|
-
typeof event.data === 'string'
|
|
132
|
-
? event.data
|
|
133
|
-
: JSON.stringify(event.data);
|
|
134
|
-
|
|
135
|
-
// Per the SSE spec, data may span multiple lines — each line is a
|
|
136
|
-
// separate `data:` field. This also means an embedded newline in a
|
|
137
|
-
// string payload can't be used to smuggle a new frame: the blank
|
|
138
|
-
// line at the end of the event is produced by us, not the caller.
|
|
139
|
-
for (const dataLine of dataString.split(/\r?\n/)) {
|
|
140
|
-
message += `data: ${dataLine}\n`;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
message += '\n';
|
|
144
|
-
return message;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Create an SSE Response from an async iterable
|
|
149
|
-
*/
|
|
150
|
-
export function createSSEResponse(
|
|
151
|
-
stream: AsyncIterable<SSEEvent>,
|
|
152
|
-
headers?: Record<string, string>
|
|
153
|
-
): Response {
|
|
154
|
-
const encoder = new TextEncoder();
|
|
155
|
-
|
|
156
|
-
const readableStream = new ReadableStream({
|
|
157
|
-
async start(controller) {
|
|
158
|
-
try {
|
|
159
|
-
for await (const event of stream) {
|
|
160
|
-
controller.enqueue(encoder.encode(encodeEvent(event)));
|
|
161
|
-
}
|
|
162
|
-
} catch (error) {
|
|
163
|
-
console.error('SSE stream error:', error);
|
|
164
|
-
} finally {
|
|
165
|
-
controller.close();
|
|
166
|
-
}
|
|
167
|
-
},
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
return new Response(readableStream, {
|
|
171
|
-
headers: {
|
|
172
|
-
...SSE_HEADERS,
|
|
173
|
-
...headers,
|
|
174
|
-
},
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Create an SSE writer for streaming events
|
|
180
|
-
*/
|
|
181
|
-
export class SSEWriter {
|
|
182
|
-
private encoder = new TextEncoder();
|
|
183
|
-
private controller: ReadableStreamDefaultController<Uint8Array> | null = null;
|
|
184
|
-
private stream: ReadableStream<Uint8Array>;
|
|
185
|
-
|
|
186
|
-
constructor() {
|
|
187
|
-
this.stream = new ReadableStream({
|
|
188
|
-
start: (controller) => {
|
|
189
|
-
this.controller = controller;
|
|
190
|
-
},
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Get the underlying ReadableStream
|
|
196
|
-
*/
|
|
197
|
-
getStream(): ReadableStream<Uint8Array> {
|
|
198
|
-
return this.stream;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Get a Response object for this stream
|
|
203
|
-
*/
|
|
204
|
-
getResponse(headers?: Record<string, string>): Response {
|
|
205
|
-
return new Response(this.stream, {
|
|
206
|
-
headers: {
|
|
207
|
-
...SSE_HEADERS,
|
|
208
|
-
...headers,
|
|
209
|
-
},
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Write an SSE event
|
|
215
|
-
*/
|
|
216
|
-
write(event: SSEEvent): void {
|
|
217
|
-
if (!this.controller) return;
|
|
218
|
-
this.controller.enqueue(this.encoder.encode(encodeEvent(event)));
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Write a data-only event
|
|
223
|
-
*/
|
|
224
|
-
writeData(data: unknown): void {
|
|
225
|
-
this.write({ data });
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Write a comment (for keep-alive)
|
|
230
|
-
*/
|
|
231
|
-
writeComment(comment: string): void {
|
|
232
|
-
if (!this.controller) return;
|
|
233
|
-
// Comments are a single `:` line followed by a blank line. Strip any
|
|
234
|
-
// CRLF so a caller can't close out the comment and smuggle a real
|
|
235
|
-
// event after it.
|
|
236
|
-
const safe = stripCRLF(comment);
|
|
237
|
-
this.controller.enqueue(this.encoder.encode(`: ${safe}\n\n`));
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* Close the stream
|
|
242
|
-
*/
|
|
243
|
-
close(): void {
|
|
244
|
-
if (this.controller) {
|
|
245
|
-
this.controller.close();
|
|
246
|
-
this.controller = null;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* Signal an error
|
|
252
|
-
*/
|
|
253
|
-
error(err: Error): void {
|
|
254
|
-
if (this.controller) {
|
|
255
|
-
this.controller.error(err);
|
|
256
|
-
this.controller = null;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Create an SSE writer
|
|
263
|
-
*/
|
|
264
|
-
export function createSSEWriter(): SSEWriter {
|
|
265
|
-
return new SSEWriter();
|
|
266
|
-
}
|
package/src/types/agent.ts
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent type definitions
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export interface Agent {
|
|
6
|
-
id: string;
|
|
7
|
-
name: string;
|
|
8
|
-
description?: string;
|
|
9
|
-
system_prompt?: string;
|
|
10
|
-
model?: string;
|
|
11
|
-
tools?: string[];
|
|
12
|
-
triggers?: AgentTrigger[];
|
|
13
|
-
workflow?: AgentWorkflow;
|
|
14
|
-
visibility?: 'public' | 'private' | 'template';
|
|
15
|
-
creator_mid?: string;
|
|
16
|
-
created_at?: string;
|
|
17
|
-
updated_at?: string;
|
|
18
|
-
enabled?: boolean;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface AgentTrigger {
|
|
22
|
-
type: 'webhook' | 'cron' | 'event';
|
|
23
|
-
config: Record<string, unknown>;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface AgentWorkflow {
|
|
27
|
-
nodes: AgentWorkflowNode[];
|
|
28
|
-
edges: AgentWorkflowEdge[];
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface AgentWorkflowNode {
|
|
32
|
-
id: string;
|
|
33
|
-
type: string;
|
|
34
|
-
position: { x: number; y: number };
|
|
35
|
-
data: Record<string, unknown>;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface AgentWorkflowEdge {
|
|
39
|
-
id: string;
|
|
40
|
-
source: string;
|
|
41
|
-
target: string;
|
|
42
|
-
sourceHandle?: string;
|
|
43
|
-
targetHandle?: string;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface AgentExecuteRequest {
|
|
47
|
-
input?: string;
|
|
48
|
-
context?: Record<string, unknown>;
|
|
49
|
-
stream?: boolean;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export interface AgentExecuteResponse {
|
|
53
|
-
id: string;
|
|
54
|
-
output: string;
|
|
55
|
-
status: 'success' | 'error';
|
|
56
|
-
metadata?: Record<string, unknown>;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export interface AgentsListResponse {
|
|
60
|
-
agents: Agent[];
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export interface AgentResponse {
|
|
64
|
-
agent?: Agent;
|
|
65
|
-
id?: string;
|
|
66
|
-
name?: string;
|
|
67
|
-
error?: string;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export interface AgentCreateInput {
|
|
71
|
-
name: string;
|
|
72
|
-
description?: string;
|
|
73
|
-
system_prompt?: string;
|
|
74
|
-
model?: string;
|
|
75
|
-
tools?: string[];
|
|
76
|
-
triggers?: AgentTrigger[];
|
|
77
|
-
workflow?: AgentWorkflow;
|
|
78
|
-
visibility?: 'public' | 'private' | 'template';
|
|
79
|
-
created_by?: string;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export interface AgentUpdateInput {
|
|
83
|
-
name?: string;
|
|
84
|
-
description?: string;
|
|
85
|
-
system_prompt?: string;
|
|
86
|
-
model?: string;
|
|
87
|
-
tools?: string[];
|
|
88
|
-
triggers?: AgentTrigger[];
|
|
89
|
-
workflow?: AgentWorkflow;
|
|
90
|
-
visibility?: 'public' | 'private' | 'template';
|
|
91
|
-
enabled?: boolean;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export interface AgentFromPromptInput {
|
|
95
|
-
prompt: string;
|
|
96
|
-
created_by?: string;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export interface AgentsClientConfig {
|
|
100
|
-
baseUrl?: string;
|
|
101
|
-
/** JWT auth token for authenticated requests */
|
|
102
|
-
authToken?: string;
|
|
103
|
-
/**
|
|
104
|
-
* Use the coprocessor API (/cpx/agent/agents) instead of legacy (/agents).
|
|
105
|
-
* Defaults to true. Set to false for backwards compatibility.
|
|
106
|
-
*/
|
|
107
|
-
useCpxApi?: boolean;
|
|
108
|
-
}
|