codex-overleaf-link 2.4.1 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (397) hide show
  1. package/README.md +275 -305
  2. package/README.zh-CN.md +290 -320
  3. package/extension/bootstrap/background.js +99 -19
  4. package/extension/bootstrap/manifest.template.json +9 -4
  5. package/extension/bootstrap/popup.html +11 -16
  6. package/extension/bootstrap/popupFallback.js +55 -0
  7. package/extension/bootstrap/update.js +25 -2
  8. package/extension/bootstrap/updateStatus.js +1 -0
  9. package/extension/runtime-manifest.json +3 -1
  10. package/extension/src/background.js +234 -56
  11. package/extension/src/backgroundBootstrapMigration.js +181 -0
  12. package/extension/src/backgroundSharedSessions.js +440 -0
  13. package/extension/src/backgroundUpdateCoordinator.js +541 -381
  14. package/extension/src/backgroundUpdateSafety.js +173 -0
  15. package/extension/src/content/activeTurnControl.js +16 -2
  16. package/extension/src/content/applyResultFormatters.js +46 -73
  17. package/extension/src/content/assetTransferBroker.js +244 -12
  18. package/extension/src/content/changeHistoryView.js +175 -0
  19. package/extension/src/content/composerAttachments.js +117 -67
  20. package/extension/src/content/composerPanel.js +41 -8
  21. package/extension/src/content/contentRuntime.js +1084 -1099
  22. package/extension/src/content/diagnosticsController.js +122 -97
  23. package/extension/src/content/diagnosticsExport.js +236 -0
  24. package/extension/src/content/diagnosticsPanel.js +78 -19
  25. package/extension/src/content/diffReviewPanel.js +8 -5
  26. package/extension/src/content/directoryCleanupRecovery.js +54 -0
  27. package/extension/src/content/generated/content.bundle.js +14680 -3606
  28. package/extension/src/content/generated/content.bundle.meta.json +30 -3
  29. package/extension/src/content/globalPreferencesController.js +1 -1
  30. package/extension/src/content/legacyGlobalRegistry.js +25 -1
  31. package/extension/src/content/localSkillsPanel.js +141 -16
  32. package/extension/src/content/markdownDomRenderer.js +9 -4
  33. package/extension/src/content/markdownText.js +5 -6
  34. package/extension/src/content/modelPicker.js +8 -5
  35. package/extension/src/content/nativeCompatibilityController.js +45 -20
  36. package/extension/src/content/otWarmMirror.js +4 -5
  37. package/extension/src/content/otWarmMirrorController.js +17 -20
  38. package/extension/src/content/pageBridgeClient.js +33 -5
  39. package/extension/src/content/panelMaintenance.js +87 -132
  40. package/extension/src/content/panelRenderer.js +10 -0
  41. package/extension/src/content/pendingInputView.js +109 -76
  42. package/extension/src/content/projectProviderSelection.js +13 -4
  43. package/extension/src/content/projectSessionCleanup.js +109 -62
  44. package/extension/src/content/projectSettingsCoordinator.js +39 -2
  45. package/extension/src/content/providerSettingsCoordinator.js +63 -14
  46. package/extension/src/content/providerSettingsDialog.js +724 -113
  47. package/extension/src/content/recentProjects.js +21 -6
  48. package/extension/src/content/runActivitySummary.js +665 -0
  49. package/extension/src/content/runCompletionMeta.js +344 -0
  50. package/extension/src/content/runController.js +40 -15
  51. package/extension/src/content/runFailureNotice.js +34 -12
  52. package/extension/src/content/runGuidanceController.js +76 -30
  53. package/extension/src/content/runGuidanceView.js +59 -10
  54. package/extension/src/content/runPresence.js +306 -0
  55. package/extension/src/content/runQueueScheduler.js +150 -43
  56. package/extension/src/content/runRecoveryActions.js +146 -0
  57. package/extension/src/content/runResultActions.js +11 -8
  58. package/extension/src/content/runReviewController.js +574 -0
  59. package/extension/src/content/runScrollLayout.js +21 -2
  60. package/extension/src/content/runTimelineView.js +315 -290
  61. package/extension/src/content/scopedPersistencePanelState.js +51 -6
  62. package/extension/src/content/selectionContextView.js +300 -0
  63. package/extension/src/content/sensitivePreflight.js +140 -0
  64. package/extension/src/content/sessionForkController.js +80 -17
  65. package/extension/src/content/sessionManager.js +1 -1
  66. package/extension/src/content/sessionPersistence.js +6 -1
  67. package/extension/src/content/settingsPanel.js +84 -55
  68. package/extension/src/content/settingsWorkbench.js +379 -0
  69. package/extension/src/content/sharedSessionViewSync.js +109 -0
  70. package/extension/src/content/subagentActivityView.js +195 -0
  71. package/extension/src/content/trackedChangeCaptureController.js +7 -3
  72. package/extension/src/content/updateIdle.js +4 -1
  73. package/extension/src/content/updateNotice.js +179 -56
  74. package/extension/src/content/updateSafetyReceiver.js +58 -0
  75. package/extension/src/content/writebackController.js +308 -2
  76. package/extension/src/content/writebackOrchestrator.js +213 -199
  77. package/extension/src/content/writebackPlan.js +231 -0
  78. package/extension/src/content/writebackRecovery.js +122 -0
  79. package/extension/src/content/writingStyleSettings.js +600 -0
  80. package/extension/src/content/writtenChangesView.js +152 -0
  81. package/extension/src/page/binaryAssetUploader.js +223 -23
  82. package/extension/src/page/fileMover.js +256 -0
  83. package/extension/src/page/overleafProjectSnapshot.js +1 -0
  84. package/extension/src/page/ownedDirectoryCleanup.js +94 -0
  85. package/extension/src/page/referenceProjects.js +149 -0
  86. package/extension/src/page/reviewContext.js +113 -0
  87. package/extension/src/page/saveState.js +20 -6
  88. package/extension/src/page/snapshotRouter.js +124 -48
  89. package/extension/src/page/textCoordinates.js +102 -0
  90. package/extension/src/page/textFileCreator.js +442 -71
  91. package/extension/src/page/trackedChangeCapture.js +53 -57
  92. package/extension/src/page/trackedChangeOwnership.js +216 -0
  93. package/extension/src/page/trackedChangeReplay.js +184 -0
  94. package/extension/src/page/trackedChangesLifecycle.js +343 -339
  95. package/extension/src/page/treeOperations.js +33 -12
  96. package/extension/src/page/updateSafetyProbe.js +41 -0
  97. package/extension/src/page/writebackReceiptJournal.js +114 -0
  98. package/extension/src/page/writebackRouter.js +242 -201
  99. package/extension/src/pageBridge.js +73 -102
  100. package/extension/src/popup.js +261 -65
  101. package/extension/src/shared/agentTranscript.js +41 -4
  102. package/extension/src/shared/auditRecords.js +73 -0
  103. package/extension/src/shared/changeHistoryModel.js +94 -0
  104. package/extension/src/shared/compatibility.js +22 -6
  105. package/extension/src/shared/compileAdapter.js +101 -37
  106. package/extension/src/shared/composerAttachmentDraft.js +151 -0
  107. package/extension/src/shared/directoryCleanupProof.js +43 -0
  108. package/extension/src/shared/failureReasons.js +329 -3
  109. package/extension/src/shared/globalPreferences.js +31 -14
  110. package/extension/src/shared/governanceRules.js +4 -37
  111. package/extension/src/shared/i18n.js +389 -25
  112. package/extension/src/shared/managedUpdateProjection.js +8 -5
  113. package/extension/src/shared/nativeRequestIdentity.js +1 -0
  114. package/extension/src/shared/pageRpcContract.js +9 -2
  115. package/extension/src/shared/projectFiles.js +21 -44
  116. package/extension/src/shared/providerProfiles.js +114 -3
  117. package/extension/src/shared/runActivityModel.js +361 -0
  118. package/extension/src/shared/runExecutionSnapshot.js +8 -2
  119. package/extension/src/shared/runExecutionSnapshotCodec.js +16 -4
  120. package/extension/src/shared/runInputQueue.js +48 -5
  121. package/extension/src/shared/scopedPersistenceBrowserAdapter.js +6 -3
  122. package/extension/src/shared/selectionContext.js +37 -0
  123. package/extension/src/shared/sessionState.js +166 -30
  124. package/extension/src/shared/settlementFacts.js +10 -2
  125. package/extension/src/shared/sharedSessionBridge.js +311 -0
  126. package/extension/src/shared/sharedSessionTransfer.js +140 -0
  127. package/extension/src/shared/staleGuard.js +118 -13
  128. package/extension/src/shared/storageDb.js +77 -78
  129. package/extension/src/shared/storageMigration.js +74 -111
  130. package/extension/src/shared/storageRunActions.js +211 -22
  131. package/extension/src/shared/storageValuePruning.js +40 -0
  132. package/extension/src/shared/subagentActivityModel.js +174 -0
  133. package/extension/src/shared/undoOperations.js +216 -6
  134. package/extension/src/shared/updateConsent.js +42 -11
  135. package/extension/src/shared/updateRuntimeIdentity.js +1 -1
  136. package/extension/src/shared/writebackIntent.js +78 -0
  137. package/extension/src/shared/writebackOperationEvidence.js +4 -15
  138. package/extension/src/shared/writebackSettlement.js +67 -48
  139. package/extension/src/shared/writingStyle.js +33 -0
  140. package/extension/styles/panel.css +1987 -385
  141. package/extension/styles/popup.css +110 -0
  142. package/native-host/src/anthropicBridgeRequest.js +6 -3
  143. package/native-host/src/anthropicBridgeResponse.js +6 -2
  144. package/native-host/src/anthropicMessagesBridge.js +24 -16
  145. package/native-host/src/bootstrapMigration.js +296 -0
  146. package/native-host/src/bootstrapMigrationContract.js +101 -0
  147. package/native-host/src/bootstrapUpdate.js +233 -0
  148. package/native-host/src/bootstrapUpdateWatchdog.js +44 -0
  149. package/native-host/src/chatBridgeResponse.js +10 -0
  150. package/native-host/src/chatCompletionsBridge.js +21 -15
  151. package/native-host/src/codexConfigPaths.js +106 -0
  152. package/native-host/src/codexHome.js +66 -73
  153. package/native-host/src/codexHomeScope.js +124 -0
  154. package/native-host/src/codexInheritedAuth.js +90 -0
  155. package/native-host/src/codexLocalSkills.js +301 -0
  156. package/native-host/src/codexModelRecovery.js +107 -0
  157. package/native-host/src/codexPromptAssembly.js +33 -12
  158. package/native-host/src/codexProviderLaunch.js +3 -3
  159. package/native-host/src/codexProviderTest.js +24 -26
  160. package/native-host/src/codexRuntimeIdentity.js +1 -0
  161. package/native-host/src/codexSessionRunner.js +211 -318
  162. package/native-host/src/codexSessionTiming.js +21 -8
  163. package/native-host/src/codexSkillIsolation.js +170 -0
  164. package/native-host/src/codexThreadFork.js +19 -3
  165. package/native-host/src/index.js +19 -7
  166. package/native-host/src/managedInstall.js +115 -39
  167. package/native-host/src/managedInstallRecovery.js +140 -0
  168. package/native-host/src/managedRuntimeEvidence.js +57 -0
  169. package/native-host/src/mirrorWorkspace.js +92 -22
  170. package/native-host/src/nativeDoctor.js +15 -0
  171. package/native-host/src/nativeEnvironment.js +70 -0
  172. package/native-host/src/nativeHelperLifecycle.js +21 -0
  173. package/native-host/src/nativeHostRegistration.js +33 -0
  174. package/native-host/src/nativeQuotas.js +15 -8
  175. package/native-host/src/nativeRunLifecycle.js +71 -0
  176. package/native-host/src/overleafWorkspaceRules.js +16 -0
  177. package/native-host/src/processStopBarrier.js +115 -0
  178. package/native-host/src/projectPathPlatform.js +30 -0
  179. package/native-host/src/providerHttp.js +80 -0
  180. package/native-host/src/providerModelCatalog.js +4 -3
  181. package/native-host/src/providerProfile.js +17 -3
  182. package/native-host/src/providerReasoning.js +10 -11
  183. package/native-host/src/providerRuntime.js +1 -0
  184. package/native-host/src/providerStore.js +76 -14
  185. package/native-host/src/releaseTransport.js +14 -5
  186. package/native-host/src/responsesPassthroughBridge.js +266 -52
  187. package/native-host/src/runtimeInstaller.js +21 -1
  188. package/native-host/src/selectionScope.js +86 -0
  189. package/native-host/src/skills/parallel-subagents/SKILL.md +31 -3
  190. package/native-host/src/skills/writing-style-builder/SKILL.md +146 -0
  191. package/native-host/src/subagentAdmission.js +26 -0
  192. package/native-host/src/subagentBroker.js +176 -159
  193. package/native-host/src/subagentTelemetry.js +325 -0
  194. package/native-host/src/subagentWorkspace.js +103 -0
  195. package/native-host/src/subagentWorkspacePath.js +34 -0
  196. package/native-host/src/taskRunnerRuntime.js +130 -57
  197. package/native-host/src/tomlStatements.js +140 -0
  198. package/native-host/src/turnAttachments.js +113 -0
  199. package/native-host/src/updateManager.js +406 -38
  200. package/native-host/src/updateNetworkControl.js +75 -0
  201. package/native-host/src/updateTrust.js +21 -2
  202. package/native-host/src/vendor/pdfjs/LICENSE +177 -0
  203. package/native-host/src/vendor/pdfjs/SOURCE.txt +3 -0
  204. package/native-host/src/vendor/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
  205. package/native-host/src/vendor/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
  206. package/native-host/src/vendor/pdfjs/cmaps/78-H.bcmap +0 -0
  207. package/native-host/src/vendor/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
  208. package/native-host/src/vendor/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
  209. package/native-host/src/vendor/pdfjs/cmaps/78-V.bcmap +0 -0
  210. package/native-host/src/vendor/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
  211. package/native-host/src/vendor/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
  212. package/native-host/src/vendor/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
  213. package/native-host/src/vendor/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
  214. package/native-host/src/vendor/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
  215. package/native-host/src/vendor/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
  216. package/native-host/src/vendor/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
  217. package/native-host/src/vendor/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
  218. package/native-host/src/vendor/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
  219. package/native-host/src/vendor/pdfjs/cmaps/Add-H.bcmap +0 -0
  220. package/native-host/src/vendor/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
  221. package/native-host/src/vendor/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
  222. package/native-host/src/vendor/pdfjs/cmaps/Add-V.bcmap +0 -0
  223. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
  224. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
  225. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
  226. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
  227. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
  228. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
  229. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
  230. package/native-host/src/vendor/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
  231. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
  232. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
  233. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
  234. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
  235. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
  236. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
  237. package/native-host/src/vendor/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
  238. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
  239. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
  240. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
  241. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
  242. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
  243. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
  244. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
  245. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
  246. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
  247. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
  248. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
  249. package/native-host/src/vendor/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
  250. package/native-host/src/vendor/pdfjs/cmaps/B5-H.bcmap +0 -0
  251. package/native-host/src/vendor/pdfjs/cmaps/B5-V.bcmap +0 -0
  252. package/native-host/src/vendor/pdfjs/cmaps/B5pc-H.bcmap +0 -0
  253. package/native-host/src/vendor/pdfjs/cmaps/B5pc-V.bcmap +0 -0
  254. package/native-host/src/vendor/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
  255. package/native-host/src/vendor/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
  256. package/native-host/src/vendor/pdfjs/cmaps/CNS1-H.bcmap +0 -0
  257. package/native-host/src/vendor/pdfjs/cmaps/CNS1-V.bcmap +0 -0
  258. package/native-host/src/vendor/pdfjs/cmaps/CNS2-H.bcmap +0 -0
  259. package/native-host/src/vendor/pdfjs/cmaps/CNS2-V.bcmap +3 -0
  260. package/native-host/src/vendor/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
  261. package/native-host/src/vendor/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
  262. package/native-host/src/vendor/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
  263. package/native-host/src/vendor/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
  264. package/native-host/src/vendor/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
  265. package/native-host/src/vendor/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
  266. package/native-host/src/vendor/pdfjs/cmaps/EUC-H.bcmap +0 -0
  267. package/native-host/src/vendor/pdfjs/cmaps/EUC-V.bcmap +0 -0
  268. package/native-host/src/vendor/pdfjs/cmaps/Ext-H.bcmap +0 -0
  269. package/native-host/src/vendor/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
  270. package/native-host/src/vendor/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
  271. package/native-host/src/vendor/pdfjs/cmaps/Ext-V.bcmap +0 -0
  272. package/native-host/src/vendor/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
  273. package/native-host/src/vendor/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
  274. package/native-host/src/vendor/pdfjs/cmaps/GB-H.bcmap +4 -0
  275. package/native-host/src/vendor/pdfjs/cmaps/GB-V.bcmap +0 -0
  276. package/native-host/src/vendor/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
  277. package/native-host/src/vendor/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
  278. package/native-host/src/vendor/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
  279. package/native-host/src/vendor/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
  280. package/native-host/src/vendor/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
  281. package/native-host/src/vendor/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
  282. package/native-host/src/vendor/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
  283. package/native-host/src/vendor/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
  284. package/native-host/src/vendor/pdfjs/cmaps/GBT-H.bcmap +0 -0
  285. package/native-host/src/vendor/pdfjs/cmaps/GBT-V.bcmap +0 -0
  286. package/native-host/src/vendor/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
  287. package/native-host/src/vendor/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
  288. package/native-host/src/vendor/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
  289. package/native-host/src/vendor/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
  290. package/native-host/src/vendor/pdfjs/cmaps/H.bcmap +0 -0
  291. package/native-host/src/vendor/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
  292. package/native-host/src/vendor/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
  293. package/native-host/src/vendor/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
  294. package/native-host/src/vendor/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
  295. package/native-host/src/vendor/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
  296. package/native-host/src/vendor/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
  297. package/native-host/src/vendor/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
  298. package/native-host/src/vendor/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
  299. package/native-host/src/vendor/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
  300. package/native-host/src/vendor/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
  301. package/native-host/src/vendor/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
  302. package/native-host/src/vendor/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
  303. package/native-host/src/vendor/pdfjs/cmaps/Hankaku.bcmap +0 -0
  304. package/native-host/src/vendor/pdfjs/cmaps/Hiragana.bcmap +0 -0
  305. package/native-host/src/vendor/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
  306. package/native-host/src/vendor/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
  307. package/native-host/src/vendor/pdfjs/cmaps/KSC-H.bcmap +0 -0
  308. package/native-host/src/vendor/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
  309. package/native-host/src/vendor/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
  310. package/native-host/src/vendor/pdfjs/cmaps/KSC-V.bcmap +0 -0
  311. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
  312. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
  313. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
  314. package/native-host/src/vendor/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
  315. package/native-host/src/vendor/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
  316. package/native-host/src/vendor/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
  317. package/native-host/src/vendor/pdfjs/cmaps/Katakana.bcmap +0 -0
  318. package/native-host/src/vendor/pdfjs/cmaps/LICENSE +36 -0
  319. package/native-host/src/vendor/pdfjs/cmaps/NWP-H.bcmap +0 -0
  320. package/native-host/src/vendor/pdfjs/cmaps/NWP-V.bcmap +0 -0
  321. package/native-host/src/vendor/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
  322. package/native-host/src/vendor/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
  323. package/native-host/src/vendor/pdfjs/cmaps/Roman.bcmap +0 -0
  324. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
  325. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
  326. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
  327. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
  328. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
  329. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
  330. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
  331. package/native-host/src/vendor/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
  332. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
  333. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
  334. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
  335. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
  336. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
  337. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
  338. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
  339. package/native-host/src/vendor/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
  340. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
  341. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
  342. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
  343. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
  344. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
  345. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
  346. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
  347. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
  348. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
  349. package/native-host/src/vendor/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
  350. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
  351. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
  352. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
  353. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
  354. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
  355. package/native-host/src/vendor/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
  356. package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
  357. package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
  358. package/native-host/src/vendor/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
  359. package/native-host/src/vendor/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
  360. package/native-host/src/vendor/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
  361. package/native-host/src/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
  362. package/native-host/src/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
  363. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
  364. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
  365. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
  366. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
  367. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
  368. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
  369. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
  370. package/native-host/src/vendor/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
  371. package/native-host/src/vendor/pdfjs/cmaps/V.bcmap +0 -0
  372. package/native-host/src/vendor/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
  373. package/native-host/src/vendor/pdfjs/pdf.mjs +26740 -0
  374. package/native-host/src/vendor/pdfjs/pdf.worker.mjs +62201 -0
  375. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
  376. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
  377. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
  378. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
  379. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
  380. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
  381. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
  382. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
  383. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
  384. package/native-host/src/vendor/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
  385. package/native-host/src/vendor/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
  386. package/native-host/src/vendor/pdfjs/standard_fonts/LICENSE_LIBERATION +102 -0
  387. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
  388. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
  389. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
  390. package/native-host/src/vendor/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
  391. package/native-host/src/writingStyleEvidence.js +102 -0
  392. package/native-host/src/writingStylePdfWorker.js +35 -0
  393. package/native-host/src/writingStyleProfile.js +165 -0
  394. package/native-host/src/writingStyleRuntime.js +475 -0
  395. package/native-host/src/writingStyleStore.js +73 -0
  396. package/package.json +1 -1
  397. package/scripts/install-managed.mjs +1 -0
