dodo-mcp 1.0.0

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 (447) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +425 -0
  3. package/dist/auth/adapter.js +43 -0
  4. package/dist/auth/adapter.js.map +1 -0
  5. package/dist/auth/clientDeletion.js +45 -0
  6. package/dist/auth/clientDeletion.js.map +1 -0
  7. package/dist/auth/clients.js +55 -0
  8. package/dist/auth/clients.js.map +1 -0
  9. package/dist/auth/constants.js +10 -0
  10. package/dist/auth/constants.js.map +1 -0
  11. package/dist/auth/interactions.js +184 -0
  12. package/dist/auth/interactions.js.map +1 -0
  13. package/dist/auth/keys.js +56 -0
  14. package/dist/auth/keys.js.map +1 -0
  15. package/dist/auth/provider.js +131 -0
  16. package/dist/auth/provider.js.map +1 -0
  17. package/dist/auth/verifier.js +74 -0
  18. package/dist/auth/verifier.js.map +1 -0
  19. package/dist/cli/kill.js +124 -0
  20. package/dist/cli/kill.js.map +1 -0
  21. package/dist/cli/main.js +1393 -0
  22. package/dist/cli/main.js.map +1 -0
  23. package/dist/cli/menu.js +127 -0
  24. package/dist/cli/menu.js.map +1 -0
  25. package/dist/cli/terminal.js +30 -0
  26. package/dist/cli/terminal.js.map +1 -0
  27. package/dist/config/globalConfig.js +144 -0
  28. package/dist/config/globalConfig.js.map +1 -0
  29. package/dist/config/limits.js +42 -0
  30. package/dist/config/limits.js.map +1 -0
  31. package/dist/config/paths.js +94 -0
  32. package/dist/config/paths.js.map +1 -0
  33. package/dist/config/projectConfig.js +63 -0
  34. package/dist/config/projectConfig.js.map +1 -0
  35. package/dist/config/stateImport.js +306 -0
  36. package/dist/config/stateImport.js.map +1 -0
  37. package/dist/config/tunnelConfig.js +23 -0
  38. package/dist/config/tunnelConfig.js.map +1 -0
  39. package/dist/errors.js +82 -0
  40. package/dist/errors.js.map +1 -0
  41. package/dist/evaluation/contracts.js +86 -0
  42. package/dist/evaluation/contracts.js.map +1 -0
  43. package/dist/evaluation/dodoBench.js +69 -0
  44. package/dist/evaluation/dodoBench.js.map +1 -0
  45. package/dist/index.js +26 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/ipc/authentication.js +117 -0
  48. package/dist/ipc/authentication.js.map +1 -0
  49. package/dist/ipc/client.js +86 -0
  50. package/dist/ipc/client.js.map +1 -0
  51. package/dist/ipc/installationClient.js +83 -0
  52. package/dist/ipc/installationClient.js.map +1 -0
  53. package/dist/ipc/ownerControl.js +46 -0
  54. package/dist/ipc/ownerControl.js.map +1 -0
  55. package/dist/ipc/protocol.js +2 -0
  56. package/dist/ipc/protocol.js.map +1 -0
  57. package/dist/ipc/server.js +108 -0
  58. package/dist/ipc/server.js.map +1 -0
  59. package/dist/platform/execResolve.js +64 -0
  60. package/dist/platform/execResolve.js.map +1 -0
  61. package/dist/platform/fileIdentity.js +26 -0
  62. package/dist/platform/fileIdentity.js.map +1 -0
  63. package/dist/platform/fsRetry.js +22 -0
  64. package/dist/platform/fsRetry.js.map +1 -0
  65. package/dist/platform/pathPolicy.js +29 -0
  66. package/dist/platform/pathPolicy.js.map +1 -0
  67. package/dist/platform/privateFs.js +116 -0
  68. package/dist/platform/privateFs.js.map +1 -0
  69. package/dist/platform/processTree.js +31 -0
  70. package/dist/platform/processTree.js.map +1 -0
  71. package/dist/platform/shell.js +74 -0
  72. package/dist/platform/shell.js.map +1 -0
  73. package/dist/platform/speech.js +94 -0
  74. package/dist/platform/speech.js.map +1 -0
  75. package/dist/platform/system.js +28 -0
  76. package/dist/platform/system.js.map +1 -0
  77. package/dist/platform/windowsSandbox.js +129 -0
  78. package/dist/platform/windowsSandbox.js.map +1 -0
  79. package/dist/projects/federation.js +312 -0
  80. package/dist/projects/federation.js.map +1 -0
  81. package/dist/projects/registry.js +291 -0
  82. package/dist/projects/registry.js.map +1 -0
  83. package/dist/security/accessMode.js +19 -0
  84. package/dist/security/accessMode.js.map +1 -0
  85. package/dist/security/approvals.js +56 -0
  86. package/dist/security/approvals.js.map +1 -0
  87. package/dist/security/env.js +57 -0
  88. package/dist/security/env.js.map +1 -0
  89. package/dist/security/mutationQueue.js +78 -0
  90. package/dist/security/mutationQueue.js.map +1 -0
  91. package/dist/security/policy.js +22 -0
  92. package/dist/security/policy.js.map +1 -0
  93. package/dist/security/projectAuthority.js +22 -0
  94. package/dist/security/projectAuthority.js.map +1 -0
  95. package/dist/security/redact.js +30 -0
  96. package/dist/security/redact.js.map +1 -0
  97. package/dist/server/aiAdmin.js +201 -0
  98. package/dist/server/aiAdmin.js.map +1 -0
  99. package/dist/server/appServer.js +461 -0
  100. package/dist/server/appServer.js.map +1 -0
  101. package/dist/server/bootstrap.js +185 -0
  102. package/dist/server/bootstrap.js.map +1 -0
  103. package/dist/server/configUi/app.css +347 -0
  104. package/dist/server/configUi/app.js +958 -0
  105. package/dist/server/configUi/index.html +379 -0
  106. package/dist/server/configUi/ui/alerts.js +92 -0
  107. package/dist/server/configUi/ui/dom.js +19 -0
  108. package/dist/server/configUi/ui/tooltips.js +115 -0
  109. package/dist/server/configUi/vendor/VERSION.txt +1 -0
  110. package/dist/server/configUi/vendor/sweetalert2.min.css +1 -0
  111. package/dist/server/configUi/vendor/sweetalert2.min.js +5 -0
  112. package/dist/server/configUi/workbench.css +62 -0
  113. package/dist/server/configUi/workbench.js +394 -0
  114. package/dist/server/installationRuntime.js +155 -0
  115. package/dist/server/installationRuntime.js.map +1 -0
  116. package/dist/server/instructions.js +17 -0
  117. package/dist/server/instructions.js.map +1 -0
  118. package/dist/server/ipcDispatch.js +225 -0
  119. package/dist/server/ipcDispatch.js.map +1 -0
  120. package/dist/server/localConfig.js +561 -0
  121. package/dist/server/localConfig.js.map +1 -0
  122. package/dist/server/optionalServices.js +30 -0
  123. package/dist/server/optionalServices.js.map +1 -0
  124. package/dist/server/projectLease.js +46 -0
  125. package/dist/server/projectLease.js.map +1 -0
  126. package/dist/server/stdioServer.js +75 -0
  127. package/dist/server/stdioServer.js.map +1 -0
  128. package/dist/server/version.js +13 -0
  129. package/dist/server/version.js.map +1 -0
  130. package/dist/server/workspaceHost.js +194 -0
  131. package/dist/server/workspaceHost.js.map +1 -0
  132. package/dist/services/agent/agentService.js +598 -0
  133. package/dist/services/agent/agentService.js.map +1 -0
  134. package/dist/services/agent/contracts.js +102 -0
  135. package/dist/services/agent/contracts.js.map +1 -0
  136. package/dist/services/ai/adapters.js +287 -0
  137. package/dist/services/ai/adapters.js.map +1 -0
  138. package/dist/services/ai/contracts.js +39 -0
  139. package/dist/services/ai/contracts.js.map +1 -0
  140. package/dist/services/ai/credentials.js +77 -0
  141. package/dist/services/ai/credentials.js.map +1 -0
  142. package/dist/services/ai/network.js +113 -0
  143. package/dist/services/ai/network.js.map +1 -0
  144. package/dist/services/ai/settings.js +178 -0
  145. package/dist/services/ai/settings.js.map +1 -0
  146. package/dist/services/ai/subagents.js +468 -0
  147. package/dist/services/ai/subagents.js.map +1 -0
  148. package/dist/services/assistance/analysis.js +352 -0
  149. package/dist/services/assistance/analysis.js.map +1 -0
  150. package/dist/services/assistance/contracts.js +54 -0
  151. package/dist/services/assistance/contracts.js.map +1 -0
  152. package/dist/services/assistance/verification.js +274 -0
  153. package/dist/services/assistance/verification.js.map +1 -0
  154. package/dist/services/brain/brainParser.js +97 -0
  155. package/dist/services/brain/brainParser.js.map +1 -0
  156. package/dist/services/brain/brainService.js +733 -0
  157. package/dist/services/brain/brainService.js.map +1 -0
  158. package/dist/services/brain/brainWorker.js +212 -0
  159. package/dist/services/brain/brainWorker.js.map +1 -0
  160. package/dist/services/brain/contracts.js +154 -0
  161. package/dist/services/brain/contracts.js.map +1 -0
  162. package/dist/services/brain/protocol.js +2 -0
  163. package/dist/services/brain/protocol.js.map +1 -0
  164. package/dist/services/changes/applier.js +544 -0
  165. package/dist/services/changes/applier.js.map +1 -0
  166. package/dist/services/changes/contentBudget.js +11 -0
  167. package/dist/services/changes/contentBudget.js.map +1 -0
  168. package/dist/services/changes/planner.js +284 -0
  169. package/dist/services/changes/planner.js.map +1 -0
  170. package/dist/services/changes/types.js +3 -0
  171. package/dist/services/changes/types.js.map +1 -0
  172. package/dist/services/context/contextEngine.js +746 -0
  173. package/dist/services/context/contextEngine.js.map +1 -0
  174. package/dist/services/context/contracts.js +88 -0
  175. package/dist/services/context/contracts.js.map +1 -0
  176. package/dist/services/desktop/desktopPolicy.js +76 -0
  177. package/dist/services/desktop/desktopPolicy.js.map +1 -0
  178. package/dist/services/desktop/desktopService.js +130 -0
  179. package/dist/services/desktop/desktopService.js.map +1 -0
  180. package/dist/services/desktop/nativeBackend.js +174 -0
  181. package/dist/services/desktop/nativeBackend.js.map +1 -0
  182. package/dist/services/desktop/protocol.js +32 -0
  183. package/dist/services/desktop/protocol.js.map +1 -0
  184. package/dist/services/files/readService.js +136 -0
  185. package/dist/services/files/readService.js.map +1 -0
  186. package/dist/services/git/gitService.js +369 -0
  187. package/dist/services/git/gitService.js.map +1 -0
  188. package/dist/services/intelligence/intelService.js +136 -0
  189. package/dist/services/intelligence/intelService.js.map +1 -0
  190. package/dist/services/intelligence/protocol.js +2 -0
  191. package/dist/services/intelligence/protocol.js.map +1 -0
  192. package/dist/services/intelligence/tsWorker.js +419 -0
  193. package/dist/services/intelligence/tsWorker.js.map +1 -0
  194. package/dist/services/jobs/commandInput.js +34 -0
  195. package/dist/services/jobs/commandInput.js.map +1 -0
  196. package/dist/services/jobs/jobManager.js +398 -0
  197. package/dist/services/jobs/jobManager.js.map +1 -0
  198. package/dist/services/jobs/sandbox.js +156 -0
  199. package/dist/services/jobs/sandbox.js.map +1 -0
  200. package/dist/services/jobs/sandboxWiring.js +37 -0
  201. package/dist/services/jobs/sandboxWiring.js.map +1 -0
  202. package/dist/services/jobs/spool.js +112 -0
  203. package/dist/services/jobs/spool.js.map +1 -0
  204. package/dist/services/jobs/windowsSandboxChild.js +24 -0
  205. package/dist/services/jobs/windowsSandboxChild.js.map +1 -0
  206. package/dist/services/jobs/windowsSandboxWorker.js +155 -0
  207. package/dist/services/jobs/windowsSandboxWorker.js.map +1 -0
  208. package/dist/services/lsp/documentUri.js +16 -0
  209. package/dist/services/lsp/documentUri.js.map +1 -0
  210. package/dist/services/lsp/jsonrpc.js +382 -0
  211. package/dist/services/lsp/jsonrpc.js.map +1 -0
  212. package/dist/services/lsp/lspService.js +1051 -0
  213. package/dist/services/lsp/lspService.js.map +1 -0
  214. package/dist/services/memory/contracts.js +94 -0
  215. package/dist/services/memory/contracts.js.map +1 -0
  216. package/dist/services/memory/memoryService.js +683 -0
  217. package/dist/services/memory/memoryService.js.map +1 -0
  218. package/dist/services/multimodal/browserService.js +407 -0
  219. package/dist/services/multimodal/browserService.js.map +1 -0
  220. package/dist/services/multimodal/byteRange.js +31 -0
  221. package/dist/services/multimodal/byteRange.js.map +1 -0
  222. package/dist/services/multimodal/contracts.js +59 -0
  223. package/dist/services/multimodal/contracts.js.map +1 -0
  224. package/dist/services/multimodal/gameService.js +95 -0
  225. package/dist/services/multimodal/gameService.js.map +1 -0
  226. package/dist/services/multimodal/images.js +107 -0
  227. package/dist/services/multimodal/images.js.map +1 -0
  228. package/dist/services/multimodal/mediaService.js +279 -0
  229. package/dist/services/multimodal/mediaService.js.map +1 -0
  230. package/dist/services/multimodal/mediaWorker.js +143 -0
  231. package/dist/services/multimodal/mediaWorker.js.map +1 -0
  232. package/dist/services/multimodal/multimodalService.js +51 -0
  233. package/dist/services/multimodal/multimodalService.js.map +1 -0
  234. package/dist/services/multimodal/network.js +69 -0
  235. package/dist/services/multimodal/network.js.map +1 -0
  236. package/dist/services/multimodal/operations.js +40 -0
  237. package/dist/services/multimodal/operations.js.map +1 -0
  238. package/dist/services/multimodal/storage.js +160 -0
  239. package/dist/services/multimodal/storage.js.map +1 -0
  240. package/dist/services/multimodal/workflowService.js +179 -0
  241. package/dist/services/multimodal/workflowService.js.map +1 -0
  242. package/dist/services/overview.js +284 -0
  243. package/dist/services/overview.js.map +1 -0
  244. package/dist/services/resources/casStore.js +304 -0
  245. package/dist/services/resources/casStore.js.map +1 -0
  246. package/dist/services/resources/contracts.js +75 -0
  247. package/dist/services/resources/contracts.js.map +1 -0
  248. package/dist/services/resources/mime.js +77 -0
  249. package/dist/services/resources/mime.js.map +1 -0
  250. package/dist/services/resources/providerRegistry.js +22 -0
  251. package/dist/services/resources/providerRegistry.js.map +1 -0
  252. package/dist/services/resources/providers.js +120 -0
  253. package/dist/services/resources/providers.js.map +1 -0
  254. package/dist/services/resources/resourceService.js +282 -0
  255. package/dist/services/resources/resourceService.js.map +1 -0
  256. package/dist/services/runtime/contracts.js +65 -0
  257. package/dist/services/runtime/contracts.js.map +1 -0
  258. package/dist/services/runtime/runtimeService.js +364 -0
  259. package/dist/services/runtime/runtimeService.js.map +1 -0
  260. package/dist/services/schedules/scheduleService.js +198 -0
  261. package/dist/services/schedules/scheduleService.js.map +1 -0
  262. package/dist/services/search/searchService.js +434 -0
  263. package/dist/services/search/searchService.js.map +1 -0
  264. package/dist/services/search/searchWorker.js +58 -0
  265. package/dist/services/search/searchWorker.js.map +1 -0
  266. package/dist/setup/componentProbes.js +259 -0
  267. package/dist/setup/componentProbes.js.map +1 -0
  268. package/dist/setup/download.js +139 -0
  269. package/dist/setup/download.js.map +1 -0
  270. package/dist/setup/managedTools.js +118 -0
  271. package/dist/setup/managedTools.js.map +1 -0
  272. package/dist/setup/sandboxProbe.js +172 -0
  273. package/dist/setup/sandboxProbe.js.map +1 -0
  274. package/dist/setup/setup.js +522 -0
  275. package/dist/setup/setup.js.map +1 -0
  276. package/dist/setup/windowsChromiumAcl.js +56 -0
  277. package/dist/setup/windowsChromiumAcl.js.map +1 -0
  278. package/dist/setup/windowsSandboxInstall.js +94 -0
  279. package/dist/setup/windowsSandboxInstall.js.map +1 -0
  280. package/dist/setup/windowsSpeechInstall.js +86 -0
  281. package/dist/setup/windowsSpeechInstall.js.map +1 -0
  282. package/dist/store/db.js +711 -0
  283. package/dist/store/db.js.map +1 -0
  284. package/dist/store/scopeEncoding.js +15 -0
  285. package/dist/store/scopeEncoding.js.map +1 -0
  286. package/dist/store/store.js +467 -0
  287. package/dist/store/store.js.map +1 -0
  288. package/dist/tools/agentRuntimeTools.js +216 -0
  289. package/dist/tools/agentRuntimeTools.js.map +1 -0
  290. package/dist/tools/agentTools.js +317 -0
  291. package/dist/tools/agentTools.js.map +1 -0
  292. package/dist/tools/assistanceTools.js +126 -0
  293. package/dist/tools/assistanceTools.js.map +1 -0
  294. package/dist/tools/brainTools.js +130 -0
  295. package/dist/tools/brainTools.js.map +1 -0
  296. package/dist/tools/catalog.js +30 -0
  297. package/dist/tools/catalog.js.map +1 -0
  298. package/dist/tools/changeTools.js +188 -0
  299. package/dist/tools/changeTools.js.map +1 -0
  300. package/dist/tools/context.js +243 -0
  301. package/dist/tools/context.js.map +1 -0
  302. package/dist/tools/contextTools.js +57 -0
  303. package/dist/tools/contextTools.js.map +1 -0
  304. package/dist/tools/coreCatalog.js +82 -0
  305. package/dist/tools/coreCatalog.js.map +1 -0
  306. package/dist/tools/desktopTools.js +41 -0
  307. package/dist/tools/desktopTools.js.map +1 -0
  308. package/dist/tools/directTools.js +273 -0
  309. package/dist/tools/directTools.js.map +1 -0
  310. package/dist/tools/envelope.js +71 -0
  311. package/dist/tools/envelope.js.map +1 -0
  312. package/dist/tools/extraTools.js +298 -0
  313. package/dist/tools/extraTools.js.map +1 -0
  314. package/dist/tools/gitTools.js +93 -0
  315. package/dist/tools/gitTools.js.map +1 -0
  316. package/dist/tools/jobTools.js +454 -0
  317. package/dist/tools/jobTools.js.map +1 -0
  318. package/dist/tools/memoryTools.js +102 -0
  319. package/dist/tools/memoryTools.js.map +1 -0
  320. package/dist/tools/metaTools.js +153 -0
  321. package/dist/tools/metaTools.js.map +1 -0
  322. package/dist/tools/multimodalTools.js +262 -0
  323. package/dist/tools/multimodalTools.js.map +1 -0
  324. package/dist/tools/projectTools.js +261 -0
  325. package/dist/tools/projectTools.js.map +1 -0
  326. package/dist/tools/resourceTools.js +81 -0
  327. package/dist/tools/resourceTools.js.map +1 -0
  328. package/dist/tools/runtimeTools.js +137 -0
  329. package/dist/tools/runtimeTools.js.map +1 -0
  330. package/dist/tools/scheduleTools.js +10 -0
  331. package/dist/tools/scheduleTools.js.map +1 -0
  332. package/dist/tools/semanticTools.js +141 -0
  333. package/dist/tools/semanticTools.js.map +1 -0
  334. package/dist/tools/subagentTools.js +32 -0
  335. package/dist/tools/subagentTools.js.map +1 -0
  336. package/dist/tools/surface.js +644 -0
  337. package/dist/tools/surface.js.map +1 -0
  338. package/dist/tunnel/control.js +113 -0
  339. package/dist/tunnel/control.js.map +1 -0
  340. package/dist/tunnel/credentials.js +392 -0
  341. package/dist/tunnel/credentials.js.map +1 -0
  342. package/dist/tunnel/log.js +84 -0
  343. package/dist/tunnel/log.js.map +1 -0
  344. package/dist/tunnel/runtime.js +55 -0
  345. package/dist/tunnel/runtime.js.map +1 -0
  346. package/dist/tunnel/supervisor.js +280 -0
  347. package/dist/tunnel/supervisor.js.map +1 -0
  348. package/dist/util/bytes.js +53 -0
  349. package/dist/util/bytes.js.map +1 -0
  350. package/dist/util/hash.js +53 -0
  351. package/dist/util/hash.js.map +1 -0
  352. package/dist/workspace/fs.js +305 -0
  353. package/dist/workspace/fs.js.map +1 -0
  354. package/dist/workspace/identity.js +17 -0
  355. package/dist/workspace/identity.js.map +1 -0
  356. package/dist/workspace/ignores.js +173 -0
  357. package/dist/workspace/ignores.js.map +1 -0
  358. package/dist/workspace/root.js +59 -0
  359. package/dist/workspace/root.js.map +1 -0
  360. package/docs/AGENT_RUNTIME.md +154 -0
  361. package/docs/AI_PROVIDERS.md +110 -0
  362. package/docs/ARCHITECTURE.md +331 -0
  363. package/docs/ASSISTANCE.md +31 -0
  364. package/docs/AUTH.md +59 -0
  365. package/docs/BRAIN.md +92 -0
  366. package/docs/COMPATIBILITY.md +92 -0
  367. package/docs/CONFIRMATION.md +13 -0
  368. package/docs/CONTEXT.md +87 -0
  369. package/docs/DESKTOP.md +35 -0
  370. package/docs/EVALUATION.md +86 -0
  371. package/docs/LARGE_INPUTS.md +21 -0
  372. package/docs/LSP.md +21 -0
  373. package/docs/MANUAL_ACCEPTANCE.md +283 -0
  374. package/docs/MEMORY.md +128 -0
  375. package/docs/MULTIMODAL.md +32 -0
  376. package/docs/PROJECTS.md +146 -0
  377. package/docs/RELEASE_1.0.0.md +111 -0
  378. package/docs/RELEASE_NOTES.md +92 -0
  379. package/docs/RESOURCES.md +83 -0
  380. package/docs/RUNTIME.md +125 -0
  381. package/docs/SCHEDULES.md +23 -0
  382. package/docs/SECURITY.md +250 -0
  383. package/docs/TEST_REPORT.md +312 -0
  384. package/docs/TUNNEL.md +86 -0
  385. package/docs/WEB_CLIENTS.md +43 -0
  386. package/docs/WINDOWS.md +79 -0
  387. package/docs/adr/001-one-process-one-workspace.md +22 -0
  388. package/docs/adr/002-external-tunnel.md +19 -0
  389. package/docs/adr/003-sdk-v2-legacy-stateless.md +20 -0
  390. package/docs/adr/004-embedded-oauth-provider.md +19 -0
  391. package/docs/adr/005-static-client-baseline.md +19 -0
  392. package/docs/adr/006-guarded-fs-explicit-exec.md +16 -0
  393. package/docs/adr/007-preview-hash-journal.md +18 -0
  394. package/docs/adr/008-ts-js-semantics-first.md +17 -0
  395. package/docs/adr/009-jobs-polling.md +18 -0
  396. package/docs/adr/010-sqlite-better-sqlite3.md +18 -0
  397. package/docs/adr/011-env-example-secure-default.md +19 -0
  398. package/docs/adr/012-workspace-scope-grant.md +24 -0
  399. package/docs/adr/013-loopback-proxy-trust.md +18 -0
  400. package/docs/adr/014-direct-coding-tier.md +48 -0
  401. package/docs/adr/015-coding-agent-parity.md +56 -0
  402. package/docs/adr/016-oidc-openid-consent.md +15 -0
  403. package/docs/adr/017-installation-identity-local-config.md +44 -0
  404. package/docs/adr/018-access-scope-encoding.md +11 -0
  405. package/docs/adr/019-runtime-workspace-switch.md +59 -0
  406. package/docs/adr/020-desktop-access.md +50 -0
  407. package/docs/adr/021-persistent-desktop-consent.md +39 -0
  408. package/docs/adr/022-owner-kill-preserves-login.md +30 -0
  409. package/docs/adr/023-large-coding-inputs.md +49 -0
  410. package/docs/adr/024-usage-rounds-and-schedules.md +72 -0
  411. package/docs/adr/025-owner-chat-whitelist.md +53 -0
  412. package/docs/adr/026-remove-conversation-confirmation.md +35 -0
  413. package/docs/adr/027-workspace-client-list.md +20 -0
  414. package/docs/adr/028-owner-client-deletion.md +25 -0
  415. package/docs/adr/029-compact-tool-surface.md +121 -0
  416. package/docs/adr/030-windows-native-candidate.md +71 -0
  417. package/docs/adr/031-owner-selected-tunnel-supervision.md +13 -0
  418. package/docs/adr/032-owner-project-registry.md +43 -0
  419. package/docs/adr/033-read-only-project-federation.md +61 -0
  420. package/docs/adr/034-universal-resource-cas.md +60 -0
  421. package/docs/adr/035-project-brain-incremental-index.md +51 -0
  422. package/docs/adr/036-context-engine-evidence.md +53 -0
  423. package/docs/adr/037-owner-reviewed-memory.md +46 -0
  424. package/docs/adr/038-runtime-intelligence.md +46 -0
  425. package/docs/adr/039-advanced-agent-runtime.md +57 -0
  426. package/docs/adr/040-dodobench-release-gate.md +43 -0
  427. package/docs/adr/041-local-macos-docker-linux-gates.md +32 -0
  428. package/docs/adr/042-project-directory-generation-identity.md +36 -0
  429. package/docs/adr/043-trusted-self-hosted-platform-gates.md +38 -0
  430. package/docs/adr/044-global-launcher-and-cli-menu.md +43 -0
  431. package/docs/adr/045-ai-providers-multiproject.md +56 -0
  432. package/docs/adr/046-personal-access-mode.md +32 -0
  433. package/docs/adr/README.md +64 -0
  434. package/examples/.dodo.json.example +20 -0
  435. package/examples/cloudflared.yml +23 -0
  436. package/examples/reverse-proxy-fixture.mjs +37 -0
  437. package/native/desktop-linux.py +387 -0
  438. package/native/desktop-windows.cs +180 -0
  439. package/native/desktop.swift +212 -0
  440. package/package.json +145 -0
  441. package/schemas/global-config.schema.json +497 -0
  442. package/schemas/project-config.schema.json +75 -0
  443. package/schemas/tools.compact.json +3236 -0
  444. package/schemas/tools.hybrid.json +8194 -0
  445. package/schemas/tools.json +34518 -0
  446. package/scripts/guard-publish.mjs +12 -0
  447. package/scripts/setup-multimodal.mjs +70 -0
