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.
- package/.env.example +20 -0
- package/.github/workflows/ci.yml +70 -0
- package/.github/workflows/publish.yml +250 -0
- package/.gitmodules +3 -0
- package/Cargo.lock +3584 -0
- package/Cargo.toml +97 -0
- package/crates/enact/Cargo.toml +27 -0
- package/crates/enact/src/lib.rs +60 -0
- package/crates/enact-a2a/Cargo.toml +25 -0
- package/crates/enact-a2a/src/lib.rs +411 -0
- package/crates/enact-channels/Cargo.toml +64 -0
- package/crates/enact-channels/examples/README.md +80 -0
- package/crates/enact-channels/examples/channel_bot.rs +169 -0
- package/crates/enact-channels/examples/telegram-echo.rs +34 -0
- package/crates/enact-channels/examples/whatsapp-echo.rs +142 -0
- package/crates/enact-channels/src/config.rs +213 -0
- package/crates/enact-channels/src/lib.rs +25 -0
- package/crates/enact-channels/src/runtime.rs +237 -0
- package/crates/enact-channels/src/security/mod.rs +5 -0
- package/crates/enact-channels/src/security/pairing.rs +205 -0
- package/crates/enact-channels/src/teams.rs +601 -0
- package/crates/enact-channels/src/telegram.rs +2833 -0
- package/crates/enact-channels/src/traits.rs +200 -0
- package/crates/enact-channels/src/webhook.rs +262 -0
- package/crates/enact-channels/src/whatsapp.rs +310 -0
- package/crates/enact-cli/Cargo.toml +40 -0
- package/crates/enact-cli/src/commands/doctor.rs +62 -0
- package/crates/enact-cli/src/commands/mod.rs +3 -0
- package/crates/enact-cli/src/commands/run.rs +69 -0
- package/crates/enact-cli/src/commands/serve.rs +81 -0
- package/crates/enact-cli/src/config.rs +2 -0
- package/crates/enact-cli/src/main.rs +79 -0
- package/crates/enact-config/Cargo.toml +36 -0
- package/crates/enact-config/ENV_VAR_MAPPING.md +135 -0
- package/crates/enact-config/QUICK_REFERENCE.md +92 -0
- package/crates/enact-config/README.md +107 -0
- package/crates/enact-config/TESTING.md +161 -0
- package/crates/enact-config/examples/test-env-vars.rs +100 -0
- package/crates/enact-config/src/config.rs +399 -0
- package/crates/enact-config/src/encrypted_store.rs +211 -0
- package/crates/enact-config/src/lib.rs +298 -0
- package/crates/enact-config/src/secrets.rs +149 -0
- package/crates/enact-config/src/sync.rs +260 -0
- package/crates/enact-config/test-env-vars.sh +34 -0
- package/crates/enact-config/tests/README.md +99 -0
- package/crates/enact-config/tests/config_integration_test.rs +202 -0
- package/crates/enact-config/tests/security_test.rs +140 -0
- package/crates/enact-context/Cargo.toml +41 -0
- package/crates/enact-context/src/budget.rs +314 -0
- package/crates/enact-context/src/calibrator.rs +535 -0
- package/crates/enact-context/src/compactor.rs +392 -0
- package/crates/enact-context/src/condenser.rs +826 -0
- package/crates/enact-context/src/lib.rs +94 -0
- package/crates/enact-context/src/segment.rs +238 -0
- package/crates/enact-context/src/step_context.rs +645 -0
- package/crates/enact-context/src/token_counter.rs +148 -0
- package/crates/enact-context/src/window.rs +372 -0
- package/crates/enact-core/Cargo.toml +42 -0
- package/crates/enact-core/README.md +98 -0
- package/crates/enact-core/src/background/executor.rs +524 -0
- package/crates/enact-core/src/background/mod.rs +48 -0
- package/crates/enact-core/src/background/target_binding.rs +390 -0
- package/crates/enact-core/src/background/trigger.rs +511 -0
- package/crates/enact-core/src/callable/callable.rs +152 -0
- package/crates/enact-core/src/callable/composite.rs +817 -0
- package/crates/enact-core/src/callable/graph.rs +104 -0
- package/crates/enact-core/src/callable/llm.rs +211 -0
- package/crates/enact-core/src/callable/mod.rs +64 -0
- package/crates/enact-core/src/callable/registry.rs +206 -0
- package/crates/enact-core/src/context/execution_context.rs +757 -0
- package/crates/enact-core/src/context/invocation.rs +99 -0
- package/crates/enact-core/src/context/mod.rs +50 -0
- package/crates/enact-core/src/context/tenant.rs +175 -0
- package/crates/enact-core/src/context/trace.rs +127 -0
- package/crates/enact-core/src/flow/conditional.rs +293 -0
- package/crates/enact-core/src/flow/mod.rs +43 -0
- package/crates/enact-core/src/flow/parallel.rs +437 -0
- package/crates/enact-core/src/flow/repeat.rs +534 -0
- package/crates/enact-core/src/flow/sequential.rs +248 -0
- package/crates/enact-core/src/graph/checkpoint.rs +79 -0
- package/crates/enact-core/src/graph/checkpoint_store.rs +76 -0
- package/crates/enact-core/src/graph/compiled.rs +189 -0
- package/crates/enact-core/src/graph/edge.rs +59 -0
- package/crates/enact-core/src/graph/graph_schema.rs +218 -0
- package/crates/enact-core/src/graph/loader.rs +155 -0
- package/crates/enact-core/src/graph/mod.rs +18 -0
- package/crates/enact-core/src/graph/node/function.rs +49 -0
- package/crates/enact-core/src/graph/node/mod.rs +48 -0
- package/crates/enact-core/src/graph/schema.rs +62 -0
- package/crates/enact-core/src/inbox/message.rs +405 -0
- package/crates/enact-core/src/inbox/mod.rs +31 -0
- package/crates/enact-core/src/inbox/store.rs +355 -0
- package/crates/enact-core/src/kernel/artifact/filesystem.rs +546 -0
- package/crates/enact-core/src/kernel/artifact/metadata.rs +283 -0
- package/crates/enact-core/src/kernel/artifact/mod.rs +27 -0
- package/crates/enact-core/src/kernel/artifact/store.rs +427 -0
- package/crates/enact-core/src/kernel/enforcement.rs +1315 -0
- package/crates/enact-core/src/kernel/error.rs +1200 -0
- package/crates/enact-core/src/kernel/event.rs +1394 -0
- package/crates/enact-core/src/kernel/execution_model.rs +831 -0
- package/crates/enact-core/src/kernel/execution_state.rs +189 -0
- package/crates/enact-core/src/kernel/execution_strategy.rs +117 -0
- package/crates/enact-core/src/kernel/ids.rs +2086 -0
- package/crates/enact-core/src/kernel/interrupt.rs +125 -0
- package/crates/enact-core/src/kernel/kernel.rs +1283 -0
- package/crates/enact-core/src/kernel/mod.rs +205 -0
- package/crates/enact-core/src/kernel/persistence/event_store.rs +270 -0
- package/crates/enact-core/src/kernel/persistence/message_store.rs +908 -0
- package/crates/enact-core/src/kernel/persistence/mod.rs +102 -0
- package/crates/enact-core/src/kernel/persistence/state_store.rs +228 -0
- package/crates/enact-core/src/kernel/persistence/vector_store.rs +299 -0
- package/crates/enact-core/src/kernel/reducer.rs +808 -0
- package/crates/enact-core/src/kernel/replay.rs +153 -0
- package/crates/enact-core/src/lib.rs +413 -0
- package/crates/enact-core/src/memory/episodic.rs +0 -0
- package/crates/enact-core/src/memory/mod.rs +6 -0
- package/crates/enact-core/src/memory/semantic.rs +0 -0
- package/crates/enact-core/src/memory/trait.rs +0 -0
- package/crates/enact-core/src/memory/vector_db.rs +0 -0
- package/crates/enact-core/src/memory/working.rs +0 -0
- package/crates/enact-core/src/policy/execution_policy.rs +292 -0
- package/crates/enact-core/src/policy/filters.rs +458 -0
- package/crates/enact-core/src/policy/input_processor.rs +407 -0
- package/crates/enact-core/src/policy/long_running.rs +134 -0
- package/crates/enact-core/src/policy/mod.rs +193 -0
- package/crates/enact-core/src/policy/pii_input.rs +274 -0
- package/crates/enact-core/src/policy/tenant_policy.rs +453 -0
- package/crates/enact-core/src/policy/tool_policy.rs +407 -0
- package/crates/enact-core/src/providers/mod.rs +63 -0
- package/crates/enact-core/src/providers/trait.rs +292 -0
- package/crates/enact-core/src/runner/callbacks.rs +6 -0
- package/crates/enact-core/src/runner/execution_runner.rs +476 -0
- package/crates/enact-core/src/runner/loop.rs +117 -0
- package/crates/enact-core/src/runner/mod.rs +58 -0
- package/crates/enact-core/src/runner/protected_runner.rs +280 -0
- package/crates/enact-core/src/signal/inmemory.rs +231 -0
- package/crates/enact-core/src/signal/mod.rs +108 -0
- package/crates/enact-core/src/streaming/event_logger.rs +195 -0
- package/crates/enact-core/src/streaming/event_stream.rs +1423 -0
- package/crates/enact-core/src/streaming/mod.rs +108 -0
- package/crates/enact-core/src/streaming/pause_cancel.rs +0 -0
- package/crates/enact-core/src/streaming/protected_emitter.rs +173 -0
- package/crates/enact-core/src/streaming/protection/context.rs +136 -0
- package/crates/enact-core/src/streaming/protection/encryption.rs +289 -0
- package/crates/enact-core/src/streaming/protection/mod.rs +43 -0
- package/crates/enact-core/src/streaming/protection/pii_protection.rs +243 -0
- package/crates/enact-core/src/streaming/protection/processor.rs +166 -0
- package/crates/enact-core/src/streaming/sse.rs +0 -0
- package/crates/enact-core/src/telemetry/exporter.rs +0 -0
- package/crates/enact-core/src/telemetry/init.rs +0 -0
- package/crates/enact-core/src/telemetry/mod.rs +49 -0
- package/crates/enact-core/src/telemetry/spans.rs +245 -0
- package/crates/enact-core/src/tool/agent_tool.rs +177 -0
- package/crates/enact-core/src/tool/browser/mod.rs +0 -0
- package/crates/enact-core/src/tool/browser/webdriver.rs +0 -0
- package/crates/enact-core/src/tool/cost.rs +247 -0
- package/crates/enact-core/src/tool/discovery.rs +0 -0
- package/crates/enact-core/src/tool/dispatcher.rs +347 -0
- package/crates/enact-core/src/tool/filesystem.rs +231 -0
- package/crates/enact-core/src/tool/function.rs +99 -0
- package/crates/enact-core/src/tool/git.rs +162 -0
- package/crates/enact-core/src/tool/http.rs +214 -0
- package/crates/enact-core/src/tool/mcp/client.rs +0 -0
- package/crates/enact-core/src/tool/mcp/mod.rs +0 -0
- package/crates/enact-core/src/tool/mod.rs +51 -0
- package/crates/enact-core/src/tool/reasoning/debugging.rs +0 -0
- package/crates/enact-core/src/tool/reasoning/mcts.rs +0 -0
- package/crates/enact-core/src/tool/reasoning/mod.rs +0 -0
- package/crates/enact-core/src/tool/reasoning/sequential.rs +0 -0
- package/crates/enact-core/src/tool/sandbox/dagger.rs +0 -0
- package/crates/enact-core/src/tool/sandbox/mod.rs +0 -0
- package/crates/enact-core/src/tool/shell.rs +147 -0
- package/crates/enact-core/src/tool/trait.rs +33 -0
- package/crates/enact-core/src/tool/web_search.rs +277 -0
- package/crates/enact-core/src/util/config.rs +0 -0
- package/crates/enact-core/src/util/errors.rs +0 -0
- package/crates/enact-core/src/util/mod.rs +6 -0
- package/crates/enact-core/tests/airgapped_e2e_test.rs +291 -0
- package/crates/enact-core/tests/e2e_agentic_loop.rs +119 -0
- package/crates/enact-core/tests/e2e_test.rs +259 -0
- package/crates/enact-core/tests/graph_test.rs +130 -0
- package/crates/enact-core/tests/stream_event_id_validation.rs +435 -0
- package/crates/enact-cron/Cargo.toml +28 -0
- package/crates/enact-cron/src/lib.rs +44 -0
- package/crates/enact-cron/src/schedule.rs +156 -0
- package/crates/enact-cron/src/store.rs +589 -0
- package/crates/enact-cron/src/types.rs +148 -0
- package/crates/enact-gateway/Cargo.toml +31 -0
- package/crates/enact-gateway/README.md +30 -0
- package/crates/enact-gateway/examples/whatsapp-gateway-runner-mock.rs +59 -0
- package/crates/enact-gateway/examples/whatsapp-gateway.rs +42 -0
- package/crates/enact-gateway/src/lib.rs +582 -0
- package/crates/enact-mcp/Cargo.toml +24 -0
- package/crates/enact-mcp/src/lib.rs +178 -0
- package/crates/enact-memory/Cargo.toml +25 -0
- package/crates/enact-memory/src/backend.rs +20 -0
- package/crates/enact-memory/src/chunker.rs +230 -0
- package/crates/enact-memory/src/embeddings.rs +221 -0
- package/crates/enact-memory/src/lib.rs +67 -0
- package/crates/enact-memory/src/markdown.rs +127 -0
- package/crates/enact-memory/src/none.rs +61 -0
- package/crates/enact-memory/src/sqlite.rs +276 -0
- package/crates/enact-memory/src/traits.rs +65 -0
- package/crates/enact-memory/src/vector.rs +198 -0
- package/crates/enact-oauth/Cargo.toml +27 -0
- package/crates/enact-oauth/src/lib.rs +584 -0
- package/crates/enact-observability/Cargo.toml +22 -0
- package/crates/enact-observability/src/lib.rs +197 -0
- package/crates/enact-providers/Cargo.toml +33 -0
- package/crates/enact-providers/examples/hello-agent.rs +33 -0
- package/crates/enact-providers/src/anthropic.rs +182 -0
- package/crates/enact-providers/src/azure.rs +96 -0
- package/crates/enact-providers/src/bridge.rs +221 -0
- package/crates/enact-providers/src/gemini.rs +227 -0
- package/crates/enact-providers/src/http.rs +78 -0
- package/crates/enact-providers/src/lib.rs +53 -0
- package/crates/enact-providers/src/openai_compatible.rs +167 -0
- package/crates/enact-providers/src/openrouter.rs +33 -0
- package/crates/enact-runner/Cargo.toml +24 -0
- package/crates/enact-runner/README.md +76 -0
- package/crates/enact-runner/src/compaction.rs +225 -0
- package/crates/enact-runner/src/config.rs +118 -0
- package/crates/enact-runner/src/lib.rs +63 -0
- package/crates/enact-runner/src/loop_driver.rs +414 -0
- package/crates/enact-runner/src/parser.rs +421 -0
- package/crates/enact-runner/src/retry.rs +262 -0
- package/crates/enact-runner/tests/integration.rs +278 -0
- package/crates/enact-security/Cargo.toml +22 -0
- package/crates/enact-security/src/audit.rs +375 -0
- package/crates/enact-security/src/lib.rs +37 -0
- package/crates/enact-security/src/policy.rs +406 -0
- package/crates/enact-skills/Cargo.toml +25 -0
- package/crates/enact-skills/src/lib.rs +506 -0
- package/crates/enact-tools/Cargo.toml +22 -0
- package/crates/enact-tools/src/file_read.rs +166 -0
- package/crates/enact-tools/src/file_write.rs +216 -0
- package/crates/enact-tools/src/git_operations.rs +513 -0
- package/crates/enact-tools/src/http_request.rs +417 -0
- package/crates/enact-tools/src/lib.rs +104 -0
- package/crates/enact-tools/src/security.rs +227 -0
- package/crates/enact-tools/src/shell.rs +191 -0
- package/crates/enact-tools/src/traits.rs +159 -0
- package/docs/Makefile +74 -0
- package/docs/config.toml +62 -0
- package/docs/content/_index.md +174 -0
- package/docs/content/a2a/_index.md +431 -0
- package/docs/content/api/_index.md +323 -0
- package/docs/content/channels/_index.md +160 -0
- package/docs/content/channels/teams.md +205 -0
- package/docs/content/channels/telegram.md +182 -0
- package/docs/content/channels/webhook.md +423 -0
- package/docs/content/channels/whatsapp.md +240 -0
- package/docs/content/cli/_index.md +261 -0
- package/docs/content/concepts/_index.md +273 -0
- package/docs/content/configuration/_index.md +241 -0
- package/docs/content/cron/_index.md +248 -0
- package/docs/content/developers/_index.md +278 -0
- package/docs/content/getting-started/_index.md +180 -0
- package/docs/content/installation/_index.md +186 -0
- package/docs/content/installation/uninstall.md +101 -0
- package/docs/content/installation/updating.md +120 -0
- package/docs/content/mcp/_index.md +215 -0
- package/docs/content/memory/_index.md +163 -0
- package/docs/content/oauth/_index.md +515 -0
- package/docs/content/providers/_index.md +206 -0
- package/docs/content/roadmap/_index.md +199 -0
- package/docs/content/security/_index.md +219 -0
- package/docs/content/skills/_index.md +228 -0
- package/docs/content/tools/_index.md +485 -0
- package/docs/content/troubleshooting/_index.md +259 -0
- package/docs/content/yaml-schema/_index.md +294 -0
- package/docs/static/giallo-dark.css +91 -0
- package/docs/static/giallo-light.css +91 -0
- package/docs/themes/tanuki/.github/workflows/deploy.yml +44 -0
- package/docs/themes/tanuki/LICENSE +21 -0
- package/docs/themes/tanuki/README.md +166 -0
- package/docs/themes/tanuki/examples/blog/config.toml +58 -0
- package/docs/themes/tanuki/examples/blog/content/_index.md +4 -0
- package/docs/themes/tanuki/examples/blog/content/about.md +33 -0
- package/docs/themes/tanuki/examples/blog/content/blog/_index.md +7 -0
- package/docs/themes/tanuki/examples/blog/content/blog/api-design-best-practices.md +245 -0
- package/docs/themes/tanuki/examples/blog/content/blog/building-accessible-websites.md +147 -0
- package/docs/themes/tanuki/examples/blog/content/blog/css-grid-vs-flexbox.md +165 -0
- package/docs/themes/tanuki/examples/blog/content/blog/customizing-catppuccin-colors.md +137 -0
- package/docs/themes/tanuki/examples/blog/content/blog/dark-mode-best-practices.md +82 -0
- package/docs/themes/tanuki/examples/blog/content/blog/docker-essentials.md +301 -0
- package/docs/themes/tanuki/examples/blog/content/blog/getting-started-with-zola.md +129 -0
- package/docs/themes/tanuki/examples/blog/content/blog/git-workflow-for-content.md +112 -0
- package/docs/themes/tanuki/examples/blog/content/blog/introduction-to-webassembly.md +183 -0
- package/docs/themes/tanuki/examples/blog/content/blog/modern-javascript-features.md +234 -0
- package/docs/themes/tanuki/examples/blog/content/blog/testing-strategies.md +311 -0
- package/docs/themes/tanuki/examples/blog/content/blog/typography-for-developers.md +104 -0
- package/docs/themes/tanuki/examples/blog/content/blog/welcome-to-tanuki.md +67 -0
- package/docs/themes/tanuki/examples/blog/content/blog/why-static-sites.md +85 -0
- package/docs/themes/tanuki/examples/blog/content/projects.md +64 -0
- package/docs/themes/tanuki/examples/book/config.toml +17 -0
- package/docs/themes/tanuki/examples/book/content/_index.md +12 -0
- package/docs/themes/tanuki/examples/book/content/chapter-1.md +90 -0
- package/docs/themes/tanuki/examples/book/content/chapter-2.md +143 -0
- package/docs/themes/tanuki/examples/book/content/chapter-3.md +217 -0
- package/docs/themes/tanuki/examples/book/content/chapter-4.md +224 -0
- package/docs/themes/tanuki/examples/book/content/chapter-5.md +297 -0
- package/docs/themes/tanuki/examples/book/content/print.md +6 -0
- package/docs/themes/tanuki/examples/docs/config.toml +28 -0
- package/docs/themes/tanuki/examples/docs/content/_index.md +20 -0
- package/docs/themes/tanuki/examples/docs/content/components.md +156 -0
- package/docs/themes/tanuki/examples/docs/content/configuration.md +94 -0
- package/docs/themes/tanuki/examples/docs/content/customization.md +202 -0
- package/docs/themes/tanuki/examples/docs/content/deployment.md +204 -0
- package/docs/themes/tanuki/examples/docs/content/installation.md +59 -0
- package/docs/themes/tanuki/examples/docs/content/print.md +6 -0
- package/docs/themes/tanuki/examples/docs/static/img/tanuki-icon.avif +0 -0
- package/docs/themes/tanuki/examples/index.html +2104 -0
- package/docs/themes/tanuki/mise.toml +108 -0
- package/docs/themes/tanuki/sass/base/_catppuccin.scss +164 -0
- package/docs/themes/tanuki/sass/base/_fonts.scss +64 -0
- package/docs/themes/tanuki/sass/base/_reset.scss +152 -0
- package/docs/themes/tanuki/sass/base/_typography.scss +523 -0
- package/docs/themes/tanuki/sass/components/_buttons.scss +209 -0
- package/docs/themes/tanuki/sass/components/_code.scss +457 -0
- package/docs/themes/tanuki/sass/components/_landing.scss +633 -0
- package/docs/themes/tanuki/sass/components/_layout.scss +294 -0
- package/docs/themes/tanuki/sass/components/_navigation.scss +1200 -0
- package/docs/themes/tanuki/sass/components/_print.scss +237 -0
- package/docs/themes/tanuki/sass/components/_search.scss +224 -0
- package/docs/themes/tanuki/sass/components/_sidebar.scss +473 -0
- package/docs/themes/tanuki/sass/components/_theme-toggle.scss +186 -0
- package/docs/themes/tanuki/sass/modes/_blog.scss +366 -0
- package/docs/themes/tanuki/sass/modes/_product.scss +875 -0
- package/docs/themes/tanuki/sass/modes/_raskell.scss +1696 -0
- package/docs/themes/tanuki/sass/patterns/_buttons.scss +183 -0
- package/docs/themes/tanuki/sass/patterns/_cards.scss +144 -0
- package/docs/themes/tanuki/sass/patterns/_index.scss +9 -0
- package/docs/themes/tanuki/sass/patterns/_lists.scss +259 -0
- package/docs/themes/tanuki/sass/patterns/_sections.scss +243 -0
- package/docs/themes/tanuki/sass/style.scss +47 -0
- package/docs/themes/tanuki/sass/tokens/_colors.scss +139 -0
- package/docs/themes/tanuki/sass/tokens/_spacing.scss +100 -0
- package/docs/themes/tanuki/sass/tokens/_typography.scss +186 -0
- package/docs/themes/tanuki/screenshot.png +0 -0
- package/docs/themes/tanuki/sentinel.kdl +59 -0
- package/docs/themes/tanuki/static/elasticlunr.min.js +10 -0
- package/docs/themes/tanuki/static/fonts/GEIST-LICENSE.txt +92 -0
- package/docs/themes/tanuki/static/fonts/Geist-Variable.woff2 +0 -0
- package/docs/themes/tanuki/static/fonts/GeistMono-Variable.woff2 +0 -0
- package/docs/themes/tanuki/static/img/tanuki-icon.avif +0 -0
- package/docs/themes/tanuki/static/img/tanuki-icon.png +0 -0
- package/docs/themes/tanuki/static/js/anchors.js +18 -0
- package/docs/themes/tanuki/static/js/app.js +274 -0
- package/docs/themes/tanuki/static/js/code.js +394 -0
- package/docs/themes/tanuki/static/js/navigation.js +778 -0
- package/docs/themes/tanuki/static/js/scroll-to-top.js +33 -0
- package/docs/themes/tanuki/static/js/search-raskell.js +240 -0
- package/docs/themes/tanuki/static/js/search.js +215 -0
- package/docs/themes/tanuki/static/js/theme.js +169 -0
- package/docs/themes/tanuki/static/syntax-dark.css +151 -0
- package/docs/themes/tanuki/static/syntax-light.css +151 -0
- package/docs/themes/tanuki/static/wasm/sentinel_playground_wasm.js +486 -0
- package/docs/themes/tanuki/static/wasm/sentinel_playground_wasm_bg.wasm +0 -0
- package/docs/themes/tanuki/templates/404.html +52 -0
- package/docs/themes/tanuki/templates/base.html +428 -0
- package/docs/themes/tanuki/templates/blog.html +66 -0
- package/docs/themes/tanuki/templates/home.html +108 -0
- package/docs/themes/tanuki/templates/index.html +178 -0
- package/docs/themes/tanuki/templates/landing.html +168 -0
- package/docs/themes/tanuki/templates/macros/nav.html +128 -0
- package/docs/themes/tanuki/templates/macros/posts.html +101 -0
- package/docs/themes/tanuki/templates/macros/ui.html +159 -0
- package/docs/themes/tanuki/templates/page.html +135 -0
- package/docs/themes/tanuki/templates/partials/footer.html +38 -0
- package/docs/themes/tanuki/templates/partials/header.html +366 -0
- package/docs/themes/tanuki/templates/partials/nav-buttons.html +55 -0
- package/docs/themes/tanuki/templates/partials/nav-overlay.html +81 -0
- package/docs/themes/tanuki/templates/partials/page-toc-panel.html +43 -0
- package/docs/themes/tanuki/templates/partials/search.html +52 -0
- package/docs/themes/tanuki/templates/partials/sidebar.html +107 -0
- package/docs/themes/tanuki/templates/partials/theme-toggle.html +35 -0
- package/docs/themes/tanuki/templates/partials/toc-overlay.html +146 -0
- package/docs/themes/tanuki/templates/partials/version-picker.html +38 -0
- package/docs/themes/tanuki/templates/print.html +244 -0
- package/docs/themes/tanuki/templates/section.html +186 -0
- package/docs/themes/tanuki/templates/taxonomy_list.html +18 -0
- package/docs/themes/tanuki/templates/taxonomy_single.html +31 -0
- package/docs/themes/tanuki/theme.toml +58 -0
- package/examples/hello-agent.rs +55 -0
- package/package.json +36 -0
- package/proto/config.proto +60 -0
- package/proto/events.proto +0 -0
- package/proto/runtime.proto +215 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
//! Background Executor - Runs callables in background mode
|
|
2
|
+
//!
|
|
3
|
+
//! The executor handles different background execution modes:
|
|
4
|
+
//! - FireAndForget: Don't wait for result, no streaming
|
|
5
|
+
//! - Silent: Wait for result, but suppress streaming events
|
|
6
|
+
//! - Deferred: Queue for later execution
|
|
7
|
+
//!
|
|
8
|
+
//! @see packages/enact-schemas/src/execution.schemas.ts
|
|
9
|
+
|
|
10
|
+
use chrono::{DateTime, Utc};
|
|
11
|
+
use serde::{Deserialize, Serialize};
|
|
12
|
+
use std::collections::HashMap;
|
|
13
|
+
|
|
14
|
+
use crate::kernel::ids::{ExecutionId, SpawnMode, TenantId};
|
|
15
|
+
use crate::kernel::ExecutionError;
|
|
16
|
+
|
|
17
|
+
use super::target_binding::TargetBindingConfig;
|
|
18
|
+
use super::trigger::{RetryConfig, TriggerId};
|
|
19
|
+
|
|
20
|
+
/// BackgroundExecutionMode - How to run a background callable
|
|
21
|
+
/// @see packages/enact-schemas/src/execution.schemas.ts - backgroundExecutionModeSchema
|
|
22
|
+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
|
|
23
|
+
#[serde(rename_all = "snake_case")]
|
|
24
|
+
pub enum BackgroundExecutionMode {
|
|
25
|
+
/// Don't wait for result, no streaming
|
|
26
|
+
#[default]
|
|
27
|
+
FireAndForget,
|
|
28
|
+
/// Wait for result, but no streaming
|
|
29
|
+
Silent,
|
|
30
|
+
/// Queue for later execution
|
|
31
|
+
Deferred,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/// BackgroundExecutionStatus - Status of a background execution
|
|
35
|
+
/// @see packages/enact-schemas/src/execution.schemas.ts - backgroundExecutionStatusSchema
|
|
36
|
+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
|
|
37
|
+
#[serde(rename_all = "snake_case")]
|
|
38
|
+
pub enum BackgroundExecutionStatus {
|
|
39
|
+
/// Waiting to execute
|
|
40
|
+
#[default]
|
|
41
|
+
Queued,
|
|
42
|
+
/// Currently executing
|
|
43
|
+
Running,
|
|
44
|
+
/// Finished successfully
|
|
45
|
+
Completed,
|
|
46
|
+
/// Failed with error
|
|
47
|
+
Failed,
|
|
48
|
+
/// Cancelled before completion
|
|
49
|
+
Cancelled,
|
|
50
|
+
/// Exceeded timeout
|
|
51
|
+
Timeout,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/// BackgroundExecutionConfig - Configuration for background execution
|
|
55
|
+
/// @see packages/enact-schemas/src/execution.schemas.ts - backgroundExecutionConfigSchema
|
|
56
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
57
|
+
#[serde(rename_all = "camelCase")]
|
|
58
|
+
pub struct BackgroundExecutionConfig {
|
|
59
|
+
/// Execution mode
|
|
60
|
+
#[serde(default)]
|
|
61
|
+
pub mode: BackgroundExecutionMode,
|
|
62
|
+
|
|
63
|
+
/// Priority (higher = runs sooner)
|
|
64
|
+
#[serde(default = "default_priority")]
|
|
65
|
+
pub priority: u8,
|
|
66
|
+
|
|
67
|
+
/// Maximum execution time in milliseconds
|
|
68
|
+
#[serde(default = "default_timeout_ms")]
|
|
69
|
+
pub timeout_ms: u64,
|
|
70
|
+
|
|
71
|
+
/// Target binding for result
|
|
72
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
73
|
+
pub target_binding: Option<TargetBindingConfig>,
|
|
74
|
+
|
|
75
|
+
/// Callback URL (for deferred mode)
|
|
76
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
77
|
+
pub callback_url: Option<String>,
|
|
78
|
+
|
|
79
|
+
/// Retry configuration
|
|
80
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
81
|
+
pub retry: Option<RetryConfig>,
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
fn default_priority() -> u8 {
|
|
85
|
+
50
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
fn default_timeout_ms() -> u64 {
|
|
89
|
+
300000 // 5 minutes
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
impl Default for BackgroundExecutionConfig {
|
|
93
|
+
fn default() -> Self {
|
|
94
|
+
Self {
|
|
95
|
+
mode: BackgroundExecutionMode::FireAndForget,
|
|
96
|
+
priority: default_priority(),
|
|
97
|
+
timeout_ms: default_timeout_ms(),
|
|
98
|
+
target_binding: None,
|
|
99
|
+
callback_url: None,
|
|
100
|
+
retry: None,
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/// BackgroundExecution - A background execution record
|
|
106
|
+
/// @see packages/enact-schemas/src/execution.schemas.ts - backgroundExecutionSchema
|
|
107
|
+
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
108
|
+
#[serde(rename_all = "camelCase")]
|
|
109
|
+
pub struct BackgroundExecution {
|
|
110
|
+
/// Execution ID
|
|
111
|
+
pub execution_id: ExecutionId,
|
|
112
|
+
|
|
113
|
+
/// Tenant that owns this execution
|
|
114
|
+
pub tenant_id: TenantId,
|
|
115
|
+
|
|
116
|
+
/// Callable to invoke
|
|
117
|
+
pub callable_name: String,
|
|
118
|
+
|
|
119
|
+
/// Input to pass to the callable
|
|
120
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
121
|
+
pub input: Option<String>,
|
|
122
|
+
|
|
123
|
+
/// Context to pass
|
|
124
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
125
|
+
pub context: Option<HashMap<String, String>>,
|
|
126
|
+
|
|
127
|
+
/// Configuration
|
|
128
|
+
pub config: BackgroundExecutionConfig,
|
|
129
|
+
|
|
130
|
+
/// Current status
|
|
131
|
+
#[serde(default)]
|
|
132
|
+
pub status: BackgroundExecutionStatus,
|
|
133
|
+
|
|
134
|
+
/// When execution was queued
|
|
135
|
+
pub queued_at: DateTime<Utc>,
|
|
136
|
+
|
|
137
|
+
/// When execution started
|
|
138
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
139
|
+
pub started_at: Option<DateTime<Utc>>,
|
|
140
|
+
|
|
141
|
+
/// When execution completed
|
|
142
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
143
|
+
pub completed_at: Option<DateTime<Utc>>,
|
|
144
|
+
|
|
145
|
+
/// Output (populated on completion)
|
|
146
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
147
|
+
pub output: Option<serde_json::Value>,
|
|
148
|
+
|
|
149
|
+
/// Error (populated on failure)
|
|
150
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
151
|
+
pub error: Option<ExecutionError>,
|
|
152
|
+
|
|
153
|
+
/// Whether target binding was applied
|
|
154
|
+
#[serde(default)]
|
|
155
|
+
pub target_binding_applied: bool,
|
|
156
|
+
|
|
157
|
+
/// Trigger that spawned this execution (if any)
|
|
158
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
159
|
+
pub trigger_id: Option<TriggerId>,
|
|
160
|
+
|
|
161
|
+
/// Metadata
|
|
162
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
163
|
+
pub metadata: Option<HashMap<String, serde_json::Value>>,
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
impl BackgroundExecution {
|
|
167
|
+
/// Create a new background execution
|
|
168
|
+
pub fn new(
|
|
169
|
+
tenant_id: TenantId,
|
|
170
|
+
callable_name: impl Into<String>,
|
|
171
|
+
config: BackgroundExecutionConfig,
|
|
172
|
+
) -> Self {
|
|
173
|
+
Self {
|
|
174
|
+
execution_id: ExecutionId::new(),
|
|
175
|
+
tenant_id,
|
|
176
|
+
callable_name: callable_name.into(),
|
|
177
|
+
input: None,
|
|
178
|
+
context: None,
|
|
179
|
+
config,
|
|
180
|
+
status: BackgroundExecutionStatus::Queued,
|
|
181
|
+
queued_at: Utc::now(),
|
|
182
|
+
started_at: None,
|
|
183
|
+
completed_at: None,
|
|
184
|
+
output: None,
|
|
185
|
+
error: None,
|
|
186
|
+
target_binding_applied: false,
|
|
187
|
+
trigger_id: None,
|
|
188
|
+
metadata: None,
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/// Create from a trigger
|
|
193
|
+
pub fn from_trigger(
|
|
194
|
+
tenant_id: TenantId,
|
|
195
|
+
trigger_id: TriggerId,
|
|
196
|
+
callable_name: impl Into<String>,
|
|
197
|
+
input: Option<String>,
|
|
198
|
+
context: Option<HashMap<String, String>>,
|
|
199
|
+
target_binding: Option<TargetBindingConfig>,
|
|
200
|
+
retry: Option<RetryConfig>,
|
|
201
|
+
) -> Self {
|
|
202
|
+
let config = BackgroundExecutionConfig {
|
|
203
|
+
mode: BackgroundExecutionMode::Silent,
|
|
204
|
+
target_binding,
|
|
205
|
+
retry,
|
|
206
|
+
..Default::default()
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
let mut execution = Self::new(tenant_id, callable_name, config);
|
|
210
|
+
execution.trigger_id = Some(trigger_id);
|
|
211
|
+
execution.input = input;
|
|
212
|
+
execution.context = context;
|
|
213
|
+
execution
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/// Create from SpawnMode::Child
|
|
217
|
+
///
|
|
218
|
+
/// This bridges the gap between SpawnMode::Child { background: true, .. }
|
|
219
|
+
/// and the BackgroundExecution infrastructure.
|
|
220
|
+
///
|
|
221
|
+
/// @see docs/TECHNICAL/32-SPAWN-MODE.md
|
|
222
|
+
pub fn from_spawn_mode(
|
|
223
|
+
spawn_mode: &SpawnMode,
|
|
224
|
+
tenant_id: TenantId,
|
|
225
|
+
callable_name: impl Into<String>,
|
|
226
|
+
input: Option<String>,
|
|
227
|
+
context: Option<HashMap<String, String>>,
|
|
228
|
+
) -> Option<Self> {
|
|
229
|
+
match spawn_mode {
|
|
230
|
+
SpawnMode::Child { background: true, .. } => {
|
|
231
|
+
// Background=true means fire-and-forget execution
|
|
232
|
+
let config = BackgroundExecutionConfig {
|
|
233
|
+
mode: BackgroundExecutionMode::FireAndForget,
|
|
234
|
+
..Default::default()
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
let mut execution = Self::new(tenant_id, callable_name, config);
|
|
238
|
+
execution.input = input;
|
|
239
|
+
execution.context = context;
|
|
240
|
+
Some(execution)
|
|
241
|
+
}
|
|
242
|
+
SpawnMode::Child { background: false, .. } => {
|
|
243
|
+
// Background=false means inline execution - not a background execution
|
|
244
|
+
None
|
|
245
|
+
}
|
|
246
|
+
SpawnMode::Inline => {
|
|
247
|
+
// Inline mode doesn't create a separate execution
|
|
248
|
+
None
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/// Check if a SpawnMode should create a background execution
|
|
254
|
+
pub fn should_run_background(spawn_mode: &SpawnMode) -> bool {
|
|
255
|
+
matches!(spawn_mode, SpawnMode::Child { background: true, .. })
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/// Mark execution as started
|
|
259
|
+
pub fn start(&mut self) {
|
|
260
|
+
self.status = BackgroundExecutionStatus::Running;
|
|
261
|
+
self.started_at = Some(Utc::now());
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/// Mark execution as completed
|
|
265
|
+
pub fn complete(&mut self, output: serde_json::Value) {
|
|
266
|
+
self.status = BackgroundExecutionStatus::Completed;
|
|
267
|
+
self.completed_at = Some(Utc::now());
|
|
268
|
+
self.output = Some(output);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/// Mark execution as failed
|
|
272
|
+
pub fn fail(&mut self, error: ExecutionError) {
|
|
273
|
+
self.status = BackgroundExecutionStatus::Failed;
|
|
274
|
+
self.completed_at = Some(Utc::now());
|
|
275
|
+
self.error = Some(error);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/// Mark execution as cancelled
|
|
279
|
+
pub fn cancel(&mut self) {
|
|
280
|
+
self.status = BackgroundExecutionStatus::Cancelled;
|
|
281
|
+
self.completed_at = Some(Utc::now());
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/// Mark execution as timed out
|
|
285
|
+
pub fn timeout(&mut self) {
|
|
286
|
+
self.status = BackgroundExecutionStatus::Timeout;
|
|
287
|
+
self.completed_at = Some(Utc::now());
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/// Check if execution has completed (successfully or not)
|
|
291
|
+
pub fn is_finished(&self) -> bool {
|
|
292
|
+
matches!(
|
|
293
|
+
self.status,
|
|
294
|
+
BackgroundExecutionStatus::Completed
|
|
295
|
+
| BackgroundExecutionStatus::Failed
|
|
296
|
+
| BackgroundExecutionStatus::Cancelled
|
|
297
|
+
| BackgroundExecutionStatus::Timeout
|
|
298
|
+
)
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/// Check if execution succeeded
|
|
302
|
+
pub fn is_success(&self) -> bool {
|
|
303
|
+
self.status == BackgroundExecutionStatus::Completed
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/// Calculate execution duration
|
|
307
|
+
pub fn duration_ms(&self) -> Option<i64> {
|
|
308
|
+
match (self.started_at, self.completed_at) {
|
|
309
|
+
(Some(start), Some(end)) => Some((end - start).num_milliseconds()),
|
|
310
|
+
_ => None,
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/// Check if execution should suppress streaming events (silent mode)
|
|
315
|
+
pub fn is_silent(&self) -> bool {
|
|
316
|
+
matches!(
|
|
317
|
+
self.config.mode,
|
|
318
|
+
BackgroundExecutionMode::Silent | BackgroundExecutionMode::FireAndForget
|
|
319
|
+
)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/// Check if execution requires waiting for result
|
|
323
|
+
pub fn requires_result(&self) -> bool {
|
|
324
|
+
matches!(self.config.mode, BackgroundExecutionMode::Silent)
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/// BackgroundExecutionQueue - Queue for managing background executions
|
|
329
|
+
/// This is an in-memory implementation for testing. Production uses Redis/Postgres.
|
|
330
|
+
#[derive(Debug, Default)]
|
|
331
|
+
pub struct BackgroundExecutionQueue {
|
|
332
|
+
executions: std::collections::VecDeque<BackgroundExecution>,
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
impl BackgroundExecutionQueue {
|
|
336
|
+
/// Create a new empty queue
|
|
337
|
+
pub fn new() -> Self {
|
|
338
|
+
Self::default()
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/// Enqueue a new execution
|
|
342
|
+
pub fn enqueue(&mut self, execution: BackgroundExecution) {
|
|
343
|
+
// Insert based on priority (higher priority first)
|
|
344
|
+
let pos = self
|
|
345
|
+
.executions
|
|
346
|
+
.iter()
|
|
347
|
+
.position(|e| e.config.priority < execution.config.priority)
|
|
348
|
+
.unwrap_or(self.executions.len());
|
|
349
|
+
self.executions.insert(pos, execution);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/// Dequeue the next execution to run
|
|
353
|
+
pub fn dequeue(&mut self) -> Option<BackgroundExecution> {
|
|
354
|
+
self.executions.pop_front()
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/// Peek at the next execution without removing it
|
|
358
|
+
pub fn peek(&self) -> Option<&BackgroundExecution> {
|
|
359
|
+
self.executions.front()
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/// Get queue length
|
|
363
|
+
pub fn len(&self) -> usize {
|
|
364
|
+
self.executions.len()
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/// Check if queue is empty
|
|
368
|
+
pub fn is_empty(&self) -> bool {
|
|
369
|
+
self.executions.is_empty()
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/// Get all queued execution IDs
|
|
373
|
+
pub fn execution_ids(&self) -> Vec<ExecutionId> {
|
|
374
|
+
self.executions.iter().map(|e| e.execution_id.clone()).collect()
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
#[cfg(test)]
|
|
379
|
+
mod tests {
|
|
380
|
+
use super::*;
|
|
381
|
+
|
|
382
|
+
#[test]
|
|
383
|
+
fn test_background_execution_modes() {
|
|
384
|
+
// Test fire and forget
|
|
385
|
+
let config = BackgroundExecutionConfig {
|
|
386
|
+
mode: BackgroundExecutionMode::FireAndForget,
|
|
387
|
+
..Default::default()
|
|
388
|
+
};
|
|
389
|
+
let exec = BackgroundExecution::new(TenantId::new(), "test", config);
|
|
390
|
+
assert!(exec.is_silent());
|
|
391
|
+
assert!(!exec.requires_result());
|
|
392
|
+
|
|
393
|
+
// Test silent
|
|
394
|
+
let config = BackgroundExecutionConfig {
|
|
395
|
+
mode: BackgroundExecutionMode::Silent,
|
|
396
|
+
..Default::default()
|
|
397
|
+
};
|
|
398
|
+
let exec = BackgroundExecution::new(TenantId::new(), "test", config);
|
|
399
|
+
assert!(exec.is_silent());
|
|
400
|
+
assert!(exec.requires_result());
|
|
401
|
+
|
|
402
|
+
// Test deferred
|
|
403
|
+
let config = BackgroundExecutionConfig {
|
|
404
|
+
mode: BackgroundExecutionMode::Deferred,
|
|
405
|
+
..Default::default()
|
|
406
|
+
};
|
|
407
|
+
let exec = BackgroundExecution::new(TenantId::new(), "test", config);
|
|
408
|
+
assert!(!exec.is_silent());
|
|
409
|
+
assert!(!exec.requires_result());
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
#[test]
|
|
413
|
+
fn test_background_execution_lifecycle() {
|
|
414
|
+
let config = BackgroundExecutionConfig::default();
|
|
415
|
+
let mut exec = BackgroundExecution::new(TenantId::new(), "test", config);
|
|
416
|
+
|
|
417
|
+
assert_eq!(exec.status, BackgroundExecutionStatus::Queued);
|
|
418
|
+
assert!(!exec.is_finished());
|
|
419
|
+
|
|
420
|
+
exec.start();
|
|
421
|
+
assert_eq!(exec.status, BackgroundExecutionStatus::Running);
|
|
422
|
+
assert!(exec.started_at.is_some());
|
|
423
|
+
|
|
424
|
+
exec.complete(serde_json::json!({"result": "success"}));
|
|
425
|
+
assert_eq!(exec.status, BackgroundExecutionStatus::Completed);
|
|
426
|
+
assert!(exec.is_finished());
|
|
427
|
+
assert!(exec.is_success());
|
|
428
|
+
assert!(exec.output.is_some());
|
|
429
|
+
assert!(exec.duration_ms().is_some());
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
#[test]
|
|
433
|
+
fn test_background_execution_queue() {
|
|
434
|
+
let mut queue = BackgroundExecutionQueue::new();
|
|
435
|
+
assert!(queue.is_empty());
|
|
436
|
+
|
|
437
|
+
// Add low priority
|
|
438
|
+
let low = BackgroundExecution::new(
|
|
439
|
+
TenantId::new(),
|
|
440
|
+
"low",
|
|
441
|
+
BackgroundExecutionConfig {
|
|
442
|
+
priority: 10,
|
|
443
|
+
..Default::default()
|
|
444
|
+
},
|
|
445
|
+
);
|
|
446
|
+
queue.enqueue(low);
|
|
447
|
+
|
|
448
|
+
// Add high priority
|
|
449
|
+
let high = BackgroundExecution::new(
|
|
450
|
+
TenantId::new(),
|
|
451
|
+
"high",
|
|
452
|
+
BackgroundExecutionConfig {
|
|
453
|
+
priority: 90,
|
|
454
|
+
..Default::default()
|
|
455
|
+
},
|
|
456
|
+
);
|
|
457
|
+
queue.enqueue(high);
|
|
458
|
+
|
|
459
|
+
assert_eq!(queue.len(), 2);
|
|
460
|
+
|
|
461
|
+
// High priority should come first
|
|
462
|
+
let first = queue.dequeue().unwrap();
|
|
463
|
+
assert_eq!(first.callable_name, "high");
|
|
464
|
+
|
|
465
|
+
let second = queue.dequeue().unwrap();
|
|
466
|
+
assert_eq!(second.callable_name, "low");
|
|
467
|
+
|
|
468
|
+
assert!(queue.is_empty());
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
#[test]
|
|
472
|
+
fn test_spawn_mode_integration() {
|
|
473
|
+
let tenant_id = TenantId::new();
|
|
474
|
+
|
|
475
|
+
// SpawnMode::Child with background=true creates a background execution
|
|
476
|
+
let spawn_mode = SpawnMode::Child {
|
|
477
|
+
background: true,
|
|
478
|
+
inherit_inbox: false,
|
|
479
|
+
policies: None,
|
|
480
|
+
};
|
|
481
|
+
assert!(BackgroundExecution::should_run_background(&spawn_mode));
|
|
482
|
+
|
|
483
|
+
let exec = BackgroundExecution::from_spawn_mode(
|
|
484
|
+
&spawn_mode,
|
|
485
|
+
tenant_id.clone(),
|
|
486
|
+
"background_callable",
|
|
487
|
+
Some("input data".to_string()),
|
|
488
|
+
None,
|
|
489
|
+
);
|
|
490
|
+
assert!(exec.is_some());
|
|
491
|
+
let exec = exec.unwrap();
|
|
492
|
+
assert_eq!(exec.callable_name, "background_callable");
|
|
493
|
+
assert_eq!(exec.config.mode, BackgroundExecutionMode::FireAndForget);
|
|
494
|
+
assert!(exec.is_silent());
|
|
495
|
+
|
|
496
|
+
// SpawnMode::Child with background=false does not create a background execution
|
|
497
|
+
let spawn_mode = SpawnMode::Child {
|
|
498
|
+
background: false,
|
|
499
|
+
inherit_inbox: false,
|
|
500
|
+
policies: None,
|
|
501
|
+
};
|
|
502
|
+
assert!(!BackgroundExecution::should_run_background(&spawn_mode));
|
|
503
|
+
let exec = BackgroundExecution::from_spawn_mode(
|
|
504
|
+
&spawn_mode,
|
|
505
|
+
tenant_id.clone(),
|
|
506
|
+
"sync_callable",
|
|
507
|
+
None,
|
|
508
|
+
None,
|
|
509
|
+
);
|
|
510
|
+
assert!(exec.is_none());
|
|
511
|
+
|
|
512
|
+
// SpawnMode::Inline does not create a background execution
|
|
513
|
+
let spawn_mode = SpawnMode::Inline;
|
|
514
|
+
assert!(!BackgroundExecution::should_run_background(&spawn_mode));
|
|
515
|
+
let exec = BackgroundExecution::from_spawn_mode(
|
|
516
|
+
&spawn_mode,
|
|
517
|
+
tenant_id,
|
|
518
|
+
"inline_callable",
|
|
519
|
+
None,
|
|
520
|
+
None,
|
|
521
|
+
);
|
|
522
|
+
assert!(exec.is_none());
|
|
523
|
+
}
|
|
524
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
//! Background Module - Background execution and triggers
|
|
2
|
+
//!
|
|
3
|
+
//! This module provides the infrastructure for background callable execution:
|
|
4
|
+
//!
|
|
5
|
+
//! - **Triggers**: Event-based callable invocation
|
|
6
|
+
//! - **Executor**: Background execution with different modes
|
|
7
|
+
//! - **Target Binding**: Binds execution results to targets
|
|
8
|
+
//!
|
|
9
|
+
//! ## Background Execution Modes
|
|
10
|
+
//!
|
|
11
|
+
//! - `FireAndForget`: Don't wait for result, no streaming
|
|
12
|
+
//! - `Silent`: Wait for result, but suppress streaming events
|
|
13
|
+
//! - `Deferred`: Queue for later execution
|
|
14
|
+
//!
|
|
15
|
+
//! ## Triggers
|
|
16
|
+
//!
|
|
17
|
+
//! Triggers watch for specific events and spawn background executions:
|
|
18
|
+
//! - Event: Fired by execution/step events
|
|
19
|
+
//! - Schedule: Fired by cron/interval schedules
|
|
20
|
+
//! - Webhook: Fired by external webhooks
|
|
21
|
+
//! - Threshold: Fired when metrics cross thresholds
|
|
22
|
+
//! - Lifecycle: Fired by thread/user lifecycle events
|
|
23
|
+
//!
|
|
24
|
+
//! @see packages/enact-schemas/src/execution.schemas.ts
|
|
25
|
+
//! @see docs/TECHNICAL/32-SPAWN-MODE.md
|
|
26
|
+
|
|
27
|
+
pub mod executor;
|
|
28
|
+
pub mod target_binding;
|
|
29
|
+
pub mod trigger;
|
|
30
|
+
|
|
31
|
+
// Re-exports - Trigger
|
|
32
|
+
pub use trigger::{
|
|
33
|
+
RetryConfig, TargetBindingConfig as TriggerTargetBindingConfig, TargetBindingType as TriggerTargetBindingType,
|
|
34
|
+
ThresholdOperator, Trigger, TriggerAction, TriggerCondition, TriggerFiredEvent, TriggerId,
|
|
35
|
+
TriggerStatus, TriggerType,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Re-exports - Executor
|
|
39
|
+
pub use executor::{
|
|
40
|
+
BackgroundExecution, BackgroundExecutionConfig, BackgroundExecutionMode,
|
|
41
|
+
BackgroundExecutionQueue, BackgroundExecutionStatus,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Re-exports - Target Binding
|
|
45
|
+
pub use target_binding::{
|
|
46
|
+
apply_transform, TargetBindingConfig, TargetBindingResult, TargetBindingTransform,
|
|
47
|
+
TargetBindingType,
|
|
48
|
+
};
|