Skip to content

MeowAndy/super-bot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

super-bot

English | 简体中文

super-bot is an async QQ bot orchestration framework inspired by NoneBot. The v1.1 direction is an LLM-facing dispatch hub: it learns capabilities from external bot frameworks, decides whether a natural-language request should call one of those capabilities, confirms risky or ambiguous requests, bridges the call into the target framework, and routes results back to the right QQ account.

Documentation quick links: Deployment Checklist | External Evidence Capture | 简体中文

Goals

  • Async-first event handling.
  • Decorator-based plugin API.
  • Protocol adapters that normalize raw payloads into common events.
  • Capability cards and a JSON-backed capability index.
  • Precise trigger and conservative confirmation gates for names such as 菲比.
  • Optional HTTP JSON LLM decision provider for capability selection, with deterministic local matching as the default.
  • Source-level plugin scanning for Yunzai, AstrBot, NoneBot, GSUID Core, Koishi, and KiviBot.
  • Deterministic learning, capability sync, version fingerprints, and source-missing disablement.
  • Task orchestration with status messages, permission checks, bridge dispatch, result mode policy, and Trace logs.
  • OneBot v11 reverse WebSocket transport primitives with self_id -> connection routing.
  • Local Web control console on port 8612 for status, capabilities, scanners, policies, traces/logs, and OneBot connections.
  • No mandatory runtime dependency for the framework core.
  • Testable handlers and adapters.

Quick start

from superbot import SuperBot, on_command, on_message
from superbot.adapters.onebot.v11 import OneBotV11Adapter


@on_command("ping")
async def ping(bot, event):
    await bot.send(event, "pong")


@on_message()
async def echo(bot, event):
    await bot.send(event, event.message.plain_text)


app = SuperBot()
app.register_adapter(OneBotV11Adapter())

Handlers registered with the module-level decorators are copied into a SuperBot instance when the app is created. Register those global decorators before constructing the app, or pass an explicit PluginManager for fully manual wiring. Command names and aliases must be non-empty strings. Passing aliases="pong" registers one alias, and command prefixes must be strings.

An adapter receives protocol-specific payloads and feeds normalized events into the app:

await app.feed_event(
    "onebot.v11",
    {
        "post_type": "message",
        "message_type": "private",
        "self_id": 10000,
        "user_id": 20000,
        "message": "ping",
        "raw_message": "ping",
    },
)

Installation

Install the core package from a source checkout:

python -m pip install -e .

For a packaged install, use:

python -m pip install super-bot

The optional reverse WebSocket server used by real NapCat or compatible OneBot deployments requires the onebot-ws extra:

python -m pip install -e ".[onebot-ws]"
# or, from a package index:
python -m pip install "super-bot[onebot-ws]"

After installation, the console scripts are sb, superbot-control, superbot-smoke, superbot-evidence, superbot-capture-evidence, superbot-acceptance, superbot-lab-acceptance, and superbot-readiness.

v1.1 task flow

from superbot import CapabilityCard, CapabilityIndex, TriggerGate
from superbot.bridges import CapabilityCall, YunzaiBridge

index = CapabilityIndex([
    CapabilityCard(
        capability_id="image.draw",
        framework="yunzai",
        adapter="yunzai.source",
        commands=["#bnn {prompt}"],
        natural_language_triggers=["画图", "绘图", "出图"],
    )
])

decision = TriggerGate(index).evaluate_text("菲比 帮我画图 小猫", session_id="demo")
card = index.get(decision.target_capability)
payload = YunzaiBridge().build(CapabilityCall(card=card, arguments=decision.arguments))
assert payload.payload["command"] == "#bnn 小猫"

The runtime orchestrator connects the full documented flow:

from superbot import SuperBot

app = SuperBot()
orchestrator = app.enable_task_orchestrator()

# Incoming message events now run through the trigger -> permission -> bridge
# -> delivery flow before falling through to lower-priority handlers.

The orchestrator only sends status text after should_call=true, capability matching, confirmation, and permission checks have passed. Pending confirmations expire after five minutes by default, so a later “去执行” will not accidentally approve stale work. Short English confirmation words such as y and n are matched as standalone tokens, so ordinary words such as maybe or none do not accidentally confirm or cancel a pending action. Capability cards can set confirmation_policy to auto, always, or never; always forces confirmation even for prefixed commands, while never disables the conservative in-sentence confirmation. Capability cards use delivery_mode="inherit" by default, which follows the delivery policy default_mode. Set a card to superbot_send or framework_direct_send only when that capability should ignore the global default. Policy default_mode and policy overrides must be concrete modes: superbot_send or framework_direct_send. Policy override keys must be global, user:<id>, group:<id>, capability:<capability_id>, framework:<framework>, or plugin:<framework>:<plugin>. Unknown bare keys are rejected so typos do not silently create policies that never match. Permission policy sets such as owners, user_whitelist, and group_blacklist accept a list of string IDs, or a single string for one ID; surrounding whitespace is trimmed, and non-string or blank entries are rejected. Capability-level permissions are also strict. The supported shape is {"required": "owner"}; unknown permission fields, non-string required values, and unsupported requirements are rejected before startup or API update.

