rird 1.0.200

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 (350) hide show
  1. package/AGENTS.md +27 -0
  2. package/Dockerfile +18 -0
  3. package/README.md +15 -0
  4. package/bin/opencode +336 -0
  5. package/bin/pty-wrapper.js +285 -0
  6. package/bunfig.toml +4 -0
  7. package/facebook_ads_library.png +0 -0
  8. package/nul`nif +0 -0
  9. package/package.json +111 -0
  10. package/parsers-config.ts +239 -0
  11. package/rird-1.0.199.tgz +0 -0
  12. package/script/build-windows.ts +54 -0
  13. package/script/build.ts +167 -0
  14. package/script/postinstall.mjs +544 -0
  15. package/script/publish-registries.ts +187 -0
  16. package/script/publish.ts +72 -0
  17. package/script/schema.ts +47 -0
  18. package/src/acp/README.md +164 -0
  19. package/src/acp/agent.ts +1063 -0
  20. package/src/acp/session.ts +101 -0
  21. package/src/acp/types.ts +22 -0
  22. package/src/agent/agent.ts +367 -0
  23. package/src/agent/generate.txt +75 -0
  24. package/src/agent/prompt/compaction.txt +12 -0
  25. package/src/agent/prompt/explore.txt +18 -0
  26. package/src/agent/prompt/summary.txt +10 -0
  27. package/src/agent/prompt/title.txt +36 -0
  28. package/src/auth/index.ts +70 -0
  29. package/src/bun/index.ts +114 -0
  30. package/src/bus/bus-event.ts +43 -0
  31. package/src/bus/global.ts +10 -0
  32. package/src/bus/index.ts +105 -0
  33. package/src/cli/bootstrap.ts +17 -0
  34. package/src/cli/cmd/acp.ts +88 -0
  35. package/src/cli/cmd/agent.ts +256 -0
  36. package/src/cli/cmd/auth.ts +391 -0
  37. package/src/cli/cmd/cmd.ts +7 -0
  38. package/src/cli/cmd/debug/config.ts +15 -0
  39. package/src/cli/cmd/debug/file.ts +91 -0
  40. package/src/cli/cmd/debug/index.ts +43 -0
  41. package/src/cli/cmd/debug/lsp.ts +48 -0
  42. package/src/cli/cmd/debug/ripgrep.ts +83 -0
  43. package/src/cli/cmd/debug/scrap.ts +15 -0
  44. package/src/cli/cmd/debug/skill.ts +15 -0
  45. package/src/cli/cmd/debug/snapshot.ts +48 -0
  46. package/src/cli/cmd/export.ts +88 -0
  47. package/src/cli/cmd/generate.ts +38 -0
  48. package/src/cli/cmd/github.ts +1400 -0
  49. package/src/cli/cmd/import.ts +98 -0
  50. package/src/cli/cmd/mcp.ts +654 -0
  51. package/src/cli/cmd/models.ts +77 -0
  52. package/src/cli/cmd/pr.ts +112 -0
  53. package/src/cli/cmd/run.ts +368 -0
  54. package/src/cli/cmd/serve.ts +31 -0
  55. package/src/cli/cmd/session.ts +106 -0
  56. package/src/cli/cmd/stats.ts +298 -0
  57. package/src/cli/cmd/tui/app.tsx +696 -0
  58. package/src/cli/cmd/tui/attach.ts +30 -0
  59. package/src/cli/cmd/tui/component/border.tsx +21 -0
  60. package/src/cli/cmd/tui/component/dialog-agent.tsx +31 -0
  61. package/src/cli/cmd/tui/component/dialog-command.tsx +124 -0
  62. package/src/cli/cmd/tui/component/dialog-mcp.tsx +86 -0
  63. package/src/cli/cmd/tui/component/dialog-model.tsx +245 -0
  64. package/src/cli/cmd/tui/component/dialog-provider.tsx +224 -0
  65. package/src/cli/cmd/tui/component/dialog-session-list.tsx +102 -0
  66. package/src/cli/cmd/tui/component/dialog-session-rename.tsx +31 -0
  67. package/src/cli/cmd/tui/component/dialog-stash.tsx +86 -0
  68. package/src/cli/cmd/tui/component/dialog-status.tsx +162 -0
  69. package/src/cli/cmd/tui/component/dialog-tag.tsx +44 -0
  70. package/src/cli/cmd/tui/component/dialog-theme-list.tsx +50 -0
  71. package/src/cli/cmd/tui/component/did-you-know.tsx +85 -0
  72. package/src/cli/cmd/tui/component/logo.tsx +35 -0
  73. package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +574 -0
  74. package/src/cli/cmd/tui/component/prompt/history.tsx +108 -0
  75. package/src/cli/cmd/tui/component/prompt/index.tsx +1090 -0
  76. package/src/cli/cmd/tui/component/prompt/stash.tsx +101 -0
  77. package/src/cli/cmd/tui/component/tips.ts +27 -0
  78. package/src/cli/cmd/tui/component/todo-item.tsx +32 -0
  79. package/src/cli/cmd/tui/context/args.tsx +14 -0
  80. package/src/cli/cmd/tui/context/directory.ts +13 -0
  81. package/src/cli/cmd/tui/context/exit.tsx +23 -0
  82. package/src/cli/cmd/tui/context/helper.tsx +25 -0
  83. package/src/cli/cmd/tui/context/keybind.tsx +101 -0
  84. package/src/cli/cmd/tui/context/kv.tsx +49 -0
  85. package/src/cli/cmd/tui/context/local.tsx +354 -0
  86. package/src/cli/cmd/tui/context/prompt.tsx +18 -0
  87. package/src/cli/cmd/tui/context/route.tsx +46 -0
  88. package/src/cli/cmd/tui/context/sdk.tsx +74 -0
  89. package/src/cli/cmd/tui/context/sync.tsx +372 -0
  90. package/src/cli/cmd/tui/context/theme/aura.json +69 -0
  91. package/src/cli/cmd/tui/context/theme/ayu.json +80 -0
  92. package/src/cli/cmd/tui/context/theme/catppuccin-frappe.json +233 -0
  93. package/src/cli/cmd/tui/context/theme/catppuccin-macchiato.json +233 -0
  94. package/src/cli/cmd/tui/context/theme/catppuccin.json +112 -0
  95. package/src/cli/cmd/tui/context/theme/cobalt2.json +228 -0
  96. package/src/cli/cmd/tui/context/theme/cursor.json +249 -0
  97. package/src/cli/cmd/tui/context/theme/dracula.json +219 -0
  98. package/src/cli/cmd/tui/context/theme/everforest.json +241 -0
  99. package/src/cli/cmd/tui/context/theme/flexoki.json +237 -0
  100. package/src/cli/cmd/tui/context/theme/github.json +233 -0
  101. package/src/cli/cmd/tui/context/theme/gruvbox.json +95 -0
  102. package/src/cli/cmd/tui/context/theme/kanagawa.json +77 -0
  103. package/src/cli/cmd/tui/context/theme/lucent-orng.json +227 -0
  104. package/src/cli/cmd/tui/context/theme/material.json +235 -0
  105. package/src/cli/cmd/tui/context/theme/matrix.json +77 -0
  106. package/src/cli/cmd/tui/context/theme/mercury.json +252 -0
  107. package/src/cli/cmd/tui/context/theme/monokai.json +221 -0
  108. package/src/cli/cmd/tui/context/theme/nightowl.json +221 -0
  109. package/src/cli/cmd/tui/context/theme/nord.json +223 -0
  110. package/src/cli/cmd/tui/context/theme/one-dark.json +84 -0
  111. package/src/cli/cmd/tui/context/theme/orng.json +245 -0
  112. package/src/cli/cmd/tui/context/theme/palenight.json +222 -0
  113. package/src/cli/cmd/tui/context/theme/rird.json +245 -0
  114. package/src/cli/cmd/tui/context/theme/rosepine.json +234 -0
  115. package/src/cli/cmd/tui/context/theme/solarized.json +223 -0
  116. package/src/cli/cmd/tui/context/theme/synthwave84.json +226 -0
  117. package/src/cli/cmd/tui/context/theme/tokyonight.json +243 -0
  118. package/src/cli/cmd/tui/context/theme/vercel.json +245 -0
  119. package/src/cli/cmd/tui/context/theme/vesper.json +218 -0
  120. package/src/cli/cmd/tui/context/theme/zenburn.json +223 -0
  121. package/src/cli/cmd/tui/context/theme.tsx +1109 -0
  122. package/src/cli/cmd/tui/event.ts +40 -0
  123. package/src/cli/cmd/tui/routes/home.tsx +138 -0
  124. package/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +64 -0
  125. package/src/cli/cmd/tui/routes/session/dialog-message.tsx +109 -0
  126. package/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +26 -0
  127. package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +47 -0
  128. package/src/cli/cmd/tui/routes/session/footer.tsx +88 -0
  129. package/src/cli/cmd/tui/routes/session/header.tsx +125 -0
  130. package/src/cli/cmd/tui/routes/session/index.tsx +1864 -0
  131. package/src/cli/cmd/tui/routes/session/sidebar.tsx +318 -0
  132. package/src/cli/cmd/tui/spawn.ts +60 -0
  133. package/src/cli/cmd/tui/thread.ts +142 -0
  134. package/src/cli/cmd/tui/ui/dialog-alert.tsx +57 -0
  135. package/src/cli/cmd/tui/ui/dialog-confirm.tsx +83 -0
  136. package/src/cli/cmd/tui/ui/dialog-help.tsx +38 -0
  137. package/src/cli/cmd/tui/ui/dialog-prompt.tsx +77 -0
  138. package/src/cli/cmd/tui/ui/dialog-select.tsx +332 -0
  139. package/src/cli/cmd/tui/ui/dialog.tsx +170 -0
  140. package/src/cli/cmd/tui/ui/spinner.ts +368 -0
  141. package/src/cli/cmd/tui/ui/toast.tsx +100 -0
  142. package/src/cli/cmd/tui/util/clipboard.ts +127 -0
  143. package/src/cli/cmd/tui/util/editor.ts +32 -0
  144. package/src/cli/cmd/tui/util/terminal.ts +114 -0
  145. package/src/cli/cmd/tui/worker.ts +63 -0
  146. package/src/cli/cmd/uninstall.ts +344 -0
  147. package/src/cli/cmd/upgrade.ts +100 -0
  148. package/src/cli/cmd/web.ts +84 -0
  149. package/src/cli/error.ts +56 -0
  150. package/src/cli/ui.ts +84 -0
  151. package/src/cli/upgrade.ts +25 -0
  152. package/src/command/index.ts +80 -0
  153. package/src/command/template/initialize.txt +10 -0
  154. package/src/command/template/review.txt +97 -0
  155. package/src/config/config.ts +995 -0
  156. package/src/config/markdown.ts +41 -0
  157. package/src/env/index.ts +26 -0
  158. package/src/file/ignore.ts +83 -0
  159. package/src/file/index.ts +328 -0
  160. package/src/file/ripgrep.ts +393 -0
  161. package/src/file/time.ts +64 -0
  162. package/src/file/watcher.ts +103 -0
  163. package/src/flag/flag.ts +46 -0
  164. package/src/format/formatter.ts +315 -0
  165. package/src/format/index.ts +137 -0
  166. package/src/global/index.ts +52 -0
  167. package/src/id/id.ts +73 -0
  168. package/src/ide/index.ts +76 -0
  169. package/src/index.ts +240 -0
  170. package/src/installation/index.ts +239 -0
  171. package/src/lsp/client.ts +229 -0
  172. package/src/lsp/index.ts +485 -0
  173. package/src/lsp/language.ts +116 -0
  174. package/src/lsp/server.ts +1895 -0
  175. package/src/mcp/auth.ts +135 -0
  176. package/src/mcp/index.ts +690 -0
  177. package/src/mcp/oauth-callback.ts +200 -0
  178. package/src/mcp/oauth-provider.ts +154 -0
  179. package/src/patch/index.ts +622 -0
  180. package/src/permission/index.ts +199 -0
  181. package/src/plugin/index.ts +91 -0
  182. package/src/project/bootstrap.ts +31 -0
  183. package/src/project/instance.ts +78 -0
  184. package/src/project/project.ts +221 -0
  185. package/src/project/state.ts +65 -0
  186. package/src/project/vcs.ts +76 -0
  187. package/src/provider/auth.ts +143 -0
  188. package/src/provider/models-macro.ts +11 -0
  189. package/src/provider/models.ts +106 -0
  190. package/src/provider/provider.ts +1071 -0
  191. package/src/provider/sdk/openai-compatible/src/README.md +5 -0
  192. package/src/provider/sdk/openai-compatible/src/index.ts +2 -0
  193. package/src/provider/sdk/openai-compatible/src/openai-compatible-provider.ts +100 -0
  194. package/src/provider/sdk/openai-compatible/src/responses/convert-to-openai-responses-input.ts +303 -0
  195. package/src/provider/sdk/openai-compatible/src/responses/map-openai-responses-finish-reason.ts +22 -0
  196. package/src/provider/sdk/openai-compatible/src/responses/openai-config.ts +18 -0
  197. package/src/provider/sdk/openai-compatible/src/responses/openai-error.ts +22 -0
  198. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-api-types.ts +207 -0
  199. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-language-model.ts +1713 -0
  200. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-prepare-tools.ts +177 -0
  201. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-settings.ts +1 -0
  202. package/src/provider/sdk/openai-compatible/src/responses/tool/code-interpreter.ts +88 -0
  203. package/src/provider/sdk/openai-compatible/src/responses/tool/file-search.ts +128 -0
  204. package/src/provider/sdk/openai-compatible/src/responses/tool/image-generation.ts +115 -0
  205. package/src/provider/sdk/openai-compatible/src/responses/tool/local-shell.ts +65 -0
  206. package/src/provider/sdk/openai-compatible/src/responses/tool/web-search-preview.ts +104 -0
  207. package/src/provider/sdk/openai-compatible/src/responses/tool/web-search.ts +103 -0
  208. package/src/provider/transform.ts +455 -0
  209. package/src/pty/index.ts +231 -0
  210. package/src/security/guardrails.test.ts +341 -0
  211. package/src/security/guardrails.ts +558 -0
  212. package/src/security/index.ts +19 -0
  213. package/src/server/error.ts +36 -0
  214. package/src/server/project.ts +79 -0
  215. package/src/server/server.ts +2642 -0
  216. package/src/server/tui.ts +71 -0
  217. package/src/session/compaction.ts +223 -0
  218. package/src/session/index.ts +461 -0
  219. package/src/session/llm.ts +201 -0
  220. package/src/session/message-v2.ts +690 -0
  221. package/src/session/message.ts +189 -0
  222. package/src/session/processor.ts +409 -0
  223. package/src/session/prompt/act-switch.txt +5 -0
  224. package/src/session/prompt/anthropic-20250930.txt +166 -0
  225. package/src/session/prompt/anthropic.txt +85 -0
  226. package/src/session/prompt/anthropic_spoof.txt +1 -0
  227. package/src/session/prompt/beast.txt +103 -0
  228. package/src/session/prompt/codex.txt +304 -0
  229. package/src/session/prompt/copilot-gpt-5.txt +138 -0
  230. package/src/session/prompt/gemini.txt +85 -0
  231. package/src/session/prompt/max-steps.txt +16 -0
  232. package/src/session/prompt/plan-reminder-anthropic.txt +35 -0
  233. package/src/session/prompt/plan.txt +24 -0
  234. package/src/session/prompt/polaris.txt +84 -0
  235. package/src/session/prompt/qwen.txt +106 -0
  236. package/src/session/prompt.ts +1509 -0
  237. package/src/session/retry.ts +86 -0
  238. package/src/session/revert.ts +108 -0
  239. package/src/session/sensitive-filter.test.ts +327 -0
  240. package/src/session/sensitive-filter.ts +466 -0
  241. package/src/session/status.ts +76 -0
  242. package/src/session/summary.ts +194 -0
  243. package/src/session/system.ts +120 -0
  244. package/src/session/todo.ts +37 -0
  245. package/src/share/share-next.ts +194 -0
  246. package/src/share/share.ts +87 -0
  247. package/src/shell/shell.ts +67 -0
  248. package/src/skill/index.ts +1 -0
  249. package/src/skill/skill.ts +83 -0
  250. package/src/snapshot/index.ts +197 -0
  251. package/src/storage/storage.ts +226 -0
  252. package/src/tests/agent.test.ts +308 -0
  253. package/src/tests/build-guards.test.ts +267 -0
  254. package/src/tests/config.test.ts +664 -0
  255. package/src/tests/tool-registry.test.ts +589 -0
  256. package/src/tool/bash.ts +317 -0
  257. package/src/tool/bash.txt +158 -0
  258. package/src/tool/batch.ts +175 -0
  259. package/src/tool/batch.txt +24 -0
  260. package/src/tool/codesearch.ts +168 -0
  261. package/src/tool/codesearch.txt +12 -0
  262. package/src/tool/edit.ts +675 -0
  263. package/src/tool/edit.txt +10 -0
  264. package/src/tool/glob.ts +65 -0
  265. package/src/tool/glob.txt +6 -0
  266. package/src/tool/grep.ts +121 -0
  267. package/src/tool/grep.txt +8 -0
  268. package/src/tool/invalid.ts +17 -0
  269. package/src/tool/ls.ts +110 -0
  270. package/src/tool/ls.txt +1 -0
  271. package/src/tool/lsp-diagnostics.ts +26 -0
  272. package/src/tool/lsp-diagnostics.txt +1 -0
  273. package/src/tool/lsp-hover.ts +31 -0
  274. package/src/tool/lsp-hover.txt +1 -0
  275. package/src/tool/lsp.ts +87 -0
  276. package/src/tool/lsp.txt +19 -0
  277. package/src/tool/multiedit.ts +46 -0
  278. package/src/tool/multiedit.txt +41 -0
  279. package/src/tool/patch.ts +233 -0
  280. package/src/tool/patch.txt +1 -0
  281. package/src/tool/read.ts +219 -0
  282. package/src/tool/read.txt +12 -0
  283. package/src/tool/registry.ts +162 -0
  284. package/src/tool/skill.ts +100 -0
  285. package/src/tool/task.ts +136 -0
  286. package/src/tool/task.txt +51 -0
  287. package/src/tool/todo.ts +39 -0
  288. package/src/tool/todoread.txt +14 -0
  289. package/src/tool/todowrite.txt +167 -0
  290. package/src/tool/tool.ts +71 -0
  291. package/src/tool/webfetch.ts +198 -0
  292. package/src/tool/webfetch.txt +13 -0
  293. package/src/tool/websearch.ts +180 -0
  294. package/src/tool/websearch.txt +11 -0
  295. package/src/tool/write.ts +110 -0
  296. package/src/tool/write.txt +8 -0
  297. package/src/util/archive.ts +16 -0
  298. package/src/util/color.ts +19 -0
  299. package/src/util/context.ts +25 -0
  300. package/src/util/defer.ts +12 -0
  301. package/src/util/eventloop.ts +20 -0
  302. package/src/util/filesystem.ts +83 -0
  303. package/src/util/fn.ts +11 -0
  304. package/src/util/iife.ts +3 -0
  305. package/src/util/keybind.ts +102 -0
  306. package/src/util/lazy.ts +11 -0
  307. package/src/util/license.ts +325 -0
  308. package/src/util/locale.ts +81 -0
  309. package/src/util/lock.ts +98 -0
  310. package/src/util/log.ts +180 -0
  311. package/src/util/queue.ts +32 -0
  312. package/src/util/rpc.ts +42 -0
  313. package/src/util/scrap.ts +10 -0
  314. package/src/util/signal.ts +12 -0
  315. package/src/util/timeout.ts +14 -0
  316. package/src/util/token.ts +7 -0
  317. package/src/util/wildcard.ts +54 -0
  318. package/sst-env.d.ts +9 -0
  319. package/test/agent/agent.test.ts +146 -0
  320. package/test/bun.test.ts +53 -0
  321. package/test/cli/github-remote.test.ts +80 -0
  322. package/test/config/agent-color.test.ts +66 -0
  323. package/test/config/config.test.ts +535 -0
  324. package/test/config/markdown.test.ts +89 -0
  325. package/test/file/ignore.test.ts +10 -0
  326. package/test/fixture/fixture.ts +36 -0
  327. package/test/fixture/lsp/fake-lsp-server.js +77 -0
  328. package/test/ide/ide.test.ts +82 -0
  329. package/test/keybind.test.ts +421 -0
  330. package/test/lsp/client.test.ts +95 -0
  331. package/test/mcp/headers.test.ts +153 -0
  332. package/test/patch/patch.test.ts +348 -0
  333. package/test/preload.ts +57 -0
  334. package/test/project/project.test.ts +72 -0
  335. package/test/provider/provider.test.ts +1809 -0
  336. package/test/provider/transform.test.ts +411 -0
  337. package/test/session/retry.test.ts +111 -0
  338. package/test/session/session.test.ts +71 -0
  339. package/test/skill/skill.test.ts +131 -0
  340. package/test/snapshot/snapshot.test.ts +939 -0
  341. package/test/tool/__snapshots__/tool.test.ts.snap +9 -0
  342. package/test/tool/bash.test.ts +434 -0
  343. package/test/tool/grep.test.ts +108 -0
  344. package/test/tool/patch.test.ts +259 -0
  345. package/test/tool/read.test.ts +42 -0
  346. package/test/util/iife.test.ts +36 -0
  347. package/test/util/lazy.test.ts +50 -0
  348. package/test/util/timeout.test.ts +21 -0
  349. package/test/util/wildcard.test.ts +55 -0
  350. package/tsconfig.json +16 -0
@@ -0,0 +1,558 @@
1
+ /**
2
+ * Safety Guardrails for RIRD Agent
3
+ *
4
+ * Prevents misuse by blocking:
5
+ * - Malicious task descriptions
6
+ * - Dangerous target domains
7
+ * - Destructive system commands
8
+ * - Financial transactions (sending money)
9
+ * - Data deletion operations
10
+ * - Prompt injection attempts
11
+ */
12
+
13
+ import fs from "fs"
14
+ import path from "path"
15
+ import os from "os"
16
+
17
+ // Security audit log path - uses XDG data dir pattern
18
+ const SECURITY_LOG_DIR = path.join(
19
+ process.env.XDG_DATA_HOME || path.join(os.homedir(), ".local", "share"),
20
+ "rird",
21
+ "security"
22
+ )
23
+
24
+ // Ensure security log directory exists
25
+ try {
26
+ fs.mkdirSync(SECURITY_LOG_DIR, { recursive: true })
27
+ } catch {
28
+ // Directory may already exist or permissions issue - will fallback to console only
29
+ }
30
+
31
+ // Domains that should NEVER be automated against (high fraud/harm risk)
32
+ // NOTE: This is a MINIMAL blocklist - we allow most sites for legitimate work
33
+ // The intent detection layer catches malicious USE of any site
34
+ export const BLOCKED_DOMAINS = new Set([
35
+ // Banking & Financial (fraud risk - transactions require human oversight)
36
+ "chase.com",
37
+ "bankofamerica.com",
38
+ "wellsfargo.com",
39
+ "citibank.com",
40
+ "capitalone.com",
41
+
42
+ // Crypto exchanges (irreversible transactions)
43
+ "coinbase.com",
44
+ "binance.com",
45
+ "kraken.com",
46
+
47
+ // Government identity (identity theft risk)
48
+ "irs.gov",
49
+ "ssa.gov",
50
+ "login.gov",
51
+ "id.me",
52
+ ])
53
+
54
+ // ALLOWED for legitimate AI worker use:
55
+ // - Email (Gmail, Outlook, Yahoo, etc.) - essential for communication
56
+ // - Social media (LinkedIn, Twitter, Facebook) - outreach and engagement
57
+ // - E-commerce (Amazon, eBay, etc.) - shopping and research
58
+ // - Healthcare portals - appointment booking, etc.
59
+ // - Payment services (PayPal, Venmo) - with user oversight
60
+
61
+ // Patterns that indicate malicious intent
62
+ export const MALICIOUS_PATTERNS = [
63
+ // Credential harvesting
64
+ /harvest.*(password|credential|key|token|secret)/i,
65
+ /steal.*(password|credential|key|token|secret|data|info)/i,
66
+ /scrape.*(password|credential|key|token|login)/i,
67
+ /extract.*(password|credential|key|token|cookie)/i,
68
+ /dump.*(password|credential|database|cookie)/i,
69
+ /capture.*(keystroke|keylog|password)/i,
70
+
71
+ // Account compromise
72
+ /brute.?force/i,
73
+ /crack.*(password|hash|account)/i,
74
+ /bypass.*(auth|2fa|mfa|captcha|security)/i,
75
+ /hijack.*(session|account|cookie)/i,
76
+ /takeover.*(account)/i,
77
+
78
+ // Data exfiltration
79
+ /exfiltrate/i,
80
+ /mass.?download.*(data|user|profile)/i,
81
+ /bulk.?scrape.*(email|phone|contact|profile)/i,
82
+ /harvest.*(email|phone|contact|pii)/i,
83
+
84
+ // Malware/attacks
85
+ /inject.*(malware|virus|trojan|payload)/i,
86
+ /deploy.*(rat|backdoor|rootkit)/i,
87
+ /ransomware/i,
88
+ /cryptojack/i,
89
+ /ddos|dos.?attack/i,
90
+ /phish/i,
91
+ /spoof/i,
92
+
93
+ // Fraud
94
+ /fake.*(account|identity|profile)/i,
95
+ /impersonate/i,
96
+ /catfish/i,
97
+ /scam/i,
98
+ /fraud/i,
99
+
100
+ // Illegal activities
101
+ /illegal/i,
102
+ /dark.?web/i,
103
+ /black.?market/i,
104
+ /launder/i,
105
+ ]
106
+
107
+ // CRITICAL SAFETY BLOCKS - These actions are IRREVERSIBLE or CATASTROPHIC
108
+ // RIRD is autonomous for SAFE actions, but BLOCKS dangerous ones outright
109
+ // No confirmation dialogs - just refuses dangerous actions
110
+ export const CRITICAL_DANGER_PATTERNS = [
111
+ // ============ VIOLENCE/WEAPONS ============
112
+ /kill/i,
113
+ /murder/i,
114
+ /assassinate/i,
115
+ /bomb/i,
116
+ /weapon/i,
117
+ /terroris/i,
118
+ /shoot\s+(them|him|her|the|a\s+person)/i,
119
+ /stab/i,
120
+ /poison/i,
121
+ /explode/i,
122
+ /detonate/i,
123
+ /attack\s+.*(person|people|target|victim|user)/i,
124
+ /harm\s+.*(person|people|target|victim)/i,
125
+ /stalk\s+.*(person|target|victim|them|him|her)/i,
126
+ /harass\s+.*(person|target|victim|them|him|her)/i,
127
+ /doxx/i,
128
+ /swat/i,
129
+ /threaten\s+.*(person|target|victim)/i,
130
+ /target\s+(these|those|the|all)\s*(person|people|user|victim)/i,
131
+
132
+ // ============ MONEY/FINANCIAL ============
133
+ // Block ALL money sending - too risky if agent compromised
134
+ /send\s+(money|funds|payment|\$\d)/i,
135
+ /transfer\s+(money|funds|\$\d)/i,
136
+ /wire\s+(money|funds|transfer)/i,
137
+ /pay\s+(them|someone|him|her|\$\d)/i,
138
+ /venmo\s+(send|pay|transfer)/i,
139
+ /zelle\s+(send|pay|transfer)/i,
140
+ /paypal\s+(send|pay|transfer)/i,
141
+ /cash\s*app\s+(send|pay)/i,
142
+ /withdraw\s+(money|funds|cash|\$)/i,
143
+ /purchase\s+(crypto|bitcoin|ethereum|gift\s*card)/i,
144
+ /buy\s+(crypto|bitcoin|ethereum|gift\s*card)/i,
145
+
146
+ // ============ DATA DESTRUCTION ============
147
+ // Block mass deletion - catastrophic if wrong
148
+ /delete\s+(all|everything|every|the\s+entire)/i,
149
+ /remove\s+(all|everything|every)/i,
150
+ /erase\s+(all|everything|every|the\s+entire)/i,
151
+ /wipe\s+(all|everything|the|my)/i,
152
+ /destroy\s+(all|everything|the|my)/i,
153
+ /purge\s+(all|everything|the|my)/i,
154
+ /drop\s+(database|table|collection|all)/i,
155
+ /truncate\s+(table|database)/i,
156
+ /rm\s+-rf/i,
157
+ /format\s+(drive|disk|c:)/i,
158
+
159
+ // ============ CREDENTIALS/SECRETS ============
160
+ // Block credential operations - theft vector
161
+ /export\s+.*(password|credential|secret|key|token)/i,
162
+ /send\s+.*(password|credential|secret|key|token)/i,
163
+ /share\s+.*(password|credential|secret|key|token)/i,
164
+ /forward\s+.*(password|credential|secret|key|token)/i,
165
+ /dump\s+.*(password|credential|hash|database)/i,
166
+ /extract\s+.*(password|credential|cookie|session)/i,
167
+
168
+ // ============ ACCOUNT DESTRUCTION ============
169
+ /close\s+(my\s+)?account/i,
170
+ /delete\s+(my\s+)?account/i,
171
+ /deactivate\s+(my\s+)?account/i,
172
+ /terminate\s+(my\s+)?account/i,
173
+ ]
174
+
175
+ // Alias for backwards compatibility
176
+ export const WEAPON_ATTACK_PATTERNS = CRITICAL_DANGER_PATTERNS
177
+
178
+ // AUTONOMOUS SAFE ACTIONS (no blocking):
179
+ // - Read emails, browse, search, research
180
+ // - Send emails/messages (content, not money)
181
+ // - Fill forms, schedule meetings
182
+ // - Normal work tasks
183
+ // - Delete SPECIFIC items (not "all")
184
+
185
+ // PROMPT INJECTION DETECTION - Block attempts to hijack the agent
186
+ export const PROMPT_INJECTION_PATTERNS = [
187
+ // Direct instruction override attempts
188
+ /ignore\s+(all\s+)?(previous|prior|above)\s+(instructions|rules|guidelines)/i,
189
+ /disregard\s+(all\s+)?(previous|prior|above)\s+(instructions|rules)/i,
190
+ /forget\s+(all\s+)?(previous|prior|your)\s+(instructions|rules|training)/i,
191
+ /override\s+(your|the|all)\s+(instructions|rules|restrictions)/i,
192
+ /bypass\s+(your|the|all)\s+(restrictions|limitations|guardrails)/i,
193
+
194
+ // Role-play injection
195
+ /pretend\s+(you\s+are|to\s+be|you're)\s+(a|an|the)/i,
196
+ /act\s+as\s+(if\s+you\s+are|a|an|the)/i,
197
+ /you\s+are\s+now\s+(a|an|the|in)/i,
198
+ /roleplay\s+as/i,
199
+ /simulate\s+(being|a|an)/i,
200
+ /imagine\s+you\s+are/i,
201
+
202
+ // System prompt extraction
203
+ /reveal\s+(your|the)\s+(system|initial)\s+(prompt|instructions)/i,
204
+ /show\s+(me\s+)?(your|the)\s+(system|initial)\s+(prompt|instructions)/i,
205
+ /what\s+(are|is)\s+your\s+(system|initial)\s+(prompt|instructions)/i,
206
+ /print\s+(your|the)\s+(system|initial)\s+prompt/i,
207
+ /output\s+(your|the)\s+(system|initial)\s+prompt/i,
208
+
209
+ // Fake system messages
210
+ /<\/?system>/i,
211
+ /<\/?instructions>/i,
212
+ /<\/?admin>/i,
213
+ /\[SYSTEM\]/i,
214
+ /\[ADMIN\]/i,
215
+ /\[OVERRIDE\]/i,
216
+ /###\s*(system|admin|override)/i,
217
+
218
+ // Jailbreak keywords
219
+ /jailbreak/i,
220
+ /dan\s+mode/i,
221
+ /developer\s+mode\s+enabled/i,
222
+ /sudo\s+mode/i,
223
+ /god\s+mode/i,
224
+ /unrestricted\s+mode/i,
225
+ ]
226
+
227
+ // Destructive bash command patterns (regex)
228
+ export const BLOCKED_COMMAND_PATTERNS = [
229
+ // Filesystem destruction - only block rm targeting root/home/current dir exactly
230
+ /^rm\s+(-[rfv]+\s+)*\/\s*$/i, // rm -rf /
231
+ /^rm\s+(-[rfv]+\s+)*\/\*\s*$/i, // rm -rf /*
232
+ /^rm\s+(-[rfv]+\s+)*~\s*$/i, // rm -rf ~
233
+ /^rm\s+(-[rfv]+\s+)*\.\s*$/i, // rm -rf . (exact)
234
+ /^rm\s+(-[rfv]+\s+)*\.\.\s*$/i, // rm -rf .. (exact)
235
+ ]
236
+
237
+ // Destructive bash commands that should NEVER execute (substring match)
238
+ export const BLOCKED_COMMANDS = [
239
+ // Filesystem destruction
240
+ "> /dev/sda",
241
+ "dd if=/dev/zero",
242
+ "dd if=/dev/random",
243
+ "mkfs",
244
+ "format",
245
+ ":(){:|:&};:", // fork bomb
246
+
247
+ // System compromise
248
+ "chmod -R 777 /",
249
+ "chown -R",
250
+ "passwd",
251
+ "useradd",
252
+ "userdel",
253
+ "visudo",
254
+
255
+ // Network attacks
256
+ "nmap -sS",
257
+ "hping3",
258
+ "slowloris",
259
+
260
+ // Crypto mining
261
+ "xmrig",
262
+ "minerd",
263
+ "cpuminer",
264
+ ]
265
+
266
+ export interface GuardrailResult {
267
+ blocked: boolean
268
+ reason?: string
269
+ category?: "domain" | "intent" | "command" | "weapon" | "injection"
270
+ }
271
+
272
+ /**
273
+ * Check if a URL/domain is blocked
274
+ */
275
+ export function checkDomain(url: string): GuardrailResult {
276
+ try {
277
+ const urlObj = new URL(url.startsWith("http") ? url : `https://${url}`)
278
+ const hostname = urlObj.hostname.toLowerCase()
279
+
280
+ // Check exact match and parent domains
281
+ const parts = hostname.split(".")
282
+ for (let i = 0; i < parts.length - 1; i++) {
283
+ const domain = parts.slice(i).join(".")
284
+ if (BLOCKED_DOMAINS.has(domain)) {
285
+ return {
286
+ blocked: true,
287
+ reason: `Domain "${domain}" is blocked for security reasons. This appears to be a banking, financial, healthcare, or government site.`,
288
+ category: "domain",
289
+ }
290
+ }
291
+ }
292
+ } catch {
293
+ // Invalid URL, let it through for other validation
294
+ }
295
+
296
+ return { blocked: false }
297
+ }
298
+
299
+ /**
300
+ * Check if task description contains malicious intent
301
+ */
302
+ export function checkIntent(taskDescription: string): GuardrailResult {
303
+ const normalized = taskDescription.toLowerCase()
304
+
305
+ for (const pattern of MALICIOUS_PATTERNS) {
306
+ if (pattern.test(normalized)) {
307
+ return {
308
+ blocked: true,
309
+ reason: `Task appears to involve malicious activity. RIRD is designed for legitimate automation only.`,
310
+ category: "intent",
311
+ }
312
+ }
313
+ }
314
+
315
+ return { blocked: false }
316
+ }
317
+
318
+ /**
319
+ * Check if task contains dangerous/irreversible actions
320
+ * Blocks: violence, money transfers, mass deletion, credential export
321
+ * Users warned upfront - no confirmations, just refuses dangerous actions
322
+ */
323
+ export function checkWeaponUse(taskDescription: string): GuardrailResult {
324
+ const normalized = taskDescription.toLowerCase()
325
+
326
+ for (const pattern of CRITICAL_DANGER_PATTERNS) {
327
+ if (pattern.test(normalized)) {
328
+ return {
329
+ blocked: true,
330
+ reason: `BLOCKED: This action is dangerous and irreversible. RIRD blocks: violence/weapons, money transfers, mass deletion, and credential export.`,
331
+ category: "weapon",
332
+ }
333
+ }
334
+ }
335
+
336
+ return { blocked: false }
337
+ }
338
+
339
+ /**
340
+ * Check for prompt injection attempts
341
+ * Detects attempts to hijack the agent via malicious instructions
342
+ */
343
+ export function checkPromptInjection(content: string): GuardrailResult {
344
+ const normalized = content.toLowerCase()
345
+
346
+ for (const pattern of PROMPT_INJECTION_PATTERNS) {
347
+ if (pattern.test(normalized)) {
348
+ return {
349
+ blocked: true,
350
+ reason: `PROMPT INJECTION DETECTED: Content contains patterns that attempt to override agent instructions. This may be a malicious webpage or document.`,
351
+ category: "injection",
352
+ }
353
+ }
354
+ }
355
+
356
+ return { blocked: false }
357
+ }
358
+
359
+ /**
360
+ * Check if bash command is destructive
361
+ */
362
+ export function checkCommand(command: string): GuardrailResult {
363
+ const normalized = command.toLowerCase().trim()
364
+
365
+ // Check exact pattern matches first (rm commands targeting dangerous paths)
366
+ for (const pattern of BLOCKED_COMMAND_PATTERNS) {
367
+ if (pattern.test(normalized)) {
368
+ return {
369
+ blocked: true,
370
+ reason: "Recursive deletion of system directories is blocked.",
371
+ category: "command",
372
+ }
373
+ }
374
+ }
375
+
376
+ // Check substring matches for other dangerous commands
377
+ for (const blocked of BLOCKED_COMMANDS) {
378
+ if (normalized.includes(blocked.toLowerCase())) {
379
+ return {
380
+ blocked: true,
381
+ reason: `Command containing "${blocked}" is blocked as potentially destructive.`,
382
+ category: "command",
383
+ }
384
+ }
385
+ }
386
+
387
+ // Block direct disk writes
388
+ if (/>\s*\/dev\/[sh]d[a-z]/.test(normalized)) {
389
+ return {
390
+ blocked: true,
391
+ reason: "Direct writes to disk devices are blocked.",
392
+ category: "command",
393
+ }
394
+ }
395
+
396
+ return { blocked: false }
397
+ }
398
+
399
+ /**
400
+ * Run all guardrail checks on a task
401
+ * Logs all blocked attempts for security audit trail
402
+ */
403
+ export function validateTask(task: {
404
+ description?: string
405
+ url?: string
406
+ command?: string
407
+ webContent?: string // Content scraped from web pages
408
+ }): GuardrailResult {
409
+ const context = {
410
+ task: task.description,
411
+ url: task.url,
412
+ command: task.command,
413
+ webContent: task.webContent,
414
+ timestamp: new Date(),
415
+ }
416
+
417
+ // Check for prompt injection in web content FIRST (highest priority)
418
+ if (task.webContent) {
419
+ const injectionResult = checkPromptInjection(task.webContent)
420
+ if (injectionResult.blocked) {
421
+ logBlockedAttempt(injectionResult, context)
422
+ return injectionResult
423
+ }
424
+ }
425
+
426
+ // Check for prompt injection in task description
427
+ if (task.description) {
428
+ const injectionResult = checkPromptInjection(task.description)
429
+ if (injectionResult.blocked) {
430
+ logBlockedAttempt(injectionResult, context)
431
+ return injectionResult
432
+ }
433
+ }
434
+
435
+ // Check for weapon use (violence, stalking, targeting people)
436
+ if (task.description) {
437
+ const weaponResult = checkWeaponUse(task.description)
438
+ if (weaponResult.blocked) {
439
+ logBlockedAttempt(weaponResult, context)
440
+ return weaponResult
441
+ }
442
+ }
443
+
444
+ // Check malicious intent
445
+ if (task.description) {
446
+ const intentResult = checkIntent(task.description)
447
+ if (intentResult.blocked) {
448
+ logBlockedAttempt(intentResult, context)
449
+ return intentResult
450
+ }
451
+ }
452
+
453
+ // Check domain
454
+ if (task.url) {
455
+ const domainResult = checkDomain(task.url)
456
+ if (domainResult.blocked) {
457
+ logBlockedAttempt(domainResult, context)
458
+ return domainResult
459
+ }
460
+ }
461
+
462
+ // Check command
463
+ if (task.command) {
464
+ const commandResult = checkCommand(task.command)
465
+ if (commandResult.blocked) {
466
+ logBlockedAttempt(commandResult, context)
467
+ return commandResult
468
+ }
469
+ }
470
+
471
+ return { blocked: false }
472
+ }
473
+
474
+ /**
475
+ * Log blocked attempt (for audit)
476
+ * Writes to both console and persistent file-based audit log
477
+ */
478
+ export function logBlockedAttempt(
479
+ result: GuardrailResult,
480
+ context: { task?: string; url?: string; command?: string; webContent?: string; timestamp?: Date }
481
+ ): void {
482
+ const timestamp = context.timestamp || new Date()
483
+ const entry = {
484
+ timestamp: timestamp.toISOString(),
485
+ category: result.category,
486
+ reason: result.reason,
487
+ task: context.task?.substring(0, 200), // Truncate for privacy but keep enough context
488
+ url: context.url,
489
+ command: context.command?.substring(0, 100),
490
+ webContentPreview: context.webContent?.substring(0, 100), // Brief preview if injection detected
491
+ }
492
+
493
+ // Log to console (visible in terminal)
494
+ console.warn("[GUARDRAIL BLOCKED]", JSON.stringify(entry))
495
+
496
+ // Persistent file-based audit logging
497
+ try {
498
+ const logFileName = `security-blocks-${timestamp.toISOString().split("T")[0]}.jsonl`
499
+ const logFilePath = path.join(SECURITY_LOG_DIR, logFileName)
500
+
501
+ // Append to daily log file (JSONL format - one JSON object per line)
502
+ fs.appendFileSync(logFilePath, JSON.stringify(entry) + "\n", { encoding: "utf-8" })
503
+ } catch (err) {
504
+ // If file logging fails, at least console.warn already ran
505
+ console.warn("[GUARDRAIL] Failed to write audit log:", err instanceof Error ? err.message : err)
506
+ }
507
+ }
508
+
509
+ /**
510
+ * Get path to security audit logs directory
511
+ * Logs are stored as daily JSONL files: security-blocks-YYYY-MM-DD.jsonl
512
+ */
513
+ export function getSecurityLogDir(): string {
514
+ return SECURITY_LOG_DIR
515
+ }
516
+
517
+ /**
518
+ * Read recent security blocks from audit log
519
+ * @param days Number of days to look back (default: 7)
520
+ * @returns Array of blocked attempt entries
521
+ */
522
+ export function getRecentSecurityBlocks(days: number = 7): Array<{
523
+ timestamp: string
524
+ category: string
525
+ reason: string
526
+ task?: string
527
+ url?: string
528
+ command?: string
529
+ }> {
530
+ const entries: Array<any> = []
531
+
532
+ try {
533
+ const files = fs.readdirSync(SECURITY_LOG_DIR)
534
+ .filter(f => f.startsWith("security-blocks-") && f.endsWith(".jsonl"))
535
+ .sort()
536
+ .slice(-days) // Get last N days
537
+
538
+ for (const file of files) {
539
+ try {
540
+ const content = fs.readFileSync(path.join(SECURITY_LOG_DIR, file), "utf-8")
541
+ const lines = content.trim().split("\n").filter(Boolean)
542
+ for (const line of lines) {
543
+ try {
544
+ entries.push(JSON.parse(line))
545
+ } catch {
546
+ // Skip malformed lines
547
+ }
548
+ }
549
+ } catch {
550
+ // Skip unreadable files
551
+ }
552
+ }
553
+ } catch {
554
+ // Directory may not exist yet
555
+ }
556
+
557
+ return entries
558
+ }
@@ -0,0 +1,19 @@
1
+ export {
2
+ checkDomain,
3
+ checkIntent,
4
+ checkCommand,
5
+ checkWeaponUse,
6
+ checkPromptInjection,
7
+ validateTask,
8
+ logBlockedAttempt,
9
+ getSecurityLogDir,
10
+ getRecentSecurityBlocks,
11
+ BLOCKED_DOMAINS,
12
+ MALICIOUS_PATTERNS,
13
+ BLOCKED_COMMANDS,
14
+ BLOCKED_COMMAND_PATTERNS,
15
+ CRITICAL_DANGER_PATTERNS,
16
+ WEAPON_ATTACK_PATTERNS,
17
+ PROMPT_INJECTION_PATTERNS,
18
+ type GuardrailResult,
19
+ } from "./guardrails"
@@ -0,0 +1,36 @@
1
+ import { resolver } from "hono-openapi"
2
+ import z from "zod"
3
+ import { Storage } from "../storage/storage"
4
+
5
+ export const ERRORS = {
6
+ 400: {
7
+ description: "Bad request",
8
+ content: {
9
+ "application/json": {
10
+ schema: resolver(
11
+ z
12
+ .object({
13
+ data: z.any(),
14
+ errors: z.array(z.record(z.string(), z.any())),
15
+ success: z.literal(false),
16
+ })
17
+ .meta({
18
+ ref: "BadRequestError",
19
+ }),
20
+ ),
21
+ },
22
+ },
23
+ },
24
+ 404: {
25
+ description: "Not found",
26
+ content: {
27
+ "application/json": {
28
+ schema: resolver(Storage.NotFoundError.Schema),
29
+ },
30
+ },
31
+ },
32
+ } as const
33
+
34
+ export function errors(...codes: number[]) {
35
+ return Object.fromEntries(codes.map((code) => [code, ERRORS[code as keyof typeof ERRORS]]))
36
+ }
@@ -0,0 +1,79 @@
1
+ import { Hono } from "hono"
2
+ import { describeRoute, validator } from "hono-openapi"
3
+ import { resolver } from "hono-openapi"
4
+ import { Instance } from "../project/instance"
5
+ import { Project } from "../project/project"
6
+ import z from "zod"
7
+ import { errors } from "./error"
8
+
9
+ export const ProjectRoute = new Hono()
10
+ .get(
11
+ "/",
12
+ describeRoute({
13
+ summary: "List all projects",
14
+ description: "Get a list of projects that have been opened with RIRD.",
15
+ operationId: "project.list",
16
+ responses: {
17
+ 200: {
18
+ description: "List of projects",
19
+ content: {
20
+ "application/json": {
21
+ schema: resolver(Project.Info.array()),
22
+ },
23
+ },
24
+ },
25
+ },
26
+ }),
27
+ async (c) => {
28
+ const projects = await Project.list()
29
+ return c.json(projects)
30
+ },
31
+ )
32
+ .get(
33
+ "/current",
34
+ describeRoute({
35
+ summary: "Get current project",
36
+ description: "Retrieve the currently active project that RIRD is working with.",
37
+ operationId: "project.current",
38
+ responses: {
39
+ 200: {
40
+ description: "Current project information",
41
+ content: {
42
+ "application/json": {
43
+ schema: resolver(Project.Info),
44
+ },
45
+ },
46
+ },
47
+ },
48
+ }),
49
+ async (c) => {
50
+ return c.json(Instance.project)
51
+ },
52
+ )
53
+ .patch(
54
+ "/:projectID",
55
+ describeRoute({
56
+ summary: "Update project",
57
+ description: "Update project properties such as name, icon and color.",
58
+ operationId: "project.update",
59
+ responses: {
60
+ 200: {
61
+ description: "Updated project information",
62
+ content: {
63
+ "application/json": {
64
+ schema: resolver(Project.Info),
65
+ },
66
+ },
67
+ },
68
+ ...errors(400, 404),
69
+ },
70
+ }),
71
+ validator("param", z.object({ projectID: z.string() })),
72
+ validator("json", Project.update.schema.omit({ projectID: true })),
73
+ async (c) => {
74
+ const projectID = c.req.valid("param").projectID
75
+ const body = c.req.valid("json")
76
+ const project = await Project.update({ ...body, projectID })
77
+ return c.json(project)
78
+ },
79
+ )