Skip to content

Commit 207359a

Browse files
authored
fix(ci): repair current main checks
Summary: - Guard child-session candidate lookup when the session store is absent. - Refresh Talk UI and compaction rotation tests for current main. - Clean up Microsoft Foundry provider lint that blocked the refreshed CI lane. Verification: - node scripts/run-vitest.mjs src/gateway/session-utils.test.ts ui/src/ui/views/chat.test.ts src/agents/agent-command.compaction-rotation.test.ts --reporter=dot - node scripts/run-vitest.mjs extensions/microsoft-foundry/index.test.ts --reporter=dot - node_modules/.bin/oxfmt --check --threads=1 extensions/microsoft-foundry/provider.ts src/gateway/session-utils.ts ui/src/ui/views/chat.test.ts src/agents/agent-command.compaction-rotation.test.ts - node scripts/run-oxlint.mjs extensions/microsoft-foundry/provider.ts src/gateway/session-utils.ts ui/src/ui/views/chat.test.ts src/agents/agent-command.compaction-rotation.test.ts - pnpm lint --threads=8 - autoreview clean - GitHub checks on f96270e: 135 success, 29 skipped, 1 neutral, 0 pending/failing Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
1 parent 3fc485c commit 207359a

3 files changed

Lines changed: 64 additions & 55 deletions

File tree

src/agents/agent-command.compaction-rotation.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vite
55
import { loadSessionStore, saveSessionStore, type SessionEntry } from "../config/sessions.js";
66
import { CURRENT_SESSION_VERSION } from "../config/sessions/version.js";
77
import type { OpenClawConfig } from "../config/types.openclaw.js";
8+
import type { runAgentAttempt } from "./command/attempt-execution.runtime.js";
89
import type { EmbeddedAgentRunResult } from "./embedded-agent.js";
910
import type { loadManifestModelCatalog } from "./model-catalog.js";
1011

1112
type ProviderModelNormalizationParams = { provider: string; context: { modelId: string } };
1213
type LoadManifestModelCatalogParams = Parameters<typeof loadManifestModelCatalog>[0];
13-
type RunAgentAttempt = typeof import("./command/attempt-execution.runtime.js").runAgentAttempt;
14+
type RunAgentAttempt = typeof runAgentAttempt;
1415

