Commit Graph
6 Commits
Author SHA1 Message Date
DrSmoothl 7c0519f75f lint 2026-10-12 15:43:34 +08:00
DrSmoothl f9c4063fc5 feat(onebot): complete trace operation chains
Make short TRACE captures independently explain OneBot action and event lifecycles from complete input through a truthful terminal conclusion. Preserve request correlation across asynchronous work while keeping disabled TRACE paths allocation-free and lazy.

Cover shutdown rejection, stream cancellation, event conversion and suppression, reporter invocation settlement, and HTTP delivery outcomes without changing established transport or observer behavior. Add focused regression coverage for lifecycle uniqueness, context reuse, disconnect handling, and quiesce ingress boundaries.
2026-07-30 17:13:40 +08:00
DrSmoothl 852004291b feat(onebot): reconcile and drain network adapters
Serialize desired network plans, isolate per-adapter apply failures, restore prior bindings when possible, and report saved versus applied state. Quiesce Action and event ingress, await in-flight dispatches and transport closes, retain failed generations for retry, and propagate shutdown failures.
2026-07-10 13:49:17 +08:00
DrSmoothl 01ef98abb6 feat(onebot): Stream API transport plumbing (#163 phase 1)
Foundation for NapCat-compatible Stream API actions (chunked file
upload/download): a single request answered by many response frames.

- streaming.ts: StreamSink + frame wrappers (wrapStreamFrame /
  wrapStreamTerminal) matching NapCat's wire — each frame an OB11 envelope
  with stream:'stream-action', data.type ∈ stream/response/error, and
  message mirrored into wording.
- ApiHandler: registerStreamAction / isStreamAction; handle() threads a
  sink; processStreamRequest drives WS multi-frame dispatch with optional
  liveness-based abort; dead processRequest removed.
- action-kit: defineStreamAction (sink-aware run, registers as a stream
  action) reusing defineAction's parse/describe.
- adapters: HTTP server streams chunked \r\n\r\n-delimited frames (no
  Content-Length, no false application/json), aborting on client
  disconnect; WS server/client use a backpressure-aware safeSendAsync and
  abort a stream once the socket closes.

No stream actions are registered yet — those land in the next phases.
Verified by two adversarial review passes. 480 onebot tests green.
2026-06-30 14:40:39 +08:00
DrSmoothl 18f7d847ac refactor(onebot): lift the network adapter reload state machine into the base class
The four NetworkAdapters each carried a byte-identical reload() state machine (sigChanged/wasEnabled -> Reopened/Closed/Opened/Normal). Lift it into IOneBotNetworkAdapter as a template method; per-adapter variation is now expressed via three hooks: bindingSignature(), willEnable() (default enabled!==false; clients add && !!url), and onConfigReplaced() (post-swap side effects).

Also delete four redundant 'override get isActive()' (identical to the base getter), lift the duplicated uin-logger setup into the base ctor, and drop http-post's now-redundant signature_ cache.

NetworkReloadType is a test-observability seam -- the sole production caller (instance.applyConfigDiff) discards it -- so a new base-level test exercises all transitions directly. Behaviour-preserving: +94/-157 in src, full workspace typecheck clean, 332 onebot tests pass.
2026-06-03 20:53:36 +08:00
DrSmoothl 9a30df9907 refactor(onebot): extract OneBot protocol translation into @snowluma/onebot
Phase 3 of the 4-package split (RoadMap #3). Moves the entire
`packages/core/src/onebot/` subtree (43 source files + 20 test files
spanning network adapters, action handlers, event converters, message
parser, message store, media store, instance + manager) into the new
`@snowluma/onebot` workspace package. The remaining `@snowluma/core`
now hosts only the api-layer (Bridge class + 13 Api classes), the
hook tooling, the WebUI server, and the runnable `index.ts`.

Why
---
- The OneBot adapter is the public-facing OneBot11 protocol surface;
  it has its own version cadence and its own consumers (third-party
  bots talking OneBot WS / HTTP). Splitting it lets that cadence move
  independently of the Api-on-ctx layer.
- The two were sharing the `packages/core/` build pipeline only
  because they happened to live in the same directory. Nothing in
  the api-layer reaches into OneBot internals.
- Mirrors NapCat / Lagrange.OneBot's repo split (their OneBot adapter
  is a separate assembly from the Core protocol library).

Layout
------
Moved via `git mv` (history preserved):
  packages/core/src/onebot/*  → @snowluma/onebot/src/<x>
  packages/core/tests/onebot/* (6 files)   → @snowluma/onebot/tests/
  packages/core/tests/{message-parser,message-store,event-pipeline,
    media-store,media-url-resolver,event-converter,
    http-server-hot-reload,http-server-content-type,
    api-handler-logging,message-id,group-msg-emoji-like,
    config,media-indexer,network-manager}.test.ts (14 files)
                                              → @snowluma/onebot/tests/

What stays in @snowluma/core
----------------------------
- `bridge/{bridge,bridge-interface,bridge-context,manager}.ts`
- `bridge/apis/*` (the 13 typed Api classes)
- `hook/*` (debugger/injector — tooling for the core protocol layer)
- `webui/*` (admin UI server — application wiring, not the OneBot
  adapter itself)
- `index.ts` (application entry that wires BridgeManager +
  OneBotManager + HookManager + WebUI together)

Changes
-------
- New package `packages/onebot/` (package.json with subpath exports
  mirroring legacy `core/src/onebot/<x>` 1:1, tsconfig.json,
  vitest.config.ts with `SNOWLUMA_LOG_LEVEL=debug` env so the action-
  dispatch logging tests see debug-level subscribers — copied verbatim
  from core's vitest.config.ts).
- @snowluma/core grows new subpath exports for the api-layer files
  OneBot's type-only imports need: `./bridge`, `./bridge-interface`,
  `./bridge-context`, `./manager`, `./apis`.
- `@snowluma/onebot` depends on `@snowluma/bridge`, `@snowluma/common`,
  `@snowluma/core`, `@snowluma/proto-defs`, `@snowluma/proton`,
  `@snowluma/websocket`.
- `@snowluma/core` depends on `@snowluma/onebot` (for index.ts +
  webui/server.ts wiring).
- 100+ import sites rewritten via sed:
  * OneBot → core: `'../bridge/bridge'` → `'@snowluma/core/bridge'`,
    `'../bridge/manager'` → `'@snowluma/core/manager'`,
    `'../bridge/bridge-interface'` → `'@snowluma/core/bridge-interface'`,
    `'@/bridge/bridge'` (vite path alias) → `'@snowluma/core/bridge'`.
  * Core → OneBot: `'./onebot/manager'` → `'@snowluma/onebot/manager'`,
    `'../onebot/config'` → `'@snowluma/onebot/config'`, etc.
  * Test relative paths: `'../../src/onebot/<x>'` → `'../src/<x>'`
    after the test file move (one level shallower).
- New `packages/onebot/src/env.d.ts` declaring `__APP_VERSION__` and
  `__BUILD_WEBUI__` (the vite-injected globals `info.ts` reads).

Workspace cycle
---------------
core ↔ onebot is allowed by pnpm workspaces. The runtime direction
is one-way: core → onebot (index.ts constructs OneBotManager,
webui/server reads OneBot config). OneBot only reaches into core for
TYPES (Bridge, BridgeInterface, BridgeManager, ClientKeyInfo,
DownloadRKeyInfo); those imports use `import type` so they compile
out at runtime and don't introduce a real cycle.

Verification
------------
- Full workspace `pnpm -r typecheck`: all 11 projects clean.
- `@snowluma/core` test suite: 302/302 pass (33 test files).
- `@snowluma/onebot` test suite: 250/250 pass (20 test files;
  pre-existing `network-manager.test.ts` native-addon failure
  unchanged — same baseline as before the split).
- Combined: 552/552 — identical pass count to the pre-Phase-3
  baseline.
- Vite build with stubbed native binary: clean, 2.84 MB bundle /
  224 KB gzip (identical envelope).
2026-05-21 08:52:00 +08:00