Optional LLM Decision Provider

By default, TriggerGate uses deterministic local matching so the framework has no mandatory runtime dependency. Production deployments that want an external LLM or model gateway to choose capabilities can either configure an OpenAI-compatible chat completions provider directly, or keep using a custom HTTP JSON decision endpoint.

For OpenAI-compatible providers, set the API base, API key, and model:

sb run --api-token $env:SUPERBOT_API_TOKEN --enable-task-orchestrator --llm-api-base https://api.example.com/v1 --llm-api-key $env:SUPERBOT_LLM_API_KEY --llm-model gpt-5.5

The same values can be supplied by SUPERBOT_LLM_API_BASE, SUPERBOT_LLM_API_KEY, SUPERBOT_LLM_MODEL, and SUPERBOT_LLM_PROVIDER_NAME. When the upstream gateway supports OpenAI JSON mode, add --llm-json-mode or set SUPERBOT_LLM_JSON_MODE=true to send response_format: {"type": "json_object"} with chat completion requests; it is off by default so existing custom gateways keep their current behavior. The Web control console exposes an AI provider panel where operators can save the same OpenAI-compatible provider settings, toggle JSON mode, test connectivity, and see a redacted key preview. Leaving the key input blank while saving keeps the existing saved key; use the dashboard Clear key action to revoke the saved secret while keeping the API base, model, timeout, and JSON-mode settings. When the production acceptance page says the AI provider is configured and tested, it means the current provider type and current model have at least one successful dashboard model-test trace; saving settings alone is not enough. When --llm-provider .superbot/llm-provider.json is passed, dashboard edits are saved back to that file and are reused on the next sb run. That JSON file stores the API key in plaintext on the local machine; protect its file permissions in production, or prefer environment variables / a system credential store for the key.

The legacy provider mode is a custom HTTP JSON decision endpoint:

sb run --api-token $env:SUPERBOT_API_TOKEN --enable-task-orchestrator --llm-decision-url http://127.0.0.1:9000/decide --llm-decision-token $env:SUPERBOT_LLM_DECISION_TOKEN

SUPERBOT_LLM_DECISION_URL and SUPERBOT_LLM_DECISION_TOKEN provide the same values from the environment. The provider receives the message, the bot-name stripped body, session ID, prefix status, and the enabled capability cards. It must return JSON with should_call, target_capability, arguments, confidence, reason, and confirmation_required. A response may be returned directly, under a decision key, or as JSON text in choices[0].message.content from an OpenAI-compatible gateway.

Provider decisions are fail-closed: unknown or disabled capability IDs are rejected, provider errors do not fall back to unsafe execution, and capability confirmation policies such as always still force confirmation even when the provider says no confirmation is needed. --validate-config checks the provider URL, timeout, and token configuration. Pass --strict-validate-config when warning diagnostics should block deployment. For live provider evidence, require the optional smoke probe after startup:

superbot-smoke --control-url http://127.0.0.1:8612 --api-token $env:SUPERBOT_API_TOKEN --require-llm-decision-provider --llm-decision-url http://127.0.0.1:9000/decide --llm-decision-token $env:SUPERBOT_LLM_DECISION_TOKEN --llm-decision-smoke-message "superbot draw smoke kitten"

The smoke probe posts the same standard decision payload shape used by the runtime and fails closed when the provider is unreachable, returns malformed JSON, or selects a capability that is not enabled in the running service.

Framework scanning and capability learning

External framework plugins can be scanned into capability cards:

from superbot.scanners import ScannerRegistry

registry = ScannerRegistry(index)
registry.configure("yunzai", r"C:\path\to\Yunzai")
registry.configure("nonebot", r"C:\path\to\NoneBot")
result = registry.scan("yunzai")

Source scanners extract common command declarations as well as aliases, arrays, sets, and tuple-style command lists for Yunzai, AstrBot, NoneBot, GSUID Core, Koishi, and KiviBot projects. Scanner roots can point at a whole framework checkout, a configured plugin directory, or one plugin package. Single-plugin packages with nested helper modules are scanned as one plugin, and loose Yunzai plugin files such as plugins/paint.js are learned alongside directory-style plugins.

Automatically learned capability IDs are namespaced as framework.plugin.intent, for example yunzai.paint.image.draw, so multiple plugins with the same broad intent do not overwrite each other. The broad intent is also stored in metadata.capability_kind. Plugin names are normalized for stable IDs, while the original name is preserved in metadata.plugin_name. When a configured framework is scanned again, learned source facts such as commands, source paths, and fingerprints refresh, while operator-managed policy fields such as enabled state, delivery mode, confirmation policy, risk level, and permissions are preserved. A source-missing scan does not overwrite an operator-disabled capability, so a later source recovery will not silently re-enable something an operator turned off. The dashboard includes a framework scanning guide backed by GET /api/scanners/onboarding. It lists supported frameworks, configured roots, whether each root exists outside the SuperBot repository, learned capability counts, and next actions. It is read-only and does not run scan-all; use the dashboard scan button or POST /api/scanners/scan-all to refresh learned capabilities.

OneBot v11 reverse WebSocket

