


























@@ -149,6 +149,29 @@ type RunWithModelFallbackParams = {
149149run: (provider: string, model: string) => Promise<unknown>;
150150};
151151152+function requireRecord(value: unknown, label: string): Record<string, unknown> {
153+if (typeof value !== "object" || value === null || Array.isArray(value)) {
154+throw new Error(`expected ${label} to be an object`);
155+}
156+return value as Record<string, unknown>;
157+}
158+159+function expectRecordFields(
160+value: unknown,
161+expected: Record<string, unknown>,
162+label: string,
163+): Record<string, unknown> {
164+const record = requireRecord(value, label);
165+for (const [key, expectedValue] of Object.entries(expected)) {
166+expect(record[key], `${label}.${key}`).toEqual(expectedValue);
167+}
168+return record;
169+}
170+171+function expectReplyText(result: unknown, text: string): void {
172+expectRecordFields(result, { text }, "reply result");
173+}
174+152175beforeEach(() => {
153176clearRuntimeConfigSnapshot();
154177resetDiagnosticEventsForTest();
@@ -377,7 +400,7 @@ describe("runReplyAgent auto-compaction token update", () => {
377400typingMode: "instant",
378401});
379402380-expect(result).toMatchObject({ text: "ok" });
403+expectReplyText(result, "ok");
381404expect(scheduleFollowupDrain).toHaveBeenCalledTimes(1);
382405});
383406@@ -392,21 +415,33 @@ describe("runReplyAgent auto-compaction token update", () => {
392415},
393416});
394417395-expect(usageEvent).toMatchObject({
396-type: "model.usage",
397-agentId: "main",
398-usage: {
418+const usagePayload = expectRecordFields(
419+usageEvent,
420+{
421+type: "model.usage",
422+agentId: "main",
423+},
424+"usage diagnostic event",
425+);
426+expectRecordFields(
427+usagePayload.usage,
428+{
399429input: 75_000,
400430output: 5_000,
401431cacheRead: 25_000,
402432promptTokens: 100_000,
403433total: 105_000,
404434},
405-context: {
435+"usage diagnostic usage",
436+);
437+expectRecordFields(
438+usagePayload.context,
439+{
406440limit: 200_000,
407441used: 44_000,
408442},
409-});
443+"usage diagnostic context",
444+);
410445});
411446412447it("falls back to last-call prompt usage for live diagnostic context", async () => {
@@ -425,20 +460,32 @@ describe("runReplyAgent auto-compaction token update", () => {
425460},
426461});
427462428-expect(usageEvent).toMatchObject({
429-type: "model.usage",
430-usage: {
463+const usagePayload = expectRecordFields(
464+usageEvent,
465+{
466+type: "model.usage",
467+},
468+"usage diagnostic event",
469+);
470+expectRecordFields(
471+usagePayload.usage,
472+{
431473input: 75_000,
432474output: 5_000,
433475cacheRead: 25_000,
434476promptTokens: 100_000,
435477total: 105_000,
436478},
437-context: {
479+"usage diagnostic usage",
480+);
481+expectRecordFields(
482+usagePayload.context,
483+{
438484limit: 200_000,
439485used: 81_000,
440486},
441-});
487+"usage diagnostic context",
488+);
442489});
443490});
444491@@ -634,7 +681,7 @@ describe("runReplyAgent block streaming", () => {
634681const result = await resultPromise;
635682636683expect(sawAbort).toBe(true);
637-expect(result).toMatchObject({ text: "Final message" });
684+expectReplyText(result, "Final message");
638685});
639686});
640687@@ -1304,7 +1351,7 @@ describe("runReplyAgent Active Memory inline debug", () => {
13041351typingMode: "instant",
13051352});
130613531307-expect(result).toMatchObject({ text: "Visible reply" });
1354+expectReplyText(result, "Visible reply");
13081355expect(Array.isArray(result)).toBe(false);
13091356});
13101357@@ -1613,7 +1660,7 @@ describe("runReplyAgent Active Memory inline debug", () => {
16131660});
1614166116151662expect(loadSessionStoreSpy).not.toHaveBeenCalledWith(storePath, { skipCache: true });
1616-expect(result).toMatchObject({ text: "Normal reply" });
1663+expectReplyText(result, "Normal reply");
16171664});
16181665});
16191666@@ -1690,7 +1737,7 @@ describe("runReplyAgent claude-cli routing", () => {
1690173716911738expect(runEmbeddedPiAgentMock).not.toHaveBeenCalled();
16921739expect(runCliAgentMock).toHaveBeenCalledTimes(1);
1693-expect(result).toMatchObject({ text: "ok" });
1740+expectReplyText(result, "ok");
16941741});
1695174216961743it("does not leak hook-blocked CLI input in raw trace payloads", async () => {
@@ -1871,10 +1918,12 @@ describe("runReplyAgent claude-cli routing", () => {
18711918});
1872191918731920expect(runEmbeddedPiAgentMock).not.toHaveBeenCalled();
1874-expect(runCliAgentMock).toHaveBeenCalledWith(
1875-expect.objectContaining({ provider: "claude-cli" }),
1921+expectRecordFields(
1922+runCliAgentMock.mock.calls[0]?.[0],
1923+{ provider: "claude-cli" },
1924+"CLI run params",
18761925);
1877-expect(result).toMatchObject({ text: "ok" });
1926+expectReplyText(result, "ok");
18781927});
18791928});
18801929@@ -1952,7 +2001,7 @@ describe("runReplyAgent messaging tool dedupe", () => {
1952200119532002const result = await createRun("slack");
195420031955-expect(result).toMatchObject({ text: "hello world!" });
2004+expectReplyText(result, "hello world!");
19562005});
1957200619582007it("drops duplicate replies when a messaging tool sent the same text via the same provider + target", async () => {
@@ -1978,7 +2027,7 @@ describe("runReplyAgent messaging tool dedupe", () => {
1978202719792028const result = await createRun("slack");
198020291981-expect(result).toMatchObject({ text: "hello world!" });
2030+expectReplyText(result, "hello world!");
19822031});
1983203219842033it("keeps final reply when text matches a cross-target messaging send", async () => {
@@ -1991,7 +2040,7 @@ describe("runReplyAgent messaging tool dedupe", () => {
1991204019922041const result = await createRun("slack");
199320421994-expect(result).toMatchObject({ text: "hello world!" });
2043+expectReplyText(result, "hello world!");
19952044});
1996204519972046it("delivers replies when account ids do not match", async () => {
@@ -2011,7 +2060,7 @@ describe("runReplyAgent messaging tool dedupe", () => {
2011206020122061const result = await createRun("slack");
201320622014-expect(result).toMatchObject({ text: "hello world!" });
2063+expectReplyText(result, "hello world!");
20152064});
20162065});
20172066@@ -2083,9 +2132,10 @@ describe("runReplyAgent reminder commitment guard", () => {
20832132});
2084213320852134const result = await createRun();
2086-expect(result).toMatchObject({
2087-text: "I'll remind you tomorrow morning.\n\nNote: I did not schedule a reminder in this turn, so this will not trigger automatically.",
2088-});
2135+expectReplyText(
2136+result,
2137+"I'll remind you tomorrow morning.\n\nNote: I did not schedule a reminder in this turn, so this will not trigger automatically.",
2138+);
20892139});
2090214020912141it("keeps reminder commitment unchanged when cron.add succeeded", async () => {
@@ -2096,9 +2146,7 @@ describe("runReplyAgent reminder commitment guard", () => {
20962146});
2097214720982148const result = await createRun();
2099-expect(result).toMatchObject({
2100-text: "I'll remind you tomorrow morning.",
2101-});
2149+expectReplyText(result, "I'll remind you tomorrow morning.");
21022150});
2103215121042152it("suppresses guard note when session already has an active cron job", async () => {
@@ -2123,9 +2171,7 @@ describe("runReplyAgent reminder commitment guard", () => {
21232171});
2124217221252173const result = await createRun();
2126-expect(result).toMatchObject({
2127-text: "I'll ping you when it's done.",
2128-});
2174+expectReplyText(result, "I'll ping you when it's done.");
21292175});
2130217621312177it("still appends guard note when cron jobs exist but not for the current session", async () => {
@@ -2150,9 +2196,10 @@ describe("runReplyAgent reminder commitment guard", () => {
21502196});
2151219721522198const result = await createRun();
2153-expect(result).toMatchObject({
2154-text: "I'll remind you tomorrow morning.\n\nNote: I did not schedule a reminder in this turn, so this will not trigger automatically.",
2155-});
2199+expectReplyText(
2200+result,
2201+"I'll remind you tomorrow morning.\n\nNote: I did not schedule a reminder in this turn, so this will not trigger automatically.",
2202+);
21562203});
2157220421582205it("still appends guard note when cron jobs for session exist but are disabled", async () => {
@@ -2177,9 +2224,10 @@ describe("runReplyAgent reminder commitment guard", () => {
21772224});
2178222521792226const result = await createRun();
2180-expect(result).toMatchObject({
2181-text: "I'll check back in an hour.\n\nNote: I did not schedule a reminder in this turn, so this will not trigger automatically.",
2182-});
2227+expectReplyText(
2228+result,
2229+"I'll check back in an hour.\n\nNote: I did not schedule a reminder in this turn, so this will not trigger automatically.",
2230+);
21832231});
2184223221852233it("still appends guard note when sessionKey is missing", async () => {
@@ -2204,9 +2252,10 @@ describe("runReplyAgent reminder commitment guard", () => {
22042252});
2205225322062254const result = await createRun({ omitSessionKey: true });
2207-expect(result).toMatchObject({
2208-text: "I'll ping you later.\n\nNote: I did not schedule a reminder in this turn, so this will not trigger automatically.",
2209-});
2255+expectReplyText(
2256+result,
2257+"I'll ping you later.\n\nNote: I did not schedule a reminder in this turn, so this will not trigger automatically.",
2258+);
22102259});
2211226022122261it("still appends guard note when cron store read fails", async () => {
@@ -2219,9 +2268,10 @@ describe("runReplyAgent reminder commitment guard", () => {
22192268});
2220226922212270const result = await createRun({ sessionKey: "main" });
2222-expect(result).toMatchObject({
2223-text: "I'll remind you after lunch.\n\nNote: I did not schedule a reminder in this turn, so this will not trigger automatically.",
2224-});
2271+expectReplyText(
2272+result,
2273+"I'll remind you after lunch.\n\nNote: I did not schedule a reminder in this turn, so this will not trigger automatically.",
2274+);
22252275});
22262276});
22272277@@ -2705,9 +2755,11 @@ describe("runReplyAgent mid-turn rate-limit fallback", () => {
27052755const result = await createRun();
27062756const payload = Array.isArray(result) ? result[0] : result;
270727572708-expect(payload).toMatchObject({
2709-mediaUrl: "https://example.test/image.png",
2710-});
2758+expectRecordFields(
2759+payload,
2760+{ mediaUrl: "https://example.test/image.png" },
2761+"media-only retry-limit payload",
2762+);
27112763expect(payload?.text).toBeUndefined();
27122764});
27132765});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。