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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 DODO contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,425 @@
1
+ # DODO MCP
2
+
3
+ **DODO MCP 1.0.0** คือ MCP server แบบ local-first สำหรับให้ AI ช่วยพัฒนา software โดยทำงานกับ workspace ที่เจ้าของเลือก ค่าเริ่มต้นเป็นโหมดส่วนตัวแบบเพิ่มโปรเจกต์แล้วใช้ได้ทันที และยังมีโหมด managed สำหรับแยก workspace ACL/trust แบบละเอียด
4
+
5
+ ## จุดเด่น
6
+
7
+ - MCP ผ่าน HTTP ที่ `127.0.0.1:21730/mcp` พร้อม OAuth และ PKCE
8
+ - Local Config แบบ loopback ที่ `127.0.0.1:21731`
9
+ - HTTP ใช้ Compact Tool Surface 19 tools เพื่อลดภาระการโหลด schema
10
+ - STDIO ใช้ Full Tool Surface; มี capability definitions ทั้งหมด 125 รายการ แต่ค่าเริ่มต้นซ่อน Sub-agent 4 operations จาก MCP จึงเห็น 121 tools
11
+ - Hybrid Surface 49 tools สำหรับ client ที่รับ catalog ขนาดกลาง
12
+ - อ่าน ค้นหา สร้าง แก้ ย้าย ลบไฟล์ พร้อม expected hash, journal และ rollback
13
+ - รันคำสั่ง งานแบบขนาน jobs, Git, TypeScript/JavaScript intelligence, LSP และ task assistance
14
+ - รองรับภาพ เสียง วิดีโอ เบราว์เซอร์ เกม และ workflow ตาม dependency และ permission ที่เจ้าของเปิดใช้
15
+ - มี Universal Resource Layer + CAS สำหรับ text/binary/image/audio/video/PDF/ZIP/WASM พร้อม SHA-256, dedup, bounded range/resume และ MCP image/audio blocks
16
+ - มี Project Brain ที่ทำ incremental AST index สำหรับ symbols, references, imports, routes, tests และ dependencies พร้อม source-hash freshness
17
+ - มี Context Engine สำหรับ goal-driven retrieval แบบมี budget, provenance, confidence, freshness และ L0–L6 dependency cache
18
+ - มี owner-reviewed Memory สำหรับ fact/decision/fix/convention ที่ผูก source evidence, retention และ freshness พร้อม learning proposal ที่ไม่ติดตั้งหรือรันเอง
19
+ - มี Runtime Intelligence สำหรับ task ที่ reconnect ได้, process/test/browser evidence แบบ bounded, snapshot freshness และ diagnosis ที่แยก fact/observation/inference
20
+ - มี Advanced Agent Runtime สำหรับ immutable plan, parallel hypotheses, intent locks, guarded snapshots, evidence-backed completion, restart recovery และ owner-reviewed reusable guidance
21
+ - มี AI Providers เจ็ด presets/Custom, profiles, model/tool loop และประวัติ private ผ่าน Local Config ([คู่มือ](docs/AI_PROVIDERS.md))
22
+ - เขียน/รันหลายโปรเจกต์พร้อมกันด้วย targetProjectId และคิว mutation แยกโปรเจกต์
23
+ - มี DodoBench และ revision-bound release gate สำหรับ retrieval, safe edit, runtime, resource, recovery, security และ fresh package artifact
24
+ - เปลี่ยน workspace จาก Local Config ได้จริง โดยรอ request/jobs และ rollback เมื่อเตรียม workspace ใหม่ไม่สำเร็จ
25
+ - มี owner-only Project Registry พร้อม stable project ID และ readiness โดยไม่คัดลอก trust/ACL
26
+ - อ่าน overview/list/files และค้นหาพร้อมกันได้สูงสุด 8 โปรเจกต์ที่เจ้าของลงทะเบียน โดย personal mode ไม่ต้องตั้ง ACL ซ้ำ
27
+ - เปิด Cloudflare Tunnel พร้อม `dodo start` ด้วย token ชั่วคราวจาก terminal หรือ Local Config โดยไม่บันทึก token ลงเครื่อง
28
+ - ไม่ส่ง token, secret หรือ state DB ไปที่ repository และไม่ให้ repository config เพิ่มสิทธิ์
29
+
30
+ ## เริ่มใช้งาน
31
+
32
+ ```bash
33
+ npm install -g dodo-mcp
34
+ dodo setup --check
35
+ dodo --cli
36
+ ```
37
+
38
+ `dodo --cli` เปิดเมนู local owner สำหรับเลือก/เพิ่มโปรเจกต์ เปิด MCP + Local Config +
39
+ Tunnel และรัน setup รวม `cloudflared` โดยไม่ต้อง `cd` เข้าโปรเจกต์
40
+ ก่อน หากเรียก `dodo` หรือ `dodo start` จากโฟลเดอร์ใดก็ตาม ระบบจะเปิดโปรเจกต์ที่
41
+ เจ้าของเลือกล่าสุด หากยังไม่มีโปรเจกต์ใน registry จะเปิด control plane, OAuth และ
42
+ authenticated tool catalog ได้โดยไม่ใช้ CWD เป็น workspace เมื่อเจ้าของเพิ่มโปรเจกต์
43
+ จาก Local Config แล้ว OAuth client ที่เจ้าของอนุมัติจะใช้โปรเจกต์นั้นได้ทันทีตาม scopes
44
+ ของ token และ Agent Profile ที่เลือก โดยไม่ต้องตั้ง permission ซ้ำต่อ path
45
+
46
+ เปิดโปรเจกต์โดยตรงและจำไว้สำหรับครั้งถัดไปได้ด้วย:
47
+
48
+ ```bash
49
+ dodo start --root /path/to/your/project
50
+ ```
51
+
52
+ โหมดส่วนตัวใช้ effective trust แบบ trusted กับโปรเจกต์ที่เจ้าของลงทะเบียน คำสั่งจึงรัน
53
+ ด้วยสิทธิ์ OS ของบัญชีเจ้าของและยังผ่าน command sandbox ที่ตั้งไว้, path/secret guards,
54
+ expected hash, workspace context และ OAuth scopes หากต้องแยก client/profile/trust ต่อ
55
+ โปรเจกต์ ให้เปลี่ยนเป็นโหมด managed ที่หน้า Settings
56
+
57
+ `dodo setup --check` และ `dodo setup --plan` เป็น read-only หากแผนมี dependency ที่ต้องติดตั้ง ให้ตรวจรายการก่อนแล้วจึงรัน `dodo setup --yes --components <list>` ระบบจะไม่เริ่ม installer หากไม่มี `--yes` และ `--yes` ไม่ข้าม sudo, OS permission หรือ owner consent
58
+
59
+ เมื่อ DODO ตรวจพบ config เดิมในตำแหน่งมาตรฐาน สามารถใช้ `dodo setup --import-state` เพื่อนำเข้าเฉพาะ preference ที่ปลอดภัย เช่น port, search backend, retention และ tool surface ระบบจะสร้าง installation identity ใหม่เสมอและไม่คัดลอก OAuth keys/tokens, client grants, workspace ACL, trust, approvals, schedules, public origin, web/desktop permission, executable registration หรือฐานข้อมูลเดิม ต้นฉบับจะไม่ถูกแก้ไข
60
+
61
+ เปิด Local Config จาก URL ที่ `dodo` แสดงใน terminal ใช้สำหรับเพิ่มโปรเจกต์, AI
62
+ connections/profiles, public origin และเปลี่ยน access mode เจ้าของเท่านั้น โหมดส่วนตัว
63
+ พร้อมใช้โดยไม่ต้องตั้ง trust/client/profile permission รายโปรเจกต์
64
+
65
+ หน้าเว็บจัดเป็น dashboard 8 หน้า (ภาพรวม · โปรเจกต์ · Providers & Profiles ·
66
+ Chat & Tasks · Runs & Jobs · Approvals · Knowledge · Settings) หน้าภาพรวมแสดงสถานะ,
67
+ ขั้นตอนถัดไป และสิ่งที่ต้องตรวจสอบเท่านั้น คำอธิบายยาวถูกย้ายไป tooltip (ปุ่ม `?`
68
+ เปิดด้วย hover/โฟกัสคีย์บอร์ด/แตะ ปิดด้วย Escape) และส่วน "รายละเอียดทางเทคนิค"
69
+ ที่พับได้ กล่องยืนยัน/แจ้งผลใช้ SweetAlert2 ที่ vendor มากับแพ็กเกจ (same-origin
70
+ ไม่มี CDN, CSP `'self'` เท่าเดิม) การลบ/ยกเลิก/เปลี่ยนโหมดต้องยืนยันก่อนเสมอ
71
+ และงานที่มีค่าใช้จ่ายหรือผลไม่แน่นอนจะบอกชัดว่า "ไม่ retry อัตโนมัติ"
72
+
73
+ หน้า **Settings → Sub-agent tools ใน MCP** มีสวิตช์เปิด/ปิดการ expose
74
+ `subagent_spawn`, `subagent_status`, `subagent_result` และ `subagent_control` ให้ AI
75
+ ภายนอก ค่าเริ่มต้นปิดเพื่อให้ catalog สำหรับงานทั่วไปกระชับขึ้น แต่หน้า Chat & Tasks
76
+ ยังสร้างและจัดการ agent ได้ตามเดิม เมื่อเปลี่ยนค่านี้ต้อง restart DODO แล้ว rescan หรือ
77
+ สร้าง MCP app ใหม่ตามพฤติกรรมของ client การตั้งค่านี้เปลี่ยนเฉพาะการมองเห็น tools
78
+ และไม่เพิ่ม OAuth scope, trust, approval หรือสิทธิ์ของ profile
79
+
80
+ ลงทะเบียนโปรเจกต์ที่ต้องการใช้งานบ่อยได้โดยไม่เริ่ม server:
81
+
82
+ ```bash
83
+ dodo project add /absolute/path/to/project --name "Web application"
84
+ dodo project list
85
+ dodo project info prj_xxxxxxxxxxxx
86
+ dodo project remove prj_xxxxxxxxxxxx --yes
87
+ ```
88
+
89
+ Project Registry ใช้ project ID คงที่แยกจาก workspace authority และแสดง readiness
90
+ ของ path ปัจจุบัน ดู contract ที่ [Project Registry](docs/PROJECTS.md)
91
+
92
+ ### อ่านหลายโปรเจกต์พร้อมกัน
93
+
94
+ เจ้าของต้องลงทะเบียนแต่ละโปรเจกต์ โหมดส่วนตัวใช้ OAuth scopes เดิมกับทุก project
95
+ ที่ลงทะเบียน ส่วนโหมด managed ต้องให้ `dodo:read` แก่ client ในแต่ละ workspace:
96
+
97
+ ```text
98
+ project_overview()
99
+ → federation.projects แสดงเฉพาะโปรเจกต์ที่ client อ่านได้
100
+
101
+ dodo_read(operation="search_code", args={
102
+ projectIds: ["prj_2bcdefghjkmn", "prj_3cdefghjkmnp"],
103
+ query: "UserDto"
104
+ })
105
+ ```
106
+
107
+ `project_overview`, `list_files` และ `read_files` รับ `projectId` ได้ ส่วน
108
+ `search_code` รับ `projectId` หรือ `projectIds` สูงสุด 8 รายการ ผลแต่ละโปรเจกต์มี
109
+ project/workspace identity, federation epoch และ source hash เพื่อแยก evidence
110
+ ออกจากกัน ค่า `workspaceId`/`workspaceEpoch` ระดับบนของ MCP call ยังคงเป็นของ
111
+ active workspace เสมอ
112
+
113
+ Federation แบบ `projectId/projectIds` ยังคง read-only สำหรับการเขียน/รันหลายโปรเจกต์
114
+ ให้เรียก `project_overview(targetProjectId="prj_…")` แล้วใช้ `targetProjectId` และ
115
+ workspace ID/epoch ที่ได้รับกับทุก operation ต่อมา คนละโปรเจกต์ทำงานพร้อมกันได้
116
+ โดยไม่เปลี่ยน default; งาน mutation ในโปรเจกต์เดียวกันเข้าคิวร่วมกัน
117
+ ดู [การตั้ง AI Providers, Profiles และ Sub-agents ผ่านเว็บ](docs/AI_PROVIDERS.md)
118
+
119
+ ### Universal Resource Layer
120
+
121
+ ไฟล์ขนาดใหญ่และสื่อใช้ resource contract เดียวกัน โดยเริ่มจาก path ภายใน active
122
+ workspace หรือ `assetId` ที่ principal เดียวกันเป็นเจ้าของ:
123
+
124
+ ```text
125
+ resource_inspect(path="docs/spec.pdf")
126
+ → resourceId + dodo-resource:// URI + MIME + bytes + SHA-256 + capabilities
127
+
128
+ resource_read_range(resourceId=..., offset=0, length=65536)
129
+ → bounded Base64 chunk + chunk hash + principal-bound resumeToken
130
+
131
+ resource_preview(resourceId=...)
132
+ → text / MCP image / MCP audio / metadata ตามชนิดและขนาด
133
+ ```
134
+
135
+ HTTP Compact/Hybrid เรียก operation เดียวกันผ่าน `dodo_media` หลังค้นด้วย
136
+ `dodo_discover` CAS เก็บ object แบบ immutable ตาม hash และ deduplicate ข้าม reference
137
+ ได้ แต่ resource ID/URI ไม่ใช่ capability ทุก call ยังตรวจ OAuth, live grant,
138
+ target authority, workspace ID/epoch และ principal ownership ซ้ำ ไม่ ingest `.env`,
139
+ private DODO state, traversal, symlink หรือ hardlink และไม่ inflate/execute archive
140
+ content ดูรายละเอียดที่ [Resources](docs/RESOURCES.md)
141
+
142
+ ### Project Brain
143
+
144
+ Project Brain สร้าง graph แบบ bounded จาก TypeScript/JavaScript AST และ
145
+ `package.json` โดยไม่รัน source, repository plugin หรือ command ใด ๆ ระบบ refresh
146
+ อัตโนมัติและ parse ใหม่เฉพาะไฟล์ที่เปลี่ยน พร้อมขยายผลไปยัง relation ที่ได้รับ
147
+ ผลกระทบ:
148
+
149
+ ```text
150
+ brain_status()
151
+ brain_query(query="UserService", nodeTypes=["symbol"])
152
+ brain_symbol(uri="symbol://...")
153
+ brain_rebuild(mode="incremental", waitMs=10000)
154
+ ```
155
+
156
+ ใน Compact/Hybrid ให้เรียกผ่าน `dodo_assist_read` หรือ `dodo_assist_change`
157
+ ตาม schema จาก `dodo_discover` ค่า `symbol://` เป็น semantic identity ที่คงเดิม
158
+ เมื่อไฟล์ถูกย้ายแบบ exact-content แต่ URI/index row ไม่ใช่สิทธิ์ ทุก query จะตรวจ
159
+ OAuth, live grant, target authority, workspace ID/epoch, path/secret policy และ SHA-256
160
+ ของ source ปัจจุบันใหม่ก่อนคืนผล ดู [Project Brain](docs/BRAIN.md)
161
+
162
+ ### Context Engine และ Evidence
163
+
164
+ ให้ AI ขอ context ตาม goal ได้โดยไม่ต้องเลือก search/brain/git ทีละตัว:
165
+
166
+ ```text
167
+ context_query(goal="Fix login callback", terms=["loginCallback", "OAuth"],
168
+ projects=["Frontend", "Backend"], budget=24000)
169
+ ```
170
+
171
+ Compact/Hybrid ใช้ `dodo_assist_read(operation="context_query", args={...})` ผลลัพธ์
172
+ แยก `FACT`, `OBSERVATION`, `MEMORY`, `INFERENCE`, `HYPOTHESIS` และทุก evidence มี
173
+ project identity, source hash, line/commit, confidence, generated/verified time และ
174
+ freshness Cache L0–L6 ตรวจ ACL และ dependency hash ก่อนใช้ซ้ำ Source เปลี่ยนแล้ว
175
+ evidence เดิมจะเป็น stale และ derived cache ถูกสร้างใหม่
176
+
177
+ ผลค้นหา, README และ repository instruction เป็น untrusted content และไม่สามารถเพิ่ม
178
+ scope, ACL, trust หรือ approval ได้ Memory ที่เจ้าของอนุมัติจะแสดงเป็น evidence class
179
+ `MEMORY`; runtime evidence ที่ caller เดียวกันเก็บไว้จะแสดงเป็น `OBSERVATION` พร้อม
180
+ source hash และ freshness ดู contract ที่
181
+ [Context Engine](docs/CONTEXT.md)
182
+
183
+ ### Owner-reviewed Memory
184
+
185
+ AI สร้าง memory ถาวรเองไม่ได้ ขั้นแรกต้องใช้ current `context_evidence` เพื่อเสนอ:
186
+
187
+ ```text
188
+ dodo_assist_read(operation="context_query", args={goal:"Find session policy", ...})
189
+ dodo_assist_change(operation="memory_propose", args={
190
+ kind:"decision",
191
+ claim:"Keep session state scoped to one workspace.",
192
+ evidenceIds:["evidence_..."]
193
+ })
194
+ ```
195
+
196
+ จากนั้นเจ้าของตรวจ proposal และ digest ผ่าน private local CLI เท่านั้น:
197
+
198
+ ```bash
199
+ dodo memory pending
200
+ dodo memory show memprop_xxxxxxxxxxxx
201
+ dodo memory approve memprop_xxxxxxxxxxxx --digest sha256:...
202
+ ```
203
+
204
+ Memory ทุกชิ้นเป็น `evidence_only` และ `untrusted_content` Source เปลี่ยนหรือ retention
205
+ หมดจะเป็น stale และไม่ถูกใช้เป็น current context การแชร์ข้าม project ต้องระบุ
206
+ `--share-with` ตอน owner approval และ client ยังต้องมี live ACL ใน project เป้าหมาย
207
+ รายละเอียดอยู่ที่ [Memory and Reviewed Learning](docs/MEMORY.md)
208
+
209
+ ### Runtime Intelligence
210
+
211
+ งานทดสอบหรือ process ที่ต้องติดตามข้ามการ reconnect ใช้ runtime session โดยคำสั่ง
212
+ ยังผ่าน exec approval, trusted executable resolver และ command sandbox เดิม:
213
+
214
+ ```text
215
+ dodo_assist_change(operation="runtime_session_open", args={label:"verify checkout"})
216
+ dodo_exec(operation="runtime_task_start", args={
217
+ sessionId:"runtime_...", kind:"test", program:"npm", args:["test"],
218
+ network:false, idempotencyKey:"client-generated-key"
219
+ })
220
+ dodo_assist_read(operation="runtime_task_observe", args={sessionId:"runtime_...", taskId:"rtask_..."})
221
+ dodo_assist_read(operation="runtime_diagnose", args={sessionId:"runtime_...", evidenceIds:["runtimeev_..."]})
222
+ ```
223
+
224
+ Runtime store เก็บเฉพาะ status, byte counts, aggregate test counts และ SHA-256 ไม่เก็บ
225
+ stdout/stderr, DOM, console หรือ header ดิบ Browser collector ใช้ได้เฉพาะ
226
+ `browser_session` ที่ caller เปิดและมีสิทธิ์อยู่แล้ว โดยส่ง bounded observation/image
227
+ ใน response ปัจจุบัน แต่ persist เฉพาะ safe URL, hashes และ counts Snapshot ไม่ copy
228
+ ไฟล์และไม่ rollback เอง; ต้องเรียก `rollback_changes` แยกต่างหาก ดู
229
+ [Runtime Intelligence](docs/RUNTIME.md)
230
+
231
+ ### Advanced Agent Runtime
232
+
233
+ งานแก้ปัญหาหลายขั้นสามารถเปิด durable agent run ที่จำกัด project, writable paths,
234
+ programs, optional capabilities, quotas และเวลาทำงานเพิ่มจากสิทธิ์เดิม:
235
+
236
+ ```text
237
+ dodo_assist_change(operation="agent_run_open", args={goal, completionCriteria, capabilities})
238
+ dodo_assist_change(operation="agent_hypothesis_open", args={runId, ...})
239
+ dodo_assist_change(operation="agent_intent_acquire", args={runId, hypothesisId, kind:"path", resourceKey:"src"})
240
+ dodo_write(operation="agent_write", args={runId, hypothesisId, operation:"edit_file", args:{...}})
241
+ dodo_assist_read(operation="agent_snapshot_compare", args={...})
242
+ ```
243
+
244
+ Run/plan/hypothesis/intent/snapshot/skill ไม่ให้ permission เพิ่ม ทุก target ยังผ่าน
245
+ OAuth scope, live target authority/epoch, trust approval, path/secret guards, expected hash,
246
+ command sandbox, idempotency และ audit เดิม `agent_exec` ใช้ explicit argv/owned handles
247
+ เท่านั้น และ cancel/pause coordinator ไม่ kill job ดู
248
+ [Advanced Agent Runtime](docs/AGENT_RUNTIME.md)
249
+
250
+ ### เชื่อม Remote MCP ผ่าน Cloudflare Tunnel
251
+
252
+ DODO ไม่สร้าง Tunnel, DNS หรือ Cloudflare account ให้ ผู้ใช้สร้าง remotely-managed Tunnel และตั้ง public hostname ให้ route **ทุก path** มาที่ `http://127.0.0.1:21730` ก่อน จากนั้นตั้ง public origin ครั้งเดียว:
253
+
254
+ ```bash
255
+ dodo setup --check --components cloudflared
256
+ dodo init --public-url https://mcp.example.com
257
+ dodo start
258
+ # Cloudflare Tunnel token (temporary; Enter = local only):
259
+ ```
260
+
261
+ เมื่อกรอก token DODO จะเริ่ม `cloudflared` เป็น child process ของรอบนั้นและหยุดพร้อม
262
+ DODO Token อยู่ในหน่วยความจำระหว่างรอบและ environment ของ child เท่านั้น ไม่อยู่ใน
263
+ argv, config, Keychain, Credential Manager, Secret Service, tunnel log, MCP response
264
+ หรือ environment ของ MCP jobs กด Enter หรือใช้ `dodo start --no-tunnel` เพื่อเปิด
265
+ เฉพาะ local MCP
266
+
267
+ หน้า Local Config ที่ `127.0.0.1:21731` มีช่อง **Temporary Tunnel token** สำหรับเริ่ม
268
+ และหยุด tunnel ของ DODO process ปัจจุบันได้จริง ช่องจะถูกล้างหลังส่งและ backend ไม่
269
+ persist ค่า ดูสถานะด้วย `dodo tunnel status`, ตรวจ connectivity ด้วย
270
+ `dodo tunnel doctor` และดู log ที่ redacted ด้วย `dodo tunnel logs` คำสั่ง
271
+ `dodo tunnel configure` เดิมยังมีสำหรับ advanced/headless compatibility และต้องเรียก
272
+ โดยเจ้าของอย่างชัดเจน; เส้นทาง `dodo start` และหน้าเว็บไม่ใช้ credential store
273
+
274
+ บน macOS `dodo setup --yes` เลือก component `cloudflared` อยู่ในชุด `all` แล้ว
275
+ Tunnel route ต้องชี้เฉพาะ MCP/OAuth listener `21730` ห้ามชี้ Local Config `21731`
276
+ หรือ metrics `21732` ออก public
277
+
278
+ สำหรับ local MCP client เช่น Codex, Cursor หรือ Claude Desktop:
279
+
280
+ ```bash
281
+ dodo stdio --root /path/to/your/project
282
+ ```
283
+
284
+ STDIO ใช้ full catalog เป็นค่าเริ่มต้น ถ้าต้องการลด catalog ชั่วคราว:
285
+
286
+ ```bash
287
+ dodo stdio --root /path/to/your/project --tools compact
288
+ dodo stdio --root /path/to/your/project --tools hybrid
289
+ ```
290
+
291
+ ## Compact Tool Surface
292
+
293
+ HTTP ใช้ Compact เป็นค่าเริ่มต้น ลำดับการใช้งานคือ:
294
+
295
+ ```text
296
+ project_overview
297
+ → dodo_discover
298
+ → gateway ที่ตรงกับ operation
299
+ ```
300
+
301
+ ตัวอย่างให้ AI แก้ `src/example.ts`:
302
+
303
+ ```text
304
+ dodo_discover(query="edit TypeScript file")
305
+ dodo_read(operation="read_files", args={...})
306
+ dodo_write(operation="edit_file", args={...})
307
+ dodo_read(operation="read_files", args={...})
308
+ ```
309
+
310
+ `dodo_discover` คืน schema ของ operation ที่เลือกและ hash ที่ deterministic ส่วน gateway จะส่ง request ผ่าน policy pipeline เดียวกับ tool รายตัว จึงยังตรวจ scope, ACL, workspace ID/epoch, trust, approval, path guard, secret guard, hash และ audit ครบทุกชั้น
311
+
312
+ ชื่อ gateway `dodo_*` เป็นชื่อ MCP protocol ที่คงไว้เพื่อ compatibility กับ client ที่เชื่อมต่ออยู่ การเปลี่ยนชื่อ gateway ต้องทำเป็น protocol migration แยกต่างหาก
313
+
314
+ ## การเปลี่ยน workspace
315
+
316
+ 1. เปิด Local Config จาก workspace ปัจจุบัน
317
+ 2. ใส่ absolute path ของ project ใหม่
318
+ 3. กดเปลี่ยนโปรเจกต์
319
+ 4. ระบบตรวจ realpath, root policy, jobs และ request ที่กำลังทำงาน
320
+ 5. ระบบเตรียม workspace ใหม่ก่อนสลับ และคืน workspace เดิมหากเตรียมไม่สำเร็จ
321
+ 6. client ต้องเรียก `project_overview` ใหม่เพื่อรับ workspace ID/epoch ใหม่
322
+
323
+ ระบบไม่ kill jobs เงียบ ๆ Managed mode ไม่คัดลอก trust หรือ client ACL ไปยัง workspace ใหม่
324
+
325
+ ## การเชื่อมต่อ
326
+
327
+ - **Local MCP:** `http://127.0.0.1:21730/mcp` สำหรับ process ในเครื่อง
328
+ - **Public MCP:** origin HTTPS ของ tunnel ที่เจ้าของสร้างและกำหนด route เอง; DODO อาจ supervise เฉพาะ `cloudflared` process ที่เจ้าของสั่ง
329
+ - **Local Config:** loopback เท่านั้น ใช้ owner capability token และ Host/Origin checks
330
+
331
+ DODO รายงาน `connected` เฉพาะเมื่อ managed `cloudflared` ตอบ readiness จริง และ `doctor` แยก local/public health ออกจากกัน สถานะนี้ไม่ใช่หลักฐานว่า ChatGPT หรือ AI client เชื่อมต่อแล้ว
332
+
333
+ ## สิทธิ์
334
+
335
+ ค่าเริ่มต้น **personal** ใช้ OAuth scope + Agent Profile เป็นเพดานและไม่ถามซ้ำต่อ
336
+ โปรเจกต์ ส่วน **managed** ใช้ intersection ของ OAuth scope, workspace ACL และ local policy:
337
+
338
+ - `inspect` อ่านและวิเคราะห์ได้
339
+ - `edit` ทำ file changes ที่ผ่าน approval/policy ได้
340
+ - `trusted` อนุญาต effectful work ตาม policy ที่เจ้าของยืนยัน
341
+
342
+ โหมด trusted และคำสั่งที่เจ้าของอนุมัติใช้สิทธิ์ OS ของผู้ใช้จริง ควรเปิดเฉพาะ workspace ที่เชื่อถือได้
343
+
344
+ `dodo --bypass` ปรับ policy เฉพาะรอบนั้นตามที่เจ้าของสั่ง และไม่ปิด OAuth, target authority, workspace context, path guards หรือ secret guards
345
+
346
+ Desktop/Chrome consent แบบ `--persist` เป็นระดับ installation อนุญาตครั้งเดียวจาก path
347
+ ใดก็ได้แล้วใช้กับทุกโปรเจกต์ ส่วน macOS Screen Recording/Accessibility ยังต้องกดให้
348
+ สิทธิ์ใน System Settings จริง:
349
+
350
+ ```bash
351
+ dodo desktop allow --app com.google.Chrome --mode control --persist --yes
352
+ ```
353
+
354
+ ## ความปลอดภัย
355
+
356
+ - public MCP ใช้ OAuth เสมอ ไม่มี NoAuth fallback
357
+ - Local Config bind loopback และมี capability token, expiration, Host/Origin checks และ rate limit
358
+ - client secret/access token ไม่แสดงใน UI หรือ audit
359
+ - path traversal, symlink/hardlink, secret paths และ stale hashes ถูกปฏิเสธ
360
+ - command environment ใช้ allowlist และไม่ส่ง local auth state ให้ child process
361
+ - repository instructions, `.dodo.json`, project hints และ AGENTS.md ไม่มีอำนาจเพิ่มสิทธิ์
362
+ - gateway ไม่ grant สิทธิ์และไม่ข้าม approval หรือ target operation policy
363
+ - CAS URI/hash ไม่ grant สิทธิ์; resource ทุก read/range/preview ตรวจ live target authority และ object hash ซ้ำ
364
+
365
+ ดูรายละเอียดที่ [SECURITY](docs/SECURITY.md), [AUTH](docs/AUTH.md) และ [ARCHITECTURE](docs/ARCHITECTURE.md)
366
+
367
+ ## เอกสาร
368
+
369
+ - [Release 1.0.0](docs/RELEASE_1.0.0.md)
370
+ - [Runtime Intelligence](docs/RUNTIME.md)
371
+ - [Advanced Agent Runtime](docs/AGENT_RUNTIME.md)
372
+ - [Release notes](docs/RELEASE_NOTES.md)
373
+ - [Architecture](docs/ARCHITECTURE.md)
374
+ - [Compatibility](docs/COMPATIBILITY.md)
375
+ - [Security](docs/SECURITY.md)
376
+ - [Authentication](docs/AUTH.md)
377
+ - [Tunnel](docs/TUNNEL.md)
378
+ - [Web clients](docs/WEB_CLIENTS.md)
379
+ - [Windows compatibility](docs/WINDOWS.md)
380
+ - [Task assistance](docs/ASSISTANCE.md)
381
+ - [Multimodal](docs/MULTIMODAL.md)
382
+ - [Project Registry](docs/PROJECTS.md)
383
+ - [Universal resources and CAS](docs/RESOURCES.md)
384
+ - [Project Brain and incremental index](docs/BRAIN.md)
385
+ - [DodoBench and release gate](docs/EVALUATION.md)
386
+ - [Manual acceptance](docs/MANUAL_ACCEPTANCE.md)
387
+ - [Test report](docs/TEST_REPORT.md)
388
+
389
+ ## Development
390
+
391
+ Platform CI ใช้ dedicated self-hosted runners ที่เจ้าของควบคุม: Linux X64 รันผ่าน
392
+ Docker พร้อม Playwright Chromium และ Windows X64 รัน native candidate gate ส่วน
393
+ macOS ยังรัน release gate บนเครื่องพัฒนา Workflow รับเฉพาะ push ที่ `main` และ manual
394
+ dispatch ไม่รัน pull request จากภายนอกบน self-hosted runner
395
+
396
+ รัน regression benchmark, macOS candidate gate และ Linux Docker gate ได้ด้วย:
397
+
398
+ ```bash
399
+ npm run bench
400
+ npm run release:gate
401
+ npm run test:linux:docker
402
+ ```
403
+
404
+ GitHub workflow รัน Node 22 และ 24 ทั้ง Linux/Windows โดยไม่ publish npm Windows จะ
405
+ ยังไม่ถูกประกาศเป็น supported platform จนกว่า automated native gate และ manual
406
+ Windows 11 acceptance จะผ่านตามเอกสาร
407
+
408
+ Release gate สร้างหลักฐาน non-secret ใน ignored `release-evidence/` และตรวจ fresh
409
+ exact-tarball ผ่าน STDIO Full กับ HTTP/OAuth Compact โดยไม่ publish npm ดูรายละเอียดที่
410
+ [DodoBench และ Release Gate](docs/EVALUATION.md)
411
+
412
+ เมื่อทั้งสอง report มาจาก Git revision และ `package-lock.json` เดียวกัน ให้รวมหลักฐาน
413
+ บน macOS ด้วย `node scripts/release-gate.mjs --release --platform-evidence /absolute/path/to/linux/gate-report.json`
414
+ คำสั่งนี้ไม่ publish package
415
+
416
+ ```bash
417
+ npm ci
418
+ npm run build
419
+ npm run typecheck
420
+ npm run lint
421
+ npm run test:all
422
+ npm pack
423
+ ```
424
+
425
+ โปรเจกต์นี้ใช้ GitHub repository [arthittakun/dodo-mcp](https://github.com/arthittakun/dodo-mcp) และ package `dodo-mcp`
@@ -0,0 +1,43 @@
1
+ /**
2
+ * oidc-provider persistence adapter backed by SQLite (spec §5, §8).
3
+ * The provider's own serializers are used untouched — DODO never invents its
4
+ * own OAuth token formats. Model `Client` resolves against the static
5
+ * registrations table so `dodo auth add-client` entries are live without a
6
+ * provider restart.
7
+ */
8
+ export function createAdapterFactory(store) {
9
+ return (name) => new SqliteOidcAdapter(store, name);
10
+ }
11
+ class SqliteOidcAdapter {
12
+ store;
13
+ name;
14
+ constructor(store, name) {
15
+ this.store = store;
16
+ this.name = name;
17
+ }
18
+ async upsert(id, payload, expiresIn) {
19
+ this.store.oauthUpsert(this.name, id, payload, expiresIn);
20
+ }
21
+ async find(id) {
22
+ if (this.name === 'Client') {
23
+ return this.store.getOAuthClient(id);
24
+ }
25
+ return this.store.oauthFind(this.name, id);
26
+ }
27
+ async findByUserCode(userCode) {
28
+ return this.store.oauthFindByUserCode(this.name, userCode);
29
+ }
30
+ async findByUid(uid) {
31
+ return this.store.oauthFindByUid(this.name, uid);
32
+ }
33
+ async consume(id) {
34
+ this.store.oauthConsume(this.name, id);
35
+ }
36
+ async destroy(id) {
37
+ this.store.oauthDestroy(this.name, id);
38
+ }
39
+ async revokeByGrantId(grantId) {
40
+ this.store.oauthRevokeByGrantId(grantId);
41
+ }
42
+ }
43
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/auth/adapter.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAY;IAC/C,OAAO,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,iBAAiB;IAEF;IACA;IAFnB,YACmB,KAAY,EACZ,IAAY;QADZ,UAAK,GAAL,KAAK,CAAO;QACZ,SAAI,GAAJ,IAAI,CAAQ;IAC5B,CAAC;IAEJ,KAAK,CAAC,MAAM,CAAC,EAAU,EAAE,OAAuB,EAAE,SAAkB;QAClE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,OAAkC,EAAE,SAAS,CAAC,CAAC;IACvF,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAU;QACnB,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAA+B,CAAC;QACrE,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAA+B,CAAC;IAC3E,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,QAAgB;QACnC,OAAO,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAA+B,CAAC;IAC3F,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,GAAW;QACzB,OAAO,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAA+B,CAAC;IACjF,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,EAAU;QACtB,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,EAAU;QACtB,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,OAAe;QACnC,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;CACF"}
@@ -0,0 +1,45 @@
1
+ import { z } from 'zod';
2
+ import { DodoError } from '../errors.js';
3
+ import { digestOf } from '../util/hash.js';
4
+ export const DeleteClientsInput = z.object({
5
+ clients: z.array(z.object({ id: z.string().min(1).max(128), reviewHash: z.string().regex(/^sha256:[a-f0-9]{64}$/) }).strict()).min(1).max(100),
6
+ confirm: z.literal('delete-selected-clients'),
7
+ }).strict();
8
+ /** Owner-only review: counts and opaque fingerprint, never credentials or paths. */
9
+ export function reviewClientDeletion(store, id) {
10
+ const client = store.getOAuthClient(id);
11
+ if (!client)
12
+ throw new DodoError('NOT_FOUND', 'Client no longer exists; reload the list');
13
+ const access = store.db.prepare('SELECT workspace_id, scopes FROM workspace_clients WHERE client_id=? ORDER BY workspace_id').all(id);
14
+ const grants = store.db.prepare('SELECT id,revoked_at FROM grants WHERE client_id=? ORDER BY id').all(id);
15
+ return {
16
+ id,
17
+ name: typeof client['client_name'] === 'string' ? client['client_name'] : null,
18
+ workspaceCount: access.filter(a => store.clientAccess(a.workspace_id, id).length > 0).length,
19
+ grantCount: grants.filter(g => g.revoked_at === null).length,
20
+ reviewHash: digestOf({ id, client, access, grants }),
21
+ };
22
+ }
23
+ /** One durable transaction for the reviewed selection; no wildcard/global reset. */
24
+ export function deleteReviewedClients(store, input, workspaceId) {
25
+ const ids = input.clients.map(c => c.id);
26
+ if (new Set(ids).size !== ids.length)
27
+ throw new DodoError('INVALID_INPUT', 'Select each client only once');
28
+ return store.db.transaction(() => {
29
+ // Revalidate all before touching any row. A new client is never swept in.
30
+ for (const c of input.clients) {
31
+ if (reviewClientDeletion(store, c.id).reviewHash !== c.reviewHash)
32
+ throw new DodoError('CONFLICT', 'Client access changed since review; reload and select again');
33
+ }
34
+ for (const id of ids) {
35
+ store.db.prepare("UPDATE pending_approvals SET status='denied' WHERE status IN ('pending','approved') AND (principal IN (SELECT id FROM grants WHERE client_id=?) OR (kind='oauth' AND CASE WHEN json_valid(summary) THEN json_extract(summary,'$.clientId') END=?))").run(id, id);
36
+ store.db.prepare('UPDATE grants SET revoked_at=COALESCE(revoked_at,?) WHERE client_id=?').run(Date.now(), id);
37
+ store.db.prepare("DELETE FROM oauth_models WHERE grant_id IN (SELECT id FROM grants WHERE client_id=?) OR (model='Grant' AND id IN (SELECT id FROM grants WHERE client_id=?)) OR CASE WHEN json_valid(payload) THEN json_extract(payload,'$.clientId') END=? OR CASE WHEN json_valid(payload) THEN json_extract(payload,'$.params.client_id') END=?").run(id, id, id, id);
38
+ store.db.prepare('DELETE FROM workspace_clients WHERE client_id=?').run(id);
39
+ store.db.prepare('DELETE FROM oauth_clients WHERE client_id=?').run(id);
40
+ store.audit({ principal: 'local-config-owner', workspaceId, tool: 'local.client.delete', refId: id, result: 'deleted' });
41
+ }
42
+ return { ok: true, deleted: ids };
43
+ }).immediate();
44
+ }
45
+ //# sourceMappingURL=clientDeletion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clientDeletion.js","sourceRoot":"","sources":["../../src/auth/clientDeletion.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { DodoError } from '../errors.js';
3
+ export function addStaticClient(store, opts) {
4
+ if (opts.redirectUris.length === 0)
5
+ throw new DodoError('INVALID_INPUT', 'at least one --redirect-uri is required');
6
+ for (const uri of opts.redirectUris) {
7
+ let parsed;
8
+ try {
9
+ parsed = new URL(uri);
10
+ }
11
+ catch {
12
+ throw new DodoError('INVALID_INPUT', `redirect URI is not a valid URL: ${uri}`);
13
+ }
14
+ if (parsed.protocol !== 'https:' && parsed.hostname !== 'localhost' && parsed.hostname !== '127.0.0.1') {
15
+ throw new DodoError('INVALID_INPUT', 'redirect URIs must be https (or loopback for local testing)');
16
+ }
17
+ if (uri.includes('*'))
18
+ throw new DodoError('INVALID_INPUT', 'wildcard redirect URIs are not allowed');
19
+ if (parsed.hash !== '')
20
+ throw new DodoError('INVALID_INPUT', 'redirect URIs must not contain a fragment');
21
+ }
22
+ const clientId = `dodo-client-${randomBytes(6).toString('hex')}`;
23
+ const isPublic = opts.public === true;
24
+ const clientSecret = isPublic ? undefined : randomBytes(32).toString('base64url');
25
+ const payload = {
26
+ client_id: clientId,
27
+ client_name: opts.name ?? 'dodo remote client',
28
+ redirect_uris: opts.redirectUris,
29
+ grant_types: ['authorization_code', 'refresh_token'],
30
+ response_types: ['code'],
31
+ token_endpoint_auth_method: isPublic ? 'none' : 'client_secret_basic',
32
+ application_type: 'web',
33
+ };
34
+ if (clientSecret)
35
+ payload['client_secret'] = clientSecret;
36
+ store.putOAuthClient(clientId, payload);
37
+ const info = {
38
+ clientId,
39
+ redirectUris: opts.redirectUris,
40
+ name: payload['client_name'] ?? 'dodo remote client',
41
+ tokenEndpointAuthMethod: payload['token_endpoint_auth_method'],
42
+ };
43
+ if (clientSecret !== undefined)
44
+ info.clientSecret = clientSecret;
45
+ return info;
46
+ }
47
+ export function listStaticClients(store) {
48
+ return store.listOAuthClients().map((c) => ({
49
+ clientId: c.clientId,
50
+ name: c.payload['client_name'] ?? '',
51
+ redirectUris: c.payload['redirect_uris'] ?? [],
52
+ createdAt: c.createdAt,
53
+ }));
54
+ }
55
+ //# sourceMappingURL=clients.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clients.js","sourceRoot":"","sources":["../../src/auth/clients.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /** The single local owner account id (single-owner mode, spec §8.4). */
2
+ export const OWNER_ACCOUNT_ID = 'owner';
3
+ /**
4
+ * OAuth login identifies one DODO installation. Project access is a separate
5
+ * owner-managed ACL, so consent must never be bound to whichever project is
6
+ * selected while the browser flow happens.
7
+ */
8
+ export const INSTALLATION_AUTHORITY_ID = 'dodo-installation';
9
+ export const INSTALLATION_AUTHORITY_EPOCH = 'installation-auth-v2';
10
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/auth/constants.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC;AAExC;;;;GAIG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,mBAAmB,CAAC;AAC7D,MAAM,CAAC,MAAM,4BAA4B,GAAG,sBAAsB,CAAC"}