(messages: Message[])
| 380 | * @internal Exported for testing - use loadConversationForResume instead |
| 381 | */ |
| 382 | export function restoreSkillStateFromMessages(messages: Message[]): void { |
| 383 | for (const message of messages) { |
| 384 | if (message.type !== 'attachment') { |
| 385 | continue |
| 386 | } |
| 387 | if (message.attachment.type === 'invoked_skills') { |
| 388 | for (const skill of message.attachment.skills) { |
| 389 | if (skill.name && skill.path && skill.content) { |
| 390 | // Resume only happens for the main session, so agentId is null |
| 391 | addInvokedSkill(skill.name, skill.path, skill.content, null) |
| 392 | } |
| 393 | } |
| 394 | } |
| 395 | // A prior process already injected the skills-available reminder — it's |
| 396 | // in the transcript the model is about to see. sentSkillNames is |
| 397 | // process-local, so without this every resume re-announces the same |
| 398 | // ~600 tokens. Fire-once latch; consumed on the first attachment pass. |
| 399 | if (message.attachment.type === 'skill_listing') { |
| 400 | suppressNextSkillListing() |
| 401 | } |
| 402 | } |
| 403 | } |
| 404 | |
| 405 | /** |
| 406 | * Chain-walk a transcript jsonl by path. Same sequence loadFullLog |
no test coverage detected