mirror of
https://github.com/murashit/codex-panel.git
synced 2026-07-22 06:57:10 +00:00
Tighten pending request controller contracts
This commit is contained in:
parent
5fb6212e92
commit
0becb8f39a
4 changed files with 21 additions and 26 deletions
|
|
@ -1,5 +1,4 @@
|
|||
import type { ChatStateStore } from "../state/reducer";
|
||||
import type { ChatInboundController } from "../../app-server/inbound/controller";
|
||||
import { pendingRequestFocusSignature } from "../../domain/pending-requests/signatures";
|
||||
import { pendingRequestBlockState } from "./snapshot";
|
||||
import {
|
||||
|
|
@ -10,9 +9,15 @@ import {
|
|||
} from "../../domain/pending-requests/model";
|
||||
import type { PendingRequestBlockActions, PendingRequestBlockState, PendingRequestId } from "./block";
|
||||
|
||||
interface PendingRequestResponder {
|
||||
resolveApproval: (approval: PendingApproval, action: ApprovalAction) => void;
|
||||
resolveUserInput: (input: PendingUserInput, answers: Record<string, string>) => void;
|
||||
cancelUserInput: (input: PendingUserInput) => void;
|
||||
}
|
||||
|
||||
export interface PendingRequestControllerHost {
|
||||
stateStore: ChatStateStore;
|
||||
controller: ChatInboundController;
|
||||
responder: PendingRequestResponder;
|
||||
composerHasFocus: () => boolean;
|
||||
refreshLiveState: () => void;
|
||||
}
|
||||
|
|
@ -55,14 +60,14 @@ export class PendingRequestController {
|
|||
resolveApproval(requestId: PendingRequestId, action: ApprovalAction): void {
|
||||
const approval = this.pendingApproval(requestId);
|
||||
if (!approval) return;
|
||||
this.host.controller.resolveApproval(approval, action);
|
||||
this.host.responder.resolveApproval(approval, action);
|
||||
this.commitRequestAction();
|
||||
}
|
||||
|
||||
resolveUserInput(requestId: PendingRequestId): void {
|
||||
const input = this.pendingUserInput(requestId);
|
||||
if (!input) return;
|
||||
this.host.controller.resolveUserInput(
|
||||
this.host.responder.resolveUserInput(
|
||||
input,
|
||||
answersForPendingUserInput(input, pendingRequestBlockState(this.host.stateStore.getState()).userInputDrafts),
|
||||
);
|
||||
|
|
@ -72,7 +77,7 @@ export class PendingRequestController {
|
|||
cancelUserInput(requestId: PendingRequestId): void {
|
||||
const input = this.pendingUserInput(requestId);
|
||||
if (!input) return;
|
||||
this.host.controller.cancelUserInput(input);
|
||||
this.host.responder.cancelUserInput(input);
|
||||
this.commitRequestAction();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import {
|
|||
type ChatRuntimeState,
|
||||
} from "../../domain/runtime/state";
|
||||
import type { RequestedServiceTier } from "../../domain/runtime/pending-settings";
|
||||
import type { RequestId } from "../../../../app-server/connection/rpc-messages";
|
||||
import type { PendingRequestId } from "../../domain/pending-requests/model";
|
||||
import type { ComposerSuggestion } from "../composer/suggestions";
|
||||
import type { MessageStreamItem } from "../../domain/message-stream/items";
|
||||
import type {
|
||||
|
|
@ -278,7 +278,7 @@ export type ChatAction = ChatTransitionAction | ChatSliceAction;
|
|||
|
||||
interface RequestResolvedAction {
|
||||
type: "request/resolved";
|
||||
requestId: RequestId;
|
||||
requestId: PendingRequestId;
|
||||
resultItem?: MessageStreamItem;
|
||||
}
|
||||
|
||||
|
|
@ -1036,7 +1036,7 @@ function clearAllRequestDisclosures(state: ChatUiState): ChatUiState {
|
|||
});
|
||||
}
|
||||
|
||||
function clearResolvedRequestDisclosures(state: ChatUiState, requestId: RequestId): ChatUiState {
|
||||
function clearResolvedRequestDisclosures(state: ChatUiState, requestId: PendingRequestId): ChatUiState {
|
||||
const id = String(requestId);
|
||||
const approvalDetails = filterStringSet(state.disclosures.approvalDetails, (key) => !key.startsWith(`${id}:`));
|
||||
if (approvalDetails === state.disclosures.approvalDetails) return state;
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ export function createConversationParts(
|
|||
|
||||
const pendingRequests = new PendingRequestController({
|
||||
stateStore,
|
||||
controller: refs.controller,
|
||||
responder: refs.controller,
|
||||
composerHasFocus: () => composerController.hasFocus(),
|
||||
refreshLiveState: liveState.refresh,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { ChatInboundController } from "../../../../../src/features/chat/app-server/inbound/controller";
|
||||
import { createChatState, createChatStateStore } from "../../../../../src/features/chat/application/state/reducer";
|
||||
import { PendingRequestController } from "../../../../../src/features/chat/application/pending-requests/controller";
|
||||
import { toPendingUserInput } from "../../../../../src/features/chat/app-server/requests/user-input";
|
||||
|
|
@ -14,23 +13,15 @@ function expectPresent<T>(value: T | null | undefined): T {
|
|||
describe("PendingRequestController", () => {
|
||||
it("resolves user input from immutable draft state and refreshes the host", () => {
|
||||
const stateStore = createChatStateStore(createChatState());
|
||||
const respondToServerRequest = vi.fn().mockReturnValue(true);
|
||||
const resolveUserInput = vi.fn();
|
||||
const refreshLiveState = vi.fn();
|
||||
const controller = new ChatInboundController(stateStore, {
|
||||
refreshThreads: vi.fn(),
|
||||
refreshRateLimits: vi.fn(),
|
||||
refreshSkills: vi.fn(),
|
||||
publishAppServerMetadata: vi.fn(),
|
||||
maybeNameThread: vi.fn(),
|
||||
notifyThreadArchived: vi.fn(),
|
||||
notifyThreadRenamed: vi.fn(),
|
||||
recordMcpStartupStatus: vi.fn(),
|
||||
respondToServerRequest,
|
||||
rejectServerRequest: vi.fn(),
|
||||
});
|
||||
const pendingRequests = new PendingRequestController({
|
||||
stateStore,
|
||||
controller,
|
||||
responder: {
|
||||
resolveApproval: vi.fn(),
|
||||
resolveUserInput,
|
||||
cancelUserInput: vi.fn(),
|
||||
},
|
||||
composerHasFocus: () => false,
|
||||
refreshLiveState,
|
||||
});
|
||||
|
|
@ -40,8 +31,7 @@ describe("PendingRequestController", () => {
|
|||
|
||||
pendingRequests.resolveUserInput(input.requestId);
|
||||
|
||||
expect(respondToServerRequest).toHaveBeenCalledWith(7, { answers: { direction: { answers: ["Left"] } } });
|
||||
expect(stateStore.getState().requests.pendingUserInputs).toEqual([]);
|
||||
expect(resolveUserInput).toHaveBeenCalledWith(input, { direction: "Left" });
|
||||
expect(refreshLiveState).toHaveBeenCalledOnce();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue