@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,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin manifest for `@boombot/protocol` (lesson #7 from the
|
|
3
|
+
* Hermes/OpenClaw comparison: capability + configSchema + doctorContract,
|
|
4
|
+
* declared up front).
|
|
5
|
+
*
|
|
6
|
+
* Extensions ship an `boombot.plugin.json` file; the gateway validates it
|
|
7
|
+
* with `parseManifest` before loading anything.
|
|
8
|
+
*/
|
|
9
|
+
import type { ChannelKind } from './channel.js';
|
|
10
|
+
/** Minimal JSON Schema subset, self-defined (no external dependency). */
|
|
11
|
+
export interface JSONSchema {
|
|
12
|
+
readonly type?: 'object' | 'array' | 'string' | 'number' | 'integer' | 'boolean' | 'null';
|
|
13
|
+
readonly description?: string;
|
|
14
|
+
readonly properties?: Readonly<Record<string, JSONSchema>>;
|
|
15
|
+
readonly required?: readonly string[];
|
|
16
|
+
readonly items?: JSONSchema;
|
|
17
|
+
readonly enum?: readonly (string | number | boolean)[];
|
|
18
|
+
readonly additionalProperties?: boolean | JSONSchema;
|
|
19
|
+
}
|
|
20
|
+
/** Self-diagnostics contract: named checks the `doctor` command can run. */
|
|
21
|
+
export interface DoctorContract {
|
|
22
|
+
readonly checks: readonly string[];
|
|
23
|
+
}
|
|
24
|
+
export interface BoomBotPluginManifest {
|
|
25
|
+
/** Reverse-DNS style id, e.g. `'boombot.telegram'`. */
|
|
26
|
+
readonly id: string;
|
|
27
|
+
/** Semver, e.g. `'1.2.0'`. */
|
|
28
|
+
readonly version: string;
|
|
29
|
+
readonly displayName: string;
|
|
30
|
+
readonly description?: string;
|
|
31
|
+
/** JavaScript module path relative to the manifest directory. Defaults to `index.js`. */
|
|
32
|
+
readonly entry?: string;
|
|
33
|
+
/** Capability tokens, e.g. `['channel.send', 'channel.receive']`. */
|
|
34
|
+
readonly capabilities: readonly string[];
|
|
35
|
+
readonly channels?: readonly ChannelKind[];
|
|
36
|
+
/** JSON Schema describing the plugin's config object. */
|
|
37
|
+
readonly configSchema: JSONSchema;
|
|
38
|
+
readonly doctorContract?: DoctorContract;
|
|
39
|
+
}
|
|
40
|
+
export type ParseManifestResult = {
|
|
41
|
+
readonly ok: true;
|
|
42
|
+
readonly manifest: BoomBotPluginManifest;
|
|
43
|
+
} | {
|
|
44
|
+
readonly ok: false;
|
|
45
|
+
readonly errors: readonly string[];
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Hand-written manifest validator (no extra dependencies on purpose —
|
|
49
|
+
* the SDK must stay tiny). Returns all errors found, not just the first.
|
|
50
|
+
*/
|
|
51
|
+
export declare function parseManifest(raw: unknown): ParseManifestResult;
|
|
52
|
+
/**
|
|
53
|
+
* Validate-and-return convenience for extension entry points: parses the
|
|
54
|
+
* bundled `boombot.plugin.json` and throws on the first import if the manifest
|
|
55
|
+
* is invalid, so an extension never runs with broken metadata. Every
|
|
56
|
+
* extension's `src/manifest.ts` is this call plus the JSON import.
|
|
57
|
+
*/
|
|
58
|
+
export declare function defineManifest(raw: unknown): BoomBotPluginManifest;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { CHANNEL_KINDS } from './channel.js';
|
|
2
|
+
const ID_PATTERN = /^[a-z0-9][a-z0-9-]*(\.[a-z0-9][a-z0-9-]*)+$/;
|
|
3
|
+
const VERSION_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$/;
|
|
4
|
+
const CAPABILITY_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
|
|
5
|
+
function isRecord(value) {
|
|
6
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
function isNonEmptyString(value) {
|
|
9
|
+
return typeof value === 'string' && value.trim() !== '';
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Hand-written manifest validator (no extra dependencies on purpose —
|
|
13
|
+
* the SDK must stay tiny). Returns all errors found, not just the first.
|
|
14
|
+
*/
|
|
15
|
+
export function parseManifest(raw) {
|
|
16
|
+
const errors = [];
|
|
17
|
+
if (!isRecord(raw)) {
|
|
18
|
+
return { ok: false, errors: ['manifest must be a JSON object'] };
|
|
19
|
+
}
|
|
20
|
+
if (!isNonEmptyString(raw['id'])) {
|
|
21
|
+
errors.push('id must be a non-empty string');
|
|
22
|
+
}
|
|
23
|
+
else if (!ID_PATTERN.test(raw['id'])) {
|
|
24
|
+
errors.push(`id must be reverse-DNS style (e.g. 'boombot.telegram'), got '${raw['id']}'`);
|
|
25
|
+
}
|
|
26
|
+
if (!isNonEmptyString(raw['version'])) {
|
|
27
|
+
errors.push('version must be a non-empty string');
|
|
28
|
+
}
|
|
29
|
+
else if (!VERSION_PATTERN.test(raw['version'])) {
|
|
30
|
+
errors.push(`version must be semver, got '${raw['version']}'`);
|
|
31
|
+
}
|
|
32
|
+
if (!isNonEmptyString(raw['displayName'])) {
|
|
33
|
+
errors.push('displayName must be a non-empty string');
|
|
34
|
+
}
|
|
35
|
+
if (raw['description'] !== undefined && typeof raw['description'] !== 'string') {
|
|
36
|
+
errors.push('description must be a string when present');
|
|
37
|
+
}
|
|
38
|
+
if (raw['entry'] !== undefined &&
|
|
39
|
+
(!isNonEmptyString(raw['entry']) || raw['entry'].includes('\0'))) {
|
|
40
|
+
errors.push('entry must be a non-empty path string when present');
|
|
41
|
+
}
|
|
42
|
+
if (!Array.isArray(raw['capabilities']) || raw['capabilities'].length === 0) {
|
|
43
|
+
errors.push('capabilities must be a non-empty array of strings');
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
for (const cap of raw['capabilities']) {
|
|
47
|
+
if (!isNonEmptyString(cap)) {
|
|
48
|
+
errors.push('capabilities must contain only non-empty strings');
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
if (!CAPABILITY_PATTERN.test(cap)) {
|
|
52
|
+
errors.push(`capability '${cap}' must be lowercase alphanumeric with . _ - separators`);
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (raw['channels'] !== undefined) {
|
|
58
|
+
if (!Array.isArray(raw['channels'])) {
|
|
59
|
+
errors.push('channels must be an array of channel kinds when present');
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
for (const ch of raw['channels']) {
|
|
63
|
+
if (!CHANNEL_KINDS.includes(ch)) {
|
|
64
|
+
errors.push(`unknown channel kind '${String(ch)}' (known: ${CHANNEL_KINDS.join(', ')})`);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (!isRecord(raw['configSchema'])) {
|
|
71
|
+
errors.push('configSchema must be a JSON Schema object');
|
|
72
|
+
}
|
|
73
|
+
else if (raw['configSchema']['type'] !== undefined && typeof raw['configSchema']['type'] !== 'string') {
|
|
74
|
+
errors.push('configSchema.type must be a string when present');
|
|
75
|
+
}
|
|
76
|
+
const doctor = raw['doctorContract'];
|
|
77
|
+
if (doctor !== undefined) {
|
|
78
|
+
if (!isRecord(doctor)) {
|
|
79
|
+
errors.push('doctorContract must be an object when present');
|
|
80
|
+
}
|
|
81
|
+
else if (!Array.isArray(doctor['checks']) ||
|
|
82
|
+
!doctor['checks'].every((c) => isNonEmptyString(c))) {
|
|
83
|
+
errors.push('doctorContract.checks must be an array of non-empty strings');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (errors.length > 0) {
|
|
87
|
+
return { ok: false, errors };
|
|
88
|
+
}
|
|
89
|
+
const manifest = {
|
|
90
|
+
id: raw['id'],
|
|
91
|
+
version: raw['version'],
|
|
92
|
+
displayName: raw['displayName'],
|
|
93
|
+
capabilities: raw['capabilities'],
|
|
94
|
+
configSchema: raw['configSchema'],
|
|
95
|
+
...(typeof raw['description'] === 'string' ? { description: raw['description'] } : {}),
|
|
96
|
+
...(typeof raw['entry'] === 'string' ? { entry: raw['entry'] } : {}),
|
|
97
|
+
...(Array.isArray(raw['channels']) ? { channels: raw['channels'] } : {}),
|
|
98
|
+
...(isRecord(raw['doctorContract'])
|
|
99
|
+
? { doctorContract: { checks: raw['doctorContract']['checks'] } }
|
|
100
|
+
: {}),
|
|
101
|
+
};
|
|
102
|
+
return { ok: true, manifest };
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Validate-and-return convenience for extension entry points: parses the
|
|
106
|
+
* bundled `boombot.plugin.json` and throws on the first import if the manifest
|
|
107
|
+
* is invalid, so an extension never runs with broken metadata. Every
|
|
108
|
+
* extension's `src/manifest.ts` is this call plus the JSON import.
|
|
109
|
+
*/
|
|
110
|
+
export function defineManifest(raw) {
|
|
111
|
+
const result = parseManifest(raw);
|
|
112
|
+
if (!result.ok) {
|
|
113
|
+
throw new Error(`boombot.plugin.json is invalid: ${result.errors.join('; ')}`);
|
|
114
|
+
}
|
|
115
|
+
return result.manifest;
|
|
116
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { JSONSchema } from './manifest.js';
|
|
2
|
+
export interface PluginToolDefinition {
|
|
3
|
+
readonly name: string;
|
|
4
|
+
readonly description: string;
|
|
5
|
+
readonly parameters: JSONSchema;
|
|
6
|
+
}
|
|
7
|
+
export interface PluginToolCall {
|
|
8
|
+
readonly id: string;
|
|
9
|
+
readonly name: string;
|
|
10
|
+
readonly arguments: Readonly<Record<string, unknown>>;
|
|
11
|
+
}
|
|
12
|
+
export interface PluginToolResult {
|
|
13
|
+
readonly output: string;
|
|
14
|
+
readonly error?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export type PluginToolHandler = (call: PluginToolCall, signal?: AbortSignal) => Promise<PluginToolResult> | PluginToolResult;
|
|
17
|
+
export interface BoomBotPluginApi {
|
|
18
|
+
readonly config: unknown;
|
|
19
|
+
registerTool(definition: PluginToolDefinition, handler: PluginToolHandler): void;
|
|
20
|
+
log(level: 'debug' | 'info' | 'warn' | 'error', message: string): void;
|
|
21
|
+
}
|
|
22
|
+
export interface BoomBotPlugin {
|
|
23
|
+
activate(api: BoomBotPluginApi): void;
|
|
24
|
+
deactivate?(): void;
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Encrypt `plaintext` with `masterKey`. Returns the wire-format payload. */
|
|
2
|
+
export declare function encryptSecret(masterKey: string, plaintext: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* Decrypt a payload produced by {@link encryptSecret}. Throws when the
|
|
5
|
+
* master key is wrong or the payload was tampered with (GCM auth fails).
|
|
6
|
+
*/
|
|
7
|
+
export declare function decryptSecret(masterKey: string, payload: string): string;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* At-rest encryption for provider API keys.
|
|
3
|
+
*
|
|
4
|
+
* AES-256-GCM with a 96-bit random IV per encryption; the 256-bit key is
|
|
5
|
+
* derived from the caller-supplied master secret via SHA-256. Deriving
|
|
6
|
+
* (instead of requiring exactly 32 bytes) keeps the `BOOMBOT_MASTER_KEY`
|
|
7
|
+
* contract ergonomic — any non-empty string works — while staying a standard
|
|
8
|
+
* construction.
|
|
9
|
+
*
|
|
10
|
+
* Wire format: `base64(iv).base64(ciphertext).base64(authTag)`.
|
|
11
|
+
*/
|
|
12
|
+
import { createCipheriv, createDecipheriv, createHash, randomBytes } from 'node:crypto';
|
|
13
|
+
function deriveKey(masterKey) {
|
|
14
|
+
return createHash('sha256').update(masterKey, 'utf8').digest();
|
|
15
|
+
}
|
|
16
|
+
function b64url(buf) {
|
|
17
|
+
return buf.toString('base64');
|
|
18
|
+
}
|
|
19
|
+
function fromB64(s) {
|
|
20
|
+
return Buffer.from(s, 'base64');
|
|
21
|
+
}
|
|
22
|
+
/** Encrypt `plaintext` with `masterKey`. Returns the wire-format payload. */
|
|
23
|
+
export function encryptSecret(masterKey, plaintext) {
|
|
24
|
+
if (!masterKey)
|
|
25
|
+
throw new Error('encryptSecret: masterKey must not be empty');
|
|
26
|
+
const key = deriveKey(masterKey);
|
|
27
|
+
const iv = randomBytes(12);
|
|
28
|
+
const cipher = createCipheriv('aes-256-gcm', key, iv);
|
|
29
|
+
const ciphertext = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
|
|
30
|
+
const tag = cipher.getAuthTag();
|
|
31
|
+
return `${b64url(iv)}.${b64url(ciphertext)}.${b64url(tag)}`;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Decrypt a payload produced by {@link encryptSecret}. Throws when the
|
|
35
|
+
* master key is wrong or the payload was tampered with (GCM auth fails).
|
|
36
|
+
*/
|
|
37
|
+
export function decryptSecret(masterKey, payload) {
|
|
38
|
+
if (!masterKey)
|
|
39
|
+
throw new Error('decryptSecret: masterKey must not be empty');
|
|
40
|
+
const parts = payload.split('.');
|
|
41
|
+
if (parts.length !== 3)
|
|
42
|
+
throw new Error('decryptSecret: malformed payload');
|
|
43
|
+
const [ivB64, ctB64, tagB64] = parts;
|
|
44
|
+
const key = deriveKey(masterKey);
|
|
45
|
+
const decipher = createDecipheriv('aes-256-gcm', key, fromB64(ivB64));
|
|
46
|
+
decipher.setAuthTag(fromB64(tagB64));
|
|
47
|
+
const plaintext = Buffer.concat([
|
|
48
|
+
decipher.update(fromB64(ctB64)),
|
|
49
|
+
decipher.final(),
|
|
50
|
+
]);
|
|
51
|
+
return plaintext.toString('utf8');
|
|
52
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@boombot/protocol` — LLM provider registry for BoomBot.
|
|
3
|
+
*
|
|
4
|
+
* File-backed CRUD (`createProviderService`) with API keys encrypted at rest
|
|
5
|
+
* (AES-256-GCM, `BOOMBOT_MASTER_KEY`-derived key), plus a live connectivity
|
|
6
|
+
* probe (`probeProvider`) used by the gateway's `provider.test` handler.
|
|
7
|
+
*
|
|
8
|
+
* Boundary: leaf package — node builtins only, no `@boombot/*` imports.
|
|
9
|
+
* Provider shapes mirror `@boombot/protocol`'s wire schemas
|
|
10
|
+
* structurally so the gateway can pass zod-parsed payloads straight in.
|
|
11
|
+
*/
|
|
12
|
+
export { decryptSecret, encryptSecret } from './cipher.js';
|
|
13
|
+
export { buildAuthHeaders, defaultBaseUrlFor, probeProvider } from './probe.js';
|
|
14
|
+
export { createProviderService } from './service.js';
|
|
15
|
+
export { DEFAULT_KEY_COOLDOWN_MS, KeyRoulette, type KeyRouletteOptions, } from './key-roulette.js';
|
|
16
|
+
export { deepMergeRecords, isRequestProfile, kindDefaultProfile, mergeRequestProfiles, resolveRequestProfile, type ReasoningProfile, type RequestProfile, } from './request-profile.js';
|
|
17
|
+
export { PROVIDER_KINDS, ProviderError, type ProbeOptions, type ProbeResult, type Provider, type ProviderInput, type ProviderKind, type ProviderService, type ProviderServiceOptions, } from './types.js';
|
|
18
|
+
export { getProviderProfile, listProviderProfiles, registerProvider, registeredProviderKinds, type ProviderApiMode, type ProviderAuthStyle, type ProviderProfile, } from './profiles/index.js';
|
|
19
|
+
export { CUSTOM_PROVIDERS_FILE, loadCustomProviders, registerCustomProviders, type CustomProviderWarnFn, } from './profiles/custom.js';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@boombot/protocol` — LLM provider registry for BoomBot.
|
|
3
|
+
*
|
|
4
|
+
* File-backed CRUD (`createProviderService`) with API keys encrypted at rest
|
|
5
|
+
* (AES-256-GCM, `BOOMBOT_MASTER_KEY`-derived key), plus a live connectivity
|
|
6
|
+
* probe (`probeProvider`) used by the gateway's `provider.test` handler.
|
|
7
|
+
*
|
|
8
|
+
* Boundary: leaf package — node builtins only, no `@boombot/*` imports.
|
|
9
|
+
* Provider shapes mirror `@boombot/protocol`'s wire schemas
|
|
10
|
+
* structurally so the gateway can pass zod-parsed payloads straight in.
|
|
11
|
+
*/
|
|
12
|
+
export { decryptSecret, encryptSecret } from './cipher.js';
|
|
13
|
+
export { buildAuthHeaders, defaultBaseUrlFor, probeProvider } from './probe.js';
|
|
14
|
+
export { createProviderService } from './service.js';
|
|
15
|
+
export { DEFAULT_KEY_COOLDOWN_MS, KeyRoulette, } from './key-roulette.js';
|
|
16
|
+
export { deepMergeRecords, isRequestProfile, kindDefaultProfile, mergeRequestProfiles, resolveRequestProfile, } from './request-profile.js';
|
|
17
|
+
export { PROVIDER_KINDS, ProviderError, } from './types.js';
|
|
18
|
+
export { getProviderProfile, listProviderProfiles, registerProvider, registeredProviderKinds, } from './profiles/index.js';
|
|
19
|
+
export { CUSTOM_PROVIDERS_FILE, loadCustomProviders, registerCustomProviders, } from './profiles/custom.js';
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KeyRoulette-lite: per-provider API key rotation.
|
|
3
|
+
*
|
|
4
|
+
* A provider may hold a *ring* of API keys (each stored AES-256-GCM encrypted
|
|
5
|
+
* like the old single key — the cipher is untouched). The roulette picks
|
|
6
|
+
* which key serves the next request:
|
|
7
|
+
*
|
|
8
|
+
* - The persisted `cursor` is the first key tried. It only advances when a
|
|
9
|
+
* key fails with HTTP 401/429, so a healthy key keeps serving traffic
|
|
10
|
+
* (sticky-until-failure, not blind round-robin on every request).
|
|
11
|
+
* - A failed key is benched for `cooldownMs` (default 60s) so the ring does
|
|
12
|
+
* not spin straight back into a dead key while retrying.
|
|
13
|
+
* - When the cursor's key is benched, the next healthy key scanning forward
|
|
14
|
+
* (wrapping) is used.
|
|
15
|
+
* - A single success clears the key's bench — transient blips do not
|
|
16
|
+
* permanently sideline a key.
|
|
17
|
+
* - When every key is benched, `pickIndex()` returns `null` and the caller
|
|
18
|
+
* fails the request loudly instead of hammering dead keys.
|
|
19
|
+
*
|
|
20
|
+
* The cursor is the only persisted state (via `onCursorAdvanced`, which the
|
|
21
|
+
* gateway wires to `ProviderService.setKeyCursor`). Cooldowns are
|
|
22
|
+
* intentionally in-memory: after a restart every key is tried again, which
|
|
23
|
+
* is the safe direction for a short bench.
|
|
24
|
+
*
|
|
25
|
+
* This class is transport-agnostic: the gateway's `KeyRotatingLlmClient`
|
|
26
|
+
* (`agent-worker/src/services/key-roulette-client.ts`) drives it on the real
|
|
27
|
+
* request path and retries the failed request with the next key.
|
|
28
|
+
*
|
|
29
|
+
* Boundary: leaf package — node builtins only, no `@boombot/*` imports.
|
|
30
|
+
*/
|
|
31
|
+
export interface KeyRouletteOptions {
|
|
32
|
+
/** Decrypted keys in ring order. Must be non-empty. */
|
|
33
|
+
readonly keys: readonly string[];
|
|
34
|
+
/** Persisted cursor: index of the key to try first. Defaults to 0. */
|
|
35
|
+
readonly cursor?: number;
|
|
36
|
+
/** Bench duration for a failed key, in ms. Defaults to 60_000. */
|
|
37
|
+
readonly cooldownMs?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Called whenever the cursor advances (on failure) so the caller can
|
|
40
|
+
* persist it. May be async; failures are the caller's to handle.
|
|
41
|
+
*/
|
|
42
|
+
readonly onCursorAdvanced?: (cursor: number) => void | Promise<void>;
|
|
43
|
+
/** Clock override, for tests. Defaults to `Date.now`. */
|
|
44
|
+
readonly now?: () => number;
|
|
45
|
+
}
|
|
46
|
+
/** Default bench for a key that answered 401/429. */
|
|
47
|
+
export declare const DEFAULT_KEY_COOLDOWN_MS = 60000;
|
|
48
|
+
export declare class KeyRoulette {
|
|
49
|
+
private readonly keys;
|
|
50
|
+
private cursor;
|
|
51
|
+
private readonly cooldownMs;
|
|
52
|
+
private readonly onCursorAdvanced;
|
|
53
|
+
private readonly clock;
|
|
54
|
+
/** Key index → epoch ms when the bench expires. */
|
|
55
|
+
private readonly benchedUntil;
|
|
56
|
+
constructor(options: KeyRouletteOptions);
|
|
57
|
+
/** Number of keys in the ring. */
|
|
58
|
+
get size(): number;
|
|
59
|
+
/** Current cursor — the index `pickIndex()` tries first. */
|
|
60
|
+
get currentCursor(): number;
|
|
61
|
+
/** The key at `index` (normalized into range). */
|
|
62
|
+
keyAt(index: number): string;
|
|
63
|
+
/** Epoch ms when the bench for `index` expires, or 0 when not benched. */
|
|
64
|
+
benchExpiresAt(index: number): number;
|
|
65
|
+
private isBenched;
|
|
66
|
+
/**
|
|
67
|
+
* Pick the next usable key index: the cursor when healthy, otherwise the
|
|
68
|
+
* next healthy key scanning forward (wrapping around the ring).
|
|
69
|
+
* Returns `null` when every key is benched.
|
|
70
|
+
*/
|
|
71
|
+
pickIndex(now?: number): number | null;
|
|
72
|
+
/**
|
|
73
|
+
* Mark the key at `index` as failed: bench it for `cooldownMs` and advance
|
|
74
|
+
* the cursor past it (persisted through `onCursorAdvanced`).
|
|
75
|
+
*/
|
|
76
|
+
markFailed(index: number, now?: number): Promise<void>;
|
|
77
|
+
/** A success clears the key's bench — transient blips do not sideline keys. */
|
|
78
|
+
recordSuccess(index: number): void;
|
|
79
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/** Default bench for a key that answered 401/429. */
|
|
2
|
+
export const DEFAULT_KEY_COOLDOWN_MS = 60_000;
|
|
3
|
+
function normalizeIndex(index, size) {
|
|
4
|
+
return ((index % size) + size) % size;
|
|
5
|
+
}
|
|
6
|
+
export class KeyRoulette {
|
|
7
|
+
keys;
|
|
8
|
+
cursor;
|
|
9
|
+
cooldownMs;
|
|
10
|
+
onCursorAdvanced;
|
|
11
|
+
clock;
|
|
12
|
+
/** Key index → epoch ms when the bench expires. */
|
|
13
|
+
benchedUntil = new Map();
|
|
14
|
+
constructor(options) {
|
|
15
|
+
if (options.keys.length === 0) {
|
|
16
|
+
throw new Error('KeyRoulette requires at least one key.');
|
|
17
|
+
}
|
|
18
|
+
if (options.cooldownMs !== undefined && (!Number.isFinite(options.cooldownMs) || options.cooldownMs < 0)) {
|
|
19
|
+
throw new Error('KeyRoulette cooldownMs must be a non-negative number.');
|
|
20
|
+
}
|
|
21
|
+
this.keys = options.keys;
|
|
22
|
+
this.cursor = normalizeIndex(options.cursor ?? 0, options.keys.length);
|
|
23
|
+
this.cooldownMs = options.cooldownMs ?? DEFAULT_KEY_COOLDOWN_MS;
|
|
24
|
+
this.onCursorAdvanced = options.onCursorAdvanced ?? (() => { });
|
|
25
|
+
this.clock = options.now ?? Date.now;
|
|
26
|
+
}
|
|
27
|
+
/** Number of keys in the ring. */
|
|
28
|
+
get size() {
|
|
29
|
+
return this.keys.length;
|
|
30
|
+
}
|
|
31
|
+
/** Current cursor — the index `pickIndex()` tries first. */
|
|
32
|
+
get currentCursor() {
|
|
33
|
+
return this.cursor;
|
|
34
|
+
}
|
|
35
|
+
/** The key at `index` (normalized into range). */
|
|
36
|
+
keyAt(index) {
|
|
37
|
+
return this.keys[normalizeIndex(index, this.keys.length)];
|
|
38
|
+
}
|
|
39
|
+
/** Epoch ms when the bench for `index` expires, or 0 when not benched. */
|
|
40
|
+
benchExpiresAt(index) {
|
|
41
|
+
return this.benchedUntil.get(normalizeIndex(index, this.keys.length)) ?? 0;
|
|
42
|
+
}
|
|
43
|
+
isBenched(index, now) {
|
|
44
|
+
const until = this.benchedUntil.get(index);
|
|
45
|
+
if (until === undefined)
|
|
46
|
+
return false;
|
|
47
|
+
if (until <= now) {
|
|
48
|
+
// Bench expired — drop it so the map does not grow unboundedly.
|
|
49
|
+
this.benchedUntil.delete(index);
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Pick the next usable key index: the cursor when healthy, otherwise the
|
|
56
|
+
* next healthy key scanning forward (wrapping around the ring).
|
|
57
|
+
* Returns `null` when every key is benched.
|
|
58
|
+
*/
|
|
59
|
+
pickIndex(now = this.clock()) {
|
|
60
|
+
for (let step = 0; step < this.keys.length; step++) {
|
|
61
|
+
const index = normalizeIndex(this.cursor + step, this.keys.length);
|
|
62
|
+
if (!this.isBenched(index, now))
|
|
63
|
+
return index;
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Mark the key at `index` as failed: bench it for `cooldownMs` and advance
|
|
69
|
+
* the cursor past it (persisted through `onCursorAdvanced`).
|
|
70
|
+
*/
|
|
71
|
+
async markFailed(index, now = this.clock()) {
|
|
72
|
+
const at = normalizeIndex(index, this.keys.length);
|
|
73
|
+
this.benchedUntil.set(at, now + this.cooldownMs);
|
|
74
|
+
this.cursor = normalizeIndex(at + 1, this.keys.length);
|
|
75
|
+
await this.onCursorAdvanced(this.cursor);
|
|
76
|
+
}
|
|
77
|
+
/** A success clears the key's bench — transient blips do not sideline keys. */
|
|
78
|
+
recordSuccess(index) {
|
|
79
|
+
this.benchedUntil.delete(normalizeIndex(index, this.keys.length));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live connectivity probe for an LLM provider.
|
|
3
|
+
*
|
|
4
|
+
* Strategy:
|
|
5
|
+
* 1. `GET {baseUrl}/models` — the OpenAI-style catalog (Anthropic also serves
|
|
6
|
+
* `/v1/models` with `x-api-key` + `anthropic-version`). On success the
|
|
7
|
+
* discovered model ids are returned so callers can persist them.
|
|
8
|
+
* 2. Fallback: minimal non-streaming `POST {baseUrl}/chat/completions` when
|
|
9
|
+
* the catalog endpoint 404s/405s — verifies the key works even when the
|
|
10
|
+
* provider has no models endpoint.
|
|
11
|
+
*
|
|
12
|
+
* Never throws for expected failures: they come back as `{ ok: false, error }`.
|
|
13
|
+
* Error strings never include secret material.
|
|
14
|
+
*/
|
|
15
|
+
import type { ProbeOptions, ProbeResult, ProviderKind } from './types.js';
|
|
16
|
+
/**
|
|
17
|
+
* Default base URL for a provider kind, or `null` when the kind has no
|
|
18
|
+
* default and requires an explicit `baseUrl` (`openai-compatible`, `local`).
|
|
19
|
+
* Resolved from the provider's declarative profile — the single source of
|
|
20
|
+
* truth the connectivity probe and the gateway's LLM client share.
|
|
21
|
+
*/
|
|
22
|
+
export declare function defaultBaseUrlFor(kind: ProviderKind): string | null;
|
|
23
|
+
/**
|
|
24
|
+
* Authorization headers for a provider kind, derived from its profile:
|
|
25
|
+
* `x-api-key` (+ version header) for `x-api-key` auth, `Bearer` otherwise.
|
|
26
|
+
* Exported so the gateway's LLM client authenticates exactly like the probe does.
|
|
27
|
+
*/
|
|
28
|
+
export declare function buildAuthHeaders(kind: ProviderKind, apiKey?: string): Record<string, string>;
|
|
29
|
+
export declare function probeProvider(options: ProbeOptions, apiKey?: string, timeoutMs?: number): Promise<ProbeResult>;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { getProviderProfile } from './profiles/index.js';
|
|
2
|
+
const DEFAULT_TIMEOUT_MS = 10_000;
|
|
3
|
+
/**
|
|
4
|
+
* Default base URL for a provider kind, or `null` when the kind has no
|
|
5
|
+
* default and requires an explicit `baseUrl` (`openai-compatible`, `local`).
|
|
6
|
+
* Resolved from the provider's declarative profile — the single source of
|
|
7
|
+
* truth the connectivity probe and the gateway's LLM client share.
|
|
8
|
+
*/
|
|
9
|
+
export function defaultBaseUrlFor(kind) {
|
|
10
|
+
return getProviderProfile(kind)?.defaultBaseUrl ?? null;
|
|
11
|
+
}
|
|
12
|
+
function authHeaders(kind, apiKey) {
|
|
13
|
+
const headers = { Accept: 'application/json' };
|
|
14
|
+
if (!apiKey)
|
|
15
|
+
return headers;
|
|
16
|
+
const profile = getProviderProfile(kind);
|
|
17
|
+
if (profile?.authStyle === 'x-api-key') {
|
|
18
|
+
headers['x-api-key'] = apiKey;
|
|
19
|
+
if (profile.authVersionHeader) {
|
|
20
|
+
headers[profile.authVersionHeader.name] = profile.authVersionHeader.value;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
headers['Authorization'] = `Bearer ${apiKey}`;
|
|
25
|
+
}
|
|
26
|
+
return headers;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Authorization headers for a provider kind, derived from its profile:
|
|
30
|
+
* `x-api-key` (+ version header) for `x-api-key` auth, `Bearer` otherwise.
|
|
31
|
+
* Exported so the gateway's LLM client authenticates exactly like the probe does.
|
|
32
|
+
*/
|
|
33
|
+
export function buildAuthHeaders(kind, apiKey) {
|
|
34
|
+
return authHeaders(kind, apiKey);
|
|
35
|
+
}
|
|
36
|
+
function toErrorMessage(err) {
|
|
37
|
+
if (err instanceof Error) {
|
|
38
|
+
if (err.name === 'AbortError' || err.name === 'TimeoutError')
|
|
39
|
+
return 'Probe timed out.';
|
|
40
|
+
return err.message;
|
|
41
|
+
}
|
|
42
|
+
return String(err);
|
|
43
|
+
}
|
|
44
|
+
export async function probeProvider(options, apiKey, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
45
|
+
const rawBase = options.baseUrl ?? getProviderProfile(options.kind)?.defaultBaseUrl ?? '';
|
|
46
|
+
const baseUrl = rawBase.replace(/\/+$/, '');
|
|
47
|
+
if (!baseUrl) {
|
|
48
|
+
return { ok: false, error: `Provider kind '${options.kind}' requires a baseUrl.` };
|
|
49
|
+
}
|
|
50
|
+
let parsed;
|
|
51
|
+
try {
|
|
52
|
+
parsed = new URL(baseUrl);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return { ok: false, error: `Invalid baseUrl '${baseUrl}'.` };
|
|
56
|
+
}
|
|
57
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
|
58
|
+
return { ok: false, error: 'baseUrl must use http(s).' };
|
|
59
|
+
}
|
|
60
|
+
const headers = authHeaders(options.kind, apiKey);
|
|
61
|
+
const request = (path, init) => fetch(`${baseUrl}${path}`, {
|
|
62
|
+
...init,
|
|
63
|
+
headers: { ...headers, ...(init?.headers ?? {}) },
|
|
64
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
65
|
+
});
|
|
66
|
+
try {
|
|
67
|
+
const catalog = await request('/models', { method: 'GET' });
|
|
68
|
+
if (catalog.ok) {
|
|
69
|
+
const body = (await catalog.json().catch(() => null));
|
|
70
|
+
const models = Array.isArray(body?.data)
|
|
71
|
+
? body.data
|
|
72
|
+
.map((m) => m?.id)
|
|
73
|
+
.filter((id) => typeof id === 'string' && id.length > 0)
|
|
74
|
+
: [];
|
|
75
|
+
return { ok: true, models };
|
|
76
|
+
}
|
|
77
|
+
if (catalog.status === 404 || catalog.status === 405) {
|
|
78
|
+
const chat = await request('/chat/completions', {
|
|
79
|
+
method: 'POST',
|
|
80
|
+
headers: { 'Content-Type': 'application/json' },
|
|
81
|
+
body: JSON.stringify({
|
|
82
|
+
model: 'probe',
|
|
83
|
+
messages: [{ role: 'user', content: 'ok' }],
|
|
84
|
+
max_tokens: 1,
|
|
85
|
+
}),
|
|
86
|
+
});
|
|
87
|
+
if (chat.ok)
|
|
88
|
+
return { ok: true };
|
|
89
|
+
return { ok: false, error: `Probe failed: HTTP ${chat.status}.` };
|
|
90
|
+
}
|
|
91
|
+
return { ok: false, error: `Probe failed: HTTP ${catalog.status}.` };
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
return { ok: false, error: `Probe failed: ${toErrorMessage(err)}` };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic provider profile.
|
|
3
|
+
*
|
|
4
|
+
* The only provider on the Messages wire protocol: `x-api-key` auth plus
|
|
5
|
+
* the `anthropic-version` header, and `max_tokens` is required on every
|
|
6
|
+
* request (hence the tier-1 default).
|
|
7
|
+
*
|
|
8
|
+
* Boundary: leaf package — node builtins only.
|
|
9
|
+
*/
|
|
10
|
+
import type { ProviderProfile } from './types.js';
|
|
11
|
+
export declare const anthropicProfile: ProviderProfile;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const anthropicProfile = {
|
|
2
|
+
name: 'anthropic',
|
|
3
|
+
displayName: 'Anthropic',
|
|
4
|
+
apiMode: 'anthropic_messages',
|
|
5
|
+
defaultBaseUrl: 'https://api.anthropic.com/v1',
|
|
6
|
+
authStyle: 'x-api-key',
|
|
7
|
+
authVersionHeader: { name: 'anthropic-version', value: '2023-06-01' },
|
|
8
|
+
defaultModel: 'claude-sonnet-4-5',
|
|
9
|
+
defaultProfile: { maxTokens: 4096 },
|
|
10
|
+
description: 'Anthropic Messages API (Claude models).',
|
|
11
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ProviderProfile } from './types.js';
|
|
2
|
+
/** File name (inside the config dir) holding user-defined providers. */
|
|
3
|
+
export declare const CUSTOM_PROVIDERS_FILE = "custom-providers.json";
|
|
4
|
+
/** Warning sink. The gateway passes its logger; default drops warnings. */
|
|
5
|
+
export type CustomProviderWarnFn = (message: string, meta?: Record<string, unknown>) => void;
|
|
6
|
+
/**
|
|
7
|
+
* Read and validate `<configDir>/custom-providers.json`.
|
|
8
|
+
*
|
|
9
|
+
* Returns the valid profiles (possibly empty). A missing file is not an
|
|
10
|
+
* error — it just means the user defined no custom providers. Malformed
|
|
11
|
+
* JSON or invalid entries produce warnings via `onWarn` and are skipped;
|
|
12
|
+
* this function never throws for user-data problems.
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadCustomProviders(configDir: string, onWarn?: CustomProviderWarnFn): ProviderProfile[];
|
|
15
|
+
/**
|
|
16
|
+
* Load custom providers from `<configDir>/custom-providers.json` and register
|
|
17
|
+
* them into the profile registry. Returns the number successfully registered.
|
|
18
|
+
*
|
|
19
|
+
* Never throws for user-data problems — invalid entries are skipped with a
|
|
20
|
+
* warning. Registration itself is best-effort for the same reason.
|
|
21
|
+
*/
|
|
22
|
+
export declare function registerCustomProviders(configDir: string, onWarn?: CustomProviderWarnFn): number;
|