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,534 @@
1
+ //! Loop Flow - Iteration with exit condition
2
+ //!
3
+ //! Repeatedly execute a callable until an exit condition is met.
4
+
5
+ use crate::callable::Callable;
6
+ use std::sync::Arc;
7
+
8
+ /// Loop exit condition
9
+ pub enum LoopCondition {
10
+ /// Fixed number of iterations
11
+ MaxIterations(usize),
12
+ /// Output matches predicate
13
+ OutputMatches(Box<dyn Fn(&str) -> bool + Send + Sync>),
14
+ /// Output contains string
15
+ OutputContains(String),
16
+ /// Combined: max iterations OR output matches
17
+ Either {
18
+ max_iterations: usize,
19
+ predicate: Box<dyn Fn(&str) -> bool + Send + Sync>,
20
+ },
21
+ }
22
+
23
+ impl LoopCondition {
24
+ /// Check if loop should exit
25
+ pub fn should_exit(&self, iteration: usize, output: &str) -> bool {
26
+ match self {
27
+ LoopCondition::MaxIterations(max) => iteration >= *max,
28
+ LoopCondition::OutputMatches(pred) => pred(output),
29
+ LoopCondition::OutputContains(needle) => output.contains(needle),
30
+ LoopCondition::Either {
31
+ max_iterations,
32
+ predicate,
33
+ } => iteration >= *max_iterations || predicate(output),
34
+ }
35
+ }
36
+
37
+ /// Create a max iterations condition
38
+ pub fn max(n: usize) -> Self {
39
+ LoopCondition::MaxIterations(n)
40
+ }
41
+
42
+ /// Create an output contains condition
43
+ pub fn until_contains(s: impl Into<String>) -> Self {
44
+ LoopCondition::OutputContains(s.into())
45
+ }
46
+
47
+ /// Create a predicate condition
48
+ pub fn until(pred: impl Fn(&str) -> bool + Send + Sync + 'static) -> Self {
49
+ LoopCondition::OutputMatches(Box::new(pred))
50
+ }
51
+
52
+ /// Create a combined condition
53
+ pub fn max_or_until(
54
+ max: usize,
55
+ pred: impl Fn(&str) -> bool + Send + Sync + 'static,
56
+ ) -> Self {
57
+ LoopCondition::Either {
58
+ max_iterations: max,
59
+ predicate: Box::new(pred),
60
+ }
61
+ }
62
+ }
63
+
64
+ /// Loop execution flow
65
+ pub struct LoopFlow<C: Callable> {
66
+ /// The callable to execute repeatedly
67
+ callable: Arc<C>,
68
+ /// Exit condition
69
+ condition: LoopCondition,
70
+ /// Flow name
71
+ name: String,
72
+ /// Whether to pass previous output as input (feedback loop)
73
+ feedback: bool,
74
+ }
75
+
76
+ impl<C: Callable> LoopFlow<C> {
77
+ /// Create a new loop flow
78
+ pub fn new(name: impl Into<String>, callable: Arc<C>, condition: LoopCondition) -> Self {
79
+ Self {
80
+ callable,
81
+ condition,
82
+ name: name.into(),
83
+ feedback: true, // Default: use output as next input
84
+ }
85
+ }
86
+
87
+ /// Create a loop that runs N times
88
+ pub fn times(name: impl Into<String>, n: usize, callable: Arc<C>) -> Self {
89
+ Self::new(name, callable, LoopCondition::MaxIterations(n))
90
+ }
91
+
92
+ /// Create a loop that runs until output contains string
93
+ pub fn until_contains(
94
+ name: impl Into<String>,
95
+ s: impl Into<String>,
96
+ callable: Arc<C>,
97
+ ) -> Self {
98
+ Self::new(name, callable, LoopCondition::OutputContains(s.into()))
99
+ }
100
+
101
+ /// Set whether to use output as next input
102
+ pub fn with_feedback(mut self, feedback: bool) -> Self {
103
+ self.feedback = feedback;
104
+ self
105
+ }
106
+
107
+ /// Execute the loop
108
+ pub async fn execute(&self, input: &str) -> anyhow::Result<String> {
109
+ let mut current_input = input.to_string();
110
+ let mut iteration = 0;
111
+
112
+ loop {
113
+ let output = self.callable.run(&current_input).await?;
114
+
115
+ if self.condition.should_exit(iteration, &output) {
116
+ return Ok(output);
117
+ }
118
+
119
+ // Prepare next iteration
120
+ if self.feedback {
121
+ current_input = output;
122
+ }
123
+ iteration += 1;
124
+ }
125
+ }
126
+
127
+ /// Execute with iteration tracking
128
+ pub async fn execute_with_history(&self, input: &str) -> anyhow::Result<LoopHistory> {
129
+ let mut current_input = input.to_string();
130
+ let mut iteration = 0;
131
+ let mut outputs = Vec::new();
132
+
133
+ loop {
134
+ let output = self.callable.run(&current_input).await?;
135
+ outputs.push(output.clone());
136
+
137
+ if self.condition.should_exit(iteration, &output) {
138
+ return Ok(LoopHistory {
139
+ iterations: iteration + 1,
140
+ outputs,
141
+ final_output: output,
142
+ });
143
+ }
144
+
145
+ if self.feedback {
146
+ current_input = output;
147
+ }
148
+ iteration += 1;
149
+ }
150
+ }
151
+
152
+ /// Get the flow name
153
+ pub fn name(&self) -> &str {
154
+ &self.name
155
+ }
156
+ }
157
+
158
+ /// History of a loop execution
159
+ #[derive(Debug)]
160
+ pub struct LoopHistory {
161
+ /// Number of iterations executed
162
+ pub iterations: usize,
163
+ /// Output from each iteration
164
+ pub outputs: Vec<String>,
165
+ /// Final output
166
+ pub final_output: String,
167
+ }
168
+
169
+ #[cfg(test)]
170
+ mod tests {
171
+ use super::*;
172
+ use async_trait::async_trait;
173
+ use std::sync::atomic::{AtomicUsize, Ordering};
174
+
175
+ /// Mock callable that tracks calls and transforms input
176
+ struct MockCallable {
177
+ name: String,
178
+ call_count: Arc<AtomicUsize>,
179
+ transform: Box<dyn Fn(&str, usize) -> String + Send + Sync>,
180
+ }
181
+
182
+ impl MockCallable {
183
+ fn new(
184
+ name: &str,
185
+ transform: impl Fn(&str, usize) -> String + Send + Sync + 'static,
186
+ ) -> Self {
187
+ Self {
188
+ name: name.to_string(),
189
+ call_count: Arc::new(AtomicUsize::new(0)),
190
+ transform: Box::new(transform),
191
+ }
192
+ }
193
+
194
+ /// Simple incrementing callable - appends iteration count
195
+ fn incrementing(name: &str) -> Self {
196
+ Self::new(name, |input, n| format!("{}:{}", input, n))
197
+ }
198
+
199
+ /// Callable that emits "DONE" on the Nth call
200
+ fn done_on_call(name: &str, n: usize) -> Self {
201
+ Self::new(name, move |input, call| {
202
+ if call >= n - 1 {
203
+ "DONE".to_string()
204
+ } else {
205
+ format!("{}:{}", input, call)
206
+ }
207
+ })
208
+ }
209
+
210
+ fn get_call_count(&self) -> usize {
211
+ self.call_count.load(Ordering::SeqCst)
212
+ }
213
+ }
214
+
215
+ #[async_trait]
216
+ impl Callable for MockCallable {
217
+ fn name(&self) -> &str {
218
+ &self.name
219
+ }
220
+
221
+ async fn run(&self, input: &str) -> anyhow::Result<String> {
222
+ let n = self.call_count.fetch_add(1, Ordering::SeqCst);
223
+ Ok((self.transform)(input, n))
224
+ }
225
+ }
226
+
227
+ // ============ LoopCondition Tests ============
228
+
229
+ #[test]
230
+ fn test_condition_max_iterations() {
231
+ let cond = LoopCondition::MaxIterations(3);
232
+ assert!(!cond.should_exit(0, "any"));
233
+ assert!(!cond.should_exit(1, "any"));
234
+ assert!(!cond.should_exit(2, "any"));
235
+ assert!(cond.should_exit(3, "any")); // Exit at iteration 3
236
+ assert!(cond.should_exit(5, "any")); // Also exit if past
237
+ }
238
+
239
+ #[test]
240
+ fn test_condition_output_matches() {
241
+ let cond = LoopCondition::OutputMatches(Box::new(|s| s.len() > 5));
242
+ assert!(!cond.should_exit(0, "hi"));
243
+ assert!(!cond.should_exit(10, "short"));
244
+ assert!(cond.should_exit(0, "longer"));
245
+ assert!(cond.should_exit(0, "this is long enough"));
246
+ }
247
+
248
+ #[test]
249
+ fn test_condition_output_contains() {
250
+ let cond = LoopCondition::OutputContains("DONE".to_string());
251
+ assert!(!cond.should_exit(0, "not yet"));
252
+ assert!(!cond.should_exit(5, "still working"));
253
+ assert!(cond.should_exit(0, "DONE"));
254
+ assert!(cond.should_exit(0, "task DONE here"));
255
+ }
256
+
257
+ #[test]
258
+ fn test_condition_either() {
259
+ let cond = LoopCondition::Either {
260
+ max_iterations: 5,
261
+ predicate: Box::new(|s| s.contains("STOP")),
262
+ };
263
+
264
+ // Not exit before max or predicate
265
+ assert!(!cond.should_exit(0, "working"));
266
+ assert!(!cond.should_exit(4, "still going"));
267
+
268
+ // Exit at max iterations
269
+ assert!(cond.should_exit(5, "working"));
270
+
271
+ // Exit when predicate matches, even before max
272
+ assert!(cond.should_exit(2, "STOP now"));
273
+ }
274
+
275
+ #[test]
276
+ fn test_condition_helpers() {
277
+ // max()
278
+ let cond = LoopCondition::max(2);
279
+ assert!(!cond.should_exit(1, "x"));
280
+ assert!(cond.should_exit(2, "x"));
281
+
282
+ // until_contains()
283
+ let cond = LoopCondition::until_contains("END");
284
+ assert!(!cond.should_exit(0, "not"));
285
+ assert!(cond.should_exit(0, "END"));
286
+
287
+ // until()
288
+ let cond = LoopCondition::until(|s| s == "target");
289
+ assert!(!cond.should_exit(0, "other"));
290
+ assert!(cond.should_exit(0, "target"));
291
+
292
+ // max_or_until()
293
+ let cond = LoopCondition::max_or_until(3, |s| s.starts_with("!"));
294
+ assert!(!cond.should_exit(0, "a"));
295
+ assert!(cond.should_exit(3, "a")); // max hit
296
+ assert!(cond.should_exit(0, "!bang")); // predicate hit
297
+ }
298
+
299
+ // ============ LoopFlow Construction Tests ============
300
+
301
+ #[tokio::test]
302
+ async fn test_loop_flow_new() {
303
+ let callable = Arc::new(MockCallable::incrementing("inc"));
304
+ let flow = LoopFlow::new("test_loop", callable, LoopCondition::MaxIterations(2));
305
+ assert_eq!(flow.name(), "test_loop");
306
+ }
307
+
308
+ #[tokio::test]
309
+ async fn test_loop_flow_times() {
310
+ let callable = Arc::new(MockCallable::incrementing("inc"));
311
+ let flow = LoopFlow::times("timer", 3, callable);
312
+ assert_eq!(flow.name(), "timer");
313
+ }
314
+
315
+ #[tokio::test]
316
+ async fn test_loop_flow_until_contains() {
317
+ let callable = Arc::new(MockCallable::done_on_call("done", 2));
318
+ let flow = LoopFlow::until_contains("stopper", "DONE", callable);
319
+ assert_eq!(flow.name(), "stopper");
320
+ }
321
+
322
+ // ============ LoopFlow Execute Tests ============
323
+
324
+ #[tokio::test]
325
+ async fn test_loop_execute_max_iterations() {
326
+ let callable = Arc::new(MockCallable::incrementing("inc"));
327
+ let flow = LoopFlow::times("loop", 3, callable.clone());
328
+
329
+ let result = flow.execute("start").await.unwrap();
330
+ // With MaxIterations(3), exit condition is iteration >= 3
331
+ // iteration 0: run, check 0>=3=false, inc to 1
332
+ // iteration 1: run, check 1>=3=false, inc to 2
333
+ // iteration 2: run, check 2>=3=false, inc to 3
334
+ // iteration 3: run, check 3>=3=true, exit
335
+ // So 4 total calls
336
+ assert_eq!(callable.get_call_count(), 4);
337
+ assert!(result.contains("start"));
338
+ }
339
+
340
+ #[tokio::test]
341
+ async fn test_loop_execute_until_contains() {
342
+ let callable = Arc::new(MockCallable::done_on_call("done", 3));
343
+ let flow = LoopFlow::until_contains("wait_done", "DONE", callable.clone());
344
+
345
+ let result = flow.execute("input").await.unwrap();
346
+ assert_eq!(result, "DONE");
347
+ assert_eq!(callable.get_call_count(), 3);
348
+ }
349
+
350
+ #[tokio::test]
351
+ async fn test_loop_execute_with_predicate() {
352
+ let callable = Arc::new(MockCallable::new("counter", |_, n| format!("count:{}", n)));
353
+ let flow = LoopFlow::new(
354
+ "until_five",
355
+ callable.clone(),
356
+ LoopCondition::until(|s| s == "count:5"),
357
+ );
358
+
359
+ let result = flow.execute("x").await.unwrap();
360
+ assert_eq!(result, "count:5");
361
+ assert_eq!(callable.get_call_count(), 6); // 0,1,2,3,4,5
362
+ }
363
+
364
+ #[tokio::test]
365
+ async fn test_loop_execute_either_max_first() {
366
+ let callable = Arc::new(MockCallable::new("counter", |_, n| format!("v{}", n)));
367
+ let flow = LoopFlow::new(
368
+ "either",
369
+ callable.clone(),
370
+ LoopCondition::max_or_until(3, |s| s == "never"),
371
+ );
372
+
373
+ let result = flow.execute("x").await.unwrap();
374
+ // Exit at iteration >= 3, so 4 calls total
375
+ assert_eq!(callable.get_call_count(), 4);
376
+ assert_eq!(result, "v3");
377
+ }
378
+
379
+ #[tokio::test]
380
+ async fn test_loop_execute_either_predicate_first() {
381
+ let callable = Arc::new(MockCallable::done_on_call("done", 2));
382
+ let flow = LoopFlow::new(
383
+ "either",
384
+ callable.clone(),
385
+ LoopCondition::max_or_until(10, |s| s == "DONE"),
386
+ );
387
+
388
+ let result = flow.execute("x").await.unwrap();
389
+ assert_eq!(result, "DONE");
390
+ assert_eq!(callable.get_call_count(), 2); // Exit before max
391
+ }
392
+
393
+ // ============ Feedback Mode Tests ============
394
+
395
+ #[tokio::test]
396
+ async fn test_loop_with_feedback_enabled() {
397
+ // Track inputs to verify feedback
398
+ let inputs: Arc<std::sync::Mutex<Vec<String>>> = Arc::new(std::sync::Mutex::new(Vec::new()));
399
+ let inputs_clone = inputs.clone();
400
+
401
+ let callable = Arc::new(MockCallable::new("fb", move |input, n| {
402
+ inputs_clone.lock().unwrap().push(input.to_string());
403
+ format!("out{}", n)
404
+ }));
405
+
406
+ let flow = LoopFlow::times("feedback_on", 3, callable).with_feedback(true);
407
+ flow.execute("start").await.unwrap();
408
+
409
+ let recorded = inputs.lock().unwrap().clone();
410
+ // MaxIterations(3) runs 4 times (exits when iteration >= 3)
411
+ assert_eq!(recorded, vec!["start", "out0", "out1", "out2"]);
412
+ }
413
+
414
+ #[tokio::test]
415
+ async fn test_loop_with_feedback_disabled() {
416
+ let inputs: Arc<std::sync::Mutex<Vec<String>>> = Arc::new(std::sync::Mutex::new(Vec::new()));
417
+ let inputs_clone = inputs.clone();
418
+
419
+ let callable = Arc::new(MockCallable::new("no_fb", move |input, n| {
420
+ inputs_clone.lock().unwrap().push(input.to_string());
421
+ format!("out{}", n)
422
+ }));
423
+
424
+ let flow = LoopFlow::times("feedback_off", 3, callable).with_feedback(false);
425
+ flow.execute("same").await.unwrap();
426
+
427
+ let recorded = inputs.lock().unwrap().clone();
428
+ // Without feedback, input stays the same; MaxIterations(3) runs 4 times
429
+ assert_eq!(recorded, vec!["same", "same", "same", "same"]);
430
+ }
431
+
432
+ // ============ Execute with History Tests ============
433
+
434
+ #[tokio::test]
435
+ async fn test_loop_execute_with_history() {
436
+ let callable = Arc::new(MockCallable::new("hist", |_, n| format!("iter{}", n)));
437
+ let flow = LoopFlow::times("history_test", 4, callable);
438
+
439
+ let history = flow.execute_with_history("start").await.unwrap();
440
+
441
+ // MaxIterations(4) exits when iteration >= 4, so runs 5 times
442
+ assert_eq!(history.iterations, 5);
443
+ assert_eq!(history.outputs.len(), 5);
444
+ assert_eq!(history.outputs, vec!["iter0", "iter1", "iter2", "iter3", "iter4"]);
445
+ assert_eq!(history.final_output, "iter4");
446
+ }
447
+
448
+ #[tokio::test]
449
+ async fn test_loop_execute_with_history_early_exit() {
450
+ let callable = Arc::new(MockCallable::done_on_call("early", 2));
451
+ let flow = LoopFlow::until_contains("early_exit", "DONE", callable);
452
+
453
+ let history = flow.execute_with_history("x").await.unwrap();
454
+
455
+ assert_eq!(history.iterations, 2);
456
+ assert_eq!(history.outputs.len(), 2);
457
+ assert_eq!(history.final_output, "DONE");
458
+ }
459
+
460
+ // ============ Error Handling Tests ============
461
+
462
+ #[tokio::test]
463
+ async fn test_loop_error_propagation() {
464
+ struct FailingCallable {
465
+ fail_on: usize,
466
+ call_count: Arc<AtomicUsize>,
467
+ }
468
+
469
+ #[async_trait]
470
+ impl Callable for FailingCallable {
471
+ fn name(&self) -> &str {
472
+ "failing"
473
+ }
474
+
475
+ async fn run(&self, _input: &str) -> anyhow::Result<String> {
476
+ let n = self.call_count.fetch_add(1, Ordering::SeqCst);
477
+ if n >= self.fail_on {
478
+ anyhow::bail!("Intentional failure at iteration {}", n)
479
+ }
480
+ Ok(format!("ok{}", n))
481
+ }
482
+ }
483
+
484
+ let callable = Arc::new(FailingCallable {
485
+ fail_on: 2,
486
+ call_count: Arc::new(AtomicUsize::new(0)),
487
+ });
488
+
489
+ let flow = LoopFlow::times("fail_loop", 5, callable);
490
+ let result = flow.execute("start").await;
491
+
492
+ assert!(result.is_err());
493
+ assert!(result.unwrap_err().to_string().contains("Intentional failure"));
494
+ }
495
+
496
+ // ============ Edge Cases ============
497
+
498
+ #[tokio::test]
499
+ async fn test_loop_zero_iterations() {
500
+ let callable = Arc::new(MockCallable::incrementing("zero"));
501
+ let flow = LoopFlow::times("zero_loop", 0, callable.clone());
502
+
503
+ // With max 0, should_exit returns true on iteration 0
504
+ // So we run once and immediately exit
505
+ let result = flow.execute("input").await.unwrap();
506
+ assert_eq!(callable.get_call_count(), 1);
507
+ assert!(result.contains("input"));
508
+ }
509
+
510
+ #[tokio::test]
511
+ async fn test_loop_immediate_exit_predicate() {
512
+ let callable = Arc::new(MockCallable::new("imm", |_, _| "STOP".to_string()));
513
+ let flow = LoopFlow::new(
514
+ "immediate",
515
+ callable.clone(),
516
+ LoopCondition::until_contains("STOP"),
517
+ );
518
+
519
+ let result = flow.execute("x").await.unwrap();
520
+ assert_eq!(result, "STOP");
521
+ assert_eq!(callable.get_call_count(), 1);
522
+ }
523
+
524
+ #[tokio::test]
525
+ async fn test_loop_single_iteration() {
526
+ let callable = Arc::new(MockCallable::incrementing("single"));
527
+ let flow = LoopFlow::times("one", 1, callable.clone());
528
+
529
+ let history = flow.execute_with_history("x").await.unwrap();
530
+ // MaxIterations(1) exits when iteration >= 1, so runs 2 times
531
+ assert_eq!(history.iterations, 2);
532
+ assert_eq!(callable.get_call_count(), 2);
533
+ }
534
+ }