mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 07:20:43 +00:00
fix(gateway): respect explicit voicewake session targets
This commit is contained in:
committed by
Peter Steinberger
parent
ef7ad8229a
commit
4cc2ffce09
@@ -1634,6 +1634,54 @@ describe("gateway agent handler", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("does not auto-route voice wake requests with an explicit session key", async () => {
|
||||
mocks.loadVoiceWakeRoutingConfig.mockResolvedValue({
|
||||
version: 1,
|
||||
defaultTarget: { sessionKey: "agent:main:voice" },
|
||||
routes: [],
|
||||
updatedAtMs: 0,
|
||||
});
|
||||
mocks.resolveVoiceWakeRouteByTrigger.mockReturnValue({ sessionKey: "agent:main:voice" });
|
||||
|
||||
mocks.loadSessionEntry.mockImplementation((sessionKey: string) => ({
|
||||
cfg: {},
|
||||
storePath: "/tmp/sessions.json",
|
||||
entry: {
|
||||
sessionId: "voice-session-id",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
canonicalKey: sessionKey,
|
||||
}));
|
||||
mocks.updateSessionStore.mockResolvedValue(undefined);
|
||||
mocks.agentCommand.mockResolvedValue({
|
||||
payloads: [{ text: "ok" }],
|
||||
meta: { durationMs: 100 },
|
||||
});
|
||||
mocks.loadVoiceWakeRoutingConfig.mockClear();
|
||||
mocks.resolveVoiceWakeRouteByTrigger.mockClear();
|
||||
|
||||
const respond = vi.fn();
|
||||
await agentHandlers.agent({
|
||||
params: {
|
||||
message: "do thing",
|
||||
sessionKey: "agent:main:research",
|
||||
voiceWakeTrigger: "robot wake",
|
||||
idempotencyKey: "test-voice-route-explicit-session",
|
||||
},
|
||||
respond,
|
||||
context: makeContext(),
|
||||
req: { type: "req", id: "voice-5", method: "agent" },
|
||||
client: null,
|
||||
isWebchatConnect: () => false,
|
||||
});
|
||||
|
||||
await vi.waitFor(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const callArgs = mocks.agentCommand.mock.calls.at(-1)?.[0] as { sessionKey?: string };
|
||||
expect(callArgs.sessionKey).toBe("agent:main:research");
|
||||
expect(mocks.loadVoiceWakeRoutingConfig).not.toHaveBeenCalled();
|
||||
expect(mocks.resolveVoiceWakeRouteByTrigger).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("treats explicit sessionId as an opt-out for voice wake auto-routing", async () => {
|
||||
mocks.loadVoiceWakeRoutingConfig.mockResolvedValue({
|
||||
version: 1,
|
||||
@@ -1657,6 +1705,8 @@ describe("gateway agent handler", () => {
|
||||
payloads: [{ text: "ok" }],
|
||||
meta: { durationMs: 100 },
|
||||
});
|
||||
mocks.loadVoiceWakeRoutingConfig.mockClear();
|
||||
mocks.resolveVoiceWakeRouteByTrigger.mockClear();
|
||||
|
||||
const respond = vi.fn();
|
||||
await agentHandlers.agent({
|
||||
@@ -1669,7 +1719,7 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
respond,
|
||||
context: makeContext(),
|
||||
req: { type: "req", id: "voice-5", method: "agent" },
|
||||
req: { type: "req", id: "voice-6", method: "agent" },
|
||||
client: null,
|
||||
isWebchatConnect: () => false,
|
||||
});
|
||||
@@ -1681,6 +1731,7 @@ describe("gateway agent handler", () => {
|
||||
};
|
||||
expect(callArgs.sessionId).toBe("caller-selected-session-id");
|
||||
expect(callArgs.sessionKey).toBe("agent:main:main");
|
||||
expect(mocks.loadVoiceWakeRoutingConfig).not.toHaveBeenCalled();
|
||||
expect(mocks.resolveVoiceWakeRouteByTrigger).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
@@ -113,6 +113,7 @@ import {
|
||||
waitForTerminalGatewayDedupe,
|
||||
} from "./agent-wait-dedupe.js";
|
||||
import { normalizeRpcAttachmentsToChatAttachments } from "./attachment-normalize.js";
|
||||
import type { GatewayRequestHandlerOptions, GatewayRequestHandlers } from "./types.js";
|
||||
|
||||
const RESET_COMMAND_RE = /^\/(new|reset)(?:\s+([\s\S]*))?$/i;
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ describe("createGatewayRequestContext", () => {
|
||||
markChannelLoggedOut: vi.fn(),
|
||||
wizardRunner: vi.fn(async () => undefined),
|
||||
broadcastVoiceWakeChanged: vi.fn(),
|
||||
broadcastVoiceWakeRoutingChanged: vi.fn(),
|
||||
unavailableGatewayMethods: new Set(),
|
||||
});
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ export type GatewayRequestContextParams = {
|
||||
markChannelLoggedOut: GatewayRequestContext["markChannelLoggedOut"];
|
||||
wizardRunner: GatewayRequestContext["wizardRunner"];
|
||||
broadcastVoiceWakeChanged: GatewayRequestContext["broadcastVoiceWakeChanged"];
|
||||
broadcastVoiceWakeRoutingChanged: GatewayRequestContext["broadcastVoiceWakeRoutingChanged"];
|
||||
unavailableGatewayMethods: ReadonlySet<string>;
|
||||
};
|
||||
|
||||
@@ -149,6 +150,7 @@ export function createGatewayRequestContext(
|
||||
markChannelLoggedOut: params.markChannelLoggedOut,
|
||||
wizardRunner: params.wizardRunner,
|
||||
broadcastVoiceWakeChanged: params.broadcastVoiceWakeChanged,
|
||||
broadcastVoiceWakeRoutingChanged: params.broadcastVoiceWakeRoutingChanged,
|
||||
unavailableGatewayMethods: params.unavailableGatewayMethods,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import { isTruthyEnvValue, isVitestRuntimeEnv, logAcceptedEnvOption } from "../i
|
||||
import { ensureOpenClawCliOnPath } from "../infra/path-env.js";
|
||||
import { setGatewaySigusr1RestartPolicy, setPreRestartDeferralCheck } from "../infra/restart.js";
|
||||
import { enqueueSystemEvent } from "../infra/system-events.js";
|
||||
import { scheduleGatewayUpdateCheck } from "../infra/update-startup.js";
|
||||
import type { VoiceWakeRoutingConfig } from "../infra/voicewake-routing.js";
|
||||
import { startDiagnosticHeartbeat, stopDiagnosticHeartbeat } from "../logging/diagnostic.js";
|
||||
import { createSubsystemLogger, runtimeForLogger } from "../logging/subsystem.js";
|
||||
@@ -623,41 +622,9 @@ export async function startGatewayServer(
|
||||
await runClosePrelude();
|
||||
await createCloseHandler()({ reason: "gateway startup failed" });
|
||||
};
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
const nodeRegistry = new NodeRegistry();
|
||||
const nodePresenceTimers = new Map<string, ReturnType<typeof setInterval>>();
|
||||
const nodeSubscriptions = createNodeSubscriptionManager();
|
||||
const sessionEventSubscribers = createSessionEventSubscriberRegistry();
|
||||
const sessionMessageSubscribers = createSessionMessageSubscriberRegistry();
|
||||
const nodeSendEvent = (opts: { nodeId: string; event: string; payloadJSON?: string | null }) => {
|
||||
const payload = safeParseJson(opts.payloadJSON ?? null);
|
||||
nodeRegistry.sendEvent(opts.nodeId, opts.event, payload);
|
||||
};
|
||||
const nodeSendToSession = (sessionKey: string, event: string, payload: unknown) =>
|
||||
nodeSubscriptions.sendToSession(sessionKey, event, payload, nodeSendEvent);
|
||||
const nodeSendToAllSubscribed = (event: string, payload: unknown) =>
|
||||
nodeSubscriptions.sendToAllSubscribed(event, payload, nodeSendEvent);
|
||||
const nodeSubscribe = nodeSubscriptions.subscribe;
|
||||
const nodeUnsubscribe = nodeSubscriptions.unsubscribe;
|
||||
const nodeUnsubscribeAll = nodeSubscriptions.unsubscribeAll;
|
||||
const broadcastVoiceWakeChanged = (triggers: string[]) => {
|
||||
broadcast("voicewake.changed", { triggers }, { dropIfSlow: true });
|
||||
};
|
||||
const broadcastVoiceWakeRoutingChanged = (config: VoiceWakeRoutingConfig) => {
|
||||
broadcast("voicewake.routing.changed", { config }, { dropIfSlow: true });
|
||||
};
|
||||
const hasMobileNodeConnected = () => hasConnectedMobileNode(nodeRegistry);
|
||||
applyGatewayLaneConcurrency(cfgAtStart);
|
||||
|
||||
let cronState = buildGatewayCronService({
|
||||
cfg: cfgAtStart,
|
||||
deps,
|
||||
broadcast,
|
||||
});
|
||||
let { cron, storePath: cronStorePath } = cronState;
|
||||
deps.cron = cron;
|
||||
>>>>>>> 85f70db0b2 (feat(voicewake): refresh trigger routing on main)
|
||||
|
||||
try {
|
||||
const earlyRuntime = await startupTrace.measure("runtime.early", () =>
|
||||
@@ -808,12 +775,8 @@ export async function startGatewayServer(
|
||||
wizardRunner,
|
||||
broadcastVoiceWakeChanged,
|
||||
unavailableGatewayMethods,
|
||||
<<<<<<< HEAD
|
||||
});
|
||||
=======
|
||||
broadcastVoiceWakeRoutingChanged,
|
||||
};
|
||||
>>>>>>> 85f70db0b2 (feat(voicewake): refresh trigger routing on main)
|
||||
});
|
||||
|
||||
setFallbackGatewayContextResolver(() => gatewayRequestContext);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user