OneBotV11Adapter includes a multi-account connection registry. NapCat or BotShepherd instances should connect to one shared reverse WebSocket URL. The default NapCat/OneBot URL shape is ws://<ip>:4612/onebot/v11/ws; on a local machine that is usually ws://127.0.0.1:4612/onebot/v11/ws. self_id is read from X-Self-ID or from event payloads. Surrounding whitespace is trimmed from self_id, and a blank value is treated as missing. API calls are routed back through the matching connection, and echo waiters are isolated per connection. When a reverse WebSocket disconnects, pending OneBot API calls for that connection fail immediately instead of waiting for the request timeout. The dashboard includes a NapCat onboarding guide backed by GET /api/onebot/onboarding. It reports the recommended URL, NapCat fields, whether the WS token is enabled, real self_id connection counts, a smoke command, and next steps. The response uses environment-variable placeholders and does not echo the current token. When --onebot-token is set, reverse WebSocket clients must provide the token as Authorization: Bearer <token>, X-SuperBot-Token: <token>, or ?token=<token> / ?access_token=<token>. The Bearer scheme is case-insensitive, and header or query token values may include surrounding whitespace. Programmatic access_token values are trimmed on server creation. Custom --onebot-path values are trimmed, deduplicated, and must start with /; invalid paths fail during startup so a typo does not leave a server running on an unreachable endpoint. Runtime validation also reports empty, duplicate, or non-slash-prefixed OneBot paths when a deployment is assembled programmatically.

Production startup

The recommended packaged startup command is sb run, matching the concise runtime-entry style used by framework CLIs such as NoneBot nb run and AstrBot astrbot run. The older superbot-control command remains available as a compatibility entry point and as the lower-level control CLI for initialization, validation, scanning, and direct control-server operations.

Initialize the persistent runtime stores before the first deployment:

superbot-control --init-config .superbot

The initializer creates .superbot/capabilities.json, .superbot/policies.json, .superbot/scanners.json, and .superbot/llm-provider.json when they are missing and reports existing files without overwriting them.

Production startup example:

$env:SUPERBOT_API_TOKEN = -join ((48..57 + 65..90 + 97..122) | Get-Random -Count 40 | ForEach-Object { [char]$_ })
$env:SUPERBOT_ONEBOT_TOKEN = -join ((48..57 + 65..90 + 97..122) | Get-Random -Count 40 | ForEach-Object { [char]$_ })
sb run --capabilities .superbot/capabilities.json --policies .superbot/policies.json --scanners .superbot/scanners.json --llm-provider .superbot/llm-provider.json --api-token $env:SUPERBOT_API_TOKEN --onebot-ws --onebot-token $env:SUPERBOT_ONEBOT_TOKEN --scan-on-start --enable-task-orchestrator --require-production-config

If the HTTP control port cannot be bound, the CLI exits with a clear startup error instead of emitting a traceback. When --port 0 or --onebot-port 0 is used for an ephemeral local run, runtime status and CLI output report the real bound port. Use --require-production-config for deployment starts. It runs a strict startup gate after any --scan-on-start refresh and rejects weak production posture such as missing control or OneBot tokens, missing persistent store files, missing task orchestrator, missing OneBot reverse WebSocket, no enabled scanner, no enabled learned capability, non-loopback control binding, or disabled high-risk owner enforcement. It also rejects placeholder token values such as change-me, ws-change-me, secret, and token.

Load local decorator-based plugin packages at startup with --plugins:

sb run --plugins my_bot_plugins --onebot-ws --enable-task-orchestrator

Plugin package imports are recursive, so handlers registered from nested subpackages are available before the app starts.

Scan and configuration validation

For operational sync without starting long-running servers, scan all configured framework roots once and persist learned capabilities:

superbot-control --capabilities .superbot/capabilities.json --scanners .superbot/scanners.json --scan-once

Use --scan-on-start when the service should refresh configured scanners before binding the HTTP and WebSocket ports. Startup exits with code 2 if any scanner reports an error; pass --allow-scan-errors-on-start only when you explicitly want a degraded start after partial scan failure. When startup is rejected for scanner errors, partial successful scan results are not persisted to the capability store. When --require-production-config is also set, the production gate runs after the scan refresh so newly learned capabilities can satisfy the deployment posture check before the service starts accepting traffic. Scan-all results are per-framework; a broken configured root reports error without preventing other configured scanners from completing. Filesystem permission and I/O errors, including unreadable source files, are reported the same way with the source path in the error message. Disabled scanners are returned with skipped=true and skipped_reason="disabled". --scan-once prints the same JSON summary and exits with code 2 if any scanner reports an error, so CI and deployment scripts can fail fast on broken scanner roots or bad source files. Source scanners ignore common generated/cache directories inside plugin roots and skip metadata/config-only directories that do not expose runtime command declarations, so stale build output and empty package metadata do not become learned capabilities.

Validate configuration without starting servers:

sb run --capabilities .superbot/capabilities.json --policies .superbot/policies.json --scanners .superbot/scanners.json --llm-provider .superbot/llm-provider.json --validate-config

