rird 2.1.231 → 2.3.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 (381) hide show
  1. package/AGENTS.md +86 -0
  2. package/COMPLETED_TEST_SUITE.txt +280 -0
  3. package/Dockerfile +18 -0
  4. package/README.md +397 -6
  5. package/RIRD_ERROR_HANDLING_SUMMARY.md +307 -0
  6. package/TESTING.md +512 -0
  7. package/TEST_IMPLEMENTATION_REPORT.md +463 -0
  8. package/TEST_SUITE.md +307 -0
  9. package/TEST_SUMMARY.txt +380 -0
  10. package/bin/rird-perf.js +37 -0
  11. package/bin/rird.js +43 -8
  12. package/bunfig.toml +4 -0
  13. package/create-wrapper.ps1 +51 -0
  14. package/docs/ARCHITECTURE.md +768 -0
  15. package/docs/CLI_REFERENCE.md +681 -0
  16. package/docs/DOCUMENTATION_MANIFEST.md +392 -0
  17. package/docs/INDEX.md +295 -0
  18. package/docs/PRODUCTION_SETUP.md +633 -0
  19. package/docs/TROUBLESHOOTING.md +914 -0
  20. package/facebook_ads_library.png +0 -0
  21. package/nul +0 -0
  22. package/nul`nif +0 -0
  23. package/package.json +104 -15
  24. package/parsers-config.ts +239 -0
  25. package/rird-1.0.199.tgz +0 -0
  26. package/rird-1.0.205.tgz +0 -0
  27. package/script/build-windows.ts +56 -0
  28. package/script/build.ts +165 -0
  29. package/{postinstall.mjs → script/postinstall.mjs} +47 -68
  30. package/script/publish-registries.ts +187 -0
  31. package/script/publish.ts +85 -0
  32. package/script/schema.ts +47 -0
  33. package/src/acp/README.md +164 -0
  34. package/src/acp/agent.ts +1063 -0
  35. package/src/acp/session.ts +101 -0
  36. package/src/acp/types.ts +22 -0
  37. package/src/agent/agent.ts +367 -0
  38. package/src/agent/generate.txt +75 -0
  39. package/src/agent/prompt/compaction.txt +12 -0
  40. package/src/agent/prompt/explore.txt +18 -0
  41. package/src/agent/prompt/summary.txt +10 -0
  42. package/src/agent/prompt/title.txt +36 -0
  43. package/src/auth/index.ts +70 -0
  44. package/src/bun/index.ts +114 -0
  45. package/src/bus/bus-event.ts +43 -0
  46. package/src/bus/global.ts +10 -0
  47. package/src/bus/index.ts +105 -0
  48. package/src/cli/bootstrap.ts +17 -0
  49. package/src/cli/cmd/acp.ts +104 -0
  50. package/src/cli/cmd/activate.ts +50 -0
  51. package/src/cli/cmd/agent.ts +256 -0
  52. package/src/cli/cmd/auth.ts +412 -0
  53. package/src/cli/cmd/cmd.ts +7 -0
  54. package/src/cli/cmd/debug/config.ts +15 -0
  55. package/src/cli/cmd/debug/file.ts +91 -0
  56. package/src/cli/cmd/debug/index.ts +43 -0
  57. package/src/cli/cmd/debug/lsp.ts +48 -0
  58. package/src/cli/cmd/debug/ripgrep.ts +83 -0
  59. package/src/cli/cmd/debug/scrap.ts +15 -0
  60. package/src/cli/cmd/debug/skill.ts +15 -0
  61. package/src/cli/cmd/debug/snapshot.ts +48 -0
  62. package/src/cli/cmd/export.ts +88 -0
  63. package/src/cli/cmd/generate.ts +38 -0
  64. package/src/cli/cmd/github.ts +1400 -0
  65. package/src/cli/cmd/import.ts +98 -0
  66. package/src/cli/cmd/mcp.ts +654 -0
  67. package/src/cli/cmd/models.ts +68 -0
  68. package/src/cli/cmd/pr.ts +112 -0
  69. package/src/cli/cmd/run.ts +434 -0
  70. package/src/cli/cmd/serve.ts +31 -0
  71. package/src/cli/cmd/session.ts +106 -0
  72. package/src/cli/cmd/stats.ts +298 -0
  73. package/src/cli/cmd/tui/app.tsx +694 -0
  74. package/src/cli/cmd/tui/attach.ts +30 -0
  75. package/src/cli/cmd/tui/component/border.tsx +21 -0
  76. package/src/cli/cmd/tui/component/dialog-agent.tsx +31 -0
  77. package/src/cli/cmd/tui/component/dialog-command.tsx +124 -0
  78. package/src/cli/cmd/tui/component/dialog-mcp.tsx +86 -0
  79. package/src/cli/cmd/tui/component/dialog-model.tsx +236 -0
  80. package/src/cli/cmd/tui/component/dialog-provider.tsx +240 -0
  81. package/src/cli/cmd/tui/component/dialog-session-list.tsx +102 -0
  82. package/src/cli/cmd/tui/component/dialog-session-rename.tsx +31 -0
  83. package/src/cli/cmd/tui/component/dialog-stash.tsx +86 -0
  84. package/src/cli/cmd/tui/component/dialog-status.tsx +162 -0
  85. package/src/cli/cmd/tui/component/dialog-tag.tsx +44 -0
  86. package/src/cli/cmd/tui/component/dialog-theme-list.tsx +50 -0
  87. package/src/cli/cmd/tui/component/did-you-know.tsx +85 -0
  88. package/src/cli/cmd/tui/component/logo.tsx +48 -0
  89. package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +574 -0
  90. package/src/cli/cmd/tui/component/prompt/history.tsx +108 -0
  91. package/src/cli/cmd/tui/component/prompt/index.tsx +1087 -0
  92. package/src/cli/cmd/tui/component/prompt/stash.tsx +101 -0
  93. package/src/cli/cmd/tui/component/tips.ts +27 -0
  94. package/src/cli/cmd/tui/component/todo-item.tsx +32 -0
  95. package/src/cli/cmd/tui/context/args.tsx +14 -0
  96. package/src/cli/cmd/tui/context/directory.ts +13 -0
  97. package/src/cli/cmd/tui/context/exit.tsx +23 -0
  98. package/src/cli/cmd/tui/context/helper.tsx +25 -0
  99. package/src/cli/cmd/tui/context/keybind.tsx +101 -0
  100. package/src/cli/cmd/tui/context/kv.tsx +49 -0
  101. package/src/cli/cmd/tui/context/local.tsx +345 -0
  102. package/src/cli/cmd/tui/context/prompt.tsx +18 -0
  103. package/src/cli/cmd/tui/context/route.tsx +46 -0
  104. package/src/cli/cmd/tui/context/sdk.tsx +74 -0
  105. package/src/cli/cmd/tui/context/sync.tsx +372 -0
  106. package/src/cli/cmd/tui/context/theme/aura.json +69 -0
  107. package/src/cli/cmd/tui/context/theme/ayu.json +80 -0
  108. package/src/cli/cmd/tui/context/theme/catppuccin-frappe.json +233 -0
  109. package/src/cli/cmd/tui/context/theme/catppuccin-macchiato.json +233 -0
  110. package/src/cli/cmd/tui/context/theme/catppuccin.json +112 -0
  111. package/src/cli/cmd/tui/context/theme/cobalt2.json +228 -0
  112. package/src/cli/cmd/tui/context/theme/cursor.json +249 -0
  113. package/src/cli/cmd/tui/context/theme/dracula.json +219 -0
  114. package/src/cli/cmd/tui/context/theme/everforest.json +241 -0
  115. package/src/cli/cmd/tui/context/theme/flexoki.json +237 -0
  116. package/src/cli/cmd/tui/context/theme/github.json +233 -0
  117. package/src/cli/cmd/tui/context/theme/gruvbox.json +95 -0
  118. package/src/cli/cmd/tui/context/theme/kanagawa.json +77 -0
  119. package/src/cli/cmd/tui/context/theme/lucent-orng.json +227 -0
  120. package/src/cli/cmd/tui/context/theme/material.json +235 -0
  121. package/src/cli/cmd/tui/context/theme/matrix.json +77 -0
  122. package/src/cli/cmd/tui/context/theme/mercury.json +252 -0
  123. package/src/cli/cmd/tui/context/theme/monokai.json +221 -0
  124. package/src/cli/cmd/tui/context/theme/nightowl.json +221 -0
  125. package/src/cli/cmd/tui/context/theme/nord.json +223 -0
  126. package/src/cli/cmd/tui/context/theme/one-dark.json +84 -0
  127. package/src/cli/cmd/tui/context/theme/orng.json +245 -0
  128. package/src/cli/cmd/tui/context/theme/palenight.json +222 -0
  129. package/src/cli/cmd/tui/context/theme/rird.json +245 -0
  130. package/src/cli/cmd/tui/context/theme/rosepine.json +234 -0
  131. package/src/cli/cmd/tui/context/theme/solarized.json +223 -0
  132. package/src/cli/cmd/tui/context/theme/synthwave84.json +226 -0
  133. package/src/cli/cmd/tui/context/theme/tokyonight.json +243 -0
  134. package/src/cli/cmd/tui/context/theme/vercel.json +245 -0
  135. package/src/cli/cmd/tui/context/theme/vesper.json +218 -0
  136. package/src/cli/cmd/tui/context/theme/zenburn.json +223 -0
  137. package/src/cli/cmd/tui/context/theme.tsx +1109 -0
  138. package/src/cli/cmd/tui/event.ts +40 -0
  139. package/src/cli/cmd/tui/hooks/use-safe-terminal-dimensions.ts +12 -0
  140. package/src/cli/cmd/tui/routes/home.tsx +138 -0
  141. package/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +64 -0
  142. package/src/cli/cmd/tui/routes/session/dialog-message.tsx +109 -0
  143. package/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +26 -0
  144. package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +47 -0
  145. package/src/cli/cmd/tui/routes/session/footer.tsx +88 -0
  146. package/src/cli/cmd/tui/routes/session/header.tsx +125 -0
  147. package/src/cli/cmd/tui/routes/session/index.tsx +1876 -0
  148. package/src/cli/cmd/tui/routes/session/sidebar.tsx +320 -0
  149. package/src/cli/cmd/tui/spawn.ts +60 -0
  150. package/src/cli/cmd/tui/thread.ts +142 -0
  151. package/src/cli/cmd/tui/ui/dialog-alert.tsx +57 -0
  152. package/src/cli/cmd/tui/ui/dialog-confirm.tsx +83 -0
  153. package/src/cli/cmd/tui/ui/dialog-help.tsx +38 -0
  154. package/src/cli/cmd/tui/ui/dialog-prompt.tsx +77 -0
  155. package/src/cli/cmd/tui/ui/dialog-select.tsx +333 -0
  156. package/src/cli/cmd/tui/ui/dialog.tsx +171 -0
  157. package/src/cli/cmd/tui/ui/spinner.ts +368 -0
  158. package/src/cli/cmd/tui/ui/toast.tsx +100 -0
  159. package/src/cli/cmd/tui/util/clipboard.ts +127 -0
  160. package/src/cli/cmd/tui/util/editor.ts +32 -0
  161. package/src/cli/cmd/tui/util/terminal.ts +146 -0
  162. package/src/cli/cmd/tui/worker.ts +63 -0
  163. package/src/cli/cmd/uninstall.ts +344 -0
  164. package/src/cli/cmd/upgrade.ts +127 -0
  165. package/src/cli/cmd/web.ts +84 -0
  166. package/src/cli/error.ts +69 -0
  167. package/src/cli/ui.ts +101 -0
  168. package/src/cli/upgrade.ts +28 -0
  169. package/src/command/index.ts +80 -0
  170. package/src/command/template/initialize.txt +10 -0
  171. package/src/command/template/review.txt +97 -0
  172. package/src/config/config.ts +994 -0
  173. package/src/config/markdown.ts +41 -0
  174. package/src/env/index.ts +26 -0
  175. package/src/file/ignore.ts +83 -0
  176. package/src/file/index.ts +328 -0
  177. package/src/file/ripgrep.ts +393 -0
  178. package/src/file/time.ts +64 -0
  179. package/src/file/watcher.ts +103 -0
  180. package/src/flag/flag.ts +84 -0
  181. package/src/format/formatter.ts +315 -0
  182. package/src/format/index.ts +137 -0
  183. package/src/global/index.ts +101 -0
  184. package/src/id/id.ts +73 -0
  185. package/src/ide/index.ts +76 -0
  186. package/src/index.ts +297 -0
  187. package/src/index.ts.backup +271 -0
  188. package/src/installation/index.ts +258 -0
  189. package/src/lib/IMPLEMENTATION_NOTES.md +345 -0
  190. package/src/lib/error-handler.ts +225 -0
  191. package/src/lib/error-testing-guide.md +258 -0
  192. package/src/lib/errors.ts +285 -0
  193. package/src/lib/performance.ts +70 -0
  194. package/src/lib/telemetry.ts +282 -0
  195. package/src/lsp/client.ts +229 -0
  196. package/src/lsp/index.ts +485 -0
  197. package/src/lsp/language.ts +116 -0
  198. package/src/lsp/server.ts +1895 -0
  199. package/src/mcp/auth.ts +135 -0
  200. package/src/mcp/index.ts +1117 -0
  201. package/src/mcp/intent-analyzer.ts +376 -0
  202. package/src/mcp/oauth-callback.ts +200 -0
  203. package/src/mcp/oauth-provider.ts +154 -0
  204. package/src/patch/index.ts +632 -0
  205. package/src/permission/index.ts +199 -0
  206. package/src/plugin/index.ts +91 -0
  207. package/src/project/bootstrap.ts +33 -0
  208. package/src/project/instance.ts +78 -0
  209. package/src/project/project.ts +236 -0
  210. package/src/project/state.ts +65 -0
  211. package/src/project/vcs.ts +76 -0
  212. package/src/provider/auth.ts +143 -0
  213. package/src/provider/models-macro.ts +55 -0
  214. package/src/provider/models.ts +161 -0
  215. package/src/provider/provider.ts +1109 -0
  216. package/src/provider/sdk/openai-compatible/src/README.md +5 -0
  217. package/src/provider/sdk/openai-compatible/src/index.ts +2 -0
  218. package/src/provider/sdk/openai-compatible/src/openai-compatible-provider.ts +100 -0
  219. package/src/provider/sdk/openai-compatible/src/responses/convert-to-openai-responses-input.ts +303 -0
  220. package/src/provider/sdk/openai-compatible/src/responses/map-openai-responses-finish-reason.ts +22 -0
  221. package/src/provider/sdk/openai-compatible/src/responses/openai-config.ts +18 -0
  222. package/src/provider/sdk/openai-compatible/src/responses/openai-error.ts +22 -0
  223. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-api-types.ts +207 -0
  224. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-language-model.ts +1713 -0
  225. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-prepare-tools.ts +177 -0
  226. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-settings.ts +1 -0
  227. package/src/provider/sdk/openai-compatible/src/responses/tool/code-interpreter.ts +88 -0
  228. package/src/provider/sdk/openai-compatible/src/responses/tool/file-search.ts +128 -0
  229. package/src/provider/sdk/openai-compatible/src/responses/tool/image-generation.ts +115 -0
  230. package/src/provider/sdk/openai-compatible/src/responses/tool/local-shell.ts +65 -0
  231. package/src/provider/sdk/openai-compatible/src/responses/tool/web-search-preview.ts +104 -0
  232. package/src/provider/sdk/openai-compatible/src/responses/tool/web-search.ts +103 -0
  233. package/src/provider/transform.ts +455 -0
  234. package/src/pty/index.ts +231 -0
  235. package/src/security/guardrails.test.ts +341 -0
  236. package/src/security/guardrails.ts +570 -0
  237. package/src/security/index.ts +19 -0
  238. package/src/server/error.ts +36 -0
  239. package/src/server/project.ts +79 -0
  240. package/src/server/server.ts +2641 -0
  241. package/src/server/tui.ts +71 -0
  242. package/src/session/compaction.ts +228 -0
  243. package/src/session/index.ts +464 -0
  244. package/src/session/llm.ts +201 -0
  245. package/src/session/message-v2.ts +695 -0
  246. package/src/session/message.ts +189 -0
  247. package/src/session/processor.ts +409 -0
  248. package/src/session/prompt/act-switch.txt +5 -0
  249. package/src/session/prompt/anthropic-20250930.txt +166 -0
  250. package/src/session/prompt/anthropic.txt +63 -0
  251. package/src/session/prompt/anthropic_spoof.txt +1 -0
  252. package/src/session/prompt/beast.txt +76 -0
  253. package/src/session/prompt/codex.txt +304 -0
  254. package/src/session/prompt/copilot-gpt-5.txt +137 -0
  255. package/src/session/prompt/gemini.txt +62 -0
  256. package/src/session/prompt/max-steps.txt +16 -0
  257. package/src/session/prompt/plan-reminder-anthropic.txt +35 -0
  258. package/src/session/prompt/plan.txt +24 -0
  259. package/src/session/prompt/polaris.txt +88 -0
  260. package/src/session/prompt/qwen.txt +59 -0
  261. package/src/session/prompt.ts +1552 -0
  262. package/src/session/retry.ts +86 -0
  263. package/src/session/revert.ts +108 -0
  264. package/src/session/sensitive-filter.test.ts +327 -0
  265. package/src/session/sensitive-filter.ts +466 -0
  266. package/src/session/status.ts +76 -0
  267. package/src/session/summary.ts +209 -0
  268. package/src/session/system.ts +122 -0
  269. package/src/session/todo.ts +37 -0
  270. package/src/share/share-next.ts +222 -0
  271. package/src/share/share.ts +87 -0
  272. package/src/shell/shell.ts +67 -0
  273. package/src/skill/index.ts +1 -0
  274. package/src/skill/skill.ts +83 -0
  275. package/src/snapshot/index.ts +197 -0
  276. package/src/storage/storage.ts +226 -0
  277. package/src/tests/agent.test.ts +308 -0
  278. package/src/tests/build-guards.test.ts +267 -0
  279. package/src/tests/config.test.ts +664 -0
  280. package/src/tests/tool-registry.test.ts +589 -0
  281. package/src/tool/bash.ts +314 -0
  282. package/src/tool/bash.txt +158 -0
  283. package/src/tool/batch.ts +175 -0
  284. package/src/tool/batch.txt +24 -0
  285. package/src/tool/codesearch.ts +184 -0
  286. package/src/tool/codesearch.txt +12 -0
  287. package/src/tool/edit.ts +675 -0
  288. package/src/tool/edit.txt +10 -0
  289. package/src/tool/glob.ts +65 -0
  290. package/src/tool/glob.txt +6 -0
  291. package/src/tool/grep.ts +121 -0
  292. package/src/tool/grep.txt +8 -0
  293. package/src/tool/invalid.ts +17 -0
  294. package/src/tool/ls.ts +110 -0
  295. package/src/tool/ls.txt +1 -0
  296. package/src/tool/lsp-diagnostics.ts +26 -0
  297. package/src/tool/lsp-diagnostics.txt +1 -0
  298. package/src/tool/lsp-hover.ts +31 -0
  299. package/src/tool/lsp-hover.txt +1 -0
  300. package/src/tool/lsp.ts +87 -0
  301. package/src/tool/lsp.txt +19 -0
  302. package/src/tool/multiedit.ts +46 -0
  303. package/src/tool/multiedit.txt +41 -0
  304. package/src/tool/patch.ts +233 -0
  305. package/src/tool/patch.txt +1 -0
  306. package/src/tool/read.ts +219 -0
  307. package/src/tool/read.txt +12 -0
  308. package/src/tool/registry.ts +162 -0
  309. package/src/tool/skill.ts +100 -0
  310. package/src/tool/task.ts +136 -0
  311. package/src/tool/task.txt +51 -0
  312. package/src/tool/todo.ts +39 -0
  313. package/src/tool/todoread.txt +14 -0
  314. package/src/tool/todowrite.txt +167 -0
  315. package/src/tool/tool.ts +71 -0
  316. package/src/tool/webfetch.ts +198 -0
  317. package/src/tool/webfetch.txt +13 -0
  318. package/src/tool/websearch.ts +268 -0
  319. package/src/tool/websearch.txt +13 -0
  320. package/src/tool/write.ts +110 -0
  321. package/src/tool/write.txt +8 -0
  322. package/src/util/archive.ts +16 -0
  323. package/src/util/color.ts +19 -0
  324. package/src/util/context.ts +25 -0
  325. package/src/util/defer.ts +12 -0
  326. package/src/util/eventloop.ts +20 -0
  327. package/src/util/filesystem.ts +83 -0
  328. package/src/util/fn.ts +11 -0
  329. package/src/util/iife.ts +3 -0
  330. package/src/util/keybind.ts +102 -0
  331. package/src/util/lazy.ts +11 -0
  332. package/src/util/license.ts +362 -0
  333. package/src/util/locale.ts +81 -0
  334. package/src/util/lock.ts +98 -0
  335. package/src/util/log.ts +180 -0
  336. package/src/util/queue.ts +32 -0
  337. package/src/util/rpc.ts +42 -0
  338. package/src/util/scrap.ts +10 -0
  339. package/src/util/signal.ts +12 -0
  340. package/src/util/timeout.ts +14 -0
  341. package/src/util/token.ts +7 -0
  342. package/src/util/wildcard.ts +54 -0
  343. package/sst-env.d.ts +9 -0
  344. package/test/agent/agent.test.ts +146 -0
  345. package/test/bun.test.ts +53 -0
  346. package/test/cli/cmd/acp.test.ts +144 -0
  347. package/test/cli/cmd/run.test.ts +250 -0
  348. package/test/cli/github-remote.test.ts +80 -0
  349. package/test/config/agent-color.test.ts +66 -0
  350. package/test/config/config.test.ts +536 -0
  351. package/test/config/markdown.test.ts +89 -0
  352. package/test/file/ignore.test.ts +10 -0
  353. package/test/fixture/fixture.ts +37 -0
  354. package/test/fixture/lsp/fake-lsp-server.js +77 -0
  355. package/test/helpers.ts +172 -0
  356. package/test/ide/ide.test.ts +82 -0
  357. package/test/installation/installation.test.ts +143 -0
  358. package/test/keybind.test.ts +421 -0
  359. package/test/lsp/client.test.ts +95 -0
  360. package/test/mcp/headers.test.ts +153 -0
  361. package/test/patch/patch.test.ts +348 -0
  362. package/test/preload.ts +57 -0
  363. package/test/project/project.test.ts +74 -0
  364. package/test/provider/provider.test.ts +74 -0
  365. package/test/provider/transform.test.ts +411 -0
  366. package/test/session/retry.test.ts +111 -0
  367. package/test/session/session.test.ts +71 -0
  368. package/test/skill/skill.test.ts +131 -0
  369. package/test/snapshot/snapshot.test.ts +940 -0
  370. package/test/tool/__snapshots__/tool.test.ts.snap +9 -0
  371. package/test/tool/bash.test.ts +434 -0
  372. package/test/tool/grep.test.ts +108 -0
  373. package/test/tool/patch.test.ts +259 -0
  374. package/test/tool/read.test.ts +42 -0
  375. package/test/util/iife.test.ts +36 -0
  376. package/test/util/lazy.test.ts +50 -0
  377. package/test/util/license.test.ts +235 -0
  378. package/test/util/timeout.test.ts +21 -0
  379. package/test/util/wildcard.test.ts +55 -0
  380. package/tsconfig.json +16 -0
  381. package/update-versions.ps1 +65 -0
@@ -0,0 +1,376 @@
1
+ /**
2
+ * Intent-to-Section Analyzer for automatic MCP tool loading
3
+ *
4
+ * Analyzes user prompts to determine which MCP tool sections should be loaded.
5
+ * This enables lazy loading of MCP tools based on task requirements.
6
+ */
7
+
8
+ /**
9
+ * Mapping of intent keywords to MCP sections that should be loaded.
10
+ * Each keyword maps to an array of section names.
11
+ */
12
+ const INTENT_SECTIONS: Record<string, string[]> = {
13
+ // Data extraction intents
14
+ scrape: ["element-extraction", "file-extraction"],
15
+ extract: ["element-extraction", "file-extraction"],
16
+ parse: ["element-extraction", "file-extraction"],
17
+ find: ["element-extraction"],
18
+ search: ["element-interaction", "element-extraction", "browser-management"],
19
+ collect: ["element-extraction", "element-interaction", "browser-management"],
20
+ output: ["element-extraction"],
21
+ download: ["file-extraction"],
22
+ save: ["file-extraction"],
23
+ export: ["file-extraction"],
24
+
25
+ // Form/interaction intents
26
+ form: ["element-interaction", "cookies-storage"],
27
+ fill: ["element-interaction"],
28
+ click: ["element-interaction"],
29
+ "type in": ["element-interaction"],
30
+ "type into": ["element-interaction"],
31
+ typing: ["element-interaction"],
32
+ input: ["element-interaction"],
33
+ submit: ["element-interaction"],
34
+ select: ["element-interaction"],
35
+ press: ["element-interaction"],
36
+ toggle: ["element-interaction"],
37
+ drag: ["element-interaction"],
38
+ drop: ["element-interaction"],
39
+ scroll: ["element-interaction"],
40
+ hover: ["element-interaction"],
41
+ interact: ["element-interaction"],
42
+
43
+ // Debugging intents
44
+ debug: ["debugging", "network-debugging"],
45
+ inspect: ["debugging", "network-debugging", "cdp-functions"],
46
+ analyze: ["debugging", "network-debugging"],
47
+ troubleshoot: ["debugging", "network-debugging"],
48
+ diagnose: ["debugging", "network-debugging"],
49
+
50
+ // Network intents
51
+ network: ["network-debugging", "dynamic-hooks"],
52
+ intercept: ["dynamic-hooks", "network-debugging"],
53
+ request: ["network-debugging", "dynamic-hooks"],
54
+ response: ["network-debugging", "dynamic-hooks"],
55
+ traffic: ["network-debugging", "dynamic-hooks"],
56
+ api: ["network-debugging", "dynamic-hooks"],
57
+ xhr: ["network-debugging", "dynamic-hooks"],
58
+ fetch: ["network-debugging", "dynamic-hooks"],
59
+ websocket: ["network-debugging", "dynamic-hooks"],
60
+
61
+ // CDP/JavaScript intents
62
+ cdp: ["cdp-functions"],
63
+ javascript: ["cdp-functions"],
64
+ js: ["cdp-functions"],
65
+ eval: ["cdp-functions"],
66
+ execute: ["cdp-functions"],
67
+ console: ["cdp-functions", "debugging"],
68
+ script: ["cdp-functions"],
69
+
70
+ // Tab management intents
71
+ tabs: ["tabs"],
72
+ tab: ["tabs"],
73
+ window: ["tabs"],
74
+ browser: ["browser-management", "tabs"],
75
+ spawn: ["browser-management"],
76
+ start: ["browser-management"],
77
+
78
+ // Persistence/Memory intents
79
+ memory: ["persistence"],
80
+ history: ["persistence"],
81
+ knowledge: ["persistence"],
82
+ checkpoint: ["persistence"],
83
+ recall: ["persistence"],
84
+ remember: ["persistence"],
85
+
86
+ // Cookie/storage intents
87
+ cookie: ["cookies-storage"],
88
+ cookies: ["cookies-storage"],
89
+ storage: ["cookies-storage"],
90
+ localstorage: ["cookies-storage"],
91
+ sessionstorage: ["cookies-storage"],
92
+ cache: ["cookies-storage"],
93
+
94
+ // Cloning intents
95
+ clone: ["progressive-cloning", "element-extraction"],
96
+ copy: ["progressive-cloning", "element-extraction"],
97
+ mirror: ["progressive-cloning", "element-extraction"],
98
+ replicate: ["progressive-cloning", "element-extraction"],
99
+
100
+ // File-specific intents
101
+ pdf: ["file-extraction"],
102
+ screenshot: ["element-interaction"],
103
+ image: ["element-extraction", "file-extraction"],
104
+ video: ["file-extraction"],
105
+ audio: ["file-extraction"],
106
+ document: ["file-extraction"],
107
+
108
+ // Authentication intents
109
+ login: ["element-interaction", "cookies-storage"],
110
+ "log in": ["element-interaction", "cookies-storage"],
111
+ "log into": ["element-interaction", "cookies-storage"],
112
+ "logged in": ["element-interaction", "cookies-storage"],
113
+ "logging in": ["element-interaction", "cookies-storage"],
114
+ signin: ["element-interaction", "cookies-storage"],
115
+ "sign in": ["element-interaction", "cookies-storage"],
116
+ "sign into": ["element-interaction", "cookies-storage"],
117
+ auth: ["element-interaction", "cookies-storage"],
118
+ authenticate: ["element-interaction", "cookies-storage"],
119
+ logout: ["element-interaction", "cookies-storage"],
120
+
121
+ // Table/data intents
122
+ table: ["element-extraction"],
123
+ list: ["element-extraction"],
124
+ data: ["element-extraction", "file-extraction"],
125
+ record: ["element-extraction"],
126
+ url: ["element-extraction"],
127
+ link: ["element-extraction"],
128
+ profile: ["element-extraction"],
129
+ lead: ["element-extraction", "element-interaction"],
130
+ prospect: ["element-extraction", "element-interaction"],
131
+ client: ["element-extraction", "element-interaction"],
132
+ advertiser: ["element-extraction", "element-interaction"],
133
+ ad: ["element-extraction", "element-interaction"],
134
+ listing: ["element-extraction", "element-interaction"],
135
+
136
+ // RIRD brand intents
137
+ rird: ["browser-management", "element-interaction", "element-extraction"],
138
+
139
+ // Site-specific intents
140
+ facebook: ["browser-management", "element-interaction", "element-extraction"],
141
+ fb: ["browser-management", "element-interaction", "element-extraction"],
142
+ instagram: ["browser-management", "element-interaction", "element-extraction"],
143
+ ig: ["browser-management", "element-interaction", "element-extraction"],
144
+ linkedin: ["browser-management", "element-interaction", "element-extraction"],
145
+ reddit: ["browser-management", "element-interaction", "element-extraction"],
146
+ twitter: ["browser-management", "element-interaction", "element-extraction"],
147
+ x: ["browser-management", "element-interaction", "element-extraction"],
148
+ maps: ["browser-management", "element-interaction", "element-extraction"],
149
+ google: ["browser-management", "element-interaction"],
150
+ amazon: ["browser-management", "element-interaction", "element-extraction"],
151
+ lib: ["browser-management", "element-interaction", "element-extraction"],
152
+ library: ["browser-management", "element-interaction", "element-extraction"],
153
+ thread: ["browser-management", "element-interaction", "element-extraction"],
154
+ post: ["browser-management", "element-interaction", "element-extraction"],
155
+ }
156
+
157
+ /**
158
+ * Keywords that indicate a simple navigation-only task (layer0 only).
159
+ * These patterns suggest no advanced MCP tools are needed.
160
+ */
161
+ const SIMPLE_TASK_PATTERNS: RegExp[] = [
162
+ /^(go\s+to|open|visit|navigate\s+to|load)\s+/i,
163
+ /^(show|display|view)\s+(me\s+)?(the\s+)?/i,
164
+ /^what('s|\s+is)\s+(on|at)\s+/i,
165
+ /^(take\s+me\s+to|bring\s+up)\s+/i,
166
+ ]
167
+
168
+ /**
169
+ * URLs or simple navigation patterns
170
+ */
171
+ const URL_PATTERN = /^https?:\/\/[^\s]+$/i
172
+ const DOMAIN_PATTERN = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$/i
173
+
174
+ /**
175
+ * The core/base section that is always loaded
176
+ */
177
+ export const LAYER0_SECTION = "layer0"
178
+
179
+ /**
180
+ * Result of intent analysis
181
+ */
182
+ export interface IntentAnalysisResult {
183
+ /** Sections to load (always includes layer0) */
184
+ sections: string[]
185
+ /** Keywords that were matched in the prompt */
186
+ matchedKeywords: string[]
187
+ /** Whether this is a simple task (layer0 only) */
188
+ isSimple: boolean
189
+ }
190
+
191
+ /**
192
+ * Analyzes a user prompt to determine which MCP sections should be loaded.
193
+ *
194
+ * @param prompt - The user's task description or prompt
195
+ * @returns List of section names to load (always includes layer0, deduplicated)
196
+ *
197
+ * @example
198
+ * analyzeIntent("scrape all product prices from the page")
199
+ * // Returns: ["layer0", "element-extraction", "file-extraction"]
200
+ *
201
+ * @example
202
+ * analyzeIntent("go to google.com")
203
+ * // Returns: ["layer0"]
204
+ */
205
+ export function analyzeIntent(prompt: string): string[] {
206
+ const result = analyzeIntentDetailed(prompt)
207
+ return result.sections
208
+ }
209
+
210
+ /**
211
+ * Detailed intent analysis with additional metadata.
212
+ *
213
+ * @param prompt - The user's task description or prompt
214
+ * @returns Detailed analysis result including matched keywords
215
+ */
216
+ export function analyzeIntentDetailed(prompt: string): IntentAnalysisResult {
217
+ // Check if it's a simple task first
218
+ if (isSimpleTask(prompt)) {
219
+ return {
220
+ sections: [LAYER0_SECTION],
221
+ matchedKeywords: [],
222
+ isSimple: true,
223
+ }
224
+ }
225
+
226
+ // Guard against null/undefined prompt
227
+ if (!prompt || typeof prompt !== "string") {
228
+ return {
229
+ sections: [LAYER0_SECTION],
230
+ matchedKeywords: [],
231
+ isSimple: true,
232
+ }
233
+ }
234
+
235
+ const normalizedPrompt = prompt.toLowerCase()
236
+ const sections = new Set<string>([LAYER0_SECTION])
237
+ const matchedKeywords: string[] = []
238
+
239
+ // Check each intent keyword
240
+ for (const [keyword, sectionList] of Object.entries(INTENT_SECTIONS)) {
241
+ // Use word boundary matching to avoid partial matches
242
+ const pattern = new RegExp(`\\b${escapeRegex(keyword)}\\b`, "i")
243
+ if (pattern.test(normalizedPrompt)) {
244
+ matchedKeywords.push(keyword)
245
+ for (const section of sectionList) {
246
+ sections.add(section)
247
+ }
248
+ }
249
+ }
250
+
251
+ return {
252
+ sections: Array.from(sections),
253
+ matchedKeywords,
254
+ isSimple: sections.size === 1,
255
+ }
256
+ }
257
+
258
+ /**
259
+ * Checks if a prompt describes a simple task that only needs layer0 (core) capabilities.
260
+ * Simple tasks are basic navigation operations like "go to google.com" or "open https://example.com".
261
+ *
262
+ * @param prompt - The user's task description or prompt
263
+ * @returns True if the task only needs layer0 capabilities
264
+ *
265
+ * @example
266
+ * isSimpleTask("go to google.com") // true
267
+ * isSimpleTask("open https://example.com") // true
268
+ * isSimpleTask("scrape all products from the page") // false
269
+ */
270
+ export function isSimpleTask(prompt: string): boolean {
271
+ const trimmedPrompt = prompt.trim()
272
+
273
+ // Check if it's just a URL
274
+ if (URL_PATTERN.test(trimmedPrompt) || DOMAIN_PATTERN.test(trimmedPrompt)) {
275
+ return true
276
+ }
277
+
278
+ // Check simple task patterns
279
+ for (const pattern of SIMPLE_TASK_PATTERNS) {
280
+ if (pattern.test(trimmedPrompt)) {
281
+ // Extract what comes after the pattern
282
+ const remainder = trimmedPrompt.replace(pattern, "").trim()
283
+
284
+ // If remainder is just a URL or domain, it's simple
285
+ if (URL_PATTERN.test(remainder) || DOMAIN_PATTERN.test(remainder)) {
286
+ return true
287
+ }
288
+
289
+ // If remainder is very short (likely just a site name), it's simple
290
+ if (remainder.length < 50 && !containsComplexIntent(remainder)) {
291
+ return true
292
+ }
293
+ }
294
+ }
295
+
296
+ return false
297
+ }
298
+
299
+ /**
300
+ * Gets all available section names from the intent mapping.
301
+ *
302
+ * @returns Array of unique section names
303
+ */
304
+ export function getAvailableSections(): string[] {
305
+ const sections = new Set<string>([LAYER0_SECTION])
306
+ for (const sectionList of Object.values(INTENT_SECTIONS)) {
307
+ for (const section of sectionList) {
308
+ sections.add(section)
309
+ }
310
+ }
311
+ return Array.from(sections).sort()
312
+ }
313
+
314
+ /**
315
+ * Gets all intent keywords that map to a specific section.
316
+ *
317
+ * @param section - The section name to look up
318
+ * @returns Array of keywords that trigger loading of this section
319
+ */
320
+ export function getKeywordsForSection(section: string): string[] {
321
+ const keywords: string[] = []
322
+ for (const [keyword, sectionList] of Object.entries(INTENT_SECTIONS)) {
323
+ if (sectionList.includes(section)) {
324
+ keywords.push(keyword)
325
+ }
326
+ }
327
+ return keywords.sort()
328
+ }
329
+
330
+ /**
331
+ * Gets the raw intent-to-section mapping for external use.
332
+ *
333
+ * @returns Copy of the intent sections mapping
334
+ */
335
+ export function getIntentSectionsMapping(): Record<string, string[]> {
336
+ return { ...INTENT_SECTIONS }
337
+ }
338
+
339
+ // Helper functions
340
+
341
+ /**
342
+ * Escapes special regex characters in a string
343
+ */
344
+ function escapeRegex(str: string): string {
345
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
346
+ }
347
+
348
+ /**
349
+ * Checks if text contains keywords suggesting a complex task
350
+ */
351
+ function containsComplexIntent(text: string): boolean {
352
+ const normalizedText = text.toLowerCase()
353
+
354
+ // Check for any intent keywords
355
+ for (const keyword of Object.keys(INTENT_SECTIONS)) {
356
+ const pattern = new RegExp(`\\b${escapeRegex(keyword)}\\b`, "i")
357
+ if (pattern.test(normalizedText)) {
358
+ return true
359
+ }
360
+ }
361
+
362
+ // Check for action words that suggest complexity
363
+ const complexPatterns = [
364
+ /\band\s+then\b/i,
365
+ /\bafter\s+that\b/i,
366
+ /\bfor\s+each\b/i,
367
+ /\ball\s+(the\s+)?/i,
368
+ /\bevery\s+/i,
369
+ /\bmultiple\b/i,
370
+ /\brepeat\b/i,
371
+ /\bloop\b/i,
372
+ /\bwait\s+(for|until)\b/i,
373
+ ]
374
+
375
+ return complexPatterns.some((pattern) => pattern.test(normalizedText))
376
+ }
@@ -0,0 +1,200 @@
1
+ import { Log } from "../util/log"
2
+ import { OAUTH_CALLBACK_PORT, OAUTH_CALLBACK_PATH } from "./oauth-provider"
3
+
4
+ const log = Log.create({ service: "mcp.oauth-callback" })
5
+
6
+ const HTML_SUCCESS = `<!DOCTYPE html>
7
+ <html>
8
+ <head>
9
+ <title>RIRD - Authorization Successful</title>
10
+ <style>
11
+ body { font-family: system-ui, -apple-system, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background: #1a1a2e; color: #eee; }
12
+ .container { text-align: center; padding: 2rem; }
13
+ h1 { color: #4ade80; margin-bottom: 1rem; }
14
+ p { color: #aaa; }
15
+ </style>
16
+ </head>
17
+ <body>
18
+ <div class="container">
19
+ <h1>Authorization Successful</h1>
20
+ <p>You can close this window and return to RIRD.</p>
21
+ </div>
22
+ <script>setTimeout(() => window.close(), 2000);</script>
23
+ </body>
24
+ </html>`
25
+
26
+ const HTML_ERROR = (error: string) => `<!DOCTYPE html>
27
+ <html>
28
+ <head>
29
+ <title>RIRD - Authorization Failed</title>
30
+ <style>
31
+ body { font-family: system-ui, -apple-system, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background: #1a1a2e; color: #eee; }
32
+ .container { text-align: center; padding: 2rem; }
33
+ h1 { color: #f87171; margin-bottom: 1rem; }
34
+ p { color: #aaa; }
35
+ .error { color: #fca5a5; font-family: monospace; margin-top: 1rem; padding: 1rem; background: rgba(248,113,113,0.1); border-radius: 0.5rem; }
36
+ </style>
37
+ </head>
38
+ <body>
39
+ <div class="container">
40
+ <h1>Authorization Failed</h1>
41
+ <p>An error occurred during authorization.</p>
42
+ <div class="error">${error}</div>
43
+ </div>
44
+ </body>
45
+ </html>`
46
+
47
+ interface PendingAuth {
48
+ resolve: (code: string) => void
49
+ reject: (error: Error) => void
50
+ timeout: ReturnType<typeof setTimeout>
51
+ }
52
+
53
+ export namespace McpOAuthCallback {
54
+ let server: ReturnType<typeof Bun.serve> | undefined
55
+ const pendingAuths = new Map<string, PendingAuth>()
56
+
57
+ const CALLBACK_TIMEOUT_MS = 5 * 60 * 1000 // 5 minutes
58
+
59
+ export async function ensureRunning(): Promise<void> {
60
+ if (server) return
61
+
62
+ const running = await isPortInUse()
63
+ if (running) {
64
+ log.info("oauth callback server already running on another instance", { port: OAUTH_CALLBACK_PORT })
65
+ return
66
+ }
67
+
68
+ server = Bun.serve({
69
+ port: OAUTH_CALLBACK_PORT,
70
+ fetch(req) {
71
+ const url = new URL(req.url)
72
+
73
+ if (url.pathname !== OAUTH_CALLBACK_PATH) {
74
+ return new Response("Not found", { status: 404 })
75
+ }
76
+
77
+ const code = url.searchParams.get("code")
78
+ const state = url.searchParams.get("state")
79
+ const error = url.searchParams.get("error")
80
+ const errorDescription = url.searchParams.get("error_description")
81
+
82
+ log.info("received oauth callback", { hasCode: !!code, state, error })
83
+
84
+ // Enforce state parameter presence
85
+ if (!state) {
86
+ const errorMsg = "Missing required state parameter - potential CSRF attack"
87
+ log.error("oauth callback missing state parameter", { url: url.toString() })
88
+ return new Response(HTML_ERROR(errorMsg), {
89
+ status: 400,
90
+ headers: { "Content-Type": "text/html" },
91
+ })
92
+ }
93
+
94
+ if (error) {
95
+ const errorMsg = errorDescription || error
96
+ if (pendingAuths.has(state)) {
97
+ const pending = pendingAuths.get(state)!
98
+ clearTimeout(pending.timeout)
99
+ pendingAuths.delete(state)
100
+ pending.reject(new Error(errorMsg))
101
+ }
102
+ return new Response(HTML_ERROR(errorMsg), {
103
+ headers: { "Content-Type": "text/html" },
104
+ })
105
+ }
106
+
107
+ if (!code) {
108
+ return new Response(HTML_ERROR("No authorization code provided"), {
109
+ status: 400,
110
+ headers: { "Content-Type": "text/html" },
111
+ })
112
+ }
113
+
114
+ // Validate state parameter
115
+ if (!pendingAuths.has(state)) {
116
+ const errorMsg = "Invalid or expired state parameter - potential CSRF attack"
117
+ log.error("oauth callback with invalid state", { state, pendingStates: Array.from(pendingAuths.keys()) })
118
+ return new Response(HTML_ERROR(errorMsg), {
119
+ status: 400,
120
+ headers: { "Content-Type": "text/html" },
121
+ })
122
+ }
123
+
124
+ const pending = pendingAuths.get(state)!
125
+
126
+ clearTimeout(pending.timeout)
127
+ pendingAuths.delete(state)
128
+ pending.resolve(code)
129
+
130
+ return new Response(HTML_SUCCESS, {
131
+ headers: { "Content-Type": "text/html" },
132
+ })
133
+ },
134
+ })
135
+
136
+ log.info("oauth callback server started", { port: OAUTH_CALLBACK_PORT })
137
+ }
138
+
139
+ export function waitForCallback(oauthState: string): Promise<string> {
140
+ return new Promise((resolve, reject) => {
141
+ const timeout = setTimeout(() => {
142
+ if (pendingAuths.has(oauthState)) {
143
+ pendingAuths.delete(oauthState)
144
+ reject(new Error("OAuth callback timeout - authorization took too long"))
145
+ }
146
+ }, CALLBACK_TIMEOUT_MS)
147
+
148
+ pendingAuths.set(oauthState, { resolve, reject, timeout })
149
+ })
150
+ }
151
+
152
+ export function cancelPending(mcpName: string): void {
153
+ const pending = pendingAuths.get(mcpName)
154
+ if (pending) {
155
+ clearTimeout(pending.timeout)
156
+ pendingAuths.delete(mcpName)
157
+ pending.reject(new Error("Authorization cancelled"))
158
+ }
159
+ }
160
+
161
+ export async function isPortInUse(): Promise<boolean> {
162
+ return new Promise((resolve) => {
163
+ Bun.connect({
164
+ hostname: "127.0.0.1",
165
+ port: OAUTH_CALLBACK_PORT,
166
+ socket: {
167
+ open(socket) {
168
+ socket.end()
169
+ resolve(true)
170
+ },
171
+ error() {
172
+ resolve(false)
173
+ },
174
+ data() {},
175
+ close() {},
176
+ },
177
+ }).catch(() => {
178
+ resolve(false)
179
+ })
180
+ })
181
+ }
182
+
183
+ export async function stop(): Promise<void> {
184
+ if (server) {
185
+ server.stop()
186
+ server = undefined
187
+ log.info("oauth callback server stopped")
188
+ }
189
+
190
+ for (const [name, pending] of pendingAuths) {
191
+ clearTimeout(pending.timeout)
192
+ pending.reject(new Error("OAuth callback server stopped"))
193
+ }
194
+ pendingAuths.clear()
195
+ }
196
+
197
+ export function isRunning(): boolean {
198
+ return server !== undefined
199
+ }
200
+ }