@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,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent tools for web research: `research.search`, `research.extract`,
|
|
3
|
+
* `research.deep`, `research.academic`, `research.crawl`.
|
|
4
|
+
*
|
|
5
|
+
* `researchToolDefinitions` carries the `ToolDefinition`s the agent loop
|
|
6
|
+
* advertises; `createResearchToolExecutor` implements agent-core's
|
|
7
|
+
* `ToolExecutor` and dispatches calls to the orchestrator. Tool outputs are
|
|
8
|
+
* compact JSON (snippets only) to keep turn context small; full text comes
|
|
9
|
+
* from `research.extract` / `research.deep`.
|
|
10
|
+
*/
|
|
11
|
+
import type { ToolDefinition, ToolExecutor } from '@boombot/core';
|
|
12
|
+
import type { ResearchOrchestrator } from './orchestrator.js';
|
|
13
|
+
export declare const RESEARCH_SEARCH_TOOL = "research.search";
|
|
14
|
+
export declare const RESEARCH_EXTRACT_TOOL = "research.extract";
|
|
15
|
+
export declare const RESEARCH_DEEP_TOOL = "research.deep";
|
|
16
|
+
export declare const RESEARCH_ACADEMIC_TOOL = "research.academic";
|
|
17
|
+
export declare const RESEARCH_CRAWL_TOOL = "research.crawl";
|
|
18
|
+
/** `ToolDefinition`s to advertise to the agent loop. */
|
|
19
|
+
export declare const researchToolDefinitions: readonly ToolDefinition[];
|
|
20
|
+
export interface ResearchToolExecutorDeps {
|
|
21
|
+
readonly orchestrator: ResearchOrchestrator;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Dispatch tool calls to the orchestrator. Unknown tool names and invalid
|
|
25
|
+
* arguments produce error `ToolResult`s — never throws.
|
|
26
|
+
*/
|
|
27
|
+
export declare function createResearchToolExecutor(deps: ResearchToolExecutorDeps): ToolExecutor;
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent tools for web research: `research.search`, `research.extract`,
|
|
3
|
+
* `research.deep`, `research.academic`, `research.crawl`.
|
|
4
|
+
*
|
|
5
|
+
* `researchToolDefinitions` carries the `ToolDefinition`s the agent loop
|
|
6
|
+
* advertises; `createResearchToolExecutor` implements agent-core's
|
|
7
|
+
* `ToolExecutor` and dispatches calls to the orchestrator. Tool outputs are
|
|
8
|
+
* compact JSON (snippets only) to keep turn context small; full text comes
|
|
9
|
+
* from `research.extract` / `research.deep`.
|
|
10
|
+
*/
|
|
11
|
+
export const RESEARCH_SEARCH_TOOL = 'research.search';
|
|
12
|
+
export const RESEARCH_EXTRACT_TOOL = 'research.extract';
|
|
13
|
+
export const RESEARCH_DEEP_TOOL = 'research.deep';
|
|
14
|
+
export const RESEARCH_ACADEMIC_TOOL = 'research.academic';
|
|
15
|
+
export const RESEARCH_CRAWL_TOOL = 'research.crawl';
|
|
16
|
+
/** `ToolDefinition`s to advertise to the agent loop. */
|
|
17
|
+
export const researchToolDefinitions = [
|
|
18
|
+
{
|
|
19
|
+
name: RESEARCH_SEARCH_TOOL,
|
|
20
|
+
description: 'Search the public WEB for a query (Wikipedia and DuckDuckGo by default; a paid provider first when one is configured). The fan-out is bounded, so slow engines are dropped rather than made to wait. It does NOT search local files or the project directory — use the local file tools for anything on disk. Returns title/url/snippet per hit.',
|
|
21
|
+
parameters: {
|
|
22
|
+
type: 'object',
|
|
23
|
+
properties: {
|
|
24
|
+
query: { type: 'string', description: 'Search query.' },
|
|
25
|
+
limit: {
|
|
26
|
+
type: 'integer',
|
|
27
|
+
description: 'Max results (default 8, hard max 20).',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
required: ['query'],
|
|
31
|
+
additionalProperties: false,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: RESEARCH_EXTRACT_TOOL,
|
|
36
|
+
description: 'Extract a URL to markdown (main content). Free default backend is Jina Reader; Firecrawl when its key is configured. URLs ending in .pdf/.docx are parsed locally (zero-dependency, quota-guarded) instead of going to a third-party reader. Output is truncated to a safe length; pass "offset" (from a previous result\'s nextOffset) to read the next window of a long page.',
|
|
37
|
+
parameters: {
|
|
38
|
+
type: 'object',
|
|
39
|
+
properties: {
|
|
40
|
+
url: { type: 'string', description: 'Full URL to extract.' },
|
|
41
|
+
offset: {
|
|
42
|
+
type: 'integer',
|
|
43
|
+
description: 'Character offset into the page (default 0). Use nextOffset from the previous result to continue reading.',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
required: ['url'],
|
|
47
|
+
additionalProperties: false,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: RESEARCH_DEEP_TOOL,
|
|
52
|
+
description: 'Multi-hop deep research: searches the query, follows up on the top results, then extracts the top pages. Returns results, extracted markdown, and a per-provider source list for claim grounding.',
|
|
53
|
+
parameters: {
|
|
54
|
+
type: 'object',
|
|
55
|
+
properties: {
|
|
56
|
+
query: { type: 'string', description: 'Research question or topic.' },
|
|
57
|
+
maxHops: {
|
|
58
|
+
type: 'integer',
|
|
59
|
+
description: 'Search hops 1–3 (default 2).',
|
|
60
|
+
},
|
|
61
|
+
maxExtracts: {
|
|
62
|
+
type: 'integer',
|
|
63
|
+
description: 'URLs to extract 0–5 (default 3).',
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
required: ['query'],
|
|
67
|
+
additionalProperties: false,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: RESEARCH_ACADEMIC_TOOL,
|
|
72
|
+
description: 'Search scholarly sources only (arXiv, OpenAlex, Semantic Scholar) for papers and academic metadata. Free, no key needed.',
|
|
73
|
+
parameters: {
|
|
74
|
+
type: 'object',
|
|
75
|
+
properties: {
|
|
76
|
+
query: { type: 'string', description: 'Academic search query.' },
|
|
77
|
+
limit: {
|
|
78
|
+
type: 'integer',
|
|
79
|
+
description: 'Max results (default 8, hard max 20).',
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
required: ['query'],
|
|
83
|
+
additionalProperties: false,
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: RESEARCH_CRAWL_TOOL,
|
|
88
|
+
description: 'Crawl multiple pages of ONE site: extracts the start URL, follows same-site links from the page markdown (depth ≤ 2, hard max 10 pages) and returns compact per-page markdown. Use for site surveys; use research.extract for a single full page.',
|
|
89
|
+
parameters: {
|
|
90
|
+
type: 'object',
|
|
91
|
+
properties: {
|
|
92
|
+
url: { type: 'string', description: 'Start URL of the crawl (http/https).' },
|
|
93
|
+
maxPages: {
|
|
94
|
+
type: 'integer',
|
|
95
|
+
description: 'Max pages including the start URL (default 5, hard max 10).',
|
|
96
|
+
},
|
|
97
|
+
depth: {
|
|
98
|
+
type: 'integer',
|
|
99
|
+
description: 'Link-follow depth: 1 = start page only, 2 = follow its same-site links once (default 2, hard max 2).',
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
required: ['url'],
|
|
103
|
+
additionalProperties: false,
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
];
|
|
107
|
+
function asString(value) {
|
|
108
|
+
return typeof value === 'string' ? value : undefined;
|
|
109
|
+
}
|
|
110
|
+
function asNumber(value) {
|
|
111
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
112
|
+
}
|
|
113
|
+
function errorResult(call, message) {
|
|
114
|
+
return { callId: call.id, name: call.name, output: message, error: true };
|
|
115
|
+
}
|
|
116
|
+
function okResult(call, output) {
|
|
117
|
+
return {
|
|
118
|
+
callId: call.id,
|
|
119
|
+
name: call.name,
|
|
120
|
+
output: JSON.stringify(output),
|
|
121
|
+
error: false,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
// Per-executor cache: never reuse another configuration or account's results.
|
|
125
|
+
const SEARCH_CACHE_TTL_MS = 60_000;
|
|
126
|
+
const SEARCH_CACHE_MAX_ENTRIES = 50;
|
|
127
|
+
/**
|
|
128
|
+
* Dispatch tool calls to the orchestrator. Unknown tool names and invalid
|
|
129
|
+
* arguments produce error `ToolResult`s — never throws.
|
|
130
|
+
*/
|
|
131
|
+
export function createResearchToolExecutor(deps) {
|
|
132
|
+
const { orchestrator } = deps;
|
|
133
|
+
const searchCache = new Map();
|
|
134
|
+
function searchCacheKey(query, limit) {
|
|
135
|
+
return `${query.trim()}\u0000${limit ?? ''}`;
|
|
136
|
+
}
|
|
137
|
+
function readSearchCache(key) {
|
|
138
|
+
const entry = searchCache.get(key);
|
|
139
|
+
if (entry === undefined)
|
|
140
|
+
return undefined;
|
|
141
|
+
if (Date.now() - entry.at > SEARCH_CACHE_TTL_MS) {
|
|
142
|
+
searchCache.delete(key);
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
// Re-insert so the oldest untouched entry is the one evicted.
|
|
146
|
+
searchCache.delete(key);
|
|
147
|
+
searchCache.set(key, entry);
|
|
148
|
+
return entry.results;
|
|
149
|
+
}
|
|
150
|
+
function writeSearchCache(key, results) {
|
|
151
|
+
if (results.length === 0)
|
|
152
|
+
return;
|
|
153
|
+
searchCache.delete(key);
|
|
154
|
+
searchCache.set(key, { at: Date.now(), results });
|
|
155
|
+
while (searchCache.size > SEARCH_CACHE_MAX_ENTRIES) {
|
|
156
|
+
const oldest = searchCache.keys().next();
|
|
157
|
+
if (oldest.done === true)
|
|
158
|
+
break;
|
|
159
|
+
searchCache.delete(oldest.value);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return {
|
|
163
|
+
async execute(call, signal) {
|
|
164
|
+
const args = call.arguments;
|
|
165
|
+
try {
|
|
166
|
+
signal?.throwIfAborted();
|
|
167
|
+
switch (call.name) {
|
|
168
|
+
case RESEARCH_SEARCH_TOOL: {
|
|
169
|
+
const query = asString(args['query']);
|
|
170
|
+
if (query === undefined || query.trim() === '') {
|
|
171
|
+
return errorResult(call, 'research.search: "query" must be a non-empty string.');
|
|
172
|
+
}
|
|
173
|
+
const limit = asNumber(args['limit']);
|
|
174
|
+
const cacheKey = searchCacheKey(query, limit);
|
|
175
|
+
// A cancelled turn must not be kept alive by a cache hit.
|
|
176
|
+
const cached = signal?.aborted === true ? undefined : readSearchCache(cacheKey);
|
|
177
|
+
if (cached !== undefined) {
|
|
178
|
+
// `cached` is reported, so a model reading the output knows the
|
|
179
|
+
// snippets may be up to a minute old.
|
|
180
|
+
return okResult(call, { query, results: cached, cached: true });
|
|
181
|
+
}
|
|
182
|
+
const results = await orchestrator.search(query, { limit, signal });
|
|
183
|
+
signal?.throwIfAborted();
|
|
184
|
+
writeSearchCache(cacheKey, results);
|
|
185
|
+
return okResult(call, { query, results });
|
|
186
|
+
}
|
|
187
|
+
case RESEARCH_EXTRACT_TOOL: {
|
|
188
|
+
const url = asString(args['url']);
|
|
189
|
+
if (url === undefined || url.trim() === '') {
|
|
190
|
+
return errorResult(call, 'research.extract: "url" must be a non-empty string.');
|
|
191
|
+
}
|
|
192
|
+
const offset = asNumber(args['offset']);
|
|
193
|
+
if (offset !== undefined && (offset < 0 || !Number.isInteger(offset))) {
|
|
194
|
+
return errorResult(call, 'research.extract: "offset" must be a non-negative integer.');
|
|
195
|
+
}
|
|
196
|
+
const result = await orchestrator.extract(url, signal, offset !== undefined ? { offset } : undefined);
|
|
197
|
+
// An offset past the end of the document yields an empty window
|
|
198
|
+
// — report it as a readable error instead of empty content.
|
|
199
|
+
if (offset !== undefined &&
|
|
200
|
+
result.markdown === '' &&
|
|
201
|
+
typeof result.totalLength === 'number') {
|
|
202
|
+
return errorResult(call, `research.extract: offset ${offset} is beyond the end of the document (${result.totalLength} chars). Use a smaller offset.`);
|
|
203
|
+
}
|
|
204
|
+
return okResult(call, result);
|
|
205
|
+
}
|
|
206
|
+
case RESEARCH_DEEP_TOOL: {
|
|
207
|
+
const query = asString(args['query']);
|
|
208
|
+
if (query === undefined || query.trim() === '') {
|
|
209
|
+
return errorResult(call, 'research.deep: "query" must be a non-empty string.');
|
|
210
|
+
}
|
|
211
|
+
const result = await orchestrator.deep(query, {
|
|
212
|
+
maxHops: asNumber(args['maxHops']),
|
|
213
|
+
maxExtracts: asNumber(args['maxExtracts']),
|
|
214
|
+
signal,
|
|
215
|
+
});
|
|
216
|
+
return okResult(call, result);
|
|
217
|
+
}
|
|
218
|
+
case RESEARCH_ACADEMIC_TOOL: {
|
|
219
|
+
const query = asString(args['query']);
|
|
220
|
+
if (query === undefined || query.trim() === '') {
|
|
221
|
+
return errorResult(call, 'research.academic: "query" must be a non-empty string.');
|
|
222
|
+
}
|
|
223
|
+
const results = await orchestrator.academic(query, {
|
|
224
|
+
limit: asNumber(args['limit']),
|
|
225
|
+
signal,
|
|
226
|
+
});
|
|
227
|
+
return okResult(call, { query, results });
|
|
228
|
+
}
|
|
229
|
+
case RESEARCH_CRAWL_TOOL: {
|
|
230
|
+
const url = asString(args['url']);
|
|
231
|
+
if (url === undefined || url.trim() === '') {
|
|
232
|
+
return errorResult(call, 'research.crawl: "url" must be a non-empty string.');
|
|
233
|
+
}
|
|
234
|
+
const result = await orchestrator.crawl(url, {
|
|
235
|
+
maxPages: asNumber(args['maxPages']),
|
|
236
|
+
depth: asNumber(args['depth']),
|
|
237
|
+
signal,
|
|
238
|
+
});
|
|
239
|
+
return okResult(call, result);
|
|
240
|
+
}
|
|
241
|
+
default:
|
|
242
|
+
return errorResult(call, `Unknown research tool: ${call.name}`);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
catch (err) {
|
|
246
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
247
|
+
return errorResult(call, `research tool failed: ${detail}`);
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
};
|
|
251
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public contracts for `@boombot/core`.
|
|
3
|
+
*
|
|
4
|
+
* These interfaces are the shared language between this package's skeleton
|
|
5
|
+
* (config/registry, HTTP helpers) and the provider/orchestrator executors.
|
|
6
|
+
* Additive-first: fields may be added, never renamed or removed.
|
|
7
|
+
*/
|
|
8
|
+
/** One search hit returned by a {@link ResearchProvider}. */
|
|
9
|
+
export interface SearchResult {
|
|
10
|
+
readonly title: string;
|
|
11
|
+
readonly url: string;
|
|
12
|
+
readonly snippet: string;
|
|
13
|
+
/** Provider id, e.g. `'wikipedia'`. */
|
|
14
|
+
readonly source: string;
|
|
15
|
+
/** ISO 8601 string, when the provider supplies one. */
|
|
16
|
+
readonly publishedAt?: string;
|
|
17
|
+
}
|
|
18
|
+
/** Full-page extraction returned by an {@link ExtractProvider}. */
|
|
19
|
+
export interface ExtractResult {
|
|
20
|
+
readonly url: string;
|
|
21
|
+
readonly title: string;
|
|
22
|
+
readonly markdown: string;
|
|
23
|
+
readonly truncated: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Offset this result was served from (0 when the provider ignores
|
|
26
|
+
* windowing). Additive: older providers may omit it.
|
|
27
|
+
*/
|
|
28
|
+
readonly offset?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Character length of the full extracted document, before windowing.
|
|
31
|
+
* Present when the provider knows it — lets callers validate `offset`.
|
|
32
|
+
*/
|
|
33
|
+
readonly totalLength?: number;
|
|
34
|
+
/**
|
|
35
|
+
* When more content remains after this window: the offset to pass back
|
|
36
|
+
* as {@link ExtractOpts.offset} to read the next window. Absent at the
|
|
37
|
+
* end of the document.
|
|
38
|
+
*/
|
|
39
|
+
readonly nextOffset?: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Options accepted by {@link ExtractProvider.extract} (third parameter).
|
|
43
|
+
* Additive-first: providers that ignore `opts` stay valid implementations.
|
|
44
|
+
*/
|
|
45
|
+
export interface ExtractOpts {
|
|
46
|
+
/**
|
|
47
|
+
* Character offset into the extracted markdown. The provider fetches the
|
|
48
|
+
* page again and serves the window `[offset, offset + maxChars)`.
|
|
49
|
+
* Default 0 (first window). Out-of-range offsets produce an empty
|
|
50
|
+
* `markdown` with `totalLength` set so callers can report a precise error.
|
|
51
|
+
*/
|
|
52
|
+
readonly offset?: number;
|
|
53
|
+
}
|
|
54
|
+
/** Options accepted by {@link ResearchProvider.search}. */
|
|
55
|
+
export interface SearchOpts {
|
|
56
|
+
/** Max results. Default 8, hard max 20 — providers MUST clamp. */
|
|
57
|
+
readonly limit?: number;
|
|
58
|
+
readonly signal?: AbortSignal;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* A search backend. Free providers are hand-rolled HTTP clients (global
|
|
62
|
+
* `fetch` only, zero runtime deps); paid providers wrap their APIs.
|
|
63
|
+
*/
|
|
64
|
+
export interface ResearchProvider {
|
|
65
|
+
/** `'wikipedia' | 'tavily' | ...` — unique across search + extract providers. */
|
|
66
|
+
readonly id: string;
|
|
67
|
+
readonly kind: 'free' | 'paid';
|
|
68
|
+
search(query: string, opts?: SearchOpts): Promise<readonly SearchResult[]>;
|
|
69
|
+
}
|
|
70
|
+
/** A URL → markdown extraction backend (jina-reader, firecrawl, ...). */
|
|
71
|
+
export interface ExtractProvider {
|
|
72
|
+
readonly id: string;
|
|
73
|
+
readonly kind: 'free' | 'paid';
|
|
74
|
+
/**
|
|
75
|
+
* `opts` is additive: implementations with the old two-parameter shape
|
|
76
|
+
* remain valid and simply always serve the first window.
|
|
77
|
+
*/
|
|
78
|
+
extract(url: string, signal?: AbortSignal, opts?: ExtractOpts): Promise<ExtractResult>;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Runtime configuration. Keys come from env (see `loadResearchConfig`).
|
|
82
|
+
* Keys are held in memory only — never logged, never serialized.
|
|
83
|
+
*/
|
|
84
|
+
export interface ResearchConfig {
|
|
85
|
+
readonly tavilyApiKey?: string;
|
|
86
|
+
readonly exaApiKey?: string;
|
|
87
|
+
readonly braveApiKey?: string;
|
|
88
|
+
readonly firecrawlApiKey?: string;
|
|
89
|
+
readonly defaultMode?: 'auto';
|
|
90
|
+
/**
|
|
91
|
+
* Free engines the general fan-out may call, by id (e.g.
|
|
92
|
+
* `['wikipedia', 'duckduckgo']`). Absent = `DEFAULT_SEARCH_ENGINES`; an
|
|
93
|
+
* explicit `[]` disables free engines entirely and leaves only the paid
|
|
94
|
+
* providers that have a key. The scholarly engines are not in the default
|
|
95
|
+
* set on purpose — they are reachable only through the explicit
|
|
96
|
+
* `research.academic` tool, so an ordinary search never pays for them.
|
|
97
|
+
*/
|
|
98
|
+
readonly engines?: readonly string[];
|
|
99
|
+
}
|
|
100
|
+
/** One crawled page in a {@link CrawlResult}. */
|
|
101
|
+
export interface CrawlPage {
|
|
102
|
+
readonly url: string;
|
|
103
|
+
readonly title: string;
|
|
104
|
+
/** Page markdown, truncated to the crawl window (smaller than extract). */
|
|
105
|
+
readonly markdown: string;
|
|
106
|
+
readonly truncated: boolean;
|
|
107
|
+
/** BFS depth: 0 for the start URL. */
|
|
108
|
+
readonly depth: number;
|
|
109
|
+
}
|
|
110
|
+
/** Options accepted by the crawl engine / `research.crawl`. */
|
|
111
|
+
export interface CrawlOpts {
|
|
112
|
+
/** Max pages including the start URL. Default 5, hard max 10. */
|
|
113
|
+
readonly maxPages?: number;
|
|
114
|
+
/**
|
|
115
|
+
* Link-follow depth. 1 = start URL only, no link following.
|
|
116
|
+
* Default 2, hard max 2.
|
|
117
|
+
*/
|
|
118
|
+
readonly depth?: number;
|
|
119
|
+
/** Per-page markdown window in characters. Default 2000. */
|
|
120
|
+
readonly perPageChars?: number;
|
|
121
|
+
readonly signal?: AbortSignal;
|
|
122
|
+
}
|
|
123
|
+
/** Result of a crawl run. Pages are in BFS completion order. */
|
|
124
|
+
export interface CrawlResult {
|
|
125
|
+
readonly startUrl: string;
|
|
126
|
+
readonly pages: readonly CrawlPage[];
|
|
127
|
+
/** Deepest BFS level that yielded at least one page. */
|
|
128
|
+
readonly depthReached: number;
|
|
129
|
+
/** Same-host candidate URLs that failed to extract, capped at 10. */
|
|
130
|
+
readonly failedUrls: readonly string[];
|
|
131
|
+
/** True when the run stopped early because `signal` was aborted. */
|
|
132
|
+
readonly aborted: boolean;
|
|
133
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public contracts for `@boombot/core`.
|
|
3
|
+
*
|
|
4
|
+
* These interfaces are the shared language between this package's skeleton
|
|
5
|
+
* (config/registry, HTTP helpers) and the provider/orchestrator executors.
|
|
6
|
+
* Additive-first: fields may be added, never renamed or removed.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One-call gateway wiring for research tools.
|
|
3
|
+
*
|
|
4
|
+
* `registerResearchTools` builds the provider instances from config,
|
|
5
|
+
* resolves the search chain + extract backend, creates the orchestrator,
|
|
6
|
+
* and registers `research.search` / `research.extract` / `research.deep` /
|
|
7
|
+
* `research.academic` on any `registerTool`-shaped registry (e.g.
|
|
8
|
+
* `GatewayToolExecutor`). The gateway calls this once per turn's deps in
|
|
9
|
+
* `startTurnService`.
|
|
10
|
+
*/
|
|
11
|
+
import type { ToolCall, ToolDefinition, ToolResult } from '@boombot/core';
|
|
12
|
+
import type { ResearchConfig } from './types.js';
|
|
13
|
+
/**
|
|
14
|
+
* Structural subset of `GatewayToolExecutor` needed for registration —
|
|
15
|
+
* structural so this package never imports from `gateway`.
|
|
16
|
+
*/
|
|
17
|
+
export interface ResearchToolRegistry {
|
|
18
|
+
registerTool(definition: ToolDefinition, handler: (call: ToolCall, signal?: AbortSignal) => Promise<ToolResult> | ToolResult): void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Build the full research stack from `config` (defaults to env via
|
|
22
|
+
* `loadResearchConfig`) and register all four tools on `registry`.
|
|
23
|
+
* Throws when a tool name is already registered (registry's own guard).
|
|
24
|
+
*/
|
|
25
|
+
export declare function registerResearchTools(registry: ResearchToolRegistry, config?: ResearchConfig): void;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One-call gateway wiring for research tools.
|
|
3
|
+
*
|
|
4
|
+
* `registerResearchTools` builds the provider instances from config,
|
|
5
|
+
* resolves the search chain + extract backend, creates the orchestrator,
|
|
6
|
+
* and registers `research.search` / `research.extract` / `research.deep` /
|
|
7
|
+
* `research.academic` on any `registerTool`-shaped registry (e.g.
|
|
8
|
+
* `GatewayToolExecutor`). The gateway calls this once per turn's deps in
|
|
9
|
+
* `startTurnService`.
|
|
10
|
+
*/
|
|
11
|
+
import { createHash } from 'node:crypto';
|
|
12
|
+
import { loadResearchConfig, resolveAcademicProviders, resolveExtractProvider, resolveSearchProviders, } from './config.js';
|
|
13
|
+
import { createExtractProviders, createSearchProviders } from './factory.js';
|
|
14
|
+
import { ResearchOrchestrator } from './orchestrator.js';
|
|
15
|
+
import { createResearchToolExecutor, researchToolDefinitions } from './tools.js';
|
|
16
|
+
// Reuse the bounded search cache across turns, never across provider configurations.
|
|
17
|
+
const executors = new Map();
|
|
18
|
+
/**
|
|
19
|
+
* Build the full research stack from `config` (defaults to env via
|
|
20
|
+
* `loadResearchConfig`) and register all four tools on `registry`.
|
|
21
|
+
* Throws when a tool name is already registered (registry's own guard).
|
|
22
|
+
*/
|
|
23
|
+
export function registerResearchTools(registry, config = loadResearchConfig()) {
|
|
24
|
+
const key = createHash('sha256').update(JSON.stringify(config)).digest('hex');
|
|
25
|
+
let executor = executors.get(key);
|
|
26
|
+
if (executor === undefined) {
|
|
27
|
+
const { paid, free } = createSearchProviders(config);
|
|
28
|
+
const searchChain = resolveSearchProviders(config, { paid, free });
|
|
29
|
+
// `research.academic` searches the full free pool, not the resolved chain:
|
|
30
|
+
// the scholarly engines are left out of the default fan-out for latency
|
|
31
|
+
// (`DEFAULT_SEARCH_ENGINES`), and a caller asking for them by name must
|
|
32
|
+
// still get them.
|
|
33
|
+
const academicChain = resolveAcademicProviders({ free });
|
|
34
|
+
const extractCandidates = createExtractProviders(config);
|
|
35
|
+
const extractProvider = resolveExtractProvider(config, extractCandidates);
|
|
36
|
+
const orchestrator = new ResearchOrchestrator({
|
|
37
|
+
searchChain,
|
|
38
|
+
academicChain,
|
|
39
|
+
extractProvider,
|
|
40
|
+
});
|
|
41
|
+
executor = createResearchToolExecutor({ orchestrator });
|
|
42
|
+
const oldest = executors.keys().next();
|
|
43
|
+
if (executors.size >= 8 && !oldest.done)
|
|
44
|
+
executors.delete(oldest.value);
|
|
45
|
+
executors.set(key, executor);
|
|
46
|
+
}
|
|
47
|
+
const resolvedExecutor = executor;
|
|
48
|
+
for (const definition of researchToolDefinitions) {
|
|
49
|
+
registry.registerTool(definition, (call, signal) => resolvedExecutor.execute(call, signal));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hand-written 5-field cron parser. No regex is applied to user input beyond
|
|
3
|
+
* one anchored charset check (linear-time, no nested quantifiers), so
|
|
4
|
+
* evaluation is ReDoS-safe by construction.
|
|
5
|
+
*
|
|
6
|
+
* Supported per field: `*`, `*\/step`, `a-b`, `a-b/step`, `n`, and
|
|
7
|
+
* comma-separated lists thereof.
|
|
8
|
+
*/
|
|
9
|
+
import type { WallParts } from './timezone.js';
|
|
10
|
+
export declare const MAX_CRON_LENGTH = 120;
|
|
11
|
+
export interface CronSchedule {
|
|
12
|
+
readonly minute: ReadonlySet<number>;
|
|
13
|
+
readonly hour: ReadonlySet<number>;
|
|
14
|
+
readonly dayOfMonth: ReadonlySet<number>;
|
|
15
|
+
readonly month: ReadonlySet<number>;
|
|
16
|
+
readonly dayOfWeek: ReadonlySet<number>;
|
|
17
|
+
/** True when the original field was a bare `*` (Vixie DOM/DOW semantics). */
|
|
18
|
+
readonly dayOfMonthIsStar: boolean;
|
|
19
|
+
readonly dayOfWeekIsStar: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Parse a 5-field cron expression. Throws `SchedulerError`
|
|
23
|
+
* (`SCHEDULER_INVALID_SPEC`) on any invalid input.
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseCron(expr: string): CronSchedule;
|
|
26
|
+
/** Non-throwing validation wrapper for API boundaries. */
|
|
27
|
+
export declare function validateCronExpression(expr: string): {
|
|
28
|
+
readonly ok: true;
|
|
29
|
+
} | {
|
|
30
|
+
readonly ok: false;
|
|
31
|
+
readonly reason: string;
|
|
32
|
+
};
|
|
33
|
+
/** True when the wall-clock parts satisfy the schedule. */
|
|
34
|
+
export declare function matchesCron(schedule: CronSchedule, parts: WallParts): boolean;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { invalidSpec } from './types.js';
|
|
2
|
+
export const MAX_CRON_LENGTH = 120;
|
|
3
|
+
/** Anchored charset pre-check: linear, no backtracking risk. */
|
|
4
|
+
const CHARSET_CHECK = /^[0-9*,/\-\s]+$/;
|
|
5
|
+
const FIELDS = [
|
|
6
|
+
{ name: 'minute', min: 0, max: 59 },
|
|
7
|
+
{ name: 'hour', min: 0, max: 23 },
|
|
8
|
+
{ name: 'day of month', min: 1, max: 31 },
|
|
9
|
+
{ name: 'month', min: 1, max: 12 },
|
|
10
|
+
{ name: 'day of week', min: 0, max: 7 },
|
|
11
|
+
];
|
|
12
|
+
function fail(reason) {
|
|
13
|
+
throw invalidSpec(`Invalid cron expression: ${reason}`);
|
|
14
|
+
}
|
|
15
|
+
function parseRangeItem(item, def, values) {
|
|
16
|
+
// Split off an optional "/step" using a manual scan (no regex).
|
|
17
|
+
let base = item;
|
|
18
|
+
let step;
|
|
19
|
+
const slash = item.indexOf('/');
|
|
20
|
+
if (slash >= 0) {
|
|
21
|
+
base = item.slice(0, slash);
|
|
22
|
+
const stepText = item.slice(slash + 1);
|
|
23
|
+
if (stepText.length === 0 || !/^[0-9]+$/.test(stepText)) {
|
|
24
|
+
fail(`bad step in ${def.name} field: "${item}"`);
|
|
25
|
+
}
|
|
26
|
+
step = Number(stepText);
|
|
27
|
+
if (!Number.isSafeInteger(step) || step < 1 || step > def.max) {
|
|
28
|
+
fail(`step out of range in ${def.name} field: "${item}"`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
let lo;
|
|
32
|
+
let hi;
|
|
33
|
+
if (base === '*') {
|
|
34
|
+
lo = def.min;
|
|
35
|
+
hi = def.max;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
const dash = base.indexOf('-');
|
|
39
|
+
if (dash >= 0) {
|
|
40
|
+
const loText = base.slice(0, dash);
|
|
41
|
+
const hiText = base.slice(dash + 1);
|
|
42
|
+
if (!/^[0-9]+$/.test(loText) || !/^[0-9]+$/.test(hiText)) {
|
|
43
|
+
fail(`bad range in ${def.name} field: "${item}"`);
|
|
44
|
+
}
|
|
45
|
+
lo = Number(loText);
|
|
46
|
+
hi = Number(hiText);
|
|
47
|
+
if (lo > hi)
|
|
48
|
+
fail(`reversed range in ${def.name} field: "${item}"`);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
if (!/^[0-9]+$/.test(base))
|
|
52
|
+
fail(`bad value in ${def.name} field: "${item}"`);
|
|
53
|
+
lo = Number(base);
|
|
54
|
+
hi = lo;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (lo < def.min || hi > def.max) {
|
|
58
|
+
fail(`${def.name} value out of range (${def.min}-${def.max}): "${item}"`);
|
|
59
|
+
}
|
|
60
|
+
const stepBy = step ?? 1;
|
|
61
|
+
for (let v = lo; v <= hi; v += stepBy)
|
|
62
|
+
values.add(v);
|
|
63
|
+
}
|
|
64
|
+
function parseField(fieldText, def, isStar) {
|
|
65
|
+
const values = new Set();
|
|
66
|
+
isStar.value = fieldText === '*';
|
|
67
|
+
const items = fieldText.split(',');
|
|
68
|
+
for (const item of items) {
|
|
69
|
+
if (item.length === 0)
|
|
70
|
+
fail(`empty list item in ${def.name} field`);
|
|
71
|
+
parseRangeItem(item, def, values);
|
|
72
|
+
}
|
|
73
|
+
if (values.size === 0)
|
|
74
|
+
fail(`empty ${def.name} field`);
|
|
75
|
+
return values;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Parse a 5-field cron expression. Throws `SchedulerError`
|
|
79
|
+
* (`SCHEDULER_INVALID_SPEC`) on any invalid input.
|
|
80
|
+
*/
|
|
81
|
+
export function parseCron(expr) {
|
|
82
|
+
if (typeof expr !== 'string')
|
|
83
|
+
fail('expression must be a string');
|
|
84
|
+
if (expr.length === 0)
|
|
85
|
+
fail('expression is empty');
|
|
86
|
+
if (expr.length > MAX_CRON_LENGTH) {
|
|
87
|
+
fail(`expression exceeds ${MAX_CRON_LENGTH} characters`);
|
|
88
|
+
}
|
|
89
|
+
if (!CHARSET_CHECK.test(expr)) {
|
|
90
|
+
fail('expression contains unsupported characters');
|
|
91
|
+
}
|
|
92
|
+
const fields = expr.trim().split(/\s+/);
|
|
93
|
+
if (fields.length !== 5) {
|
|
94
|
+
fail(`expected 5 fields, found ${fields.length}`);
|
|
95
|
+
}
|
|
96
|
+
const domStar = { value: false };
|
|
97
|
+
const dowStar = { value: false };
|
|
98
|
+
const minute = parseField(fields[0], FIELDS[0], { value: false });
|
|
99
|
+
const hour = parseField(fields[1], FIELDS[1], { value: false });
|
|
100
|
+
const dayOfMonth = parseField(fields[2], FIELDS[2], domStar);
|
|
101
|
+
const month = parseField(fields[3], FIELDS[3], { value: false });
|
|
102
|
+
const rawDow = parseField(fields[4], FIELDS[4], dowStar);
|
|
103
|
+
// Normalize Sunday 7 -> 0.
|
|
104
|
+
const dayOfWeek = new Set();
|
|
105
|
+
for (const d of rawDow)
|
|
106
|
+
dayOfWeek.add(d === 7 ? 0 : d);
|
|
107
|
+
return {
|
|
108
|
+
minute,
|
|
109
|
+
hour,
|
|
110
|
+
dayOfMonth,
|
|
111
|
+
month,
|
|
112
|
+
dayOfWeek,
|
|
113
|
+
dayOfMonthIsStar: domStar.value,
|
|
114
|
+
dayOfWeekIsStar: dowStar.value,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/** Non-throwing validation wrapper for API boundaries. */
|
|
118
|
+
export function validateCronExpression(expr) {
|
|
119
|
+
try {
|
|
120
|
+
parseCron(expr);
|
|
121
|
+
return { ok: true };
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
return {
|
|
125
|
+
ok: false,
|
|
126
|
+
reason: error instanceof Error ? error.message : 'unknown validation failure',
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function dayMatches(schedule, parts) {
|
|
131
|
+
const dom = schedule.dayOfMonth.has(parts.day);
|
|
132
|
+
const dowMatch = schedule.dayOfWeek.has(parts.weekday);
|
|
133
|
+
if (schedule.dayOfMonthIsStar && schedule.dayOfWeekIsStar)
|
|
134
|
+
return true;
|
|
135
|
+
if (schedule.dayOfMonthIsStar)
|
|
136
|
+
return dowMatch;
|
|
137
|
+
if (schedule.dayOfWeekIsStar)
|
|
138
|
+
return dom;
|
|
139
|
+
return dom || dowMatch;
|
|
140
|
+
}
|
|
141
|
+
/** True when the wall-clock parts satisfy the schedule. */
|
|
142
|
+
export function matchesCron(schedule, parts) {
|
|
143
|
+
return (schedule.minute.has(parts.minute) &&
|
|
144
|
+
schedule.hour.has(parts.hour) &&
|
|
145
|
+
schedule.month.has(parts.month) &&
|
|
146
|
+
dayMatches(schedule, parts));
|
|
147
|
+
}
|