enya-agent 0.1.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 (389) hide show
  1. package/.env.example +20 -0
  2. package/.github/workflows/ci.yml +70 -0
  3. package/.github/workflows/publish.yml +250 -0
  4. package/.gitmodules +3 -0
  5. package/Cargo.lock +3584 -0
  6. package/Cargo.toml +97 -0
  7. package/crates/enact/Cargo.toml +27 -0
  8. package/crates/enact/src/lib.rs +60 -0
  9. package/crates/enact-a2a/Cargo.toml +25 -0
  10. package/crates/enact-a2a/src/lib.rs +411 -0
  11. package/crates/enact-channels/Cargo.toml +64 -0
  12. package/crates/enact-channels/examples/README.md +80 -0
  13. package/crates/enact-channels/examples/channel_bot.rs +169 -0
  14. package/crates/enact-channels/examples/telegram-echo.rs +34 -0
  15. package/crates/enact-channels/examples/whatsapp-echo.rs +142 -0
  16. package/crates/enact-channels/src/config.rs +213 -0
  17. package/crates/enact-channels/src/lib.rs +25 -0
  18. package/crates/enact-channels/src/runtime.rs +237 -0
  19. package/crates/enact-channels/src/security/mod.rs +5 -0
  20. package/crates/enact-channels/src/security/pairing.rs +205 -0
  21. package/crates/enact-channels/src/teams.rs +601 -0
  22. package/crates/enact-channels/src/telegram.rs +2833 -0
  23. package/crates/enact-channels/src/traits.rs +200 -0
  24. package/crates/enact-channels/src/webhook.rs +262 -0
  25. package/crates/enact-channels/src/whatsapp.rs +310 -0
  26. package/crates/enact-cli/Cargo.toml +40 -0
  27. package/crates/enact-cli/src/commands/doctor.rs +62 -0
  28. package/crates/enact-cli/src/commands/mod.rs +3 -0
  29. package/crates/enact-cli/src/commands/run.rs +69 -0
  30. package/crates/enact-cli/src/commands/serve.rs +81 -0
  31. package/crates/enact-cli/src/config.rs +2 -0
  32. package/crates/enact-cli/src/main.rs +79 -0
  33. package/crates/enact-config/Cargo.toml +36 -0
  34. package/crates/enact-config/ENV_VAR_MAPPING.md +135 -0
  35. package/crates/enact-config/QUICK_REFERENCE.md +92 -0
  36. package/crates/enact-config/README.md +107 -0
  37. package/crates/enact-config/TESTING.md +161 -0
  38. package/crates/enact-config/examples/test-env-vars.rs +100 -0
  39. package/crates/enact-config/src/config.rs +399 -0
  40. package/crates/enact-config/src/encrypted_store.rs +211 -0
  41. package/crates/enact-config/src/lib.rs +298 -0
  42. package/crates/enact-config/src/secrets.rs +149 -0
  43. package/crates/enact-config/src/sync.rs +260 -0
  44. package/crates/enact-config/test-env-vars.sh +34 -0
  45. package/crates/enact-config/tests/README.md +99 -0
  46. package/crates/enact-config/tests/config_integration_test.rs +202 -0
  47. package/crates/enact-config/tests/security_test.rs +140 -0
  48. package/crates/enact-context/Cargo.toml +41 -0
  49. package/crates/enact-context/src/budget.rs +314 -0
  50. package/crates/enact-context/src/calibrator.rs +535 -0
  51. package/crates/enact-context/src/compactor.rs +392 -0
  52. package/crates/enact-context/src/condenser.rs +826 -0
  53. package/crates/enact-context/src/lib.rs +94 -0
  54. package/crates/enact-context/src/segment.rs +238 -0
  55. package/crates/enact-context/src/step_context.rs +645 -0
  56. package/crates/enact-context/src/token_counter.rs +148 -0
  57. package/crates/enact-context/src/window.rs +372 -0
  58. package/crates/enact-core/Cargo.toml +42 -0
  59. package/crates/enact-core/README.md +98 -0
  60. package/crates/enact-core/src/background/executor.rs +524 -0
  61. package/crates/enact-core/src/background/mod.rs +48 -0
  62. package/crates/enact-core/src/background/target_binding.rs +390 -0
  63. package/crates/enact-core/src/background/trigger.rs +511 -0
  64. package/crates/enact-core/src/callable/callable.rs +152 -0
  65. package/crates/enact-core/src/callable/composite.rs +817 -0
  66. package/crates/enact-core/src/callable/graph.rs +104 -0
  67. package/crates/enact-core/src/callable/llm.rs +211 -0
  68. package/crates/enact-core/src/callable/mod.rs +64 -0
  69. package/crates/enact-core/src/callable/registry.rs +206 -0
  70. package/crates/enact-core/src/context/execution_context.rs +757 -0
  71. package/crates/enact-core/src/context/invocation.rs +99 -0
  72. package/crates/enact-core/src/context/mod.rs +50 -0
  73. package/crates/enact-core/src/context/tenant.rs +175 -0
  74. package/crates/enact-core/src/context/trace.rs +127 -0
  75. package/crates/enact-core/src/flow/conditional.rs +293 -0
  76. package/crates/enact-core/src/flow/mod.rs +43 -0
  77. package/crates/enact-core/src/flow/parallel.rs +437 -0
  78. package/crates/enact-core/src/flow/repeat.rs +534 -0
  79. package/crates/enact-core/src/flow/sequential.rs +248 -0
  80. package/crates/enact-core/src/graph/checkpoint.rs +79 -0
  81. package/crates/enact-core/src/graph/checkpoint_store.rs +76 -0
  82. package/crates/enact-core/src/graph/compiled.rs +189 -0
  83. package/crates/enact-core/src/graph/edge.rs +59 -0
  84. package/crates/enact-core/src/graph/graph_schema.rs +218 -0
  85. package/crates/enact-core/src/graph/loader.rs +155 -0
  86. package/crates/enact-core/src/graph/mod.rs +18 -0
  87. package/crates/enact-core/src/graph/node/function.rs +49 -0
  88. package/crates/enact-core/src/graph/node/mod.rs +48 -0
  89. package/crates/enact-core/src/graph/schema.rs +62 -0
  90. package/crates/enact-core/src/inbox/message.rs +405 -0
  91. package/crates/enact-core/src/inbox/mod.rs +31 -0
  92. package/crates/enact-core/src/inbox/store.rs +355 -0
  93. package/crates/enact-core/src/kernel/artifact/filesystem.rs +546 -0
  94. package/crates/enact-core/src/kernel/artifact/metadata.rs +283 -0
  95. package/crates/enact-core/src/kernel/artifact/mod.rs +27 -0
  96. package/crates/enact-core/src/kernel/artifact/store.rs +427 -0
  97. package/crates/enact-core/src/kernel/enforcement.rs +1315 -0
  98. package/crates/enact-core/src/kernel/error.rs +1200 -0
  99. package/crates/enact-core/src/kernel/event.rs +1394 -0
  100. package/crates/enact-core/src/kernel/execution_model.rs +831 -0
  101. package/crates/enact-core/src/kernel/execution_state.rs +189 -0
  102. package/crates/enact-core/src/kernel/execution_strategy.rs +117 -0
  103. package/crates/enact-core/src/kernel/ids.rs +2086 -0
  104. package/crates/enact-core/src/kernel/interrupt.rs +125 -0
  105. package/crates/enact-core/src/kernel/kernel.rs +1283 -0
  106. package/crates/enact-core/src/kernel/mod.rs +205 -0
  107. package/crates/enact-core/src/kernel/persistence/event_store.rs +270 -0
  108. package/crates/enact-core/src/kernel/persistence/message_store.rs +908 -0
  109. package/crates/enact-core/src/kernel/persistence/mod.rs +102 -0
  110. package/crates/enact-core/src/kernel/persistence/state_store.rs +228 -0
  111. package/crates/enact-core/src/kernel/persistence/vector_store.rs +299 -0
  112. package/crates/enact-core/src/kernel/reducer.rs +808 -0
  113. package/crates/enact-core/src/kernel/replay.rs +153 -0
  114. package/crates/enact-core/src/lib.rs +413 -0
  115. package/crates/enact-core/src/memory/episodic.rs +0 -0
  116. package/crates/enact-core/src/memory/mod.rs +6 -0
  117. package/crates/enact-core/src/memory/semantic.rs +0 -0
  118. package/crates/enact-core/src/memory/trait.rs +0 -0
  119. package/crates/enact-core/src/memory/vector_db.rs +0 -0
  120. package/crates/enact-core/src/memory/working.rs +0 -0
  121. package/crates/enact-core/src/policy/execution_policy.rs +292 -0
  122. package/crates/enact-core/src/policy/filters.rs +458 -0
  123. package/crates/enact-core/src/policy/input_processor.rs +407 -0
  124. package/crates/enact-core/src/policy/long_running.rs +134 -0
  125. package/crates/enact-core/src/policy/mod.rs +193 -0
  126. package/crates/enact-core/src/policy/pii_input.rs +274 -0
  127. package/crates/enact-core/src/policy/tenant_policy.rs +453 -0
  128. package/crates/enact-core/src/policy/tool_policy.rs +407 -0
  129. package/crates/enact-core/src/providers/mod.rs +63 -0
  130. package/crates/enact-core/src/providers/trait.rs +292 -0
  131. package/crates/enact-core/src/runner/callbacks.rs +6 -0
  132. package/crates/enact-core/src/runner/execution_runner.rs +476 -0
  133. package/crates/enact-core/src/runner/loop.rs +117 -0
  134. package/crates/enact-core/src/runner/mod.rs +58 -0
  135. package/crates/enact-core/src/runner/protected_runner.rs +280 -0
  136. package/crates/enact-core/src/signal/inmemory.rs +231 -0
  137. package/crates/enact-core/src/signal/mod.rs +108 -0
  138. package/crates/enact-core/src/streaming/event_logger.rs +195 -0
  139. package/crates/enact-core/src/streaming/event_stream.rs +1423 -0
  140. package/crates/enact-core/src/streaming/mod.rs +108 -0
  141. package/crates/enact-core/src/streaming/pause_cancel.rs +0 -0
  142. package/crates/enact-core/src/streaming/protected_emitter.rs +173 -0
  143. package/crates/enact-core/src/streaming/protection/context.rs +136 -0
  144. package/crates/enact-core/src/streaming/protection/encryption.rs +289 -0
  145. package/crates/enact-core/src/streaming/protection/mod.rs +43 -0
  146. package/crates/enact-core/src/streaming/protection/pii_protection.rs +243 -0
  147. package/crates/enact-core/src/streaming/protection/processor.rs +166 -0
  148. package/crates/enact-core/src/streaming/sse.rs +0 -0
  149. package/crates/enact-core/src/telemetry/exporter.rs +0 -0
  150. package/crates/enact-core/src/telemetry/init.rs +0 -0
  151. package/crates/enact-core/src/telemetry/mod.rs +49 -0
  152. package/crates/enact-core/src/telemetry/spans.rs +245 -0
  153. package/crates/enact-core/src/tool/agent_tool.rs +177 -0
  154. package/crates/enact-core/src/tool/browser/mod.rs +0 -0
  155. package/crates/enact-core/src/tool/browser/webdriver.rs +0 -0
  156. package/crates/enact-core/src/tool/cost.rs +247 -0
  157. package/crates/enact-core/src/tool/discovery.rs +0 -0
  158. package/crates/enact-core/src/tool/dispatcher.rs +347 -0
  159. package/crates/enact-core/src/tool/filesystem.rs +231 -0
  160. package/crates/enact-core/src/tool/function.rs +99 -0
  161. package/crates/enact-core/src/tool/git.rs +162 -0
  162. package/crates/enact-core/src/tool/http.rs +214 -0
  163. package/crates/enact-core/src/tool/mcp/client.rs +0 -0
  164. package/crates/enact-core/src/tool/mcp/mod.rs +0 -0
  165. package/crates/enact-core/src/tool/mod.rs +51 -0
  166. package/crates/enact-core/src/tool/reasoning/debugging.rs +0 -0
  167. package/crates/enact-core/src/tool/reasoning/mcts.rs +0 -0
  168. package/crates/enact-core/src/tool/reasoning/mod.rs +0 -0
  169. package/crates/enact-core/src/tool/reasoning/sequential.rs +0 -0
  170. package/crates/enact-core/src/tool/sandbox/dagger.rs +0 -0
  171. package/crates/enact-core/src/tool/sandbox/mod.rs +0 -0
  172. package/crates/enact-core/src/tool/shell.rs +147 -0
  173. package/crates/enact-core/src/tool/trait.rs +33 -0
  174. package/crates/enact-core/src/tool/web_search.rs +277 -0
  175. package/crates/enact-core/src/util/config.rs +0 -0
  176. package/crates/enact-core/src/util/errors.rs +0 -0
  177. package/crates/enact-core/src/util/mod.rs +6 -0
  178. package/crates/enact-core/tests/airgapped_e2e_test.rs +291 -0
  179. package/crates/enact-core/tests/e2e_agentic_loop.rs +119 -0
  180. package/crates/enact-core/tests/e2e_test.rs +259 -0
  181. package/crates/enact-core/tests/graph_test.rs +130 -0
  182. package/crates/enact-core/tests/stream_event_id_validation.rs +435 -0
  183. package/crates/enact-cron/Cargo.toml +28 -0
  184. package/crates/enact-cron/src/lib.rs +44 -0
  185. package/crates/enact-cron/src/schedule.rs +156 -0
  186. package/crates/enact-cron/src/store.rs +589 -0
  187. package/crates/enact-cron/src/types.rs +148 -0
  188. package/crates/enact-gateway/Cargo.toml +31 -0
  189. package/crates/enact-gateway/README.md +30 -0
  190. package/crates/enact-gateway/examples/whatsapp-gateway-runner-mock.rs +59 -0
  191. package/crates/enact-gateway/examples/whatsapp-gateway.rs +42 -0
  192. package/crates/enact-gateway/src/lib.rs +582 -0
  193. package/crates/enact-mcp/Cargo.toml +24 -0
  194. package/crates/enact-mcp/src/lib.rs +178 -0
  195. package/crates/enact-memory/Cargo.toml +25 -0
  196. package/crates/enact-memory/src/backend.rs +20 -0
  197. package/crates/enact-memory/src/chunker.rs +230 -0
  198. package/crates/enact-memory/src/embeddings.rs +221 -0
  199. package/crates/enact-memory/src/lib.rs +67 -0
  200. package/crates/enact-memory/src/markdown.rs +127 -0
  201. package/crates/enact-memory/src/none.rs +61 -0
  202. package/crates/enact-memory/src/sqlite.rs +276 -0
  203. package/crates/enact-memory/src/traits.rs +65 -0
  204. package/crates/enact-memory/src/vector.rs +198 -0
  205. package/crates/enact-oauth/Cargo.toml +27 -0
  206. package/crates/enact-oauth/src/lib.rs +584 -0
  207. package/crates/enact-observability/Cargo.toml +22 -0
  208. package/crates/enact-observability/src/lib.rs +197 -0
  209. package/crates/enact-providers/Cargo.toml +33 -0
  210. package/crates/enact-providers/examples/hello-agent.rs +33 -0
  211. package/crates/enact-providers/src/anthropic.rs +182 -0
  212. package/crates/enact-providers/src/azure.rs +96 -0
  213. package/crates/enact-providers/src/bridge.rs +221 -0
  214. package/crates/enact-providers/src/gemini.rs +227 -0
  215. package/crates/enact-providers/src/http.rs +78 -0
  216. package/crates/enact-providers/src/lib.rs +53 -0
  217. package/crates/enact-providers/src/openai_compatible.rs +167 -0
  218. package/crates/enact-providers/src/openrouter.rs +33 -0
  219. package/crates/enact-runner/Cargo.toml +24 -0
  220. package/crates/enact-runner/README.md +76 -0
  221. package/crates/enact-runner/src/compaction.rs +225 -0
  222. package/crates/enact-runner/src/config.rs +118 -0
  223. package/crates/enact-runner/src/lib.rs +63 -0
  224. package/crates/enact-runner/src/loop_driver.rs +414 -0
  225. package/crates/enact-runner/src/parser.rs +421 -0
  226. package/crates/enact-runner/src/retry.rs +262 -0
  227. package/crates/enact-runner/tests/integration.rs +278 -0
  228. package/crates/enact-security/Cargo.toml +22 -0
  229. package/crates/enact-security/src/audit.rs +375 -0
  230. package/crates/enact-security/src/lib.rs +37 -0
  231. package/crates/enact-security/src/policy.rs +406 -0
  232. package/crates/enact-skills/Cargo.toml +25 -0
  233. package/crates/enact-skills/src/lib.rs +506 -0
  234. package/crates/enact-tools/Cargo.toml +22 -0
  235. package/crates/enact-tools/src/file_read.rs +166 -0
  236. package/crates/enact-tools/src/file_write.rs +216 -0
  237. package/crates/enact-tools/src/git_operations.rs +513 -0
  238. package/crates/enact-tools/src/http_request.rs +417 -0
  239. package/crates/enact-tools/src/lib.rs +104 -0
  240. package/crates/enact-tools/src/security.rs +227 -0
  241. package/crates/enact-tools/src/shell.rs +191 -0
  242. package/crates/enact-tools/src/traits.rs +159 -0
  243. package/docs/Makefile +74 -0
  244. package/docs/config.toml +62 -0
  245. package/docs/content/_index.md +174 -0
  246. package/docs/content/a2a/_index.md +431 -0
  247. package/docs/content/api/_index.md +323 -0
  248. package/docs/content/channels/_index.md +160 -0
  249. package/docs/content/channels/teams.md +205 -0
  250. package/docs/content/channels/telegram.md +182 -0
  251. package/docs/content/channels/webhook.md +423 -0
  252. package/docs/content/channels/whatsapp.md +240 -0
  253. package/docs/content/cli/_index.md +261 -0
  254. package/docs/content/concepts/_index.md +273 -0
  255. package/docs/content/configuration/_index.md +241 -0
  256. package/docs/content/cron/_index.md +248 -0
  257. package/docs/content/developers/_index.md +278 -0
  258. package/docs/content/getting-started/_index.md +180 -0
  259. package/docs/content/installation/_index.md +186 -0
  260. package/docs/content/installation/uninstall.md +101 -0
  261. package/docs/content/installation/updating.md +120 -0
  262. package/docs/content/mcp/_index.md +215 -0
  263. package/docs/content/memory/_index.md +163 -0
  264. package/docs/content/oauth/_index.md +515 -0
  265. package/docs/content/providers/_index.md +206 -0
  266. package/docs/content/roadmap/_index.md +199 -0
  267. package/docs/content/security/_index.md +219 -0
  268. package/docs/content/skills/_index.md +228 -0
  269. package/docs/content/tools/_index.md +485 -0
  270. package/docs/content/troubleshooting/_index.md +259 -0
  271. package/docs/content/yaml-schema/_index.md +294 -0
  272. package/docs/static/giallo-dark.css +91 -0
  273. package/docs/static/giallo-light.css +91 -0
  274. package/docs/themes/tanuki/.github/workflows/deploy.yml +44 -0
  275. package/docs/themes/tanuki/LICENSE +21 -0
  276. package/docs/themes/tanuki/README.md +166 -0
  277. package/docs/themes/tanuki/examples/blog/config.toml +58 -0
  278. package/docs/themes/tanuki/examples/blog/content/_index.md +4 -0
  279. package/docs/themes/tanuki/examples/blog/content/about.md +33 -0
  280. package/docs/themes/tanuki/examples/blog/content/blog/_index.md +7 -0
  281. package/docs/themes/tanuki/examples/blog/content/blog/api-design-best-practices.md +245 -0
  282. package/docs/themes/tanuki/examples/blog/content/blog/building-accessible-websites.md +147 -0
  283. package/docs/themes/tanuki/examples/blog/content/blog/css-grid-vs-flexbox.md +165 -0
  284. package/docs/themes/tanuki/examples/blog/content/blog/customizing-catppuccin-colors.md +137 -0
  285. package/docs/themes/tanuki/examples/blog/content/blog/dark-mode-best-practices.md +82 -0
  286. package/docs/themes/tanuki/examples/blog/content/blog/docker-essentials.md +301 -0
  287. package/docs/themes/tanuki/examples/blog/content/blog/getting-started-with-zola.md +129 -0
  288. package/docs/themes/tanuki/examples/blog/content/blog/git-workflow-for-content.md +112 -0
  289. package/docs/themes/tanuki/examples/blog/content/blog/introduction-to-webassembly.md +183 -0
  290. package/docs/themes/tanuki/examples/blog/content/blog/modern-javascript-features.md +234 -0
  291. package/docs/themes/tanuki/examples/blog/content/blog/testing-strategies.md +311 -0
  292. package/docs/themes/tanuki/examples/blog/content/blog/typography-for-developers.md +104 -0
  293. package/docs/themes/tanuki/examples/blog/content/blog/welcome-to-tanuki.md +67 -0
  294. package/docs/themes/tanuki/examples/blog/content/blog/why-static-sites.md +85 -0
  295. package/docs/themes/tanuki/examples/blog/content/projects.md +64 -0
  296. package/docs/themes/tanuki/examples/book/config.toml +17 -0
  297. package/docs/themes/tanuki/examples/book/content/_index.md +12 -0
  298. package/docs/themes/tanuki/examples/book/content/chapter-1.md +90 -0
  299. package/docs/themes/tanuki/examples/book/content/chapter-2.md +143 -0
  300. package/docs/themes/tanuki/examples/book/content/chapter-3.md +217 -0
  301. package/docs/themes/tanuki/examples/book/content/chapter-4.md +224 -0
  302. package/docs/themes/tanuki/examples/book/content/chapter-5.md +297 -0
  303. package/docs/themes/tanuki/examples/book/content/print.md +6 -0
  304. package/docs/themes/tanuki/examples/docs/config.toml +28 -0
  305. package/docs/themes/tanuki/examples/docs/content/_index.md +20 -0
  306. package/docs/themes/tanuki/examples/docs/content/components.md +156 -0
  307. package/docs/themes/tanuki/examples/docs/content/configuration.md +94 -0
  308. package/docs/themes/tanuki/examples/docs/content/customization.md +202 -0
  309. package/docs/themes/tanuki/examples/docs/content/deployment.md +204 -0
  310. package/docs/themes/tanuki/examples/docs/content/installation.md +59 -0
  311. package/docs/themes/tanuki/examples/docs/content/print.md +6 -0
  312. package/docs/themes/tanuki/examples/docs/static/img/tanuki-icon.avif +0 -0
  313. package/docs/themes/tanuki/examples/index.html +2104 -0
  314. package/docs/themes/tanuki/mise.toml +108 -0
  315. package/docs/themes/tanuki/sass/base/_catppuccin.scss +164 -0
  316. package/docs/themes/tanuki/sass/base/_fonts.scss +64 -0
  317. package/docs/themes/tanuki/sass/base/_reset.scss +152 -0
  318. package/docs/themes/tanuki/sass/base/_typography.scss +523 -0
  319. package/docs/themes/tanuki/sass/components/_buttons.scss +209 -0
  320. package/docs/themes/tanuki/sass/components/_code.scss +457 -0
  321. package/docs/themes/tanuki/sass/components/_landing.scss +633 -0
  322. package/docs/themes/tanuki/sass/components/_layout.scss +294 -0
  323. package/docs/themes/tanuki/sass/components/_navigation.scss +1200 -0
  324. package/docs/themes/tanuki/sass/components/_print.scss +237 -0
  325. package/docs/themes/tanuki/sass/components/_search.scss +224 -0
  326. package/docs/themes/tanuki/sass/components/_sidebar.scss +473 -0
  327. package/docs/themes/tanuki/sass/components/_theme-toggle.scss +186 -0
  328. package/docs/themes/tanuki/sass/modes/_blog.scss +366 -0
  329. package/docs/themes/tanuki/sass/modes/_product.scss +875 -0
  330. package/docs/themes/tanuki/sass/modes/_raskell.scss +1696 -0
  331. package/docs/themes/tanuki/sass/patterns/_buttons.scss +183 -0
  332. package/docs/themes/tanuki/sass/patterns/_cards.scss +144 -0
  333. package/docs/themes/tanuki/sass/patterns/_index.scss +9 -0
  334. package/docs/themes/tanuki/sass/patterns/_lists.scss +259 -0
  335. package/docs/themes/tanuki/sass/patterns/_sections.scss +243 -0
  336. package/docs/themes/tanuki/sass/style.scss +47 -0
  337. package/docs/themes/tanuki/sass/tokens/_colors.scss +139 -0
  338. package/docs/themes/tanuki/sass/tokens/_spacing.scss +100 -0
  339. package/docs/themes/tanuki/sass/tokens/_typography.scss +186 -0
  340. package/docs/themes/tanuki/screenshot.png +0 -0
  341. package/docs/themes/tanuki/sentinel.kdl +59 -0
  342. package/docs/themes/tanuki/static/elasticlunr.min.js +10 -0
  343. package/docs/themes/tanuki/static/fonts/GEIST-LICENSE.txt +92 -0
  344. package/docs/themes/tanuki/static/fonts/Geist-Variable.woff2 +0 -0
  345. package/docs/themes/tanuki/static/fonts/GeistMono-Variable.woff2 +0 -0
  346. package/docs/themes/tanuki/static/img/tanuki-icon.avif +0 -0
  347. package/docs/themes/tanuki/static/img/tanuki-icon.png +0 -0
  348. package/docs/themes/tanuki/static/js/anchors.js +18 -0
  349. package/docs/themes/tanuki/static/js/app.js +274 -0
  350. package/docs/themes/tanuki/static/js/code.js +394 -0
  351. package/docs/themes/tanuki/static/js/navigation.js +778 -0
  352. package/docs/themes/tanuki/static/js/scroll-to-top.js +33 -0
  353. package/docs/themes/tanuki/static/js/search-raskell.js +240 -0
  354. package/docs/themes/tanuki/static/js/search.js +215 -0
  355. package/docs/themes/tanuki/static/js/theme.js +169 -0
  356. package/docs/themes/tanuki/static/syntax-dark.css +151 -0
  357. package/docs/themes/tanuki/static/syntax-light.css +151 -0
  358. package/docs/themes/tanuki/static/wasm/sentinel_playground_wasm.js +486 -0
  359. package/docs/themes/tanuki/static/wasm/sentinel_playground_wasm_bg.wasm +0 -0
  360. package/docs/themes/tanuki/templates/404.html +52 -0
  361. package/docs/themes/tanuki/templates/base.html +428 -0
  362. package/docs/themes/tanuki/templates/blog.html +66 -0
  363. package/docs/themes/tanuki/templates/home.html +108 -0
  364. package/docs/themes/tanuki/templates/index.html +178 -0
  365. package/docs/themes/tanuki/templates/landing.html +168 -0
  366. package/docs/themes/tanuki/templates/macros/nav.html +128 -0
  367. package/docs/themes/tanuki/templates/macros/posts.html +101 -0
  368. package/docs/themes/tanuki/templates/macros/ui.html +159 -0
  369. package/docs/themes/tanuki/templates/page.html +135 -0
  370. package/docs/themes/tanuki/templates/partials/footer.html +38 -0
  371. package/docs/themes/tanuki/templates/partials/header.html +366 -0
  372. package/docs/themes/tanuki/templates/partials/nav-buttons.html +55 -0
  373. package/docs/themes/tanuki/templates/partials/nav-overlay.html +81 -0
  374. package/docs/themes/tanuki/templates/partials/page-toc-panel.html +43 -0
  375. package/docs/themes/tanuki/templates/partials/search.html +52 -0
  376. package/docs/themes/tanuki/templates/partials/sidebar.html +107 -0
  377. package/docs/themes/tanuki/templates/partials/theme-toggle.html +35 -0
  378. package/docs/themes/tanuki/templates/partials/toc-overlay.html +146 -0
  379. package/docs/themes/tanuki/templates/partials/version-picker.html +38 -0
  380. package/docs/themes/tanuki/templates/print.html +244 -0
  381. package/docs/themes/tanuki/templates/section.html +186 -0
  382. package/docs/themes/tanuki/templates/taxonomy_list.html +18 -0
  383. package/docs/themes/tanuki/templates/taxonomy_single.html +31 -0
  384. package/docs/themes/tanuki/theme.toml +58 -0
  385. package/examples/hello-agent.rs +55 -0
  386. package/package.json +36 -0
  387. package/proto/config.proto +60 -0
  388. package/proto/events.proto +0 -0
  389. package/proto/runtime.proto +215 -0
