(
envelope: MemxTurnEnvelope,
pending?: MemxTurnEnvelope | null,
options: { timeoutMs?: number; intervalMs?: number } = {},
)
| 294 | } |
| 295 | |
| 296 | export async function completeEnvelopeFromTranscript( |
| 297 | envelope: MemxTurnEnvelope, |
| 298 | pending?: MemxTurnEnvelope | null, |
| 299 | options: { timeoutMs?: number; intervalMs?: number } = {}, |
| 300 | ): Promise<MemxTurnEnvelope> { |
| 301 | if (envelope.messages.some((message) => message.role === "assistant" && message.content.trim())) { |
| 302 | return envelope; |
| 303 | } |
| 304 | const expectedUserText = [...(pending?.messages ?? [])] |
| 305 | .reverse() |
| 306 | .find((message) => message.role === "user" && message.content.trim())?.content; |
| 307 | const transcriptPath = |
| 308 | envelope.metadata && typeof envelope.metadata.transcriptPath === "string" |
| 309 | ? envelope.metadata.transcriptPath |
| 310 | : pending?.metadata && typeof pending.metadata.transcriptPath === "string" |
| 311 | ? pending.metadata.transcriptPath |
| 312 | : undefined; |
| 313 | const timeoutMs = parsePositiveInt( |
| 314 | options.timeoutMs !== undefined |
| 315 | ? String(options.timeoutMs) |
| 316 | : process.env["MEMX_TRANSCRIPT_CAPTURE_TIMEOUT_MS"], |
| 317 | MEMX_TRANSCRIPT_CAPTURE_TIMEOUT_MS, |
| 318 | ); |
| 319 | const intervalMs = parsePositiveInt( |
| 320 | options.intervalMs !== undefined |
| 321 | ? String(options.intervalMs) |
| 322 | : process.env["MEMX_TRANSCRIPT_CAPTURE_INTERVAL_MS"], |
| 323 | MEMX_TRANSCRIPT_CAPTURE_INTERVAL_MS, |
| 324 | ); |
| 325 | const startedAt = Date.now(); |
| 326 | let capture: TranscriptAssistantCapture | null = null; |
| 327 | do { |
| 328 | capture = await extractAssistantFromTranscript({ |
| 329 | hostId: envelope.hostId, |
| 330 | transcriptPath, |
| 331 | sessionId: envelope.sessionId, |
| 332 | expectedUserText, |
| 333 | }); |
| 334 | if (capture || timeoutMs === 0) { |
| 335 | break; |
| 336 | } |
| 337 | const remainingMs = timeoutMs - (Date.now() - startedAt); |
| 338 | if (remainingMs <= 0) { |
| 339 | break; |
| 340 | } |
| 341 | await sleep(Math.min(intervalMs, remainingMs)); |
| 342 | } while (Date.now() - startedAt <= timeoutMs); |
| 343 | if (!capture) { |
| 344 | return { |
| 345 | ...envelope, |
| 346 | metadata: { |
| 347 | ...(envelope.metadata ?? {}), |
| 348 | transcriptAssistantCapture: "missing", |
| 349 | }, |
| 350 | }; |
| 351 | } |
| 352 | return { |
| 353 | ...envelope, |
no test coverage detected