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
11 changes: 4 additions & 7 deletions src/modules/workbench-shell/model/composer-commands.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { describe, expect, it } from "vitest";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review completed for this PR diff. No concrete inline issue was selected after aggregation.

import type { PromptInputMessage } from "@/components/ai-elements/prompt-input";
import type { RunMode } from "@/shared/types/api";
import {
buildCommandEffectivePrompt,
buildComposerCommandRegistry,
Expand All @@ -10,8 +9,6 @@ import {
parseSlashCommandInput,
} from "@/modules/workbench-shell/model/composer-commands";

const RUN_MODE: RunMode = "default";

function createMessage(text: string): PromptInputMessage {
return {
text,
Expand All @@ -22,7 +19,7 @@ function createMessage(text: string): PromptInputMessage {
describe("buildComposerSubmission", () => {
it("preserves plain multi-line Markdown exactly", () => {
const text = " 1. First\n2. Second\n\n- Bullet\n```ts\nconst value = 1;\n```\n ";
const submission = buildComposerSubmission(createMessage(text), [], RUN_MODE);
const submission = buildComposerSubmission(createMessage(text), []);

expect(submission).not.toBeNull();
expect(submission?.kind).toBe("plain");
Expand All @@ -31,15 +28,15 @@ describe("buildComposerSubmission", () => {
});

it("rejects whitespace-only messages without attachments", () => {
const submission = buildComposerSubmission(createMessage(" \n\t "), [], RUN_MODE);
const submission = buildComposerSubmission(createMessage(" \n\t "), []);

expect(submission).toBeNull();
});

it("parses slash commands from trimmed text while preserving the original display text", () => {
const registry = buildComposerCommandRegistry([]);
const text = " /init \n";
const submission = buildComposerSubmission(createMessage(text), registry, RUN_MODE);
const submission = buildComposerSubmission(createMessage(text), registry);

expect(submission).not.toBeNull();
expect(submission?.kind).toBe("command");
Expand All @@ -51,7 +48,7 @@ describe("buildComposerSubmission", () => {
it("preserves multi-line /goal objectives as command arguments", () => {
const registry = buildComposerCommandRegistry([]);
const text = "/goal First goal line\nSecond goal line\n- checklist item";
const submission = buildComposerSubmission(createMessage(text), registry, RUN_MODE);
const submission = buildComposerSubmission(createMessage(text), registry);

expect(submission).not.toBeNull();
expect(submission?.kind).toBe("command");
Expand Down
6 changes: 1 addition & 5 deletions src/modules/workbench-shell/model/composer-commands.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { PromptInputMessage } from "@/components/ai-elements/prompt-input";
import type { CommandEntry } from "@/modules/settings-center/model/types";
import type { MessageAttachmentDto, RunMode } from "@/shared/types/api";
import type { MessageAttachmentDto } from "@/shared/types/api";

export type ComposerReferencedFile = {
name: string;
Expand Down Expand Up @@ -139,7 +139,6 @@ export type ComposerSubmission = {
attachments: MessageAttachmentDto[];
command?: ComposerCommandInvocation;
metadata?: Record<string, unknown> | null;
runMode?: RunMode;
};

const BUILTIN_COMMANDS: ReadonlyArray<ComposerCommandDescriptor> = [
Expand Down Expand Up @@ -551,7 +550,6 @@ export function buildCommandEffectivePrompt(
export function buildComposerSubmission(
message: PromptInputMessage,
registry: ReadonlyArray<ComposerCommandDescriptor>,
runMode?: RunMode,
): ComposerSubmission | null {
const rawText = message.text ?? "";
const trimmedText = rawText.trim();
Expand All @@ -574,7 +572,6 @@ export function buildComposerSubmission(
rawMessage: message,
attachments,
metadata: null,
runMode,
};
}

Expand Down Expand Up @@ -605,6 +602,5 @@ export function buildComposerSubmission(
command: invocation,
},
},
runMode,
};
}
8 changes: 0 additions & 8 deletions src/modules/workbench-shell/model/composer-store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { describe, it, expect, beforeEach } from "vitest";
import {
composerStore,
setNewThreadValue,
setNewThreadRunMode,
setNewThreadReferencedFiles,
setNewThreadAttachmentData,
setDraft,
Expand All @@ -25,13 +24,6 @@ describe("composerStore", () => {
expect(composerStore.getState().newThreadValue).toBe("hello world");
});

it("should set new thread run mode", () => {
setNewThreadRunMode("plan");
expect(composerStore.getState().newThreadRunMode).toBe("plan");
setNewThreadRunMode("default");
expect(composerStore.getState().newThreadRunMode).toBe("default");
});

it("should clear new thread composer", () => {
setNewThreadValue("some value");
setNewThreadReferencedFiles([{ name: "test.ts", path: "/test.ts", parentPath: "/" }]);
Expand Down
8 changes: 0 additions & 8 deletions src/modules/workbench-shell/model/composer-store.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { createStore, useStore as useStoreBase, shallowEqual } from "@/shared/lib/create-store";
import type { RunMode } from "@/shared/types/api";
import type { ComposerReferencedFile } from "@/modules/workbench-shell/model/composer-commands";

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -28,8 +27,6 @@ export interface ComposerStoreState {
[key: string]: unknown;
/** Input value for new-thread mode. */
newThreadValue: string;
/** Run mode for new threads (default / plan). */
newThreadRunMode: RunMode;
/** @file references for new-thread composer. */
newThreadReferencedFiles: ComposerReferencedFile[];
/** Serialized attachment data for new-thread composer. */
Expand All @@ -46,7 +43,6 @@ export interface ComposerStoreState {

export const composerStore = createStore<ComposerStoreState>({
newThreadValue: "",
newThreadRunMode: "default",
newThreadReferencedFiles: [],
newThreadAttachmentData: [],
drafts: {},
Expand All @@ -67,10 +63,6 @@ export function setNewThreadValue(value: string): void {
composerStore.setState({ newThreadValue: value });
}

export function setNewThreadRunMode(mode: RunMode): void {
composerStore.setState({ newThreadRunMode: mode });
}

export function setNewThreadReferencedFiles(files: ReadonlyArray<ComposerReferencedFile>): void {
composerStore.setState({ newThreadReferencedFiles: files as ComposerReferencedFile[] });
}
Expand Down
1 change: 0 additions & 1 deletion src/modules/workbench-shell/model/thread-store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ function makePendingRun(overrides?: Partial<PendingThreadRun>): PendingThreadRun
effectivePrompt: "test prompt",
attachments: [],
metadata: null,
runMode: "default",
threadId: "thread-1",
...overrides,
};
Expand Down
9 changes: 2 additions & 7 deletions src/modules/workbench-shell/model/workbench-actions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ describe("deleteThread", () => {
threadStore.setState({
activeThreadId: null,
workspaces: [makeWorkspace("ws-1", [thread])],
pendingRuns: { "thread-1": { id: "run-1", prompt: "test", runMode: "auto" } as any },
pendingRuns: { "thread-1": { id: "run-1", prompt: "test" } as any },
});

await deleteThread("thread-1", { skipIpc: true });
Expand Down Expand Up @@ -461,7 +461,7 @@ describe("removeWorkspace", () => {
threadStore.setState({
activeThreadId: null,
workspaces: [ws1],
pendingRuns: { "thread-1": { id: "run-1", prompt: "test", runMode: "auto" } as any },
pendingRuns: { "thread-1": { id: "run-1", prompt: "test" } as any },
});

await removeWorkspace(ws1 as any);
Expand Down Expand Up @@ -583,7 +583,6 @@ describe("submitNewThread", () => {
): NewThreadSubmission {
return {
value: "test prompt",
runMode: "default",
effectivePrompt: "test prompt",
...overrides,
};
Expand All @@ -594,7 +593,6 @@ describe("submitNewThread", () => {
workspaces: [],
isNewThreadMode: true,
});
composerStore.setState({ newThreadRunMode: "default" });
settingsStore.setState({ activeAgentProfileId: "default-profile" });

await submitNewThread(makeSubmission({ value: "hello" }));
Expand Down Expand Up @@ -626,7 +624,6 @@ describe("submitNewThread", () => {
workspaces: [workspace],
isNewThreadMode: true,
});
composerStore.setState({ newThreadRunMode: "default" });
settingsStore.setState({ activeAgentProfileId: "default-profile" });

await submitNewThread(makeSubmission({ value: "hello" }));
Expand Down Expand Up @@ -659,7 +656,6 @@ describe("submitNewThread", () => {
isNewThreadMode: true,
});
projectStore.setState({ selectedProject: project, recentProjects: [project] });
composerStore.setState({ newThreadRunMode: "default" });
settingsStore.setState({ activeAgentProfileId: "default-profile" });

await submitNewThread(makeSubmission({
Expand Down Expand Up @@ -703,7 +699,6 @@ describe("submitNewThread", () => {
workspaces: [workspace],
isNewThreadMode: true,
});
composerStore.setState({ newThreadRunMode: "default" });
settingsStore.setState({ activeAgentProfileId: "default-profile" });

await submitNewThread(makeSubmission({ value: "new thread" }));
Expand Down
6 changes: 1 addition & 5 deletions src/modules/workbench-shell/model/workbench-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import {
findWorkspaceByPath,
} from "@/modules/workbench-shell/model/workspace-path-bindings";
import type { ProjectOption, WorkspaceItem } from "@/modules/workbench-shell/model/types";
import type { MessageAttachmentDto, RunMode, ThreadSummaryDto, WorkspaceDto } from "@/shared/types/api";
import type { MessageAttachmentDto, ThreadSummaryDto, WorkspaceDto } from "@/shared/types/api";
import type { LanguagePreference } from "@/app/providers/language-provider";
import type { ComposerCommandInvocation } from "@/modules/workbench-shell/model/composer-commands";

Expand All @@ -61,7 +61,6 @@ import type { ComposerCommandInvocation } from "@/modules/workbench-shell/model/

export interface NewThreadSubmission {
value: string;
runMode: RunMode;
displayText?: string;
effectivePrompt: string;
attachments?: MessageAttachmentDto[];
Expand Down Expand Up @@ -574,7 +573,6 @@ export async function submitNewThread(submission: NewThreadSubmission): Promise<

// Re-read workspaces after async IPC to avoid stale state
const { workspaces } = threadStore.getState();
const { newThreadRunMode } = composerStore.getState();

// Find or match the workspace in the sidebar
const existingWorkspace =
Expand Down Expand Up @@ -674,7 +672,6 @@ export async function submitNewThread(submission: NewThreadSubmission): Promise<
attachments: (submission.attachments ?? []) as unknown as PendingThreadRun["attachments"],
metadata: submission.metadata ?? null,
command: submission.command,
runMode: submission.runMode ?? newThreadRunMode,
threadId,
};
return {
Expand Down Expand Up @@ -717,7 +714,6 @@ export async function submitNewThread(submission: NewThreadSubmission): Promise<
// Reset composer
composerStore.setState({
newThreadValue: "",
newThreadRunMode: "default",
newThreadReferencedFiles: [],
newThreadAttachmentData: [],
error: null,
Expand Down
3 changes: 1 addition & 2 deletions src/modules/workbench-shell/ui/dashboard-workbench-logic.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { LanguagePreference } from "@/app/providers/language-provider";
import type { MessageAttachmentDto, RunMode, WorkspaceDto } from "@/shared/types/api";
import type { MessageAttachmentDto, WorkspaceDto } from "@/shared/types/api";
import { buildProjectOptionFromPath } from "@/modules/workbench-shell/model/helpers";
import type {
ProjectOption,
Expand Down Expand Up @@ -188,6 +188,5 @@ export type PendingThreadRun = {
attachments: MessageAttachmentDto[];
metadata: Record<string, unknown> | null;
command?: import("@/modules/workbench-shell/model/composer-commands").ComposerCommandInvocation;
runMode: RunMode;
threadId: string;
};
2 changes: 0 additions & 2 deletions src/modules/workbench-shell/ui/dashboard-workbench.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,6 @@ const drawerWidth = useStore(uiLayoutStore, (s) => s.drawerWidth);

const composerValue = useStore(composerStore, (s) => s.newThreadValue);
const composerError = useStore(composerStore, (s) => s.error);
const newThreadRunMode = useStore(composerStore, (s) => s.newThreadRunMode);
const newThreadReferencedFiles = useStore(composerStore, (s) => s.newThreadReferencedFiles);
const newThreadAttachmentData = useStore(composerStore, (s) => s.newThreadAttachmentData);

Expand Down Expand Up @@ -714,7 +713,6 @@ const drawerWidth = useStore(uiLayoutStore, (s) => s.drawerWidth);

void submitNewThread({
value: trimmedValue,
runMode: newThreadRunMode,
displayText: submission.displayText,
effectivePrompt,
attachments: submission.attachments,
Expand Down
18 changes: 0 additions & 18 deletions src/modules/workbench-shell/ui/runtime-thread-surface-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import type {
MessageAttachmentDto,
MessageDto,
MessagePartDto,
RunMode,
RunSummaryDto,
ThreadSnapshotDto,
ToolCallDto,
Expand Down Expand Up @@ -279,7 +278,6 @@ export type InitialPromptRequest = {
effectivePrompt: string;
attachments: MessageAttachmentDto[];
metadata: Record<string, unknown> | null;
runMode?: RunMode;
};

export type ThinkingPlaceholder = {
Expand Down Expand Up @@ -392,22 +390,6 @@ export function mapRecordedUserMessage(event: RecordedUserMessageEvent): Surface



export function deriveSelectedRunMode(snapshot: ThreadSnapshotDto, currentMode: RunMode) {
if (
snapshot.thread.status === "waiting_approval"
&& !snapshot.activeRun
&& snapshot.latestRun?.runMode === "plan"
) {
return "plan";
}

if (snapshot.activeRun?.runMode === "default" || snapshot.activeRun?.runMode === "plan") {
return snapshot.activeRun.runMode;
}

return currentMode;
}

export function formatApprovalPromptState(state: string, approvedAction: PlanApprovalAction | null, t: (key: TranslationKey) => string) {
switch (state) {
case "approved":
Expand Down
Loading
Loading