@@ -0,0 +1,237 @@
1
+ //! Channel runtime — orchestrates channels and routes messages to handlers.
2
+
3
+ use crate::traits::{Channel, ChannelMessage, SendMessage};
4
+ use async_trait::async_trait;
5
+ use std::sync::Arc;
6
+ use std::time::Duration;
7
+ use tokio::sync::{mpsc, Semaphore};
8
+ use tokio::task::JoinHandle;
9
+
10
+ const DEFAULT_MAX_CONCURRENT: usize = 4;
11
+ const DEFAULT_TIMEOUT_SECS: u64 = 300;
12
+ const TYPING_REFRESH_SECS: u64 = 4;
13
+ const BACKOFF_INITIAL_MS: u64 = 2000;
14
+ const BACKOFF_MAX_MS: u64 = 60000;
15
+
16
+ /// Handler for processing channel messages.
17
+ #[async_trait]
18
+ pub trait MessageHandler: Send + Sync {
19
+ /// Process a message and return the response.
20
+ async fn handle(&self, message: &ChannelMessage) -> anyhow::Result<String>;
21
+
22
+ async fn on_start(&self, _message: &ChannelMessage) {}
23
+ async fn on_complete(&self, _message: &ChannelMessage, _response: &str) {}
24
+ async fn on_error(&self, _message: &ChannelMessage, _error: &anyhow::Error) {}
25
+ }
26
+
27
+ /// Runtime configuration.
28
+ #[derive(Debug, Clone)]
29
+ pub struct RuntimeConfig {
30
+ pub max_concurrent: usize,
31
+ pub timeout_secs: u64,
32
+ pub show_typing: bool,
33
+ }
34
+
35
+ impl Default for RuntimeConfig {
36
+ fn default() -> Self {
37
+ Self {
38
+ max_concurrent: DEFAULT_MAX_CONCURRENT,
39
+ timeout_secs: DEFAULT_TIMEOUT_SECS,
40
+ show_typing: true,
41
+ }
42
+ }
43
+ }
44
+
45
+ /// Channel runtime — manages channels and message routing.
46
+ pub struct ChannelRuntime {
47
+ channels: Vec<Arc<dyn Channel>>,
48
+ handler: Arc<dyn MessageHandler>,
49
+ config: RuntimeConfig,
50
+ shutdown_tx: Option<mpsc::Sender<()>>,
51
+ }
52
+
53
+ impl ChannelRuntime {
54
+ pub fn new(handler: impl MessageHandler + 'static) -> Self {
55
+ Self {
56
+ channels: Vec::new(),
57
+ handler: Arc::new(handler),
58
+ config: RuntimeConfig::default(),
59
+ shutdown_tx: None,
60
+ }
61
+ }
62
+
63
+ pub fn with_config(handler: impl MessageHandler + 'static, config: RuntimeConfig) -> Self {
64
+ Self {
65
+ channels: Vec::new(),
66
+ handler: Arc::new(handler),
67
+ config,
68
+ shutdown_tx: None,
69
+ }
70
+ }
71
+
72
+ pub fn add_channel(mut self, channel: impl Channel + 'static) -> Self {
73
+ self.channels.push(Arc::new(channel));
74
+ self
75
+ }
76
+
77
+ pub fn add_channel_arc(mut self, channel: Arc<dyn Channel>) -> Self {
78
+ self.channels.push(channel);
79
+ self
80
+ }
81
+
82
+ /// Run all channels and process messages.
83
+ pub async fn run(&mut self) -> anyhow::Result<()> {
84
+ if self.channels.is_empty() {
85
+ anyhow::bail!("No channels registered");
86
+ }
87
+
88
+ let (shutdown_tx, mut shutdown_rx) = mpsc::channel::<()>(1);
89
+ self.shutdown_tx = Some(shutdown_tx);
90
+
91
+ let (msg_tx, mut msg_rx) = mpsc::channel::<ChannelMessage>(100);
92
+
93
+ // Spawn channel listeners
94
+ let mut handles: Vec<JoinHandle<()>> = Vec::new();
95
+ for channel in &self.channels {
96
+ let handle = spawn_supervised_listener(channel.clone(), msg_tx.clone());
97
+ handles.push(handle);
98
+ tracing::info!("Started listener for channel: {}", channel.name());
99
+ }
100
+
101
+ let semaphore = Arc::new(Semaphore::new(self.config.max_concurrent));
102
+
103
+ tracing::info!(
104
+ "Channel runtime started with {} channel(s)",
105
+ self.channels.len()
106
+ );
107
+
108
+ loop {
109
+ tokio::select! {
110
+ Some(message) = msg_rx.recv() => {
111
+ let permit = semaphore.clone().acquire_owned().await?;
112
+ let handler = self.handler.clone();
113
+ let channel = self.find_channel(&message.channel);
114
+ let config = self.config.clone();
115
+
116
+ tokio::spawn(async move {
117
+ let _permit = permit;
118
+ process_message(message, handler, channel, config).await;
119
+ });
120
+ }
121
+ _ = shutdown_rx.recv() => {
122
+ tracing::info!("Channel runtime shutting down");
123
+ break;
124
+ }
125
+ }
126
+ }
127
+
128
+ for handle in handles {
129
+ handle.abort();
130
+ }
131
+
132
+ Ok(())
133
+ }
134
+
135
+ pub fn shutdown(&self) {
136
+ if let Some(ref tx) = self.shutdown_tx {
137
+ let _ = tx.try_send(());
138
+ }
139
+ }
140
+
141
+ fn find_channel(&self, name: &str) -> Option<Arc<dyn Channel>> {
142
+ self.channels.iter().find(|c| c.name() == name).cloned()
143
+ }
144
+ }
145
+
146
+ fn spawn_supervised_listener(
147
+ channel: Arc<dyn Channel>,
148
+ tx: mpsc::Sender<ChannelMessage>,
149
+ ) -> JoinHandle<()> {
150
+ tokio::spawn(async move {
151
+ let mut attempt = 0u32;
152
+ loop {
153
+ let name = channel.name().to_string();
154
+ match channel.listen(tx.clone()).await {
155
+ Ok(()) => break,
156
+ Err(e) => {
157
+ attempt += 1;
158
+ let delay = (BACKOFF_INITIAL_MS as f64 * 2.0_f64.powi(attempt as i32 - 1)) as u64;
159
+ let delay = delay.min(BACKOFF_MAX_MS);
160
+ tracing::warn!("Channel {} failed: {}. Retrying in {}ms", name, e, delay);
161
+ tokio::time::sleep(Duration::from_millis(delay)).await;
162
+ }
163
+ }
164
+ }
165
+ })
166
+ }
167
+
168
+ async fn process_message(
169
+ message: ChannelMessage,
170
+ handler: Arc<dyn MessageHandler>,
171
+ channel: Option<Arc<dyn Channel>>,
172
+ config: RuntimeConfig,
173
+ ) {
174
+ let reply_target = message.reply_target.clone();
175
+
176
+ handler.on_start(&message).await;
177
+
178
+ // Typing indicator
179
+ let typing_handle = if config.show_typing {
180
+ channel.as_ref().map(|ch| {
181
+ let ch = ch.clone();
182
+ let target = reply_target.clone();
183
+ tokio::spawn(async move {
184
+ loop {
185
+ let _ = ch.start_typing(&target).await;
186
+ tokio::time::sleep(Duration::from_secs(TYPING_REFRESH_SECS)).await;
187
+ }
188
+ })
189
+ })
190
+ } else {
191
+ None
192
+ };
193
+
194
+ // Process with timeout
195
+ let timeout = Duration::from_secs(config.timeout_secs);
196
+ let result = tokio::time::timeout(timeout, handler.handle(&message)).await;
197
+
198
+ // Stop typing
199
+ if let Some(handle) = typing_handle {
200
+ handle.abort();
201
+ }
202
+ if let Some(ref ch) = channel {
203
+ let _ = ch.stop_typing(&reply_target).await;
204
+ }
205
+
206
+ // Send response
207
+ match result {
208
+ Ok(Ok(response)) => {
209
+ if let Some(ref ch) = channel {
210
+ let _ = ch.send(&SendMessage::new(&response, &reply_target)).await;
211
+ }
212
+ handler.on_complete(&message, &response).await;
213
+ }
214
+ Ok(Err(e)) => {
215
+ if let Some(ref ch) = channel {
216
+ let _ = ch.send(&SendMessage::new(format!("Error: {}", e), &reply_target)).await;
217
+ }
218
+ handler.on_error(&message, &e).await;
219
+ }
220
+ Err(_) => {
221
+ if let Some(ref ch) = channel {
222
+ let _ = ch.send(&SendMessage::new("Request timed out", &reply_target)).await;
223
+ }
224
+ handler.on_error(&message, &anyhow::anyhow!("Timeout")).await;
225
+ }
226
+ }
227
+ }
228
+
229
+ /// Echo handler for testing.
230
+ pub struct EchoHandler;
231
+
232
+ #[async_trait]
233
+ impl MessageHandler for EchoHandler {
234
+ async fn handle(&self, message: &ChannelMessage) -> anyhow::Result<String> {
235
+ Ok(format!("Echo: {}", message.content))
236
+ }
237
+ }
@@ -0,0 +1,5 @@
1
+ //! Security modules for channel authentication.
2
+
3
+ pub mod pairing;
4
+
5
+ pub use pairing::PairingGuard;
@@ -0,0 +1,205 @@
1
+ //! Pairing guard for secure channel authentication.
2
+ //!
3
+ //! Simplified from zeroclaw's pairing module.
4
+
5
+ use parking_lot::Mutex;
6
+ use sha2::{Digest, Sha256};
7
+ use std::collections::HashSet;
8
+ use std::time::{Duration, Instant};
9
+
10
+ /// Token prefix for generated tokens.
11
+ const TOKEN_PREFIX: &str = "enact_";
12
+
13
+ /// Maximum failed attempts before lockout.
14
+ const MAX_FAILED_ATTEMPTS: u32 = 5;
15
+
16
+ /// Lockout duration in seconds.
17
+ const LOCKOUT_DURATION_SECS: u64 = 60;
18
+
19
+ /// Generate a random pairing code.
20
+ fn generate_pairing_code() -> String {
21
+ use rand::Rng;
22
+ let mut rng = rand::thread_rng();
23
+ let code: String = (0..6).map(|_| rng.gen_range(0..10).to_string()).collect();
24
+ code
25
+ }
26
+
27
+ /// Hash a token using SHA-256.
28
+ fn hash_token(token: &str) -> String {
29
+ let mut hasher = Sha256::new();
30
+ hasher.update(token.as_bytes());
31
+ hex::encode(hasher.finalize())
32
+ }
33
+
34
+ /// Check if a string looks like a token hash (64 hex chars).
35
+ fn is_token_hash(s: &str) -> bool {
36
+ s.len() == 64 && s.chars().all(|c| c.is_ascii_hexdigit())
37
+ }
38
+
39
+ /// Pairing guard for secure authentication.
40
+ ///
41
+ /// Provides a simple pairing flow:
42
+ /// 1. Generate a pairing code on startup
43
+ /// 2. User sends the code via the channel
44
+ /// 3. A persistent token is issued and stored
45
+ #[derive(Debug)]
46
+ pub struct PairingGuard {
47
+ /// Whether pairing is required.
48
+ require_pairing: bool,
49
+ /// One-time pairing code.
50
+ pairing_code: Mutex<Option<String>>,
51
+ /// Set of hashed bearer tokens.
52
+ paired_tokens: Mutex<HashSet<String>>,
53
+ /// Brute-force protection: (failed_count, lockout_until).
54
+ failed_attempts: Mutex<(u32, Option<Instant>)>,
55
+ }
56
+
57
+ impl PairingGuard {
58
+ /// Create a new pairing guard.
59
+ pub fn new(require_pairing: bool, existing_tokens: &[String]) -> Self {
60
+ let tokens: HashSet<String> = existing_tokens
61
+ .iter()
62
+ .map(|t| {
63
+ if is_token_hash(t) {
64
+ t.clone()
65
+ } else {
66
+ hash_token(t)
67
+ }
68
+ })
69
+ .collect();
70
+
71
+ let code = if require_pairing && tokens.is_empty() {
72
+ Some(generate_pairing_code())
73
+ } else {
74
+ None
75
+ };
76
+
77
+ Self {
78
+ require_pairing,
79
+ pairing_code: Mutex::new(code),
80
+ paired_tokens: Mutex::new(tokens),
81
+ failed_attempts: Mutex::new((0, None)),
82
+ }
83
+ }
84
+
85
+ /// Get the current pairing code (if any).
86
+ pub fn pairing_code(&self) -> Option<String> {
87
+ self.pairing_code.lock().clone()
88
+ }
89
+
90
+ /// Check if a user is authorized (by user ID or token).
91
+ pub fn is_authorized(&self, user_id: &str, allowed_users: &[String]) -> bool {
92
+ // If pairing is not required, allow all
93
+ if !self.require_pairing {
94
+ return true;
95
+ }
96
+
97
+ // Check if user is in allowed list
98
+ if !allowed_users.is_empty() && !allowed_users.contains(&user_id.to_string()) {
99
+ return false;
100
+ }
101
+
102
+ // Check if any token is paired
103
+ !self.paired_tokens.lock().is_empty()
104
+ }
105
+
106
+ /// Attempt to pair with a code.
107
+ ///
108
+ /// Returns:
109
+ /// - `Ok(Some(token))` if pairing succeeded
110
+ /// - `Ok(None)` if the code was wrong
111
+ /// - `Err(lockout_secs)` if too many failed attempts
112
+ pub fn try_pair(&self, code: &str) -> Result<Option<String>, u64> {
113
+ // Check for lockout
114
+ {
115
+ let attempts = self.failed_attempts.lock();
116
+ if let Some(lockout_until) = attempts.1 {
117
+ if Instant::now() < lockout_until {
118
+ let remaining = lockout_until.duration_since(Instant::now()).as_secs();
119
+ return Err(remaining.max(1));
120
+ }
121
+ }
122
+ }
123
+
124
+ let mut pairing_code = self.pairing_code.lock();
125
+
126
+ if let Some(ref expected) = *pairing_code {
127
+ if code == expected {
128
+ // Reset failed attempts on success
129
+ *self.failed_attempts.lock() = (0, None);
130
+
131
+ // Generate a new token
132
+ let token = format!("{}{}", TOKEN_PREFIX, uuid::Uuid::new_v4());
133
+ let hash = hash_token(&token);
134
+
135
+ // Store the hash
136
+ self.paired_tokens.lock().insert(hash);
137
+
138
+ // Consume the pairing code
139
+ *pairing_code = None;
140
+
141
+ return Ok(Some(token));
142
+ }
143
+ }
144
+
145
+ // Track failed attempt
146
+ let mut attempts = self.failed_attempts.lock();
147
+ attempts.0 += 1;
148
+
149
+ if attempts.0 >= MAX_FAILED_ATTEMPTS {
150
+ let lockout_until = Instant::now() + Duration::from_secs(LOCKOUT_DURATION_SECS);
151
+ attempts.1 = Some(lockout_until);
152
+ return Err(LOCKOUT_DURATION_SECS);
153
+ }
154
+
155
+ Ok(None)
156
+ }
157
+
158
+ /// Check if a token is valid.
159
+ pub fn is_token_valid(&self, token: &str) -> bool {
160
+ let hash = hash_token(token);
161
+ self.paired_tokens.lock().contains(&hash)
162
+ }
163
+
164
+ /// Get paired tokens (hashed).
165
+ pub fn paired_tokens(&self) -> Vec<String> {
166
+ self.paired_tokens.lock().iter().cloned().collect()
167
+ }
168
+ }
169
+
170
+ impl Default for PairingGuard {
171
+ fn default() -> Self {
172
+ Self::new(false, &[])
173
+ }
174
+ }
175
+
176
+ #[cfg(test)]
177
+ mod tests {
178
+ use super::*;
179
+
180
+ #[test]
181
+ fn test_pairing_disabled() {
182
+ let guard = PairingGuard::new(false, &[]);
183
+ assert!(guard.is_authorized("any_user", &[]));
184
+ assert!(guard.pairing_code().is_none());
185
+ }
186
+
187
+ #[test]
188
+ fn test_pairing_flow() {
189
+ let guard = PairingGuard::new(true, &[]);
190
+ let code = guard.pairing_code().expect("should have code");
191
+
192
+ // Wrong code should fail
193
+ assert!(matches!(guard.try_pair("wrong"), Ok(None)));
194
+
195
+ // Correct code should succeed
196
+ let token = guard.try_pair(&code).expect("should not be locked").expect("should pair");
197
+ assert!(token.starts_with(TOKEN_PREFIX));
198
+
199
+ // Code should be consumed
200
+ assert!(guard.pairing_code().is_none());
201
+
202
+ // Token should be valid
203
+ assert!(guard.is_token_valid(&token));
204
+ }
205
+ }