1516
const state = vi.hoisted(() => ({
1617
cfg: undefined as OpenClawConfig | undefined,
@@ -137,7 +138,7 @@ vi.mock("./command/attempt-execution.runtime.js", async () => {
137138
);
138139
return {
139140
...actual,
140-
runAgentAttempt: (params: Parameters<RunAgentAttempt>[0]) => state.runAgentAttemptMock(params),
141+
runAgentAttempt: (...args: Parameters<RunAgentAttempt>) => state.runAgentAttemptMock(...args),
141142
};
142143
});
143144

@@ -207,7 +208,7 @@ function makeResult(params: {
207208
durationMs: 1,
208209
stopReason: "end_turn",
209210
executionTrace: {
210-
runner: "embedded",
211+
runner: "embedded" as const,
211212
fallbackUsed: false,
212213
winnerProvider: "openai",
213214
winnerModel: "gpt-5.5",

src/gateway/session-utils.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -488,9 +488,12 @@ function rememberSingleRowChildSessionCandidateCacheEntry(
488488
}
489489

490490
function buildStoreChildSessionCandidateIndex(
491-
store: Record<string, SessionEntry>,
491+
store: Record<string, SessionEntry> | null | undefined,
492492
): Map<string, string[]> {
493493
const childSessionsByKey = new Map<string, string[]>();
494+
if (!store) {
495+
return childSessionsByKey;
496+
}
494497
for (const [key, entry] of Object.entries(store)) {
495498
if (!entry) {
496499
continue;
@@ -508,8 +511,11 @@ function buildStoreChildSessionCandidateIndex(
508511

509512
function getSingleRowChildSessionCandidates(params: {
510513
storePath: string;
511-
store: Record<string, SessionEntry>;
514+
store: Record<string, SessionEntry> | null | undefined;
512515
}): Map<string, string[]> {
516+
if (!params.store) {
517+
return new Map();
518+
}
513519
const storeVersion = getSessionStoreCacheVersion(params.storePath);
514520
const cached = singleRowChildSessionCandidateCache.get(params.storePath);
515521
if (cached && cached.store === params.store && cached.storeVersion === storeVersion) {

ui/src/ui/views/chat.test.ts

Lines changed: 52 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,24 @@ function requireElement(container: Element, selector: string, label: string): El
473473
return element;
474474
}
475475

476+
function getTalkSelectOptionValues(container: Element, name: string): string[] {
477+
return Array.from(
478+
container.querySelectorAll<HTMLButtonElement>(
479+
`[data-talk-select="${name}"] [data-talk-select-option]`,
480+
),
481+
).map((option) => option.dataset.talkSelectOption ?? "");
482+
}
483+
484+
function clickTalkSelectOption(container: Element, name: string, value: string): void {
485+
const option = container.querySelector<HTMLButtonElement>(
486+
`[data-talk-select="${name}"] [data-talk-select-option="${value}"]`,
487+
);
488+
if (option === null) {
489+
throw new Error(`expected Talk ${name} option ${value}`);
490+
}
491+
option.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
492+
}
493+
476494
function renderChatView(overrides: Partial<Parameters<typeof renderChat>[0]> = {}) {
477495
const container = document.createElement("div");
478496
render(
@@ -845,26 +863,13 @@ describe("chat voice controls", () => {
845863
const model = container.querySelector<HTMLInputElement>(
846864
'.agent-chat__talk-options-primary input[placeholder="Auto"]',
847865
);
848-
const voice = container.querySelector<HTMLElement>('[data-talk-select="voice"]');
849-
const sensitivity = container.querySelector<HTMLElement>('[data-talk-select="sensitivity"]');
850-
const voiceOptions = Array.from(
851-
container.querySelectorAll<HTMLOptionElement>(
852-
'[data-talk-select="voice"] [data-talk-select-option]',
853-
),
854-
).map((option) => option.dataset.talkSelectOption ?? "");
855-
const reasoningOptions = Array.from(
856-
container.querySelectorAll<HTMLOptionElement>(
857-
'[data-talk-select="reasoning"] [data-talk-select-option]',
858-
),
859-
).map((option) => option.dataset.talkSelectOption ?? "");
866+
const sensitivityLabel = requireElement(
867+
container,
868+
'[data-talk-select="sensitivity"] .agent-chat__talk-select-label',
869+
"Talk sensitivity selected label",
870+
);
860871

861-
if (voice === null) {
862-
throw new Error("expected Talk voice select");
863-
}
864-
if (sensitivity === null) {
865-
throw new Error("expected Talk sensitivity select");
866-
}
867-
expect(voiceOptions).toEqual([
872+
expect(getTalkSelectOptionValues(container, "voice")).toEqual([
868873
"",
869874
"alloy",
870875
"ash",
@@ -877,15 +882,21 @@ describe("chat voice controls", () => {
877882
"marin",
878883
"cedar",
879884
]);
880-
expect(
881-
sensitivity.querySelector<HTMLElement>('[aria-selected="true"]')?.dataset.talkSelectOption,
882-
).toBe("__custom");
883-
expect(
884-
Array.from(sensitivity.querySelectorAll<HTMLElement>("[data-talk-select-option]")).map(
885-
(option) => option.dataset.talkSelectOption ?? "",
886-
),
887-
).toEqual(["", "0.65", "0.5", "0.35", "__custom"]);
888-
expect(reasoningOptions).toEqual(["", "minimal", "low", "medium", "high"]);
885+
expect(sensitivityLabel.textContent).toBe("Custom");
886+
expect(getTalkSelectOptionValues(container, "sensitivity")).toEqual([
887+
"",
888+
"0.65",
889+
"0.5",
890+
"0.35",
891+
"__custom",
892+
]);
893+
expect(getTalkSelectOptionValues(container, "reasoning")).toEqual([
894+
"",
895+
"minimal",
896+
"low",
897+
"medium",
898+
"high",
899+
]);
889900
expect(container.textContent).toContain("Sensitivity");
890901
expect(container.textContent).toContain("Advanced");
891902
expect(container.textContent).toContain("Pause before send");
@@ -894,19 +905,10 @@ describe("chat voice controls", () => {
894905
if (model === null) {
895906
throw new Error("expected Talk model input");
896907
}
897-
const chooseOption = (root: HTMLElement, value: string) => {
898-
const option = Array.from(
899-
root.querySelectorAll<HTMLButtonElement>("[data-talk-select-option]"),
900-
).find((button) => button.dataset.talkSelectOption === value);
901-
if (!option) {
902-
throw new Error(`expected Talk option ${value}`);
903-
}
904-
option.click();
905-
};
906908
model.value = "gpt-realtime-mini";
907909
model.dispatchEvent(new Event("input", { bubbles: true }));
908-
chooseOption(sensitivity, "0.35");
909-
chooseOption(sensitivity, "");
910+
clickTalkSelectOption(container, "sensitivity", "0.35");
911+
clickTalkSelectOption(container, "sensitivity", "");
910912

911913
expect(onRealtimeTalkOptionsChange).toHaveBeenCalledWith({ model: "gpt-realtime-mini" });
912914
expect(onRealtimeTalkOptionsChange).toHaveBeenCalledWith({ vadThreshold: "0.35" });
@@ -926,18 +928,18 @@ describe("chat voice controls", () => {
926928
},
927929
onRealtimeTalkOptionsChange,
928930
});
929-
const defaultSensitivity = defaultContainer.querySelector<HTMLElement>(
930-
'[data-talk-select="sensitivity"]',
931+
const defaultSensitivityLabel = requireElement(
932+
defaultContainer,
933+
'[data-talk-select="sensitivity"] .agent-chat__talk-select-label',
934+
"default Talk sensitivity selected label",
931935
);
932-
expect(
933-
defaultSensitivity?.querySelector<HTMLElement>('[aria-selected="true"]')?.dataset
934-
.talkSelectOption,
935-
).toBe("");
936-
expect(
937-
Array.from(
938-
defaultSensitivity?.querySelectorAll<HTMLElement>("[data-talk-select-option]") ?? [],
939-
).map((option) => option.dataset.talkSelectOption ?? ""),
940-
).toEqual(["", "0.65", "0.5", "0.35"]);
936+
expect(defaultSensitivityLabel.textContent).toBe("Default");
937+
expect(getTalkSelectOptionValues(defaultContainer, "sensitivity")).toEqual([
938+
"",
939+
"0.65",
940+
"0.5",
941+
"0.35",
942+
]);
941943
});
942944

943945
it("renders composer and Talk labels from the active locale", async () => {

0 commit comments

Comments
 (0)