Dashboard › opencode › Distillation
db1c3b24-4aec-4b54-a795-2e769cbe03cb["lore_tm_v1_YZYZq_sLz1fZGqB_I-f2w6G3OCh3JIYNhuB20i5e0Rw","lore_tm_v1_VoEygm1-FvkiLciaLZDTlIsjK-tqiNiru1Eo_reXVBM","lore_tm_v1_iq8gRy5X40EIlNrYvQ8mFluJ2JEatxDly7uf0_FaFw8","lore_tm_v1_We2qnvYIrMbZC61TprISmLaqUzRtYlq7s0AbXFjoZxM","lore_tm_v1_RdZB4M30QN4uu8olXSMqiVD3VofZN2f4Vvj4MCaP5Os","lore_tm_v1_w8eY6nQ0Xw_Xdt6HAKC3sbtrklFVFYp1FfRb8ejDkWk","lore_tm_v1_8Dx05-FOsWWFzEkubvMBQe0xp5kR22J2XZvgPgJGRKA","lore_tm_v1_oWxD8h3LspGBUU8BWBMtubQa-RSFxRxmT7hYiGTbWdg","lore_tm_v1_ku5a816SlgPRbD3uSGDfcR6fMHa98Zkf-lghTa6sKVQ"]
Date: Sep 15, 2026
packages/core/src/session/message-updater.ts found session.next.step.ended, session.next.step.failed, and session.next.step.interrupted all use updateOwnedAssistant(event.data.assistantMessageID, ...); ended records completion timestamp, finish, cost, tokens, and optional snapshot/files, while failed and interrupted mark finish = "error" and attach the event error.packages/core/src/session/message-updater.ts handles session.next.step.recovered by selecting error text from the execution phase: phase "unknown" produces "Provider Step outcome unknown after server restart"; other phases produce "Session execution interrupted by server restart".assistantMessageID, packages/core/src/session/message-updater.ts appends a SessionMessage.Synthetic whose ID is message(event.data.executionID), text is the recovery error message, and creation time is the event timestamp.assistantMessageID, packages/core/src/session/message-updater.ts updates only the owned assistant: sets completion time, finish = "error", attaches the recovery error, and appends an assistant text part with ID recovery:${event.data.executionID}.SessionMessage.ToolStateError with message "Tool execution outcome unknown after server restart" and completion timestamp; it preserves parsed input when available, preserves structured and content only for formerly running tools, and uses empty values for formerly pending tools.packages/core/src/session/message-updater.ts is assistant-owned: session.next.text.started appends an empty SessionMessage.AssistantText, session.next.text.delta appends to the latest matching text part, and session.next.text.ended replaces that part’s text with the final event text.packages/core/src/event.ts found new durable-event publication runs projectors first, then the optional commit(seq) effect, then upserts EventSequenceTable, then inserts EventTable, all inside an immediate database transaction; durable subscribers are notified only after that transaction returns a committed result.packages/core/src/event.ts accepts an existing sequence only when stored event ID, versioned type, and encoded data exactly match; otherwise it dies with InvalidDurableEventError containing Replay diverged at aggregate ${aggregateID} sequence ${input.seq}.packages/core/src/event.ts rejects noncontiguous supplied durable sequences with Sequence mismatch for aggregate ${aggregateID}: expected ${latest + 1}, got ${seq}, and rejects reuse of an event ID at another stored location with Event ${event.id} already exists at aggregate ${stored.aggregateID} sequence ${stored.seq}.packages/core/src/event.ts: an idempotent replay can populate a previously null EventSequenceTable.owner_id; a new publication with a supplied owner differing from the aggregate’s existing owner returns without committing.packages/core/src/event.ts use a per-aggregate sliding PubSub of capacity 1. durable({ aggregateID, after }) starts at after ?? -1, reads persisted events ordered by ascending sequence, updates its sequence cursor to the final event read, emits historical events first, and then rereads persisted rows after each live wake.remove(aggregateID) in packages/core/src/event.ts transactionally deletes the aggregate’s row from EventSequenceTable and all matching rows from EventTable; claim(aggregateID, ownerID) updates EventSequenceTable.owner_id.packages/core/src/session/compaction.ts found overflow compaction is skipped when the model context limit is absent/nonpositive, no eligible selection exists, the selected head is empty without a previous compaction, or the estimated summary prompt exceeds context - summaryOutput.input.request.generation?.maxTokens ?? input.model.route.defaults.limits?.output ?? 0, caps summary generation at SUMMARY_OUTPUT_TOKENS, and calls the LLM with one user message containing the summary prompt, no tools, and generation: { maxTokens: summaryOutput }.compactAfterOverflow() publishes SessionEvent.Compaction.Started with a newly created SessionMessage.ID, timestamp, and reason: "auto" before streaming; it invokes optional beforeStream, accumulates LLMEvent text deltas, marks provider-error events as failure, catches LLM.Error, and returns false without an ended event if streaming fails, any provider error occurs, or the joined summary is blank.SessionEvent.Compaction.Ended with the same messageID, a new timestamp, reason: "auto", generated text, and selected.recent, using { commit: input.commit }, then returns true.compactIfNeeded() in packages/core/src/session/compaction.ts requires automatic compaction to be enabled and estimated system/messages/tools tokens to exceed context - Math.max(output, config.buffer) before delegating to compactAfterOverflow().