feat(monitoring): dispatch monitoring tasks to desktop via AMQP outbox

Replace SSE /desktop/events with priority AMQP dispatch for monitoring
runs, and add phase1/phase2 infrastructure so desktop workers can lease,
resume, report, skip, and cancel monitoring tasks over the existing
dispatch WebSocket.

- Add monitoring collect outbox worker and phase2 desktop task fields
- Add /desktop/monitoring/tasks/{lease,resume,result,skip,cancel} routes
- Introduce execution-devtools and network-observer on desktop runtime
- Refactor runtime-controller, LoginView, and doubao adapter for the new flow
- Add channelName column to tracking views

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-22 00:24:21 +08:00
parent 749b6b99cd
commit 4142c53fa6
57 changed files with 7897 additions and 985 deletions
@@ -5,6 +5,7 @@ import { dirname, join } from "node:path";
import { app, session } from "electron/main";
import type { Session } from "electron/main";
import { observeSessionRequests } from "./network-observer";
import { STANDARD_ACCEPT_LANGUAGES, STANDARD_USER_AGENT } from "./user-agent";
export interface SessionHandle {
@@ -98,8 +99,15 @@ function applyStandardUserAgent(target: Session): Session {
return target;
}
function prepareSession(target: Session): Session {
function prepareSession(
target: Session,
options: { label: string; partition: string },
): Session {
applyStandardUserAgent(target);
observeSessionRequests(target, {
label: options.label,
partition: options.partition,
});
target.clearHostResolverCache().catch((error) => {
console.warn("[desktop-session] clearHostResolverCache failed", error);
});
@@ -121,7 +129,10 @@ export function createSessionHandle(accountId?: string): SessionHandle {
const handle: SessionHandle = {
accountId: resolvedAccountID,
partition,
session: prepareSession(session.fromPartition(partition)),
session: prepareSession(session.fromPartition(partition), {
label: resolvedAccountID,
partition,
}),
};
registry.set(resolvedAccountID, handle);
return handle;
@@ -136,7 +147,10 @@ export function createSessionHandleForPartition(accountId: string, partition: st
const handle: SessionHandle = {
accountId,
partition,
session: prepareSession(session.fromPartition(partition)),
session: prepareSession(session.fromPartition(partition), {
label: accountId,
partition,
}),
};
registry.set(accountId, handle);
rememberPersistedPartition(accountId, partition);
@@ -149,7 +163,10 @@ export function createPendingSessionHandle(seed = "bind"): SessionHandle {
const handle: SessionHandle = {
accountId,
partition,
session: prepareSession(session.fromPartition(partition)),
session: prepareSession(session.fromPartition(partition), {
label: accountId,
partition,
}),
};
registry.set(accountId, handle);
return handle;
@@ -189,7 +206,10 @@ export async function clearSessionHandle(accountId: string): Promise<void> {
return;
}
const target = prepareSession(session.fromPartition(partition));
const target = prepareSession(session.fromPartition(partition), {
label: accountId,
partition,
});
try {
await target.clearStorageData();