



























@@ -44,6 +44,44 @@ const gpt54Model = {
4444maxTokens: 8_192,
4545} as const;
464647+function expectExtraParams(
48+extraParams: Record<string, unknown> | undefined,
49+expected: {
50+parallelToolCalls: boolean;
51+textVerbosity: string;
52+},
53+): void {
54+expect(extraParams?.parallel_tool_calls).toBe(expected.parallelToolCalls);
55+expect(extraParams?.text_verbosity).toBe(expected.textVerbosity);
56+}
57+58+function latestFollowupRouteCall(): {
59+provider?: unknown;
60+runtimeHandle?: Record<string, unknown>;
61+context?: Record<string, unknown>;
62+} {
63+const call = vi.mocked(resolveProviderFollowupFallbackRoute).mock.calls.at(-1)?.[0];
64+if (!call || typeof call !== "object") {
65+throw new Error("expected follow-up route call");
66+}
67+const record = call as {
68+provider?: unknown;
69+runtimeHandle?: unknown;
70+context?: unknown;
71+};
72+return {
73+provider: record.provider,
74+runtimeHandle:
75+record.runtimeHandle && typeof record.runtimeHandle === "object"
76+ ? (record.runtimeHandle as Record<string, unknown>)
77+ : undefined,
78+context:
79+record.context && typeof record.context === "object"
80+ ? (record.context as Record<string, unknown>)
81+ : undefined,
82+};
83+}
84+4785describe("AgentRuntimePlan", () => {
4886afterEach(() => {
4987resetConfigRuntimeState();
@@ -65,9 +103,9 @@ describe("AgentRuntimePlan", () => {
65103});
6610467105expect(prepareProviderExtraParamsMock).not.toHaveBeenCalled();
68-expect(plan.transport.extraParams).toMatchObject({
69-parallel_tool_calls: true,
70-text_verbosity: "low",
106+expectExtraParams(plan.transport.extraParams, {
107+parallelToolCalls: true,
108+textVerbosity: "low",
71109});
72110expect(prepareProviderExtraParamsMock).toHaveBeenCalledTimes(1);
73111void plan.transport.extraParams;
@@ -91,31 +129,28 @@ describe("AgentRuntimePlan", () => {
91129},
92130});
9313194-expect(plan.auth).toMatchObject({
95-providerForAuth: "openai",
96-authProfileProviderForAuth: "openai-codex",
97-harnessAuthProvider: "openai-codex",
98-forwardedAuthProfileId: "openai-codex:work",
99-});
132+expect(plan.auth.providerForAuth).toBe("openai");
133+expect(plan.auth.authProfileProviderForAuth).toBe("openai-codex");
134+expect(plan.auth.harnessAuthProvider).toBe("openai-codex");
135+expect(plan.auth.forwardedAuthProfileId).toBe("openai-codex:work");
100136expect(plan.delivery.isSilentPayload({ text: '{"action":"NO_REPLY"}' })).toBe(true);
101137expect(
102138plan.delivery.isSilentPayload({
103139text: '{"action":"NO_REPLY"}',
104140mediaUrl: "file:///tmp/image.png",
105141}),
106142).toBe(false);
107-expect(plan.transport.extraParams).toMatchObject({
108-parallel_tool_calls: true,
109-text_verbosity: "low",
143+expectExtraParams(plan.transport.extraParams, {
144+parallelToolCalls: true,
145+textVerbosity: "low",
110146});
111-expect(
112-plan.transport.resolveExtraParams({
113-extraParamsOverride: { parallel_tool_calls: false },
114-resolvedTransport: "websocket",
115-}),
116-).toMatchObject({
117-parallel_tool_calls: false,
118-text_verbosity: "low",
147+const resolvedExtraParams = plan.transport.resolveExtraParams({
148+extraParamsOverride: { parallel_tool_calls: false },
149+resolvedTransport: "websocket",
150+});
151+expectExtraParams(resolvedExtraParams, {
152+parallelToolCalls: false,
153+textVerbosity: "low",
119154});
120155expect(
121156plan.prompt.resolveSystemPromptContribution({
@@ -169,11 +204,9 @@ describe("AgentRuntimePlan", () => {
169204workspaceDir: "/tmp/openclaw-runtime-plan",
170205});
171206172-expect(plan.auth).toMatchObject({
173-providerForAuth: "openai",
174-authProfileProviderForAuth: "openai",
175-harnessAuthProvider: "openai-codex",
176-});
207+expect(plan.auth.providerForAuth).toBe("openai");
208+expect(plan.auth.authProfileProviderForAuth).toBe("openai");
209+expect(plan.auth.harnessAuthProvider).toBe("openai-codex");
177210expect(plan.auth.forwardedAuthProfileId).toBeUndefined();
178211});
179212@@ -190,11 +223,9 @@ describe("AgentRuntimePlan", () => {
190223workspaceDir: "/tmp/openclaw-runtime-plan",
191224});
192225193-expect(plan.auth).toMatchObject({
194-providerForAuth: "openai",
195-authProfileProviderForAuth: "openai-codex",
196-forwardedAuthProfileId: "openai-codex:work",
197-});
226+expect(plan.auth.providerForAuth).toBe("openai");
227+expect(plan.auth.authProfileProviderForAuth).toBe("openai-codex");
228+expect(plan.auth.forwardedAuthProfileId).toBe("openai-codex:work");
198229});
199230200231it("resolves follow-up routes with the prepared provider handle", () => {
@@ -228,18 +259,13 @@ describe("AgentRuntimePlan", () => {
228259route: "dispatcher",
229260reason: "prepared-route",
230261});
231-expect(resolveProviderFollowupFallbackRouteMock).toHaveBeenCalledWith(
232-expect.objectContaining({
233-provider: "openai",
234-runtimeHandle: providerRuntimeHandle,
235-context: expect.objectContaining({
236-provider: "openai",
237-modelId: "gpt-5.4",
238-originRoutable: false,
239-dispatcherAvailable: true,
240-}),
241-}),
242-);
262+const followupCall = latestFollowupRouteCall();
263+expect(followupCall.provider).toBe("openai");
264+expect(followupCall.runtimeHandle?.provider).toBe(providerRuntimeHandle.provider);
265+expect(followupCall.context?.provider).toBe("openai");
266+expect(followupCall.context?.modelId).toBe("gpt-5.4");
267+expect(followupCall.context?.originRoutable).toBe(false);
268+expect(followupCall.context?.dispatcherAvailable).toBe(true);
243269});
244270245271it("resolves incomplete supplied provider handles before invoking runtime hooks", () => {
@@ -288,11 +314,8 @@ describe("AgentRuntimePlan", () => {
288314bundledProviderAllowlistCompat: undefined,
289315bundledProviderVitestCompat: undefined,
290316});
291-expect(resolveProviderFollowupFallbackRouteMock).toHaveBeenCalledWith(
292-expect.objectContaining({
293-runtimeHandle: resolvedHandle,
294-}),
295-);
317+const followupCall = latestFollowupRouteCall();
318+expect(followupCall.runtimeHandle).toBe(resolvedHandle);
296319});
297320298321it("resolves incomplete supplied delivery handles before follow-up routing", () => {
@@ -338,11 +361,8 @@ describe("AgentRuntimePlan", () => {
338361bundledProviderAllowlistCompat: undefined,
339362bundledProviderVitestCompat: undefined,
340363});
341-expect(resolveProviderFollowupFallbackRouteMock).toHaveBeenCalledWith(
342-expect.objectContaining({
343-runtimeHandle: resolvedHandle,
344-}),
345-);
364+const followupCall = latestFollowupRouteCall();
365+expect(followupCall.runtimeHandle).toBe(resolvedHandle);
346366});
347367348368it("plans tool metadata against the runtime source snapshot lazily", () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。