@theowlops/boombot 0.0.0-stage → 1.1.1
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/README.md +69 -3
- package/dist/LICENSE +21 -0
- package/dist/bin/boombot.js +16 -0
- package/dist/cli/api-key.js +123 -0
- package/dist/cli/bin-bun.js +17 -0
- package/dist/cli/bin.js +34 -0
- package/dist/cli/cli/cli-error.js +61 -0
- package/dist/cli/cli/dispatch.js +138 -0
- package/dist/cli/cli/help.js +83 -0
- package/dist/cli/cli/parser.js +89 -0
- package/dist/cli/cli/registry.js +185 -0
- package/dist/cli/cli/spec.js +41 -0
- package/dist/cli/cli/suggest.js +125 -0
- package/dist/cli/cli/version.js +30 -0
- package/dist/cli/cli/vocabulary.js +87 -0
- package/dist/cli/commands/doctor.js +365 -0
- package/dist/cli/commands/gateway.js +290 -0
- package/dist/cli/commands/migrate.js +270 -0
- package/dist/cli/commands/plugin.js +97 -0
- package/dist/cli/commands/setup.js +244 -0
- package/dist/cli/config-file.js +133 -0
- package/dist/cli/master-key.js +78 -0
- package/dist/cli/open-browser.js +59 -0
- package/dist/cli/web-assets.js +58 -0
- package/dist/gateway/auth.js +46 -0
- package/dist/gateway/config-format.js +202 -0
- package/dist/gateway/config.js +427 -0
- package/dist/gateway/context.js +1 -0
- package/dist/gateway/env-file.js +129 -0
- package/dist/gateway/events.js +172 -0
- package/dist/gateway/guard/tagging.js +505 -0
- package/dist/gateway/handlers/index.js +66 -0
- package/dist/gateway/handlers/memory.js +54 -0
- package/dist/gateway/handlers/providers.js +73 -0
- package/dist/gateway/handlers/registry.js +39 -0
- package/dist/gateway/handlers/sessions.js +188 -0
- package/dist/gateway/handlers/system.js +12 -0
- package/dist/gateway/handlers/tasks.js +191 -0
- package/dist/gateway/handlers/turn.js +100 -0
- package/dist/gateway/index.js +126 -0
- package/dist/gateway/main.js +23 -0
- package/dist/gateway/server.js +354 -0
- package/dist/gateway/services/context-limits.js +75 -0
- package/dist/gateway/services/history-normalizer.js +42 -0
- package/dist/gateway/services/image-pipeline.js +56 -0
- package/dist/gateway/services/key-roulette-client.js +43 -0
- package/dist/gateway/services/llm-client.js +593 -0
- package/dist/gateway/services/llm-decoder.js +200 -0
- package/dist/gateway/services/local-fallback.js +135 -0
- package/dist/gateway/services/memory.js +511 -0
- package/dist/gateway/services/persistent-memory.js +196 -0
- package/dist/gateway/services/providers.js +44 -0
- package/dist/gateway/services/tasks.js +237 -0
- package/dist/gateway/services/verification.js +124 -0
- package/dist/gateway/services/vision-payload.js +48 -0
- package/dist/gateway/services.js +257 -0
- package/dist/gateway/session-snapshot.js +19 -0
- package/dist/gateway/sessions.js +701 -0
- package/dist/gateway/static.js +239 -0
- package/dist/gateway/turns/clarify-tool.js +57 -0
- package/dist/gateway/turns/cronjob-tool.js +96 -0
- package/dist/gateway/turns/deferred-tools.js +154 -0
- package/dist/gateway/turns/execute-code-tool.js +84 -0
- package/dist/gateway/turns/file-tool-defs.js +178 -0
- package/dist/gateway/turns/file-tool-ops.js +178 -0
- package/dist/gateway/turns/file-tool-scan.js +182 -0
- package/dist/gateway/turns/file-tool.js +302 -0
- package/dist/gateway/turns/index.js +416 -0
- package/dist/gateway/turns/jev-middleware.js +91 -0
- package/dist/gateway/turns/local-reply.js +156 -0
- package/dist/gateway/turns/mcp-client.js +643 -0
- package/dist/gateway/turns/memory-tool.js +171 -0
- package/dist/gateway/turns/middleware.js +96 -0
- package/dist/gateway/turns/python-core.js +397 -0
- package/dist/gateway/turns/routing/index.js +3 -0
- package/dist/gateway/turns/routing/intent-classifier.js +60 -0
- package/dist/gateway/turns/routing/planner-adapter.js +91 -0
- package/dist/gateway/turns/routing/types.js +1 -0
- package/dist/gateway/turns/runtime-deps.js +228 -0
- package/dist/gateway/turns/self-config-tool.js +277 -0
- package/dist/gateway/turns/service-types.js +11 -0
- package/dist/gateway/turns/service.js +820 -0
- package/dist/gateway/turns/session-adapter.js +158 -0
- package/dist/gateway/turns/session-tool.js +49 -0
- package/dist/gateway/turns/shell-tool.js +190 -0
- package/dist/gateway/turns/skill-tool.js +239 -0
- package/dist/gateway/turns/spillover.js +201 -0
- package/dist/gateway/turns/subagent-tool.js +140 -0
- package/dist/gateway/turns/system-prompt.js +121 -0
- package/dist/gateway/turns/tool-schema.js +90 -0
- package/dist/gateway/turns/turn-utils.js +58 -0
- package/dist/gateway/turns/vision-tool.js +120 -0
- package/dist/gateway/types.js +1 -0
- package/dist/native/win32-x64/boombot-native-host.exe +0 -0
- package/dist/node_modules/@boombot/channels/handlers.d.ts +9 -0
- package/dist/node_modules/@boombot/channels/handlers.js +109 -0
- package/dist/node_modules/@boombot/channels/index.d.ts +12 -0
- package/dist/node_modules/@boombot/channels/index.js +12 -0
- package/dist/node_modules/@boombot/channels/package.json +9 -0
- package/dist/node_modules/@boombot/channels/service.d.ts +62 -0
- package/dist/node_modules/@boombot/channels/service.js +608 -0
- package/dist/node_modules/@boombot/channels/tool.d.ts +10 -0
- package/dist/node_modules/@boombot/channels/tool.js +46 -0
- package/dist/node_modules/@boombot/channels/transports/common/dedup.d.ts +17 -0
- package/dist/node_modules/@boombot/channels/transports/common/dedup.js +42 -0
- package/dist/node_modules/@boombot/channels/transports/common/handoff.d.ts +19 -0
- package/dist/node_modules/@boombot/channels/transports/common/handoff.js +32 -0
- package/dist/node_modules/@boombot/channels/transports/common/index.d.ts +3 -0
- package/dist/node_modules/@boombot/channels/transports/common/index.js +3 -0
- package/dist/node_modules/@boombot/channels/transports/common/types.d.ts +99 -0
- package/dist/node_modules/@boombot/channels/transports/common/types.js +54 -0
- package/dist/node_modules/@boombot/channels/transports/common.d.ts +2 -0
- package/dist/node_modules/@boombot/channels/transports/common.js +2 -0
- package/dist/node_modules/@boombot/channels/transports/dedup/index.d.ts +1 -0
- package/dist/node_modules/@boombot/channels/transports/dedup/index.js +1 -0
- package/dist/node_modules/@boombot/channels/transports/dedup.d.ts +2 -0
- package/dist/node_modules/@boombot/channels/transports/dedup.js +2 -0
- package/dist/node_modules/@boombot/channels/transports/discord/index.d.ts +1 -0
- package/dist/node_modules/@boombot/channels/transports/discord/index.js +1 -0
- package/dist/node_modules/@boombot/channels/transports/discord/transport.d.ts +36 -0
- package/dist/node_modules/@boombot/channels/transports/discord/transport.js +199 -0
- package/dist/node_modules/@boombot/channels/transports/discord.d.ts +2 -0
- package/dist/node_modules/@boombot/channels/transports/discord.js +2 -0
- package/dist/node_modules/@boombot/channels/transports/handoff.d.ts +2 -0
- package/dist/node_modules/@boombot/channels/transports/handoff.js +2 -0
- package/dist/node_modules/@boombot/channels/transports/messenger/index.d.ts +1 -0
- package/dist/node_modules/@boombot/channels/transports/messenger/index.js +1 -0
- package/dist/node_modules/@boombot/channels/transports/messenger/transport.d.ts +34 -0
- package/dist/node_modules/@boombot/channels/transports/messenger/transport.js +180 -0
- package/dist/node_modules/@boombot/channels/transports/messenger.d.ts +2 -0
- package/dist/node_modules/@boombot/channels/transports/messenger.js +2 -0
- package/dist/node_modules/@boombot/channels/transports/slack/index.d.ts +1 -0
- package/dist/node_modules/@boombot/channels/transports/slack/index.js +1 -0
- package/dist/node_modules/@boombot/channels/transports/slack/transport.d.ts +35 -0
- package/dist/node_modules/@boombot/channels/transports/slack/transport.js +183 -0
- package/dist/node_modules/@boombot/channels/transports/slack.d.ts +2 -0
- package/dist/node_modules/@boombot/channels/transports/slack.js +2 -0
- package/dist/node_modules/@boombot/channels/transports/streamer/index.d.ts +1 -0
- package/dist/node_modules/@boombot/channels/transports/streamer/index.js +1 -0
- package/dist/node_modules/@boombot/channels/transports/streamer/streamer.d.ts +31 -0
- package/dist/node_modules/@boombot/channels/transports/streamer/streamer.js +141 -0
- package/dist/node_modules/@boombot/channels/transports/streamer.d.ts +2 -0
- package/dist/node_modules/@boombot/channels/transports/streamer.js +2 -0
- package/dist/node_modules/@boombot/channels/transports/telegram/index.d.ts +1 -0
- package/dist/node_modules/@boombot/channels/transports/telegram/index.js +1 -0
- package/dist/node_modules/@boombot/channels/transports/telegram/transport.d.ts +75 -0
- package/dist/node_modules/@boombot/channels/transports/telegram/transport.js +395 -0
- package/dist/node_modules/@boombot/channels/transports/telegram.d.ts +2 -0
- package/dist/node_modules/@boombot/channels/transports/telegram.js +2 -0
- package/dist/node_modules/@boombot/channels/transports/tiktok/index.d.ts +1 -0
- package/dist/node_modules/@boombot/channels/transports/tiktok/index.js +1 -0
- package/dist/node_modules/@boombot/channels/transports/tiktok/transport.d.ts +27 -0
- package/dist/node_modules/@boombot/channels/transports/tiktok/transport.js +97 -0
- package/dist/node_modules/@boombot/channels/transports/tiktok.d.ts +2 -0
- package/dist/node_modules/@boombot/channels/transports/tiktok.js +2 -0
- package/dist/node_modules/@boombot/channels/transports/whatsapp/index.d.ts +1 -0
- package/dist/node_modules/@boombot/channels/transports/whatsapp/index.js +1 -0
- package/dist/node_modules/@boombot/channels/transports/whatsapp/transport.d.ts +38 -0
- package/dist/node_modules/@boombot/channels/transports/whatsapp/transport.js +189 -0
- package/dist/node_modules/@boombot/channels/transports/whatsapp.d.ts +2 -0
- package/dist/node_modules/@boombot/channels/transports/whatsapp.js +2 -0
- package/dist/node_modules/@boombot/channels/transports/zalo/index.d.ts +2 -0
- package/dist/node_modules/@boombot/channels/transports/zalo/index.js +2 -0
- package/dist/node_modules/@boombot/channels/transports/zalo/oa.d.ts +28 -0
- package/dist/node_modules/@boombot/channels/transports/zalo/oa.js +94 -0
- package/dist/node_modules/@boombot/channels/transports/zalo/personal.d.ts +106 -0
- package/dist/node_modules/@boombot/channels/transports/zalo/personal.js +171 -0
- package/dist/node_modules/@boombot/channels/transports/zalo-personal.d.ts +2 -0
- package/dist/node_modules/@boombot/channels/transports/zalo-personal.js +2 -0
- package/dist/node_modules/@boombot/channels/transports/zalo.d.ts +2 -0
- package/dist/node_modules/@boombot/channels/transports/zalo.js +2 -0
- package/dist/node_modules/@boombot/core/agent-core/index.d.ts +12 -0
- package/dist/node_modules/@boombot/core/agent-core/index.js +12 -0
- package/dist/node_modules/@boombot/core/agent-core/middleware.d.ts +60 -0
- package/dist/node_modules/@boombot/core/agent-core/middleware.js +152 -0
- package/dist/node_modules/@boombot/core/agent-core/routing.d.ts +128 -0
- package/dist/node_modules/@boombot/core/agent-core/routing.js +437 -0
- package/dist/node_modules/@boombot/core/agent-core/runtime-deps.d.ts +88 -0
- package/dist/node_modules/@boombot/core/agent-core/runtime-deps.js +8 -0
- package/dist/node_modules/@boombot/core/agent-core/tool-errors.d.ts +44 -0
- package/dist/node_modules/@boombot/core/agent-core/tool-errors.js +60 -0
- package/dist/node_modules/@boombot/core/agent-core/turn-loop.d.ts +21 -0
- package/dist/node_modules/@boombot/core/agent-core/turn-loop.js +561 -0
- package/dist/node_modules/@boombot/core/agent-core/types.d.ts +189 -0
- package/dist/node_modules/@boombot/core/agent-core/types.js +7 -0
- package/dist/node_modules/@boombot/core/compaction/compactor.d.ts +19 -0
- package/dist/node_modules/@boombot/core/compaction/compactor.js +127 -0
- package/dist/node_modules/@boombot/core/compaction/estimator.d.ts +10 -0
- package/dist/node_modules/@boombot/core/compaction/estimator.js +48 -0
- package/dist/node_modules/@boombot/core/compaction/index.d.ts +3 -0
- package/dist/node_modules/@boombot/core/compaction/index.js +3 -0
- package/dist/node_modules/@boombot/core/compaction/types.d.ts +31 -0
- package/dist/node_modules/@boombot/core/compaction/types.js +7 -0
- package/dist/node_modules/@boombot/core/index.d.ts +9 -0
- package/dist/node_modules/@boombot/core/index.js +9 -0
- package/dist/node_modules/@boombot/core/jev/index.d.ts +2 -0
- package/dist/node_modules/@boombot/core/jev/index.js +2 -0
- package/dist/node_modules/@boombot/core/jev/jev.d.ts +30 -0
- package/dist/node_modules/@boombot/core/jev/jev.js +164 -0
- package/dist/node_modules/@boombot/core/jev/types.d.ts +22 -0
- package/dist/node_modules/@boombot/core/jev/types.js +1 -0
- package/dist/node_modules/@boombot/core/memory/consolidation/budget.d.ts +63 -0
- package/dist/node_modules/@boombot/core/memory/consolidation/budget.js +94 -0
- package/dist/node_modules/@boombot/core/memory/consolidation/consolidator.d.ts +152 -0
- package/dist/node_modules/@boombot/core/memory/consolidation/consolidator.js +318 -0
- package/dist/node_modules/@boombot/core/memory/consolidation/index.d.ts +12 -0
- package/dist/node_modules/@boombot/core/memory/consolidation/index.js +12 -0
- package/dist/node_modules/@boombot/core/memory/curation.d.ts +86 -0
- package/dist/node_modules/@boombot/core/memory/curation.js +120 -0
- package/dist/node_modules/@boombot/core/memory/errors.d.ts +12 -0
- package/dist/node_modules/@boombot/core/memory/errors.js +20 -0
- package/dist/node_modules/@boombot/core/memory/hybrid-search.d.ts +29 -0
- package/dist/node_modules/@boombot/core/memory/hybrid-search.js +52 -0
- package/dist/node_modules/@boombot/core/memory/index.d.ts +23 -0
- package/dist/node_modules/@boombot/core/memory/index.js +23 -0
- package/dist/node_modules/@boombot/core/memory/indexer.d.ts +47 -0
- package/dist/node_modules/@boombot/core/memory/indexer.js +138 -0
- package/dist/node_modules/@boombot/core/memory/lifecycle.d.ts +12 -0
- package/dist/node_modules/@boombot/core/memory/lifecycle.js +66 -0
- package/dist/node_modules/@boombot/core/memory/provider.d.ts +84 -0
- package/dist/node_modules/@boombot/core/memory/provider.js +117 -0
- package/dist/node_modules/@boombot/core/memory/recall.d.ts +7 -0
- package/dist/node_modules/@boombot/core/memory/recall.js +111 -0
- package/dist/node_modules/@boombot/core/memory/scope-resolver.d.ts +27 -0
- package/dist/node_modules/@boombot/core/memory/scope-resolver.js +60 -0
- package/dist/node_modules/@boombot/core/memory/search.d.ts +37 -0
- package/dist/node_modules/@boombot/core/memory/search.js +158 -0
- package/dist/node_modules/@boombot/core/memory/store.d.ts +60 -0
- package/dist/node_modules/@boombot/core/memory/store.js +289 -0
- package/dist/node_modules/@boombot/core/memory/types.d.ts +121 -0
- package/dist/node_modules/@boombot/core/memory/types.js +21 -0
- package/dist/node_modules/@boombot/core/memory/vector-index.d.ts +34 -0
- package/dist/node_modules/@boombot/core/memory/vector-index.js +65 -0
- package/dist/node_modules/@boombot/core/package.json +9 -0
- package/dist/node_modules/@boombot/core/reflection/classifier.d.ts +13 -0
- package/dist/node_modules/@boombot/core/reflection/classifier.js +77 -0
- package/dist/node_modules/@boombot/core/reflection/index.d.ts +2 -0
- package/dist/node_modules/@boombot/core/reflection/index.js +2 -0
- package/dist/node_modules/@boombot/core/reflection/types.d.ts +13 -0
- package/dist/node_modules/@boombot/core/reflection/types.js +4 -0
- package/dist/node_modules/@boombot/core/research/config.d.ts +89 -0
- package/dist/node_modules/@boombot/core/research/config.js +206 -0
- package/dist/node_modules/@boombot/core/research/crawl.d.ts +36 -0
- package/dist/node_modules/@boombot/core/research/crawl.js +179 -0
- package/dist/node_modules/@boombot/core/research/factory.d.ts +26 -0
- package/dist/node_modules/@boombot/core/research/factory.js +46 -0
- package/dist/node_modules/@boombot/core/research/http.d.ts +87 -0
- package/dist/node_modules/@boombot/core/research/http.js +250 -0
- package/dist/node_modules/@boombot/core/research/index.d.ts +17 -0
- package/dist/node_modules/@boombot/core/research/index.js +10 -0
- package/dist/node_modules/@boombot/core/research/orchestrator.d.ts +113 -0
- package/dist/node_modules/@boombot/core/research/orchestrator.js +252 -0
- package/dist/node_modules/@boombot/core/research/parse/docx.d.ts +24 -0
- package/dist/node_modules/@boombot/core/research/parse/docx.js +183 -0
- package/dist/node_modules/@boombot/core/research/parse/guards.d.ts +89 -0
- package/dist/node_modules/@boombot/core/research/parse/guards.js +171 -0
- package/dist/node_modules/@boombot/core/research/parse/index.d.ts +68 -0
- package/dist/node_modules/@boombot/core/research/parse/index.js +219 -0
- package/dist/node_modules/@boombot/core/research/parse/pdf.d.ts +38 -0
- package/dist/node_modules/@boombot/core/research/parse/pdf.js +567 -0
- package/dist/node_modules/@boombot/core/research/providers/arxiv.d.ts +9 -0
- package/dist/node_modules/@boombot/core/research/providers/arxiv.js +72 -0
- package/dist/node_modules/@boombot/core/research/providers/brave.d.ts +11 -0
- package/dist/node_modules/@boombot/core/research/providers/brave.js +36 -0
- package/dist/node_modules/@boombot/core/research/providers/duckduckgo.d.ts +9 -0
- package/dist/node_modules/@boombot/core/research/providers/duckduckgo.js +78 -0
- package/dist/node_modules/@boombot/core/research/providers/exa.d.ts +11 -0
- package/dist/node_modules/@boombot/core/research/providers/exa.js +34 -0
- package/dist/node_modules/@boombot/core/research/providers/firecrawl.d.ts +16 -0
- package/dist/node_modules/@boombot/core/research/providers/firecrawl.js +47 -0
- package/dist/node_modules/@boombot/core/research/providers/index.d.ts +17 -0
- package/dist/node_modules/@boombot/core/research/providers/index.js +11 -0
- package/dist/node_modules/@boombot/core/research/providers/jina.d.ts +13 -0
- package/dist/node_modules/@boombot/core/research/providers/jina.js +114 -0
- package/dist/node_modules/@boombot/core/research/providers/openalex.d.ts +14 -0
- package/dist/node_modules/@boombot/core/research/providers/openalex.js +66 -0
- package/dist/node_modules/@boombot/core/research/providers/semantic-scholar.d.ts +9 -0
- package/dist/node_modules/@boombot/core/research/providers/semantic-scholar.js +56 -0
- package/dist/node_modules/@boombot/core/research/providers/tavily.d.ts +11 -0
- package/dist/node_modules/@boombot/core/research/providers/tavily.js +35 -0
- package/dist/node_modules/@boombot/core/research/providers/wikipedia.d.ts +12 -0
- package/dist/node_modules/@boombot/core/research/providers/wikipedia.js +47 -0
- package/dist/node_modules/@boombot/core/research/tools.d.ts +27 -0
- package/dist/node_modules/@boombot/core/research/tools.js +251 -0
- package/dist/node_modules/@boombot/core/research/types.d.ts +133 -0
- package/dist/node_modules/@boombot/core/research/types.js +8 -0
- package/dist/node_modules/@boombot/core/research/wiring.d.ts +25 -0
- package/dist/node_modules/@boombot/core/research/wiring.js +51 -0
- package/dist/node_modules/@boombot/core/scheduler/cron.d.ts +34 -0
- package/dist/node_modules/@boombot/core/scheduler/cron.js +147 -0
- package/dist/node_modules/@boombot/core/scheduler/evaluator.d.ts +42 -0
- package/dist/node_modules/@boombot/core/scheduler/evaluator.js +148 -0
- package/dist/node_modules/@boombot/core/scheduler/index.d.ts +15 -0
- package/dist/node_modules/@boombot/core/scheduler/index.js +15 -0
- package/dist/node_modules/@boombot/core/scheduler/registry.d.ts +81 -0
- package/dist/node_modules/@boombot/core/scheduler/registry.js +263 -0
- package/dist/node_modules/@boombot/core/scheduler/runner.d.ts +59 -0
- package/dist/node_modules/@boombot/core/scheduler/runner.js +257 -0
- package/dist/node_modules/@boombot/core/scheduler/store.d.ts +150 -0
- package/dist/node_modules/@boombot/core/scheduler/store.js +526 -0
- package/dist/node_modules/@boombot/core/scheduler/timezone.d.ts +35 -0
- package/dist/node_modules/@boombot/core/scheduler/timezone.js +96 -0
- package/dist/node_modules/@boombot/core/scheduler/types.d.ts +157 -0
- package/dist/node_modules/@boombot/core/scheduler/types.js +89 -0
- package/dist/node_modules/@boombot/core/task-runner/index.d.ts +7 -0
- package/dist/node_modules/@boombot/core/task-runner/index.js +5 -0
- package/dist/node_modules/@boombot/core/task-runner/planner.d.ts +37 -0
- package/dist/node_modules/@boombot/core/task-runner/planner.js +154 -0
- package/dist/node_modules/@boombot/core/task-runner/runner.d.ts +8 -0
- package/dist/node_modules/@boombot/core/task-runner/runner.js +564 -0
- package/dist/node_modules/@boombot/core/task-runner/store.d.ts +28 -0
- package/dist/node_modules/@boombot/core/task-runner/store.js +126 -0
- package/dist/node_modules/@boombot/core/task-runner/types.d.ts +138 -0
- package/dist/node_modules/@boombot/core/task-runner/types.js +11 -0
- package/dist/node_modules/@boombot/core/workflow/dag.d.ts +16 -0
- package/dist/node_modules/@boombot/core/workflow/dag.js +109 -0
- package/dist/node_modules/@boombot/core/workflow/engine.d.ts +34 -0
- package/dist/node_modules/@boombot/core/workflow/engine.js +304 -0
- package/dist/node_modules/@boombot/core/workflow/index.d.ts +3 -0
- package/dist/node_modules/@boombot/core/workflow/index.js +3 -0
- package/dist/node_modules/@boombot/core/workflow/types.d.ts +98 -0
- package/dist/node_modules/@boombot/core/workflow/types.js +21 -0
- package/dist/node_modules/@boombot/cronjobs/handlers.d.ts +11 -0
- package/dist/node_modules/@boombot/cronjobs/handlers.js +174 -0
- package/dist/node_modules/@boombot/cronjobs/index.d.ts +2 -0
- package/dist/node_modules/@boombot/cronjobs/index.js +2 -0
- package/dist/node_modules/@boombot/cronjobs/package.json +9 -0
- package/dist/node_modules/@boombot/cronjobs/service.d.ts +53 -0
- package/dist/node_modules/@boombot/cronjobs/service.js +200 -0
- package/dist/node_modules/@boombot/plugins/index.d.ts +2 -0
- package/dist/node_modules/@boombot/plugins/index.js +2 -0
- package/dist/node_modules/@boombot/plugins/installer.d.ts +45 -0
- package/dist/node_modules/@boombot/plugins/installer.js +487 -0
- package/dist/node_modules/@boombot/plugins/manager.d.ts +23 -0
- package/dist/node_modules/@boombot/plugins/manager.js +243 -0
- package/dist/node_modules/@boombot/plugins/package.json +9 -0
- package/dist/node_modules/@boombot/protocol/gateway-protocol/commands-channels.d.ts +125 -0
- package/dist/node_modules/@boombot/protocol/gateway-protocol/commands-channels.js +76 -0
- package/dist/node_modules/@boombot/protocol/gateway-protocol/commands-plugins.d.ts +220 -0
- package/dist/node_modules/@boombot/protocol/gateway-protocol/commands-plugins.js +60 -0
- package/dist/node_modules/@boombot/protocol/gateway-protocol/commands-scheduler.d.ts +33 -0
- package/dist/node_modules/@boombot/protocol/gateway-protocol/commands-scheduler.js +25 -0
- package/dist/node_modules/@boombot/protocol/gateway-protocol/commands.d.ts +4349 -0
- package/dist/node_modules/@boombot/protocol/gateway-protocol/commands.js +563 -0
- package/dist/node_modules/@boombot/protocol/gateway-protocol/envelope.d.ts +32 -0
- package/dist/node_modules/@boombot/protocol/gateway-protocol/envelope.js +61 -0
- package/dist/node_modules/@boombot/protocol/gateway-protocol/errors.d.ts +13 -0
- package/dist/node_modules/@boombot/protocol/gateway-protocol/errors.js +16 -0
- package/dist/node_modules/@boombot/protocol/gateway-protocol/events.d.ts +567 -0
- package/dist/node_modules/@boombot/protocol/gateway-protocol/events.js +395 -0
- package/dist/node_modules/@boombot/protocol/gateway-protocol/index.d.ts +20 -0
- package/dist/node_modules/@boombot/protocol/gateway-protocol/index.js +13 -0
- package/dist/node_modules/@boombot/protocol/gateway-protocol/types.d.ts +91 -0
- package/dist/node_modules/@boombot/protocol/gateway-protocol/types.js +7 -0
- package/dist/node_modules/@boombot/protocol/index.d.ts +4 -0
- package/dist/node_modules/@boombot/protocol/index.js +3 -0
- package/dist/node_modules/@boombot/protocol/package.json +9 -0
- package/dist/node_modules/@boombot/protocol/plugin-sdk/channel.d.ts +41 -0
- package/dist/node_modules/@boombot/protocol/plugin-sdk/channel.js +17 -0
- package/dist/node_modules/@boombot/protocol/plugin-sdk/index.d.ts +10 -0
- package/dist/node_modules/@boombot/protocol/plugin-sdk/index.js +10 -0
- package/dist/node_modules/@boombot/protocol/plugin-sdk/manifest.d.ts +58 -0
- package/dist/node_modules/@boombot/protocol/plugin-sdk/manifest.js +116 -0
- package/dist/node_modules/@boombot/protocol/plugin-sdk/plugin.d.ts +25 -0
- package/dist/node_modules/@boombot/protocol/plugin-sdk/plugin.js +1 -0
- package/dist/node_modules/@boombot/protocol/providers/cipher.d.ts +7 -0
- package/dist/node_modules/@boombot/protocol/providers/cipher.js +52 -0
- package/dist/node_modules/@boombot/protocol/providers/index.d.ts +19 -0
- package/dist/node_modules/@boombot/protocol/providers/index.js +19 -0
- package/dist/node_modules/@boombot/protocol/providers/key-roulette.d.ts +79 -0
- package/dist/node_modules/@boombot/protocol/providers/key-roulette.js +81 -0
- package/dist/node_modules/@boombot/protocol/providers/probe.d.ts +29 -0
- package/dist/node_modules/@boombot/protocol/providers/probe.js +96 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/anthropic.d.ts +11 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/anthropic.js +11 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/custom.d.ts +22 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/custom.js +222 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/deepseek.d.ts +7 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/deepseek.js +9 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/google.d.ts +10 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/google.js +10 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/index.d.ts +31 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/index.js +56 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/local.d.ts +10 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/local.js +11 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/mistral.d.ts +7 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/mistral.js +9 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/openai-compatible.d.ts +10 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/openai-compatible.js +10 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/openai.d.ts +7 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/openai.js +11 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/types.d.ts +58 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/types.js +1 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/xai.d.ts +7 -0
- package/dist/node_modules/@boombot/protocol/providers/profiles/xai.js +10 -0
- package/dist/node_modules/@boombot/protocol/providers/request-profile.d.ts +102 -0
- package/dist/node_modules/@boombot/protocol/providers/request-profile.js +118 -0
- package/dist/node_modules/@boombot/protocol/providers/service.d.ts +2 -0
- package/dist/node_modules/@boombot/protocol/providers/service.js +418 -0
- package/dist/node_modules/@boombot/protocol/providers/types.d.ts +141 -0
- package/dist/node_modules/@boombot/protocol/providers/types.js +16 -0
- package/dist/node_modules/@boombot/sandbox/fs-path.d.ts +13 -0
- package/dist/node_modules/@boombot/sandbox/fs-path.js +79 -0
- package/dist/node_modules/@boombot/sandbox/index.d.ts +13 -0
- package/dist/node_modules/@boombot/sandbox/index.js +13 -0
- package/dist/node_modules/@boombot/sandbox/native.d.ts +39 -0
- package/dist/node_modules/@boombot/sandbox/native.js +224 -0
- package/dist/node_modules/@boombot/sandbox/package.json +9 -0
- package/dist/node_modules/@boombot/sandbox/sandbox.d.ts +92 -0
- package/dist/node_modules/@boombot/sandbox/sandbox.js +229 -0
- package/dist/node_modules/@boombot/security/harness-guard/boundary.d.ts +22 -0
- package/dist/node_modules/@boombot/security/harness-guard/boundary.js +105 -0
- package/dist/node_modules/@boombot/security/harness-guard/gates.d.ts +90 -0
- package/dist/node_modules/@boombot/security/harness-guard/gates.js +791 -0
- package/dist/node_modules/@boombot/security/harness-guard/index.d.ts +23 -0
- package/dist/node_modules/@boombot/security/harness-guard/index.js +23 -0
- package/dist/node_modules/@boombot/security/harness-guard/policy.d.ts +20 -0
- package/dist/node_modules/@boombot/security/harness-guard/policy.js +70 -0
- package/dist/node_modules/@boombot/security/harness-guard/sanitizer.d.ts +53 -0
- package/dist/node_modules/@boombot/security/harness-guard/sanitizer.js +145 -0
- package/dist/node_modules/@boombot/security/harness-guard/types.d.ts +71 -0
- package/dist/node_modules/@boombot/security/harness-guard/types.js +10 -0
- package/dist/node_modules/@boombot/security/harness-guard/verifier.d.ts +59 -0
- package/dist/node_modules/@boombot/security/harness-guard/verifier.js +169 -0
- package/dist/node_modules/@boombot/security/index.d.ts +5 -0
- package/dist/node_modules/@boombot/security/index.js +9 -0
- package/dist/node_modules/@boombot/security/package.json +9 -0
- package/dist/node_modules/@boombot/security/policy/approval.d.ts +117 -0
- package/dist/node_modules/@boombot/security/policy/approval.js +223 -0
- package/dist/node_modules/@boombot/security/reasoning-guard/claim-extractor.d.ts +10 -0
- package/dist/node_modules/@boombot/security/reasoning-guard/claim-extractor.js +124 -0
- package/dist/node_modules/@boombot/security/reasoning-guard/evidence-ledger.d.ts +25 -0
- package/dist/node_modules/@boombot/security/reasoning-guard/evidence-ledger.js +70 -0
- package/dist/node_modules/@boombot/security/reasoning-guard/gate.d.ts +38 -0
- package/dist/node_modules/@boombot/security/reasoning-guard/gate.js +61 -0
- package/dist/node_modules/@boombot/security/reasoning-guard/grounding-check.d.ts +12 -0
- package/dist/node_modules/@boombot/security/reasoning-guard/grounding-check.js +234 -0
- package/dist/node_modules/@boombot/security/reasoning-guard/index.d.ts +17 -0
- package/dist/node_modules/@boombot/security/reasoning-guard/index.js +13 -0
- package/dist/node_modules/@boombot/security/reasoning-guard/policy.d.ts +15 -0
- package/dist/node_modules/@boombot/security/reasoning-guard/policy.js +39 -0
- package/dist/node_modules/@boombot/security/reasoning-guard/types.d.ts +46 -0
- package/dist/node_modules/@boombot/security/reasoning-guard/types.js +7 -0
- package/dist/node_modules/@boombot/security/security/approval.d.ts +63 -0
- package/dist/node_modules/@boombot/security/security/approval.js +140 -0
- package/dist/node_modules/@boombot/security/security/audit.d.ts +39 -0
- package/dist/node_modules/@boombot/security/security/audit.js +70 -0
- package/dist/node_modules/@boombot/security/security/index.d.ts +12 -0
- package/dist/node_modules/@boombot/security/security/index.js +12 -0
- package/dist/node_modules/@boombot/security/security/trust.d.ts +79 -0
- package/dist/node_modules/@boombot/security/security/trust.js +87 -0
- package/dist/package.json +5 -0
- package/dist/proto/agent_core.proto +56 -0
- package/dist/python/agent-core-python/pyproject.toml +40 -0
- package/dist/python/agent-core-python/src/boombot_agent/__init__.py +5 -0
- package/dist/python/agent-core-python/src/boombot_agent/generated/__init__.py +0 -0
- package/dist/python/agent-core-python/src/boombot_agent/generated/agent_core_pb2.py +54 -0
- package/dist/python/agent-core-python/src/boombot_agent/generated/agent_core_pb2_grpc.py +140 -0
- package/dist/python/agent-core-python/src/boombot_agent/rpc.py +265 -0
- package/dist/python/agent-core-python/src/boombot_agent/turn.py +577 -0
- package/dist/python/agent-core-python/src/boombot_ml/__init__.py +12 -0
- package/dist/python/agent-core-python/src/boombot_ml/embeddings.py +58 -0
- package/dist/python/agent-core-python/src/boombot_ml/training.py +156 -0
- package/dist/python/agent-core-python/uv.lock +2856 -0
- package/dist/web/assets/ChatView-BZrSD-64.js +262 -0
- package/dist/web/assets/ChatView-Cahbjez6.css +1 -0
- package/dist/web/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/dist/web/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/dist/web/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/dist/web/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/dist/web/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/dist/web/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/dist/web/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/dist/web/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/dist/web/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/dist/web/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/dist/web/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/dist/web/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/dist/web/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/dist/web/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/dist/web/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/dist/web/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/dist/web/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/dist/web/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/dist/web/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/dist/web/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/dist/web/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/dist/web/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/dist/web/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/dist/web/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/dist/web/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/dist/web/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/dist/web/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/dist/web/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/dist/web/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/dist/web/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/dist/web/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/dist/web/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/dist/web/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/dist/web/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/dist/web/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/dist/web/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/dist/web/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/dist/web/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/dist/web/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/dist/web/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/dist/web/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/dist/web/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/dist/web/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/dist/web/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/dist/web/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/dist/web/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/dist/web/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/dist/web/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/dist/web/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/dist/web/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/dist/web/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/dist/web/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/dist/web/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/dist/web/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/dist/web/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/dist/web/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/dist/web/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/dist/web/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/dist/web/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/dist/web/assets/MemoryView-BJbXqqs7.css +1 -0
- package/dist/web/assets/MemoryView-BfMq_6CD.js +1 -0
- package/dist/web/assets/SchedulesView-B22QmPR-.js +1 -0
- package/dist/web/assets/SchedulesView-C6XK7A8a.css +1 -0
- package/dist/web/assets/SessionsView-C1dqdhxI.css +1 -0
- package/dist/web/assets/SessionsView-DS0-aH2a.js +1 -0
- package/dist/web/assets/TasksView-Dtasg4hd.css +1 -0
- package/dist/web/assets/TasksView-ey0FLsW8.js +2 -0
- package/dist/web/assets/Textarea-DN3Zybl1.js +1 -0
- package/dist/web/assets/Tooltip-Bn2cqFPz.css +1 -0
- package/dist/web/assets/Tooltip-MzV2Gqnc.js +1 -0
- package/dist/web/assets/browser-Bnt73-Ub.js +8 -0
- package/dist/web/assets/index-BL8bi7Yt.css +1 -0
- package/dist/web/assets/index-CuPR73Tn.js +73 -0
- package/dist/web/favicon.svg +4 -0
- package/dist/web/index.html +26 -0
- package/dist/web/logo.jpg +0 -0
- package/dist/web/logo.png +0 -0
- package/package.json +51 -4
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
// Background task runner: durable multi-step tasks executed through an
|
|
2
|
+
// injected, transport-agnostic TurnRunner. Depends only on node builtins.
|
|
3
|
+
//
|
|
4
|
+
// Concurrency model:
|
|
5
|
+
// - One AbortController per task (taskId -> controller).
|
|
6
|
+
// - One background loop per task at most (activeLoops guard).
|
|
7
|
+
// - Steps run sequentially inside a task; tasks run concurrently.
|
|
8
|
+
// - HITL: when a turn reports approval_required, the task parks in
|
|
9
|
+
// awaiting_approval WITHOUT aborting the turn — the turn service holds the
|
|
10
|
+
// runTurn promise open. resume(id, decision) delivers the verdict.
|
|
11
|
+
import { randomUUID } from 'node:crypto';
|
|
12
|
+
import { TaskError } from './types.js';
|
|
13
|
+
function nowIso() {
|
|
14
|
+
return new Date().toISOString();
|
|
15
|
+
}
|
|
16
|
+
function isRetryableStatus(status) {
|
|
17
|
+
return status === 'failed' || status === 'cancelled' || status === 'interrupted';
|
|
18
|
+
}
|
|
19
|
+
export function createTaskRunner(options) {
|
|
20
|
+
const { store, turnRunner, onEvent } = options;
|
|
21
|
+
const controllers = new Map();
|
|
22
|
+
const activeLoops = new Set();
|
|
23
|
+
/**
|
|
24
|
+
* Per-task mutex serializing every read-modify-save section.
|
|
25
|
+
*
|
|
26
|
+
* The store hands out copies (`structuredClone`) and `save()` is a blind
|
|
27
|
+
* upsert, so two interleaved read-modify-save sequences silently lose one
|
|
28
|
+
* update (last writer wins): a `pause()` racing a completing turn could be
|
|
29
|
+
* silently undone, or a fresh checkpoint wiped, depending on which save
|
|
30
|
+
* landed last. Sections never hold the lock across `runTurn` or other
|
|
31
|
+
* I/O — only across the synchronous read-modify plus the `save()` itself
|
|
32
|
+
* — so control-plane calls stay responsive, and the lock is never nested
|
|
33
|
+
* (no deadlock).
|
|
34
|
+
*/
|
|
35
|
+
const taskLocks = new Map();
|
|
36
|
+
async function withTaskLock(taskId, fn) {
|
|
37
|
+
const prev = taskLocks.get(taskId) ?? Promise.resolve();
|
|
38
|
+
let release;
|
|
39
|
+
const gate = new Promise((resolve) => {
|
|
40
|
+
release = resolve;
|
|
41
|
+
});
|
|
42
|
+
const chained = prev.then(() => gate);
|
|
43
|
+
taskLocks.set(taskId, chained);
|
|
44
|
+
await prev;
|
|
45
|
+
try {
|
|
46
|
+
return await fn();
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
release();
|
|
50
|
+
if (taskLocks.get(taskId) === chained) {
|
|
51
|
+
taskLocks.delete(taskId);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Turn results that settled while their task was in awaiting_approval.
|
|
57
|
+
* resume(id, { approved: true }) applies the stashed result; this covers
|
|
58
|
+
* transports that resolve runTurn at the same time as (or just before)
|
|
59
|
+
* reporting approval_required.
|
|
60
|
+
*/
|
|
61
|
+
const pendingTurnResults = new Map();
|
|
62
|
+
function emit(event) {
|
|
63
|
+
try {
|
|
64
|
+
onEvent?.(event);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// A listener must never break the runner.
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function requireTask(id) {
|
|
71
|
+
const task = store.get(id);
|
|
72
|
+
if (task === null) {
|
|
73
|
+
throw new TaskError('NOT_FOUND', `Task ${id} not found`);
|
|
74
|
+
}
|
|
75
|
+
return task;
|
|
76
|
+
}
|
|
77
|
+
async function saveAndSnapshot(task) {
|
|
78
|
+
task.updatedAt = nowIso();
|
|
79
|
+
await store.save(task);
|
|
80
|
+
const snapshot = store.get(task.id);
|
|
81
|
+
if (snapshot === null) {
|
|
82
|
+
throw new TaskError('STORAGE', `Task ${task.id} vanished after save`);
|
|
83
|
+
}
|
|
84
|
+
return snapshot;
|
|
85
|
+
}
|
|
86
|
+
async function failTask(task, error) {
|
|
87
|
+
task.status = 'failed';
|
|
88
|
+
task.error = error;
|
|
89
|
+
const snapshot = await saveAndSnapshot(task);
|
|
90
|
+
emit({ type: 'task.failed', taskId: task.id, error });
|
|
91
|
+
return snapshot;
|
|
92
|
+
}
|
|
93
|
+
async function failStep(task, stepIndex, error) {
|
|
94
|
+
const step = task.steps[stepIndex];
|
|
95
|
+
if (step !== undefined) {
|
|
96
|
+
step.status = 'failed';
|
|
97
|
+
step.error = error;
|
|
98
|
+
step.endedAt = nowIso();
|
|
99
|
+
}
|
|
100
|
+
return failTask(task, error);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Record a finished turn against its step. Safe to call from both the
|
|
104
|
+
* background loop and resume(): it no-ops unless the task is running and
|
|
105
|
+
* the step is still the in-flight one.
|
|
106
|
+
*/
|
|
107
|
+
async function applyTurnResult(taskId, stepIndex, result) {
|
|
108
|
+
await withTaskLock(taskId, async () => {
|
|
109
|
+
const task = store.get(taskId);
|
|
110
|
+
if (task === null || task.status !== 'running')
|
|
111
|
+
return;
|
|
112
|
+
const step = task.steps[stepIndex];
|
|
113
|
+
if (step === undefined || step.status !== 'running')
|
|
114
|
+
return;
|
|
115
|
+
if (result.status === 'completed') {
|
|
116
|
+
if (result.sessionId !== undefined)
|
|
117
|
+
task.sessionId = result.sessionId;
|
|
118
|
+
step.status = 'done';
|
|
119
|
+
if (result.output !== undefined)
|
|
120
|
+
step.output = result.output;
|
|
121
|
+
step.endedAt = nowIso();
|
|
122
|
+
task.messageQueue = []; // redirects are consumed by this successful step
|
|
123
|
+
task.checkpoints.push({ stepIndex, at: nowIso() });
|
|
124
|
+
task.currentStepIndex = stepIndex + 1;
|
|
125
|
+
await saveAndSnapshot(task);
|
|
126
|
+
emit({ type: 'task.checkpoint', taskId, stepIndex });
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
await failStep(task, stepIndex, result.error ?? 'turn failed');
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
async function handleApprovalRequired(taskId, event) {
|
|
134
|
+
await withTaskLock(taskId, async () => {
|
|
135
|
+
const task = store.get(taskId);
|
|
136
|
+
// Ignore stale events (pause/cancel won the race).
|
|
137
|
+
if (task === null || task.status !== 'running')
|
|
138
|
+
return;
|
|
139
|
+
// NOTE: the turn is NOT aborted — the turn service keeps the runTurn
|
|
140
|
+
// promise open and waits for resume(id, decision).
|
|
141
|
+
task.status = 'awaiting_approval';
|
|
142
|
+
task.approval = {
|
|
143
|
+
runId: event.runId,
|
|
144
|
+
toolName: event.toolName,
|
|
145
|
+
args: event.args,
|
|
146
|
+
reason: event.reason,
|
|
147
|
+
};
|
|
148
|
+
await saveAndSnapshot(task);
|
|
149
|
+
emit({
|
|
150
|
+
type: 'task.awaiting_approval',
|
|
151
|
+
taskId,
|
|
152
|
+
runId: event.runId,
|
|
153
|
+
toolName: event.toolName,
|
|
154
|
+
reason: event.reason,
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
async function runStep(taskId, stepIndex) {
|
|
159
|
+
// The read-modify-save is locked; the turn itself runs outside the lock.
|
|
160
|
+
const started = await withTaskLock(taskId, async () => {
|
|
161
|
+
const task = store.get(taskId);
|
|
162
|
+
if (task === null || task.status !== 'running')
|
|
163
|
+
return undefined;
|
|
164
|
+
const step = task.steps[stepIndex];
|
|
165
|
+
if (step === undefined || step.status !== 'pending')
|
|
166
|
+
return undefined;
|
|
167
|
+
// Drain redirect queue into this step's prompt. The queue is cleared only
|
|
168
|
+
// when the step succeeds, so a pause/failure never loses a redirect.
|
|
169
|
+
let prompt = step.prompt;
|
|
170
|
+
if (task.messageQueue.length > 0) {
|
|
171
|
+
const redirects = task.messageQueue.map((m) => `User redirect: ${m}`).join('\n');
|
|
172
|
+
prompt = `${redirects}\n\n${prompt}`;
|
|
173
|
+
}
|
|
174
|
+
step.status = 'running';
|
|
175
|
+
step.attempts += 1;
|
|
176
|
+
step.startedAt = nowIso();
|
|
177
|
+
delete step.error;
|
|
178
|
+
task.currentStepIndex = stepIndex;
|
|
179
|
+
await saveAndSnapshot(task);
|
|
180
|
+
emit({ type: 'task.progress', taskId, stepIndex, totalSteps: task.steps.length });
|
|
181
|
+
return { prompt, sessionId: task.sessionId };
|
|
182
|
+
});
|
|
183
|
+
if (started === undefined)
|
|
184
|
+
return;
|
|
185
|
+
const controller = new AbortController();
|
|
186
|
+
controllers.set(taskId, controller);
|
|
187
|
+
let result;
|
|
188
|
+
try {
|
|
189
|
+
result = await turnRunner.runTurn({
|
|
190
|
+
prompt: started.prompt,
|
|
191
|
+
...(started.sessionId !== undefined ? { sessionId: started.sessionId } : {}),
|
|
192
|
+
signal: controller.signal,
|
|
193
|
+
onEvent: (e) => {
|
|
194
|
+
if (e.type === 'approval_required') {
|
|
195
|
+
void handleApprovalRequired(taskId, e).catch(() => undefined);
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
catch (err) {
|
|
201
|
+
controllers.delete(taskId);
|
|
202
|
+
const aborted = controller.signal.aborted;
|
|
203
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
204
|
+
await withTaskLock(taskId, async () => {
|
|
205
|
+
const fresh = store.get(taskId);
|
|
206
|
+
// pause/cancel/reject already transitioned the task; nothing to do.
|
|
207
|
+
if (fresh === null || fresh.status !== 'running')
|
|
208
|
+
return;
|
|
209
|
+
if (aborted)
|
|
210
|
+
return;
|
|
211
|
+
await failStep(fresh, stepIndex, message);
|
|
212
|
+
});
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
controllers.delete(taskId);
|
|
216
|
+
const fresh = store.get(taskId);
|
|
217
|
+
if (fresh === null)
|
|
218
|
+
return;
|
|
219
|
+
if (fresh.status === 'awaiting_approval') {
|
|
220
|
+
// The turn settled while (or just as) approval was requested.
|
|
221
|
+
// Stash it; an approving resume() will apply it.
|
|
222
|
+
pendingTurnResults.set(taskId, { stepIndex, result });
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
if (fresh.status !== 'running')
|
|
226
|
+
return; // paused/cancelled meanwhile
|
|
227
|
+
await applyTurnResult(taskId, stepIndex, result);
|
|
228
|
+
}
|
|
229
|
+
async function runLoop(taskId) {
|
|
230
|
+
if (activeLoops.has(taskId))
|
|
231
|
+
return; // guard double-start
|
|
232
|
+
activeLoops.add(taskId);
|
|
233
|
+
try {
|
|
234
|
+
for (;;) {
|
|
235
|
+
const task = store.get(taskId);
|
|
236
|
+
if (task === null || task.status !== 'running')
|
|
237
|
+
return;
|
|
238
|
+
// Never start a second step while one is still in flight
|
|
239
|
+
// (e.g. a turn parked on approval whose loop was restarted).
|
|
240
|
+
const inFlight = task.steps.some((s) => s.status === 'running');
|
|
241
|
+
if (inFlight)
|
|
242
|
+
return;
|
|
243
|
+
const nextIndex = task.steps.findIndex((s) => s.status === 'pending');
|
|
244
|
+
if (nextIndex === -1) {
|
|
245
|
+
await completeTask(taskId);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
await runStep(taskId, nextIndex);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
catch (err) {
|
|
252
|
+
// Defensive: an unexpected loop error fails the task instead of
|
|
253
|
+
// silently abandoning it.
|
|
254
|
+
try {
|
|
255
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
256
|
+
await withTaskLock(taskId, async () => {
|
|
257
|
+
const task = store.get(taskId);
|
|
258
|
+
if (task !== null && task.status === 'running') {
|
|
259
|
+
await failTask(task, message);
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
// Nothing left to do.
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
finally {
|
|
268
|
+
activeLoops.delete(taskId);
|
|
269
|
+
controllers.delete(taskId);
|
|
270
|
+
// NOTE: pendingTurnResults is intentionally NOT cleared here — a loop
|
|
271
|
+
// can exit while parked on approval_required, and resume() still needs
|
|
272
|
+
// the stashed turn result. cancel()/retry()/recover() clear it.
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
async function completeTask(taskId) {
|
|
276
|
+
await withTaskLock(taskId, async () => {
|
|
277
|
+
const task = store.get(taskId);
|
|
278
|
+
if (task === null || task.status !== 'running')
|
|
279
|
+
return;
|
|
280
|
+
task.status = 'completed';
|
|
281
|
+
delete task.error;
|
|
282
|
+
await saveAndSnapshot(task);
|
|
283
|
+
emit({ type: 'task.completed', taskId });
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
async function createAndStart(input) {
|
|
287
|
+
const title = input.title.trim();
|
|
288
|
+
if (title === '') {
|
|
289
|
+
throw new TaskError('INVALID_STATE', 'Task title must not be empty');
|
|
290
|
+
}
|
|
291
|
+
if (input.steps.length === 0) {
|
|
292
|
+
throw new TaskError('INVALID_STATE', 'Task must have at least one step');
|
|
293
|
+
}
|
|
294
|
+
input.steps.forEach((s, i) => {
|
|
295
|
+
if (s.prompt.trim() === '') {
|
|
296
|
+
throw new TaskError('INVALID_STATE', `Step ${i} prompt must not be empty`);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
const at = nowIso();
|
|
300
|
+
const steps = input.steps.map((s, index) => ({
|
|
301
|
+
id: randomUUID(),
|
|
302
|
+
index,
|
|
303
|
+
kind: 'turn',
|
|
304
|
+
prompt: s.prompt,
|
|
305
|
+
status: 'pending',
|
|
306
|
+
attempts: 0,
|
|
307
|
+
}));
|
|
308
|
+
const task = {
|
|
309
|
+
id: randomUUID(),
|
|
310
|
+
title,
|
|
311
|
+
status: 'queued',
|
|
312
|
+
steps,
|
|
313
|
+
currentStepIndex: 0,
|
|
314
|
+
checkpoints: [],
|
|
315
|
+
messageQueue: [],
|
|
316
|
+
createdAt: at,
|
|
317
|
+
updatedAt: at,
|
|
318
|
+
};
|
|
319
|
+
await store.create(task);
|
|
320
|
+
emit({ type: 'task.created', taskId: task.id });
|
|
321
|
+
task.status = 'running';
|
|
322
|
+
const snapshot = await saveAndSnapshot(task);
|
|
323
|
+
// Fire-and-forget: the caller never blocks. runLoop funnels every error
|
|
324
|
+
// into task.failed + persist, so this cannot reject.
|
|
325
|
+
void runLoop(task.id);
|
|
326
|
+
return snapshot;
|
|
327
|
+
}
|
|
328
|
+
async function get(id) {
|
|
329
|
+
return store.get(id);
|
|
330
|
+
}
|
|
331
|
+
async function list() {
|
|
332
|
+
return store.list();
|
|
333
|
+
}
|
|
334
|
+
async function pause(id) {
|
|
335
|
+
const snapshot = await withTaskLock(id, async () => {
|
|
336
|
+
const task = requireTask(id);
|
|
337
|
+
if (task.status !== 'running') {
|
|
338
|
+
throw new TaskError('INVALID_STATE', `Cannot pause task in status '${task.status}'`);
|
|
339
|
+
}
|
|
340
|
+
task.status = 'paused';
|
|
341
|
+
const current = task.steps[task.currentStepIndex];
|
|
342
|
+
if (current !== undefined && current.status === 'running') {
|
|
343
|
+
current.status = 'pending';
|
|
344
|
+
current.endedAt = nowIso();
|
|
345
|
+
}
|
|
346
|
+
const snapshot = await saveAndSnapshot(task);
|
|
347
|
+
emit({ type: 'task.paused', taskId: id });
|
|
348
|
+
return snapshot;
|
|
349
|
+
});
|
|
350
|
+
// Abort outside the lock: the in-flight turn's rejection handler takes
|
|
351
|
+
// the same lock, so aborting while holding it would only add latency.
|
|
352
|
+
controllers.get(id)?.abort();
|
|
353
|
+
return snapshot;
|
|
354
|
+
}
|
|
355
|
+
async function resume(id, decision) {
|
|
356
|
+
const task = requireTask(id);
|
|
357
|
+
if (task.status === 'awaiting_approval') {
|
|
358
|
+
if (!decision) {
|
|
359
|
+
throw new TaskError('INVALID_STATE', 'A decision is required to resume a task awaiting approval');
|
|
360
|
+
}
|
|
361
|
+
const approval = task.approval;
|
|
362
|
+
if (!approval) {
|
|
363
|
+
throw new TaskError('INVALID_STATE', 'Task is awaiting approval but has no approval info');
|
|
364
|
+
}
|
|
365
|
+
if (decision.approved) {
|
|
366
|
+
if (turnRunner.approveTurn) {
|
|
367
|
+
const ok = await turnRunner
|
|
368
|
+
.approveTurn(approval.runId, true, decision.editedArgs)
|
|
369
|
+
.catch(() => false);
|
|
370
|
+
if (!ok) {
|
|
371
|
+
return withTaskLock(id, async () => failTask(requireTask(id), `Turn service refused to resume run '${approval.runId}'`));
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
// Re-read under the lock: a cancel() may have landed while the
|
|
375
|
+
// approval I/O was in flight — never resurrect a task that left
|
|
376
|
+
// awaiting_approval meanwhile.
|
|
377
|
+
await withTaskLock(id, async () => {
|
|
378
|
+
const fresh = requireTask(id);
|
|
379
|
+
if (fresh.status !== 'awaiting_approval') {
|
|
380
|
+
throw new TaskError('INVALID_STATE', `Cannot resume task in status '${fresh.status}'`);
|
|
381
|
+
}
|
|
382
|
+
delete fresh.approval;
|
|
383
|
+
fresh.status = 'running';
|
|
384
|
+
await saveAndSnapshot(fresh);
|
|
385
|
+
});
|
|
386
|
+
// Apply a turn result that settled while approval was pending.
|
|
387
|
+
const pending = pendingTurnResults.get(id);
|
|
388
|
+
if (pending) {
|
|
389
|
+
pendingTurnResults.delete(id);
|
|
390
|
+
await applyTurnResult(id, pending.stepIndex, pending.result);
|
|
391
|
+
}
|
|
392
|
+
emit({ type: 'task.resumed', taskId: id });
|
|
393
|
+
// Safe either way: if the old loop is still blocked inside runTurn,
|
|
394
|
+
// the double-start guard makes this a no-op.
|
|
395
|
+
void runLoop(id);
|
|
396
|
+
const snapshot = store.get(id);
|
|
397
|
+
if (snapshot === null)
|
|
398
|
+
throw new TaskError('STORAGE', `Task ${id} vanished after save`);
|
|
399
|
+
return snapshot;
|
|
400
|
+
}
|
|
401
|
+
// Rejected: release the in-flight turn, then fail the step and task.
|
|
402
|
+
controllers.get(id)?.abort();
|
|
403
|
+
pendingTurnResults.delete(id);
|
|
404
|
+
if (turnRunner.approveTurn) {
|
|
405
|
+
await turnRunner.approveTurn(approval.runId, false, decision.editedArgs).catch(() => false);
|
|
406
|
+
}
|
|
407
|
+
return withTaskLock(id, async () => {
|
|
408
|
+
const fresh = requireTask(id);
|
|
409
|
+
delete fresh.approval;
|
|
410
|
+
const current = fresh.steps[fresh.currentStepIndex];
|
|
411
|
+
if (current !== undefined && (current.status === 'running' || current.status === 'pending')) {
|
|
412
|
+
current.status = 'failed';
|
|
413
|
+
current.error = 'approval rejected';
|
|
414
|
+
current.endedAt = nowIso();
|
|
415
|
+
}
|
|
416
|
+
return failTask(fresh, 'approval rejected');
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
if (task.status === 'paused') {
|
|
420
|
+
const snapshot = await withTaskLock(id, async () => {
|
|
421
|
+
const fresh = requireTask(id);
|
|
422
|
+
if (fresh.status !== 'paused') {
|
|
423
|
+
throw new TaskError('INVALID_STATE', `Cannot resume task in status '${fresh.status}'`);
|
|
424
|
+
}
|
|
425
|
+
fresh.status = 'running';
|
|
426
|
+
return saveAndSnapshot(fresh);
|
|
427
|
+
});
|
|
428
|
+
emit({ type: 'task.resumed', taskId: id });
|
|
429
|
+
void runLoop(id);
|
|
430
|
+
return snapshot;
|
|
431
|
+
}
|
|
432
|
+
throw new TaskError('INVALID_STATE', `Cannot resume task in status '${task.status}'`);
|
|
433
|
+
}
|
|
434
|
+
async function cancel(id) {
|
|
435
|
+
const snapshot = await withTaskLock(id, async () => {
|
|
436
|
+
const task = requireTask(id);
|
|
437
|
+
if (task.status === 'completed' || task.status === 'failed' || task.status === 'cancelled') {
|
|
438
|
+
throw new TaskError('INVALID_STATE', `Cannot cancel task in status '${task.status}'`);
|
|
439
|
+
}
|
|
440
|
+
const current = task.steps[task.currentStepIndex];
|
|
441
|
+
if (current !== undefined && current.status === 'running') {
|
|
442
|
+
current.status = 'failed';
|
|
443
|
+
current.error = 'task cancelled';
|
|
444
|
+
current.endedAt = nowIso();
|
|
445
|
+
}
|
|
446
|
+
task.status = 'cancelled';
|
|
447
|
+
delete task.approval;
|
|
448
|
+
pendingTurnResults.delete(id);
|
|
449
|
+
const snapshot = await saveAndSnapshot(task);
|
|
450
|
+
emit({ type: 'task.cancelled', taskId: id });
|
|
451
|
+
return snapshot;
|
|
452
|
+
});
|
|
453
|
+
controllers.get(id)?.abort();
|
|
454
|
+
return snapshot;
|
|
455
|
+
}
|
|
456
|
+
async function redirect(id, message) {
|
|
457
|
+
if (message.trim() === '') {
|
|
458
|
+
throw new TaskError('INVALID_STATE', 'Redirect message must not be empty');
|
|
459
|
+
}
|
|
460
|
+
return withTaskLock(id, async () => {
|
|
461
|
+
const task = requireTask(id);
|
|
462
|
+
if (task.status !== 'queued' && task.status !== 'running' && task.status !== 'paused') {
|
|
463
|
+
throw new TaskError('INVALID_STATE', `Cannot redirect task in status '${task.status}'`);
|
|
464
|
+
}
|
|
465
|
+
task.messageQueue.push(message);
|
|
466
|
+
return saveAndSnapshot(task);
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
async function retry(id, fromStep) {
|
|
470
|
+
const snapshot = await withTaskLock(id, async () => {
|
|
471
|
+
const task = requireTask(id);
|
|
472
|
+
if (!isRetryableStatus(task.status)) {
|
|
473
|
+
throw new TaskError('INVALID_STATE', `Cannot retry task in status '${task.status}'`);
|
|
474
|
+
}
|
|
475
|
+
let start;
|
|
476
|
+
if (fromStep !== undefined) {
|
|
477
|
+
if (!Number.isInteger(fromStep) || fromStep < 0 || fromStep >= task.steps.length) {
|
|
478
|
+
throw new TaskError('INVALID_STATE', `fromStep ${fromStep} is out of range`);
|
|
479
|
+
}
|
|
480
|
+
start = fromStep;
|
|
481
|
+
}
|
|
482
|
+
else {
|
|
483
|
+
const firstFailed = task.steps.findIndex((s) => s.status === 'failed');
|
|
484
|
+
if (firstFailed !== -1) {
|
|
485
|
+
start = firstFailed;
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
const firstNonDone = task.steps.findIndex((s) => s.status !== 'done');
|
|
489
|
+
if (firstNonDone === -1) {
|
|
490
|
+
throw new TaskError('INVALID_STATE', 'Nothing to retry: all steps are done');
|
|
491
|
+
}
|
|
492
|
+
start = firstNonDone;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
for (const s of task.steps) {
|
|
496
|
+
if (s.index >= start) {
|
|
497
|
+
s.status = 'pending';
|
|
498
|
+
delete s.error;
|
|
499
|
+
delete s.output;
|
|
500
|
+
delete s.startedAt;
|
|
501
|
+
delete s.endedAt;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
// Attempts are preserved; checkpoints at/after the retry point are dropped.
|
|
505
|
+
task.checkpoints = task.checkpoints.filter((c) => c.stepIndex < start);
|
|
506
|
+
task.currentStepIndex = start;
|
|
507
|
+
task.status = 'running';
|
|
508
|
+
delete task.error;
|
|
509
|
+
delete task.approval;
|
|
510
|
+
pendingTurnResults.delete(id);
|
|
511
|
+
const snapshot = await saveAndSnapshot(task);
|
|
512
|
+
emit({ type: 'task.resumed', taskId: id });
|
|
513
|
+
return snapshot;
|
|
514
|
+
});
|
|
515
|
+
void runLoop(id);
|
|
516
|
+
return snapshot;
|
|
517
|
+
}
|
|
518
|
+
async function recover() {
|
|
519
|
+
const tasks = store.list();
|
|
520
|
+
for (const task of tasks) {
|
|
521
|
+
if (task.status === 'running' ||
|
|
522
|
+
task.status === 'paused' ||
|
|
523
|
+
task.status === 'awaiting_approval') {
|
|
524
|
+
// Re-read under the lock: the boot-time list() snapshot may be
|
|
525
|
+
// stale if a loop is still settling in the same process.
|
|
526
|
+
await withTaskLock(task.id, async () => {
|
|
527
|
+
const fresh = store.get(task.id);
|
|
528
|
+
if (fresh === null)
|
|
529
|
+
return;
|
|
530
|
+
if (fresh.status !== 'running' &&
|
|
531
|
+
fresh.status !== 'paused' &&
|
|
532
|
+
fresh.status !== 'awaiting_approval') {
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
fresh.status = 'interrupted';
|
|
536
|
+
delete fresh.approval;
|
|
537
|
+
pendingTurnResults.delete(fresh.id);
|
|
538
|
+
const current = fresh.steps[fresh.currentStepIndex];
|
|
539
|
+
if (current !== undefined && current.status === 'running') {
|
|
540
|
+
current.status = 'pending';
|
|
541
|
+
delete current.startedAt;
|
|
542
|
+
}
|
|
543
|
+
await saveAndSnapshot(fresh);
|
|
544
|
+
});
|
|
545
|
+
// Release a same-process loop still blocked inside runTurn, if any.
|
|
546
|
+
// After a real restart there is no controller, so this is a no-op.
|
|
547
|
+
controllers.get(task.id)?.abort();
|
|
548
|
+
emit({ type: 'task.interrupted', taskId: task.id });
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
const runner = {
|
|
553
|
+
createAndStart,
|
|
554
|
+
get,
|
|
555
|
+
list,
|
|
556
|
+
pause,
|
|
557
|
+
resume,
|
|
558
|
+
cancel,
|
|
559
|
+
redirect,
|
|
560
|
+
retry,
|
|
561
|
+
recover,
|
|
562
|
+
};
|
|
563
|
+
return runner;
|
|
564
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Task } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* TaskStore persists tasks to a single JSON file with atomic writes.
|
|
4
|
+
* `load()` MUST be called before any other method.
|
|
5
|
+
*/
|
|
6
|
+
export declare class TaskStore {
|
|
7
|
+
private readonly filePath;
|
|
8
|
+
private tasks;
|
|
9
|
+
private loadedFlag;
|
|
10
|
+
private persistQueue;
|
|
11
|
+
constructor(filePath: string);
|
|
12
|
+
/** Read the store file into memory. Must be called before any other method. */
|
|
13
|
+
load(): Promise<void>;
|
|
14
|
+
private requireLoaded;
|
|
15
|
+
/** Atomically persist the whole document: write tmp file, then rename. */
|
|
16
|
+
private persist;
|
|
17
|
+
/** Insert a new task. */
|
|
18
|
+
create(task: Task): Promise<void>;
|
|
19
|
+
/** Upsert a task (insert or replace by id). */
|
|
20
|
+
save(task: Task): Promise<void>;
|
|
21
|
+
get(id: string): Task | null;
|
|
22
|
+
list(): Task[];
|
|
23
|
+
remove(id: string): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
/** Factory for {@link TaskStore} (options-object style, matches gateway wiring). */
|
|
26
|
+
export declare function createTaskStore(options: {
|
|
27
|
+
storagePath: string;
|
|
28
|
+
}): TaskStore;
|