The validator prints JSON diagnostics and exits with code 2 when any error diagnostic is present. Warnings such as disabled API tokens or disabled scanner roots are reported without failing the command unless --strict-validate-config is also passed. Use strict validation for deployment gates when warning diagnostics should block release. Malformed capability, policy, or scanner JSON files are reported as JSON load diagnostics so automation can consume the failure consistently. Permission policy ID fields are also audited: blank IDs, non-string IDs, and unsupported collection shapes are reported before startup. Pass --require-production-config with --validate-config to preview the same production posture gate used by deployment startup. This mode treats warnings as deployment blockers and adds checks for tokens, persistent stores, task orchestration, OneBot reverse WebSocket, enabled scanners, enabled capabilities, loopback control binding, and high-risk owner enforcement. Once the service is running, GET /api/diagnostics exposes the same diagnostics engine through the token-protected control API. The live API accepts strict=true and production=true query flags, and redacts URL credentials, query strings, fragments, and secret-like diagnostic fields.

sb run --capabilities .superbot/capabilities.json --policies .superbot/policies.json --scanners .superbot/scanners.json --llm-provider .superbot/llm-provider.json --api-token $env:SUPERBOT_API_TOKEN --onebot-ws --onebot-token $env:SUPERBOT_ONEBOT_TOKEN --enable-task-orchestrator --validate-config --require-production-config

Smoke and production acceptance

After a deployment is running, use the smoke checker to produce machine-readable evidence for control API health, policy posture, loaded capabilities, configured scanners, and visible OneBot connections:

superbot-smoke --control-url http://127.0.0.1:8612 --api-token $env:SUPERBOT_API_TOKEN --require-control-api-token --require-loopback-control-host --require-task-orchestrator --require-high-risk-owner-policy --require-persistent-stores --require-writable-stores --require-capabilities --require-enabled-capability --require-scanners --require-enabled-scanner --require-clean-scan --require-onebot-connection --expect-delivery-mode superbot_send --expect-owner 10000 --expect-self-id 10000 --expect-scanner yunzai --expect-enabled-scanner yunzai --expect-framework yunzai --expect-enabled-framework yunzai --expect-trace scanner:scan_all_completed

The smoke checker prints JSON and exits with code 2 when any required check fails. URL, token, and expected-value arguments may include surrounding whitespace, which is trimmed before checks run; blank expected values fail as configuration errors instead of being ignored. It can require deployment hardening signals such as control API token enforcement, loopback-only control binding, task-orchestrator enablement, delivery default mode, configured policy owners, high-risk owner enforcement, persistent store paths, files, and writability, configured scanners, specific enabled scanners, loaded capabilities, enabled capabilities, enabled framework capabilities, clean live scanner runs, and visible OneBot connections. When --require-clean-scan is set, it runs /api/scanners/scan-all, fails on any scanner error, fails if any enabled scanner is missing from the scan-all results, and refreshes capabilities before evaluating capability expectations. Use --expect-trace stage:message, such as --expect-trace scanner:scan_all_completed, to require audit evidence from the running service. It can also verify that the reverse WebSocket endpoint accepts a handshake:

superbot-smoke --control-url http://127.0.0.1:8612 --api-token $env:SUPERBOT_API_TOKEN --onebot-ws-url ws://127.0.0.1:4612/onebot/v11/ws --onebot-token $env:SUPERBOT_ONEBOT_TOKEN --onebot-self-id "superbot-smoke" --require-onebot-smoke-connection --require-onebot-connection --expect-self-id superbot-smoke --expect-trace onebot:connection_registered

