fix(ui): satisfy Custodian receipt checks

This commit is contained in:
jesse-merhi
2026-08-13 13:10:30 +10:00
parent aba77aea6b
commit f5bc88d981
4 changed files with 34 additions and 33 deletions
@@ -270,11 +270,11 @@ describe("openclaw.chat reset boundary", () => {
historyResponses.push({ ok, payload, error }),
} as never);
expect(historyResponses[0]).toMatchObject({ ok: true, error: undefined });
expect(historyResponses[0]).not.toHaveProperty("payload.activeWizard");
const restoredTurns = (
historyResponses[0]?.payload as { turns: SystemAgentChatHistoryTurn[] }
).turns;
const historyResponse = expectDefined(historyResponses[0], "recovery history response");
expect(historyResponse).toMatchObject({ ok: true, error: undefined });
expect(historyResponse).not.toHaveProperty("payload.activeWizard");
const restoredTurns = (historyResponse.payload as { turns: SystemAgentChatHistoryTurn[] })
.turns;
expect(restoredTurns.find((turn) => turn.text === "banana")).not.toHaveProperty(
"wizardAction",
);
@@ -3,7 +3,6 @@ import {
readSystemAgentInferenceUnavailableErrorDetails,
type SystemAgentChatParams,
type SystemAgentChatResult,
type SystemAgentWizardActionReceipt,
} from "@openclaw/gateway-protocol";
import type { GatewayBrowserClient } from "../../api/gateway.ts";
import { selectApplicationSession } from "../../app/agent-selection.ts";
@@ -17,7 +16,12 @@ import {
import { buildAgentMainSessionKey, normalizeAgentId } from "../../lib/sessions/session-key.ts";
import { pathForCustodianAgentHandoff } from "./custodian-navigation.ts";
import { readCustodianRecoveryForClient } from "./custodian-recovery.ts";
import { createCustodianStructuredInteraction } from "./custodian-structured-interaction.ts";
import {
createCustodianStructuredInteraction,
hasCustodianUserInput,
hasCustodianWizardAction,
type CustodianSendResult,
} from "./custodian-structured-interaction.ts";
import {
CustodianTranscriptState,
type CustodianTranscriptHistoryOutcome,
@@ -41,25 +45,8 @@ import {
const SYSTEM_AGENT_CHAT_TIMEOUT_MS = 190_000;
const SILENT_REPLY_PATTERN = /^\s*NO_REPLY\s*$/;
function hasCustodianUserInput(params: SystemAgentChatParams): boolean {
return (
params.message !== undefined ||
params.wizardAnswer !== undefined ||
params.wizardCancel !== undefined
);
}
function hasCustodianWizardAction(params: SystemAgentChatParams): boolean {
return params.wizardAnswer !== undefined || params.wizardCancel !== undefined;
}
type StoreListener = () => void;
type ConfiguredInferenceState = "unresolved" | "required" | "ready";
type CustodianSetupIssue = "missing" | "unavailable";
type CustodianSendResult = {
outcome: eventNudgeState.CustodianSendOutcome;
wizardAction?: SystemAgentWizardActionReceipt;
};
/** One process-local conversation owner shared by the full page and dock surface. */
export class CustodianSessionStore extends CustodianTranscriptState {
@@ -88,7 +75,7 @@ export class CustodianSessionStore extends CustodianTranscriptState {
private gatewayCleanup: (() => void) | null = null;
private agentCleanup: (() => void) | null = null;
private eventCleanup: (() => void) | null = null;
private readonly listeners = new Set<StoreListener>();
private readonly listeners = new Set<() => void>();
private readonly structuredInteraction = createCustodianStructuredInteraction({
state: () => ({
activeClient: this.activeClient,
@@ -107,7 +94,7 @@ export class CustodianSessionStore extends CustodianTranscriptState {
this.sendUserTurn(client, params, display, true, appendUserMessage),
});
subscribe(listener: StoreListener): () => void {
subscribe(listener: () => void): () => void {
this.listeners.add(listener);
return () => this.listeners.delete(listener);
}
@@ -8,6 +8,23 @@ import { custodianWizardSubmission } from "./custodian-wizard-step.ts";
import type * as eventNudgeState from "./event-nudge.ts";
import type { CustodianMessage, CustodianStructuredResponse } from "./transcript.ts";
export type CustodianSendResult = {
outcome: eventNudgeState.CustodianSendOutcome;
wizardAction?: SystemAgentWizardActionReceipt;
};
export function hasCustodianUserInput(params: SystemAgentChatParams): boolean {
return (
params.message !== undefined ||
params.wizardAnswer !== undefined ||
params.wizardCancel !== undefined
);
}
export function hasCustodianWizardAction(params: SystemAgentChatParams): boolean {
return params.wizardAnswer !== undefined || params.wizardCancel !== undefined;
}
type StructuredInteractionState = {
activeClient: GatewayBrowserClient | null;
chatAvailable: boolean;
@@ -29,10 +46,7 @@ type StructuredInteractionHost = {
params: SystemAgentChatParams,
display: string,
userTurnProjection: "always" | "unless-accepted",
) => Promise<{
outcome: eventNudgeState.CustodianSendOutcome;
wizardAction?: SystemAgentWizardActionReceipt;
}>;
) => Promise<CustodianSendResult>;
};
function withResponse(
+3 -3
View File
@@ -303,8 +303,8 @@ openclaw-custodian-page {
}
.custodian__structured-response-icon--cancelled {
background: color-mix(in srgb, var(--text-muted) 18%, transparent);
color: var(--text-muted);
background: color-mix(in srgb, var(--muted) 18%, transparent);
color: var(--muted);
}
.custodian__structured-response-copy {
@@ -328,7 +328,7 @@ openclaw-custodian-page {
}
.custodian__structured-response-status {
color: var(--text-muted);
color: var(--muted);
font-size: 12px;
}