( d: TranscriptDraft, id: string, title: string, text: string, timestamp: string, ctx: TranscriptItemContext, acpSource?: string, updateMarkerId?: string, )
| 486 | } |
| 487 | |
| 488 | function upsertPlan( |
| 489 | d: TranscriptDraft, |
| 490 | id: string, |
| 491 | title: string, |
| 492 | text: string, |
| 493 | timestamp: string, |
| 494 | ctx: TranscriptItemContext, |
| 495 | acpSource?: string, |
| 496 | updateMarkerId?: string, |
| 497 | ) { |
| 498 | const existing = d.itemsById.get(id); |
| 499 | if (existing?.type === "plan") { |
| 500 | const changed = existing.text !== text; |
| 501 | replaceItem(d, id, { |
| 502 | ...existing, |
| 503 | text, |
| 504 | channelId: ctx.channelId, |
| 505 | turnId: ctx.turnId ?? existing.turnId, |
| 506 | sessionId: ctx.sessionId ?? existing.sessionId, |
| 507 | acpSource: acpSource ?? existing.acpSource, |
| 508 | }); |
| 509 | if (changed) { |
| 510 | pushItem(d, { |
| 511 | id: updateMarkerId ?? `${id}:update:${timestamp}`, |
| 512 | type: "plan", |
| 513 | renderClass: "plan", |
| 514 | title: "Plan updated", |
| 515 | text: summarizePlanUpdate(text), |
| 516 | timestamp, |
| 517 | isUpdate: true, |
| 518 | targetId: id, |
| 519 | channelId: ctx.channelId, |
| 520 | turnId: ctx.turnId, |
| 521 | sessionId: ctx.sessionId, |
| 522 | acpSource, |
| 523 | }); |
| 524 | } |
| 525 | return; |
| 526 | } |
| 527 | sealOpenMessages(d); |
| 528 | pushItem(d, { |
| 529 | id, |
| 530 | type: "plan", |
| 531 | renderClass: "plan", |
| 532 | title, |
| 533 | text, |
| 534 | timestamp, |
| 535 | channelId: ctx.channelId, |
| 536 | turnId: ctx.turnId, |
| 537 | sessionId: ctx.sessionId, |
| 538 | acpSource, |
| 539 | }); |
| 540 | } |
| 541 | |
| 542 | function summarizePlanUpdate(text: string) { |
| 543 | const taskMatches = [...text.matchAll(/\[[ xX]\]/g)]; |
no test coverage detected