refactor(commands): trim internal helper exports (#106455)

This commit is contained in:
Peter Steinberger
2026-07-13 07:49:09 -07:00
committed by GitHub
parent f167089d61
commit 96522b9fce
15 changed files with 86 additions and 130 deletions
-12
View File
@@ -1339,8 +1339,6 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [
"src/cli/update-cli/update-command-service.ts: shouldUseLegacyProcessRestartAfterUpdate",
"src/commands/audit.ts: testApi",
"src/commands/auth-choice-options.ts: buildAuthChoiceOptions",
"src/commands/auth-choice.model-check.ts: DefaultModelAuthStatus",
"src/commands/auth-choice.model-check.ts: DefaultModelCatalogFacts",
"src/commands/backup-shared.ts: encodeAbsolutePathForBackupArchive",
"src/commands/backup-shared.ts: formatBackupArchiveTimestamp",
"src/commands/backup-shared.ts: resolveBackupPlanFromPaths",
@@ -1364,7 +1362,6 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [
"src/commands/doctor-sandbox.ts: resolveSandboxScript",
"src/commands/doctor-session-snapshots.ts: resolveSessionSnapshotBundledSkillsDir",
"src/commands/doctor-session-snapshots.ts: scanSessionStoreForStaleRuntimeSnapshotPaths",
"src/commands/doctor-session-sqlite-migration-run.ts: SessionSqliteMigrationManifest",
"src/commands/doctor-session-state-providers.ts: applySessionRouteStateRepair",
"src/commands/doctor-session-state-providers.ts: resolveConfiguredDoctorSessionStateRoute",
"src/commands/doctor-session-state-providers.ts: scanSessionRouteStateOwners",
@@ -1372,8 +1369,6 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [
"src/commands/doctor-session-transcripts.ts: repairBrokenSessionTranscriptFile",
"src/commands/doctor-skills.ts: describeGhConfigDirHintFromDiscovery",
"src/commands/doctor-skills.ts: formatUnavailableSkillDoctorLines",
"src/commands/doctor-state-sqlite-compact.ts: DoctorStateSqliteCompactReport",
"src/commands/doctor-ui.ts: UiProtocolFreshnessIssue",
"src/commands/doctor-whatsapp-responsiveness.ts: listLocalTuiProcesses",
"src/commands/doctor-whatsapp-responsiveness.ts: terminateLocalTuiProcesses",
"src/commands/doctor/cron/legacy-delivery.ts: buildDeliveryFromLegacyPayload",
@@ -1396,11 +1391,6 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [
"src/commands/doctor/shared/release-configured-plugin-installs.ts: shouldRunConfiguredPluginInstallReleaseStep",
"src/commands/doctor/shared/stale-auth-order.ts: repairStaleConfiguredAuthOrders",
"src/commands/doctor/shared/stale-oauth-profile-shadows.ts: testing",
"src/commands/migrate/selection.ts: MIGRATION_PLUGIN_NOT_SELECTED_REASON",
"src/commands/migrate/selection.ts: MIGRATION_SKILL_NOT_SELECTED_REASON",
"src/commands/migrate/selection.ts: MIGRATION_SKILL_SELECTION_ACCEPT",
"src/commands/migrate/selection.ts: MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF",
"src/commands/migrate/selection.ts: MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON",
"src/commands/onboard-inference.ts: detectNativeCodexAppServer",
"src/commands/onboard-non-interactive/local.ts: resolveGatewayHealthProbeToken",
"src/commands/onboard-non-interactive/local.ts: resolveInstallDaemonGatewayHealthTiming",
@@ -1413,8 +1403,6 @@ export const KNIP_UNUSED_EXPORT_BASELINE = [
"src/commands/sessions-tail.ts: setSessionsTailFollowIntervalMsForTests",
"src/commands/sessions.ts: testing",
"src/commands/status.command.ts: resolvePairingRecoveryContext",
"src/commands/status.scan.config-shared.ts: resolveStatusScanColdStart",
"src/commands/status.scan.config-shared.ts: shouldSkipStatusScanMissingConfigFastPath",
"src/commitments/extraction.ts: validateCommitmentCandidates",
"src/commitments/runtime.ts: configureCommitmentExtractionRuntime",
"src/commitments/runtime.ts: drainCommitmentExtractionQueue",
+2 -2
View File
@@ -16,7 +16,7 @@ type ModelRouteObservation = {
baseUrl?: unknown;
};
export type DefaultModelAuthStatus = {
type DefaultModelAuthStatus = {
provider: string;
model: string;
} & (
@@ -112,7 +112,7 @@ function catalogRouteObservation(
};
}
export type DefaultModelCatalogFacts = {
type DefaultModelCatalogFacts = {
found: boolean;
observedRoutes?: readonly ModelRouteObservation[];
};
@@ -39,7 +39,7 @@ type SessionSqliteMigrationTargetManifest = SessionSqliteMigrationTargetInput &
validationBeforeArchive: "not_run" | "passed" | "failed";
};
export type SessionSqliteMigrationManifest = {
type SessionSqliteMigrationManifest = {
completedAt?: string;
failedAt?: string;
failureReports?: {
+3 -1
View File
@@ -24,11 +24,13 @@ import { closeOpenClawStateDatabaseForTest } from "../state/openclaw-state-db.js
import {
assertSafeSessionSqliteMigrationMove,
restoreSessionSqliteMigrationRun,
type SessionSqliteMigrationManifest,
type ActiveSessionSqliteMigrationRun,
} from "./doctor-session-sqlite-migration-run.js";
import { resolveTargetSqlitePath } from "./doctor-session-sqlite-readers.js";
import { runDoctorSessionSqlite } from "./doctor-session-sqlite.js";
type SessionSqliteMigrationManifest = ActiveSessionSqliteMigrationRun["manifest"];
type TestStore = {
configPath: string;
env: NodeJS.ProcessEnv;
@@ -11,10 +11,7 @@ import {
} from "../state/openclaw-state-db.js";
import { resolveOpenClawStateSqlitePath } from "../state/openclaw-state-db.paths.js";
import { OPENCLAW_STATE_SCHEMA_SQL } from "../state/openclaw-state-schema.generated.js";
import {
type DoctorStateSqliteCompactReport,
runDoctorStateSqliteCompact,
} from "./doctor-state-sqlite-compact.js";
import { runDoctorStateSqliteCompact } from "./doctor-state-sqlite-compact.js";
const tempDirs = useAutoCleanupTempDirTracker((cleanup) => {
afterEach(() => {
@@ -22,6 +19,7 @@ const tempDirs = useAutoCleanupTempDirTracker((cleanup) => {
cleanup();
});
});
type DoctorStateSqliteCompactReport = Awaited<ReturnType<typeof runDoctorStateSqliteCompact>>;
type CompletedStateSqliteCompactReport = Extract<
DoctorStateSqliteCompactReport,
{ skipped: false }
+1 -1
View File
@@ -12,7 +12,7 @@ import {
} from "./doctor-sqlite-compact.js";
import { withDoctorSqliteMaintenanceLock } from "./doctor-sqlite-maintenance-lock.js";
export type DoctorStateSqliteCompactReport =
type DoctorStateSqliteCompactReport =
| {
mode: "compact";
path: string;
+1 -1
View File
@@ -7,10 +7,10 @@ import {
detectUiProtocolFreshnessIssues,
uiProtocolFreshnessIssueToHealthFinding,
uiProtocolFreshnessIssueToRepairEffects,
type UiProtocolFreshnessIssue,
} from "./doctor-ui.js";
const tempRoots: string[] = [];
type UiProtocolFreshnessIssue = Awaited<ReturnType<typeof detectUiProtocolFreshnessIssues>>[number];
function issue(overrides: Partial<UiProtocolFreshnessIssue> = {}): UiProtocolFreshnessIssue {
return {
+1 -1
View File
@@ -12,7 +12,7 @@ import { runCommandWithTimeout } from "../process/exec.js";
import type { RuntimeEnv } from "../runtime.js";
import type { DoctorPrompter } from "./doctor-prompter.js";
export type UiProtocolFreshnessIssue =
type UiProtocolFreshnessIssue =
| {
readonly kind: "missing-assets";
readonly root: string;
+15 -15
View File
@@ -71,9 +71,9 @@ vi.mock("./backup.js", () => ({
}));
const {
MIGRATION_SKILL_SELECTION_ACCEPT,
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF,
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON,
MIGRATION_SELECTION_ACCEPT,
MIGRATION_SELECTION_TOGGLE_ALL_OFF,
MIGRATION_SELECTION_TOGGLE_ALL_ON,
} = await import("./migrate/selection.js");
const { migrateApplyCommand, migrateDefaultCommand, migratePlanCommand } =
await import("./migrate.js");
@@ -685,11 +685,11 @@ describe("migrateApplyCommand", () => {
expect(selectionPrompt.initialValues).toStrictEqual(["skill:alpha", "skill:beta"]);
expect(selectionPrompt.required).toBe(false);
expect(selectionPrompt.options?.map(({ label, value }) => ({ label, value }))).toStrictEqual([
{ value: MIGRATION_SKILL_SELECTION_ACCEPT, label: "Accept recommended" },
{ value: MIGRATION_SELECTION_ACCEPT, label: "Accept recommended" },
{ value: "skill:alpha", label: "alpha" },
{ value: "skill:beta", label: "beta" },
{ value: MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON, label: "Toggle all on" },
{ value: MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF, label: "Toggle all off" },
{ value: MIGRATION_SELECTION_TOGGLE_ALL_ON, label: "Toggle all on" },
{ value: MIGRATION_SELECTION_TOGGLE_ALL_OFF, label: "Toggle all off" },
]);
expect(mocks.promptYesNo).toHaveBeenCalledWith("Apply this migration now?", false);
const appliedPlan = firstAppliedPlan();
@@ -745,11 +745,11 @@ describe("migrateApplyCommand", () => {
expect(pluginPrompt.initialValues).toStrictEqual(["plugin:google-calendar", "plugin:gmail"]);
expect(pluginPrompt.required).toBe(false);
expect(pluginPrompt.options?.map(({ label, value }) => ({ label, value }))).toStrictEqual([
{ value: MIGRATION_SKILL_SELECTION_ACCEPT, label: "Accept recommended" },
{ value: MIGRATION_SELECTION_ACCEPT, label: "Accept recommended" },
{ value: "plugin:google-calendar", label: "google-calendar" },
{ value: "plugin:gmail", label: "gmail" },
{ value: MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON, label: "Toggle all on" },
{ value: MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF, label: "Toggle all off" },
{ value: MIGRATION_SELECTION_TOGGLE_ALL_ON, label: "Toggle all on" },
{ value: MIGRATION_SELECTION_TOGGLE_ALL_OFF, label: "Toggle all off" },
]);
expect(mocks.promptYesNo).toHaveBeenCalledWith("Apply this migration now?", false);
const appliedPlan = firstAppliedPlan();
@@ -799,7 +799,7 @@ describe("migrateApplyCommand", () => {
});
mocks.provider.plan.mockResolvedValue(planned);
mocks.multiselect
.mockResolvedValueOnce([MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF])
.mockResolvedValueOnce([MIGRATION_SELECTION_TOGGLE_ALL_OFF])
.mockResolvedValueOnce(["plugin:google-calendar", "plugin:gmail"]);
mocks.promptYesNo.mockResolvedValue(true);
mocks.provider.apply.mockImplementation(async (_ctx, selectedPlan: MigrationPlan) => ({
@@ -900,7 +900,7 @@ describe("migrateApplyCommand", () => {
});
const planned = codexPluginPlan();
mocks.provider.plan.mockResolvedValue(planned);
mocks.multiselect.mockResolvedValue([MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF]);
mocks.multiselect.mockResolvedValue([MIGRATION_SELECTION_TOGGLE_ALL_OFF]);
const result = await migrateDefaultCommand(runtime, { provider: "codex" });
@@ -1016,7 +1016,7 @@ describe("migrateApplyCommand", () => {
});
const planned = codexSkillPlan();
mocks.provider.plan.mockResolvedValue(planned);
mocks.multiselect.mockResolvedValue([MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF]);
mocks.multiselect.mockResolvedValue([MIGRATION_SELECTION_TOGGLE_ALL_OFF]);
const result = await migrateDefaultCommand(runtime, { provider: "codex" });
@@ -1044,7 +1044,7 @@ describe("migrateApplyCommand", () => {
});
const planned = codexSkillPlan();
mocks.provider.plan.mockResolvedValue(planned);
mocks.multiselect.mockResolvedValue([MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON]);
mocks.multiselect.mockResolvedValue([MIGRATION_SELECTION_TOGGLE_ALL_ON]);
mocks.promptYesNo.mockResolvedValue(true);
mocks.provider.apply.mockImplementation(async (_ctx, selectedPlan: MigrationPlan) => ({
...selectedPlan,
@@ -1063,8 +1063,8 @@ describe("migrateApplyCommand", () => {
mocks.provider.plan.mockResolvedValue(planned);
mocks.multiselect.mockResolvedValue([
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON,
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF,
MIGRATION_SELECTION_TOGGLE_ALL_ON,
MIGRATION_SELECTION_TOGGLE_ALL_OFF,
]);
mocks.promptYesNo.mockResolvedValue(true);
mocks.provider.apply.mockClear();
+34 -44
View File
@@ -12,10 +12,8 @@ import {
getDefaultMigrationPluginSelectionValues,
getSelectableMigrationPluginItems,
getDefaultMigrationSkillSelectionValues,
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF,
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON,
MIGRATION_PLUGIN_NOT_SELECTED_REASON,
MIGRATION_SKILL_NOT_SELECTED_REASON,
MIGRATION_SELECTION_TOGGLE_ALL_OFF,
MIGRATION_SELECTION_TOGGLE_ALL_ON,
reconcileInteractiveMigrationEnterValues,
reconcileInteractiveMigrationShortcutValues,
reconcileInteractiveMigrationSkillToggleValues,
@@ -23,6 +21,8 @@ import {
resolveInteractiveMigrationSkillSelection,
} from "./selection.js";
const MIGRATION_NOT_SELECTED_REASON = "not selected for migration";
function skillItem(params: {
id: string;
name: string;
@@ -197,7 +197,7 @@ describe("applyMigrationSkillSelection", () => {
conflicts: 0,
});
expectItemStatus(selected.items, "skill:alpha", "planned");
expectItemStatus(selected.items, "skill:beta", "skipped", MIGRATION_SKILL_NOT_SELECTED_REASON);
expectItemStatus(selected.items, "skill:beta", "skipped", MIGRATION_NOT_SELECTED_REASON);
expectItemStatus(selected.items, "archive:config.toml", "planned");
});
@@ -227,7 +227,7 @@ describe("applyMigrationSkillSelection", () => {
expect(selected.summary.conflicts).toBe(0);
expectItemStatus(selected.items, "skill:alpha", "planned");
expectItemStatus(selected.items, "skill:beta", "skipped", MIGRATION_SKILL_NOT_SELECTED_REASON);
expectItemStatus(selected.items, "skill:beta", "skipped", MIGRATION_NOT_SELECTED_REASON);
});
it("allows interactive selection to choose no skills", () => {
@@ -270,12 +270,12 @@ describe("applyMigrationSkillSelection", () => {
expect(
resolveInteractiveMigrationSkillSelection(items, [
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON,
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF,
MIGRATION_SELECTION_TOGGLE_ALL_ON,
MIGRATION_SELECTION_TOGGLE_ALL_OFF,
]),
).toEqual({ action: "select", selectedItemIds: new Set() });
expect(
resolveInteractiveMigrationSkillSelection(items, [MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON]),
resolveInteractiveMigrationSkillSelection(items, [MIGRATION_SELECTION_TOGGLE_ALL_ON]),
).toEqual({
action: "select",
selectedItemIds: new Set(["skill:alpha", "skill:beta"]),
@@ -287,28 +287,28 @@ describe("applyMigrationSkillSelection", () => {
expect(
reconcileInteractiveMigrationSkillToggleValues(
[MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON],
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON,
[MIGRATION_SELECTION_TOGGLE_ALL_ON],
MIGRATION_SELECTION_TOGGLE_ALL_ON,
selectable,
),
).toEqual([MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON, "skill:alpha", "skill:beta"]);
).toEqual([MIGRATION_SELECTION_TOGGLE_ALL_ON, "skill:alpha", "skill:beta"]);
expect(
reconcileInteractiveMigrationSkillToggleValues(
[
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON,
MIGRATION_SELECTION_TOGGLE_ALL_ON,
"skill:alpha",
"skill:beta",
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF,
MIGRATION_SELECTION_TOGGLE_ALL_OFF,
],
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF,
MIGRATION_SELECTION_TOGGLE_ALL_OFF,
selectable,
),
).toEqual([MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF]);
).toEqual([MIGRATION_SELECTION_TOGGLE_ALL_OFF]);
expect(
reconcileInteractiveMigrationSkillToggleValues(
[MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF, "skill:alpha"],
[MIGRATION_SELECTION_TOGGLE_ALL_OFF, "skill:alpha"],
"skill:alpha",
selectable,
),
@@ -318,24 +318,24 @@ describe("applyMigrationSkillSelection", () => {
reconcileInteractiveMigrationShortcutValues(
["skill:alpha", "skill:beta"],
[
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON,
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF,
MIGRATION_SELECTION_TOGGLE_ALL_ON,
MIGRATION_SELECTION_TOGGLE_ALL_OFF,
"skill:alpha",
"skill:beta",
],
selectable,
"a",
),
).toEqual([MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF]);
).toEqual([MIGRATION_SELECTION_TOGGLE_ALL_OFF]);
expect(
reconcileInteractiveMigrationShortcutValues(
[MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF],
[MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF, MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON],
[MIGRATION_SELECTION_TOGGLE_ALL_OFF],
[MIGRATION_SELECTION_TOGGLE_ALL_OFF, MIGRATION_SELECTION_TOGGLE_ALL_ON],
selectable,
"i",
),
).toEqual([MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF]);
).toEqual([MIGRATION_SELECTION_TOGGLE_ALL_OFF]);
});
it("reconciles enter as activating the cursor row without toggling it off", () => {
@@ -344,18 +344,18 @@ describe("applyMigrationSkillSelection", () => {
expect(
reconcileInteractiveMigrationEnterValues(
["skill:alpha"],
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON,
MIGRATION_SELECTION_TOGGLE_ALL_ON,
selectable,
),
).toEqual([MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON, "skill:alpha", "skill:beta"]);
).toEqual([MIGRATION_SELECTION_TOGGLE_ALL_ON, "skill:alpha", "skill:beta"]);
expect(
reconcileInteractiveMigrationEnterValues(
["skill:alpha"],
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF,
MIGRATION_SELECTION_TOGGLE_ALL_OFF,
selectable,
),
).toEqual([MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF]);
).toEqual([MIGRATION_SELECTION_TOGGLE_ALL_OFF]);
expect(
reconcileInteractiveMigrationEnterValues(["skill:alpha"], "skill:beta", selectable),
@@ -402,12 +402,7 @@ describe("applyMigrationPluginSelection", () => {
expectSummaryFields(selected.summary, { planned: 2, skipped: 1, conflicts: 0 });
expectItemStatus(selected.items, "plugin:google-calendar", "planned");
expectItemStatus(
selected.items,
"plugin:gmail",
"skipped",
MIGRATION_PLUGIN_NOT_SELECTED_REASON,
);
expectItemStatus(selected.items, "plugin:gmail", "skipped", MIGRATION_NOT_SELECTED_REASON);
const configItem = requireItem(selected.items, "config:codex-plugins");
expect(configItem.status).toBe("planned");
const plugins = requireCodexPluginConfigPlugins(configItem);
@@ -434,19 +429,14 @@ describe("applyMigrationPluginSelection", () => {
selected.items,
"plugin:google-calendar",
"skipped",
MIGRATION_PLUGIN_NOT_SELECTED_REASON,
);
expectItemStatus(
selected.items,
"plugin:gmail",
"skipped",
MIGRATION_PLUGIN_NOT_SELECTED_REASON,
MIGRATION_NOT_SELECTED_REASON,
);
expectItemStatus(selected.items, "plugin:gmail", "skipped", MIGRATION_NOT_SELECTED_REASON);
expectItemStatus(
selected.items,
"config:codex-plugins",
"skipped",
MIGRATION_PLUGIN_NOT_SELECTED_REASON,
MIGRATION_NOT_SELECTED_REASON,
);
});
@@ -506,12 +496,12 @@ describe("applyMigrationPluginSelection", () => {
expect(
resolveInteractiveMigrationPluginSelection(items, [
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON,
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF,
MIGRATION_SELECTION_TOGGLE_ALL_ON,
MIGRATION_SELECTION_TOGGLE_ALL_OFF,
]),
).toEqual({ action: "select", selectedItemIds: new Set() });
expect(
resolveInteractiveMigrationPluginSelection(items, [MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON]),
resolveInteractiveMigrationPluginSelection(items, [MIGRATION_SELECTION_TOGGLE_ALL_ON]),
).toEqual({
action: "select",
selectedItemIds: new Set(["plugin:google-calendar", "plugin:gmail"]),
+5 -9
View File
@@ -8,15 +8,11 @@ import { markMigrationItemSkipped, summarizeMigrationItems } from "../../plugin-
import type { MigrationItem, MigrationPlan } from "../../plugins/types.js";
import { MIGRATION_CONFLICT_REASON_PHRASES } from "./output.js";
// Public selection tokens and skip reasons shared with prompt tests and apply filtering.
export const MIGRATION_SKILL_NOT_SELECTED_REASON = "not selected for migration";
export const MIGRATION_PLUGIN_NOT_SELECTED_REASON = "not selected for migration";
// Selection tokens are shared with the command and prompt implementations.
const MIGRATION_NOT_SELECTED_REASON = "not selected for migration";
export const MIGRATION_SELECTION_ACCEPT = "__openclaw_migrate_accept_recommended__";
export const MIGRATION_SELECTION_TOGGLE_ALL_ON = "__openclaw_migrate_toggle_all_on__";
export const MIGRATION_SELECTION_TOGGLE_ALL_OFF = "__openclaw_migrate_toggle_all_off__";
export const MIGRATION_SKILL_SELECTION_ACCEPT = MIGRATION_SELECTION_ACCEPT;
export const MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON = MIGRATION_SELECTION_TOGGLE_ALL_ON;
export const MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF = MIGRATION_SELECTION_TOGGLE_ALL_OFF;
type InteractiveMigrationSelection = { action: "select"; selectedItemIds: Set<string> };
/** Interactive skill selection result consumed by the apply flow. */
@@ -274,7 +270,7 @@ export function applyMigrationSelectedSkillItemIds(
if (!selectableIds.has(item.id) || selectedItemIds.has(item.id)) {
return item;
}
return markMigrationItemSkipped(item, MIGRATION_SKILL_NOT_SELECTED_REASON);
return markMigrationItemSkipped(item, MIGRATION_NOT_SELECTED_REASON);
});
return {
...plan,
@@ -329,7 +325,7 @@ export function applyMigrationSelectedPluginItemIds(
if (!selectableIds.has(item.id) || selectedItemIds.has(item.id)) {
return item;
}
return markMigrationItemSkipped(item, MIGRATION_PLUGIN_NOT_SELECTED_REASON);
return markMigrationItemSkipped(item, MIGRATION_NOT_SELECTED_REASON);
});
return {
...plan,
@@ -377,7 +373,7 @@ function applyCodexPluginConfigSelection(
Object.entries(codexPlugins.plugins).filter(([configKey]) => selectedConfigKeys.has(configKey)),
);
if (Object.keys(plugins).length === 0) {
return markMigrationItemSkipped(item, MIGRATION_PLUGIN_NOT_SELECTED_REASON);
return markMigrationItemSkipped(item, MIGRATION_NOT_SELECTED_REASON);
}
return {
...item,
@@ -2,9 +2,9 @@
import { PassThrough, Writable } from "node:stream";
import { describe, expect, it } from "vitest";
import {
MIGRATION_SKILL_SELECTION_ACCEPT,
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF,
MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON,
MIGRATION_SELECTION_ACCEPT,
MIGRATION_SELECTION_TOGGLE_ALL_OFF,
MIGRATION_SELECTION_TOGGLE_ALL_ON,
} from "./selection.js";
import { promptMigrationSkillSelectionValues } from "./skill-selection-prompt.js";
@@ -30,11 +30,11 @@ async function runPromptWithKeys(params: {
const result = promptMigrationSkillSelectionValues({
message: "Select Codex skills",
options: [
{ value: MIGRATION_SKILL_SELECTION_ACCEPT, label: "Accept recommended" },
{ value: MIGRATION_SELECTION_ACCEPT, label: "Accept recommended" },
{ value: "skill:alpha", label: "alpha" },
{ value: "skill:beta", label: "beta" },
{ value: MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON, label: "Toggle all on" },
{ value: MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF, label: "Toggle all off" },
{ value: MIGRATION_SELECTION_TOGGLE_ALL_ON, label: "Toggle all on" },
{ value: MIGRATION_SELECTION_TOGGLE_ALL_OFF, label: "Toggle all off" },
],
initialValues: params.initialValues,
required: false,
@@ -93,25 +93,25 @@ describe("promptMigrationSkillSelectionValues", () => {
it("activates Toggle all off before submitting with return", async () => {
await expect(
runPromptWithReturn({
cursorAt: MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF,
cursorAt: MIGRATION_SELECTION_TOGGLE_ALL_OFF,
initialValues: ["skill:alpha", "skill:beta"],
}),
).resolves.toEqual([MIGRATION_SKILL_SELECTION_TOGGLE_ALL_OFF]);
).resolves.toEqual([MIGRATION_SELECTION_TOGGLE_ALL_OFF]);
});
it("activates Toggle all on before submitting with return", async () => {
await expect(
runPromptWithReturn({
cursorAt: MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON,
cursorAt: MIGRATION_SELECTION_TOGGLE_ALL_ON,
initialValues: [],
}),
).resolves.toEqual([MIGRATION_SKILL_SELECTION_TOGGLE_ALL_ON, "skill:alpha", "skill:beta"]);
).resolves.toEqual([MIGRATION_SELECTION_TOGGLE_ALL_ON, "skill:alpha", "skill:beta"]);
});
it("submits the initial recommended set when Enter is pressed on Accept recommended", async () => {
await expect(
runPromptWithReturn({
cursorAt: MIGRATION_SKILL_SELECTION_ACCEPT,
cursorAt: MIGRATION_SELECTION_ACCEPT,
initialValues: ["skill:alpha", "skill:beta"],
}),
).resolves.toEqual(["skill:alpha", "skill:beta"]);
@@ -124,7 +124,7 @@ describe("promptMigrationSkillSelectionValues", () => {
// submitted value list.
await expect(
runPromptWithKeys({
cursorAt: MIGRATION_SKILL_SELECTION_ACCEPT,
cursorAt: MIGRATION_SELECTION_ACCEPT,
initialValues: ["skill:alpha", "skill:beta"],
keys: [" ", "\r"],
}),
+1 -19
View File
@@ -1,11 +1,7 @@
// Status scan config tests cover scan command config loading and cold-start resolution.
import { beforeEach, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import {
loadStatusScanCommandConfig,
resolveStatusScanColdStart,
shouldSkipStatusScanMissingConfigFastPath,
} from "./status.scan.config-shared.js";
import { loadStatusScanCommandConfig } from "./status.scan.config-shared.js";
const mocks = vi.hoisted(() => ({
resolveConfigPath: vi.fn(),
@@ -23,20 +19,6 @@ describe("status.scan.config-shared", () => {
);
});
it("detects the test fast-path env toggle", () => {
expect(shouldSkipStatusScanMissingConfigFastPath({ ...process.env, VITEST: "true" })).toBe(
true,
);
expect(shouldSkipStatusScanMissingConfigFastPath({ ...process.env, NODE_ENV: "test" })).toBe(
true,
);
expect(shouldSkipStatusScanMissingConfigFastPath({})).toBe(false);
});
it("treats missing config as cold-start when fast-path bypass is disabled", () => {
expect(resolveStatusScanColdStart({ env: {}, allowMissingConfigFastPath: false })).toBe(true);
});
it("skips read/resolve on fast-json cold-start outside tests", async () => {
const readConfigSnapshot = vi.fn(async () => ({
config: { channels: { quietchat: {} } },
+2 -4
View File
@@ -7,14 +7,12 @@ import type { OpenClawConfig } from "../config/types.js";
import { resolveGatewayAuthTokenSourceConflict } from "../gateway/auth-token-source-conflict.js";
/** Returns true when tests should avoid the missing-config cold-start fast path. */
export function shouldSkipStatusScanMissingConfigFastPath(
env: NodeJS.ProcessEnv = process.env,
): boolean {
function shouldSkipStatusScanMissingConfigFastPath(env: NodeJS.ProcessEnv = process.env): boolean {
return env.VITEST === "true" || env.VITEST_POOL_ID !== undefined || env.NODE_ENV === "test";
}
/** Returns whether status should treat this run as a no-config cold start. */
export function resolveStatusScanColdStart(params?: {
function resolveStatusScanColdStart(params?: {
env?: NodeJS.ProcessEnv;
allowMissingConfigFastPath?: boolean;
}): boolean {
+6 -4
View File
@@ -3,14 +3,16 @@ import fs from "node:fs/promises";
import { expectDefined } from "@openclaw/normalization-core";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { createWizardPrompter as buildWizardPrompter } from "../../test/helpers/wizard-prompter.js";
import type {
DefaultModelAuthStatus,
DefaultModelCatalogFacts,
} from "../commands/auth-choice.model-check.js";
import type * as AuthChoiceModelCheck from "../commands/auth-choice.model-check.js";
import type { OpenClawConfig } from "../config/config.js";
import type { PluginWebSearchProviderEntry } from "../plugins/types.js";
import type { RuntimeEnv } from "../runtime.js";
type DefaultModelAuthStatus = ReturnType<typeof AuthChoiceModelCheck.resolveDefaultModelAuthStatus>;
type DefaultModelCatalogFacts = ReturnType<
typeof AuthChoiceModelCheck.resolveDefaultModelCatalogFacts
>;
const launchTuiCli = vi.hoisted(() => vi.fn(async () => {}));
const restoreTerminalState = vi.hoisted(() => vi.fn());
const probeGatewayReachable = vi.hoisted(() =>