@@ -0,0 +1,185 @@
1
+ import { acquireProjectLease } from './projectLease.js';
2
+ import { MutationQueue } from '../security/mutationQueue.js';
3
+ import { isPersonalMode, setAccessMode } from '../security/accessMode.js';
4
+ import { MultimodalService } from '../services/multimodal/multimodalService.js';
5
+ import { ResourceService } from '../services/resources/resourceService.js';
6
+ import { ProjectBrainService } from '../services/brain/brainService.js';
7
+ import { ContextEngineService } from '../services/context/contextEngine.js';
8
+ import { MemoryService } from '../services/memory/memoryService.js';
9
+ import { RuntimeService } from '../services/runtime/runtimeService.js';
10
+ import { AgentRuntimeService } from '../services/agent/agentService.js';
11
+ import { ScheduleService } from '../services/schedules/scheduleService.js';
12
+ import { DesktopService } from '../services/desktop/desktopService.js';
13
+ import { NativeDesktopBackend } from '../services/desktop/nativeBackend.js';
14
+ import { resolveConfigDir, ensureConfigDir, statePaths } from '../config/paths.js';
15
+ import { loadGlobalConfig } from '../config/globalConfig.js';
16
+ import { loadProjectConfig } from '../config/projectConfig.js';
17
+ import { resolveWorkspaceRoot } from '../workspace/root.js';
18
+ import { mintWorkspaceId, mintEpoch } from '../workspace/identity.js';
19
+ import { IgnoreEngine } from '../workspace/ignores.js';
20
+ import { WorkspaceFS } from '../workspace/fs.js';
21
+ import { openDatabase } from '../store/db.js';
22
+ import { Store } from '../store/store.js';
23
+ import { ReadService, ListService } from '../services/files/readService.js';
24
+ import { SearchService } from '../services/search/searchService.js';
25
+ import { Planner } from '../services/changes/planner.js';
26
+ import { Applier } from '../services/changes/applier.js';
27
+ import { JobManager } from '../services/jobs/jobManager.js';
28
+ import { GitService } from '../services/git/gitService.js';
29
+ import { IntelService } from '../services/intelligence/intelService.js';
30
+ import { OverviewService } from '../services/overview.js';
31
+ import { sandboxWrapperFromConfig } from '../services/jobs/sandboxWiring.js';
32
+ import { DODO_VERSION } from './version.js';
33
+ import { FederationService } from '../projects/federation.js';
34
+ import { activateManagedTools } from '../setup/managedTools.js';
35
+ export function bootstrapWorkspace(opts) {
36
+ const { log } = opts;
37
+ const configResolution = opts.configDir ?? resolveConfigDir(process.env);
38
+ const { dir: configDir, source: configDirSource, envVar: configDirEnvVar } = configResolution;
39
+ ensureConfigDir(configDir);
40
+ const paths = statePaths(configDir);
41
+ const config = loadGlobalConfig(paths.configFile);
42
+ if (opts.runMode)
43
+ config.allowWebFetch = true;
44
+ if (opts.runMode === 'bypass')
45
+ config.commandSandbox = 'off';
46
+ const limits = config.limits;
47
+ const rootInfo = resolveWorkspaceRoot(opts.rootOverride ?? opts.invokedCwd, { allowUnsafe: opts.allowUnsafeRoot ?? false });
48
+ const releaseLease = acquireProjectLease(configDir, rootInfo.root);
49
+ let openedDb;
50
+ try {
51
+ activateManagedTools(configDir, rootInfo.root);
52
+ const db = openDatabase(paths.dbFile);
53
+ openedDb = db;
54
+ const store = new Store(db);
55
+ // Global config is the owner-controlled source for this installation-wide
56
+ // choice. Mirror it into private state so authorization helpers that only
57
+ // receive Store can make the same decision for every target runtime.
58
+ setAccessMode(store, config.accessMode);
59
+ const installSecret = store.installSecret();
60
+ const workspaceId = mintWorkspaceId(installSecret, rootInfo.root);
61
+ const epoch = mintEpoch();
62
+ const existingWs = store.getWorkspace(workspaceId);
63
+ if (existingWs && (existingWs.dev !== rootInfo.dev || existingWs.ino !== rootInfo.ino)) {
64
+ // The path now points at a DIFFERENT directory identity (replaced root):
65
+ // epoch-based trust survives, but note it loudly (spec §6).
66
+ store.db.prepare('DELETE FROM workspace_clients WHERE workspace_id=?').run(workspaceId);
67
+ store.setTrustMode(workspaceId, 'inspect');
68
+ log('[dodo] workspace directory identity changed: client access and saved trust reset');
69
+ }
70
+ store.upsertWorkspace({ id: workspaceId, root: rootInfo.root, dev: rootInfo.dev, ino: rootInfo.ino, epoch });
71
+ const interrupted = store.markInterruptedJobs(epoch, workspaceId);
72
+ if (interrupted > 0)
73
+ log(`[dodo] ${interrupted} job(s) from a previous run marked interrupted_on_restart`);
74
+ const projectConfig = loadProjectConfig(rootInfo.root);
75
+ const ignores = new IgnoreEngine({
76
+ root: rootInfo.root,
77
+ extraSecretPatterns: config.secretDeny,
78
+ secretAllow: config.secretAllow,
79
+ projectExcludes: projectConfig.config.exclude,
80
+ });
81
+ const wfs = new WorkspaceFS(rootInfo.root, ignores);
82
+ const applier = new Applier(wfs, limits, store, paths.backupsDir, workspaceId);
83
+ const recon = applier.reconcileOnBoot();
84
+ if (recon.recoveryRequired.length > 0) {
85
+ log(`[dodo] WARNING: ${recon.recoveryRequired.length} changeset(s) need manual recovery (dodo recover); mutations are blocked until resolved`);
86
+ }
87
+ const git = new GitService(wfs, limits);
88
+ const listService = new ListService(wfs, limits);
89
+ const jobs = new JobManager(wfs, limits, store, paths.jobsDir, config.envAllowlist, sandboxWrapperFromConfig(config, rootInfo.root, configDir));
90
+ const intel = new IntelService({
91
+ root: rootInfo.root,
92
+ extraSecretPatterns: config.secretDeny,
93
+ projectExcludes: projectConfig.config.exclude,
94
+ semanticFilesMax: limits.semanticFilesMax,
95
+ maxSnapshotBytes: Math.min(limits.readFileBytes, 512 * 1024),
96
+ }, limits);
97
+ const mutations = new MutationQueue();
98
+ jobs.mutations = mutations;
99
+ const services = {
100
+ mutations,
101
+ federation: new FederationService(store, config, limits),
102
+ schedules: new ScheduleService({ store, workspaceId, epoch, wfs, jobs, config, limits }),
103
+ version: DODO_VERSION,
104
+ config,
105
+ limits,
106
+ store,
107
+ wfs,
108
+ readService: new ReadService(wfs, limits),
109
+ listService,
110
+ search: new SearchService(wfs, limits, config.searchBackend),
111
+ planner: new Planner(wfs, limits, store),
112
+ applier,
113
+ jobs,
114
+ git,
115
+ intel,
116
+ overview: new OverviewService(wfs, limits, listService, git),
117
+ desktop: new DesktopService(store, workspaceId, epoch, new NativeDesktopBackend(configDir)),
118
+ projectConfig,
119
+ workspaceId,
120
+ epoch,
121
+ trustMode: () => opts.runMode || isPersonalMode(store) ? 'trusted' : store.trustMode(workspaceId),
122
+ };
123
+ services.multimodal = new MultimodalService(services, configDir);
124
+ services.resources = new ResourceService(services, configDir, paths.resourceStoreDir, paths.resourceStagingDir, installSecret);
125
+ services.brain = new ProjectBrainService(services, installSecret);
126
+ services.runtime = new RuntimeService(services);
127
+ services.agentRuntime = new AgentRuntimeService(services);
128
+ services.contextEngine = new ContextEngineService(services, installSecret);
129
+ services.memory = new MemoryService(services, installSecret);
130
+ let closed = false;
131
+ return {
132
+ configDir,
133
+ configDirSource,
134
+ ...(configDirEnvVar ? { configDirEnvVar } : {}),
135
+ paths,
136
+ config,
137
+ db,
138
+ store,
139
+ rootInfo,
140
+ workspaceId,
141
+ epoch,
142
+ projectConfig,
143
+ services,
144
+ async shutdownServices() {
145
+ if (closed)
146
+ return;
147
+ closed = true;
148
+ services.schedules.stop();
149
+ services.memory?.close();
150
+ services.contextEngine?.close();
151
+ services.agentRuntime?.close();
152
+ services.runtime?.close();
153
+ await services.brain?.close();
154
+ await services.multimodal?.close();
155
+ services.resources?.close();
156
+ await services.desktop.close();
157
+ try {
158
+ await services.jobs.shutdown(3000);
159
+ await services.intel.shutdown();
160
+ await services.lsp?.shutdown();
161
+ }
162
+ catch {
163
+ /* best effort */
164
+ }
165
+ try {
166
+ db.close();
167
+ releaseLease();
168
+ }
169
+ catch {
170
+ /* already closed */
171
+ }
172
+ },
173
+ };
174
+ }
175
+ catch (error) {
176
+ try {
177
+ openedDb?.close();
178
+ }
179
+ finally {
180
+ releaseLease();
181
+ }
182
+ throw error;
183
+ }
184
+ }
185
+ //# sourceMappingURL=bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/server/bootstrap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,347 @@
1
+ /* DODO Local Config — developer dashboard. No external assets.
2
+ * Design system: dark-first charcoal/slate surfaces, restrained violet
3
+ * accents, systematic spacing and borders, and no gradients or page-wide
4
+ * glow effects. */
5
+ :root {
6
+ --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans Thai", "Sarabun", "Thonburi", "Leelawadee UI", Arial, sans-serif;
7
+ --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
8
+ --radius: 14px;
9
+ --radius-sm: 9px;
10
+ --gap: 16px;
11
+ /* 8px spacing scale — every margin/padding/gap is a multiple of 4. */
12
+ --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 20px; --s6: 24px; --s8: 32px;
13
+ --card-pad: 22px;
14
+ --shell: 1120px; /* one shared content width across every page */
15
+ }
16
+ :root[data-theme="dark"] {
17
+ color-scheme: dark;
18
+ --bg: #0b0b0d;
19
+ --panel: #131317;
20
+ --panel-2: #1a1a20;
21
+ --raised: #212129;
22
+ --border: #24242c;
23
+ --border-strong: #34343e;
24
+ --text: #ececf1;
25
+ --muted: #9d9dab;
26
+ --accent: #a78bfa;
27
+ --accent-strong: #c4b5fd;
28
+ --accent-contrast: #16101f;
29
+ --accent-soft: rgba(167, 139, 250, .14);
30
+ --ok: #4cc38a;
31
+ --warn: #e3b341;
32
+ --danger: #f2717a;
33
+ --info: #7cc4ff;
34
+ --focus: #b7a9ff;
35
+ --code-bg: #0e0e11;
36
+ --shadow: 0 1px 2px rgba(0, 0, 0, .4);
37
+ --shadow-lg: 0 16px 48px rgba(0, 0, 0, .5);
38
+ }
39
+ :root[data-theme="light"] {
40
+ color-scheme: light;
41
+ --bg: #f2f0ec;
42
+ --panel: #fcfbf9;
43
+ --panel-2: #f5f3ef;
44
+ --raised: #ffffff;
45
+ --border: #e2ded6;
46
+ --border-strong: #ccc6bb;
47
+ --text: #1d1c22;
48
+ --muted: #6b6975;
49
+ --accent: #6d5ae6;
50
+ --accent-strong: #5646c8;
51
+ --accent-contrast: #ffffff;
52
+ --accent-soft: rgba(109, 90, 230, .11);
53
+ --ok: #15803d;
54
+ --warn: #96660a;
55
+ --danger: #b91c1c;
56
+ --info: #3b5bdb;
57
+ --focus: #6d5ae6;
58
+ --code-bg: #eae7e0;
59
+ --shadow: 0 1px 3px rgba(45, 38, 25, .08);
60
+ --shadow-lg: 0 16px 48px rgba(45, 38, 25, .16);
61
+ }
62
+
63
+ * { box-sizing: border-box; }
64
+ /* The hidden attribute must always win over class-based display values. */
65
+ [hidden] { display: none !important; }
66
+ html { font-size: 16px; }
67
+ body {
68
+ margin: 0;
69
+ font-family: var(--font);
70
+ line-height: 1.55;
71
+ background: var(--bg);
72
+ color: var(--text);
73
+ -webkit-font-smoothing: antialiased;
74
+ }
75
+ h1, h2, h3 { margin: 0; line-height: 1.25; font-weight: 650; letter-spacing: -.01em; }
76
+ h1 { font-size: 1.25rem; }
77
+ h2 { font-size: 1.05rem; }
78
+ h3 { font-size: 1rem; }
79
+ p { margin: 0 0 .6rem; }
80
+ p:last-child { margin-bottom: 0; }
81
+ code, pre, .path { font-family: var(--mono); font-size: .875em; }
82
+ code { background: var(--code-bg); border: 1px solid var(--border); border-radius: 5px; padding: .08em .4em; overflow-wrap: anywhere; }
83
+ pre { background: var(--code-bg); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: .7rem .9rem; overflow-x: auto; margin: .4rem 0 0; }
84
+ pre code { background: none; border: 0; padding: 0; }
85
+ a { color: var(--accent); }
86
+ .muted { color: var(--muted); }
87
+ .small-text { font-size: .85rem; }
88
+ .sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
89
+ .skip { position: absolute; left: -999px; top: 8px; background: var(--accent); color: var(--accent-contrast); padding: .4rem .8rem; border-radius: 6px; z-index: 10; }
90
+ .skip:focus { left: 8px; }
91
+
92
+ :focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 4px; }
93
+
94
+ /* Header — static; the nav below is the sticky element. */
95
+ .topbar {
96
+ display: flex; align-items: center; gap: var(--gap); flex-wrap: wrap;
97
+ padding: 16px 24px; border-bottom: 1px solid var(--border);
98
+ background: color-mix(in srgb, var(--panel) 55%, transparent);
99
+ }
100
+ .brand { display: flex; align-items: center; gap: 12px; min-width: 0; }
101
+ .logo {
102
+ width: 40px; height: 40px; border-radius: 12px;
103
+ background: var(--accent);
104
+ color: #fff; display: grid; place-items: center; font-weight: 800; font-size: .95rem; letter-spacing: .02em; flex: none;
105
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), var(--shadow);
106
+ }
107
+ .version { font-family: var(--mono); font-size: .8rem; font-weight: 500; color: var(--muted); margin-left: .35rem; }
108
+ .sub { margin: 0; color: var(--muted); font-size: .85rem; }
109
+ .chips { list-style: none; margin: 0 auto; padding: 0; display: flex; gap: 8px; flex-wrap: wrap; }
110
+ .chip { display: inline-flex; align-items: center; gap: 7px; padding: 5px 10px; border: 1px solid var(--border); border-radius: 999px; background: var(--panel-2); font-size: .82rem; }
111
+ .chip b { font-weight: 600; }
112
+ .chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); flex: none; }
113
+ .chip[data-state="ok"] .dot { background: var(--ok); }
114
+ .chip[data-state="warn"] .dot { background: var(--warn); }
115
+ .chip[data-state="error"] .dot { background: var(--danger); }
116
+ .chip[data-state="busy"] .dot { background: var(--info); }
117
+ .chip-icon { font-size: .9rem; line-height: 1; }
118
+
119
+ /* Layout */
120
+ .grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s4); padding: 0; max-width: var(--shell); margin: 0 auto; }
121
+ @media (max-width: 860px) {
122
+ .grid { grid-template-columns: 1fr; }
123
+ .topbar { padding: 12px 14px; }
124
+ .chips { margin: 0; width: 100%; }
125
+ }
126
+ .card { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); padding: var(--card-pad); box-shadow: var(--shadow); min-width: 0; }
127
+ .card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); margin-bottom: var(--s4); }
128
+ .card > h2:first-child, .card-head + * { margin-top: 0; }
129
+ .card-state { color: var(--muted); padding: var(--s3) 0; }
130
+ .card-state.error-state { color: var(--danger); }
131
+ .card-body > * + * { margin-top: var(--s4); }
132
+ .badge { display: inline-block; font-size: .75rem; padding: 2px 9px; border-radius: 999px; border: 1px solid var(--border-strong); background: var(--panel-2); color: var(--muted); }
133
+ .badge.ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 50%, var(--border)); }
134
+ .badge.warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 50%, var(--border)); }
135
+ .badge.danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 50%, var(--border)); }
136
+ .badge.info { color: var(--info); border-color: color-mix(in srgb, var(--info) 50%, var(--border)); }
137
+
138
+ /* Key/value */
139
+ .kv { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 8px 16px; align-items: center; }
140
+ .kv .k { color: var(--muted); font-size: .85rem; }
141
+ .kv .v { min-width: 0; }
142
+ @media (max-width: 520px) { .kv { grid-template-columns: 1fr; gap: 2px 0; } .kv .k { margin-top: 8px; } }
143
+ .path-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
144
+ .path { display: inline-block; max-width: 100%; overflow-wrap: anywhere; word-break: break-all; padding: .25em .5em; }
145
+ .ws-name { font-size: 1.15rem; }
146
+ .desktop-command pre { white-space: pre-wrap; overflow-wrap: anywhere; }
147
+ .desktop-command .help { margin-top: 8px; }
148
+
149
+ /* Callouts */
150
+ .callout { display: flex; gap: 10px; align-items: flex-start; padding: 10px 12px; border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--panel-2); font-size: .92rem; }
151
+ .callout.warn { border-color: color-mix(in srgb, var(--warn) 45%, var(--border)); }
152
+ .callout.warn > span:first-child { color: var(--warn); }
153
+ .callout.info { border-color: color-mix(in srgb, var(--info) 45%, var(--border)); }
154
+ .callout.info > span:first-child { color: var(--info); }
155
+ .callout.danger { border-color: color-mix(in srgb, var(--danger) 45%, var(--border)); }
156
+
157
+ /* Forms */
158
+ .form { display: flex; flex-direction: column; gap: 8px; }
159
+ label { font-size: .9rem; font-weight: 600; }
160
+ .input-row { display: flex; gap: 8px; flex-wrap: wrap; }
161
+ .input-row input { flex: 1 1 260px; min-width: 0; }
162
+ input[type="text"], input[type="url"], input[type="password"], input[type="number"], select {
163
+ font: inherit; color: var(--text); background: var(--code-bg); border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
164
+ padding: 9px 11px; width: 100%;
165
+ }
166
+ input[type="text"]:focus-visible, input[type="url"]:focus-visible, input[type="password"]:focus-visible, input[type="number"]:focus-visible, select:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; border-color: var(--focus); }
167
+ input[aria-invalid="true"] { border-color: var(--danger); }
168
+ .help { color: var(--muted); font-size: .84rem; margin: 0; }
169
+ .error { color: var(--danger); font-size: .88rem; margin: 0; }
170
+ .progress { display: flex; align-items: center; gap: 8px; color: var(--info); font-size: .9rem; margin: 0; }
171
+ .spinner { width: 14px; height: 14px; border: 2px solid var(--border-strong); border-top-color: var(--info); border-radius: 50%; animation: spin .8s linear infinite; }
172
+ @keyframes spin { to { transform: rotate(360deg); } }
173
+ @media (prefers-reduced-motion: reduce) { .spinner { animation: none; } }
174
+ .actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
175
+ .actions.right { justify-content: flex-end; }
176
+
177
+ .btn {
178
+ font: inherit; font-size: .92rem; font-weight: 600; cursor: pointer;
179
+ -webkit-appearance: none; appearance: none;
180
+ color: var(--text); background: var(--panel-2); border: 1px solid var(--border-strong); border-radius: 10px;
181
+ padding: 8px 14px; line-height: 1.2; white-space: nowrap;
182
+ transition: border-color .15s ease, background-color .15s ease, color .15s ease, transform .06s ease;
183
+ }
184
+ .btn:hover { border-color: var(--accent); background: var(--raised); }
185
+ .btn:active { transform: translateY(1px); }
186
+ .btn:disabled, .btn[aria-busy="true"] { opacity: .6; cursor: progress; transform: none; }
187
+ .btn.primary { background: var(--accent); color: var(--accent-contrast); border-color: transparent; box-shadow: inset 0 1px 0 rgba(255, 255, 255, .22), var(--shadow); }
188
+ .btn.primary:hover { background: var(--accent-strong); }
189
+ @media (prefers-reduced-motion: reduce) { .btn { transition: none; } .btn:active { transform: none; } }
190
+ .btn.ghost { background: transparent; border-color: transparent; color: var(--muted); }
191
+ .btn.ghost:hover { color: var(--text); border-color: var(--border-strong); }
192
+ .btn.small { font-size: .8rem; padding: 5px 10px; }
193
+ .btn.danger { background: var(--danger); color: #fff; border-color: var(--danger); }
194
+ .btn.danger-outline { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 55%, var(--border)); background: transparent; }
195
+ .btn.danger-outline:hover { background: color-mix(in srgb, var(--danger) 10%, transparent); }
196
+
197
+ /* Radios / checks */
198
+ .radios, .checks { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 6px 12px 10px; margin: 0; }
199
+ legend { font-weight: 600; font-size: .9rem; padding: 0 4px; }
200
+ .radio, .check { display: flex; gap: 10px; align-items: flex-start; padding: 8px 4px; border-radius: 6px; font-weight: 500; cursor: pointer; }
201
+ .radio:hover, .check:hover { background: var(--panel-2); }
202
+ .radio input, .check input { margin: .3rem 0 0; accent-color: var(--accent); flex: none; width: 16px; height: 16px; }
203
+ .radio small, .check small { display: block; color: var(--muted); font-weight: 400; font-size: .84rem; }
204
+
205
+ /* Stats */
206
+ .two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
207
+ @media (max-width: 520px) { .two-col { grid-template-columns: 1fr; } }
208
+ .stat { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 10px 12px; background: var(--panel-2); }
209
+ .stat-label { color: var(--muted); font-size: .8rem; }
210
+ .stat-value { font-family: var(--mono); font-size: 1.05rem; font-weight: 600; margin-top: 2px; }
211
+ .stat-value .badge { font-family: var(--font); margin-left: 6px; }
212
+
213
+ /* Details */
214
+ .details { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 8px 12px; }
215
+ .details summary { cursor: pointer; font-weight: 600; font-size: .9rem; }
216
+ .dl { display: grid; grid-template-columns: max-content 1fr; gap: 6px 14px; margin: 10px 0; }
217
+ .dl dt { color: var(--muted); font-size: .85rem; }
218
+ .dl dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
219
+ @media (max-width: 520px) { .dl { grid-template-columns: 1fr; gap: 2px 0; } .dl dt { margin-top: 6px; } }
220
+
221
+ /* Clients */
222
+ .clients { display: flex; flex-direction: column; gap: 12px; }
223
+ .client { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 12px 14px; background: var(--panel-2); }
224
+ .client-head { display: flex; justify-content: space-between; gap: 10px; align-items: flex-start; margin-bottom: 8px; }
225
+ .client-name { font-weight: 650; }
226
+ .client-id { font-size: .8rem; }
227
+ .client .checks { background: var(--panel); }
228
+ .client .actions { margin-top: 10px; }
229
+ .project-entry > * + * { margin-top: 9px; }
230
+ .project-path { display: block; width: 100%; overflow-wrap: anywhere; white-space: normal; }
231
+ .project-status { margin-bottom: 0; }
232
+ .empty { border: 1px dashed var(--border-strong); border-radius: var(--radius-sm); padding: 14px; color: var(--muted); }
233
+
234
+ /* Notice */
235
+ .notice {
236
+ display: flex; gap: 10px; align-items: flex-start; max-width: 1180px; margin: 14px auto 0; padding: 10px 14px;
237
+ border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--panel); font-size: .92rem;
238
+ }
239
+ @media (max-width: 860px) { .notice { margin: 12px 14px 0; } }
240
+ .notice[data-kind="success"] { border-color: color-mix(in srgb, var(--ok) 55%, var(--border)); }
241
+ .notice[data-kind="success"] .notice-icon { color: var(--ok); }
242
+ .notice[data-kind="error"] { border-color: color-mix(in srgb, var(--danger) 55%, var(--border)); }
243
+ .notice[data-kind="error"] .notice-icon { color: var(--danger); }
244
+ .notice[data-kind="info"] { border-color: color-mix(in srgb, var(--info) 55%, var(--border)); }
245
+ .notice[data-kind="info"] .notice-icon { color: var(--info); }
246
+ .notice-text { flex: 1; overflow-wrap: anywhere; white-space: pre-wrap; }
247
+ .notice-close { flex: none; }
248
+
249
+ /* Footer */
250
+ .foot { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; max-width: 1180px; margin: 0 auto; padding: 8px 24px 28px; color: var(--muted); font-size: .82rem; }
251
+ @media (max-width: 860px) { .foot { padding: 8px 14px 24px; } }
252
+
253
+ /* Dialog */
254
+ .dialog { border: 1px solid var(--border-strong); border-radius: var(--radius); background: var(--panel); color: var(--text); padding: 18px 20px; max-width: 32rem; width: calc(100% - 32px); box-shadow: var(--shadow-lg); }
255
+ .dialog::backdrop { background: rgba(0, 0, 0, .55); }
256
+ .dialog h3 { margin-bottom: 8px; }
257
+ .dialog p { overflow-wrap: anywhere; }
258
+
259
+ /* Owner consent details stay readable on narrow screens and with long commands. */
260
+ #schedules-list pre { white-space: pre-wrap; overflow-wrap: anywhere; max-height: 220px; overflow: auto; padding: 12px; background: var(--panel); border-radius: var(--radius-sm); }
261
+ #schedules-list code { overflow-wrap: anywhere; }
262
+ #schedules-list .btn { margin: 8px 8px 0 0; }
263
+
264
+ /* ---- Page router layout: one shared shell width, consistent rhythm ---- */
265
+ .page-stack { display: flex; flex-direction: column; gap: var(--s4); padding: var(--s6) 24px 40px; }
266
+ .page-stack > .card, .page-stack > #workbench, .page-stack > .grid, .page-stack > .callout { width: 100%; max-width: var(--shell); margin-inline: auto; }
267
+ @media (max-width: 860px) { .page-stack { padding: var(--s4) 14px 32px; } }
268
+ .workbench-nav {
269
+ position: sticky; top: 0; z-index: 4;
270
+ background: var(--bg);
271
+ border-bottom: 1px solid var(--border);
272
+ }
273
+ @supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
274
+ .workbench-nav {
275
+ background: color-mix(in srgb, var(--bg) 74%, transparent);
276
+ -webkit-backdrop-filter: blur(14px) saturate(1.15);
277
+ backdrop-filter: blur(14px) saturate(1.15);
278
+ }
279
+ }
280
+ @media (max-width: 400px) { .workbench-nav { gap: 6px; } .workbench-nav .btn { font-size: .84rem; padding: 6px 10px; } }
281
+
282
+ /* ---- Accessible tooltips (ui/tooltips.js) ---- */
283
+ .help-tip {
284
+ display: inline-grid; place-items: center; width: 1.25rem; height: 1.25rem; padding: 0;
285
+ font: inherit; font-size: .75rem; font-weight: 700; line-height: 1; cursor: help;
286
+ color: var(--muted); background: var(--panel-2); border: 1px solid var(--border-strong); border-radius: 50%;
287
+ vertical-align: text-bottom; margin-left: .25rem; flex: none;
288
+ }
289
+ .help-tip:hover, .help-tip[aria-expanded="true"] { color: var(--accent); border-color: var(--accent); }
290
+ #dodo-tooltip {
291
+ position: fixed; z-index: 60; max-width: min(320px, calc(100vw - 16px));
292
+ background: var(--panel); color: var(--text); border: 1px solid var(--border-strong);
293
+ border-radius: var(--radius-sm); padding: 8px 11px; font-size: .84rem; line-height: 1.5;
294
+ box-shadow: 0 6px 24px rgba(0, 0, 0, .3); pointer-events: none; overflow-wrap: anywhere;
295
+ }
296
+
297
+ /* ---- SweetAlert2 (vendored, same origin) themed with the panel tokens ---- */
298
+ .swal2-popup { background: var(--panel) !important; color: var(--text) !important; border: 1px solid var(--border-strong); border-radius: var(--radius) !important; font-family: var(--font) !important; box-shadow: var(--shadow-lg) !important; }
299
+ .swal2-title { color: var(--text) !important; font-size: 1.15rem !important; }
300
+ .swal2-html-container { color: var(--text) !important; font-size: .95rem !important; overflow-wrap: anywhere; }
301
+ /* swal2-toast-shown lives on <body>; only real modals get the dark backdrop. */
302
+ body:not(.swal2-toast-shown) .swal2-container.swal2-backdrop-show { background: rgba(0, 0, 0, .55) !important; }
303
+ body.swal2-toast-shown .swal2-container { background: transparent !important; }
304
+ .swal2-actions { gap: 10px; }
305
+ .swal2-actions .btn { margin: 0; }
306
+ .swal2-toast { background: var(--panel) !important; color: var(--text) !important; border: 1px solid var(--border-strong); box-shadow: var(--shadow) !important; }
307
+ .swal2-toast .swal2-title { font-size: .92rem !important; font-weight: 600; }
308
+ .swal2-timer-progress-bar { background: var(--accent) !important; }
309
+ .swal2-loader { border-color: var(--accent) transparent var(--accent) transparent !important; }
310
+ @media (prefers-reduced-motion: reduce) {
311
+ .swal2-show, .swal2-hide, .swal2-toast { animation: none !important; }
312
+ .swal2-timer-progress-bar { display: none !important; }
313
+ }
314
+
315
+ /* ---- Overview checklist ---- */
316
+ .ov-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
317
+ .ov-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; counter-reset: step; }
318
+ .ov-step { display: flex; align-items: center; gap: 12px; border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 10px 12px; background: var(--panel-2); }
319
+ .ov-step .num { flex: none; width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; font-size: .85rem; font-weight: 700; border: 1px solid var(--border-strong); color: var(--muted); }
320
+ .ov-step[data-done="true"] { border-color: color-mix(in srgb, var(--ok) 45%, var(--border)); }
321
+ .ov-step[data-done="true"] .num { color: var(--ok); border-color: var(--ok); }
322
+ .ov-step .grow { flex: 1 1 160px; min-width: 0; }
323
+ .ov-step small { display: block; color: var(--muted); }
324
+ @media (max-width: 480px) {
325
+ .ov-step { flex-wrap: wrap; }
326
+ .ov-step .grow { flex: 1 1 calc(100% - 40px); }
327
+ .ov-step .btn { margin-left: 38px; }
328
+ }
329
+ .ov-issues { display: flex; flex-direction: column; gap: var(--s2); }
330
+
331
+ /* Full-width items inside a 2-col page grid. */
332
+ #personal-note { grid-column: 1 / -1; }
333
+
334
+ /* ---- Bounded loading skeleton (no flicker under reduced motion) ---- */
335
+ .skeleton { position: relative; overflow: hidden; background: var(--panel-2); border-radius: var(--radius-sm); min-height: 3rem; color: transparent; animation: skeleton-pulse 1.4s ease-in-out 4; }
336
+ @keyframes skeleton-pulse { 0%, 100% { opacity: .72; } 50% { opacity: 1; } }
337
+ @media (prefers-reduced-motion: reduce) { .skeleton { animation: none; } }
338
+
339
+ .client-add { margin-top: 14px; }
340
+ .client-add form { display: grid; gap: 10px; margin: 12px 0; }
341
+ .client-add form[hidden] { display: none; }
342
+ .client-add select { width: 100%; min-width: 0; }
343
+ .client-add .btn.primary { justify-self: start; }
344
+
345
+ #client-manage-delete { margin: 12px 0; }
346
+ #client-manage-list small { overflow-wrap: anywhere; }
347
+ #confirm-text { white-space: pre-line; overflow-wrap: anywhere; max-height: 55vh; overflow-y: auto; }