The optional WebSocket handshake briefly registers the supplied smoke self_id, so use a dedicated value that cannot collide with a real QQ account. When --require-onebot-smoke-connection is set, the smoke checker keeps the socket open long enough to verify that /api/connections reports that self_id, and the same connection snapshot can satisfy --require-onebot-connection and --expect-self-id. The OneBot reverse WebSocket also records lifecycle traces such as onebot:connection_registered and onebot:connection_unregistered, so the same smoke run can require connection audit evidence with --expect-trace. Use superbot-acceptance to prepare persistent stores, preview the production gate, and print the startup, smoke, OneBot smoke, external evidence, and capture_before / capture_after commands for an acceptance window. Use superbot-capture-evidence to save control API snapshots before and after a real QQ trigger; when a raw NapCat action log is provided, it checks for send_group_msg or send_private_msg evidence. Final production verification requires that raw log evidence; screenshots are supplementary human-review evidence only. Pass --napcat-action-screenshot <path> when a non-empty screenshot should also be recorded in capture-summary.json. Pass superbot-acceptance preflight --with-scan when scanner roots are available before the acceptance window; it runs scan-once first, saves .superbot/acceptance/scan.json, and fails if scanner refresh reports an error before validation. superbot-acceptance commands also emits artifact_commands: copy those PowerShell redirection commands when you want the required smoke, OneBot smoke, external evidence, capture result, and verify JSON files saved directly under .superbot/acceptance/. The same payload includes readiness_gaps, a token-safe list of missing real acceptance inputs such as OneBot self_id, external framework roots, trigger message, QQ group/user target, and NapCat raw action log. Use it before opening the real QQ trigger window so incomplete parameters fail early instead of at the final capture or verify step. The generated production start and preflight commands pass --llm-provider CONFIG_DIR/llm-provider.json by default, so AI provider settings saved from the Web console are loaded again during the acceptance restart. The same payload includes acceptance_steps, an ordered runbook for the acceptance window: preflight, start service, connect NapCat/OneBot, smoke, external evidence, pre-trigger capture, optional NapCat log baseline copy, real QQ trigger, post-trigger capture, and final verify. The generated post-trigger capture command includes --wait-for-capture-ok --wait-deadline 30 --wait-interval 2, so it polls until the control snapshots and capture checks pass, or records failed attempts in wait-attempts.json when the deadline expires. When --napcat-action-log is supplied, the generated artifact_commands also include napcat_action_log_baseline, a pre-trigger copy command for the raw log; the generated post-trigger capture command passes that baseline with --baseline-napcat-action-log so only newly added send actions can satisfy the NapCat raw-log evidence gate. Parseable JSON/JSONL action records are checked for successful status or retcode, and for a successful record matching qq_group_id or qq_user_id when trigger target metadata is supplied. Pass the pre-trigger traces.json to the after capture with --baseline-traces to require dispatch, bridge, and send traces added by the trigger rather than stale entries from an earlier run. Post-trigger captures also require a rendered bridge command, the selected capability in bridge traces, and a delivery target matching the captured QQ group or user. Use --expect-capability-id <id> when the acceptance trigger must prove a specific learned capability was selected. Declared self_id, framework-root, post-trigger, bridge, delivery-target, capability, trigger/bridge/delivery same-dispatch_id closed-loop, send-trace, raw-log, and optional screenshot expectations are folded into the capture gate, so insufficient evidence exits non-zero instead of looking like a successful capture. The source checkout also keeps python tools/production_acceptance.py ... and python tools/capture_external_evidence.py ... wrappers for local development. After the acceptance window, run superbot-acceptance verify --config-dir .superbot --require-capture-summary to check the saved preflight.json, smoke.json, onebot-smoke.json, external-evidence.json, any generated scan.json, capture-before-result.json, capture-after-result.json, and post-trigger capture-summary.json artifacts as one gate. The default generated command layout stores the capture summary at .superbot/acceptance/after/capture-summary.json. When the post-trigger capture used the generated wait mode, the final summary also records wait.satisfied; wait-attempts.json keeps the failed pre-success polling attempts for diagnosis. The final verify gate also cross-checks the capture summary for declared NapCat action evidence: raw logs are required and must pass existence/readability/send-action checks, baseline-backed raw logs must pass new_napcat_* checks, and any declared screenshots must pass existence/file/non-empty checks. The capture summary must also declare the trigger message and at least one QQ target (qq_group_id or qq_user_id); a trigger text without the real group or private-user target is rejected by final production verification. For final production verification, the embedded gate_result from superbot-evidence must also be present, ok, and have no failed summary or check entries. The standalone capture-summary.json must match the embedded summary inside capture-after-result.json, so swapped or stale capture files fail verification. A capture with no declared real self_id, framework root, trigger metadata, or NapCat action log/screenshot is only a snapshot and fails the external capture gate. See docs/deployment-checklist.md and docs/external-evidence-capture.md for the runtime, scanner, OneBot, smoke, and end-to-end dispatch evidence required before calling a deployment complete.

For the final external-evidence gate, require the real NapCat or compatible OneBot self_id and the real framework checkout path that should have been scanned:

superbot-evidence --control-url http://127.0.0.1:8612 --api-token $env:SUPERBOT_API_TOKEN --expect-onebot-self-id 10000 --expect-framework-root yunzai=C:\bots\Yunzai

The evidence checker prints JSON and exits with code 2 when evidence is insufficient. It rejects reserved smoke identities such as superbot-smoke, runs live /api/scanners/scan-all, requires the configured scanner root to match the provided path, requires the scan to discover plugins and learned capabilities, and requires connection and scan traces in the running service. It uses raw traces internally for those checks, but its saved evidence.traces output is reduced to a redacted audit summary with stage, message, dispatch, self_id, capability, framework, action, rendered-command presence, and target metadata only; raw payloads, prompts, commands, tokens, and secret-like fields are not kept in external-evidence.json. Framework roots under the current workspace are rejected by default so local fixtures are not mistaken for external framework evidence; use --allow-workspace-framework-root only for lab harnesses.

Current external evidence boundary

This repository can verify the local tooling, startup gates, smoke checks, and artifact validators, but it does not contain the live external evidence itself. A deployment is still unfinished until an operator captures artifacts from a real NapCat or compatible OneBot connection, a real framework checkout outside this workspace, and a real QQ trigger. The completion boundary is:

  • superbot-acceptance verify --config-dir .superbot --require-capture-summary reports ok: true.
  • superbot-evidence reports ok: true for the real self_id and framework root.
  • The post-trigger capture-summary.json reports capture_ok: true with an empty capture_failures list.
  • If wait mode was used, the post-trigger capture-summary.json reports wait.satisfied: true.
  • The post-trigger capture-summary.json contains rendered bridge-command traces, selected capability traces, and delivery target matches for the captured QQ group or user.
  • The NapCat action log proves the matching send_group_msg/send_private_msg result for the trigger target; final production verify no longer accepts screenshot-only NapCat evidence. When a raw action-log baseline was captured before the trigger, the proof must come from a new send action absent from that baseline.

