@neta-art/cohub 1.9.0 → 1.10.1
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 +6 -105
- package/dist/chunks/environment.js +33 -0
- package/dist/chunks/http.d.ts +1615 -0
- package/dist/chunks/http.js +1919 -0
- package/dist/chunks/websocket.d.ts +266 -0
- package/dist/chunks/websocket.js +655 -0
- package/dist/debugger.d.ts +198 -0
- package/dist/debugger.js +1120 -0
- package/dist/http.d.ts +3 -32
- package/dist/http.js +2 -48
- package/dist/index.d.ts +35 -14
- package/dist/index.js +105 -8
- package/dist/websocket.d.ts +2 -141
- package/dist/websocket.js +2 -628
- package/package.json +11 -7
- package/dist/apis/channels.d.ts +0 -13
- package/dist/apis/channels.js +0 -24
- package/dist/apis/cron-jobs.d.ts +0 -18
- package/dist/apis/cron-jobs.js +0 -25
- package/dist/apis/explore.d.ts +0 -9
- package/dist/apis/explore.js +0 -9
- package/dist/apis/generations.d.ts +0 -7
- package/dist/apis/generations.js +0 -13
- package/dist/apis/invitations.d.ts +0 -20
- package/dist/apis/invitations.js +0 -36
- package/dist/apis/models.d.ts +0 -10
- package/dist/apis/models.js +0 -13
- package/dist/apis/prompts.d.ts +0 -9
- package/dist/apis/prompts.js +0 -16
- package/dist/apis/search.d.ts +0 -10
- package/dist/apis/search.js +0 -14
- package/dist/apis/session-access.d.ts +0 -13
- package/dist/apis/session-access.js +0 -19
- package/dist/apis/spaces.d.ts +0 -371
- package/dist/apis/spaces.js +0 -766
- package/dist/apis/tasks.d.ts +0 -13
- package/dist/apis/tasks.js +0 -18
- package/dist/apis/user.d.ts +0 -27
- package/dist/apis/user.js +0 -71
- package/dist/client.d.ts +0 -33
- package/dist/client.js +0 -103
- package/dist/environment.d.ts +0 -22
- package/dist/environment.js +0 -37
- package/dist/realtime.d.ts +0 -2
- package/dist/realtime.js +0 -8
- package/dist/session-generation-stream.d.ts +0 -114
- package/dist/session-generation-stream.js +0 -514
- package/dist/session-patch-reducer.d.ts +0 -61
- package/dist/session-patch-reducer.js +0 -432
- package/dist/transport.d.ts +0 -40
- package/dist/transport.js +0 -78
- package/dist/types.d.ts +0 -535
- package/dist/types.js +0 -1
|
@@ -1,514 +0,0 @@
|
|
|
1
|
-
import { ensureRealtimeConnected } from "./realtime.js";
|
|
2
|
-
import { SessionPatchReducer, } from "./session-patch-reducer.js";
|
|
3
|
-
const isRecord = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
4
|
-
const isContentBlockArray = (value) => Array.isArray(value) &&
|
|
5
|
-
value.every((item) => isRecord(item) && typeof item.type === "string");
|
|
6
|
-
const stringField = (record, key) => {
|
|
7
|
-
const value = record[key];
|
|
8
|
-
return typeof value === "string" ? value : null;
|
|
9
|
-
};
|
|
10
|
-
const numberField = (record, key) => {
|
|
11
|
-
const value = record[key];
|
|
12
|
-
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
13
|
-
};
|
|
14
|
-
const getMessageKind = (message) => {
|
|
15
|
-
const kind = message.meta?.messageKind;
|
|
16
|
-
return typeof kind === "string" ? kind : null;
|
|
17
|
-
};
|
|
18
|
-
export function parseAssistantMessageCommit(message) {
|
|
19
|
-
if (message.role !== "assistant") {
|
|
20
|
-
return { kind: "ignored", message, isFinal: false };
|
|
21
|
-
}
|
|
22
|
-
const kind = getMessageKind(message);
|
|
23
|
-
if (kind === "assistant_intermediate") {
|
|
24
|
-
return { kind: "intermediate", message, isFinal: false };
|
|
25
|
-
}
|
|
26
|
-
if (kind === "assistant_final") {
|
|
27
|
-
return { kind: "final", message, isFinal: true };
|
|
28
|
-
}
|
|
29
|
-
if (kind === "assistant_error") {
|
|
30
|
-
return { kind: "error", message, isFinal: true };
|
|
31
|
-
}
|
|
32
|
-
return { kind: "ignored", message, isFinal: false };
|
|
33
|
-
}
|
|
34
|
-
function cloneContentBlock(block) {
|
|
35
|
-
return structuredClone(block);
|
|
36
|
-
}
|
|
37
|
-
function getStreamIndex(block) {
|
|
38
|
-
const value = block._meta?.streamIndex;
|
|
39
|
-
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
40
|
-
}
|
|
41
|
-
function findMergeTargetIndex(result, block) {
|
|
42
|
-
const streamIndex = getStreamIndex(block);
|
|
43
|
-
if (streamIndex != null) {
|
|
44
|
-
return result.findIndex((existing) => existing.type === block.type && getStreamIndex(existing) === streamIndex);
|
|
45
|
-
}
|
|
46
|
-
if (block.type === "tool_use") {
|
|
47
|
-
return result.findIndex((existing) => existing.type === "tool_use" && existing.id === block.id);
|
|
48
|
-
}
|
|
49
|
-
if (block.type === "tool_result") {
|
|
50
|
-
return result.findIndex((existing) => existing.type === "tool_result" &&
|
|
51
|
-
existing.tool_use_id === block.tool_use_id);
|
|
52
|
-
}
|
|
53
|
-
return -1;
|
|
54
|
-
}
|
|
55
|
-
function mergeStreamingDeltaBlocks(existing, delta) {
|
|
56
|
-
if (delta.length === 0)
|
|
57
|
-
return existing;
|
|
58
|
-
const result = existing.map(cloneContentBlock);
|
|
59
|
-
for (const block of delta) {
|
|
60
|
-
const targetIndex = findMergeTargetIndex(result, block);
|
|
61
|
-
if (targetIndex === -1) {
|
|
62
|
-
result.push(cloneContentBlock(block));
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
const target = result[targetIndex];
|
|
66
|
-
if (block.type === "text" && target?.type === "text") {
|
|
67
|
-
target.text += block.text;
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
if (block.type === "thinking" && target?.type === "thinking") {
|
|
71
|
-
target.thinking += block.thinking;
|
|
72
|
-
if (block.signature)
|
|
73
|
-
target.signature = block.signature;
|
|
74
|
-
if (block._meta)
|
|
75
|
-
target._meta = { ...(target._meta ?? {}), ...block._meta };
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
result[targetIndex] = Object.assign(target ?? {}, cloneContentBlock(block));
|
|
79
|
-
}
|
|
80
|
-
return result;
|
|
81
|
-
}
|
|
82
|
-
function parseSnapshotMessage(value) {
|
|
83
|
-
if (!isRecord(value) || !isContentBlockArray(value.content))
|
|
84
|
-
return null;
|
|
85
|
-
return {
|
|
86
|
-
messageId: stringField(value, "messageId"),
|
|
87
|
-
messageOrdinal: numberField(value, "messageOrdinal"),
|
|
88
|
-
content: value.content,
|
|
89
|
-
...(typeof value.id === "string" ? { id: value.id } : {}),
|
|
90
|
-
...(typeof value.sessionId === "string" ? { sessionId: value.sessionId } : {}),
|
|
91
|
-
...(value.role === "user" ||
|
|
92
|
-
value.role === "assistant" ||
|
|
93
|
-
value.role === "system"
|
|
94
|
-
? { role: value.role }
|
|
95
|
-
: {}),
|
|
96
|
-
...(typeof value.text === "string" ? { text: value.text } : {}),
|
|
97
|
-
...(typeof value.provider === "string" ? { provider: value.provider } : {}),
|
|
98
|
-
...(typeof value.model === "string" ? { model: value.model } : {}),
|
|
99
|
-
...(typeof value.stopReason === "string"
|
|
100
|
-
? { stopReason: value.stopReason }
|
|
101
|
-
: {}),
|
|
102
|
-
...(typeof value.errorMessage === "string"
|
|
103
|
-
? { errorMessage: value.errorMessage }
|
|
104
|
-
: {}),
|
|
105
|
-
...(isRecord(value.usage) ? { usage: value.usage } : {}),
|
|
106
|
-
...(typeof value.toolCallsObjectKey === "string"
|
|
107
|
-
? { toolCallsObjectKey: value.toolCallsObjectKey }
|
|
108
|
-
: {}),
|
|
109
|
-
...(isRecord(value.meta) ? { meta: value.meta } : {}),
|
|
110
|
-
...(typeof value.createdAt === "string" ? { createdAt: value.createdAt } : {}),
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
function messageRecordToIntermediate(message) {
|
|
114
|
-
if (!isContentBlockArray(message.content) || message.content.length === 0) {
|
|
115
|
-
return null;
|
|
116
|
-
}
|
|
117
|
-
const meta = isRecord(message.meta) ? message.meta : {};
|
|
118
|
-
return {
|
|
119
|
-
id: message.id,
|
|
120
|
-
sessionId: message.sessionId,
|
|
121
|
-
role: message.role,
|
|
122
|
-
messageId: typeof meta.streamMessageId === "string"
|
|
123
|
-
? meta.streamMessageId
|
|
124
|
-
: message.id ?? null,
|
|
125
|
-
messageOrdinal: typeof meta.messageOrdinal === "number" ? meta.messageOrdinal : null,
|
|
126
|
-
content: message.content,
|
|
127
|
-
text: message.text,
|
|
128
|
-
provider: message.provider,
|
|
129
|
-
model: message.model,
|
|
130
|
-
stopReason: message.stopReason,
|
|
131
|
-
errorMessage: message.errorMessage,
|
|
132
|
-
usage: message.usage,
|
|
133
|
-
meta: message.meta,
|
|
134
|
-
createdAt: message.createdAt,
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
function resolveStreamMessageId(input) {
|
|
138
|
-
if (input.messageId?.trim())
|
|
139
|
-
return input.messageId.trim();
|
|
140
|
-
if (input.messageOrdinal == null)
|
|
141
|
-
return null;
|
|
142
|
-
if (input.turnId?.trim()) {
|
|
143
|
-
return `turn:${input.turnId.trim()}:assistant:${input.messageOrdinal}`;
|
|
144
|
-
}
|
|
145
|
-
return `session:${input.sessionId}:assistant:${input.messageOrdinal}:${input.anchorUserMessageId ?? "unknown"}`;
|
|
146
|
-
}
|
|
147
|
-
function getTurnIdFromMessage(message) {
|
|
148
|
-
const turnId = message.meta?.turnId;
|
|
149
|
-
return typeof turnId === "string" ? turnId : null;
|
|
150
|
-
}
|
|
151
|
-
export class SessionGenerationStreamClient {
|
|
152
|
-
websocketClient;
|
|
153
|
-
spaceId;
|
|
154
|
-
sessionId;
|
|
155
|
-
reducer = new SessionPatchReducer();
|
|
156
|
-
messageId = null;
|
|
157
|
-
messageOrdinal = null;
|
|
158
|
-
intermediateMessages = [];
|
|
159
|
-
progressState = null;
|
|
160
|
-
constructor(websocketClient, spaceId, sessionId) {
|
|
161
|
-
this.websocketClient = websocketClient;
|
|
162
|
-
this.spaceId = spaceId;
|
|
163
|
-
this.sessionId = sessionId;
|
|
164
|
-
}
|
|
165
|
-
subscribe(handlers) {
|
|
166
|
-
if (!this.websocketClient) {
|
|
167
|
-
throw new Error("realtime transport is not configured for this client");
|
|
168
|
-
}
|
|
169
|
-
ensureRealtimeConnected(this.websocketClient);
|
|
170
|
-
const stream = new SessionGenerationStreamClient(this.websocketClient, this.spaceId, this.sessionId);
|
|
171
|
-
const unsubscribe = this.websocketClient.on("event", (event) => {
|
|
172
|
-
if (event.spaceId !== this.spaceId || event.sessionId !== this.sessionId) {
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
stream.handleEvent(event, handlers);
|
|
176
|
-
});
|
|
177
|
-
return () => unsubscribe();
|
|
178
|
-
}
|
|
179
|
-
emit(handlers, event) {
|
|
180
|
-
handlers.event?.(event);
|
|
181
|
-
if (event.type === "state")
|
|
182
|
-
handlers.state?.(event);
|
|
183
|
-
if (event.type === "commit")
|
|
184
|
-
handlers.commit?.(event);
|
|
185
|
-
if (event.type === "finalized")
|
|
186
|
-
handlers.finalized?.(event);
|
|
187
|
-
if (event.type === "turn_updated")
|
|
188
|
-
handlers.turnUpdated?.(event);
|
|
189
|
-
if (event.type === "error")
|
|
190
|
-
handlers.error?.(event);
|
|
191
|
-
if (event.type === "out_of_sync")
|
|
192
|
-
handlers.outOfSync?.(event);
|
|
193
|
-
}
|
|
194
|
-
resetCurrentMessage() {
|
|
195
|
-
this.messageId = null;
|
|
196
|
-
this.messageOrdinal = null;
|
|
197
|
-
this.progressState = null;
|
|
198
|
-
}
|
|
199
|
-
appendCurrentMessage(state) {
|
|
200
|
-
if (state.contentBlocks.length === 0)
|
|
201
|
-
return;
|
|
202
|
-
this.addIntermediateMessage({
|
|
203
|
-
messageId: this.messageId,
|
|
204
|
-
messageOrdinal: this.messageOrdinal,
|
|
205
|
-
content: state.contentBlocks,
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
addIntermediateMessage(message) {
|
|
209
|
-
const index = this.intermediateMessages.findIndex((existing) => {
|
|
210
|
-
if (message.messageId && existing.messageId) {
|
|
211
|
-
return existing.messageId === message.messageId;
|
|
212
|
-
}
|
|
213
|
-
return (message.messageOrdinal !== null &&
|
|
214
|
-
existing.messageOrdinal === message.messageOrdinal);
|
|
215
|
-
});
|
|
216
|
-
if (index < 0) {
|
|
217
|
-
this.intermediateMessages = [...this.intermediateMessages, message];
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
this.intermediateMessages = this.intermediateMessages.map((existing, i) => i === index ? { ...existing, ...message } : existing);
|
|
221
|
-
}
|
|
222
|
-
handleAppliedState(handlers, source, result, rawEvent, messageId, messageOrdinal) {
|
|
223
|
-
if (!result.applied) {
|
|
224
|
-
this.emit(handlers, {
|
|
225
|
-
type: "out_of_sync",
|
|
226
|
-
source: source === "progress" ? "patch" : source,
|
|
227
|
-
reason: result.reason,
|
|
228
|
-
state: result.state,
|
|
229
|
-
rawEvent,
|
|
230
|
-
});
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
this.progressState = result.state;
|
|
234
|
-
this.messageId = messageId;
|
|
235
|
-
this.messageOrdinal = messageOrdinal;
|
|
236
|
-
this.emit(handlers, {
|
|
237
|
-
type: "state",
|
|
238
|
-
source,
|
|
239
|
-
state: result.state,
|
|
240
|
-
messageId,
|
|
241
|
-
messageOrdinal,
|
|
242
|
-
intermediateMessages: [...this.intermediateMessages],
|
|
243
|
-
rawEvent,
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
prepareMessageBoundary(input) {
|
|
247
|
-
const current = this.progressState ??
|
|
248
|
-
this.reducer.get({
|
|
249
|
-
spaceId: this.spaceId,
|
|
250
|
-
sessionId: this.sessionId,
|
|
251
|
-
});
|
|
252
|
-
const nextMessageId = resolveStreamMessageId({
|
|
253
|
-
sessionId: this.sessionId,
|
|
254
|
-
turnId: input.turnId,
|
|
255
|
-
anchorUserMessageId: input.anchorUserMessageId,
|
|
256
|
-
messageId: input.messageId,
|
|
257
|
-
messageOrdinal: input.messageOrdinal,
|
|
258
|
-
});
|
|
259
|
-
const differentTurn = Boolean(current.turnId && input.turnId && current.turnId !== input.turnId);
|
|
260
|
-
const messageChanged = Boolean(nextMessageId &&
|
|
261
|
-
current.contentBlocks.length > 0 &&
|
|
262
|
-
this.messageId &&
|
|
263
|
-
nextMessageId !== this.messageId);
|
|
264
|
-
if (differentTurn) {
|
|
265
|
-
this.intermediateMessages = [];
|
|
266
|
-
this.resetCurrentMessage();
|
|
267
|
-
this.reducer.start({
|
|
268
|
-
spaceId: this.spaceId,
|
|
269
|
-
sessionId: this.sessionId,
|
|
270
|
-
turnId: input.turnId,
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
else if (messageChanged) {
|
|
274
|
-
this.appendCurrentMessage(current);
|
|
275
|
-
this.resetCurrentMessage();
|
|
276
|
-
this.reducer.start({
|
|
277
|
-
spaceId: this.spaceId,
|
|
278
|
-
sessionId: this.sessionId,
|
|
279
|
-
turnId: input.turnId ?? current.turnId,
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
return nextMessageId;
|
|
283
|
-
}
|
|
284
|
-
handleSnapshot(event, handlers) {
|
|
285
|
-
const payload = event.payload;
|
|
286
|
-
const current = isRecord(payload.current) ? payload.current : null;
|
|
287
|
-
const content = current ? current.content : null;
|
|
288
|
-
const seq = typeof payload.seq === "number" ? payload.seq : null;
|
|
289
|
-
if (!current || !isContentBlockArray(content) || seq === null) {
|
|
290
|
-
this.emit(handlers, {
|
|
291
|
-
type: "out_of_sync",
|
|
292
|
-
source: "snapshot",
|
|
293
|
-
reason: "invalid",
|
|
294
|
-
state: this.reducer.get({ spaceId: this.spaceId, sessionId: this.sessionId }),
|
|
295
|
-
rawEvent: event,
|
|
296
|
-
});
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
|
-
const turnId = typeof payload.turnId === "string" ? payload.turnId : null;
|
|
300
|
-
const anchorUserMessageId = typeof payload.anchorUserMessageId === "string"
|
|
301
|
-
? payload.anchorUserMessageId
|
|
302
|
-
: null;
|
|
303
|
-
const messageOrdinal = numberField(current, "messageOrdinal");
|
|
304
|
-
const messageId = this.prepareMessageBoundary({
|
|
305
|
-
turnId,
|
|
306
|
-
messageId: stringField(current, "messageId"),
|
|
307
|
-
messageOrdinal,
|
|
308
|
-
anchorUserMessageId,
|
|
309
|
-
});
|
|
310
|
-
this.intermediateMessages = Array.isArray(payload.intermediateMessages)
|
|
311
|
-
? payload.intermediateMessages
|
|
312
|
-
.map(parseSnapshotMessage)
|
|
313
|
-
.filter((message) => message !== null)
|
|
314
|
-
: [];
|
|
315
|
-
const result = this.reducer.applySnapshot({
|
|
316
|
-
spaceId: this.spaceId,
|
|
317
|
-
sessionId: this.sessionId,
|
|
318
|
-
turnId,
|
|
319
|
-
seq,
|
|
320
|
-
contentBlocks: content,
|
|
321
|
-
anchorUserMessageId,
|
|
322
|
-
appendPath: stringField(current, "appendPath"),
|
|
323
|
-
});
|
|
324
|
-
this.handleAppliedState(handlers, "snapshot", result, event, messageId, messageOrdinal);
|
|
325
|
-
}
|
|
326
|
-
handlePatch(event, handlers) {
|
|
327
|
-
const payload = event.payload;
|
|
328
|
-
const seq = typeof payload.seq === "number" ? payload.seq : null;
|
|
329
|
-
const baseSeq = typeof payload.baseSeq === "number" ? payload.baseSeq : null;
|
|
330
|
-
if (seq === null || baseSeq === null || !Array.isArray(payload.ops)) {
|
|
331
|
-
this.emit(handlers, {
|
|
332
|
-
type: "out_of_sync",
|
|
333
|
-
source: "patch",
|
|
334
|
-
reason: "invalid",
|
|
335
|
-
state: this.reducer.get({ spaceId: this.spaceId, sessionId: this.sessionId }),
|
|
336
|
-
rawEvent: event,
|
|
337
|
-
});
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
const turnId = typeof payload.turnId === "string" ? payload.turnId : null;
|
|
341
|
-
const anchorUserMessageId = typeof payload.anchorUserMessageId === "string"
|
|
342
|
-
? payload.anchorUserMessageId
|
|
343
|
-
: null;
|
|
344
|
-
const messageOrdinal = typeof payload.messageOrdinal === "number" ? payload.messageOrdinal : null;
|
|
345
|
-
const messageId = this.prepareMessageBoundary({
|
|
346
|
-
turnId,
|
|
347
|
-
messageId: typeof payload.messageId === "string" ? payload.messageId : null,
|
|
348
|
-
messageOrdinal,
|
|
349
|
-
anchorUserMessageId,
|
|
350
|
-
});
|
|
351
|
-
const input = {
|
|
352
|
-
spaceId: this.spaceId,
|
|
353
|
-
sessionId: this.sessionId,
|
|
354
|
-
turnId,
|
|
355
|
-
seq,
|
|
356
|
-
baseSeq,
|
|
357
|
-
ops: payload.ops,
|
|
358
|
-
anchorUserMessageId,
|
|
359
|
-
};
|
|
360
|
-
const result = this.reducer.applyPatch(input);
|
|
361
|
-
this.handleAppliedState(handlers, "patch", result, event, messageId, messageOrdinal);
|
|
362
|
-
}
|
|
363
|
-
handleProgress(event, handlers) {
|
|
364
|
-
const payload = event.payload;
|
|
365
|
-
if (!isContentBlockArray(payload.content))
|
|
366
|
-
return;
|
|
367
|
-
const current = this.progressState ??
|
|
368
|
-
this.reducer.get({ spaceId: this.spaceId, sessionId: this.sessionId });
|
|
369
|
-
const turnId = typeof payload.turnId === "string" ? payload.turnId : current.turnId;
|
|
370
|
-
const anchorUserMessageId = typeof payload.anchorUserMessageId === "string"
|
|
371
|
-
? payload.anchorUserMessageId
|
|
372
|
-
: current.anchorUserMessageId;
|
|
373
|
-
const messageOrdinal = typeof payload.messageOrdinal === "number"
|
|
374
|
-
? payload.messageOrdinal
|
|
375
|
-
: this.messageOrdinal;
|
|
376
|
-
const messageId = this.prepareMessageBoundary({
|
|
377
|
-
turnId,
|
|
378
|
-
messageId: typeof payload.messageId === "string" ? payload.messageId : this.messageId,
|
|
379
|
-
messageOrdinal,
|
|
380
|
-
anchorUserMessageId,
|
|
381
|
-
});
|
|
382
|
-
const base = this.progressState?.turnId === turnId ? this.progressState : current;
|
|
383
|
-
const state = {
|
|
384
|
-
...base,
|
|
385
|
-
spaceId: this.spaceId,
|
|
386
|
-
sessionId: this.sessionId,
|
|
387
|
-
status: "streaming",
|
|
388
|
-
contentBlocks: mergeStreamingDeltaBlocks(base.contentBlocks, payload.content),
|
|
389
|
-
anchorUserMessageId,
|
|
390
|
-
turnId,
|
|
391
|
-
};
|
|
392
|
-
this.progressState = state;
|
|
393
|
-
this.messageId = messageId;
|
|
394
|
-
this.messageOrdinal = messageOrdinal;
|
|
395
|
-
this.emit(handlers, {
|
|
396
|
-
type: "state",
|
|
397
|
-
source: "progress",
|
|
398
|
-
state,
|
|
399
|
-
messageId,
|
|
400
|
-
messageOrdinal,
|
|
401
|
-
intermediateMessages: [...this.intermediateMessages],
|
|
402
|
-
rawEvent: event,
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
handlePersisted(event, handlers) {
|
|
406
|
-
const message = event.payload.message;
|
|
407
|
-
if (!isRecord(message))
|
|
408
|
-
return;
|
|
409
|
-
const commit = parseAssistantMessageCommit(message);
|
|
410
|
-
if (commit.kind === "intermediate") {
|
|
411
|
-
const intermediate = messageRecordToIntermediate(commit.message);
|
|
412
|
-
if (intermediate) {
|
|
413
|
-
this.addIntermediateMessage(intermediate);
|
|
414
|
-
}
|
|
415
|
-
this.reducer.reset({ spaceId: this.spaceId, sessionId: this.sessionId });
|
|
416
|
-
this.resetCurrentMessage();
|
|
417
|
-
}
|
|
418
|
-
if (commit.kind === "final") {
|
|
419
|
-
this.reducer.complete({
|
|
420
|
-
spaceId: this.spaceId,
|
|
421
|
-
sessionId: this.sessionId,
|
|
422
|
-
turnId: getTurnIdFromMessage(commit.message),
|
|
423
|
-
});
|
|
424
|
-
this.resetCurrentMessage();
|
|
425
|
-
}
|
|
426
|
-
if (commit.kind === "error") {
|
|
427
|
-
this.reducer.fail({
|
|
428
|
-
spaceId: this.spaceId,
|
|
429
|
-
sessionId: this.sessionId,
|
|
430
|
-
turnId: getTurnIdFromMessage(commit.message),
|
|
431
|
-
});
|
|
432
|
-
this.resetCurrentMessage();
|
|
433
|
-
}
|
|
434
|
-
this.emit(handlers, {
|
|
435
|
-
type: "commit",
|
|
436
|
-
commit,
|
|
437
|
-
rawEvent: event,
|
|
438
|
-
});
|
|
439
|
-
}
|
|
440
|
-
handleFinalized(event, handlers) {
|
|
441
|
-
const turn = event.payload.turn;
|
|
442
|
-
if (!isRecord(turn))
|
|
443
|
-
return;
|
|
444
|
-
const typedTurn = turn;
|
|
445
|
-
if (typedTurn.status === "interrupted") {
|
|
446
|
-
this.reducer.interrupt({
|
|
447
|
-
spaceId: this.spaceId,
|
|
448
|
-
sessionId: this.sessionId,
|
|
449
|
-
turnId: typedTurn.id,
|
|
450
|
-
});
|
|
451
|
-
}
|
|
452
|
-
else {
|
|
453
|
-
this.reducer.complete({
|
|
454
|
-
spaceId: this.spaceId,
|
|
455
|
-
sessionId: this.sessionId,
|
|
456
|
-
turnId: typedTurn.id,
|
|
457
|
-
});
|
|
458
|
-
}
|
|
459
|
-
this.resetCurrentMessage();
|
|
460
|
-
this.emit(handlers, {
|
|
461
|
-
type: "finalized",
|
|
462
|
-
turn: typedTurn,
|
|
463
|
-
rawEvent: event,
|
|
464
|
-
});
|
|
465
|
-
}
|
|
466
|
-
handleEvent(event, handlers) {
|
|
467
|
-
switch (event.type) {
|
|
468
|
-
case "session.turn.snapshot":
|
|
469
|
-
this.handleSnapshot(event, handlers);
|
|
470
|
-
return;
|
|
471
|
-
case "session.turn.patch":
|
|
472
|
-
this.handlePatch(event, handlers);
|
|
473
|
-
return;
|
|
474
|
-
case "session.turn.progress":
|
|
475
|
-
this.handleProgress(event, handlers);
|
|
476
|
-
return;
|
|
477
|
-
case "session.message.persisted":
|
|
478
|
-
this.handlePersisted(event, handlers);
|
|
479
|
-
return;
|
|
480
|
-
case "session.turn.finalized":
|
|
481
|
-
this.handleFinalized(event, handlers);
|
|
482
|
-
return;
|
|
483
|
-
case "session.turn.updated": {
|
|
484
|
-
const turn = event.payload.turn;
|
|
485
|
-
if (!isRecord(turn))
|
|
486
|
-
return;
|
|
487
|
-
this.emit(handlers, {
|
|
488
|
-
type: "turn_updated",
|
|
489
|
-
turn: turn,
|
|
490
|
-
rawEvent: event,
|
|
491
|
-
});
|
|
492
|
-
return;
|
|
493
|
-
}
|
|
494
|
-
case "session.turn.error": {
|
|
495
|
-
const message = typeof event.payload.error === "string" && event.payload.error.trim()
|
|
496
|
-
? event.payload.error.trim()
|
|
497
|
-
: "Generation failed";
|
|
498
|
-
this.reducer.fail({ spaceId: this.spaceId, sessionId: this.sessionId });
|
|
499
|
-
this.resetCurrentMessage();
|
|
500
|
-
this.emit(handlers, {
|
|
501
|
-
type: "error",
|
|
502
|
-
message,
|
|
503
|
-
rawEvent: event,
|
|
504
|
-
});
|
|
505
|
-
return;
|
|
506
|
-
}
|
|
507
|
-
default:
|
|
508
|
-
return;
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
export function createSessionGenerationStreamClient(input) {
|
|
513
|
-
return new SessionGenerationStreamClient(input.websocketClient, input.spaceId, input.sessionId);
|
|
514
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import type { ContentBlock } from "@neta-art/cohub-protocol/core";
|
|
2
|
-
import type { RealtimePatchOperation, SessionTurnPatchEvent } from "@neta-art/cohub-protocol/realtime";
|
|
3
|
-
export type SessionPatchStatus = "idle" | "pending" | "streaming" | "completed" | "failed" | "interrupted";
|
|
4
|
-
export type SessionPatchState = {
|
|
5
|
-
spaceId: string | null;
|
|
6
|
-
sessionId: string;
|
|
7
|
-
status: SessionPatchStatus;
|
|
8
|
-
contentBlocks: ContentBlock[];
|
|
9
|
-
anchorUserMessageId: string | null;
|
|
10
|
-
patchSeq: number;
|
|
11
|
-
turnId: string | null;
|
|
12
|
-
appendPath: string | null;
|
|
13
|
-
};
|
|
14
|
-
export type SessionPatchApplyInput = {
|
|
15
|
-
spaceId?: string | null;
|
|
16
|
-
sessionId: string;
|
|
17
|
-
turnId?: string | null;
|
|
18
|
-
seq: number;
|
|
19
|
-
baseSeq: number;
|
|
20
|
-
ops: RealtimePatchOperation[];
|
|
21
|
-
anchorUserMessageId?: string | null;
|
|
22
|
-
};
|
|
23
|
-
export type SessionPatchApplyResult = {
|
|
24
|
-
applied: true;
|
|
25
|
-
state: SessionPatchState;
|
|
26
|
-
} | {
|
|
27
|
-
applied: false;
|
|
28
|
-
reason: "duplicate" | "version_mismatch" | "invalid";
|
|
29
|
-
state: SessionPatchState;
|
|
30
|
-
};
|
|
31
|
-
export type SessionPatchSnapshotInput = SessionPatchKeyInput & {
|
|
32
|
-
turnId?: string | null;
|
|
33
|
-
seq: number;
|
|
34
|
-
contentBlocks: ContentBlock[];
|
|
35
|
-
anchorUserMessageId?: string | null;
|
|
36
|
-
appendPath?: string | null;
|
|
37
|
-
};
|
|
38
|
-
type SessionPatchKeyInput = {
|
|
39
|
-
spaceId?: string | null;
|
|
40
|
-
sessionId: string;
|
|
41
|
-
turnId?: string | null;
|
|
42
|
-
};
|
|
43
|
-
export declare class SessionPatchReducer {
|
|
44
|
-
private readonly states;
|
|
45
|
-
private key;
|
|
46
|
-
get(input: SessionPatchKeyInput): SessionPatchState;
|
|
47
|
-
start(input: SessionPatchKeyInput): SessionPatchState;
|
|
48
|
-
replaceTurnId(input: SessionPatchKeyInput & {
|
|
49
|
-
nextTurnId: string | null;
|
|
50
|
-
}): SessionPatchState;
|
|
51
|
-
complete(input: SessionPatchKeyInput): SessionPatchState;
|
|
52
|
-
fail(input: SessionPatchKeyInput): SessionPatchState;
|
|
53
|
-
interrupt(input: SessionPatchKeyInput): SessionPatchState;
|
|
54
|
-
reset(input: SessionPatchKeyInput): void;
|
|
55
|
-
applySnapshot(input: SessionPatchSnapshotInput): SessionPatchApplyResult;
|
|
56
|
-
resetAll(): void;
|
|
57
|
-
applyEvent(event: SessionTurnPatchEvent): SessionPatchApplyResult;
|
|
58
|
-
applyPatch(input: SessionPatchApplyInput): SessionPatchApplyResult;
|
|
59
|
-
}
|
|
60
|
-
export declare const createSessionPatchReducer: () => SessionPatchReducer;
|
|
61
|
-
export {};
|