mirror of
https://github.com/murashit/codex-panel.git
synced 2026-07-22 17:30:31 +00:00
Extract thread resume action
This commit is contained in:
parent
6b0707112e
commit
89a5be5774
3 changed files with 109 additions and 17 deletions
29
src/features/chat/thread-resume.ts
Normal file
29
src/features/chat/thread-resume.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import { parseServiceTier } from "../../app-server/service-tier";
|
||||
import { upsertThread } from "../../domain/threads/model";
|
||||
import type { Thread } from "../../generated/app-server/v2/Thread";
|
||||
import type { ThreadResumeResponse } from "../../generated/app-server/v2/ThreadResumeResponse";
|
||||
import type { ChatAction } from "./chat-state";
|
||||
import type { DisplayItem } from "./display/types";
|
||||
|
||||
export interface ResumedThreadActionParams {
|
||||
response: ThreadResumeResponse;
|
||||
listedThreads: readonly Thread[];
|
||||
displayItems?: readonly DisplayItem[];
|
||||
}
|
||||
|
||||
export function resumedThreadAction(params: ResumedThreadActionParams): Extract<ChatAction, { type: "thread/resumed" }> {
|
||||
const { response } = params;
|
||||
return {
|
||||
type: "thread/resumed",
|
||||
thread: response.thread,
|
||||
cwd: response.cwd,
|
||||
model: response.model,
|
||||
reasoningEffort: response.reasoningEffort,
|
||||
serviceTier: parseServiceTier(response.serviceTier),
|
||||
approvalPolicy: response.approvalPolicy,
|
||||
approvalsReviewer: response.approvalsReviewer,
|
||||
activePermissionProfile: response.activePermissionProfile,
|
||||
...(params.displayItems ? { displayItems: params.displayItems } : {}),
|
||||
listedThreads: upsertThread(params.listedThreads, response.thread),
|
||||
};
|
||||
}
|
||||
|
|
@ -2,7 +2,6 @@ import { ItemView, Notice, type ViewStateResult, type WorkspaceLeaf } from "obsi
|
|||
|
||||
import type { AppServerClient } from "../../app-server/client";
|
||||
import { ConnectionManager, StaleConnectionError } from "../../app-server/connection-manager";
|
||||
import { parseServiceTier } from "../../app-server/service-tier";
|
||||
import type { ApprovalAction, PendingApproval } from "./approvals/model";
|
||||
import type { SlashCommandName } from "./composer/slash-commands";
|
||||
import { parseSlashCommand } from "./composer/suggestions";
|
||||
|
|
@ -12,7 +11,6 @@ import type { DisplayDetailSection, DisplayItem } from "./display/types";
|
|||
import type { ReasoningEffort } from "../../generated/app-server/ReasoningEffort";
|
||||
import type { Model } from "../../generated/app-server/v2/Model";
|
||||
import type { Thread } from "../../generated/app-server/v2/Thread";
|
||||
import type { ThreadResumeResponse } from "../../generated/app-server/v2/ThreadResumeResponse";
|
||||
import type { UserInput } from "../../generated/app-server/v2/UserInput";
|
||||
import { collaborationModeLabel as formatCollaborationModeLabel } from "../../runtime/collaboration-mode";
|
||||
import { ChatController } from "./chat-controller";
|
||||
|
|
@ -40,7 +38,7 @@ import {
|
|||
type ChatAction,
|
||||
type ChatState,
|
||||
} from "./chat-state";
|
||||
import { codexPanelDisplayTitle, explicitThreadName, getThreadTitle, upsertThread } from "../../domain/threads/model";
|
||||
import { codexPanelDisplayTitle, explicitThreadName, getThreadTitle } from "../../domain/threads/model";
|
||||
import {
|
||||
referencedThreadDisplay,
|
||||
referencedThreadPrompt,
|
||||
|
|
@ -92,6 +90,7 @@ import {
|
|||
optimisticTurnStart,
|
||||
shouldAcknowledgeTurnStart,
|
||||
} from "./turn-submission";
|
||||
import { resumedThreadAction, type ResumedThreadActionParams } from "./thread-resume";
|
||||
|
||||
export interface CodexChatHost {
|
||||
readonly settings: CodexPanelSettings;
|
||||
|
|
@ -671,20 +670,10 @@ export class CodexChatView extends ItemView {
|
|||
}
|
||||
}
|
||||
|
||||
private applyResumedThread(response: ThreadResumeResponse): void {
|
||||
this.dispatch({
|
||||
type: "thread/resumed",
|
||||
thread: response.thread,
|
||||
cwd: response.cwd,
|
||||
model: response.model,
|
||||
reasoningEffort: response.reasoningEffort,
|
||||
serviceTier: parseServiceTier(response.serviceTier),
|
||||
approvalPolicy: response.approvalPolicy,
|
||||
approvalsReviewer: response.approvalsReviewer,
|
||||
activePermissionProfile: response.activePermissionProfile,
|
||||
displayItems: [this.systemItem("Loading thread...")],
|
||||
listedThreads: upsertThread(this.state.listedThreads, response.thread),
|
||||
});
|
||||
private applyResumedThread(response: ResumedThreadActionParams["response"]): void {
|
||||
this.dispatch(
|
||||
resumedThreadAction({ response, listedThreads: this.state.listedThreads, displayItems: [this.systemItem("Loading thread...")] }),
|
||||
);
|
||||
this.clearRestoredThreadLifecycle();
|
||||
this.clearDeferredRestoredThreadHydration();
|
||||
this.threadRename.resetThreadTurnPresence(false);
|
||||
|
|
|
|||
74
tests/features/chat/thread-resume.test.ts
Normal file
74
tests/features/chat/thread-resume.test.ts
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { resumedThreadAction } from "../../../src/features/chat/thread-resume";
|
||||
import type { Thread } from "../../../src/generated/app-server/v2/Thread";
|
||||
import type { ThreadResumeResponse } from "../../../src/generated/app-server/v2/ThreadResumeResponse";
|
||||
|
||||
describe("chat thread resume helpers", () => {
|
||||
it("builds thread resumed actions from response snapshots", () => {
|
||||
const existing = threadFixture("existing", "Existing");
|
||||
const resumed = threadFixture("thread", "Resumed");
|
||||
const loading = { id: "loading", kind: "system" as const, role: "system" as const, text: "Loading thread..." };
|
||||
|
||||
const action = resumedThreadAction({
|
||||
response: responseFixture(resumed),
|
||||
listedThreads: [existing],
|
||||
displayItems: [loading],
|
||||
});
|
||||
|
||||
expect(action).toMatchObject({
|
||||
type: "thread/resumed",
|
||||
thread: resumed,
|
||||
cwd: "/vault",
|
||||
model: "gpt-5.5",
|
||||
reasoningEffort: "high",
|
||||
serviceTier: "fast",
|
||||
approvalPolicy: "on-request",
|
||||
approvalsReviewer: "user",
|
||||
activePermissionProfile: null,
|
||||
displayItems: [loading],
|
||||
});
|
||||
expect(action.listedThreads?.map((thread) => thread.id)).toEqual(["thread", "existing"]);
|
||||
});
|
||||
});
|
||||
|
||||
function responseFixture(thread: Thread): ThreadResumeResponse {
|
||||
return {
|
||||
thread,
|
||||
model: "gpt-5.5",
|
||||
modelProvider: "openai",
|
||||
serviceTier: "fast",
|
||||
cwd: "/vault",
|
||||
runtimeWorkspaceRoots: [],
|
||||
instructionSources: [],
|
||||
approvalPolicy: "on-request",
|
||||
approvalsReviewer: "user",
|
||||
sandbox: { type: "readOnly", networkAccess: false },
|
||||
activePermissionProfile: null,
|
||||
reasoningEffort: "high",
|
||||
};
|
||||
}
|
||||
|
||||
function threadFixture(id: string, name: string): Thread {
|
||||
return {
|
||||
id,
|
||||
sessionId: "session",
|
||||
forkedFromId: null,
|
||||
preview: "",
|
||||
ephemeral: false,
|
||||
modelProvider: "openai",
|
||||
createdAt: 1,
|
||||
updatedAt: 1,
|
||||
status: { type: "idle" },
|
||||
path: null,
|
||||
cwd: "/vault",
|
||||
cliVersion: "0.0.0",
|
||||
source: "appServer",
|
||||
threadSource: null,
|
||||
agentNickname: null,
|
||||
agentRole: null,
|
||||
gitInfo: null,
|
||||
name,
|
||||
turns: [],
|
||||
};
|
||||
}
|
||||
Loading…
Reference in a new issue