When an app has a registered OneBotV11Adapter, app.create_task_orchestrator() uses a OneBot message-command executor by default. Bridge payloads such as #bnn 小猫 are sent to the originating group or private chat so the target framework bot can respond there. The orchestrator registers message-command bridges for Yunzai, AstrBot, NoneBot, GSUID Core, Koishi, and KiviBot learned capabilities, so command-based plugins from those frameworks can be invoked through the same QQ session when their command templates are known. Message-command bridges render named template slots from decision arguments; unknown slots such as {location} or {target} fall back to the parsed prompt, and empty slots are removed instead of being sent literally. OneBot API responses must be JSON objects; malformed protocol responses are reported as API errors rather than treated as successful sends.

The optional reverse WebSocket server requires:

pip install "super-bot[onebot-ws]"

If --onebot-ws is used without the optional dependency, the control CLI fails before starting the HTTP control server and reports the missing package.

Automation Continuation

Codex automations and parallel agents should keep this project moving through a repeatable readiness loop: inspect the next highest-priority gap, implement a small bounded change, run the relevant unit/smoke checks, clean generated artifacts, and then continue with the next gap until real external acceptance evidence is available.

Each continuation round should treat these local checks as the baseline:

superbot-readiness

The readiness command runs the full unit suite, compileall, wheel build smoke, editable-install and wheel-install console entrypoint checks, sb run --validate-config, live sb run startup smoke against /health and authenticated /api/status, and the lab acceptance harness. When websockets is already installed it also runs the focused real WebSocket tests; pass --with-onebot-ws-extra to create a temporary venv, install .[onebot-ws], and force those checks.

The local lab acceptance chain is available as:

superbot-lab-acceptance --output-dir .superbot/lab-acceptance/latest --reset-output-dir

It creates a temporary Yunzai fixture, runs scanner refresh, starts the real control API with an in-memory fake OneBot client, triggers a fake QQ group message, captures before/after evidence, and runs acceptance verify. Its artifacts are marked lab_only: true and are never a substitute for production NapCat/QQ evidence.

The remaining continuation priorities are:

  • Keep readiness coverage aligned with any new production gate or command.
  • Keep README.md and README.zh-CN.md updated together whenever startup, acceptance, or evidence commands change.

Final completion still requires the external evidence boundary above: real NapCat or compatible OneBot self_id, a real framework checkout outside this repository, a real QQ trigger, post-trigger dispatch and delivery capture, NapCat send-action evidence, and superbot-acceptance verify --require-capture-summary passing against those saved artifacts.

Control server

from superbot import SuperBot

app = SuperBot()
server = app.create_control_server(port=8612)
server.start()

After installation, the same server is available as:

sb run --capabilities .superbot/capabilities.json --policies .superbot/policies.json --scanners .superbot/scanners.json

When --capabilities or capability_store_path is provided, capability edits and scanner results are saved back to that JSON file. When --policies or policy_store_path is provided, delivery and permission policy changes are saved back to that JSON file. When --scanners or scanner_store_path is provided, scanner framework/root configuration is saved back to that JSON file. If a configured store write fails, the control API rejects the request and rolls runtime state back to the last in-memory value instead of leaving memory ahead of disk. Capability JSON loads are strict: list/object/boolean fields must have the right shape, capability_id must be non-empty and unique, and delivery_mode, confirmation_policy, and risk_level must use supported values before the runtime starts. Unknown top-level capability fields are rejected; put plugin/operator-specific extension data in metadata. Capability string fields, string-list entries, and choice values are trimmed when loaded from JSON or written through the control API, and duplicate capability_id values are detected after trimming. Permission policy JSON also rejects non-string entries inside owner, whitelist, and blacklist lists. Scanner JSON loads and scanner API updates also require string framework and non-empty string root_path values, and scanner file objects reject unknown top-level fields. Scanner framework and root_path values are trimmed when loaded from JSON, written through the API, or configured programmatically. Static scanner files reject duplicate framework entries after trimming so one scanner does not silently overwrite another during startup. Scanner API updates preserve existing scanner metadata unless a replacement metadata object is provided. When --api-token or api_token is provided, control API endpoints require Authorization: Bearer <token> or X-SuperBot-Token: <token>; /health remains unauthenticated for local health checks. Query-string tokens are ignored by /api endpoints so secrets are not exposed through browser history, logs, or Referer headers. The built-in dashboard shell can be opened at /; enter the token in the dashboard or open /#token=<token> to store it in sessionStorage. Dashboard API calls send the token with X-SuperBot-Token instead of placing it in API URLs. The Bearer scheme is case-insensitive, and header token values are trimmed before constant-time comparison. The Web control console shows runtime status, learned capabilities, OneBot connection snapshots, production completion, the current highest-priority blocker, a next-action center, runtime diagnostics, traces/logs, policies, and scanner configuration. It also includes an AI provider panel for OpenAI-compatible model base URLs, API keys, model names, redacted saved-key status, and a live provider test, plus a production startup guide that shows token-safe validate, restart, and preflight commands. It is the operator-facing place to confirm that NapCat is connected to the default reverse WebSocket URL ws://<ip>:4612/onebot/v11/ws, inspect recent dispatch activity, review production posture, run controlled OneBot status/login/test message actions, review policy state, configure the LLM provider, and run scanner refreshes without hand-writing API requests. Technical JSON previews in the dashboard are kept under collapsed "technical details" blocks by default, so operators can read the human-facing summaries first and only expand raw diagnostic context when troubleshooting. This includes LLM provider test output, controlled OneBot action responses, scanner run results, acceptance previews, and artifact summaries. Dashboard refreshes load each section independently: if one API endpoint fails, that section shows a localized error while the rest of the console continues to render. Dangerous LLM provider actions such as clearing the saved provider or clearing the saved key require a browser confirmation. The OneBot test action form also checks self_id, target, message, and the explicit send confirmation before posting send_private_msg or send_group_msg. Command blocks in the startup guide and next-action center include one-click copy controls. They copy the rendered token-safe command text only; secrets stay as environment-variable placeholders. For deployments, SUPERBOT_API_TOKEN and SUPERBOT_ONEBOT_TOKEN can provide the same secrets without placing them in the process command line; explicit CLI flags take precedence. CLI and environment token values are trimmed at startup. Programmatic api_token values are trimmed when the control server is created.

