(transcript, prompt)
| 523 | } |
| 524 | |
| 525 | async function buildPromptWithCarryOver(transcript, prompt) { |
| 526 | const conversation = listConversationEntries(transcript) |
| 527 | |
| 528 | // ── Bootstrap (soul / identity / context) injection ── |
| 529 | const bootstrap = getBootstrap() |
| 530 | |
| 531 | const systemBlock = bootstrap |
| 532 | ? `<system_context>\n${bootstrap}\n</system_context>\n\n` |
| 533 | : '' |
| 534 | |
| 535 | if (conversation.length === 0) { |
| 536 | return { |
| 537 | runnerPrompt: systemBlock + prompt, |
| 538 | usedEntries: [], |
| 539 | active: false, |
| 540 | } |
| 541 | } |
| 542 | |
| 543 | const usedEntries = [] |
| 544 | let totalChars = 0 |
| 545 | |
| 546 | for (let index = conversation.length - 1; index >= 0; index -= 1) { |
| 547 | const entry = conversation[index] |
| 548 | const label = entry.role === 'user' ? 'User' : 'Assistant' |
| 549 | const content = trimContextText(entry.content) |
| 550 | const nextSize = totalChars + label.length + content.length + 8 |
| 551 | |
| 552 | if ( |
| 553 | usedEntries.length > 0 && |
| 554 | (usedEntries.length >= contextMessageLimit || nextSize > contextCharLimit) |
| 555 | ) { |
| 556 | break |
| 557 | } |
| 558 | |
| 559 | usedEntries.unshift({ |
| 560 | role: entry.role, |
| 561 | label, |
| 562 | content, |
| 563 | }) |
| 564 | totalChars = nextSize |
| 565 | } |
| 566 | |
| 567 | const renderedConversation = usedEntries |
| 568 | .map(entry => `${entry.label}: ${entry.content}`) |
| 569 | .join('\n\n') |
| 570 | |
| 571 | return { |
| 572 | runnerPrompt: [ |
| 573 | systemBlock + 'Continue the same conversation using the recent transcript below as working context.', |
| 574 | 'Use it as background only and answer the new request directly.', |
| 575 | '', |
| 576 | '<recent_conversation>', |
| 577 | renderedConversation, |
| 578 | '</recent_conversation>', |
| 579 | '', |
| 580 | '<new_request>', |
| 581 | prompt, |
| 582 | '</new_request>', |
no test coverage detected