@@ -25,6 +25,7 @@
25
25
  const now = new Date().toISOString();
26
26
  return {
27
27
  id: input.id || generateId('aud'),
28
+ accountScopeId: redactSecretLikeText(stringField(input.accountScopeId)),
28
29
  projectId: redactSecretLikeText(stringField(input.projectId)),
29
30
  sessionId: redactSecretLikeText(stringField(input.sessionId)),
30
31
  turnId: redactSecretLikeText(stringField(input.turnId)),
@@ -75,6 +76,7 @@
75
76
  mirror: summarizeMirror(input.mirror),
76
77
  auditLogs: summarizeAuditLogList(input.auditLogs),
77
78
  run: summarizeRun(input.run),
79
+ ...(Array.isArray(input.recentRuns) ? { recentRuns: input.recentRuns.slice(0, 8).map(summarizeRun) } : {}),
78
80
  governance: summarizeGovernance(input.governance),
79
81
  projectIdHash: hashString(stringField(input.projectId))
80
82
  };
@@ -83,6 +85,7 @@
83
85
  function normalizeAuditLogRecord(input = {}) {
84
86
  return {
85
87
  id: redactSecretLikeText(stringField(input.id)) || generateId('aud'),
88
+ accountScopeId: redactSecretLikeText(stringField(input.accountScopeId)),
86
89
  projectId: redactSecretLikeText(stringField(input.projectId)),
87
90
  sessionId: redactSecretLikeText(stringField(input.sessionId)),
88
91
  turnId: redactSecretLikeText(stringField(input.turnId)),
@@ -272,9 +275,22 @@
272
275
  }
273
276
 
274
277
  function summarizeRun(run = {}) {
278
+ run = run && typeof run === 'object' && !Array.isArray(run) ? run : {};
279
+ const captures = Array.isArray(run.trackedChangeCaptures) ? run.trackedChangeCaptures : [];
275
280
  return removeEmptySummaryFields({
276
281
  id: redactSecretLikeText(stringField(run.id)),
277
282
  status: redactSecretLikeText(stringField(run.status)),
283
+ startedAt: redactSecretLikeText(stringField(run.startedAt)),
284
+ finishedAt: redactSecretLikeText(stringField(run.finishedAt)),
285
+ requireReviewing: typeof run.executionSnapshot?.requireReviewing === 'boolean'
286
+ ? run.executionSnapshot.requireReviewing : undefined,
287
+ trackedChangeStatus: diagnosticToken(run.trackedChangeStatus),
288
+ undoStatus: diagnosticToken(run.undoStatus),
289
+ appliedOperationCount: Array.isArray(run.appliedOperations) ? run.appliedOperations.length : undefined,
290
+ undoTrackedChangeCount: Array.isArray(run.undoTrackedChanges) ? run.undoTrackedChanges.length : undefined,
291
+ captureCount: Array.isArray(run.trackedChangeCaptures) ? captures.length : undefined,
292
+ capturesTruncated: captures.length > 20 ? true : undefined,
293
+ trackedChangeCaptures: captures.slice(0, 20).map(summarizeTrackedCapture),
278
294
  errorCode: redactSecretLikeText(stringField(run.errorCode)),
279
295
  errorCategory: categorizeError(run.errorCode || run.message || run.error),
280
296
  events: (Array.isArray(run.events) ? run.events : []).map(event => removeEmptyFields({
@@ -287,6 +303,63 @@
287
303
  });
288
304
  }
289
305
 
306
+ // Export only proof metadata, never document text, prompts, labels or raw IDs.
307
+ function diagnosticToken(value) {
308
+ const text = redactSecretLikeText(stringField(value));
309
+ return /^[a-z][a-z0-9_]{0,79}$/.test(text) ? text : undefined;
310
+ }
311
+
312
+ function diagnosticNumbers(value, keys) {
313
+ const source = value && typeof value === 'object' ? value : {};
314
+ const result = {};
315
+ for (const key of keys) {
316
+ if (Number.isSafeInteger(source[key]) && source[key] >= 0) result[key] = source[key];
317
+ }
318
+ return result;
319
+ }
320
+
321
+ function diagnosticFingerprint(value) {
322
+ return typeof value === 'string' && /^\d{1,16}:[a-f0-9]{1,8}:[a-f0-9]{1,8}$/.test(value)
323
+ ? value : undefined;
324
+ }
325
+
326
+ function summarizeTrackedCapture(value) {
327
+ const capture = value && typeof value === 'object' && !Array.isArray(value) ? value : {};
328
+ const before = Array.isArray(capture.before) ? capture.before : [];
329
+ const refs = Array.isArray(capture.refs) ? capture.refs : [];
330
+ const ranges = Array.isArray(capture.ranges) ? capture.ranges : [];
331
+ const diagnostics = capture.diagnostics || {};
332
+ const refSummary = ref => removeEmptySummaryFields({
333
+ idHash: stringField(ref?.id) ? hashString(ref.id) : undefined,
334
+ kind: diagnosticToken(ref?.kind),
335
+ ...diagnosticNumbers(ref, ['from', 'to', 'textLength']),
336
+ textHash: diagnosticFingerprint(ref?.textHash)
337
+ });
338
+ return removeEmptySummaryFields({
339
+ pathHash: stringField(capture.path) ? hashString(capture.path) : undefined,
340
+ nativeDocIdHash: stringField(capture.nativeDocId) ? hashString(capture.nativeDocId) : undefined,
341
+ state: diagnosticToken(capture.state), reason: diagnosticToken(capture.reason),
342
+ source: diagnosticToken(capture.source),
343
+ ...diagnosticNumbers(capture, ['startedAt', 'expiresAt']),
344
+ expectedFingerprint: diagnosticFingerprint(capture.expected),
345
+ beforeCount: before.length, refCount: refs.length, rangeCount: ranges.length,
346
+ truncated: before.length > 1200 || refs.length > 1200 || ranges.length > 1000 ? true : undefined,
347
+ before: before.slice(0, 1200).map(refSummary),
348
+ refs: refs.slice(0, 1200).map(refSummary),
349
+ ranges: ranges.slice(0, 1000).map(range => removeEmptySummaryFields({
350
+ ...diagnosticNumbers(range, ['from', 'to', 'start', 'end', 'removedLength']),
351
+ removedHash: diagnosticFingerprint(range?.removedHash)
352
+ })),
353
+ diagnostics: removeEmptySummaryFields({
354
+ ...diagnosticNumbers(diagnostics, ['beforeCount', 'afterCount', 'capturedCount',
355
+ 'filteredCount', 'polls', 'elapsedMs', 'waitMs']),
356
+ reason: diagnosticToken(diagnostics.reason),
357
+ source: diagnosticToken(diagnostics.source),
358
+ sourceReason: diagnosticToken(diagnostics.sourceReason)
359
+ })
360
+ });
361
+ }
362
+
290
363
  function summarizeGovernance(rules = {}) {
291
364
  return {
292
365
  readonlyPatternCount: Array.isArray(rules.readonlyPatterns) ? rules.readonlyPatterns.length : 0,
@@ -0,0 +1,94 @@
1
+ (function initChangeHistoryModel(root, factory) {
2
+ if (typeof module === 'object' && module.exports) {
3
+ module.exports = factory(require('./settlementFacts'), require('./sessionState'));
4
+ } else root.CodexOverleafModuleRegistry.define('ChangeHistoryModel', ['SettlementFacts', 'SessionState'], factory);
5
+ })(typeof globalThis !== 'undefined' ? globalThis : window, function changeHistoryModelFactory(SettlementFacts, SessionState) {
6
+ 'use strict';
7
+ const array = value => Array.isArray(value) ? value : [];
8
+ const text = value => typeof value === 'string' ? value : '';
9
+ const opaque = value => /^\[.*(?:omitted|redacted|chars=\d+|hash=).*?\]$/i.test(text(value).trim());
10
+
11
+ function project(records, options = {}) {
12
+ const { projectId, accountScopeId } = options;
13
+ if (!projectId || !accountScopeId) return [];
14
+ const sanitize = options.sanitizeText || text;
15
+ const safe = value => text(sanitize(text(value))).trim();
16
+ const sessions = new Map();
17
+ const live = new Map();
18
+ for (const session of array(options.storedSessions)) {
19
+ if (session?.projectId === projectId && session.accountScopeId === accountScopeId) sessions.set(session.id, session);
20
+ }
21
+ // In-memory sessions already passed the runtime's account/project hydrate
22
+ // boundary. Their review state is newer than the persisted audit snapshot.
23
+ for (const session of array(options.sessions)) {
24
+ if (!session?.id) continue;
25
+ const prior = sessions.get(session.id);
26
+ const runs = new Map(array(prior?.runs).map(run => [run.id, run]));
27
+ const current = session.id === options.activeSessionId ? array(options.activeRuns) : array(session.runs);
28
+ for (const run of current) if (run?.id) runs.set(run.id, run);
29
+ sessions.set(session.id, { ...prior, ...session, runs: [...runs.values()] });
30
+ live.set(session.id, new Set(current.filter(run => run?.id && (!run.runProjectId || run.runProjectId === projectId)).map(run => run.id)));
31
+ }
32
+ function path(value) {
33
+ const raw = text(value).replace(/\\/g, '/').replace(/^\.\//, '');
34
+ if (/(^|\/)\.codex-overleaf-(subagents|attachments)(\/|$)/.test(raw)) return '';
35
+ const result = safe(raw);
36
+ if (!result || /^\[.*\]$/.test(result)) return '';
37
+ return result.slice(0, 320);
38
+ }
39
+ const seen = new Set();
40
+ return array(records).filter(record => record?.projectId === projectId
41
+ && (!record.accountScopeId || record.accountScopeId === accountScopeId)
42
+ && sessions.has(record.sessionId))
43
+ .slice().sort((a, b) => String(b.createdAt || '').localeCompare(String(a.createdAt || '')))
44
+ .filter(record => {
45
+ const key = JSON.stringify([record.sessionId, record.turnId || record.id]);
46
+ if (seen.has(key)) return false;
47
+ seen.add(key); return true;
48
+ }).slice(0, 50).map(record => {
49
+ const session = sessions.get(record.sessionId);
50
+ const candidate = array(session.runs).find(run => run.id === record.turnId);
51
+ const run = candidate && (!candidate.runProjectId || candidate.runProjectId === projectId) ? candidate : null;
52
+ const facts = SettlementFacts.compactSettlementFacts(run?.settlement || run?.settlementFacts || {});
53
+ const projection = run ? SettlementFacts.projectRunSettlement(run) : null;
54
+ const applied = array(record.appliedFiles).filter(file => path(typeof file === 'string' ? file : file?.path));
55
+ const review = text(run?.trackedChangeStatus);
56
+ const hasWrites = applied.length > 0 || run?.changedDocument === true
57
+ || ['changed', 'possibly-changed'].includes(facts.documentEffect)
58
+ || ['pending', 'accepted', 'rejected', 'needs_review'].includes(review)
59
+ || run?.undoStatus === 'applied';
60
+ let files = applied.slice();
61
+ files.push(...facts.fileSettlements.filter(file => ['complete', 'partial'].includes(file.applied)
62
+ || ['changed', 'possibly-changed'].includes(file.documentEffect)));
63
+ if (!files.length && hasWrites) files = array(record.changedFiles);
64
+ const paths = [...new Set(files.flatMap(file => typeof file === 'string'
65
+ ? [path(file)] : [path(file?.path), path(file?.destinationPath)]).filter(Boolean))];
66
+ const unsafeSave = record.saveVerification?.ok === false
67
+ || ['failed', 'unavailable'].includes(record.saveVerification?.state);
68
+ let status;
69
+ if (review === 'accepted') status = 'accepted';
70
+ else if (review === 'rejected' || run?.undoStatus === 'applied') status = 'undone';
71
+ else if (review === 'needs_review' || projection?.terminalState === 'needs_review'
72
+ || facts.documentEffect === 'possibly-changed'
73
+ || ['partial', 'needs-review'].includes(facts.evidence.settled)
74
+ || hasWrites && (unsafeSave || ['failed', 'interrupted', 'needs_review_after_navigation'].includes(run?.status))) status = 'attention';
75
+ else if (run?.status === 'running' || record.resultStatus === 'draft' && !record.completedAt) status = 'running';
76
+ else if (review === 'pending') status = 'pending';
77
+ else if (!hasWrites) status = 'unchanged';
78
+ else status = run ? 'written' : 'unknown';
79
+ const suppliedSummary = safe(run?.safeTaskSummary || '');
80
+ const summary = suppliedSummary && !opaque(suppliedSummary)
81
+ ? SessionState.computeSafeTaskSummary(suppliedSummary) : '';
82
+ // Audit promptSummary deliberately stores a privacy marker. Never
83
+ // recover it, render it, or turn it into an apparent task summary.
84
+ return {
85
+ key: JSON.stringify([record.sessionId, record.turnId || record.id]),
86
+ projectId, accountScopeId, sessionId: record.sessionId, turnId: record.turnId,
87
+ createdAt: text(record.createdAt), paths, hasWrites, status, summary,
88
+ operation: paths.length === 1 ? text(files[0]?.type) : '',
89
+ canJump: Boolean(run && live.get(record.sessionId)?.has(record.turnId))
90
+ };
91
+ });
92
+ }
93
+ return { project };
94
+ });
@@ -12,7 +12,7 @@
12
12
  const MIN_NATIVE_VERSION = '1.0.0';
13
13
  const MIN_COMPATIBLE_NATIVE_VERSION = '1.0.0';
14
14
  const MIN_COMPATIBLE_EXTENSION_VERSION = '1.0.0';
15
- const BUILD_TARGET_VERSION = '2.4.1';
15
+ const BUILD_TARGET_VERSION = '2.5.1';
16
16
  const DEFAULT_CHROME_EXTENSION_ID = 'illdpneeeopfffmiepaejglgmhpmdhdc';
17
17
  const REQUIRED_CAPABILITIES = Object.freeze([
18
18
  'bridgePing',
@@ -25,6 +25,7 @@
25
25
  'codexModels',
26
26
  'historyClearPlugin',
27
27
  'localSkills',
28
+ 'localCodexSkills',
28
29
  'mirrorSensitiveScan',
29
30
  'providerProfiles',
30
31
  'assetTransfer',
@@ -64,6 +65,8 @@
64
65
  }
65
66
 
66
67
  function evaluateNativeCompatibility(response, metadata = {}) {
68
+ if (response?.extensionInstallIdentity) metadata = { ...metadata,
69
+ installIdentity: { ...(metadata.installIdentity || {}), ...response.extensionInstallIdentity } };
67
70
  const native = unwrapNativeResponse(response);
68
71
  if (!native) {
69
72
  return compatibilityResult('native_missing', response, metadata, 'incompatible');
@@ -86,13 +89,25 @@
86
89
  return analyzeNativeCompatibility(native, metadata).classification;
87
90
  }
88
91
 
89
- function buildInstallCommand(version = BUILD_TARGET_VERSION, platform, extensionId) {
92
+ function buildInstallCommand(version = BUILD_TARGET_VERSION, platform, extensionId, options = {}) {
90
93
  const normalized = normalizeReleaseVersion(version) || BUILD_TARGET_VERSION;
91
94
  const allowedExtensionId = normalizeInstallExtensionId(extensionId);
92
95
  const extensionIdArg = allowedExtensionId && allowedExtensionId !== DEFAULT_CHROME_EXTENSION_ID
93
- ? ` --extension-id ${allowedExtensionId}`
94
- : '';
95
-
96
+ ? ` --extension-id ${allowedExtensionId}` : '';
97
+ if (options.managed === true) {
98
+ if (!allowedExtensionId || options.extensionId !== allowedExtensionId) return '';
99
+ const managedRoot = options.managedRoot;
100
+ const browser = options.browser === 'auto' ? 'chrome' : options.browser;
101
+ if (!['chrome', 'chromium'].includes(browser) || typeof managedRoot !== 'string'
102
+ || !managedRoot || managedRoot.length > 4096 || managedRoot.trim() !== managedRoot
103
+ || /[\u0000-\u001f\u007f]/.test(managedRoot)
104
+ || !(/^(?:\/|[a-zA-Z]:[\\/]|\\\\)/.test(managedRoot))) return '';
105
+ // Windows setup commands are shown for PowerShell; POSIX uses sh quoting.
106
+ const quotedRoot = platform === 'win32' || options.platform === 'win32'
107
+ ? "'" + managedRoot.replace(/'/g, "''") + "'"
108
+ : "'" + managedRoot.replace(/'/g, "'\\''") + "'";
109
+ return `npm exec --yes codex-overleaf-link@${normalized} -- install-managed --browser ${browser} --managed-root ${quotedRoot}${extensionIdArg}`;
110
+ }
96
111
  return `npm exec --yes codex-overleaf-link@${normalized} -- install-native${extensionIdArg}`;
97
112
  }
98
113
 
@@ -126,7 +141,7 @@
126
141
  const extensionVersion = resolveMetadataVersion(metadata);
127
142
  const nativeVersion = native && typeof native === 'object' ? native.version : undefined;
128
143
  const platform = native && typeof native === 'object' ? native.platform : undefined;
129
- const updateCommand = buildInstallCommand(BUILD_TARGET_VERSION, platform, metadata.extensionId);
144
+ const updateCommand = buildInstallCommand(BUILD_TARGET_VERSION, platform, metadata.extensionId, metadata.installIdentity);
130
145
  const updateAvailable = isOlderReleaseVersion(nativeVersion, BUILD_TARGET_VERSION);
131
146
  return {
132
147
  status,
@@ -139,6 +154,7 @@
139
154
  requiredVersion: MIN_COMPATIBLE_NATIVE_VERSION,
140
155
  recommendedVersion: BUILD_TARGET_VERSION,
141
156
  updateAvailable,
157
+ ...(metadata.installIdentity ? { installIdentity: metadata.installIdentity } : {}),
142
158
  installCommand: updateCommand,
143
159
  updateCommand,
144
160
  releaseUrl: buildReleaseUrl(BUILD_TARGET_VERSION),
@@ -9,32 +9,18 @@
9
9
 
10
10
  const MAX_LOG_BYTES = 32 * 1024;
11
11
  const COMPILABLE_EXTENSIONS = new Set(['.tex', '.bib', '.sty', '.cls', '.bst', '.bbx', '.cbx']);
12
-
13
12
  function parseCompileResponse(response) {
14
- if (!response || typeof response !== 'object') {
15
- return { ok: false, reason: 'Invalid compile response: not an object' };
16
- }
17
-
18
- if (!Array.isArray(response.outputFiles)) {
19
- return { ok: false, reason: 'Invalid compile response: outputFiles is not an array' };
20
- }
21
-
13
+ if (!response || typeof response !== 'object') return { ok: false, reason: 'Invalid compile response: not an object' };
14
+ if (!Array.isArray(response.outputFiles)) return { ok: false, reason: 'Invalid compile response: outputFiles is not an array' };
22
15
  const logFile = response.outputFiles.find(function (file) {
23
16
  if (!file) return false;
24
17
  if (file.type === 'log') return true;
25
18
  if (typeof file.path === 'string' && file.path.endsWith('.log')) return true;
26
19
  return false;
27
20
  });
28
-
29
- if (!logFile) {
30
- return { ok: false, reason: 'No log file found in compile output' };
31
- }
32
-
21
+ if (!logFile) return { ok: false, reason: 'No log file found in compile output' };
33
22
  var logUrl = logFile.url || null;
34
- if (!logUrl) {
35
- return { ok: false, reason: 'Log file has no URL' };
36
- }
37
-
23
+ if (!logUrl) return { ok: false, reason: 'Log file has no URL' };
38
24
  return {
39
25
  ok: true,
40
26
  status: response.status,
@@ -82,13 +68,9 @@
82
68
  }
83
69
 
84
70
  function truncateLogForContext(log) {
85
- if (!log || typeof log !== 'string') {
86
- return '';
87
- }
71
+ if (!log || typeof log !== 'string') return '';
88
72
 
89
- if (new Blob([log]).size <= MAX_LOG_BYTES) {
90
- return log;
91
- }
73
+ if (new Blob([log]).size <= MAX_LOG_BYTES) return log;
92
74
 
93
75
  var lines = log.split('\n');
94
76
  var errorBlocks = extractErrorBlocks(lines);
@@ -108,26 +90,17 @@
108
90
  }
109
91
 
110
92
  function isCompileLogFresh(log, lastKnownSourceEditTimestamp) {
111
- if (!log || typeof log !== 'object') {
112
- return false;
113
- }
114
-
115
- if (log.sourceChangeTimestamp == null) {
116
- return false;
117
- }
93
+ if (!log || typeof log !== 'object') return false;
94
+ if (log.sourceChangeTimestamp == null) return false;
118
95
 
119
96
  return log.sourceChangeTimestamp >= lastKnownSourceEditTimestamp;
120
97
  }
121
98
 
122
99
  function isCompilableFile(filePath) {
123
- if (!filePath || typeof filePath !== 'string') {
124
- return false;
125
- }
100
+ if (!filePath || typeof filePath !== 'string') return false;
126
101
 
127
102
  var lastDot = filePath.lastIndexOf('.');
128
- if (lastDot === -1) {
129
- return false;
130
- }
103
+ if (lastDot === -1) return false;
131
104
 
132
105
  var ext = filePath.slice(lastDot).toLowerCase();
133
106
  return COMPILABLE_EXTENSIONS.has(ext);
@@ -163,7 +136,98 @@
163
136
  return result;
164
137
  }
165
138
 
139
+ function buildPostWriteCompileSummary({ result = null, logResult = null, error = null } = {}) {
140
+ const logAvailable = logResult?.ok === true;
141
+ const errors = logAvailable && Array.isArray(logResult.errors)
142
+ ? logResult.errors.slice(0, 5).map(formatCompileDiagnosticForSummary)
143
+ : [];
144
+ const warnings = logAvailable && Array.isArray(logResult.warnings)
145
+ ? logResult.warnings.slice(0, 5).map(formatCompileDiagnosticForSummary)
146
+ : [];
147
+ const failed = Boolean(error) || !result?.ok;
148
+ return {
149
+ status: failed ? 'failed' : result.compile?.status || 'triggered',
150
+ reason: error ? error?.message || 'Post-write compile failed.'
151
+ : !result?.ok ? result?.reason || 'Post-write compile did not succeed.' : result.reason || '',
152
+ errors,
153
+ warnings,
154
+ logAvailable
155
+ };
156
+ }
157
+
158
+ function formatCompileDiagnosticForSummary(value) {
159
+ const text = String(value || '').replace(/\s+/g, ' ').trim();
160
+ return text.length > 180 ? `${text.slice(0, 179)}...` : text;
161
+ }
162
+
163
+ // Page/adapter-owned explanations and activity labels are display copy. TeX logs and unknown
164
+ // upstream diagnostics stay literal; callers retain the original evidence.
165
+ function localizeCompileReason(value, locale = 'en', depth = 0) {
166
+ const text = String(value || '');
167
+ const zh = /^zh(?:\b|[-_])/i.test(String(locale));
168
+ const messages = [
169
+ ['Compile succeeded.', '编译成功。'],
170
+ ['Overleaf compile was triggered. The page will continue showing progress.', '已触发 Overleaf 编译;页面会继续显示编译进度。'],
171
+ ['Fetching compile log (@compile-log).', '正在获取编译日志 (@compile-log)。'],
172
+ ['Overleaf save state was not verified.', '尚未确认 Overleaf 已保存。'],
173
+ ['No Overleaf Recompile button or compile request template is available.', '没有可用的 Overleaf 重新编译按钮或编译请求模板。'],
174
+ ['Stored compile request template expired. Please click Overleaf Recompile once, then retry.', '已保存的编译请求模板已过期。请先点击一次 Overleaf 重新编译,再重试。'],
175
+ ['CompileAdapter not available', '编译适配器不可用'],
176
+ ['CompileAdapter not loaded', '编译适配器未加载'],
177
+ ['Overleaf save-state checker is unavailable.', 'Overleaf 保存状态检查器不可用。'],
178
+ ['No compile log URL available', '没有可用的编译日志地址'],
179
+ ['Clicked Overleaf Recompile, but no compile result was captured.', '已点击 Overleaf 重新编译,但未获取到编译结果。'],
180
+ ['Invalid compile response: not an object', '编译响应无效:结果不是对象'],
181
+ ['Invalid compile response: outputFiles is not an array', '编译响应无效:outputFiles 不是数组'],
182
+ ['No log file found in compile output', '编译输出中未找到日志文件'],
183
+ ['Log file has no URL', '日志文件没有可用地址'],
184
+ ['Post-write compile failed.', '写后编译失败。'],
185
+ ['Post-write compile did not succeed.', '写后编译未成功。'],
186
+ ['Overleaf save state has not been checked yet.', '尚未检查 Overleaf 保存状态。'],
187
+ ['Overleaf save state is unavailable.', 'Overleaf 保存状态不可用。'],
188
+ ['Overleaf is offline; saving cannot be confirmed.', 'Overleaf 当前离线,无法确认保存。'],
189
+ ['Overleaf document is unavailable for save-state detection.', 'Overleaf 文档不可用,无法检测保存状态。'],
190
+ ['Overleaf save indicator reports changes are not saved.', 'Overleaf 保存指示器显示修改尚未保存。'],
191
+ ['Overleaf is still saving or syncing changes.', 'Overleaf 仍在保存或同步修改。'],
192
+ ['Overleaf save indicator was present, but did not verify that all changes are saved.', '已找到 Overleaf 保存指示器,但未能确认全部修改已保存。'],
193
+ ['Overleaf save indicator was not found.', '未找到 Overleaf 保存指示器。']
194
+ ];
195
+ for (const [en, chinese] of messages) {
196
+ if (text === en || text === chinese) return zh ? chinese : en;
197
+ }
198
+ for (const [en, chinese] of [
199
+ ['Compile request failed with status ', '编译请求失败,状态码为 '],
200
+ ['Failed to fetch compile log: ', '获取编译日志失败,状态码为 ']
201
+ ]) {
202
+ const prefix = text.startsWith(en) ? en : text.startsWith(chinese) ? chinese : '';
203
+ if (prefix && /^\d{3}$/.test(text.slice(prefix.length))) return (zh ? chinese : en) + text.slice(prefix.length);
204
+ }
205
+ if (depth < 4) for (const [en, chinese] of [
206
+ ['Post-write compile did not succeed: ', '写后编译未成功:'],
207
+ ['Post-write compile failed: ', '写后编译出错:'],
208
+ ['Compile log unavailable: ', '编译日志不可用:'],
209
+ ['Compile request error: ', '编译请求出错:'],
210
+ ['Overleaf save-state checker failed: ', 'Overleaf 保存状态检查失败:'],
211
+ ['Could not check Overleaf save state: ', '无法检查 Overleaf 保存状态:'],
212
+ ['Could not get fresh compile: ', '无法获取最新编译结果:'],
213
+ ['Log fetch error: ', '获取日志出错:'],
214
+ ['Timed out waiting for Overleaf to finish saving changes.', '等待 Overleaf 完成保存超时。'],
215
+ ['Timed out waiting for a verified Overleaf save state.', '等待确认 Overleaf 保存状态超时。']
216
+ ]) {
217
+ const prefix = text.startsWith(en) ? en : text.startsWith(chinese) ? chinese : '';
218
+ if (prefix) {
219
+ const rest = text.slice(prefix.length);
220
+ if (prefix === en && en.endsWith('.') && rest && !rest.startsWith(' ')) continue;
221
+ const suffix = localizeCompileReason(prefix === en && en.endsWith('.') ? rest.slice(1) : rest, locale, depth + 1);
222
+ return (zh ? chinese : en) + (!zh && suffix && en.endsWith('.') ? ' ' : '') + suffix;
223
+ }
224
+ }
225
+ return text;
226
+ }
166
227
  return {
228
+ buildPostWriteCompileSummary,
229
+ formatCompileDiagnosticForSummary,
230
+ localizeCompileReason,
167
231
  COMPILABLE_EXTENSIONS,
168
232
  MAX_LOG_BYTES,
169
233
  extractErrorBlocks,
@@ -0,0 +1,151 @@
1
+ (function (root, factory) {
2
+ if (typeof module === 'object' && module.exports) module.exports = factory(require('./sessionState'));
3
+ else root.CodexOverleafModuleRegistry.define('ComposerAttachmentDraft', ['SessionState'], factory);
4
+ })(typeof globalThis !== 'undefined' ? globalThis : this, function (SessionState) {
5
+ 'use strict';
6
+ const EPOCH_KEY = 'composer-attachment-draft:clear-epoch';
7
+ const normalize = value => SessionState.normalizeComposerAttachmentsForPersistence(value);
8
+ const scopeKey = scope => JSON.stringify([scope?.accountScopeId || '', scope?.projectId || '']);
9
+ function checkedScope(scope) {
10
+ const accountScopeId = String(scope?.accountScopeId || '').trim();
11
+ const projectId = String(scope?.projectId || '').trim();
12
+ if (!accountScopeId || !projectId) throw failure('account_scope_unavailable');
13
+ return { accountScopeId, projectId };
14
+ }
15
+ function failure(code) {
16
+ return Object.assign(new Error(code === 'composer_draft_cleared'
17
+ ? 'Saved attachments were cleared in another tab. Reload, then reattach files before retrying.'
18
+ : code === 'composer_draft_conflict'
19
+ ? 'The saved attachment draft changed in another tab. Reload before changing it.'
20
+ : 'Attachment draft scope is unavailable or changed.'), { code });
21
+ }
22
+ function createStore(openDb) {
23
+ async function access(input, value) {
24
+ const scope = checkedScope(input);
25
+ const id = 'composer-attachment-draft:' + scopeKey(scope);
26
+ const db = await openDb();
27
+ return new Promise((resolve, reject) => {
28
+ const tx = db.transaction('artifacts', value ? 'readwrite' : 'readonly');
29
+ const store = tx.objectStore('artifacts');
30
+ let result, error;
31
+ tx.oncomplete = () => resolve(result);
32
+ tx.onerror = tx.onabort = () => reject(error || tx.error || new Error('Attachment draft transaction failed.'));
33
+ const epochRequest = store.get(EPOCH_KEY);
34
+ epochRequest.onsuccess = () => {
35
+ const epoch = Number(epochRequest.result?.epoch) || 0;
36
+ const clearedAt = Number(epochRequest.result?.clearedAt) || 0;
37
+ const request = store.get(id);
38
+ request.onsuccess = () => {
39
+ try {
40
+ const previous = request.result;
41
+ if (previous && (previous.accountScopeId !== scope.accountScopeId || previous.projectId !== scope.projectId)) {
42
+ throw failure('account_scope_unavailable');
43
+ }
44
+ const revision = Number(previous?.revision) || 0;
45
+ result = { epoch, clearedAt, revision, attachments: normalize(previous?.attachments) };
46
+ if (!value) return;
47
+ const attachments = normalize(value.attachments);
48
+ if (value.epoch !== epoch) {
49
+ // A clear performed by this page also invalidates its old base.
50
+ // Its empty draft needs no write; an old nonempty draft cannot return.
51
+ if (!attachments.length) return;
52
+ throw failure('composer_draft_cleared');
53
+ }
54
+ if (value.revision !== revision) throw failure('composer_draft_conflict');
55
+ if (attachments.length && value.unbased && clearedAt && value.changedAt <= clearedAt) {
56
+ throw failure('composer_draft_cleared');
57
+ }
58
+ result = { epoch, clearedAt, revision: revision + 1, attachments };
59
+ store.put({ id, type: 'composer-attachment-draft', ...scope, ...result });
60
+ } catch (caught) { error = caught; tx.abort(); }
61
+ };
62
+ };
63
+ });
64
+ }
65
+ async function clear(storeNames) {
66
+ const db = await openDb();
67
+ return new Promise((resolve, reject) => {
68
+ const tx = db.transaction(storeNames, 'readwrite');
69
+ const artifacts = tx.objectStore('artifacts');
70
+ const request = artifacts.get(EPOCH_KEY);
71
+ let epoch;
72
+ request.onsuccess = () => {
73
+ epoch = (Number(request.result?.epoch) || 0) + 1;
74
+ for (const name of storeNames) tx.objectStore(name).clear();
75
+ artifacts.put({ id: EPOCH_KEY, type: 'composer-attachment-draft-epoch', epoch, clearedAt: Date.now() });
76
+ };
77
+ tx.oncomplete = () => resolve({ composerDraftEpoch: epoch });
78
+ tx.onerror = tx.onabort = () => reject(tx.error || new Error('History clear failed.'));
79
+ });
80
+ }
81
+ return { read: scope => access(scope), write: (scope, value) => access(scope, value), clear };
82
+ }
83
+
84
+ function createController(options) {
85
+ let scope = options.getScope(), key = scopeKey(scope), generation = 0;
86
+ let base = null, hydrated = false, changedVersion = 0, savedVersion = 0;
87
+ let dirtySince = 0, dirtyUnbased = false, loadSequence = 0;
88
+ let saving = Promise.resolve();
89
+ const publish = () => options.setAttachments(normalize(options.getAttachments()));
90
+ function syncScope() {
91
+ const next = options.getScope(), nextKey = scopeKey(next);
92
+ if (nextKey === key) return;
93
+ scope = next; key = nextKey; generation++;
94
+ base = null; hydrated = false; changedVersion = savedVersion = 0; dirtySince = 0; dirtyUnbased = false;
95
+ options.clear(); publish();
96
+ }
97
+ async function load(requestedScope = options.getScope()) {
98
+ syncScope();
99
+ if (scopeKey(requestedScope) !== key) throw failure('stale_hydration');
100
+ const captured = generation, sequence = ++loadSequence;
101
+ const snapshot = await options.read(checkedScope(scope));
102
+ if (captured !== generation || sequence !== loadSequence || scopeKey(options.getScope()) !== key) throw failure('stale_hydration');
103
+ if (base && snapshot.epoch !== base.epoch) {
104
+ // Adopt an observed history clear together with its empty local view;
105
+ // otherwise the next edit could attach an old view to the new epoch.
106
+ options.clear(); changedVersion = savedVersion = 0; dirtySince = 0; dirtyUnbased = false;
107
+ hydrated = false; base = snapshot; publish();
108
+ }
109
+ const keepLocal = changedVersion || hydrated;
110
+ // A read alone does not give an unchanged visible draft a newer CAS base.
111
+ if (!base || !keepLocal) base = snapshot;
112
+ return keepLocal ? normalize(options.getAttachments()) : snapshot.attachments;
113
+ }
114
+ function hydrate(attachments) {
115
+ syncScope();
116
+ if (hydrated) return;
117
+ // Loading is allowed to finish after a local add/remove. Local edits win.
118
+ if (!changedVersion && !options.getAttachments().length) options.restore(normalize(attachments));
119
+ hydrated = true; publish();
120
+ }
121
+ function changed() {
122
+ const before = key;
123
+ syncScope();
124
+ if (before !== key) return;
125
+ if (changedVersion === savedVersion) { dirtySince = Date.now(); dirtyUnbased = !base; }
126
+ changedVersion++; hydrated = true; publish(); options.scheduleSave();
127
+ }
128
+ function save(requestedScope = options.getScope()) {
129
+ syncScope();
130
+ if (scopeKey(requestedScope) !== key) return Promise.resolve();
131
+ const captured = generation;
132
+ const work = async () => {
133
+ if (captured !== generation || scopeKey(options.getScope()) !== key || changedVersion === savedVersion) return;
134
+ const version = changedVersion;
135
+ const attachments = normalize(options.getAttachments());
136
+ const unbased = dirtyUnbased, changedAt = dirtySince;
137
+ if (!base) await load(scope);
138
+ if (captured !== generation || scopeKey(options.getScope()) !== key) return;
139
+ const written = await options.write(checkedScope(scope), { ...base, attachments, unbased, changedAt });
140
+ if (captured !== generation) return;
141
+ base = written; savedVersion = version;
142
+ if (changedVersion === version) { dirtySince = 0; dirtyUnbased = false; }
143
+ };
144
+ const next = saving.then(work, work);
145
+ saving = next.catch(() => {});
146
+ return next;
147
+ }
148
+ return { syncScope, load, hydrate, changed, save };
149
+ }
150
+ return { createStore, createController, normalize, EPOCH_KEY };
151
+ });
@@ -0,0 +1,43 @@
1
+ (function (root, factory) {
2
+ if (typeof module === 'object' && module.exports) module.exports = factory();
3
+ else if (root.CodexOverleafModuleRegistry) root.CodexOverleafModuleRegistry.define('DirectoryCleanupProof', [], factory);
4
+ else root.CodexOverleafDirectoryCleanupProof = factory();
5
+ })(typeof globalThis !== 'undefined' ? globalThis : window, function () {
6
+ 'use strict';
7
+ const LIMITS = Object.freeze({ maxDirectories: 100, maxBytes: 64 * 1024 });
8
+ const id = (value, max = 160) => typeof value === 'string' && value.length > 0 && value.length <= max
9
+ && value.trim() === value && !/[\u0000-\u001f\u007f]/.test(value);
10
+ const path = value => id(value, 2048) && !/[\\]/.test(value) && !value.startsWith('/') && !/^[A-Za-z]:/.test(value)
11
+ && !value.split('/').some(part => !part || part === '.' || part === '..');
12
+ const ownerKeys = ['accountScopeId', 'projectId', 'sessionId', 'runId'];
13
+ function normalize(value) {
14
+ if (!value || value.v !== 1 || !ownerKeys.every(key => id(value[key])) || !Array.isArray(value.directories)
15
+ || !value.directories.length || value.directories.length > LIMITS.maxDirectories) return null;
16
+ const directories = [], seen = new Set();
17
+ for (const raw of value.directories) {
18
+ if (raw?.v !== 1 || raw.projectId !== value.projectId || !path(raw.path)
19
+ || typeof raw.nativeFolderId !== 'string' || (raw.nativeFolderId && !id(raw.nativeFolderId, 256))) return null;
20
+ const key = JSON.stringify([raw.path, raw.nativeFolderId]);
21
+ if (seen.has(key)) continue;
22
+ seen.add(key);
23
+ directories.push({ v: 1, projectId: raw.projectId, path: raw.path, nativeFolderId: raw.nativeFolderId,
24
+ // No current producer has an acknowledged server-side creator ID.
25
+ ownershipConfirmed: false, observedAfterCreate: raw.observedAfterCreate === true });
26
+ }
27
+ const result = { v: 1, ...Object.fromEntries(ownerKeys.map(key => [key, value[key]])), directories };
28
+ const bytes = typeof TextEncoder === 'function' ? new TextEncoder().encode(JSON.stringify(result)).length : JSON.stringify(result).length * 2;
29
+ return bytes <= LIMITS.maxBytes ? result : null;
30
+ }
31
+ function merge(owner, previous, directories) {
32
+ const prior = previous == null ? null : normalize(previous);
33
+ if (previous != null && (!prior || ownerKeys.some(key => prior[key] !== owner[key]))) return null;
34
+ const combined = [...(prior?.directories || [])];
35
+ for (const next of directories || []) {
36
+ const index = combined.findIndex(item => item.path === next?.path && item.projectId === next?.projectId
37
+ && (!item.nativeFolderId || item.nativeFolderId === next?.nativeFolderId));
38
+ if (index < 0) combined.push(next); else combined[index] = next;
39
+ }
40
+ return normalize({ v: 1, ...owner, directories: combined });
41
+ }
42
+ return { LIMITS, normalize, merge };
43
+ });