The minimal endpoints are:

  • GET /api/status
  • GET /api/diagnostics
  • GET /api/startup/onboarding
  • GET /api/acceptance/status
  • GET /api/actions/status
  • GET /api/artifacts/status
  • GET /api/capabilities
  • GET /api/capabilities/onboarding
  • POST /api/capabilities/{capability_id}
  • GET /api/scanners
  • GET /api/scanners/onboarding
  • POST /api/scanners
  • POST /api/scanners/{framework}/scan
  • POST /api/scanners/scan-all
  • GET /api/policies
  • GET /api/policies/onboarding
  • POST /api/policies
  • GET /api/llm/provider
  • POST /api/llm/provider
  • POST /api/llm/provider/test
  • GET /api/onebot/onboarding
  • GET /api/connections
  • POST /api/onebot/action
  • GET /api/traces

The bundled dashboard exposes the same scanner controls: add or update scanner roots, mark scanners enabled or disabled, run one scanner, or run scan-all. It also shows live diagnostics from the same engine as sb run --validate-config; use /api/diagnostics?strict=true&production=true to check the production gate from a running service. GET /api/startup/onboarding powers the production startup guide: it is read-only and returns redacted token state, persistent store status, next-step blockers, and copyable commands for validating config, restarting with --llm-provider .superbot/llm-provider.json, and running preflight. It only uses $env:SUPERBOT_API_TOKEN and $env:SUPERBOT_ONEBOT_TOKEN placeholders, and does not echo the real control token, OneBot token, or LLM provider key. GET /api/acceptance/status is a read-only production acceptance overview: it summarizes production diagnostics, the current real OneBot/framework/capability/LLM gaps, saved .superbot/acceptance artifact verification, and an operator runbook with environment-variable token placeholders. It also exposes the same token-safe readiness_gaps list as superbot-acceptance commands, so the dashboard can show missing self IDs, external framework roots, trigger text, QQ targets, or NapCat raw-log parameters before the real trigger window. It does not trigger scan-all on page load and does not echo the current control or OneBot token. The production acceptance panel includes a session-only evidence-parameter form for the real trigger message, QQ group or user target, expected capability IDs, NapCat raw action log, and optional screenshots; applying it refreshes the acceptance overview and generated runbook without writing those values to the persistent stores. The same panel renders a copyable acceptance command package from artifact_commands, preferring commands that redirect smoke, evidence, capture, and verify output into .superbot/acceptance/ so operators do not have to pull required commands from the raw JSON preview. The first command block in that package is a "copy all" bundle with ordered comments for the whole acceptance window; the following blocks still allow copying one command at a time. GET /api/actions/status powers the next-action center: it read-only aggregates acceptance blockers plus the startup, NapCat, scanner, capability, policy, LLM, and artifact guides into a prioritized operator queue with dashboard anchors and token-safe commands. Its response includes those acceptance readiness gaps for the right-side operator checklist, using the same evidence parameters when the dashboard form is filled. It only returns redacted context and environment-variable placeholders, never the real control token, OneBot token, or LLM provider key. GET /api/artifacts/status powers the dashboard artifact center: it only summarizes .superbot/acceptance and .superbot/readiness file status, the latest readiness run, and bounded JSON metadata, without returning raw logs, command lines, or secret-like fields. GET /api/onebot/onboarding powers the NapCat onboarding guide: it returns the recommended reverse WebSocket URL, NapCat settings, token status, real and smoke connection counts, a smoke command, and next steps without exposing the real token. GET /api/scanners/onboarding powers the framework scanning guide: it checks scanner configuration, external repository roots, learned capability counts, and next actions without automatically running scan-all. GET /api/capabilities/onboarding powers the capability enablement guide: it is read-only and summarizes learned/enabled/unavailable capabilities, risk levels, owner-required capability counts, framework totals, persistent store status, and recommended first capabilities to review before production smoke. GET /api/policies/onboarding powers the security policy guide: it is read-only and explains whether owner QQ IDs, high-risk owner confirmation, policy store persistence, and whitelist/blacklist counts are ready for production. It can surface recent candidate user/group IDs from redacted traces, but it does not modify policy and does not echo tokens. POST /api/onebot/action is a controlled test surface, not a general OneBot proxy: it requires a control API token, only allows get_status, get_login_info, send_private_msg, and send_group_msg, and send actions require confirm_send=true. Scanner configuration changes record control:scanner_configured trace entries with the effective framework, root, enabled state, and metadata. Control API errors are returned as JSON objects with error.status, error.code, and error.message, including authentication and validation failures. POST request bodies must be UTF-8 JSON objects no larger than 1 MiB; malformed, misencoded, or oversized bodies return JSON 400 errors. Capability, policy, and scanner update payloads reject unsupported fields so typos such as owner, risk, or enabledd do not silently become no-ops. Capability, scanner, and trace API responses also recursively coerce common extension values such as datetime, path-like objects, sets, tuples, non-string mapping keys, and non-finite floats into JSON-safe values before returning or persisting them. This keeps plugin-provided metadata from breaking the control surface. The in-process capability index, trace log, scanner registry, policy objects, and OneBot connection snapshots are protected for the local control server's HTTP threads reading state while the bot runtime updates it.

