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,285 @@
1
+ /**
2
+ * Custom error classes for RIRD CLI production error handling
3
+ * Provides structured error information with user-facing messages and error codes
4
+ */
5
+
6
+ export interface ErrorContext {
7
+ code: string
8
+ statusCode: number
9
+ suggestion?: string
10
+ details?: Record<string, any>
11
+ originalError?: Error
12
+ }
13
+
14
+ /**
15
+ * Base RIRD error class with structure for production logging
16
+ */
17
+ export class RirdError extends Error implements ErrorContext {
18
+ code: string
19
+ statusCode: number
20
+ suggestion?: string
21
+ details?: Record<string, any>
22
+ originalError?: Error
23
+
24
+ constructor(message: string, context: Partial<ErrorContext> = {}) {
25
+ super(message)
26
+ this.name = this.constructor.name
27
+ this.code = context.code || "RIRD_ERROR"
28
+ this.statusCode = context.statusCode || 500
29
+ this.suggestion = context.suggestion
30
+ this.details = context.details
31
+ this.originalError = context.originalError
32
+
33
+ // Maintain proper prototype chain
34
+ Object.setPrototypeOf(this, RirdError.prototype)
35
+ }
36
+
37
+ toJSON() {
38
+ return {
39
+ name: this.name,
40
+ message: this.message,
41
+ code: this.code,
42
+ statusCode: this.statusCode,
43
+ suggestion: this.suggestion,
44
+ details: this.details,
45
+ stack: this.stack,
46
+ }
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Network-related errors (timeouts, connection failures)
52
+ */
53
+ export class NetworkError extends RirdError {
54
+ constructor(message: string, context: Partial<ErrorContext> = {}) {
55
+ super(message, {
56
+ code: "NETWORK_ERROR",
57
+ statusCode: 503,
58
+ suggestion:
59
+ "Check your internet connection, firewall settings, or try again later",
60
+ ...context,
61
+ })
62
+ Object.setPrototypeOf(this, NetworkError.prototype)
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Provider/API errors (model not found, invalid endpoints, API failures)
68
+ */
69
+ export class ProviderError extends RirdError {
70
+ constructor(message: string, context: Partial<ErrorContext> = {}) {
71
+ super(message, {
72
+ code: "PROVIDER_ERROR",
73
+ statusCode: 502,
74
+ suggestion:
75
+ "Verify your provider configuration and API credentials. Check rird status for details.",
76
+ ...context,
77
+ })
78
+ Object.setPrototypeOf(this, ProviderError.prototype)
79
+ }
80
+ }
81
+
82
+ /**
83
+ * License/authentication errors
84
+ */
85
+ export class LicenseError extends RirdError {
86
+ constructor(message: string, context: Partial<ErrorContext> = {}) {
87
+ super(message, {
88
+ code: "LICENSE_ERROR",
89
+ statusCode: 401,
90
+ suggestion: "Run 'rird activate <license-key>' to validate your license",
91
+ ...context,
92
+ })
93
+ Object.setPrototypeOf(this, LicenseError.prototype)
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Input validation errors
99
+ */
100
+ export class ValidationError extends RirdError {
101
+ constructor(message: string, context: Partial<ErrorContext> = {}) {
102
+ super(message, {
103
+ code: "VALIDATION_ERROR",
104
+ statusCode: 400,
105
+ suggestion: "Check the provided inputs and try again",
106
+ ...context,
107
+ })
108
+ Object.setPrototypeOf(this, ValidationError.prototype)
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Configuration errors
114
+ */
115
+ export class ConfigError extends RirdError {
116
+ constructor(message: string, context: Partial<ErrorContext> = {}) {
117
+ super(message, {
118
+ code: "CONFIG_ERROR",
119
+ statusCode: 500,
120
+ suggestion:
121
+ "Check your RIRD configuration file or run 'rird setup' to initialize",
122
+ ...context,
123
+ })
124
+ Object.setPrototypeOf(this, ConfigError.prototype)
125
+ }
126
+ }
127
+
128
+ /**
129
+ * File system errors
130
+ */
131
+ export class FileSystemError extends RirdError {
132
+ constructor(message: string, context: Partial<ErrorContext> = {}) {
133
+ super(message, {
134
+ code: "FILESYSTEM_ERROR",
135
+ statusCode: 500,
136
+ suggestion:
137
+ "Check file permissions and disk space. Ensure the file path is valid.",
138
+ ...context,
139
+ })
140
+ Object.setPrototypeOf(this, FileSystemError.prototype)
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Timeout errors
146
+ */
147
+ export class TimeoutError extends RirdError {
148
+ constructor(message: string, context: Partial<ErrorContext> = {}) {
149
+ super(message, {
150
+ code: "TIMEOUT_ERROR",
151
+ statusCode: 504,
152
+ suggestion: "The operation took too long. Try again or increase timeout.",
153
+ ...context,
154
+ })
155
+ Object.setPrototypeOf(this, TimeoutError.prototype)
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Server/process errors
161
+ */
162
+ export class ServerError extends RirdError {
163
+ constructor(message: string, context: Partial<ErrorContext> = {}) {
164
+ super(message, {
165
+ code: "SERVER_ERROR",
166
+ statusCode: 500,
167
+ suggestion:
168
+ "The RIRD server encountered an error. Check logs or try restarting.",
169
+ ...context,
170
+ })
171
+ Object.setPrototypeOf(this, ServerError.prototype)
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Installation/upgrade errors
177
+ */
178
+ export class InstallationError extends RirdError {
179
+ constructor(message: string, context: Partial<ErrorContext> = {}) {
180
+ super(message, {
181
+ code: "INSTALLATION_ERROR",
182
+ statusCode: 500,
183
+ suggestion:
184
+ "Installation failed. Ensure you have proper permissions and dependencies installed.",
185
+ ...context,
186
+ })
187
+ Object.setPrototypeOf(this, InstallationError.prototype)
188
+ }
189
+ }
190
+
191
+ /**
192
+ * Tool/command execution errors
193
+ */
194
+ export class ToolError extends RirdError {
195
+ constructor(message: string, context: Partial<ErrorContext> = {}) {
196
+ super(message, {
197
+ code: "TOOL_ERROR",
198
+ statusCode: 500,
199
+ suggestion: "A tool execution failed. Check the error details above.",
200
+ ...context,
201
+ })
202
+ Object.setPrototypeOf(this, ToolError.prototype)
203
+ }
204
+ }
205
+
206
+ /**
207
+ * Browser automation errors
208
+ */
209
+ export class BrowserError extends RirdError {
210
+ constructor(message: string, context: Partial<ErrorContext> = {}) {
211
+ super(message, {
212
+ code: "BROWSER_ERROR",
213
+ statusCode: 500,
214
+ suggestion:
215
+ "Browser operation failed. Ensure no other instances are running and try again.",
216
+ ...context,
217
+ })
218
+ Object.setPrototypeOf(this, BrowserError.prototype)
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Type guard to check if an error is a RirdError
224
+ */
225
+ export function isRirdError(error: unknown): error is RirdError {
226
+ return error instanceof RirdError
227
+ }
228
+
229
+ /**
230
+ * Convert any error to RirdError
231
+ */
232
+ export function toRirdError(error: unknown, defaultCode = "UNKNOWN_ERROR"): RirdError {
233
+ if (isRirdError(error)) {
234
+ return error
235
+ }
236
+
237
+ if (error instanceof Error) {
238
+ // Check if this is a NamedError with data (e.g., Storage.NotFoundError)
239
+ const namedError = error as { data?: Record<string, unknown>; name?: string }
240
+ let message = error.message
241
+ let details: Record<string, unknown> | undefined
242
+
243
+ // NamedError stores its data in .data property
244
+ if (namedError.data && typeof namedError.data === "object") {
245
+ details = namedError.data as Record<string, unknown>
246
+ // Extract message from data if the error message is just the error name
247
+ if (namedError.data.message && typeof namedError.data.message === "string") {
248
+ message = namedError.data.message as string
249
+ } else if (error.message === error.name || !error.message) {
250
+ // Build a descriptive message from the data
251
+ message = `${error.name || defaultCode}: ${JSON.stringify(namedError.data)}`
252
+ }
253
+ }
254
+
255
+ return new RirdError(message, {
256
+ code: error.name || defaultCode,
257
+ originalError: error,
258
+ details,
259
+ })
260
+ }
261
+
262
+ return new RirdError(String(error), { code: defaultCode })
263
+ }
264
+
265
+ /**
266
+ * Format error for user-friendly display
267
+ */
268
+ export function formatErrorMessage(error: RirdError): string {
269
+ const lines: string[] = []
270
+
271
+ lines.push(`Error [${error.code}]: ${error.message}`)
272
+
273
+ if (error.suggestion) {
274
+ lines.push(`Suggestion: ${error.suggestion}`)
275
+ }
276
+
277
+ if (error.details && Object.keys(error.details).length > 0) {
278
+ lines.push("Details:")
279
+ for (const [key, value] of Object.entries(error.details)) {
280
+ lines.push(` ${key}: ${JSON.stringify(value)}`)
281
+ }
282
+ }
283
+
284
+ return lines.join("\n")
285
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Performance monitoring and profiling utilities for RIRD CLI
3
+ * Tracks startup time, command execution time, and memory usage
4
+ */
5
+
6
+ const perfMarks = new Map<string, number>();
7
+ const startTime = Date.now();
8
+
9
+ export const Performance = {
10
+ /**
11
+ * Mark a performance checkpoint
12
+ */
13
+ mark(label: string) {
14
+ const elapsed = Date.now() - startTime;
15
+ perfMarks.set(label, elapsed);
16
+ if (process.env.RIRD_PERF_DEBUG) {
17
+ console.error(`[${elapsed}ms] ${label}`);
18
+ }
19
+ },
20
+
21
+ /**
22
+ * Get elapsed time for a mark
23
+ */
24
+ getTime(label: string): number | undefined {
25
+ return perfMarks.get(label);
26
+ },
27
+
28
+ /**
29
+ * Get elapsed time since startup
30
+ */
31
+ elapsed(): number {
32
+ return Date.now() - startTime;
33
+ },
34
+
35
+ /**
36
+ * Get current memory usage in MB
37
+ */
38
+ memoryUsage(): number {
39
+ const usage = process.memoryUsage();
40
+ return Math.round((usage.heapUsed / 1024 / 1024) * 100) / 100;
41
+ },
42
+
43
+ /**
44
+ * Report all performance metrics
45
+ */
46
+ report(): Record<string, number> {
47
+ const report: Record<string, number> = {};
48
+ perfMarks.forEach((time, label) => {
49
+ report[label] = time;
50
+ });
51
+ report.total = Performance.elapsed();
52
+ report.memory_mb = Performance.memoryUsage();
53
+ return report;
54
+ },
55
+
56
+ /**
57
+ * Check if startup performance is acceptable
58
+ * Returns null if ok, error message if slow
59
+ */
60
+ checkStartupPerformance(): string | null {
61
+ const total = Performance.elapsed();
62
+ if (total > 1000) {
63
+ return `Slow startup detected: ${total}ms (target: <1000ms)`;
64
+ }
65
+ return null;
66
+ },
67
+ };
68
+
69
+ // Mark startup
70
+ Performance.mark("startup");
@@ -0,0 +1,282 @@
1
+ import fs from "fs/promises"
2
+ import path from "path"
3
+ import { Global } from "../global"
4
+ import { Log } from "../util/log"
5
+
6
+ export namespace Telemetry {
7
+ const log = Log.create({ service: "telemetry" })
8
+
9
+ const TELEMETRY_DIR = path.join(Global.Path.log, "telemetry")
10
+ const ERROR_LOG_DIR = path.join(TELEMETRY_DIR, "errors")
11
+ const EVENT_LOG_DIR = path.join(TELEMETRY_DIR, "events")
12
+ const METRICS_LOG_DIR = path.join(TELEMETRY_DIR, "metrics")
13
+
14
+ const MAX_LOG_DAYS = 7
15
+ const MAX_LOGS_PER_DIR = 500
16
+
17
+ interface ErrorEntry {
18
+ timestamp: string
19
+ message: string
20
+ error?: string
21
+ stack?: string
22
+ context?: Record<string, any>
23
+ severity: "error" | "warning" | "critical"
24
+ }
25
+
26
+ interface EventEntry {
27
+ timestamp: string
28
+ name: string
29
+ properties?: Record<string, any>
30
+ duration?: number
31
+ }
32
+
33
+ interface MetricEntry {
34
+ timestamp: string
35
+ name: string
36
+ value: number
37
+ unit?: string
38
+ context?: Record<string, any>
39
+ }
40
+
41
+ async function ensureDirectories() {
42
+ try {
43
+ await Promise.all([
44
+ fs.mkdir(TELEMETRY_DIR, { recursive: true }),
45
+ fs.mkdir(ERROR_LOG_DIR, { recursive: true }),
46
+ fs.mkdir(EVENT_LOG_DIR, { recursive: true }),
47
+ fs.mkdir(METRICS_LOG_DIR, { recursive: true }),
48
+ ])
49
+ } catch (e) {
50
+ log.warn("Failed to create telemetry directories", { error: e })
51
+ }
52
+ }
53
+
54
+ async function rotateOldLogs(dir: string) {
55
+ try {
56
+ const files = await fs.readdir(dir)
57
+ if (files.length > MAX_LOGS_PER_DIR) {
58
+ const filesToDelete = files.slice(0, files.length - MAX_LOGS_PER_DIR)
59
+ await Promise.all(
60
+ filesToDelete.map((file) =>
61
+ fs.unlink(path.join(dir, file)).catch(() => {})
62
+ )
63
+ )
64
+ }
65
+
66
+ // Also clean up logs older than MAX_LOG_DAYS
67
+ const now = Date.now()
68
+ const maxAge = MAX_LOG_DAYS * 24 * 60 * 60 * 1000
69
+
70
+ for (const file of files) {
71
+ const filePath = path.join(dir, file)
72
+ const stat = await fs.stat(filePath).catch(() => null)
73
+ if (stat && now - stat.mtimeMs > maxAge) {
74
+ await fs.unlink(filePath).catch(() => {})
75
+ }
76
+ }
77
+ } catch (e) {
78
+ log.warn("Failed to rotate old logs", { error: e })
79
+ }
80
+ }
81
+
82
+ async function writeLog(dir: string, filename: string, data: any) {
83
+ try {
84
+ await ensureDirectories()
85
+ const filePath = path.join(dir, filename)
86
+ const content = typeof data === "string" ? data : JSON.stringify(data)
87
+ await fs.appendFile(filePath, content + "\n")
88
+ await rotateOldLogs(dir)
89
+ } catch (e) {
90
+ log.warn("Failed to write telemetry log", { error: e, filename })
91
+ }
92
+ }
93
+
94
+ export async function logError(
95
+ message: string,
96
+ error?: Error | unknown,
97
+ context?: Record<string, any>
98
+ ) {
99
+ const timestamp = new Date().toISOString()
100
+ const errorObj = error instanceof Error ? error : new Error(String(error))
101
+
102
+ const entry: ErrorEntry = {
103
+ timestamp,
104
+ message,
105
+ error: errorObj.message,
106
+ stack: errorObj.stack,
107
+ context,
108
+ severity: "error",
109
+ }
110
+
111
+ log.error(message, { error: errorObj, ...context })
112
+ await writeLog(
113
+ ERROR_LOG_DIR,
114
+ `errors-${new Date().toISOString().split("T")[0]}.jsonl`,
115
+ entry
116
+ )
117
+ }
118
+
119
+ export async function logWarning(
120
+ message: string,
121
+ context?: Record<string, any>
122
+ ) {
123
+ const timestamp = new Date().toISOString()
124
+ const entry: ErrorEntry = {
125
+ timestamp,
126
+ message,
127
+ context,
128
+ severity: "warning",
129
+ }
130
+
131
+ log.warn(message, context)
132
+ await writeLog(
133
+ ERROR_LOG_DIR,
134
+ `warnings-${new Date().toISOString().split("T")[0]}.jsonl`,
135
+ entry
136
+ )
137
+ }
138
+
139
+ export async function logInfo(
140
+ message: string,
141
+ context?: Record<string, any>
142
+ ) {
143
+ const timestamp = new Date().toISOString()
144
+ log.info(message, context)
145
+ }
146
+
147
+ export async function logDebug(
148
+ message: string,
149
+ context?: Record<string, any>
150
+ ) {
151
+ const timestamp = new Date().toISOString()
152
+ log.debug(message, context)
153
+ }
154
+
155
+ export async function trackEvent(
156
+ name: string,
157
+ properties?: Record<string, any>,
158
+ duration?: number
159
+ ) {
160
+ const timestamp = new Date().toISOString()
161
+ const entry: EventEntry = {
162
+ timestamp,
163
+ name,
164
+ properties,
165
+ duration,
166
+ }
167
+
168
+ log.info(`event:${name}`, properties)
169
+ await writeLog(
170
+ EVENT_LOG_DIR,
171
+ `events-${new Date().toISOString().split("T")[0]}.jsonl`,
172
+ entry
173
+ )
174
+ }
175
+
176
+ export async function trackMetric(
177
+ name: string,
178
+ value: number,
179
+ unit?: string,
180
+ context?: Record<string, any>
181
+ ) {
182
+ const timestamp = new Date().toISOString()
183
+ const entry: MetricEntry = {
184
+ timestamp,
185
+ name,
186
+ value,
187
+ unit,
188
+ context,
189
+ }
190
+
191
+ log.info(`metric:${name}`, { value, unit, ...context })
192
+ await writeLog(
193
+ METRICS_LOG_DIR,
194
+ `metrics-${new Date().toISOString().split("T")[0]}.jsonl`,
195
+ entry
196
+ )
197
+ }
198
+
199
+ export async function initialize() {
200
+ try {
201
+ await ensureDirectories()
202
+ log.info("Telemetry initialized", { directory: TELEMETRY_DIR })
203
+ } catch (e) {
204
+ log.warn("Failed to initialize telemetry", { error: e })
205
+ }
206
+ }
207
+
208
+ export async function getLogs(
209
+ type: "errors" | "warnings" | "events" | "metrics" = "errors",
210
+ days: number = 1
211
+ ): Promise<string[]> {
212
+ try {
213
+ const dir =
214
+ type === "errors" || type === "warnings"
215
+ ? ERROR_LOG_DIR
216
+ : type === "events"
217
+ ? EVENT_LOG_DIR
218
+ : METRICS_LOG_DIR
219
+
220
+ const files = await fs.readdir(dir)
221
+ const now = Date.now()
222
+ const maxAge = days * 24 * 60 * 60 * 1000
223
+
224
+ const relevantFiles = []
225
+ for (const file of files) {
226
+ const filePath = path.join(dir, file)
227
+ const stat = await fs.stat(filePath).catch(() => null)
228
+ if (stat && now - stat.mtimeMs <= maxAge) {
229
+ const content = await fs.readFile(filePath, "utf-8")
230
+ relevantFiles.push(content)
231
+ }
232
+ }
233
+
234
+ return relevantFiles
235
+ } catch (e) {
236
+ log.warn("Failed to read telemetry logs", { error: e, type })
237
+ return []
238
+ }
239
+ }
240
+
241
+ export async function printLogs(
242
+ type: "errors" | "warnings" | "events" | "metrics" = "errors",
243
+ days: number = 7
244
+ ) {
245
+ const logs = await getLogs(type, days)
246
+ if (logs.length === 0) {
247
+ console.log(`No ${type} logs found for the last ${days} days`)
248
+ return
249
+ }
250
+
251
+ console.log(`\n=== ${type.toUpperCase()} LOGS (Last ${days} days) ===\n`)
252
+ for (const log of logs) {
253
+ const lines = log.split("\n").filter((l) => l.trim())
254
+ for (const line of lines) {
255
+ try {
256
+ const entry = JSON.parse(line)
257
+ console.log(`[${entry.timestamp}] ${entry.message}`)
258
+ if (entry.error) console.log(` Error: ${entry.error}`)
259
+ if (entry.stack) console.log(` Stack: ${entry.stack}`)
260
+ if (entry.context) console.log(` Context: ${JSON.stringify(entry.context)}`)
261
+ } catch {
262
+ console.log(line)
263
+ }
264
+ }
265
+ }
266
+ console.log()
267
+ }
268
+
269
+ export function getLogPath(type: "errors" | "warnings" | "events" | "metrics" = "errors"): string {
270
+ switch (type) {
271
+ case "errors":
272
+ case "warnings":
273
+ return ERROR_LOG_DIR
274
+ case "events":
275
+ return EVENT_LOG_DIR
276
+ case "metrics":
277
+ return METRICS_LOG_DIR
278
+ default:
279
+ return TELEMETRY_DIR
280
+ }
281
+ }
282
+ }