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