Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ci/test-file-size-budget.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"test/generate-openclaw-config.test.ts": 1941,
"test/install-preflight.test.ts": 3921,
"test/nemoclaw-start.test.ts": 4791,
"test/onboard-messaging.test.ts": 2043,
"test/onboard-messaging.test.ts": 2036,
"test/onboard-selection.test.ts": 4767
}
}
31 changes: 6 additions & 25 deletions src/lib/actions/sandbox/rebuild-flow-credential-preflight.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import { describe, expect, it } from "vitest";
import { makeMessagingPlan } from "../../../../test/helpers/messaging-plan-fixtures";
import { expectNoSandboxDelete } from "../../../../test/helpers/rebuild-delete-assertions";
import {
createRebuildFlowHarness,
Expand Down Expand Up @@ -57,26 +58,11 @@ function diagnostics(harness: Harness): string {
return harness.errorSpy.mock.calls.flat().map(String).join("\n");
}

function makeMessagingPlan() {
return {
schemaVersion: 1,
function makeStagedHermesMessagingPlan() {
return makeMessagingPlan({
sandboxName: "alpha",
agent: "hermes",
workflow: "onboard",
channels: [
{
channelId: "discord",
displayName: "discord",
authMode: "token-paste",
active: true,
selected: true,
configured: true,
disabled: false,
inputs: [],
hooks: [],
},
],
disabledChannels: [],
channels: ["discord"],
credentialBindings: [
{
channelId: "discord",
Expand All @@ -89,12 +75,7 @@ function makeMessagingPlan() {
credentialHash: "discord-bot-token-hash",
},
],
networkPolicy: { presets: [], entries: [] },
agentRender: [],
buildSteps: [],
stateUpdates: [],
healthChecks: [],
};
});
}

describe("rebuildSandbox flow: credential preflight", () => {
Expand Down Expand Up @@ -349,7 +330,7 @@ describe("rebuildSandbox flow: credential preflight", () => {
});

it("copies the staged Hermes messaging plan into the rebuild resume session", async () => {
const plan = makeMessagingPlan();
const plan = makeStagedHermesMessagingPlan();
const harness = createRebuildFlowHarness({
sandboxEntry: {
agent: "hermes",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@

import { describe, expect, it, vi } from "vitest";

import { makeMessagingPlan } from "../../../../../test/helpers/messaging-plan-fixtures";
import { createSession } from "../../../state/onboard-session";
import { handlePoliciesState } from "./policies";
import {
basePolicyHandlerOptions as baseOptions,
createPolicyHandlerDeps as createDeps,
makeMessagingPlan,
} from "./policies-test-fixtures";
} from "./policies-test-fixture";

// Handler-level fallback for the runtime check the advisor calls out: the
// narrowest live assertion (read the actual OpenShell-applied preset list
Expand Down Expand Up @@ -41,7 +41,7 @@ describe("handlePoliciesState — restricted resume reconciliation", () => {
preparePolicyPresetResumeSelection: prepareResume,
arePolicyPresetsApplied: vi.fn(() => true),
getActiveSandbox: vi.fn(() => ({
messaging: { plan: makeMessagingPlan("my-assistant", []) },
messaging: { plan: makeMessagingPlan() },
policyTier: "restricted",
})),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,12 @@

import { vi } from "vitest";

import { makeMessagingPlan } from "../../../../../test/helpers/messaging-plan-fixtures";
import { createSession, type Session, type SessionUpdates } from "../../../state/onboard-session";
import type { PoliciesStateOptions } from "./policies";

export type PolicyTestAgent = { name: string } | null;
export type PolicyTestWebSearchConfig = { fetchEnabled: true };
type MessagingPlan = NonNullable<Session["messagingPlan"]>;
type MessagingChannelId = MessagingPlan["channels"][number]["channelId"];

export function makeMessagingPlan(
sandboxName: string,
channels: readonly MessagingChannelId[],
disabledChannels: readonly MessagingChannelId[] = [],
): MessagingPlan {
const disabled = new Set(disabledChannels);
return {
schemaVersion: 1,
sandboxName,
agent: "openclaw",
workflow: "onboard",
channels: channels.map((channelId) => ({
channelId,
displayName: channelId,
authMode: "token-paste",
active: !disabled.has(channelId),
selected: true,
configured: true,
disabled: disabled.has(channelId),
inputs: [],
hooks: [],
})),
disabledChannels,
credentialBindings: [],
networkPolicy: { presets: [], entries: [] },
agentRender: [],
buildSteps: [],
stateUpdates: [],
healthChecks: [],
};
}

export function createPolicyHandlerDeps(
overrides: Partial<PoliciesStateOptions<PolicyTestAgent, PolicyTestWebSearchConfig>["deps"]> = {},
Expand All @@ -50,7 +17,7 @@ export function createPolicyHandlerDeps(
const calls = {
load: vi.fn(() => session),
activeSandbox: vi.fn(() => ({
messaging: { plan: makeMessagingPlan("my-assistant", ["telegram"]) },
messaging: { plan: makeMessagingPlan({ channels: ["telegram"] }) },
})),
mergeChannels: vi.fn(
(selected: string[], recorded: string[], active: string[] | null | undefined) =>
Expand Down
6 changes: 3 additions & 3 deletions src/lib/onboard/machine/handlers/policies.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@

import { describe, expect, it, vi } from "vitest";

import { makeMessagingPlan } from "../../../../../test/helpers/messaging-plan-fixtures";
import { createSession } from "../../../state/onboard-session";
import { mergePolicyMessagingChannels } from "../../messaging-policy-presets";
import { handlePoliciesState } from "./policies";
import {
basePolicyHandlerOptions as baseOptions,
createPolicyHandlerDeps,
makeMessagingPlan,
} from "./policies-test-fixtures";
} from "./policies-test-fixture";

function createDeps(overrides: Parameters<typeof createPolicyHandlerDeps>[0] = {}) {
return createPolicyHandlerDeps({
Expand Down Expand Up @@ -63,7 +63,7 @@ describe("handlePoliciesState", () => {
});

it("uses recorded messaging channels when no active selection exists", async () => {
const session = createSession({ messagingPlan: makeMessagingPlan("my-assistant", ["slack"]) });
const session = createSession({ messagingPlan: makeMessagingPlan({ channels: ["slack"] }) });
const { deps, calls, setSession } = createDeps({
getActiveSandbox: vi.fn(() => ({ messaging: null })),
});
Expand Down
60 changes: 17 additions & 43 deletions src/lib/state/onboard-session.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import os from "node:os";
import path from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";

import { makeMessagingPlan } from "../../../test/helpers/messaging-plan-fixtures";

const require = createRequire(import.meta.url);
const distPath = require.resolve("./onboard-session");
const eventsDistPath = require.resolve("../onboard/machine/events");
Expand All @@ -18,8 +20,6 @@ type OnboardMachineEvent = import("../onboard/machine/events").OnboardMachineEve
type LoadedSession = NonNullable<ReturnType<OnboardSessionModule["loadSession"]>>;
type DebugSummary = NonNullable<ReturnType<OnboardSessionModule["summarizeForDebug"]>>;
type NullableSessionUpdateKey = import("./onboard-session").NullableSessionUpdateKey;
type MessagingPlan = NonNullable<LoadedSession["messagingPlan"]>;
type MessagingChannelId = MessagingPlan["channels"][number]["channelId"];
let session: OnboardSessionModule;
let machineEvents: OnboardMachineEventsModule;
let tmpDir: string;
Expand Down Expand Up @@ -67,38 +67,6 @@ function normalizeLegacySession(
);
}

function makeMessagingPlan(
sandboxName: string,
channels: readonly MessagingChannelId[] = [],
disabledChannels: readonly MessagingChannelId[] = [],
): MessagingPlan {
const disabled = new Set(disabledChannels);
return {
schemaVersion: 1,
sandboxName,
agent: "openclaw",
workflow: "onboard",
channels: channels.map((channelId) => ({
channelId,
displayName: channelId,
authMode: "token-paste",
active: !disabled.has(channelId),
selected: true,
configured: true,
disabled: disabled.has(channelId),
inputs: [],
hooks: [],
})),
disabledChannels: [...disabledChannels],
credentialBindings: [],
networkPolicy: { presets: [], entries: [] },
agentRender: [],
buildSteps: [],
stateUpdates: [],
healthChecks: [],
};
}

beforeEach(() => {
// Recreate tmpDir per test so lock artifacts (and any other on-disk state)
// from a previous test cannot leak into this one. Without this, malformed
Expand Down Expand Up @@ -740,7 +708,10 @@ describe("onboard session", () => {

it("persists messagingPlan across save/load roundtrips", () => {
const created = session.createSession();
created.messagingPlan = makeMessagingPlan("my-assistant", ["telegram", "slack"], ["slack"]);
created.messagingPlan = makeMessagingPlan({
channels: ["telegram", "slack"],
disabledChannels: ["slack"],
});
session.saveSession(created);

const loaded = requireLoadedSession(session.loadSession());
Expand All @@ -763,10 +734,10 @@ describe("onboard session", () => {
it("writes compact messagingPlan derived fields to onboard-session.json", () => {
const created = session.createSession();
created.messagingPlan = {
...makeMessagingPlan("my-assistant", ["telegram"]),
...makeMessagingPlan({ channels: ["telegram"] }),
channels: [
{
...makeMessagingPlan("my-assistant", ["telegram"]).channels[0],
...makeMessagingPlan({ channels: ["telegram"] }).channels[0],
hooks: [
{
channelId: "telegram",
Expand Down Expand Up @@ -820,7 +791,7 @@ describe("onboard session", () => {
JSON.stringify({
...created,
messagingPlan: {
...makeMessagingPlan("my-assistant", ["telegram"]),
...makeMessagingPlan({ channels: ["telegram"] }),
disabledChannels: ["telegram", 42, null],
},
}),
Expand All @@ -836,7 +807,10 @@ describe("onboard session", () => {
// place this can survive, because rebuild destroys the registry entry
// before `onboard --resume` reads it back.
const created = session.createSession();
created.messagingPlan = makeMessagingPlan("my-assistant", ["telegram"], ["telegram"]);
created.messagingPlan = makeMessagingPlan({
channels: ["telegram"],
disabledChannels: ["telegram"],
});
session.saveSession(created);

const loaded = requireLoadedSession(session.loadSession());
Expand All @@ -850,7 +824,7 @@ describe("onboard session", () => {

it("filterSafeUpdates passes through messagingPlan and accepts explicit null clear", () => {
session.saveSession(session.createSession());
const plan = makeMessagingPlan("my-assistant", ["discord"]);
const plan = makeMessagingPlan({ channels: ["discord"] });
session.markStepComplete("provider_selection", { messagingPlan: plan });
expect(requireLoadedSession(session.loadSession()).messagingPlan).toMatchObject({
sandboxName: "my-assistant",
Expand Down Expand Up @@ -1291,7 +1265,7 @@ describe("onboard session", () => {
});

it("round-trips messagingPlan through normalizeSession", () => {
const plan = makeMessagingPlan("my-assistant", ["telegram"]);
const plan = makeMessagingPlan({ channels: ["telegram"] });
const created = session.createSession({ messagingPlan: plan });
expect(created.messagingPlan).toEqual(plan);
const saved = session.saveSession(created);
Expand All @@ -1305,7 +1279,7 @@ describe("onboard session", () => {

it("filterSafeUpdates preserves messagingPlan field", () => {
session.saveSession(session.createSession());
const plan = makeMessagingPlan("my-assistant", ["slack", "discord"]);
const plan = makeMessagingPlan({ channels: ["slack", "discord"] });
session.markStepComplete("provider_selection", {
messagingPlan: plan,
});
Expand Down Expand Up @@ -1387,7 +1361,7 @@ describe("onboard session", () => {
});

it("creates a session with a messagingPlan override", () => {
const plan = makeMessagingPlan("my-assistant", ["telegram", "slack"]);
const plan = makeMessagingPlan({ channels: ["telegram", "slack"] });
const created = session.createSession({ messagingPlan: plan });
expect(created.messagingPlan).toEqual(plan);
expect(created.provider).toBeNull();
Expand Down
Loading
Loading