GET /api/capabilities accepts framework, enabled, q/query, limit, and offset query parameters. GET /api/traces accepts stage, message, q/query, limit, offset, and redacted. Trace responses are redacted by default for the dashboard; redacted=false requires a configured control API token, and evidence tooling uses it only with that token when it needs raw audit payloads for closed-loop verification. Both endpoints keep their original list field and add a page object with total, count, offset, and limit. GET /api/status reports whether each configured store exists and is writable, including parent-directory and file-level writability signals used by superbot-smoke --require-writable-stores.

Layout

  • superbot.core: application container, bot runtime, events, messages, and control-flow exceptions.
  • superbot.plugins: decorator-based plugin manager and handler dispatch.
  • superbot.adapters: protocol adapter interfaces and implementations.
  • superbot.adapters.onebot: OneBot protocol implementations.
  • superbot.utils: small shared internal helpers.

Public imports should prefer from superbot import .... Internal framework code should import from the concrete subpackage it belongs to, such as superbot.core.events or superbot.plugins.manager.

Development

Run the tests with:

python -m unittest discover -s tests

The CI workflow runs the same core gate on Python 3.10, 3.11, and 3.12:

python -m unittest discover -s tests -v
python -m compileall -q superbot tests
python -m pip wheel . --wheel-dir "$env:TEMP\superbot-wheel-verify"
python -m superbot.cli --help
python -m superbot --help
python -m superbot.cli run --help
python -m superbot.cli run --api-token dev-api-token --validate-config
python -m superbot.cli run --api-token dev-api-token --llm-decision-url http://127.0.0.1:9999/decide --validate-config
python -m superbot.cli run --api-token dev-api-token --validate-config --strict-validate-config
python -m superbot.cli run --api-token dev-api-token --validate-config --require-production-config
python -m superbot.control --help
python -m superbot.control.production_acceptance --help
python -m superbot.control.external_evidence_capture --help
python -m superbot.control.evidence --help
python -m superbot.control.lab_acceptance --help
python -m superbot.control.readiness --help
python -m superbot.control.smoke --help
superbot-acceptance --help
superbot-lab-acceptance --help
superbot-readiness --help
sb --help
sb run --help
sb run --api-token dev-api-token --validate-config
sb run --api-token dev-api-token --validate-config --strict-validate-config
superbot-control --help
superbot-capture-evidence --help
superbot-evidence --help
superbot-smoke --help

The superbot-control and python -m superbot.control entries remain compatibility checks for the lower-level control CLI. Production startup and runtime validation should use sb run.

In the Codex desktop runtime used for this repository, the bundled Python path is:

C:\Users\Administrator\.cache\codex-runtimes\codex-primary-runtime\dependencies\python\python.exe -m unittest discover -s tests -v

Install super-bot[onebot-ws] or websockets>=12 to enable the optional real reverse WebSocket server/client integration tests; otherwise those tests are skipped and the fake transport coverage still runs.

With the optional dependency installed, run the focused WebSocket checks with:

python -m unittest tests.test_core.CoreTests.test_onebot_reverse_ws_real_websockets_server_roundtrip_when_available tests.test_core.CoreTests.test_control_smoke_onebot_ws_handshake_when_available tests.test_core.CoreTests.test_control_smoke_onebot_ws_connection_visible_when_available tests.test_core.CoreTests.test_control_smoke_onebot_ws_trace_expectation_when_available -v

About

SuperBot: unified bot orchestration, OneBot/NapCat bridge, web control console, and production acceptance tooling

Resources

License

Stars

2 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages