27 Commits
Author SHA1 Message Date
手瓜一十雪 af8d5ab06b Split channel packages and rename Account→Core
Reorganize package layout and rename core/account types: - Move channel hook & socket sources/tests into packages/channel-hook and packages/channel-socket (many files renamed). - Remove ChannelManager from packages/channel and drop its export from package.json (multi-account host folded into Hub). - Update tests to use HookSink instead of BridgeManagerSink. - In @snowluma/core: move account/apis/* up to src/apis, rename account-context→core-context, account-interface→core-ctx, account→core, and add hub.ts; delete AccountManager. - Update constructors and type usages to accept CoreContext/CoreCtx and adapt identifiers accordingly. This is a refactor to clarify responsibilities (split transport implementations, fold multi-account manager into Hub, and rebrand the account layer as Core).
2026-05-27 14:11:45 +08:00
手瓜一十雪 adf0744f75 Rename bridge → channel and reorganize packages
Move/rename the transport/bridge code into a new @snowluma/channel layout and extract hook implementations into channel-specific packages. Many bridge sources were deleted and equivalent channel files added (adapter/ctx/interface/channel/hook/socket pieces moved/renamed), along with tests and configs relocated under packages/channel. RoadMap.md replaced with a detailed v3 architecture plan describing Channel/ChannelCtx/Core/CoreCtx/Hub boundaries and migration steps. Also apply related core package updates (account/core reshaping and package.json adjustments) to match the new architecture.
2026-05-27 13:39:17 +08:00
手瓜一十雪 652bafd75a Extract bridge transport into @snowluma/bridge
Move transport-layer bridge code out of @snowluma/core into a dedicated @snowluma/bridge package and introduce a clear account layer in core. Adds Bridge, BridgeInterface, InjectBridge, ProtocolBridge (stub), adapters, and manager files under packages/bridge and updates package.json exports. In @snowluma/core the former bridge surface is replaced by Account, AccountContext, AccountInterface and AccountManager; apis were moved/renamed to account/apis and now consume AccountContext. Adjustments include packet handling plumbing (use deliverPacket / setPacketHandler), updated sendRawPacket wiring, uploaded-file cache and lifecycle changes (InjectBridge.dispose, ProtocolBridge returns a structured not-implemented result). Tests and imports were updated accordingly.
2026-05-27 12:27:13 +08:00
手瓜一十雪 5440cbc37e Refactor bridge system: adapters & transports
Introduce a transport-adapter layer and refactor the bridge abstractions to be transport-agnostic. Added BridgeAdapter and BridgeAdapterHost (packages/core/src/bridge/adapter.ts) plus concrete InjectBridge/InjectBridgeAdapter and ProtocolBridge/ProtocolBridgeAdapter implementations (new files). Made Bridge an abstract base exposing kind/id and abstract sendRawPacket, moved transport-specific PID/sender logic into InjectBridge. Reworked BridgeManager to register/start adapters, manage bridges by id/uin, pick a primary per-UIN (inject preferred over protocol), and provide a host API for adapters to add/remove bridges. Updated index bootstrapping to register adapters and wire the WebUI to the inject adapter's HookManager. Adjusted tests and OneBot code to remove PID tracking from OneBotInstance/OneBotManager and to instantiate InjectBridge in tests. Also exported new entry points in package.json for adapter/bridge modules. This decouples transports from manager logic and adds a stubbed protocol runtime for future pure-protocol support.
2026-05-27 11:49:43 +08:00
手瓜一十雪 2c565fbd8d Switch from @snowluma/sqlite to node:sqlite (sync)
Remove the in-tree @snowluma/sqlite wrapper and vendored better-sqlite3 prebuilts; migrate consumers to node:sqlite's synchronous API. Replaced imports and types (Database/Statement -> DatabaseSync/StatementSync), updated PRAGMA calls to use exec, and adjusted code in onebot (media/message/reaction stores) and protocol (identity service). Vite config no longer bundles sqlite native binaries and references to the sqlite workspace were removed. Also delete the packages/sqlite package and its native prebuild artifacts, and add a couple of unrelated AST improvements in proton: use a module-level shared wrapper cache and add an inheritance cache to avoid repeated scans. Minor import reordering/cleanup applied where needed.
2026-05-26 21:59:26 +08:00
DrSmoothl 5924346823 chore(release): v1.9.2 2026-05-24 18:01:50 +08:00
DrSmoothl f53df5e313 refactor(packages): extract @snowluma/bridge (hook + QQ lifecycle)
Split the QQ NT client lifecycle / hook injection layer out of
@snowluma/core into its own self-contained package. The new bridge
package owns:
  - native hook addon loader (injector)
  - HookManager + per-PID HookSession orchestration
  - PipeWatcher for QQ process discovery
  - QqHookClient pipe protocol
  - qq-port-probe for early UIN sniffing

The hook layer used to type its main collaborator as
`BridgeManager` directly. To keep the new package free of any
dependency on @snowluma/core, the cross-package coupling is now
expressed via a 3-method `BridgeManagerSink` interface that lives
in the bridge package. BridgeManager (in core) satisfies the
interface structurally with no source changes; the top-level
app/webui still inject it the same way.

Pure file relocation otherwise: git mv preserves history at 100%
on every file, the only logic edit is the interface introduction
in hook-manager.ts and an updated `nativeSearchDirs()` offset
(one fewer `..` since hook now lives at packages/bridge/src
instead of packages/core/src/hook).
2026-05-23 23:40:57 +08:00
DrSmoothl c16064d7e3 refactor(packages): rename @snowluma/bridge → @snowluma/protocol
The package previously named "bridge" houses the protocol-byte layer
(OIDB cmds, msg-push decoders, highway uploaders, element-builder,
event bus). The name "bridge" suggested transport/lifecycle, which it
isn't — that role lives in core/hook and core/bridge/manager. Rename
to match what's actually inside.

This is a pure rename: zero logic changes, all 73 import sites updated
mechanically and TS-verified. core/onebot dependencies key updated.
ESLint override path adjusted for the moved oidb-services directory.

Rename detection threshold: git log --find-renames=20% recommended
when following history across this commit — content-replacement
(@snowluma/bridge → @snowluma/protocol) dropped per-file similarity
below git's default 50% on import-heavy files.
2026-05-23 23:31:03 +08:00
DrSmoothl ee0f159b7e fix(deps): drop dead hono devDeps from @snowluma/onebot, align core to ^4.12.18
`packages/onebot` declared `hono` and `@hono/node-server` as devDeps but
never imported either — they were leftover scaffolding from when onebot
was carved out of `@snowluma/core`. Combined with dependabot's hono
bump only landing on core's pin (4.12.14 → 4.12.18 in cb06624), this
left two distinct peer-dep resolutions of `@hono/node-server` in the
lockfile (`(hono@4.12.14)` for onebot, `(hono@4.12.18)` for core).
On the dev→main merge the auto-resolver kept main's snapshot list,
dropping the `(hono@4.12.14)` variant onebot still referenced — so
v1.9.1 shipped with an inconsistent lockfile and CI's
`pnpm install --frozen-lockfile` blew up with
`ERR_PNPM_LOCKFILE_MISSING_DEPENDENCY: no entry for
'@hono/node-server@1.19.14(hono@4.12.14)'`.

Fix:
- Remove `hono` + `@hono/node-server` from onebot (verified zero source
  imports — only matches were `honour` / `WebHonorType` false hits).
- Bump core's `hono` pin to `^4.12.18` so dev matches what dependabot
  already landed on main (otherwise the drift comes back on next merge).
- Regenerate pnpm-lock.yaml — now resolves to a single
  `@hono/node-server@1.19.14(hono@4.12.21)` snapshot.
2026-05-21 17:43:10 +08:00
DrSmoothl 607a7b319b chore(release): v1.9.1 2026-05-21 17:33:35 +08:00
DrSmoothl 4e51b4bd7d build(sqlite): wrap better-sqlite3 with @snowluma/sqlite + vendor prebuilts
Replaces "runtime npm dependency that gets `npm install`-ed into
dist/" with "TS wrapper that loads the native `.node` from
`dist/native/` like every other native binding in the project".

Why the change
--------------
The previous approach (better-sqlite3 declared in
packages/runtime/package.json, materialized by `npm install
--omit=dev` in dist/) worked but produced an artifact that needed
runtime npm install — a step the rest of SnowLuma's native bindings
don't need (websocket / snowluma-hook / ffmpeg are all standalone
`.node` files copied into `dist/native/` by vite-plugin-cp). The
asymmetry was friction: dev mode required `pnpm dist:install`,
build artifacts carried a `dist/node_modules/` tree the other
modules didn't need, and Docker images had to special-case the
glibc-vs-musl ABI lookup that prebuild-install runs.

The new shape:
  - `@snowluma/sqlite` (packages/sqlite/) — TS wrapper. Has
    `better-sqlite3` as a devDep (for the JS-layer types + the
    actual JS wrapper code that vite inlines). At runtime, calls
    `createRequire().require()` against
    `<dist|repo>/native/better-sqlite3-v<abi>-<platform>-<arch>.node`
    and passes the resolved addon to `new Database(path, {
    nativeBinding })`.
  - `packages/runtime/native/better-sqlite3-v<abi>-<triplet>.node`
    — prebuilt binaries vendored into the repo. Two ABIs ship side-
    by-side (v127 = Node 22 LTS used by CI, v137 = Node 24 used by
    dev boxes) so `process.versions.modules` picks the matching one
    at load time.
  - `tools/fetch-sqlite-prebuilts.mjs` — fetches all 5 platforms ×
    N ABIs from WiseLibs's GitHub releases. Idempotent: existing
    `.node` files skip. Accepts extra ABI args:
    `node tools/fetch-sqlite-prebuilts.mjs 12.10.0 v127 v137 v115`.

What was unwound
----------------
- packages/runtime/package.json — dependencies removed (runtime
  artifact is now self-contained, no `npm install` step needed).
- root package.json — `dist:install` script removed (no node_modules
  to install).
- .github/workflows/dev-build.yml — `Bundle runtime dependencies`
  step removed.
- .github/workflows/release.yml — kept the `Bundle runtime
  dependencies` step (was a no-op already, but harmless safety net
  in case a future runtime dep shows up).
- packages/core/vite.config.ts — `better-sqlite3` no longer
  external; vite inlines the JS wrapper (+~33 KB to bundle, ~2.84
  MB → 2.87 MB total).

Naming
------
Mirrors the existing `websocket-${triplet}.node` convention (flat
dir under `runtime/native/`, dash-separated `<platform>-<arch>`).
Adds a `v<abi>` segment because better-sqlite3 is NOT N-API — one
binary per Node ABI. Naming:

  better-sqlite3-v127-darwin-arm64.node    Node 22 / macOS arm
  better-sqlite3-v127-darwin-x64.node      Node 22 / macOS intel
  better-sqlite3-v127-linux-arm64.node     Node 22 / Linux arm
  better-sqlite3-v127-linux-x64.node       Node 22 / Linux x64
  better-sqlite3-v127-win32-x64.node       Node 22 / Windows x64
  better-sqlite3-v137-... (5)              Node 24 / same 5 hosts

Total: 10 binaries × ~1.9 MB = ~19 MB committed. Aligned with the
existing native-vendoring footprint (websocket ~2 MB × 5, snowluma-
hook ~10 MB × Windows + Linux, ffmpeg ~10-30 MB × 4).

What changes for consumers
--------------------------
Source-side: nothing. `import Database, { type Database, type
Statement } from '@snowluma/sqlite'` is a drop-in for the previous
`import Database from 'better-sqlite3'`. The wrapper re-exports the
same types and the `Database` callable factory has the same
overload set.

Runtime: `node` finds the binding at
`<dist|repo>/native/better-sqlite3-v${process.versions.modules}-
${process.platform}-${process.arch}.node`. If the ABI doesn't
match a vendored binary, the wrapper throws a clear error pointing
at `tools/fetch-sqlite-prebuilts.mjs` with the missing ABI/triplet.

Bumped better-sqlite3 from 11.10.0 → 12.10.0 because v11 only had
prebuilt up to Node ABI v127 (no v137 = no Node 24). v12.10.0
ships both. Both versions are API-compat (the breaking changes
between v11 and v12 were either internal or in error-handling
paths SnowLuma doesn't exercise).

Verification
------------
- pnpm -r typecheck (12 projects): clean
- @snowluma/core test: 302/302
- @snowluma/onebot test: 250/250 (552/552 combined, unchanged from
  the perf-series baseline)
- Bench numbers preserved — wrapper indirection is sub-μs:
  storeMeta ~11 μs, storeEvent ~17 μs, findMeta hit ~1.1 μs (all
  within noise of the post-RoadMap-#5 measurements).
- Vite build clean, bundle = 2.87 MB / 230 KB gzip
- `dist/index.mjs` no longer contains a `node:sqlite` import (it
  did before — media-store hadn't migrated; now neither it nor
  message-store reach into the Node builtin).

Bonus side-fix: `packages/onebot/src/media-store.ts` also moved
off `node:sqlite` (caught by the post-build bundle grep — the
file was using `DatabaseSync` + `StatementSync` from the builtin
even though it had already been written to cache its prepared
statements). Its hot paths now go through the same wrapper.
2026-05-21 13:49:19 +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
DrSmoothl f7a03ca05a refactor(bridge): extract protocol layer into @snowluma/bridge package
Phase 2 of the 4-package split (RoadMap #3). Moves ~35 files —
events / event-bus / identity-service / packet-pipeline / element-
builder / bridge-oidb / qq-info / msg-push/* / highway/* / web/* +
the bridge-side formatters — out of `packages/core/src/bridge/`
into the new `@snowluma/bridge` workspace package. Everything that
translates QQ wire bytes ↔ typed events/elements now lives there.

Why
---
- `packages/core/src/bridge/` was actually two layers: a low-level
  "protocol decoder + I/O" set (msg-push, highway, packet-pipeline,
  identity, element-builder) AND the Api-class host (bridge.ts +
  apis/*). The Api layer can't move without the protocol layer
  moving first, but the two had grown into one directory.
- Bridge-internal consumers (highway uploaders, OIDB envelope
  helper, element-builder, msg-push parsers) only ever needed
  `bridge.identity` + `bridge.sendRawPacket` + the upload-metadata
  cache. Splitting them out lets that minimal surface live in the
  bridge package as `BridgeContext` while the api-layer's extended
  context (with `apis: ApiHub`) stays in @snowluma/core.

What stays in @snowluma/core (apis layer):
  - bridge.ts          ── the god-class that composes the protocol
                          building blocks + mounts apis
  - bridge-interface.ts ── public façade for OneBot consumers
  - manager.ts          ── per-uin BridgeManager hub
  - apis/*              ── the 13 typed Api classes
  - bridge-context.ts (NEW) ── extends @snowluma/bridge's slim
                              BridgeContext with `apis: ApiHub` so
                              the 13 Api classes keep their typed
                              `this.ctx.apis.X.method()` access.

Layout
------
Moved via `git mv` (history preserved):
  events / event-bus / identity-service / packet-pipeline /
  element-builder / bridge-oidb / qq-info / msg-push/* /
  highway/* / web/*           → @snowluma/bridge/<sub>
  utils/event-format.ts        → @snowluma/bridge/format.ts

  (the last one renamed because the destination directory only has
  bridge-related files; `format.ts` reads cleaner than `event-format`.
  Listed as a rename in git's `RM` output — content unchanged.)

Layering fixes (functionality preserved, just type signatures)
--------------------------------------------------------------
- `element-builder.SendContext.bridge` → typed as `BridgeContext`
  instead of `Bridge`. Reads only `bridge.identity` and the
  upload-cache (both on BridgeContext); the concrete `Bridge`
  instance still passes via free upcast.
- `bridge-oidb.runOidb` signature widened from `Bridge` to
  `BridgeContext` — same reason.
- `highway/{highway-client,pipeline,image-upload,ptt-upload,
  video-upload}.ts` — same.
- `format.ts::formatReply` parameter typed as a new local
  `ReplyEventLookup` structural type (`{ findEvent(id): JsonObject |
  null }`) instead of `MessageStore` from @snowluma/onebot. The
  OneBot `MessageStore` is a structural superset; consumers pass
  it through unchanged.
- JSON value types moved to a new `@snowluma/common/json` subpath
  (consumed by format.ts) — `onebot/types.ts` re-exports them so
  external `import { JsonValue } from '<…>/onebot/types'` paths
  keep working.
- `UploadedFileMeta` interface moved from `core/src/bridge/bridge.ts`
  into `@snowluma/bridge/bridge-context.ts` — element-builder + the
  forward-builder both read the upload cache through BridgeContext,
  so the type has to live in @snowluma/bridge. `bridge.ts` keeps
  its re-export for back-compat.

Changes
-------
- New package `packages/bridge/` (package.json with per-file subpath
  exports mirroring legacy `core/src/bridge/<x>` layout 1:1,
  tsconfig.json, typecheck script).
- 35 `.ts` files moved via `git mv` (3 files counted by git as
  RM — rename + modify because Bridge → BridgeContext type swap).
- 150+ import sites rewritten across `packages/core/src` and
  `packages/core/tests`: `'../bridge/<x>'`, `'../../bridge/<x>'`,
  `'../src/bridge/<x>'`, `'@/bridge/web/<x>'`, and vitest
  `vi.mock(...)` literals all collapse to `@snowluma/bridge/<x>`.
- `@snowluma/core` depends on `@snowluma/bridge` (workspace:*).
- `@snowluma/bridge` depends on `@snowluma/common`,
  `@snowluma/proto-defs`, `@snowluma/proton`.
- `packages/core/src/utils/` directory removed (empty).

Verification
------------
- Full workspace `pnpm -r typecheck`: all 10 projects clean.
- core test suite: 552 passed / 552 total (pre-existing
  websocket-darwin-arm64.node addon failure unchanged — same
  baseline as the previous refactor commits).
- Vite build (with stubbed native binary): clean — 143 modules,
  2.84 MB bundle / 224 KB gzip, identical envelope to the
  pre-split build.

Phase 3 (next): OneBot + WebUI move into @snowluma/onebot. The
runnable `index.ts` stays in @snowluma/core as the application
entry, importing `OneBotManager` from `@snowluma/onebot`.
2026-05-21 08:41:34 +08:00
DrSmoothl 46b302f738 refactor(common): extract leaf utilities into @snowluma/common package
Phase 1 of the 4-package split called out in RoadMap #3. Moves the
"infrastructure" leaves — files with zero business dependencies that
@snowluma/bridge, @snowluma/core, and @snowluma/onebot all consume —
into a dedicated workspace package. Mirrors what #4 (proto-defs)
did for wire-protobuf definitions.

Why
---
- Cleaner layering: these were never bridge- or onebot-specific.
  Logger / hex codec / runtime config sit at the bottom of every
  module's import graph; giving them their own package makes that
  graph readable and prevents future leaks the other direction.
- Sets up #3's bridge + onebot extractions: those need a clean leaf
  to depend on. Without this, every cross-package import would have
  to re-export through core, which defeats the split.
- Mirrors @snowluma/proto-defs layout — per-file subpath exports
  (`@snowluma/common/logger`, `@snowluma/common/hex`, …) keep import
  sites unambiguous and let bundlers tree-shake aggressively.

Layout
------
Moved (via `git mv` — history preserved):
  packages/core/src/utils/logger.ts             → @snowluma/common/logger
  packages/core/src/utils/hex.ts                → @snowluma/common/hex
  packages/core/src/utils/log-file-transport.ts → @snowluma/common/log-file-transport
  packages/core/src/utils/log-summary.ts        → @snowluma/common/log-summary
  packages/core/src/protocol/packet-sender.ts   → @snowluma/common/packet-sender
  packages/core/src/protocol/types.ts           → @snowluma/common/protocol-types
  packages/core/src/common/runtime.ts           → @snowluma/common/runtime

Not moved (deferred to Phase 2): `packages/core/src/utils/event-format.ts`
— it has reverse imports on `bridge/events`, `bridge/identity-service`,
`onebot/message-store`, `onebot/types`. It moves into @snowluma/bridge
in Phase 2, with the MessageStore parameter decoupled via a structural
type so bridge doesn't end up depending on onebot.

Changes
-------
- New package `packages/common/` (package.json, tsconfig.json — no
  src/index.ts barrel, callers use the subpath exports directly to
  avoid pulling in `node:fs` when only the hex codec is needed).
- 7 `.ts` files moved via `git mv`.
- 50+ import sites rewritten via sed across `packages/core/src` and
  `packages/core/tests`. Old shapes (`../utils/logger`,
  `../../protocol/types`, `./common/runtime`, `../src/utils/hex`)
  all collapse to `@snowluma/common/<sub>`.
- `@snowluma/core` depends on `@snowluma/common` (workspace:*).
- `packages/core/src/{protocol,common}/` directories removed (empty).

Verification
------------
- core typecheck: clean
- common typecheck: clean
- Full workspace `pnpm -r typecheck`: all 9 projects clean
- core test suite: 552 passed / 552 total (pre-existing
  websocket-darwin-arm64.node addon failure unchanged — same baseline
  as the previous refactor commits)
- Vite build with stubbed native binary: clean (143 modules, 2.84 MB
  bundle, 224 KB gzip — same size envelope as before)

Note: `utils/event-format.ts` is the only file remaining under the
old `utils/` namespace. It moves into @snowluma/bridge alongside the
events / identity-service / packet-pipeline trio in Phase 2.
2026-05-21 08:27:05 +08:00
DrSmoothl 6c7e56d5a1 refactor(proto-defs): extract wire-protobuf definitions into standalone package
Move `packages/core/src/bridge/proto/proton/*.ts` (13 files, ~3.3k
LOC) into a new `@snowluma/proto-defs` workspace package. The proton
spike landed in the previous commit means bare-specifier imports
(`@snowluma/proto-defs/oidb`, `…/message`, …) now resolve correctly
through proton's vite plugin, so call-site replacement still fires.

Why
---
- Lets downstream consumers share the same wire
  definitions without copy-pasting them — multiple workspace packages
  can now depend on `@snowluma/proto-defs` directly.
- Trims `@snowluma/core`'s surface: the bridge no longer owns the
  protocol schema, only its consumers.
- Sets up future #5 (`message-parsing perf`) and #6 (`Api-on-ctx
  refactor`) — both want a thinner core.

Layout
------
Per-file subpath exports (mirrors the legacy `proto/proton/<sub>`
shape 1:1). The barrel `index.ts` intentionally skips `highway` and
`oidb-actions/media` because the two files share six NTV2-prefixed
type names — `export *` would silently drop one side. Subpath imports
are unambiguous, which is also why every call site in core uses them.

Changes
-------
- New package `packages/proto-defs/` (package.json, tsconfig.json,
  src/index.ts).
- 13 `.ts` files moved via `git mv` to preserve history.
- 44 import sites across 26 source files + 15 tests rewritten via sed
  from `./[…/]proto/proton/<sub>` → `@snowluma/proto-defs/<sub>`.
- `@snowluma/core` depends on `@snowluma/proto-defs` (workspace:*).

Verification
------------
- proto-defs typecheck: clean
- core typecheck: clean
- core test suite: 587 passed (same baseline as before the refactor;
  one failure is the pre-existing websocket native addon, unrelated)
- proton test suite: 99 passed (8 files including the new
  cross-package.test.ts from the spike)
- Full workspace `pnpm -r typecheck`: all 8 projects clean

Note: proton's `dist/index.js` MUST be rebuilt for the vite plugin to
pick up the bare-specifier resolution. The previous commit's source
change is only effective after `pnpm -F @snowluma/proton build`.
2026-05-20 21:31:30 +08:00
DrSmoothl 2de1ff4f0d chore(release): v1.9.0 2026-05-20 14:21:03 +08:00
DrSmoothl 3d739c255a feat(proton): proof-of-concept migration — longmsg parity test
Migrates a self-contained subset of bridge/proto/longmsg.ts to the new
@snowluma/proton compile-time DSL form and verifies wire-format parity
against the legacy runtime ProtoSchema encoder. End-to-end proof that
the toolchain works in core's vitest pipeline.

What's covered:
  - LongMsgUid / LongMsgSettings / SendLongMsgInfo / SendLongMsgReq /
    SendLongMsgResp / SendLongMsgRespResult / RecvLongMsgInfo /
    RecvLongMsgReq / RecvLongMsgResp / RecvLongMsgRespResult
  - The three schemas that pull in PushMsgBody (LongMsgContent /
    LongMsgAction / LongMsgResult) stay on the legacy API for now, since
    migrating them requires also migrating message.ts and element.ts.

Toolchain changes:
  - @snowluma/proton gets a tsup build step. The ./vite subpath now
    points at the built dist/index.js so it is loadable as plain Node
    ESM from vite.config.ts / vitest.config.ts (the source-only .ts
    layout can't be consumed from outside the Vite transform pipeline).
    The . (runtime) subpath stays at TS source — it's only ever
    imported from user code, which IS Vite-transformed.
  - prepare script ensures dist/ exists after pnpm install.
  - @snowluma/core depends on @snowluma/proton (workspace:*) and adds
    protobufVitePlugin() to its vitest config so test files get
    transformed.

Documented divergence:
  proton follows proto3 semantics: fields equal to their default value
  (0 / false / "" / empty bytes) are NOT emitted on the wire. The legacy
  runtime encoder always emits them. Both forms are round-trippable
  through a conforming proto3 reader. The parity test pins this
  behaviour explicitly.

8/8 parity tests pass.
2026-05-19 08:19:13 +08:00
DrSmoothl 941e60dea5 chore(release): v1.8.5 2026-05-18 15:03:45 +08:00
DrSmoothl b94775cb6f chore(release): v1.8.4 2026-05-18 13:31:17 +08:00
DrSmoothl c6f4d5c5a2 chore(release): v1.8.3 2026-05-18 00:10:43 +08:00
DrSmoothl 90884dfbb1 chore(release): v1.8.2 2026-05-17 19:28:58 +08:00
DrSmoothl 7da52bc591 chore(release): v1.8.1 2026-05-15 23:17:44 +08:00
DrSmoothl 85b59bc3a1 chore(release): v1.8.0 2026-05-15 01:47:06 +08:00
DrSmoothl ada591b1b4 bump 1.7.9 2026-05-13 16:52:19 +08:00
DrSmoothl 61e3867197 chore(release): single-source app version + add pnpm bump
- WebUI sidebar/login display and OneBot get_version_info now read the
  root package.json version via Vite `define`, removing hardcoded
  literals in webui/src/types.ts and core/onebot/actions/info.ts.
- tools/bump-version.mjs (exposed as `pnpm bump <ver>`) syncs the
  version field across the root and all five workspace packages.
- Bump everything to 1.7.8.
2026-05-13 16:51:44 +08:00
手瓜一十雪 252a65b833 Add @snowluma/websocket TS package and integrate
Introduce an in-tree TypeScript WebSocket package (@snowluma/websocket): move JS websocket implementation into packages/websocket/src (client, server, websocket, extensions, native, index) and add package.json + tsconfig. Replace direct 'ws' dependency in core with the workspace package and update runtime manifest/description. Implement a native addon loader for platform-specific binaries, add typings/refinements across client/server/websocket (more strict types, handshake parsing, permessage-deflate plumbing, buffer/raw data handling), and wire WebSocketClient as the package default export while exposing internal types. Update vite config to bundle the new package and copy only platform-target native binaries into dist/native. Remove legacy JS entrypoints and native loader, and adjust imports/usages in core (ws-transport) to accept broader raw data types.
2026-05-03 15:49:42 +08:00
手瓜一十雪 39f1672b29 Migrate project to pnpm monorepo
Restructure the repository into a pnpm workspace under packages/ (core, webui, runtime). Move source files for core and webui into packages/*, add package manifests for @snowluma/core and @snowluma/runtime, and remove the old launcher package.json. Update root package.json to be a monorepo controller (scripts delegate to pnpm filters, set packageManager and Node engine). Configure build outputs to emit into the repo-root dist/ (vite config changes) so the existing release pipeline continues to work. Add .npmrc with mirrors, expand .gitignore for monorepo layout, add tsconfig base and package-level tsconfigs, and add vitest config for the core package. Adjust injector native search paths and update tests import paths to the new package layout. Small CI/workflow comment added to clarify build behavior and README updated with monorepo structure and common commands.
2026-05-03 14:02:29 +08:00