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
package/Cargo.toml ADDED
@@ -0,0 +1,97 @@
1
+ [workspace]
2
+ resolver = "2"
3
+ members = [
4
+ "crates/enact-core",
5
+ "crates/enact-config",
6
+ "crates/enact-providers",
7
+ "crates/enact-runner",
8
+ "crates/enact-context",
9
+ "crates/enact-channels",
10
+ "crates/enact-memory",
11
+ "crates/enact-gateway",
12
+ "crates/enact-cli",
13
+ "crates/enact-skills",
14
+ "crates/enact-mcp",
15
+ "crates/enact-a2a",
16
+ "crates/enact-oauth",
17
+ "crates/enact-observability",
18
+ "crates/enact-cron",
19
+ "crates/enact-tools",
20
+ "crates/enact-security",
21
+ "crates/enact",
22
+ ]
23
+
24
+ [workspace.package]
25
+ version = "0.0.1"
26
+ edition = "2021"
27
+ license = "MIT"
28
+ repository = "https://github.com/adl-tan-theta/enactai"
29
+ homepage = "https://www.enactai.now"
30
+ keywords = ["ai", "agent", "llm", "gpt", "claude", "anthropic", "openai", "graph-native"]
31
+ categories = ["api-bindings", "asynchronous", "command-line-utilities"]
32
+
33
+ [workspace.dependencies]
34
+ # Async runtime
35
+ tokio = { version = "1", features = ["full"] }
36
+ tokio-util = "0.7"
37
+ tokio-stream = "0.1"
38
+ async-trait = "0.1"
39
+ async-stream = "0.3"
40
+ futures = "0.3"
41
+ futures-util = "0.3"
42
+
43
+ # Serialization
44
+ serde = { version = "1", features = ["derive"] }
45
+ serde_json = "1"
46
+ toml = "0.8"
47
+ serde_yaml = "0.9.34"
48
+
49
+ # HTTP
50
+ reqwest = { version = "0.12", features = ["json", "stream"] }
51
+
52
+ # Tracing
53
+ tracing = "0.1"
54
+ tracing-subscriber = "0.3"
55
+
56
+ # Utilities
57
+ uuid = { version = "1", features = ["v4", "serde"] }
58
+ svix-ksuid = "0.7"
59
+ chrono = { version = "0.4", features = ["serde"] }
60
+ thiserror = "1"
61
+ anyhow = "1"
62
+ regex = "1.10"
63
+ once_cell = "1.19"
64
+ urlencoding = "2.1"
65
+ html-escape = "0.2"
66
+
67
+ dirs = "5.0"
68
+ rand = "0.8"
69
+ hex = "0.4"
70
+ dotenv = "0.15.0"
71
+ tiktoken-rs = "0.5"
72
+ tempfile = "3"
73
+ parking_lot = "0.12"
74
+
75
+ # Compression & Hashing
76
+ miniz_oxide = "0.8"
77
+ sha2 = "0.10"
78
+ aes-gcm = "0.10"
79
+
80
+ # Internal crates
81
+ enact-core = { path = "crates/enact-core" }
82
+ enact-config = { path = "crates/enact-config" }
83
+ enact-providers = { path = "crates/enact-providers" }
84
+ enact-runner = { path = "crates/enact-runner" }
85
+ enact-context = { path = "crates/enact-context" }
86
+ enact-channels = { path = "crates/enact-channels" }
87
+ enact-memory = { path = "crates/enact-memory" }
88
+ enact-gateway = { path = "crates/enact-gateway" }
89
+ enact-skills = { path = "crates/enact-skills" }
90
+ enact-mcp = { path = "crates/enact-mcp" }
91
+ enact-a2a = { path = "crates/enact-a2a" }
92
+ enact-oauth = { path = "crates/enact-oauth" }
93
+ enact-observability = { path = "crates/enact-observability" }
94
+ enact-cron = { path = "crates/enact-cron" }
95
+ enact-tools = { path = "crates/enact-tools" }
96
+ enact-security = { path = "crates/enact-security" }
97
+ enact = { path = "crates/enact" }
@@ -0,0 +1,27 @@
1
+ [package]
2
+ name = "enact"
3
+ version.workspace = true
4
+ edition.workspace = true
5
+ license.workspace = true
6
+ description = "Enact - Graph-Native AI agents (umbrella crate)"
7
+ repository.workspace = true
8
+ homepage.workspace = true
9
+ keywords = ["ai", "agent", "llm", "graph-native", "gpt", "claude"]
10
+ categories.workspace = true
11
+
12
+ [dependencies]
13
+ enact-core.workspace = true
14
+ enact-config.workspace = true
15
+ enact-providers.workspace = true
16
+ enact-runner.workspace = true
17
+ enact-context.workspace = true
18
+ enact-channels.workspace = true
19
+ enact-memory.workspace = true
20
+ enact-gateway.workspace = true
21
+ enact-skills.workspace = true
22
+ enact-mcp.workspace = true
23
+ enact-a2a.workspace = true
24
+ enact-oauth.workspace = true
25
+ enact-observability.workspace = true
26
+ enact-cron.workspace = true
27
+ enact-tools.workspace = true
@@ -0,0 +1,60 @@
1
+ //! Enact - Graph-Native AI Agents
2
+ //!
3
+ //! A modular, extensible AI agent framework with support for multiple LLM providers,
4
+ //! messaging channels, skills, and multi-agent communication.
5
+ //!
6
+ //! # Quick Start
7
+ //!
8
+ //! ```ignore
9
+ //! use enact::prelude::*;
10
+ //!
11
+ //! // Use any of the sub-crates
12
+ //! // - enact_core: Core agent runtime
13
+ //! // - enact_providers: LLM provider integrations
14
+ //! // - enact_channels: Messaging integrations (WhatsApp, Telegram, Teams)
15
+ //! // - enact_runner: Agent execution loop
16
+ //! // - and more...
17
+ //! ```
18
+ //!
19
+ //! # Crates
20
+ //!
21
+ //! | Crate | Description |
22
+ //! |-------|-------------|
23
+ //! | [`enact_core`] | Core agent runtime and graph execution |
24
+ //! | [`enact_providers`] | LLM provider integrations (OpenAI, Anthropic, Azure, etc.) |
25
+ //! | [`enact_runner`] | Robust agent loop with retries and compaction |
26
+ //! | [`enact_context`] | Context window management and token counting |
27
+ //! | [`enact_channels`] | Messaging channels (WhatsApp, Telegram, Teams) |
28
+ //! | [`enact_memory`] | Local-first memory backends |
29
+ //! | [`enact_gateway`] | HTTP gateway for webhooks |
30
+ //! | [`enact_skills`] | Skills system with TOML manifests |
31
+ //! | [`enact_mcp`] | Model Context Protocol client |
32
+ //! | [`enact_a2a`] | Agent-to-Agent protocol support |
33
+ //! | [`enact_oauth`] | OAuth authentication |
34
+ //! | [`enact_observability`] | Observability and telemetry |
35
+ //! | [`enact_cron`] | Cron scheduling for agents |
36
+ //! | [`enact_tools`] | Built-in tools for agents |
37
+
38
+ // Re-export all core crates
39
+ pub use enact_a2a;
40
+ pub use enact_channels;
41
+ pub use enact_config;
42
+ pub use enact_context;
43
+ pub use enact_core;
44
+ pub use enact_cron;
45
+ pub use enact_gateway;
46
+ pub use enact_mcp;
47
+ pub use enact_memory;
48
+ pub use enact_oauth;
49
+ pub use enact_observability;
50
+ pub use enact_providers;
51
+ pub use enact_runner;
52
+ pub use enact_skills;
53
+ pub use enact_tools;
54
+
55
+ /// Re-export commonly used types
56
+ pub mod prelude {
57
+ pub use enact_core::prelude::*;
58
+ pub use enact_providers::ModelProvider;
59
+ pub use enact_runner::DefaultAgentRunner;
60
+ }
@@ -0,0 +1,25 @@
1
+ [package]
2
+ name = "enact-a2a"
3
+ version.workspace = true
4
+ edition.workspace = true
5
+ license.workspace = true
6
+ description = "Multi-agent and A2A (Agent-to-Agent) protocol support for Enact"
7
+ repository.workspace = true
8
+ homepage.workspace = true
9
+ keywords = ["a2a", "multi-agent", "agent-to-agent", "protocol"]
10
+ categories.workspace = true
11
+
12
+ [dependencies]
13
+ enact-core.workspace = true
14
+ enact-providers.workspace = true
15
+ anyhow.workspace = true
16
+ async-trait.workspace = true
17
+ tokio.workspace = true
18
+ serde.workspace = true
19
+ serde_json.workspace = true
20
+ tracing.workspace = true
21
+ uuid.workspace = true
22
+ chrono = { workspace = true, features = ["serde"] }
23
+
24
+ [dev-dependencies]
25
+ tempfile.workspace = true
@@ -0,0 +1,411 @@
1
+ use anyhow::Result;
2
+ use enact_core::callable::Callable;
3
+ use enact_providers::{ModelProvider, OpenAICompatible};
4
+ use serde_json::json;
5
+ use std::collections::HashMap;
6
+ use std::sync::Arc;
7
+ use std::time::Duration;
8
+ use tracing::{debug, info, warn};
9
+
10
+ const DELEGATE_TIMEOUT_SECS: u64 = 120;
11
+
12
+ /// Configuration for a delegate agent
13
+ #[derive(Debug, Clone)]
14
+ pub struct DelegateAgentConfig {
15
+ pub provider: String,
16
+ pub model: String,
17
+ pub system_prompt: Option<String>,
18
+ pub api_key: Option<String>,
19
+ pub temperature: Option<f32>,
20
+ pub max_depth: u32,
21
+ }
22
+
23
+ impl Default for DelegateAgentConfig {
24
+ fn default() -> Self {
25
+ Self {
26
+ provider: "openai".to_string(),
27
+ model: "gpt-4o-mini".to_string(),
28
+ system_prompt: None,
29
+ api_key: None,
30
+ temperature: Some(0.7),
31
+ max_depth: 3,
32
+ }
33
+ }
34
+ }
35
+
36
+ /// Multi-Agent system that can delegate tasks to specialized agents
37
+ pub struct MultiAgentSystem {
38
+ agents: HashMap<String, DelegateAgentConfig>,
39
+ fallback_credential: Option<String>,
40
+ }
41
+
42
+ impl MultiAgentSystem {
43
+ pub fn new() -> Self {
44
+ Self {
45
+ agents: HashMap::new(),
46
+ fallback_credential: None,
47
+ }
48
+ }
49
+
50
+ pub fn with_agents(agents: HashMap<String, DelegateAgentConfig>) -> Self {
51
+ Self {
52
+ agents,
53
+ fallback_credential: None,
54
+ }
55
+ }
56
+
57
+ pub fn set_fallback_credential(&mut self, credential: String) {
58
+ self.fallback_credential = Some(credential);
59
+ }
60
+
61
+ pub fn register_agent(
62
+ &mut self,
63
+ name: impl Into<String>,
64
+ config: DelegateAgentConfig,
65
+ ) {
66
+ self.agents.insert(name.into(), config);
67
+ }
68
+
69
+ pub fn get_agent_names(&self) -> Vec<&str> {
70
+ self.agents.keys().map(|s| s.as_str()).collect()
71
+ }
72
+
73
+ /// Delegate a task to a specialized agent
74
+ pub async fn delegate(
75
+ &self,
76
+ agent_name: &str,
77
+ prompt: &str,
78
+ context: Option<&str>,
79
+ current_depth: u32,
80
+ ) -> Result<DelegateResult> {
81
+ let agent_name = agent_name.trim();
82
+ if agent_name.is_empty() {
83
+ anyhow::bail!("Agent name cannot be empty");
84
+ }
85
+
86
+ let prompt = prompt.trim();
87
+ if prompt.is_empty() {
88
+ anyhow::bail!("Prompt cannot be empty");
89
+ }
90
+
91
+ // Look up agent config
92
+ let config = self
93
+ .agents
94
+ .get(agent_name)
95
+ .ok_or_else(|| {
96
+ let available: Vec<&str> = self.agents.keys().map(|s| s.as_str()).collect();
97
+ anyhow::anyhow!(
98
+ "Unknown agent '{agent_name}'. Available agents: {}",
99
+ if available.is_empty() {
100
+ "(none configured)".to_string()
101
+ } else {
102
+ available.join(", ")
103
+ }
104
+ )
105
+ })?;
106
+
107
+ // Check recursion depth
108
+ if current_depth >= config.max_depth {
109
+ return Ok(DelegateResult {
110
+ success: false,
111
+ output: String::new(),
112
+ error: Some(format!(
113
+ "Delegation depth limit reached ({current_depth}/{}). Cannot delegate further to prevent infinite loops.",
114
+ config.max_depth
115
+ )),
116
+ agent: agent_name.to_string(),
117
+ provider: config.provider.clone(),
118
+ model: config.model.clone(),
119
+ });
120
+ }
121
+
122
+ info!(
123
+ "Delegating to agent '{}' ({}/{})",
124
+ agent_name, current_depth, config.max_depth
125
+ );
126
+
127
+ // Create provider for this agent
128
+ let api_key = config
129
+ .api_key
130
+ .clone()
131
+ .or_else(|| self.fallback_credential.clone());
132
+
133
+ let provider: Arc<dyn ModelProvider> = match config.provider.as_str() {
134
+ "openai" | "openai-compatible" => {
135
+ let base_url = std::env::var("OPENAI_BASE_URL")
136
+ .unwrap_or_else(|_| "https://api.openai.com".to_string());
137
+ Arc::new(OpenAICompatible::new(base_url, config.model.clone(), api_key))
138
+ }
139
+ _ => {
140
+ return Ok(DelegateResult {
141
+ success: false,
142
+ output: String::new(),
143
+ error: Some(format!(
144
+ "Unsupported provider '{}' for agent '{}'",
145
+ config.provider, agent_name
146
+ )),
147
+ agent: agent_name.to_string(),
148
+ provider: config.provider.clone(),
149
+ model: config.model.clone(),
150
+ });
151
+ }
152
+ };
153
+
154
+ // Build the full prompt
155
+ let full_prompt = if let Some(ctx) = context {
156
+ if ctx.trim().is_empty() {
157
+ prompt.to_string()
158
+ } else {
159
+ format!("[Context]\n{}\n\n[Task]\n{}", ctx, prompt)
160
+ }
161
+ } else {
162
+ prompt.to_string()
163
+ };
164
+
165
+ // Execute with timeout
166
+ let temperature = config.temperature.unwrap_or(0.7);
167
+ let result = tokio::time::timeout(
168
+ Duration::from_secs(DELEGATE_TIMEOUT_SECS),
169
+ execute_with_provider(provider, config.system_prompt.as_deref(), &full_prompt, temperature),
170
+ )
171
+ .await;
172
+
173
+ match result {
174
+ Ok(Ok(response)) => {
175
+ let output = if response.trim().is_empty() {
176
+ "[Empty response]".to_string()
177
+ } else {
178
+ response
179
+ };
180
+
181
+ Ok(DelegateResult {
182
+ success: true,
183
+ output: format!(
184
+ "[Agent '{}' ({}/{})]\n{}",
185
+ agent_name, config.provider, config.model, output
186
+ ),
187
+ error: None,
188
+ agent: agent_name.to_string(),
189
+ provider: config.provider.clone(),
190
+ model: config.model.clone(),
191
+ })
192
+ }
193
+ Ok(Err(e)) => Ok(DelegateResult {
194
+ success: false,
195
+ output: String::new(),
196
+ error: Some(format!("Agent '{}' failed: {}", agent_name, e)),
197
+ agent: agent_name.to_string(),
198
+ provider: config.provider.clone(),
199
+ model: config.model.clone(),
200
+ }),
201
+ Err(_) => Ok(DelegateResult {
202
+ success: false,
203
+ output: String::new(),
204
+ error: Some(format!(
205
+ "Agent '{}' timed out after {}s",
206
+ agent_name, DELEGATE_TIMEOUT_SECS
207
+ )),
208
+ agent: agent_name.to_string(),
209
+ provider: config.provider.clone(),
210
+ model: config.model.clone(),
211
+ }),
212
+ }
213
+ }
214
+ }
215
+
216
+ impl Default for MultiAgentSystem {
217
+ fn default() -> Self {
218
+ Self::new()
219
+ }
220
+ }
221
+
222
+ async fn execute_with_provider(
223
+ provider: Arc<dyn ModelProvider>,
224
+ system_prompt: Option<&str>,
225
+ prompt: &str,
226
+ temperature: f32,
227
+ ) -> Result<String> {
228
+ use enact_core::providers::{ChatMessage, ChatRequest};
229
+
230
+ let messages = if let Some(system) = system_prompt {
231
+ vec![
232
+ ChatMessage::system(system),
233
+ ChatMessage::user(prompt),
234
+ ]
235
+ } else {
236
+ vec![ChatMessage::user(prompt)]
237
+ };
238
+
239
+ let request = ChatRequest {
240
+ messages,
241
+ max_tokens: Some(4096),
242
+ temperature: Some(temperature),
243
+ };
244
+
245
+ let response = provider.chat(request).await?;
246
+
247
+ Ok(response
248
+ .choices
249
+ .first()
250
+ .map(|c| c.message.content.clone())
251
+ .unwrap_or_default())
252
+ }
253
+
254
+ /// Result of a delegation operation
255
+ #[derive(Debug, Clone)]
256
+ pub struct DelegateResult {
257
+ pub success: bool,
258
+ pub output: String,
259
+ pub error: Option<String>,
260
+ pub agent: String,
261
+ pub provider: String,
262
+ pub model: String,
263
+ }
264
+
265
+ /// A2A Message for agent-to-agent communication
266
+ #[derive(Debug, Clone)]
267
+ pub struct A2aMessage {
268
+ pub from_agent: String,
269
+ pub to_agent: String,
270
+ pub message_type: A2aMessageType,
271
+ pub payload: String,
272
+ pub timestamp: chrono::DateTime<chrono::Utc>,
273
+ }
274
+
275
+ #[derive(Debug, Clone)]
276
+ pub enum A2aMessageType {
277
+ Request,
278
+ Response,
279
+ Event,
280
+ Error,
281
+ }
282
+
283
+ /// Agent registry for discovering and managing agents
284
+ pub struct AgentRegistry {
285
+ agents: HashMap<String, AgentInfo>,
286
+ }
287
+
288
+ #[derive(Debug, Clone)]
289
+ pub struct AgentInfo {
290
+ pub name: String,
291
+ pub description: String,
292
+ pub capabilities: Vec<String>,
293
+ pub endpoint: Option<String>,
294
+ }
295
+
296
+ impl AgentRegistry {
297
+ pub fn new() -> Self {
298
+ Self {
299
+ agents: HashMap::new(),
300
+ }
301
+ }
302
+
303
+ pub fn register(&mut self,
304
+ name: impl Into<String>,
305
+ description: impl Into<String>,
306
+ capabilities: Vec<String>,
307
+ endpoint: Option<String>,
308
+ ) {
309
+ let name = name.into();
310
+ self.agents.insert(
311
+ name.clone(),
312
+ AgentInfo {
313
+ name,
314
+ description: description.into(),
315
+ capabilities,
316
+ endpoint,
317
+ },
318
+ );
319
+ }
320
+
321
+ pub fn find_by_capability(&self,
322
+ capability: &str) -> Vec<&AgentInfo> {
323
+ self.agents
324
+ .values()
325
+ .filter(|agent| agent.capabilities.contains(&capability.to_string()))
326
+ .collect()
327
+ }
328
+
329
+ pub fn get(&self, name: &str) -> Option<&AgentInfo> {
330
+ self.agents.get(name)
331
+ }
332
+
333
+ pub fn list(&self) -> Vec<&AgentInfo> {
334
+ self.agents.values().collect()
335
+ }
336
+ }
337
+
338
+ impl Default for AgentRegistry {
339
+ fn default() -> Self {
340
+ Self::new()
341
+ }
342
+ }
343
+
344
+ #[cfg(test)]
345
+ mod tests {
346
+ use super::*;
347
+
348
+ #[test]
349
+ fn test_multi_agent_system_empty() {
350
+ let system = MultiAgentSystem::new();
351
+ assert!(system.get_agent_names().is_empty());
352
+ }
353
+
354
+ #[test]
355
+ fn test_register_agent() {
356
+ let mut system = MultiAgentSystem::new();
357
+ system.register_agent(
358
+ "researcher",
359
+ DelegateAgentConfig {
360
+ provider: "openai".to_string(),
361
+ model: "gpt-4".to_string(),
362
+ system_prompt: Some("You are a research assistant.".to_string()),
363
+ api_key: None,
364
+ temperature: Some(0.3),
365
+ max_depth: 3,
366
+ },
367
+ );
368
+
369
+ let names = system.get_agent_names();
370
+ assert_eq!(names.len(), 1);
371
+ assert_eq!(names[0], "researcher");
372
+ }
373
+
374
+ #[test]
375
+ fn test_agent_registry() {
376
+ let mut registry = AgentRegistry::new();
377
+ registry.register(
378
+ "coder",
379
+ "Writes code",
380
+ vec!["coding".to_string(), "rust".to_string()],
381
+ None,
382
+ );
383
+
384
+ let coders = registry.find_by_capability("coding");
385
+ assert_eq!(coders.len(), 1);
386
+ assert_eq!(coders[0].name, "coder");
387
+ }
388
+
389
+ #[tokio::test]
390
+ async fn test_delegate_unknown_agent() {
391
+ let system = MultiAgentSystem::new();
392
+ let result = system.delegate("unknown", "test", None, 0).await;
393
+ assert!(result.is_err());
394
+ }
395
+
396
+ #[tokio::test]
397
+ async fn test_delegate_depth_limit() {
398
+ let mut system = MultiAgentSystem::new();
399
+ system.register_agent(
400
+ "test",
401
+ DelegateAgentConfig {
402
+ max_depth: 2,
403
+ ..Default::default()
404
+ },
405
+ );
406
+
407
+ let result = system.delegate("test", "prompt", None, 2).await.unwrap();
408
+ assert!(!result.success);
409
+ assert!(result.error.unwrap().contains("depth limit"));
410
+ }
411
+ }
@@ -0,0 +1,64 @@
1
+ [package]
2
+ name = "enact-channels"
3
+ version.workspace = true
4
+ edition.workspace = true
5
+ license.workspace = true
6
+ description = "Channel integrations for Enact — Telegram, Teams, and extensible messaging"
7
+ repository.workspace = true
8
+ homepage.workspace = true
9
+ keywords = ["telegram", "teams", "whatsapp", "messaging", "webhook"]
10
+ categories.workspace = true
11
+
12
+ [dependencies]
13
+ # Internal crates
14
+ enact-core = { workspace = true }
15
+ enact-runner = { workspace = true }
16
+ enact-config = { workspace = true }
17
+
18
+ # Async runtime
19
+ tokio.workspace = true
20
+ async-trait.workspace = true
21
+ futures.workspace = true
22
+
23
+ # Serialization
24
+ serde.workspace = true
25
+ serde_json.workspace = true
26
+ toml.workspace = true
27
+
28
+ # HTTP
29
+ reqwest = { workspace = true, features = ["multipart"] }
30
+
31
+ # Logging
32
+ tracing.workspace = true
33
+
34
+ # Error handling
35
+ anyhow.workspace = true
36
+ thiserror.workspace = true
37
+
38
+ # Utilities
39
+ chrono.workspace = true
40
+ uuid.workspace = true
41
+ regex.workspace = true
42
+ dirs = "5.0"
43
+ directories = "5.0"
44
+ parking_lot = "0.12"
45
+
46
+ # Crypto for webhook verification
47
+ hmac = "0.12"
48
+ sha2.workspace = true
49
+ rand.workspace = true
50
+ hex.workspace = true
51
+
52
+ # Web server for webhooks (Teams)
53
+ axum = "0.7"
54
+ tower = "0.4"
55
+ tower-http = { version = "0.5", features = ["cors", "trace"] }
56
+
57
+ [dev-dependencies]
58
+ tokio = { workspace = true, features = ["test-util", "macros"] }
59
+ tempfile.workspace = true
60
+ tracing-subscriber = { workspace = true, features = ["env-filter"] }
61
+
62
+ [[example]]
63
+ name = "channel_bot"
64
+ path = "examples/channel_bot.rs"