Skip to content

Commit 1cc3544

Browse files
committed
test: clear session status broad matchers
1 parent 555cfed commit 1cc3544

1 file changed

Lines changed: 92 additions & 160 deletions

File tree

src/agents/openclaw-tools.session-status.test.ts

Lines changed: 92 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,23 @@ function expectSpawnedSessionLookupCalls(spawnedBy: string) {
390390
expect(callGatewayMock).toHaveBeenNthCalledWith(2, expectedCall);
391391
}
392392

393+
function expectRecordFields(record: unknown, expected: Record<string, unknown>) {
394+
expect(record).toBeDefined();
395+
const actual = record as Record<string, unknown>;
396+
for (const [key, value] of Object.entries(expected)) {
397+
expect(actual[key]).toEqual(value);
398+
}
399+
return actual;
400+
}
401+
402+
function mockCallArg(mock: ReturnType<typeof vi.fn>, callIndex = 0, argIndex = 0) {
403+
const call = mock.mock.calls[callIndex];
404+
if (!call) {
405+
throw new Error(`Expected mock call ${callIndex}`);
406+
}
407+
return call[argIndex];
408+
}
409+
393410
function getSessionStatusTool(
394411
agentSessionKey = "main",
395412
options?: { sandboxed?: boolean; activeModelProvider?: string; activeModelId?: string },
@@ -440,11 +457,7 @@ describe("session_status tool", () => {
440457

441458
await tool.execute("call-transcript-usage", {});
442459

443-
expect(buildStatusMessageMock).toHaveBeenCalledWith(
444-
expect.objectContaining({
445-
includeTranscriptUsage: true,
446-
}),
447-
);
460+
expectRecordFields(mockCallArg(buildStatusMessageMock), { includeTranscriptUsage: true });
448461
});
449462

450463
it("passes spawned workspace to session_status auth labels", async () => {
@@ -462,11 +475,9 @@ describe("session_status tool", () => {
462475

463476
await tool.execute("call-spawned-workspace-status", {});
464477

465-
expect(buildStatusMessageMock).toHaveBeenCalledWith(
466-
expect.objectContaining({
467-
workspaceDir: "/tmp/openclaw-spawned-workspace",
468-
}),
469-
);
478+
expectRecordFields(mockCallArg(buildStatusMessageMock), {
479+
workspaceDir: "/tmp/openclaw-spawned-workspace",
480+
});
470481
});
471482

472483
it("errors for unknown session keys", async () => {
@@ -698,23 +709,14 @@ describe("session_status tool", () => {
698709
expect(details.ok).toBe(true);
699710
expect(details.sessionKey).toBe("agent:main:current");
700711

701-
expect(buildStatusMessageMock).toHaveBeenCalledWith(
702-
expect.objectContaining({
703-
sessionEntry: expect.objectContaining({
704-
providerOverride: "anthropic",
705-
modelOverride: "claude-sonnet-4-6",
706-
}),
707-
}),
708-
);
709-
expect(buildStatusMessageMock).not.toHaveBeenCalledWith(
710-
expect.objectContaining({
711-
agent: expect.objectContaining({
712-
model: expect.objectContaining({
713-
primary: "openai-codex/gpt-5.2",
714-
}),
715-
}),
716-
}),
717-
);
712+
const statusArg = mockCallArg(buildStatusMessageMock) as Record<string, unknown>;
713+
expectRecordFields(statusArg.sessionEntry, {
714+
providerOverride: "anthropic",
715+
modelOverride: "claude-sonnet-4-6",
716+
});
717+
const agent = statusArg.agent as Record<string, unknown>;
718+
const model = agent.model as Record<string, unknown>;
719+
expect(model.primary).not.toBe("openai-codex/gpt-5.2");
718720
});
719721

720722
it("resolves sessionKey=current for a channel-plugin requester via implicit fallback", async () => {
@@ -745,12 +747,12 @@ describe("session_status tool", () => {
745747
expect(details.sessionKey).toBe("agent:main:telegram:group:-5096326138");
746748
expect(details.statusText).toContain("OpenClaw");
747749
expect(details.statusText).toContain("🧠 Model:");
748-
expect(callGatewayMock).not.toHaveBeenCalledWith(
749-
expect.objectContaining({
750-
method: "sessions.resolve",
751-
params: expect.objectContaining({ key: "current" }),
750+
expect(
751+
callGatewayMock.mock.calls.some(([arg]) => {
752+
const request = arg as { method?: string; params?: { key?: string } };
753+
return request.method === "sessions.resolve" && request.params?.key === "current";
752754
}),
753-
);
755+
).toBe(false);
754756
});
755757

756758
it("resolves the default session_status lookup for a channel-plugin requester via implicit fallback", async () => {
@@ -781,15 +783,9 @@ describe("session_status tool", () => {
781783

782784
await tool.execute("call-current-active-model", { sessionKey: "current" });
783785

784-
expect(buildStatusMessageMock).toHaveBeenCalledWith(
785-
expect.objectContaining({
786-
agent: expect.objectContaining({
787-
model: expect.objectContaining({
788-
primary: "openai-codex/gpt-5.2",
789-
}),
790-
}),
791-
}),
792-
);
786+
const statusArg = mockCallArg(buildStatusMessageMock) as Record<string, unknown>;
787+
const agent = statusArg.agent as Record<string, unknown>;
788+
expectRecordFields(agent.model, { primary: "openai-codex/gpt-5.2" });
793789
});
794790

795791
it("renders the active run model for omitted sessionKey lookups", async () => {
@@ -807,15 +803,9 @@ describe("session_status tool", () => {
807803

808804
await tool.execute("call-implicit-current-active-model", {});
809805

810-
expect(buildStatusMessageMock).toHaveBeenCalledWith(
811-
expect.objectContaining({
812-
agent: expect.objectContaining({
813-
model: expect.objectContaining({
814-
primary: "openai-codex/gpt-5.2",
815-
}),
816-
}),
817-
}),
818-
);
806+
const statusArg = mockCallArg(buildStatusMessageMock) as Record<string, unknown>;
807+
const agent = statusArg.agent as Record<string, unknown>;
808+
expectRecordFields(agent.model, { primary: "openai-codex/gpt-5.2" });
819809
});
820810

821811
it("renders the active run model for current lookups with persisted overrides", async () => {
@@ -835,19 +825,12 @@ describe("session_status tool", () => {
835825

836826
await tool.execute("call-current-active-model-with-override", { sessionKey: "current" });
837827

838-
expect(buildStatusMessageMock).toHaveBeenCalledWith(
839-
expect.objectContaining({
840-
sessionEntry: expect.not.objectContaining({
841-
providerOverride: expect.any(String),
842-
modelOverride: expect.any(String),
843-
}),
844-
agent: expect.objectContaining({
845-
model: expect.objectContaining({
846-
primary: "openai-codex/gpt-5.2",
847-
}),
848-
}),
849-
}),
850-
);
828+
const statusArg = mockCallArg(buildStatusMessageMock) as Record<string, unknown>;
829+
const sessionEntry = statusArg.sessionEntry as Record<string, unknown>;
830+
expect(sessionEntry.providerOverride).toBeUndefined();
831+
expect(sessionEntry.modelOverride).toBeUndefined();
832+
const agent = statusArg.agent as Record<string, unknown>;
833+
expectRecordFields(agent.model, { primary: "openai-codex/gpt-5.2" });
851834
});
852835

853836
it("does not reuse the active run model after a semantic current reset", async () => {
@@ -870,15 +853,9 @@ describe("session_status tool", () => {
870853
model: "default",
871854
});
872855

873-
expect(buildStatusMessageMock).toHaveBeenCalledWith(
874-
expect.objectContaining({
875-
agent: expect.objectContaining({
876-
model: expect.objectContaining({
877-
primary: "openai/gpt-5.4",
878-
}),
879-
}),
880-
}),
881-
);
856+
const statusArg = mockCallArg(buildStatusMessageMock) as Record<string, unknown>;
857+
const agent = statusArg.agent as Record<string, unknown>;
858+
expectRecordFields(agent.model, { primary: "openai/gpt-5.4" });
882859
});
883860

884861
it("materializes a valid persisted session entry when implicit current fallback mutates model state", async () => {
@@ -908,13 +885,11 @@ describe("session_status tool", () => {
908885
Record<string, SessionEntry>,
909886
];
910887
const saved = savedStore["agent:main:scope:scopy:direct:scopy"];
911-
expect(saved).toEqual(
912-
expect.objectContaining({
913-
providerOverride: "anthropic",
914-
modelOverride: "claude-sonnet-4-6",
915-
liveModelSwitchPending: true,
916-
}),
917-
);
888+
expectRecordFields(saved, {
889+
providerOverride: "anthropic",
890+
modelOverride: "claude-sonnet-4-6",
891+
liveModelSwitchPending: true,
892+
});
918893
expect(saved.sessionId).toBeTypeOf("string");
919894
expect(saved.sessionId.trim().length).toBeGreaterThan(0);
920895
});
@@ -936,13 +911,11 @@ describe("session_status tool", () => {
936911
Record<string, SessionEntry>,
937912
];
938913
const saved = savedStore["agent:main:scope:scopy:direct:scopy"];
939-
expect(saved).toEqual(
940-
expect.objectContaining({
941-
providerOverride: "anthropic",
942-
modelOverride: "claude-sonnet-4-6",
943-
liveModelSwitchPending: true,
944-
}),
945-
);
914+
expectRecordFields(saved, {
915+
providerOverride: "anthropic",
916+
modelOverride: "claude-sonnet-4-6",
917+
liveModelSwitchPending: true,
918+
});
946919
expect(saved.sessionId).toBeTypeOf("string");
947920
expect(saved.sessionId.trim().length).toBeGreaterThan(0);
948921
});
@@ -1202,15 +1175,12 @@ describe("session_status tool", () => {
12021175
const details = result.details as { ok?: boolean; sessionKey?: string };
12031176
expect(details.ok).toBe(true);
12041177
expect(details.sessionKey).toBe("agent:main:subagent:child");
1205-
expect(updateSessionStoreMock).toHaveBeenCalledWith(
1206-
"/tmp/main/sessions.json",
1207-
expect.objectContaining({
1208-
"agent:main:subagent:child": expect.objectContaining({
1209-
liveModelSwitchPending: true,
1210-
modelOverride: "claude-sonnet-4-6",
1211-
}),
1212-
}),
1213-
);
1178+
expect(mockCallArg(updateSessionStoreMock)).toBe("/tmp/main/sessions.json");
1179+
const savedStore = mockCallArg(updateSessionStoreMock, 0, 1) as Record<string, unknown>;
1180+
expectRecordFields(savedStore["agent:main:subagent:child"], {
1181+
liveModelSwitchPending: true,
1182+
modelOverride: "claude-sonnet-4-6",
1183+
});
12141184
});
12151185

12161186
it("uses the runtime session model as the selected card model when no override is set", async () => {
@@ -1227,15 +1197,9 @@ describe("session_status tool", () => {
12271197

12281198
await tool.execute("call-runtime-model", {});
12291199

1230-
expect(buildStatusMessageMock).toHaveBeenCalledWith(
1231-
expect.objectContaining({
1232-
agent: expect.objectContaining({
1233-
model: expect.objectContaining({
1234-
primary: "anthropic/claude-opus-4-6",
1235-
}),
1236-
}),
1237-
}),
1238-
);
1200+
const statusArg = mockCallArg(buildStatusMessageMock) as Record<string, unknown>;
1201+
const agent = statusArg.agent as Record<string, unknown>;
1202+
expectRecordFields(agent.model, { primary: "anthropic/claude-opus-4-6" });
12391203
});
12401204

12411205
it("infers configured custom providers for runtime-only models in session_status", async () => {
@@ -1274,16 +1238,10 @@ describe("session_status tool", () => {
12741238

12751239
await tool.execute("call-runtime-custom-provider", {});
12761240

1277-
expect(buildStatusMessageMock).toHaveBeenCalledWith(
1278-
expect.objectContaining({
1279-
agent: expect.objectContaining({
1280-
model: expect.objectContaining({
1281-
primary: "qwen-dashscope/qwen-max",
1282-
}),
1283-
}),
1284-
modelAuth: "api-key (models.json)",
1285-
}),
1286-
);
1241+
const statusArg = mockCallArg(buildStatusMessageMock) as Record<string, unknown>;
1242+
const agent = statusArg.agent as Record<string, unknown>;
1243+
expectRecordFields(agent.model, { primary: "qwen-dashscope/qwen-max" });
1244+
expect(statusArg.modelAuth).toBe("api-key (models.json)");
12871245
});
12881246

12891247
it("preserves an unknown runtime provider in the selected status card model", async () => {
@@ -1299,20 +1257,14 @@ describe("session_status tool", () => {
12991257

13001258
await tool.execute("call-legacy-runtime-model", {});
13011259

1302-
expect(buildStatusMessageMock).toHaveBeenCalledWith(
1303-
expect.objectContaining({
1304-
agent: expect.objectContaining({
1305-
model: expect.objectContaining({
1306-
primary: "legacy-runtime-model",
1307-
}),
1308-
}),
1309-
sessionEntry: expect.objectContaining({
1310-
model: "legacy-runtime-model",
1311-
providerOverride: "",
1312-
}),
1313-
modelAuth: undefined,
1314-
}),
1315-
);
1260+
const statusArg = mockCallArg(buildStatusMessageMock) as Record<string, unknown>;
1261+
const agent = statusArg.agent as Record<string, unknown>;
1262+
expectRecordFields(agent.model, { primary: "legacy-runtime-model" });
1263+
expectRecordFields(statusArg.sessionEntry, {
1264+
model: "legacy-runtime-model",
1265+
providerOverride: "",
1266+
});
1267+
expect(statusArg.modelAuth).toBeUndefined();
13161268
});
13171269

13181270
it("passes per-agent thinkingDefault through to the status card", async () => {
@@ -1348,14 +1300,9 @@ describe("session_status tool", () => {
13481300

13491301
await tool.execute("call-agent-thinking", {});
13501302

1351-
expect(buildStatusMessageMock).toHaveBeenCalledWith(
1352-
expect.objectContaining({
1353-
agentId: "kira",
1354-
agent: expect.objectContaining({
1355-
thinkingDefault: "xhigh",
1356-
}),
1357-
}),
1358-
);
1303+
const statusArg = mockCallArg(buildStatusMessageMock) as Record<string, unknown>;
1304+
expect(statusArg.agentId).toBe("kira");
1305+
expectRecordFields(statusArg.agent, { thinkingDefault: "xhigh" });
13591306
} finally {
13601307
mockConfig = savedConfig;
13611308
}
@@ -1393,14 +1340,9 @@ describe("session_status tool", () => {
13931340

13941341
await tool.execute("call-agent-thinking-implicit", {});
13951342

1396-
expect(buildStatusMessageMock).toHaveBeenCalledWith(
1397-
expect.objectContaining({
1398-
agentId: "kira",
1399-
agent: expect.objectContaining({
1400-
thinkingDefault: "medium",
1401-
}),
1402-
}),
1403-
);
1343+
const statusArg = mockCallArg(buildStatusMessageMock) as Record<string, unknown>;
1344+
expect(statusArg.agentId).toBe("kira");
1345+
expectRecordFields(statusArg.agent, { thinkingDefault: "medium" });
14041346
} finally {
14051347
mockConfig = savedConfig;
14061348
}
@@ -1446,14 +1388,9 @@ describe("session_status tool", () => {
14461388

14471389
await tool.execute("call-agent-thinking-runtime-hydration", {});
14481390

1449-
expect(buildStatusMessageMock).toHaveBeenCalledWith(
1450-
expect.objectContaining({
1451-
agentId: "kira",
1452-
agent: expect.objectContaining({
1453-
thinkingDefault: "medium",
1454-
}),
1455-
}),
1456-
);
1391+
const statusArg = mockCallArg(buildStatusMessageMock) as Record<string, unknown>;
1392+
expect(statusArg.agentId).toBe("kira");
1393+
expectRecordFields(statusArg.agent, { thinkingDefault: "medium" });
14571394
} finally {
14581395
mockConfig = savedConfig;
14591396
}
@@ -1472,14 +1409,9 @@ describe("session_status tool", () => {
14721409

14731410
await tool.execute("call-origin-provider", {});
14741411

1475-
expect(resolveQueueSettingsMock).toHaveBeenCalledWith(
1476-
expect.objectContaining({
1477-
channel: "quietchat",
1478-
sessionEntry: expect.objectContaining({
1479-
origin: { provider: "quietchat" },
1480-
}),
1481-
}),
1482-
);
1412+
const queueArg = mockCallArg(resolveQueueSettingsMock) as Record<string, unknown>;
1413+
expect(queueArg.channel).toBe("quietchat");
1414+
expectRecordFields(queueArg.sessionEntry, { origin: { provider: "quietchat" } });
14831415
});
14841416

14851417
it("resolves sessionId inputs", async () => {

0 commit comments

Comments
 (0)