






















@@ -0,0 +1,144 @@
1+import { loadManifestModelCatalog } from "../agents/model-catalog.js";
2+import type { CliDeps } from "../cli/deps.types.js";
3+import type { OpenClawConfig } from "../config/types.openclaw.js";
4+import type { CronServiceContract } from "../cron/service-contract.js";
5+import { createSubsystemLogger } from "../logging/subsystem.js";
6+import {
7+getPluginRuntimeGatewayRequestScope,
8+withPluginRuntimeGatewayRequestScope,
9+} from "../plugins/runtime/gateway-request-scope.js";
10+import { NodeRegistry } from "./node-registry.js";
11+import type { ChannelRuntimeSnapshot } from "./server-channel-runtime.types.js";
12+import type { GatewayRequestContext } from "./server-methods/types.js";
13+14+type LocalGatewayRequestContextParams = {
15+deps: CliDeps;
16+getRuntimeConfig: () => OpenClawConfig;
17+};
18+19+type LocalGatewayScopeParams = LocalGatewayRequestContextParams;
20+21+function cronUnavailable(): never {
22+throw new Error("Cron is unavailable in local embedded agent gateway context.");
23+}
24+25+const unavailableCron: CronServiceContract = {
26+start: async () => {
27+cronUnavailable();
28+},
29+stop: () => {},
30+status: async () => cronUnavailable(),
31+list: async () => cronUnavailable(),
32+listPage: async () => cronUnavailable(),
33+add: async () => cronUnavailable(),
34+update: async () => cronUnavailable(),
35+remove: async () => cronUnavailable(),
36+run: async () => cronUnavailable(),
37+enqueueRun: async () => cronUnavailable(),
38+getJob: () => undefined,
39+readJob: async () => undefined,
40+getDefaultAgentId: () => undefined,
41+wake: () => ({ ok: false, reason: "unwakeable-session-key" }),
42+};
43+44+export function createLocalGatewayRequestContext(
45+params: LocalGatewayRequestContextParams,
46+): GatewayRequestContext {
47+const logGateway = createSubsystemLogger("gateway/local");
48+const sessionEvents = new Set<string>();
49+const chatRuns = new Map<string, { sessionKey: string; clientRunId: string }>();
50+return {
51+deps: params.deps,
52+cron: unavailableCron,
53+cronStorePath: "",
54+getRuntimeConfig: params.getRuntimeConfig,
55+loadGatewayModelCatalog: async () =>
56+loadManifestModelCatalog({ config: params.getRuntimeConfig() }),
57+getHealthCache: () => null,
58+refreshHealthSnapshot: async () =>
59+({}) as Awaited<ReturnType<GatewayRequestContext["refreshHealthSnapshot"]>>,
60+logHealth: { error: (message) => logGateway.error(message) },
61+ logGateway,
62+incrementPresenceVersion: () => 0,
63+getHealthVersion: () => 0,
64+broadcast: () => {},
65+broadcastToConnIds: () => {},
66+nodeSendToSession: () => {},
67+nodeSendToAllSubscribed: () => {},
68+nodeSubscribe: () => {},
69+nodeUnsubscribe: () => {},
70+nodeUnsubscribeAll: () => {},
71+hasConnectedTalkNode: () => false,
72+nodeRegistry: new NodeRegistry(),
73+agentRunSeq: new Map(),
74+chatAbortControllers: new Map(),
75+chatAbortedRuns: new Map(),
76+chatRunBuffers: new Map(),
77+chatDeltaSentAt: new Map(),
78+chatDeltaLastBroadcastLen: new Map(),
79+chatDeltaLastBroadcastText: new Map(),
80+agentDeltaSentAt: new Map(),
81+bufferedAgentEvents: new Map(),
82+addChatRun: (sessionId, entry) => {
83+chatRuns.set(sessionId, entry);
84+},
85+removeChatRun: (sessionId, clientRunId, sessionKey) => {
86+const entry = chatRuns.get(sessionId);
87+if (!entry || entry.clientRunId !== clientRunId) {
88+return undefined;
89+}
90+if (sessionKey !== undefined && entry.sessionKey !== sessionKey) {
91+return undefined;
92+}
93+chatRuns.delete(sessionId);
94+return entry;
95+},
96+subscribeSessionEvents: (connId) => {
97+sessionEvents.add(connId);
98+},
99+unsubscribeSessionEvents: (connId) => {
100+sessionEvents.delete(connId);
101+},
102+subscribeSessionMessageEvents: () => {},
103+unsubscribeSessionMessageEvents: () => {},
104+unsubscribeAllSessionEvents: (connId) => {
105+sessionEvents.delete(connId);
106+},
107+getSessionEventSubscriberConnIds: () => sessionEvents,
108+registerToolEventRecipient: () => {},
109+dedupe: new Map(),
110+wizardSessions: new Map(),
111+findRunningWizard: () => null,
112+purgeWizardSession: () => {},
113+getRuntimeSnapshot: () => ({}) as ChannelRuntimeSnapshot,
114+startChannel: async () => {
115+throw new Error("Channel start is unavailable in local embedded agent gateway context.");
116+},
117+stopChannel: async () => {
118+throw new Error("Channel stop is unavailable in local embedded agent gateway context.");
119+},
120+markChannelLoggedOut: () => {},
121+wizardRunner: async () => {
122+throw new Error("Onboarding wizard is unavailable in local embedded agent gateway context.");
123+},
124+broadcastVoiceWakeChanged: () => {},
125+broadcastVoiceWakeRoutingChanged: () => {},
126+unavailableGatewayMethods: new Set(),
127+};
128+}
129+130+export function withLocalGatewayRequestScope<T>(params: LocalGatewayScopeParams, run: () => T): T {
131+const existing = getPluginRuntimeGatewayRequestScope();
132+if (existing?.context) {
133+return run();
134+}
135+const context = createLocalGatewayRequestContext(params);
136+return withPluginRuntimeGatewayRequestScope(
137+{
138+ ...existing,
139+ context,
140+isWebchatConnect: existing?.isWebchatConnect ?? (() => false),
141+},
142+run,
143+);
144+}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。