* Update a single Magic Doc
( docInfo: MagicDocInfo, context: REPLHookContext, )
| 115 | * Update a single Magic Doc |
| 116 | */ |
| 117 | async function updateMagicDoc( |
| 118 | docInfo: MagicDocInfo, |
| 119 | context: REPLHookContext, |
| 120 | ): Promise<void> { |
| 121 | const { messages, systemPrompt, userContext, systemContext, toolUseContext } = |
| 122 | context |
| 123 | |
| 124 | // Clone the FileStateCache to isolate Magic Docs operations. Delete this |
| 125 | // doc's entry so FileReadTool's dedup doesn't return a file_unchanged |
| 126 | // stub — we need the actual content to re-detect the header. |
| 127 | const clonedReadFileState = cloneFileStateCache(toolUseContext.readFileState) |
| 128 | clonedReadFileState.delete(docInfo.path) |
| 129 | const clonedToolUseContext: ToolUseContext = { |
| 130 | ...toolUseContext, |
| 131 | readFileState: clonedReadFileState, |
| 132 | } |
| 133 | |
| 134 | // Read the document; if deleted or unreadable, remove from tracking |
| 135 | let currentDoc = '' |
| 136 | try { |
| 137 | const result = await FileReadTool.call( |
| 138 | { file_path: docInfo.path }, |
| 139 | clonedToolUseContext, |
| 140 | ) |
| 141 | const output = result.data as FileReadToolOutput |
| 142 | if (output.type === 'text') { |
| 143 | currentDoc = output.file.content |
| 144 | } |
| 145 | } catch (e: unknown) { |
| 146 | // FileReadTool wraps ENOENT in a plain Error("File does not exist...") with |
| 147 | // no .code, so check the message in addition to isFsInaccessible (EACCES/EPERM). |
| 148 | if ( |
| 149 | isFsInaccessible(e) || |
| 150 | (e instanceof Error && e.message.startsWith('File does not exist')) |
| 151 | ) { |
| 152 | trackedMagicDocs.delete(docInfo.path) |
| 153 | return |
| 154 | } |
| 155 | throw e |
| 156 | } |
| 157 | |
| 158 | // Re-detect title and instructions from latest file content |
| 159 | const detected = detectMagicDocHeader(currentDoc) |
| 160 | if (!detected) { |
| 161 | // File no longer has magic doc header, remove from tracking |
| 162 | trackedMagicDocs.delete(docInfo.path) |
| 163 | return |
| 164 | } |
| 165 | |
| 166 | // Build update prompt with latest title and instructions |
| 167 | const userPrompt = await buildMagicDocsUpdatePrompt( |
| 168 | currentDoc, |
| 169 | docInfo.path, |
| 170 | detected.title, |
| 171 | detected.instructions, |
| 172 | ) |
| 173 | |
| 174 | // Create a custom canUseTool that only allows Edit for magic doc files |
no test coverage detected