@logictan/dsh-config-manager 0.1.60

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 (429) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +105 -0
  3. package/cordis.patch.yml +21 -0
  4. package/lib/adapters/agent-instructions.d.ts +13 -0
  5. package/lib/adapters/agent-instructions.js +46 -0
  6. package/lib/adapters/agent-presets.d.ts +13 -0
  7. package/lib/adapters/agent-presets.js +14 -0
  8. package/lib/adapters/credentials.d.ts +37 -0
  9. package/lib/adapters/credentials.js +122 -0
  10. package/lib/adapters/file-collection.d.ts +15 -0
  11. package/lib/adapters/file-collection.js +127 -0
  12. package/lib/adapters/index.d.ts +57 -0
  13. package/lib/adapters/index.js +55 -0
  14. package/lib/adapters/link-report.d.ts +16 -0
  15. package/lib/adapters/link-report.js +47 -0
  16. package/lib/adapters/mcp.d.ts +28 -0
  17. package/lib/adapters/mcp.js +178 -0
  18. package/lib/adapters/plugin-files.d.ts +18 -0
  19. package/lib/adapters/plugin-files.js +142 -0
  20. package/lib/adapters/plugins.d.ts +41 -0
  21. package/lib/adapters/plugins.js +603 -0
  22. package/lib/adapters/pnpm-workspace.d.ts +26 -0
  23. package/lib/adapters/pnpm-workspace.js +147 -0
  24. package/lib/adapters/prompts.d.ts +30 -0
  25. package/lib/adapters/prompts.js +231 -0
  26. package/lib/adapters/providers.d.ts +34 -0
  27. package/lib/adapters/providers.js +155 -0
  28. package/lib/adapters/self.d.ts +17 -0
  29. package/lib/adapters/self.js +71 -0
  30. package/lib/adapters/sessions.d.ts +14 -0
  31. package/lib/adapters/sessions.js +15 -0
  32. package/lib/adapters/settings.d.ts +28 -0
  33. package/lib/adapters/settings.js +165 -0
  34. package/lib/adapters/skills.d.ts +13 -0
  35. package/lib/adapters/skills.js +14 -0
  36. package/lib/adapters/test-helpers.d.ts +125 -0
  37. package/lib/adapters/test-helpers.js +236 -0
  38. package/lib/adapters/ui.d.ts +27 -0
  39. package/lib/adapters/ui.js +89 -0
  40. package/lib/adapters/workspaces.d.ts +13 -0
  41. package/lib/adapters/workspaces.js +106 -0
  42. package/lib/client.d.ts +1026 -0
  43. package/lib/client.js +10047 -0
  44. package/lib/core/analyzer.d.ts +99 -0
  45. package/lib/core/analyzer.js +934 -0
  46. package/lib/core/backup.d.ts +138 -0
  47. package/lib/core/backup.js +513 -0
  48. package/lib/core/boot-rescue.d.ts +146 -0
  49. package/lib/core/boot-rescue.js +618 -0
  50. package/lib/core/cache-cleaner.d.ts +31 -0
  51. package/lib/core/cache-cleaner.js +95 -0
  52. package/lib/core/config-lifecycle.d.ts +180 -0
  53. package/lib/core/config-lifecycle.js +481 -0
  54. package/lib/core/config-snapshot.d.ts +135 -0
  55. package/lib/core/config-snapshot.js +424 -0
  56. package/lib/core/config-state.d.ts +70 -0
  57. package/lib/core/config-state.js +177 -0
  58. package/lib/core/consult-source.d.ts +58 -0
  59. package/lib/core/consult-source.js +260 -0
  60. package/lib/core/crash-report.d.ts +84 -0
  61. package/lib/core/crash-report.js +317 -0
  62. package/lib/core/exporter.d.ts +68 -0
  63. package/lib/core/exporter.js +375 -0
  64. package/lib/core/ghost-sweep.d.ts +19 -0
  65. package/lib/core/ghost-sweep.js +52 -0
  66. package/lib/core/importer.d.ts +60 -0
  67. package/lib/core/importer.js +29 -0
  68. package/lib/core/index.d.ts +14 -0
  69. package/lib/core/index.js +14 -0
  70. package/lib/core/journal.d.ts +197 -0
  71. package/lib/core/journal.js +418 -0
  72. package/lib/core/local-plugin-host.d.ts +35 -0
  73. package/lib/core/local-plugin-host.js +120 -0
  74. package/lib/core/local-plugin-pack.d.ts +135 -0
  75. package/lib/core/local-plugin-pack.js +278 -0
  76. package/lib/core/messages.d.ts +310 -0
  77. package/lib/core/messages.js +621 -0
  78. package/lib/core/migration-consult.d.ts +117 -0
  79. package/lib/core/migration-consult.js +363 -0
  80. package/lib/core/migration-history.d.ts +153 -0
  81. package/lib/core/migration-history.js +411 -0
  82. package/lib/core/model-tools.d.ts +50 -0
  83. package/lib/core/model-tools.js +148 -0
  84. package/lib/core/msg-types.d.ts +8 -0
  85. package/lib/core/msg-types.js +6 -0
  86. package/lib/core/phase3-child-crash.d.ts +1 -0
  87. package/lib/core/phase3-child-crash.js +87 -0
  88. package/lib/core/phase3-host.d.ts +138 -0
  89. package/lib/core/phase3-host.js +359 -0
  90. package/lib/core/phase3-prod-child.d.ts +1 -0
  91. package/lib/core/phase3-prod-child.js +35 -0
  92. package/lib/core/phase4-crash-child.d.ts +1 -0
  93. package/lib/core/phase4-crash-child.js +103 -0
  94. package/lib/core/plugin-cli.d.ts +150 -0
  95. package/lib/core/plugin-cli.js +497 -0
  96. package/lib/core/reconcile.d.ts +120 -0
  97. package/lib/core/reconcile.js +389 -0
  98. package/lib/core/recovery-orchestrator.d.ts +94 -0
  99. package/lib/core/recovery-orchestrator.js +327 -0
  100. package/lib/core/restore.d.ts +162 -0
  101. package/lib/core/restore.js +703 -0
  102. package/lib/core/rollback.d.ts +12 -0
  103. package/lib/core/rollback.js +145 -0
  104. package/lib/core/run-registry.d.ts +85 -0
  105. package/lib/core/run-registry.js +157 -0
  106. package/lib/core/startup-barrier.d.ts +53 -0
  107. package/lib/core/startup-barrier.js +77 -0
  108. package/lib/core/types.d.ts +515 -0
  109. package/lib/core/types.js +27 -0
  110. package/lib/core/undo.d.ts +73 -0
  111. package/lib/core/undo.js +87 -0
  112. package/lib/core/validator.d.ts +18 -0
  113. package/lib/core/validator.js +77 -0
  114. package/lib/core/verify-recovery.d.ts +21 -0
  115. package/lib/core/verify-recovery.js +256 -0
  116. package/lib/core/watcher.d.ts +101 -0
  117. package/lib/core/watcher.js +219 -0
  118. package/lib/index.d.ts +238 -0
  119. package/lib/index.js +2764 -0
  120. package/lib/migrations/index.d.ts +29 -0
  121. package/lib/migrations/index.js +56 -0
  122. package/lib/migrations/v1-to-v2.d.ts +9 -0
  123. package/lib/migrations/v1-to-v2.js +10 -0
  124. package/lib/profiles/index.d.ts +4 -0
  125. package/lib/profiles/index.js +5 -0
  126. package/lib/profiles/profile-manager.d.ts +106 -0
  127. package/lib/profiles/profile-manager.js +543 -0
  128. package/lib/schema/config.d.ts +28 -0
  129. package/lib/schema/config.js +165 -0
  130. package/lib/schema/index.d.ts +24 -0
  131. package/lib/schema/index.js +26 -0
  132. package/lib/schema/manifest.d.ts +28 -0
  133. package/lib/schema/manifest.js +109 -0
  134. package/lib/schema/tombstones.d.ts +46 -0
  135. package/lib/schema/tombstones.js +64 -0
  136. package/lib/schema/types.d.ts +232 -0
  137. package/lib/schema/types.js +8 -0
  138. package/lib/schema/versions.d.ts +27 -0
  139. package/lib/schema/versions.js +50 -0
  140. package/lib/security/encryption.d.ts +85 -0
  141. package/lib/security/encryption.js +279 -0
  142. package/lib/security/index.d.ts +16 -0
  143. package/lib/security/index.js +17 -0
  144. package/lib/security/integrity.d.ts +30 -0
  145. package/lib/security/integrity.js +78 -0
  146. package/lib/security/redaction.d.ts +26 -0
  147. package/lib/security/redaction.js +95 -0
  148. package/lib/security/secret-scanner.d.ts +86 -0
  149. package/lib/security/secret-scanner.js +404 -0
  150. package/lib/security/vault.d.ts +59 -0
  151. package/lib/security/vault.js +151 -0
  152. package/lib/security/zip-security.d.ts +27 -0
  153. package/lib/security/zip-security.js +154 -0
  154. package/lib/sync/autosync-config.d.ts +39 -0
  155. package/lib/sync/autosync-config.js +151 -0
  156. package/lib/sync/autosync-scheduler.d.ts +139 -0
  157. package/lib/sync/autosync-scheduler.js +564 -0
  158. package/lib/sync/fs.d.ts +18 -0
  159. package/lib/sync/fs.js +49 -0
  160. package/lib/sync/git/git-transport.d.ts +100 -0
  161. package/lib/sync/git/git-transport.js +437 -0
  162. package/lib/sync/github-auth.d.ts +131 -0
  163. package/lib/sync/github-auth.js +264 -0
  164. package/lib/sync/layout.d.ts +43 -0
  165. package/lib/sync/layout.js +203 -0
  166. package/lib/sync/snapshot-json.d.ts +9 -0
  167. package/lib/sync/snapshot-json.js +107 -0
  168. package/lib/sync/sync-config.d.ts +81 -0
  169. package/lib/sync/sync-config.js +281 -0
  170. package/lib/sync/sync-engine.d.ts +269 -0
  171. package/lib/sync/sync-engine.js +591 -0
  172. package/lib/sync/sync-history.d.ts +42 -0
  173. package/lib/sync/sync-history.js +78 -0
  174. package/lib/sync/sync-selection.d.ts +29 -0
  175. package/lib/sync/sync-selection.js +127 -0
  176. package/lib/sync/sync-session.d.ts +40 -0
  177. package/lib/sync/sync-session.js +54 -0
  178. package/lib/sync/sync-state.d.ts +37 -0
  179. package/lib/sync/sync-state.js +108 -0
  180. package/lib/sync/transport.d.ts +75 -0
  181. package/lib/sync/transport.js +55 -0
  182. package/lib/sync/ui-prefs.d.ts +34 -0
  183. package/lib/sync/ui-prefs.js +109 -0
  184. package/lib/sync/webdav/webdav-transport.d.ts +77 -0
  185. package/lib/sync/webdav/webdav-transport.js +451 -0
  186. package/lib/ui/errors.d.ts +19 -0
  187. package/lib/ui/errors.js +81 -0
  188. package/lib/ui/export-flow.d.ts +82 -0
  189. package/lib/ui/export-flow.js +98 -0
  190. package/lib/ui/i18n.d.ts +289 -0
  191. package/lib/ui/i18n.js +581 -0
  192. package/lib/ui/migration-consult-view.d.ts +91 -0
  193. package/lib/ui/migration-consult-view.js +115 -0
  194. package/lib/ui/progress.d.ts +38 -0
  195. package/lib/ui/progress.js +87 -0
  196. package/lib/ui/report.d.ts +23 -0
  197. package/lib/ui/report.js +153 -0
  198. package/lib/ui/test-helpers.d.ts +69 -0
  199. package/lib/ui/test-helpers.js +154 -0
  200. package/lib/ui/types.d.ts +257 -0
  201. package/lib/ui/types.js +21 -0
  202. package/lib/utils/atomic-write.d.ts +88 -0
  203. package/lib/utils/atomic-write.js +399 -0
  204. package/lib/utils/env-lock.d.ts +393 -0
  205. package/lib/utils/env-lock.js +930 -0
  206. package/lib/utils/hashing.d.ts +17 -0
  207. package/lib/utils/hashing.js +41 -0
  208. package/lib/utils/json.d.ts +24 -0
  209. package/lib/utils/json.js +76 -0
  210. package/lib/utils/logger.d.ts +39 -0
  211. package/lib/utils/logger.js +82 -0
  212. package/lib/utils/paths.d.ts +42 -0
  213. package/lib/utils/paths.js +189 -0
  214. package/lib/utils/proxy.d.ts +69 -0
  215. package/lib/utils/proxy.js +455 -0
  216. package/lib/utils/recursive-walk.d.ts +24 -0
  217. package/lib/utils/recursive-walk.js +134 -0
  218. package/lib/utils/zip.d.ts +54 -0
  219. package/lib/utils/zip.js +285 -0
  220. package/package.json +188 -0
  221. package/src/adapters/agent-instructions.ts +48 -0
  222. package/src/adapters/agent-presets.ts +14 -0
  223. package/src/adapters/credentials.test.ts +90 -0
  224. package/src/adapters/credentials.ts +143 -0
  225. package/src/adapters/file-collection.ts +137 -0
  226. package/src/adapters/files.test.ts +353 -0
  227. package/src/adapters/index.ts +94 -0
  228. package/src/adapters/link-report.test.ts +65 -0
  229. package/src/adapters/link-report.ts +61 -0
  230. package/src/adapters/mcp.test.ts +96 -0
  231. package/src/adapters/mcp.ts +185 -0
  232. package/src/adapters/plugin-files.ts +146 -0
  233. package/src/adapters/plugins.test.ts +326 -0
  234. package/src/adapters/plugins.ts +615 -0
  235. package/src/adapters/pnpm-workspace.test.ts +87 -0
  236. package/src/adapters/pnpm-workspace.ts +150 -0
  237. package/src/adapters/prompts.test.ts +110 -0
  238. package/src/adapters/prompts.ts +230 -0
  239. package/src/adapters/providers.test.ts +126 -0
  240. package/src/adapters/providers.ts +173 -0
  241. package/src/adapters/roundtrip.test.ts +190 -0
  242. package/src/adapters/self.test.ts +92 -0
  243. package/src/adapters/self.ts +75 -0
  244. package/src/adapters/sessions.ts +15 -0
  245. package/src/adapters/settings.test.ts +100 -0
  246. package/src/adapters/settings.ts +187 -0
  247. package/src/adapters/skills.ts +14 -0
  248. package/src/adapters/test-helpers.ts +248 -0
  249. package/src/adapters/ui.test.ts +57 -0
  250. package/src/adapters/ui.ts +108 -0
  251. package/src/adapters/workspaces.test.ts +106 -0
  252. package/src/adapters/workspaces.ts +109 -0
  253. package/src/client/ConfigManagerSection.tsx +90 -0
  254. package/src/client/api.ts +66 -0
  255. package/src/client/client-types.ts +18 -0
  256. package/src/client/common/ErrorBanner.tsx +73 -0
  257. package/src/client/common/Icon.tsx +129 -0
  258. package/src/client/common/Modal.tsx +173 -0
  259. package/src/client/common/ToastViewport.tsx +73 -0
  260. package/src/client/common/toast-store.test.ts +192 -0
  261. package/src/client/common/toast-store.ts +181 -0
  262. package/src/client/common/toast-types.ts +7 -0
  263. package/src/client/common/ui.tsx +342 -0
  264. package/src/client/config-manager.module.css +2971 -0
  265. package/src/client/css-modules.d.ts +8 -0
  266. package/src/client/index.ts +65 -0
  267. package/src/client/locales.ts +56 -0
  268. package/src/client/lucide-icons.d.ts +38 -0
  269. package/src/client/run-store.test.ts +223 -0
  270. package/src/client/run-store.ts +372 -0
  271. package/src/client/sync/SyncConfirmView.tsx +379 -0
  272. package/src/client/sync/SyncHistoryView.test.ts +40 -0
  273. package/src/client/sync/SyncHistoryView.tsx +220 -0
  274. package/src/client/sync/SyncSettingsView.tsx +1535 -0
  275. package/src/client/sync/history-model.test.ts +194 -0
  276. package/src/client/sync/history-model.ts +195 -0
  277. package/src/client/sync/sync-api.test.ts +585 -0
  278. package/src/client/sync/sync-api.ts +543 -0
  279. package/src/client/sync/sync-locales.ts +416 -0
  280. package/src/client/sync/sync-push-preview.test.ts +52 -0
  281. package/src/client/sync/sync-view-v2.test.ts +213 -0
  282. package/src/client/sync/sync-view.test.ts +487 -0
  283. package/src/client/sync/sync-view.ts +759 -0
  284. package/src/core/analyzer.ts +1068 -0
  285. package/src/core/backup.ts +605 -0
  286. package/src/core/boot-rescue.test.ts +847 -0
  287. package/src/core/boot-rescue.ts +737 -0
  288. package/src/core/cache-cleaner.test.ts +169 -0
  289. package/src/core/cache-cleaner.ts +121 -0
  290. package/src/core/config-lifecycle.test.ts +727 -0
  291. package/src/core/config-lifecycle.ts +573 -0
  292. package/src/core/config-snapshot.test.ts +369 -0
  293. package/src/core/config-snapshot.ts +522 -0
  294. package/src/core/config-state.test.ts +381 -0
  295. package/src/core/config-state.ts +207 -0
  296. package/src/core/consult-source.test.ts +199 -0
  297. package/src/core/consult-source.ts +293 -0
  298. package/src/core/crash-report.test.ts +380 -0
  299. package/src/core/crash-report.ts +369 -0
  300. package/src/core/exporter.ts +417 -0
  301. package/src/core/ghost-sweep.test.ts +94 -0
  302. package/src/core/ghost-sweep.ts +67 -0
  303. package/src/core/importer.ts +83 -0
  304. package/src/core/index.ts +56 -0
  305. package/src/core/journal.test.ts +257 -0
  306. package/src/core/journal.ts +518 -0
  307. package/src/core/local-plugin-host.ts +152 -0
  308. package/src/core/local-plugin-pack.test.ts +359 -0
  309. package/src/core/local-plugin-pack.ts +363 -0
  310. package/src/core/messages.test.ts +54 -0
  311. package/src/core/messages.ts +664 -0
  312. package/src/core/migration-consult.test.ts +315 -0
  313. package/src/core/migration-consult.ts +494 -0
  314. package/src/core/migration-history.test.ts +319 -0
  315. package/src/core/migration-history.ts +484 -0
  316. package/src/core/model-tools.test.ts +190 -0
  317. package/src/core/model-tools.ts +208 -0
  318. package/src/core/msg-types.ts +10 -0
  319. package/src/core/phase3-child-crash.ts +95 -0
  320. package/src/core/phase3-host.ts +411 -0
  321. package/src/core/phase3-p1.test.ts +212 -0
  322. package/src/core/phase3-p2b-fingerprint.test.ts +189 -0
  323. package/src/core/phase3-prod-child.ts +36 -0
  324. package/src/core/phase3-production-integration.test.ts +286 -0
  325. package/src/core/phase4-crash-child.ts +101 -0
  326. package/src/core/phase4-crash-injection.test.ts +166 -0
  327. package/src/core/plugin-cli.fs.test.ts +184 -0
  328. package/src/core/plugin-cli.test.ts +137 -0
  329. package/src/core/plugin-cli.ts +563 -0
  330. package/src/core/reconcile.test.ts +392 -0
  331. package/src/core/reconcile.ts +498 -0
  332. package/src/core/recovery-orchestrator.test.ts +145 -0
  333. package/src/core/recovery-orchestrator.ts +366 -0
  334. package/src/core/restore-manage.test.ts +94 -0
  335. package/src/core/restore.ts +849 -0
  336. package/src/core/rollback.ts +151 -0
  337. package/src/core/run-progress.test.ts +237 -0
  338. package/src/core/run-registry.test.ts +232 -0
  339. package/src/core/run-registry.ts +209 -0
  340. package/src/core/smoke.test.ts +842 -0
  341. package/src/core/startup-barrier.ts +99 -0
  342. package/src/core/types.ts +542 -0
  343. package/src/core/undo.ts +116 -0
  344. package/src/core/validator.ts +84 -0
  345. package/src/core/verify-recovery.ts +265 -0
  346. package/src/core/watcher.test.ts +326 -0
  347. package/src/core/watcher.ts +263 -0
  348. package/src/index.facade.test.ts +265 -0
  349. package/src/index.sync.test.ts +217 -0
  350. package/src/index.ts +2975 -0
  351. package/src/migrations/index.ts +71 -0
  352. package/src/migrations/v1-to-v2.ts +17 -0
  353. package/src/profiles/index.ts +8 -0
  354. package/src/profiles/profile-manager.test.ts +282 -0
  355. package/src/profiles/profile-manager.ts +630 -0
  356. package/src/schema/config.ts +165 -0
  357. package/src/schema/index.ts +71 -0
  358. package/src/schema/manifest-schema.test.ts +519 -0
  359. package/src/schema/manifest.ts +124 -0
  360. package/src/schema/tombstones.test.ts +131 -0
  361. package/src/schema/tombstones.ts +89 -0
  362. package/src/schema/types.ts +245 -0
  363. package/src/schema/versions.ts +55 -0
  364. package/src/security/encryption.ts +335 -0
  365. package/src/security/index.ts +16 -0
  366. package/src/security/integrity.ts +102 -0
  367. package/src/security/redaction.ts +101 -0
  368. package/src/security/secret-scanner.ts +445 -0
  369. package/src/security/security.test.ts +1215 -0
  370. package/src/security/vault.test.ts +164 -0
  371. package/src/security/vault.ts +198 -0
  372. package/src/security/zip-security.ts +180 -0
  373. package/src/sync/autosync-config.test.ts +147 -0
  374. package/src/sync/autosync-config.ts +179 -0
  375. package/src/sync/autosync-scheduler.test.ts +490 -0
  376. package/src/sync/autosync-scheduler.ts +646 -0
  377. package/src/sync/fs.ts +48 -0
  378. package/src/sync/git/git-transport.test.ts +673 -0
  379. package/src/sync/git/git-transport.ts +491 -0
  380. package/src/sync/github-auth.test.ts +280 -0
  381. package/src/sync/github-auth.ts +356 -0
  382. package/src/sync/layout.test.ts +270 -0
  383. package/src/sync/layout.ts +222 -0
  384. package/src/sync/snapshot-json.test.ts +119 -0
  385. package/src/sync/snapshot-json.ts +128 -0
  386. package/src/sync/sync-config.test.ts +310 -0
  387. package/src/sync/sync-config.ts +299 -0
  388. package/src/sync/sync-engine.test.ts +1074 -0
  389. package/src/sync/sync-engine.ts +754 -0
  390. package/src/sync/sync-history.test.ts +116 -0
  391. package/src/sync/sync-history.ts +120 -0
  392. package/src/sync/sync-selection.test.ts +186 -0
  393. package/src/sync/sync-selection.ts +143 -0
  394. package/src/sync/sync-session.test.ts +143 -0
  395. package/src/sync/sync-session.ts +77 -0
  396. package/src/sync/sync-state.test.ts +164 -0
  397. package/src/sync/sync-state.ts +131 -0
  398. package/src/sync/transport.test.ts +111 -0
  399. package/src/sync/transport.ts +118 -0
  400. package/src/sync/ui-prefs.test.ts +152 -0
  401. package/src/sync/ui-prefs.ts +135 -0
  402. package/src/sync/webdav/webdav-transport.test.ts +871 -0
  403. package/src/sync/webdav/webdav-transport.ts +535 -0
  404. package/src/ui/errors.test.ts +47 -0
  405. package/src/ui/errors.ts +100 -0
  406. package/src/ui/export-flow.test.ts +87 -0
  407. package/src/ui/export-flow.ts +156 -0
  408. package/src/ui/i18n.ts +590 -0
  409. package/src/ui/migration-consult-view.test.ts +151 -0
  410. package/src/ui/migration-consult-view.ts +178 -0
  411. package/src/ui/progress.test.ts +47 -0
  412. package/src/ui/progress.ts +102 -0
  413. package/src/ui/report.test.ts +101 -0
  414. package/src/ui/report.ts +146 -0
  415. package/src/ui/test-helpers.ts +184 -0
  416. package/src/ui/types.ts +325 -0
  417. package/src/utils/atomic-write.test.ts +312 -0
  418. package/src/utils/atomic-write.ts +422 -0
  419. package/src/utils/env-lock.test.ts +999 -0
  420. package/src/utils/env-lock.ts +1086 -0
  421. package/src/utils/hashing.ts +53 -0
  422. package/src/utils/json.ts +77 -0
  423. package/src/utils/logger.ts +114 -0
  424. package/src/utils/paths.ts +176 -0
  425. package/src/utils/proxy.test.ts +465 -0
  426. package/src/utils/proxy.ts +493 -0
  427. package/src/utils/recursive-walk.test.ts +148 -0
  428. package/src/utils/recursive-walk.ts +145 -0
  429. package/src/utils/zip.ts +332 -0
