| 312 | } |
| 313 | |
| 314 | async function emitText(state: State, body: string, signal?: AbortSignal): Promise<void> { |
| 315 | const msg = open(state) |
| 316 | const part = take(state, "part", "part") |
| 317 | const start = Date.now() |
| 318 | |
| 319 | feed(state, { |
| 320 | type: "message.part.updated", |
| 321 | properties: { |
| 322 | sessionID: state.id, |
| 323 | time: Date.now(), |
| 324 | part: { |
| 325 | id: part, |
| 326 | sessionID: state.id, |
| 327 | messageID: msg, |
| 328 | type: "text", |
| 329 | text: "", |
| 330 | time: { |
| 331 | start, |
| 332 | }, |
| 333 | }, |
| 334 | }, |
| 335 | } as Event) |
| 336 | |
| 337 | let next = "" |
| 338 | for (const item of split(body)) { |
| 339 | if (signal?.aborted) { |
| 340 | return |
| 341 | } |
| 342 | |
| 343 | next += item |
| 344 | feed(state, { |
| 345 | type: "message.part.delta", |
| 346 | properties: { |
| 347 | sessionID: state.id, |
| 348 | messageID: msg, |
| 349 | partID: part, |
| 350 | field: "text", |
| 351 | delta: item, |
| 352 | }, |
| 353 | } as Event) |
| 354 | await wait(45, signal) |
| 355 | } |
| 356 | |
| 357 | feed(state, { |
| 358 | type: "message.part.updated", |
| 359 | properties: { |
| 360 | sessionID: state.id, |
| 361 | time: Date.now(), |
| 362 | part: { |
| 363 | id: part, |
| 364 | sessionID: state.id, |
| 365 | messageID: msg, |
| 366 | type: "text", |
| 367 | text: next, |
| 368 | time: { |
| 369 | start, |
| 370 | end: Date.now(), |
| 371 | }, |