Commit Graph
14 Commits
Author SHA1 Message Date
DrSmoothl 7c0519f75f lint 2026-10-12 15:43:34 +08:00
DrSmoothl effeb66554 feat(bridge): connect when a pipe is already up after load fails
A failed load used to stay in the error state. If the pipe is already
listening, connect instead, and keep retrying that case on later checks.
2026-10-10 10:44:15 +08:00
DrSmoothl d5f1e35c31 fix(core): close Bridges on exit without a fake offline 2026-08-17 00:08:21 +08:00
DrSmoothl 870e9a5fbc fix(bridge): recover stale outbound sessions
Recover invalidated native send bindings from same-account receive evidence. Track outbound connection loss in status health and refresh the six public native artifacts from native build 94f2b63.

Closes #342
2026-08-09 21:40:09 +08:00
DrSmoothl 4a0d14ce56 fix(bridge): keep account recovery non-interactive
Keep background account discovery passive and distinguish an identified account from a ready session.

Update the process dialog and regression coverage so recovery waits for authoritative readiness before exposing the account as online.
2026-08-03 12:54:48 +08:00
DrSmoothl 8526d0c2c5 fix(bridge): restore active sessions after delayed startup
Allow SnowLuma to discover and restore accounts that were already active before startup.

Avoid reporting sessions ready before they can serve requests, preserve account changes, and keep discovery failures observable.

Add regression coverage for delayed startup, recovery, and process isolation.

Refs #305

Refs #307
2026-08-03 10:49:47 +08:00
DrSmoothl a67614fa09 feat(logging): complete runtime trace diagnostics
Complete byte-level diagnostics for network, upload, runtime lifecycle, authenticated write, and background operation paths.

Preserve streaming behavior, file-storage boundaries, and default log volume while making failures, retries, cancellation, and final outcomes independently diagnosable.

Add focused regression coverage for correlation, partial data, resource context ownership, and terminal-state accuracy.
2026-07-31 11:21:12 +08:00
DrSmoothl f97444c391 fix(bridge): bound process operations 2026-07-29 02:15:13 +08:00
DrSmoothl d05bbe3551 fix(bridge): synchronize reconciled login state
Route recovered login state through the hook client before dependent services start. Add regression coverage to keep packet actions available after reconciliation.

Fixes #286.
2026-07-26 15:53:57 +08:00
DrSmoothl e8cb49ced9 feat(bridge): detect stalled receive paths
Arm receive monitoring only after an existing QQ heartbeat has been observed, preserving compatibility with sessions that do not expose the signal.

Require 90 seconds of receive silence plus a 15-second confirmation window before reporting degradation. Any later inbound frame refreshes or restores health, including non-routable frames that still prove the receive path is alive.

Bind watchdog state to the active account epoch so direct login switches and packet-driven account migration cannot inherit stale deadlines from a previous account.

Forward health transitions to the bridge layer without reconnecting, reinjecting, or otherwise changing session recovery behavior. Add regression coverage for arming, recovery, sleep-resume confirmation, account migration, and invalid-UIN frames.

Refs #233.
2026-07-15 16:46:16 +08:00
DrSmoothl c90a3954e4 fix(bridge): self-heal login detection when the hook misses the edge
Docker SnowLuma could hang forever at "等待登录" after QQ had already
logged in. Root cause: login detection is edge-triggered — it only learns
the state from a loginState frame the native hook PUSHES when it observes
the login transition. `getLoginState()` is a cached value read once at
connect; after that the session waits passively. Desktop attaches the
hook before the user logs in, so it catches the edge. In Docker, QQ
auto-logs-in from a persisted session — fast on startup — so the
transition lands before the recv pipe is connected (frames aren't
replayed) or via a silent restore path the hook doesn't intercept. The
edge is missed and the cached state stays not-logged-in.

Fix: while connected but not logged in, actively re-probe QQ's own
ptlogin/deeplink ports via probeQqLoginInfo (level-triggered, pipe-
independent — the same call the workaround used) and synthesize the login
once it reports a real uin. Immediate probe on connect + a 3s interval;
stopped on login / teardown / dispose, with an in-flight guard so a slow
port scan can't stack concurrent probes. Idempotent with the pushed-frame
path. 7 tests cover detect-via-probe, the later-interval case, the
not-logged-in / non-real-uin / throwing-probe guards, no double-emit, and
no concurrent stacking. probeLogin is injectable for tests.
2026-06-30 23:29:51 +08:00
DrSmoothl fb7675f3cb test(bridge): lock HookSession refresh drift fix
Two tests pinning the one intended behavior change from the status-
machine deepening: refresh while the pipe is down on a connected-but-
never-logged-in session now reports 'connecting' (matching onPipeDown),
not the old spurious 'disconnected'; and a session that HAD logged in
still settles to 'disconnected' + emits disconnected(true), proving the
flip is scoped to the never-logged-in case.

Verified against the pre-refactor baseline: test (1) fails on old code
(produced 'disconnected'), so it locks the flip rather than restating it.
2026-06-24 19:49:21 +08:00
DrSmoothl 1d2a56bcdb refactor(bridge): wire HookSession status through statusFor + shared reconcilers
Phase 2. Migrate the ~6 hand-copied status ternaries to the pure
statusFor() and collapse the pipe up/down orchestration into two shared
private reconcilers:

- reconcilePipeUp  ← onPipeUp + refresh's pipe-up branch
- reconcilePipeDown ← onPipeDown + refresh's pipe-down branch + the
  client 'close' handler (4 call sites, all were near-duplicates)

applyStatus() pushes the statusFor-derived status; loading/error stay
explicit. refreshInternal collapses to a one-line pipe poll. Behavior-
preserving except the intended drift fix (refresh-while-down + never
logged in now reports 'connecting', matching onPipeDown, not the old
spurious 'disconnected').

reconcilePipeDown short-circuits when !connected so a pipe-down tick
can't clobber a diagnostic error or emit a spurious status-changed on a
failed-connect/failed-load session — covered by two new regression
tests (caught in adversarial review). 55/55 green.
2026-06-24 19:42:59 +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