@@ -0,0 +1,375 @@
1
+ /**
2
+ * Export 编排(规范 §1/§18/§21,设计 §4.4):
3
+ * adapter 收集各分区 → Secret 过滤 → manifest → checksum → ZIP。
4
+ *
5
+ * 安全不变量:
6
+ * - Secret 值默认永不进入导出数据(结构化分区逐一过 SecretScanner);
7
+ * - includeSecrets=true 必须注入 EncryptionProvider(m4 实现),否则拒绝导出;
8
+ * - 注入 EncryptionProvider 时备份标记为加密(encrypted=true):includeSecrets=false
9
+ * 时 secrets.enc 加密空内容占位,备份仍需要密码导入,但不含任何凭据值;
10
+ * - 加密密码/秘密值绝不写入 manifest 与日志。
11
+ */
12
+ import fs from 'node:fs/promises';
13
+ import path from 'node:path';
14
+ import { buildChecksums } from '../utils/hashing.js';
15
+ import { stringifyJsonSafe } from '../utils/json.js';
16
+ import { buildManifest, CHECKSUMS_FILE, MANIFEST_FILE, EXPORTER_NAME } from '../schema/manifest.js';
17
+ import { SECTION_JSON_PATHS, SECTION_FILE_PREFIXES, isFileSection } from '../schema/config.js';
18
+ import { DEFAULT_SENSITIVE_RELS, refreshVault } from '../security/vault.js';
19
+ import { writeZip } from '../utils/zip.js';
20
+ import { msgOf } from './messages.js';
21
+ /** 缺省 SecretScanner:递归黑名单字段剥离(字段名大小写不敏感;二进制/Uint8Array 原样跳过) */
22
+ export function defaultSecretScanner() {
23
+ const SENSITIVE_FIELDS = [
24
+ 'password', 'passwd', 'token', 'accesstoken', 'refreshtoken', 'apikey',
25
+ 'secret', 'credential', 'authorization', 'cookie', 'privatekey', 'clientsecret',
26
+ ];
27
+ /** 仅存「引用名」而非值的字段(如 apiKeyEnv=DEEPSEEK_API_KEY 是环境变量名,不是秘密) */
28
+ const REFERENCE_FIELDS = new Set([
29
+ 'apikeyenv', 'api_key_env', 'apikeyname', 'tokenenv', 'accesstokenenv',
30
+ 'refreshtokenenv', 'clientsecretenv', 'passwordenv',
31
+ ]);
32
+ return {
33
+ scanAndRedact(data) {
34
+ const hits = [];
35
+ const walk = (v, p) => {
36
+ if (v === null || typeof v !== 'object')
37
+ return v;
38
+ if (v instanceof Uint8Array)
39
+ return v; // 二进制内容不按字段展开
40
+ if (Array.isArray(v))
41
+ return v.map((item, i) => walk(item, `${p}[${i}]`));
42
+ const out = {};
43
+ for (const [k, val] of Object.entries(v)) {
44
+ const lower = k.toLowerCase().replace(/[^a-z0-9]/g, '');
45
+ const isRefName = REFERENCE_FIELDS.has(lower);
46
+ const sensitive = !isRefName && SENSITIVE_FIELDS.some((f) => lower.includes(f));
47
+ if (sensitive && typeof val === 'string' && val !== '') {
48
+ hits.push({ path: p === '' ? k : `${p}.${k}`, field: k });
49
+ out[k] = ''; // 值剥离为空串(保留字段名与位置,供「需补录」提示)
50
+ continue;
51
+ }
52
+ out[k] = walk(val, p === '' ? k : `${p}.${k}`);
53
+ }
54
+ return out;
55
+ };
56
+ return { sanitized: walk(data, ''), hits };
57
+ },
58
+ };
59
+ }
60
+ /* ---------------- G-09:文件类分区文本级扫描(只报告,绝不改写) ---------------- */
61
+ /**
62
+ * 单文件扫描字节上限(1 MiB)。超大文件只扫描前 1 MiB:
63
+ * 凭据通常出现在配置/脚本的头部;超过上限的剩余部分放弃扫描,避免单个巨型文件拖垮导出。
64
+ */
65
+ export const FILE_SECTION_SCAN_MAX_BYTES = 1024 * 1024;
66
+ /** 一次导出中所有文件类分区的累计扫描字节上限(16 MiB),防「成千上万小文件」拖慢导出 */
67
+ export const FILE_SECTION_SCAN_TOTAL_BUDGET_BYTES = 16 * 1024 * 1024;
68
+ /** 每个分区最多告警的**不同文件**数(不是 hit 条数);命中仍全量计入 redactedHits(报告统计通道),超出部分由一条汇总告警兜底,避免「真有凭据的文件被静默淹没」或「截断即静默丢失」 */
69
+ export const MAX_FILE_SECTION_WARNINGS_PER_SECTION = 5;
70
+ /** 二进制探测窗口(前 4 KiB 出现 NUL 即视为二进制,不按文本扫描) */
71
+ const BINARY_SNIFF_BYTES = 4096;
72
+ /** 是否为二进制内容(含 NUL 字节 → 不是 UTF-8 文本;避免对二进制做无意义的文本扫描/误报) */
73
+ function looksBinary(bytes) {
74
+ const n = Math.min(bytes.length, BINARY_SNIFF_BYTES);
75
+ for (let i = 0; i < n; i++) {
76
+ if (bytes[i] === 0)
77
+ return true;
78
+ }
79
+ return false;
80
+ }
81
+ /**
82
+ * 文件类分区内容扫描(G-09):
83
+ * - 走注入 scanner 的 `scanText`(只报告不改写;`scanAndRedact` 会剥离值,**不得**用于用户文件);
84
+ * - 扫描档位与 `src/market/prepare.ts` 的导出侧扫描保持一致:默认保守档 +
85
+ * 值形状启发式(`valuePatterns` 默认开),**不启用** `highEntropy`(默认关,误报率高);
86
+ * - 二进制文件(含 NUL)跳过:文本扫描对它无意义且必然误报;
87
+ * - 单文件上限 `FILE_SECTION_SCAN_MAX_BYTES`、累计上限 `FILE_SECTION_SCAN_TOTAL_BUDGET_BYTES`:
88
+ * 超限即停止扫描(不是停止导出),被跳过的部分不产生命中也不产生告警;
89
+ * - scanner 未实现 `scanText`(如 core 内置的字段名黑名单 defaultSecretScanner)→ 返回空,
90
+ * 行为与修复前一致(生产路径注入的是含 scanText 的强化扫描器)。
91
+ *
92
+ * 返回命中清单,`path` 为「分区内文件相对路径」,`field` 为 `line:N`(值永不外泄)。
93
+ */
94
+ function scanFileSectionText(scanner, data) {
95
+ const scanText = scanner.scanText;
96
+ if (typeof scanText !== 'function')
97
+ return [];
98
+ const files = extractFileEntries(data);
99
+ if (files === null)
100
+ return [];
101
+ const hits = [];
102
+ let budget = FILE_SECTION_SCAN_TOTAL_BUDGET_BYTES;
103
+ for (const file of files) {
104
+ if (budget <= 0)
105
+ break;
106
+ const bytes = file.data;
107
+ if (!(bytes instanceof Uint8Array) || bytes.length === 0)
108
+ continue;
109
+ const window = bytes.subarray(0, Math.min(bytes.length, FILE_SECTION_SCAN_MAX_BYTES, budget));
110
+ budget -= window.length;
111
+ if (looksBinary(window))
112
+ continue;
113
+ let text;
114
+ try {
115
+ text = new TextDecoder('utf-8').decode(window);
116
+ }
117
+ catch {
118
+ continue;
119
+ }
120
+ for (const hit of scanText(text)) {
121
+ hits.push({ path: file.relativePath, field: hit.path });
122
+ }
123
+ }
124
+ return hits;
125
+ }
126
+ /** 从分区数据里取出文件条目(非文件类/结构异常 → null;只看 files 数组,不展开其他字段) */
127
+ function extractFileEntries(data) {
128
+ if (data === null || typeof data !== 'object')
129
+ return null;
130
+ const files = data.files;
131
+ if (!Array.isArray(files))
132
+ return null;
133
+ return files.filter((f) => (f !== null && typeof f === 'object'
134
+ && typeof f.relativePath === 'string'
135
+ && f.data instanceof Uint8Array));
136
+ }
137
+ export class Exporter {
138
+ ctx;
139
+ adapters;
140
+ scanner;
141
+ encryption;
142
+ exporterVersion;
143
+ now;
144
+ msg;
145
+ onSection;
146
+ vaultDataDir;
147
+ constructor(opts) {
148
+ this.ctx = opts.ctx;
149
+ this.adapters = opts.adapters;
150
+ this.scanner = opts.scanner ?? defaultSecretScanner();
151
+ this.encryption = opts.encryption ?? null;
152
+ this.exporterVersion = opts.exporterVersion ?? '0.1.0';
153
+ this.now = opts.now ?? (() => new Date());
154
+ this.msg = opts.msg ?? msgOf(opts.ctx);
155
+ this.onSection = opts.onSection;
156
+ this.vaultDataDir = opts.vaultDataDir ?? path.join(opts.ctx.homeDir, 'dsh-config-manager');
157
+ }
158
+ /**
159
+ * 导出:收集 → 过滤 → checksum → manifest → ZIP。
160
+ * 返回 zipPath(含文件名)、manifest、报告。
161
+ */
162
+ async export(options) {
163
+ const { includeSecrets, only } = options;
164
+ if (includeSecrets && !this.encryption) {
165
+ throw new Error(this.msg('export.encryptionRequired'));
166
+ }
167
+ // 1. 选定分区(only 过滤 + 默认包含)
168
+ const selected = this.adapters
169
+ .filter((a) => (only === undefined ? a.defaultIncluded : only.includes(a.id)))
170
+ .map((a) => a.id);
171
+ // 2. 逐 adapter 收集(导出数据)
172
+ const sections = [];
173
+ const warnings = [];
174
+ const redactedHits = [];
175
+ const included = [];
176
+ const excluded = this.adapters.filter((a) => !selected.includes(a.id)).map((a) => a.id);
177
+ // m1 埋点:每导出一个分区前上报真实进度(onSection 抛错不得中断导出)
178
+ let sectionIndex = 0;
179
+ for (const adapter of this.adapters) {
180
+ if (!selected.includes(adapter.id))
181
+ continue;
182
+ sectionIndex += 1;
183
+ try {
184
+ this.onSection?.({ section: adapter.id, index: sectionIndex, total: selected.length });
185
+ }
186
+ catch {
187
+ // 埋点回调失败不影响导出本身(进度是尽力而为)
188
+ }
189
+ let section;
190
+ try {
191
+ section = await adapter.export(this.ctx, options);
192
+ }
193
+ catch (err) {
194
+ // 单个分区失败不拖垮整体(§34.17);如实告警并跳过
195
+ warnings.push(this.msg('export.sectionFailed', { adapter: adapter.id, reason: err instanceof Error ? err.message : String(err) }));
196
+ excluded.push(adapter.id);
197
+ continue;
198
+ }
199
+ // 3. Secret 过滤:结构化数据逐一过 scanner(剥离值);
200
+ // 文件类分区(skills/agentPresets/agentInstructions/pluginFiles/sessions/self)是用户的真实文件,
201
+ // 只做**文本级扫描 + 告警**,绝不改写/剥离内容(见 scanFileSectionText)。
202
+ let sanitized = section.data;
203
+ if (!isFileSection(adapter.id)) {
204
+ const scanned = this.scanner.scanAndRedact(section.data);
205
+ redactedHits.push(...scanned.hits);
206
+ sanitized = scanned.sanitized;
207
+ }
208
+ else {
209
+ const fileHits = scanFileSectionText(this.scanner, section.data);
210
+ if (fileHits.length > 0) {
211
+ // redactedHits 是**报告统计**通道(非告警通道):仍计入全量命中(含同一文件的多行/多形态命中)。
212
+ redactedHits.push(...fileHits);
213
+ // 告警按**文件**去重(G-09/H1):同一路径只告警一次。
214
+ // 修复前按 hit 计数,同一行同时命中「字段名」与「值形状」会产出两条同路径告警,
215
+ // 使少数文件就吃满上限,导致含真实明文凭据的其它文件被静默淹没(实测 redactedHits=8 而 5 条告警全属一个文件)。
216
+ const hitPaths = [];
217
+ const seenPaths = new Set();
218
+ for (const hit of fileHits) {
219
+ if (seenPaths.has(hit.path))
220
+ continue;
221
+ seenPaths.add(hit.path);
222
+ hitPaths.push(hit.path);
223
+ }
224
+ // 上限语义 = 不同**文件**数 ≤ MAX_FILE_SECTION_WARNINGS_PER_SECTION(避免大分区刷屏)
225
+ const warnedPaths = hitPaths.slice(0, MAX_FILE_SECTION_WARNINGS_PER_SECTION);
226
+ for (const hitPath of warnedPaths) {
227
+ warnings.push(this.msg('export.fileSectionSecrets', { section: adapter.id, path: hitPath }));
228
+ }
229
+ // 被截断的文件数必须**显式**汇总告警,否则截断本身又变成静默丢失。
230
+ // 说明:此处未新增消息键(如 export.fileSectionSecretsTruncated)是为避免与并行任务冲突
231
+ // (src/core/messages.ts 属他人改动范围);故复用 export.fileSectionSecrets,仅 path 传汇总文案。
232
+ const truncatedCount = hitPaths.length - warnedPaths.length;
233
+ if (truncatedCount > 0) {
234
+ warnings.push(this.msg('export.fileSectionSecrets', { section: adapter.id, path: `(另有 ${truncatedCount} 个文件命中,详见报告)` }));
235
+ }
236
+ }
237
+ }
238
+ sections.push({ ...section, data: sanitized });
239
+ included.push({ section: adapter.id, counts: section.counts });
240
+ warnings.push(...section.warnings);
241
+ }
242
+ // 4. 组装 ZIP 条目(JSON 分区 + 文件类分区 + secrets.enc + checksums + manifest)
243
+ const entries = [];
244
+ const sectionFlags = buildSectionFlags(sections);
245
+ let containsSecrets = false;
246
+ let encrypted = false;
247
+ let encryption = null;
248
+ for (const section of sections) {
249
+ if (isFileSection(section.sectionId)) {
250
+ const prefix = SECTION_FILE_PREFIXES[section.sectionId];
251
+ const files = section.data.files ?? [];
252
+ for (const file of files) {
253
+ entries.push({ name: `${prefix}${file.relativePath}`, data: file.data });
254
+ }
255
+ continue;
256
+ }
257
+ const jsonPath = SECTION_JSON_PATHS[section.sectionId];
258
+ if (jsonPath === undefined)
259
+ continue;
260
+ entries.push({
261
+ name: jsonPath,
262
+ data: Buffer.from(stringifyJsonSafe(section.data, { space: 2 }), 'utf8'),
263
+ });
264
+ }
265
+ // secrets.enc:有加密提供者即生成。includeSecrets=true 时加密真实的凭据原文;
266
+ // 只勾选加密(不导出密钥)时加密空内容占位,备份仍标记 encrypted(导入需密码),
267
+ // 但绝不把凭据值放进去(containsSecrets 保持 false;安全不变量不破)。
268
+ if (this.encryption) {
269
+ const credentialsFile = path.join(this.ctx.homeDir, '.credentials.yaml');
270
+ let plaintext;
271
+ if (includeSecrets) {
272
+ try {
273
+ const raw = await this.ctx.fs.readFile(credentialsFile);
274
+ plaintext = Buffer.from(raw).toString('utf8');
275
+ }
276
+ catch (err) {
277
+ warnings.push(this.msg('export.credentialsReadFailed', { reason: err instanceof Error ? err.message : String(err) }));
278
+ plaintext = '';
279
+ }
280
+ }
281
+ else {
282
+ plaintext = '';
283
+ }
284
+ const result = await this.encryption.encrypt(plaintext);
285
+ entries.push({ name: 'security/secrets.enc', data: result.blob });
286
+ encryption = result.info;
287
+ containsSecrets = includeSecrets && plaintext !== '';
288
+ encrypted = true;
289
+ }
290
+ // 4b. 文件级 vault(includeSecrets=false:敏感文件明文不进归档 → 镜像到本机 vault)。
291
+ // 尽力而为:任何失败仅记警告,不中断导出。includeSecrets=true 时秘密已加密进归档,
292
+ // 无需镜像(vault 只服务于「明文不进备份」的本机留存场景)。
293
+ let vaultRefreshed = 0;
294
+ if (!includeSecrets) {
295
+ try {
296
+ const vault = await refreshVault(this.ctx.fs, this.vaultDataDir, this.ctx.homeDir, DEFAULT_SENSITIVE_RELS);
297
+ vaultRefreshed = vault.mirrored.length;
298
+ if (vault.mirrored.length > 0) {
299
+ warnings.push(this.msg('export.vaultRefreshed', { count: vault.mirrored.length }));
300
+ }
301
+ for (const s of vault.skipped) {
302
+ warnings.push(this.msg('export.vaultRefreshSkipped', { rel: s.rel, reason: s.reason }));
303
+ }
304
+ }
305
+ catch (err) {
306
+ warnings.push(this.msg('export.vaultRefreshFailed', { reason: err instanceof Error ? err.message : String(err) }));
307
+ }
308
+ }
309
+ // 5. checksums(覆盖除 manifest/checksums 外的全部条目)
310
+ const checksums = buildChecksums(entries);
311
+ entries.push({ name: CHECKSUMS_FILE, data: Buffer.from(stringifyJsonSafe(checksums, { space: 2 }), 'utf8') });
312
+ // 6. manifest(最后写:需要完整分区与安全信息)
313
+ const manifest = buildManifest({
314
+ exporterVersion: this.exporterVersion,
315
+ dshVersion: this.ctx.dshVersion,
316
+ platform: this.ctx.platform,
317
+ arch: this.ctx.arch,
318
+ sections: sectionFlags,
319
+ containsSecrets,
320
+ encrypted,
321
+ encryption,
322
+ exportedAt: this.now().toISOString(),
323
+ });
324
+ entries.push({ name: MANIFEST_FILE, data: Buffer.from(stringifyJsonSafe(manifest, { space: 2 }), 'utf8') });
325
+ // 7. 落盘
326
+ const outPath = options.outPath ?? defaultOutPath(this.now());
327
+ await writeZip(outPath, entries);
328
+ const stat = await fs.stat(outPath);
329
+ // 日志不泄值:只记分区与命中数量
330
+ this.ctx.log.info('导出完成', {
331
+ file: path.basename(outPath),
332
+ sizeBytes: stat.size,
333
+ sections: Object.keys(sectionFlags).filter((k) => sectionFlags[k]),
334
+ redactedFields: redactedHits.length,
335
+ containsSecrets,
336
+ encrypted,
337
+ vaultRefreshed,
338
+ });
339
+ const report = {
340
+ included,
341
+ excluded,
342
+ security: {
343
+ secretsExcluded: !includeSecrets,
344
+ containsSecrets,
345
+ encrypted,
346
+ redactedHits: redactedHits.length,
347
+ vaultRefreshed,
348
+ },
349
+ file: { name: path.basename(outPath), sizeBytes: stat.size },
350
+ warnings,
351
+ };
352
+ return { zipPath: outPath, manifest, report };
353
+ }
354
+ }
355
+ /** 构建 manifest.sections 布尔表(只含实际导出分区) */
356
+ function buildSectionFlags(sections) {
357
+ const flags = {};
358
+ for (const id of Object.keys(SECTION_JSON_PATHS))
359
+ flags[id] = false;
360
+ for (const id of Object.keys(SECTION_FILE_PREFIXES))
361
+ flags[id] = false;
362
+ flags['secrets'] = false;
363
+ for (const section of sections)
364
+ flags[section.sectionId] = true;
365
+ return flags;
366
+ }
367
+ function defaultOutPath(now) {
368
+ const y = now.getFullYear();
369
+ const m = String(now.getMonth() + 1).padStart(2, '0');
370
+ const d = String(now.getDate()).padStart(2, '0');
371
+ return `dsh-config-${y}-${m}-${d}.zip`;
372
+ }
373
+ /** 供报告使用:导出器身份(避免与 manifest 常量重复维护) */
374
+ export const EXPORTER_INFO = { name: EXPORTER_NAME };
375
+ //# sourceMappingURL=exporter.js.map
@@ -0,0 +1,19 @@
1
+ import type { SnapshotEntry } from './types.ts';
2
+ /** 会话文件目录键提取:把会话相对路径归一为会话目录键 <projectKey>/<sessionId>。
3
+ * 分隔符统一为 '/'(兼容 Windows '\');不足两段(无法归一会话目录)返回 null。 */
4
+ export declare function sessionKeyOf(relPath: string): string | null;
5
+ /**
6
+ * 幽灵会话检测(纯函数):
7
+ * 期望存在的会话(快照/备份记录的会话条目)在磁盘 sessions 目录已无任何对应文件 → 幽灵。
8
+ *
9
+ * @param sessionIds 快照/备份记录的会话条目(相对 sessions 基准目录的路径,如
10
+ * 'proj-a/s1/session.jsonl.zstd' 或目录键 'proj-a/s1')
11
+ * @param diskEntries 磁盘 sessions 目录扫描出的实际相对路径(同样相对 sessions 基准目录,
12
+ * 分隔符不限 Windows/Unix)
13
+ * @returns 失效(幽灵)会话键清单(<projectKey>/<sessionId>,去重保序);
14
+ * 仅磁盘有、备份没有的会话不是幽灵(属备份后新建),不返回。
15
+ */
16
+ export declare function sweepGhostSessions(sessionIds: string[], diskEntries: string[]): string[];
17
+ /** 从快照条目中提取「恢复后应存在于磁盘」的会话文件相对路径(sessions 分区、existed=true)。
18
+ * 仅参与过导入且快照时存在的会话文件才算期望项;existed=false(导入新增、恢复时删除)不算。 */
19
+ export declare function expectedSessionRefs(entries: SnapshotEntry[]): string[];
@@ -0,0 +1,52 @@
1
+ /** 会话文件目录键提取:把会话相对路径归一为会话目录键 <projectKey>/<sessionId>。
2
+ * 分隔符统一为 '/'(兼容 Windows '\');不足两段(无法归一会话目录)返回 null。 */
3
+ export function sessionKeyOf(relPath) {
4
+ if (typeof relPath !== 'string' || relPath === '')
5
+ return null;
6
+ const norm = relPath.replace(/\\/g, '/').replace(/\/{2,}/g, '/').replace(/^\/+|\/+$/g, '');
7
+ if (norm === '')
8
+ return null;
9
+ const segments = norm.split('/');
10
+ if (segments.length < 2)
11
+ return null;
12
+ return `${segments[0]}/${segments[1]}`;
13
+ }
14
+ /**
15
+ * 幽灵会话检测(纯函数):
16
+ * 期望存在的会话(快照/备份记录的会话条目)在磁盘 sessions 目录已无任何对应文件 → 幽灵。
17
+ *
18
+ * @param sessionIds 快照/备份记录的会话条目(相对 sessions 基准目录的路径,如
19
+ * 'proj-a/s1/session.jsonl.zstd' 或目录键 'proj-a/s1')
20
+ * @param diskEntries 磁盘 sessions 目录扫描出的实际相对路径(同样相对 sessions 基准目录,
21
+ * 分隔符不限 Windows/Unix)
22
+ * @returns 失效(幽灵)会话键清单(<projectKey>/<sessionId>,去重保序);
23
+ * 仅磁盘有、备份没有的会话不是幽灵(属备份后新建),不返回。
24
+ */
25
+ export function sweepGhostSessions(sessionIds, diskEntries) {
26
+ const disk = new Set();
27
+ for (const d of diskEntries) {
28
+ const key = sessionKeyOf(d);
29
+ if (key !== null)
30
+ disk.add(key);
31
+ }
32
+ const ghosts = [];
33
+ const seen = new Set();
34
+ for (const id of sessionIds) {
35
+ const key = sessionKeyOf(id);
36
+ if (key === null)
37
+ continue; // 无法归一会话目录的条目不参与判定
38
+ if (!disk.has(key) && !seen.has(key)) {
39
+ seen.add(key);
40
+ ghosts.push(key);
41
+ }
42
+ }
43
+ return ghosts;
44
+ }
45
+ /** 从快照条目中提取「恢复后应存在于磁盘」的会话文件相对路径(sessions 分区、existed=true)。
46
+ * 仅参与过导入且快照时存在的会话文件才算期望项;existed=false(导入新增、恢复时删除)不算。 */
47
+ export function expectedSessionRefs(entries) {
48
+ return entries
49
+ .filter((e) => e.kind === 'file' && e.adapter === 'sessions' && e.existed === true)
50
+ .map((e) => e.ref);
51
+ }
52
+ //# sourceMappingURL=ghost-sweep.js.map
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Importer 门面:封装导入 14 步流程(规范 §9),委托 Analyzer 三段式。
3
+ *
4
+ * 1 选 ZIP → 2 校验 ZIP → 3 读 manifest → 4 完整性 → 5 schema → 6 兼容
5
+ * → 7 扫描 → 8 ImportPlan → 9 Preview(Dry Run) → 10 用户确认
6
+ * → 11 快照 → 12 执行 → 13 校验 → 14 结果(失败则回滚)
7
+ *
8
+ * 安全阀:executeImportPlan 必须显式 confirm,否则拒绝(ImportNotConfirmedError)。
9
+ * Dry Run:analyzeImport / createImportPlan 零写入(ZIP 全程内存解析,不进磁盘)。
10
+ */
11
+ import type { ZipArchive, ZipSafetyLimits } from '../utils/zip.ts';
12
+ import type { MsgFunc } from './messages.ts';
13
+ import type { PlanItemProgress } from './analyzer.ts';
14
+ import type { ConfigAdapter, HostContext, ImportAnalysis, ImportDecisions, ImportPlan, ImportResult, SnapshotStore, TransactionSnapshotContext } from './types.ts';
15
+ import type { SectionId } from '../schema/types.ts';
16
+ export interface ImporterOptions {
17
+ ctx: HostContext;
18
+ adapters: ConfigAdapter[];
19
+ snapshotStore: SnapshotStore;
20
+ limits?: ZipSafetyLimits;
21
+ /** 依赖存在性检查器(缺省不检查) */
22
+ dependencyChecker?: (command: string) => Promise<boolean>;
23
+ /** m4 可注入强化版 ZIP 安全解析 */
24
+ parseZipOverride?: (buf: Uint8Array, limits?: ZipSafetyLimits) => ZipArchive;
25
+ /** 消息翻译器(缺省 ctx.msg ?? zh) */
26
+ msg?: MsgFunc;
27
+ }
28
+ export interface ExecuteOptions {
29
+ /** 用户确认(UI 收集);非 true 一律拒绝执行 */
30
+ confirm: boolean;
31
+ /** 用户补录的秘密值(仅内存) */
32
+ secretInputs?: Record<string, string>;
33
+ /** 加密备份解密结果(仅内存;解密必须经 m4 encryption provider) */
34
+ decryptedCredentials?: Map<string, string>;
35
+ /** 任一项失败立即整体回滚(默认 false:单项失败如实记录并继续其余项) */
36
+ rollbackOnError?: boolean;
37
+ /** m1:每完成一个计划项的进度回调(透传给 Analyzer;不传则无埋点) */
38
+ onItem?: (info: PlanItemProgress) => void;
39
+ /** m1:每开始一个计划项的进度回调(供 UI 显示「正在执行项 X」/ 判定跳过按钮;不传则无埋点) */
40
+ onItemStart?: (info: {
41
+ adapter: SectionId;
42
+ index: number;
43
+ total: number;
44
+ detail: string;
45
+ }) => void;
46
+ /** 执行日志回调(逐计划项操作 + 子进程命令行,仅非敏感文本;透传给 Analyzer → ImportContext) */
47
+ onLog?: (line: string) => void;
48
+ /** Phase 4 生产 journal↔snapshot 绑定(deferred;透传给 Analyzer;不传 = 无 journal 绑定) */
49
+ snapshotBinding?: TransactionSnapshotContext;
50
+ }
51
+ export declare class Importer {
52
+ private readonly analyzer;
53
+ constructor(opts: ImporterOptions);
54
+ /** 步骤 1-8 + 分析:只读,返回 ImportAnalysis(含兼容性/路径/依赖/秘密摘要) */
55
+ analyzeImport(zipPath: string): Promise<ImportAnalysis>;
56
+ /** 步骤 9:Dry Run / Preview —— 合并用户冲突决策与路径映射,输出最终可执行计划(零写入) */
57
+ createImportPlan(zipPath: string, decisions: ImportDecisions): Promise<ImportPlan>;
58
+ /** 步骤 10-14:确认 → 快照 → 执行 → 校验 → 结果;失败可整体回滚并如实报告 */
59
+ executeImportPlan(zipPath: string, plan: ImportPlan, opts: ExecuteOptions): Promise<ImportResult>;
60
+ }
@@ -0,0 +1,29 @@
1
+ import { Analyzer } from './analyzer.js';
2
+ export class Importer {
3
+ analyzer;
4
+ constructor(opts) {
5
+ this.analyzer = new Analyzer(opts);
6
+ }
7
+ /** 步骤 1-8 + 分析:只读,返回 ImportAnalysis(含兼容性/路径/依赖/秘密摘要) */
8
+ analyzeImport(zipPath) {
9
+ return this.analyzer.analyzeImport(zipPath);
10
+ }
11
+ /** 步骤 9:Dry Run / Preview —— 合并用户冲突决策与路径映射,输出最终可执行计划(零写入) */
12
+ createImportPlan(zipPath, decisions) {
13
+ return this.analyzer.createImportPlan(zipPath, decisions);
14
+ }
15
+ /** 步骤 10-14:确认 → 快照 → 执行 → 校验 → 结果;失败可整体回滚并如实报告 */
16
+ executeImportPlan(zipPath, plan, opts) {
17
+ return this.analyzer.executeImportPlan(zipPath, plan, {
18
+ confirm: opts.confirm,
19
+ secretInputs: opts.secretInputs,
20
+ decryptedCredentials: opts.decryptedCredentials,
21
+ rollbackOnError: opts.rollbackOnError,
22
+ onItem: opts.onItem,
23
+ onItemStart: opts.onItemStart,
24
+ onLog: opts.onLog,
25
+ snapshotBinding: opts.snapshotBinding,
26
+ });
27
+ }
28
+ }
29
+ //# sourceMappingURL=importer.js.map
@@ -0,0 +1,14 @@
1
+ /**
2
+ * 核心引擎公共出口:m5(适配器)、m6(UI)、m7(测试)与宿主插件统一从这里引用。
3
+ */
4
+ export { Exporter, defaultSecretScanner, EXPORTER_INFO, type ExporterOptions, } from './exporter.ts';
5
+ export { Importer, type ImporterOptions, type ExecuteOptions, } from './importer.ts';
6
+ export { Analyzer, type AnalyzerOptions, } from './analyzer.ts';
7
+ export { createSnapshot, FileSnapshotStore, resolveFileTarget, verifySnapshot, type CreateSnapshotOptions, type FileSnapshotStoreOptions, type SnapshotVerifyResult, } from './backup.ts';
8
+ export { rollback, type RollbackOptions } from './rollback.ts';
9
+ export { planRestore, restore, listSnapshots, type RestoreAction, type RestoreActionKind, type RestoreOptions, type RestorePlan, type RestoreReport, type SnapshotMeta, } from './restore.ts';
10
+ export { computeCompatibility, describeCompatibility, describeSchemaStatus, validateSections, } from './validator.ts';
11
+ export { ImportNotConfirmedError, ImportFailedError, } from './types.ts';
12
+ export type * from './types.ts';
13
+ export { MigrationStore, sanitizeEntry, queryHistory, summarizeHistory, renderExport, parseHistoryQuery, isValidMigrationKind, redactHistoryText, makeHistoryFilename, isHistoryBasename, MIGRATION_HISTORY_DIR, DEFAULT_MIGRATION_RETENTION, MIGRATION_HISTORY_SCHEMA_VERSION, type MigrationKind, type MigrationResult, type MigrationHistoryEntry, type StoredMigrationHistoryEntry, type MigrationQuery, type MigrationHistoryStats, type ExportFormat, type ReadMigrationResult, type AppendResult, type MigrationIo, type MigrationStoreOptions, type MigrationSource, } from './migration-history.ts';
14
+ export type { ExportOptions, ExportSection, ValidationResult, HostContext, SettingsFacade, CredentialsFacade, PluginsFacade, WorkspaceFacade, PatchFileFacade, FileSystemFacade, NamespaceInfo, PluginInfo, ConfigAdapter, Portability, SecretScanner, SensitiveHit, EncryptionProvider, PlanItem, PlanItemKind, ItemResolution, GlobalConflictStrategy, ImportAnalysis, ImportDecisions, ImportPlan, ImportResult, ExecutedItem, ImportContext, SnapshotTarget, SnapshotEntry, Snapshot, SnapshotStore, RollbackReport, PathMapping, PathIssue, CompatibilityInput, CompatibilityScore, ExportReport, ApplyResult, ConflictDecision, } from './types.ts';
@@ -0,0 +1,14 @@
1
+ /**
2
+ * 核心引擎公共出口:m5(适配器)、m6(UI)、m7(测试)与宿主插件统一从这里引用。
3
+ */
4
+ export { Exporter, defaultSecretScanner, EXPORTER_INFO, } from './exporter.js';
5
+ export { Importer, } from './importer.js';
6
+ export { Analyzer, } from './analyzer.js';
7
+ export { createSnapshot, FileSnapshotStore, resolveFileTarget, verifySnapshot, } from './backup.js';
8
+ export { rollback } from './rollback.js';
9
+ export { planRestore, restore, listSnapshots, } from './restore.js';
10
+ export { computeCompatibility, describeCompatibility, describeSchemaStatus, validateSections, } from './validator.js';
11
+ export { ImportNotConfirmedError, ImportFailedError, } from './types.js';
12
+ /* —— 迁移历史引擎(Phase 6) —— */
13
+ export { MigrationStore, sanitizeEntry, queryHistory, summarizeHistory, renderExport, parseHistoryQuery, isValidMigrationKind, redactHistoryText, makeHistoryFilename, isHistoryBasename, MIGRATION_HISTORY_DIR, DEFAULT_MIGRATION_RETENTION, MIGRATION_HISTORY_SCHEMA_VERSION, } from './migration-history.js';
14
+ //# sourceMappingURL=index.js.map