@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,236 @@
1
+ /**
2
+ * 适配器测试基础设施(仿 src/core/smoke.test.ts 的内存 mock 门面)。
3
+ * 仅供 src/adapters/*.test.ts 使用,不参与生产构建语义。
4
+ */
5
+ import { normalizePath } from '../utils/paths.js';
6
+ import { createLogger } from '../utils/logger.js';
7
+ import { sha256Hex } from '../utils/hashing.js';
8
+ import { zhMsg } from '../core/messages.js';
9
+ export class MemFs {
10
+ files = new Map();
11
+ /** 可选(issue #37):详细的链接遍历。测试按需注入;缺省走 listRecursive 回退路径。 */
12
+ listRecursiveDetailed;
13
+ homeDir;
14
+ constructor(homeDir) {
15
+ this.homeDir = homeDir;
16
+ }
17
+ key(p) {
18
+ return normalizePath(p.startsWith(this.homeDir) ? p : `${this.homeDir}/${p}`);
19
+ }
20
+ async readFile(relPath) {
21
+ const v = this.files.get(this.key(relPath));
22
+ if (v === undefined)
23
+ throw new Error(`ENOENT: ${relPath}`);
24
+ return v;
25
+ }
26
+ async writeFile(relPath, data) {
27
+ this.files.set(this.key(relPath), data);
28
+ }
29
+ async exists(relPath) {
30
+ return this.files.has(this.key(relPath));
31
+ }
32
+ async copy(from, to) {
33
+ const v = this.files.get(this.key(from));
34
+ if (v === undefined)
35
+ throw new Error(`ENOENT: ${from}`);
36
+ this.files.set(this.key(to), v);
37
+ }
38
+ async remove(relPath) {
39
+ this.files.delete(this.key(relPath));
40
+ }
41
+ async listRecursive(dir) {
42
+ const base = normalizePath(this.homeDir);
43
+ const prefix = normalizePath(dir) === '' ? base : `${base}/${normalizePath(dir)}`;
44
+ const out = [];
45
+ for (const k of this.files.keys()) {
46
+ if (k === prefix || k.startsWith(prefix + '/')) {
47
+ out.push(k.slice(base.length).replace(/^[\\/]+/, ''));
48
+ }
49
+ }
50
+ return out.sort();
51
+ }
52
+ async mkdir() { }
53
+ }
54
+ /** ns.set 时自动注册(有值即视为对应插件已激活;对齐真实 dsh-settings 的注册语义) */
55
+ class AutoRegisterMap extends Map {
56
+ registered;
57
+ constructor(registered) {
58
+ super();
59
+ this.registered = registered;
60
+ }
61
+ set(key, value) {
62
+ this.registered.add(key);
63
+ return super.set(key, value);
64
+ }
65
+ }
66
+ export class MemSettings {
67
+ /** 已注册命名空间(对齐真实 dsh-settings:插件激活时注册;未注册的 describe/replace 抛错) */
68
+ registered = new Set();
69
+ /** 有值的命名空间自动视为已注册 */
70
+ ns = new AutoRegisterMap(this.registered);
71
+ async describe(namespace, _opts) {
72
+ if (!this.registered.has(namespace))
73
+ throw new Error(`settings namespace "${namespace}" is not registered`);
74
+ const rec = this.ns.get(namespace);
75
+ return {
76
+ value: rec?.value,
77
+ base: rec?.base,
78
+ revision: rec?.revision ?? 0,
79
+ applies: rec?.applies,
80
+ secrets: rec?.secrets ?? [],
81
+ };
82
+ }
83
+ async replace(namespace, value, expectedRevision) {
84
+ if (!this.registered.has(namespace))
85
+ throw new Error(`settings namespace "${namespace}" is not registered`);
86
+ const rec = this.ns.get(namespace);
87
+ if (expectedRevision !== undefined && rec && rec.revision !== expectedRevision) {
88
+ throw new Error(`SETTINGS_CONFLICT: ${namespace} revision ${rec.revision} !== ${expectedRevision}`);
89
+ }
90
+ this.ns.set(namespace, {
91
+ value, revision: (rec?.revision ?? 0) + 1, secrets: rec?.secrets ?? [], base: rec?.base, applies: rec?.applies,
92
+ });
93
+ }
94
+ async update(namespace, patch, expectedRevision) {
95
+ if (!this.registered.has(namespace))
96
+ throw new Error(`settings namespace "${namespace}" is not registered`);
97
+ const rec = this.ns.get(namespace);
98
+ if (expectedRevision !== undefined && rec && rec.revision !== expectedRevision) {
99
+ throw new Error(`SETTINGS_CONFLICT: ${namespace} revision ${rec.revision} !== ${expectedRevision}`);
100
+ }
101
+ const merged = { ...rec?.value, ...patch };
102
+ this.ns.set(namespace, { value: merged, revision: (rec?.revision ?? 0) + 1, secrets: rec?.secrets ?? [] });
103
+ }
104
+ }
105
+ export class MemCredentials {
106
+ values = new Map();
107
+ async describe(ref) {
108
+ const v = this.values.get(ref);
109
+ return { configured: v !== undefined, source: v !== undefined ? 'file' : 'env', writable: true };
110
+ }
111
+ async set(ref, value) { this.values.set(ref, value); }
112
+ async unset(ref) { this.values.delete(ref); }
113
+ }
114
+ export class MemPlugins {
115
+ installed = new Map();
116
+ /** 测试钩子:install 抛错(模拟 npm ERESOLVE / 网络失败) */
117
+ failInstall = false;
118
+ /** 测试钩子:记录最近一次 install 收到的 spec(验证非 registry spec 透传) */
119
+ lastSpec;
120
+ async listInstalled() {
121
+ return [...this.installed.values()];
122
+ }
123
+ async install(pkg, spec) {
124
+ if (this.failInstall)
125
+ throw new Error(`npm error code ERESOLVE: could not resolve ${pkg}`);
126
+ if (this.installed.has(pkg))
127
+ return { needsRestart: false };
128
+ this.lastSpec = spec;
129
+ this.installed.set(pkg, { name: pkg, version: '1.0.0', enabled: true, spec });
130
+ return { needsRestart: true };
131
+ }
132
+ }
133
+ export class MemWorkspace {
134
+ records = new Map();
135
+ async listRecords() { return [...this.records.values()]; }
136
+ async writeRecord(r) { this.records.set(r.id, r); }
137
+ async removeRecord(id) { this.records.delete(id); }
138
+ }
139
+ export class MemPatch {
140
+ lines = new Map();
141
+ async readPatchLines(_file) {
142
+ return [...this.lines.values()];
143
+ }
144
+ async applyPatchChanges(_file, changes) {
145
+ for (const c of changes) {
146
+ if (c.action === 'remove')
147
+ this.lines.delete(c.lineId);
148
+ else
149
+ this.lines.set(c.lineId, { lineId: c.lineId, raw: c.raw });
150
+ }
151
+ }
152
+ }
153
+ export class MemSnapshotStore {
154
+ snapshots = new Map();
155
+ blobs = new Map();
156
+ async save(snapshot, blobs = new Map()) {
157
+ this.snapshots.set(snapshot.id, snapshot);
158
+ for (const [k, v] of blobs)
159
+ this.blobs.set(`${snapshot.id}/${k}`, v);
160
+ return snapshot.id;
161
+ }
162
+ async load(id) {
163
+ const s = this.snapshots.get(id);
164
+ if (!s)
165
+ throw new Error(`snapshot not found: ${id}`);
166
+ return s;
167
+ }
168
+ async readBlob(id, blobPath) {
169
+ const v = this.blobs.get(`${id}/${blobPath}`);
170
+ if (!v)
171
+ throw new Error(`blob not found: ${id}/${blobPath}`);
172
+ return v;
173
+ }
174
+ async updateStatus(id, status) {
175
+ const s = this.snapshots.get(id);
176
+ if (!s)
177
+ throw new Error(`snapshot not found: ${id}`);
178
+ s.status = status;
179
+ }
180
+ }
181
+ export class MockHostContext {
182
+ platform;
183
+ arch = 'x64';
184
+ homeDir;
185
+ dshVersion = '0.1.0-rc.6';
186
+ log;
187
+ profile;
188
+ settings = new MemSettings();
189
+ credentials = new MemCredentials();
190
+ plugins = new MemPlugins();
191
+ workspace = new MemWorkspace();
192
+ patchFile = new MemPatch();
193
+ fs;
194
+ constructor(platform, homeDir, profile) {
195
+ this.platform = platform;
196
+ this.homeDir = homeDir;
197
+ this.profile = profile;
198
+ this.fs = new MemFs(homeDir);
199
+ this.log = createLogger({ level: 'error', sink: () => { } });
200
+ }
201
+ }
202
+ export function makeContext(platform, homeDir, profile) {
203
+ return new MockHostContext(platform, homeDir, profile);
204
+ }
205
+ /** 构造最小合法 manifest(adapter 单测用;真实 manifest 由 exporter 生成) */
206
+ export function makeManifest(platform = 'win32') {
207
+ return {
208
+ schemaVersion: 1,
209
+ exporter: { name: 'dsh-config-manager-test', version: '0.0.0' },
210
+ source: { dshVersion: '0.1.0-rc.6', platform: platform, arch: 'x64' },
211
+ exportedAt: new Date('2026-08-14T12:00:00.000Z').toISOString(),
212
+ sections: {
213
+ settings: false, ui: false, providers: false, plugins: false, mcp: false, prompts: false,
214
+ skills: false, agentPresets: false, agentInstructions: false, workspaces: false, pluginFiles: false,
215
+ credentialsStatus: false, secrets: false, sessions: false, self: false,
216
+ },
217
+ security: { containsSecrets: false, encrypted: false, encryption: null },
218
+ };
219
+ }
220
+ /** 构造 ImportContext(adapter 单测用;sections 键运行时即 SectionId 字符串) */
221
+ export function makeImportContext(target, sections, overrides = {}) {
222
+ return {
223
+ manifest: makeManifest(target.platform),
224
+ targetPlatform: target.platform,
225
+ target,
226
+ sections: sections,
227
+ pathMappings: [],
228
+ resolutions: {},
229
+ secretInputs: {},
230
+ log: target.log,
231
+ msg: zhMsg,
232
+ ...overrides,
233
+ };
234
+ }
235
+ export { sha256Hex };
236
+ //# sourceMappingURL=test-helpers.js.map
@@ -0,0 +1,27 @@
1
+ /**
2
+ * ui 分区 adapter(设计 §3.3/§4.1/§4.3):
3
+ * 数据源 = settings.yaml 中「UI 类」namespace(pet / dsh-better-sidebar / remote-web-ui / ui-onboarding / skin 等)。
4
+ * localStorage 等 Host 不可迁移的 UI 状态以 uiMigrationNotes 纯说明形式导出(不含任何值)。
5
+ */
6
+ import type { UiSection } from '../schema/types.ts';
7
+ import type { MsgFunc } from '../core/messages.ts';
8
+ import type { ApplyResult, ConfigAdapter, ExportOptions, ExportSection, HostContext, ImportContext, PlanItem, ValidationResult } from '../core/types.ts';
9
+ import { type NamespaceProvider } from './settings.ts';
10
+ /** UI 类 namespace 前缀名单(设计 §4.1;随新插件扩展,只影响「某一 namespace 归哪一边」,不影响数据完整性) */
11
+ export declare const KNOWN_UI_NAMESPACE_PREFIXES: readonly string[];
12
+ /** namespace 名是否属于 UI 类(大小写不敏感前缀匹配) */
13
+ export declare function isUiNamespace(name: string): boolean;
14
+ /** localStorage 等 Host 无通道的 UI 状态说明(纯说明,不含值;研究报告 §2.2/§4.4) */
15
+ export declare const UI_MIGRATION_NOTES: UiSection['uiMigrationNotes'];
16
+ export declare class UiAdapter implements ConfigAdapter<UiSection> {
17
+ readonly id: 'ui';
18
+ readonly displayName = "UI Preferences";
19
+ readonly defaultIncluded = true;
20
+ readonly portability: 'portable';
21
+ private readonly namespaces;
22
+ constructor(namespaces?: string[] | NamespaceProvider);
23
+ export(ctx: HostContext, _options: ExportOptions): Promise<ExportSection<UiSection>>;
24
+ analyzeImport(data: UiSection, ctx: ImportContext): Promise<PlanItem[]>;
25
+ applyItem(item: PlanItem, ctx: ImportContext): Promise<ApplyResult>;
26
+ validate(data: UiSection, msg?: MsgFunc): Promise<ValidationResult>;
27
+ }
@@ -0,0 +1,89 @@
1
+ import { zhMsg } from '../core/messages.js';
2
+ import { collectNamespaceRecords, planNamespaceItems, applyNamespaceItem, resolveNamespaces } from './settings.js';
3
+ /** UI 类 namespace 前缀名单(设计 §4.1;随新插件扩展,只影响「某一 namespace 归哪一边」,不影响数据完整性) */
4
+ export const KNOWN_UI_NAMESPACE_PREFIXES = [
5
+ 'pet',
6
+ 'dsh-better-sidebar',
7
+ 'remote-web-ui',
8
+ 'ui-onboarding',
9
+ 'dsh-client-ui',
10
+ 'skin',
11
+ 'theme',
12
+ 'layout',
13
+ 'sidebar',
14
+ 'appearance',
15
+ ];
16
+ /** namespace 名是否属于 UI 类(大小写不敏感前缀匹配) */
17
+ export function isUiNamespace(name) {
18
+ const lower = name.toLowerCase();
19
+ return KNOWN_UI_NAMESPACE_PREFIXES.some((p) => lower.startsWith(p.toLowerCase()));
20
+ }
21
+ /** localStorage 等 Host 无通道的 UI 状态说明(纯说明,不含值;研究报告 §2.2/§4.4) */
22
+ export const UI_MIGRATION_NOTES = [
23
+ {
24
+ plugin: 'dsh-task-board',
25
+ storage: 'localStorage',
26
+ key: 'dsh.taskBoard.v1',
27
+ migratable: false,
28
+ reason: '任务看板数据存于浏览器 localStorage,Host 侧无访问通道,需在目标机器重新配置',
29
+ },
30
+ {
31
+ plugin: 'dsh-aionui-panel',
32
+ storage: 'localStorage',
33
+ key: 'aionui-panel.*',
34
+ migratable: false,
35
+ reason: '面板宽度/折叠状态存于浏览器 localStorage,Host 侧无访问通道,需在目标机器重新配置',
36
+ },
37
+ {
38
+ plugin: 'dsh-client-ui-*',
39
+ storage: 'localStorage',
40
+ key: '*',
41
+ migratable: false,
42
+ reason: '浏览器端 UI 状态无法经 Host API 迁移',
43
+ },
44
+ ];
45
+ export class UiAdapter {
46
+ id = 'ui';
47
+ displayName = 'UI Preferences';
48
+ defaultIncluded = true;
49
+ portability = 'portable';
50
+ namespaces;
51
+ constructor(namespaces = []) {
52
+ this.namespaces = namespaces;
53
+ }
54
+ async export(ctx, _options) {
55
+ const warnings = [];
56
+ const all = await resolveNamespaces(this.namespaces, ctx);
57
+ const uiNames = all.filter((n) => isUiNamespace(n));
58
+ const namespaces = await collectNamespaceRecords(ctx, uiNames, warnings);
59
+ return {
60
+ sectionId: 'ui',
61
+ data: { version: 1, namespaces, uiMigrationNotes: UI_MIGRATION_NOTES },
62
+ counts: { namespaces: Object.keys(namespaces).length, notes: UI_MIGRATION_NOTES.length },
63
+ warnings,
64
+ };
65
+ }
66
+ async analyzeImport(data, ctx) {
67
+ return planNamespaceItems(data.namespaces, 'ui', ctx);
68
+ }
69
+ async applyItem(item, ctx) {
70
+ return applyNamespaceItem(item, 'ui', ctx);
71
+ }
72
+ async validate(data, msg = zhMsg) {
73
+ const issues = [];
74
+ if (data === null || typeof data !== 'object') {
75
+ return { valid: false, issues: [{ path: '$', message: msg('adapter.validate.object', { subject: 'ui' }), severity: 'error' }] };
76
+ }
77
+ if (data.version !== 1) {
78
+ issues.push({ path: 'version', message: msg('adapter.validate.version', { value: String(data.version) }), severity: 'error' });
79
+ }
80
+ if (data.namespaces === null || typeof data.namespaces !== 'object') {
81
+ issues.push({ path: 'namespaces', message: msg('adapter.validate.missingObject', { subject: 'namespaces' }), severity: 'error' });
82
+ }
83
+ if (data.uiMigrationNotes !== undefined && !Array.isArray(data.uiMigrationNotes)) {
84
+ issues.push({ path: 'uiMigrationNotes', message: msg('adapter.validate.array', { subject: 'uiMigrationNotes' }), severity: 'error' });
85
+ }
86
+ return { valid: issues.filter((i) => i.severity === 'error').length === 0, issues };
87
+ }
88
+ }
89
+ //# sourceMappingURL=ui.js.map
@@ -0,0 +1,13 @@
1
+ import type { MsgFunc } from '../core/messages.ts';
2
+ import type { WorkspacesSection } from '../schema/types.ts';
3
+ import type { ApplyResult, ConfigAdapter, ExportOptions, ExportSection, HostContext, ImportContext, PlanItem, ValidationResult } from '../core/types.ts';
4
+ export declare class WorkspacesAdapter implements ConfigAdapter<WorkspacesSection> {
5
+ readonly id: 'workspaces';
6
+ readonly displayName = "Workspaces";
7
+ readonly defaultIncluded = true;
8
+ readonly portability: 'platformSpecific';
9
+ export(ctx: HostContext, _options: ExportOptions): Promise<ExportSection<WorkspacesSection>>;
10
+ analyzeImport(data: WorkspacesSection, ctx: ImportContext): Promise<PlanItem[]>;
11
+ applyItem(item: PlanItem, ctx: ImportContext): Promise<ApplyResult>;
12
+ validate(data: WorkspacesSection, msg?: MsgFunc): Promise<ValidationResult>;
13
+ }
@@ -0,0 +1,106 @@
1
+ /**
2
+ * workspaces 分区 adapter(设计 §3.3/§11):
3
+ * 数据源 = ~/.dsh/storages/workspace.json 的 tables.workspaces(经 ctx.workspace 门面)。
4
+ * workspace.path 为绝对路径 → 跨设备必须 PathMapping(analyzeImport 生成 PathMapping 项,
5
+ * 映射由引擎 PathMapper 先行应用到 sections,applyItem 拿到的已是映射后数据)。
6
+ */
7
+ import { isDeepStrictEqual } from 'node:util';
8
+ import { zhMsg } from '../core/messages.js';
9
+ export class WorkspacesAdapter {
10
+ id = 'workspaces';
11
+ displayName = 'Workspaces';
12
+ defaultIncluded = true;
13
+ portability = 'platformSpecific';
14
+ async export(ctx, _options) {
15
+ const records = await ctx.workspace.listRecords();
16
+ return {
17
+ sectionId: 'workspaces',
18
+ data: { version: 1, workspaces: records },
19
+ counts: { workspaces: records.length },
20
+ warnings: [],
21
+ };
22
+ }
23
+ async analyzeImport(data, ctx) {
24
+ const msg = ctx.msg;
25
+ const items = [];
26
+ for (const rec of data.workspaces) {
27
+ const id = `workspace:${rec.id}`;
28
+ const existing = (await ctx.target.workspace.listRecords()).find((r) => r.id === rec.id);
29
+ if (!existing) {
30
+ items.push({
31
+ id, kind: 'Create', adapter: 'workspaces',
32
+ description: msg('adapter.workspaceCreate', { title: rec.title ?? rec.id, path: rec.path }), severity: 'info',
33
+ target: { adapter: 'workspaces', ref: rec.id },
34
+ });
35
+ }
36
+ else if (isDeepStrictEqual(existing, rec)) {
37
+ items.push({ id, kind: 'Skip', adapter: 'workspaces', description: msg('adapter.workspaceSame', { id: rec.id }), severity: 'info' });
38
+ }
39
+ else {
40
+ items.push({
41
+ id, kind: 'Conflict', adapter: 'workspaces',
42
+ description: msg('adapter.workspaceDiff', { id: rec.id }),
43
+ detail: `current=${JSON.stringify(existing)} imported=${JSON.stringify(rec)}`.slice(0, 200),
44
+ severity: 'warning', target: { adapter: 'workspaces', ref: rec.id },
45
+ });
46
+ }
47
+ // 绝对路径 → 路径映射提示(oldPrefix 先用整条路径占位,newPrefix 由 UI 确认)
48
+ if (rec.path.startsWith('/') || /^[a-zA-Z]:[\\/]/.test(rec.path)) {
49
+ items.push({
50
+ id: `${id}:path`, kind: 'PathMapping', adapter: 'workspaces',
51
+ description: msg('adapter.workspacePathMapping', { path: rec.path }), severity: 'warning',
52
+ pathMapping: { oldPrefix: rec.path, newPrefix: '', appliesTo: ['workspaces'] },
53
+ target: { adapter: 'workspaces', ref: rec.id },
54
+ });
55
+ }
56
+ }
57
+ return items;
58
+ }
59
+ async applyItem(item, ctx) {
60
+ // PathMapping 项:数据已由 PathMapper 应用到 sections,无需额外写入
61
+ if (item.kind === 'PathMapping')
62
+ return { ok: true };
63
+ const ref = item.target?.ref;
64
+ if (!ref)
65
+ return { ok: false, message: ctx.msg('adapter.missingTargetRef') };
66
+ const data = ctx.sections.get('workspaces');
67
+ const rec = data?.workspaces.find((r) => r.id === ref);
68
+ if (!rec)
69
+ return { ok: false, message: ctx.msg('adapter.workspaceMissing', { ref }) };
70
+ try {
71
+ await ctx.target.workspace.writeRecord(rec);
72
+ return { ok: true };
73
+ }
74
+ catch (err) {
75
+ // 目标端无法写入(如路径 realpath 失败/目录不存在)→ 非致命警告(§34.17),
76
+ // 不触发整体回滚——否则一个失效路径会拖垮已成功导入的其余配置。
77
+ const reason = err instanceof Error ? err.message : String(err);
78
+ return {
79
+ ok: false,
80
+ warning: true,
81
+ message: ctx.msg('adapter.workspaceWriteFailed', { ref, msg: reason }),
82
+ };
83
+ }
84
+ }
85
+ async validate(data, msg = zhMsg) {
86
+ const issues = [];
87
+ if (data === null || typeof data !== 'object') {
88
+ return { valid: false, issues: [{ path: '$', message: msg('adapter.validate.object', { subject: 'workspaces' }), severity: 'error' }] };
89
+ }
90
+ if (data.version !== 1) {
91
+ issues.push({ path: 'version', message: msg('adapter.validate.version', { value: String(data.version) }), severity: 'error' });
92
+ }
93
+ if (!Array.isArray(data.workspaces)) {
94
+ issues.push({ path: 'workspaces', message: msg('adapter.validate.array', { subject: 'workspaces' }), severity: 'error' });
95
+ }
96
+ else {
97
+ for (const w of data.workspaces) {
98
+ if (w === null || typeof w !== 'object' || typeof w.id !== 'string' || typeof w.path !== 'string') {
99
+ issues.push({ path: 'workspaces[]', message: msg('adapter.validate.workspaceIdentity'), severity: 'error' });
100
+ }
101
+ }
102
+ }
103
+ return { valid: issues.filter((i) => i.severity === 'error').length === 0, issues };
104
+ }
105
+ }
106
+ //# sourceMappingURL=workspaces.js.map