diff --git a/packages/app/e2e/app/home.spec.ts b/packages/app/e2e/app/home.spec.ts index 1c6a729c3..40a814f13 100644 --- a/packages/app/e2e/app/home.spec.ts +++ b/packages/app/e2e/app/home.spec.ts @@ -1,12 +1,11 @@ import { test, expect } from "../fixtures" import { promptSelector, sessionComposerDockSelector } from "../selectors" -test("@smoke home renders the hero composer and starter cards", async ({ page, project }) => { +test("@smoke home renders hero composer without skill-card shortcuts", async ({ page, project }) => { await project.open() const home = page.locator('[data-component="session-new-home"]') const composer = home.locator(sessionComposerDockSelector) - const firstCard = home.getByRole("button", { name: /Process docs/i }) const workspaceChip = page.getByRole("button", { name: /Switch workspace|切换工作目录/i }) await expect(home).toBeVisible() await expect(page.getByRole("heading", { name: "What do you want to do?" })).toBeVisible() @@ -14,17 +13,14 @@ test("@smoke home renders the hero composer and starter cards", async ({ page, p await expect(composer).toHaveCount(1) await expect(composer).toHaveCSS("text-align", "left") await expect(home.locator(promptSelector)).toBeVisible() - await expect(firstCard).toBeVisible() - await expect(page.getByRole("button", { name: /Analyze data/i })).toBeVisible() - await expect(page.getByRole("button", { name: /Start writing/i })).toBeVisible() await expect(page.getByRole("button", { name: "Right utility panel" })).toBeVisible() await expect(workspaceChip).toBeVisible() - const cardBox = await firstCard.boundingBox() - const composerBox = await composer.boundingBox() - expect(cardBox).not.toBeNull() - expect(composerBox).not.toBeNull() - expect(cardBox!.y).toBeGreaterThan(composerBox!.y) + // Skill-card shortcuts removed in #603 PR2 — slash commands typed directly in + // the composer remain available for the same productivity skills. + await expect(home.getByRole("button", { name: /Process docs/i })).toHaveCount(0) + await expect(home.getByRole("button", { name: /Analyze data/i })).toHaveCount(0) + await expect(home.getByRole("button", { name: /Start writing/i })).toHaveCount(0) }) test("@smoke home hero prompt starts a session", async ({ page, project, assistant }) => { @@ -43,6 +39,29 @@ test("@smoke home hero prompt starts a session", async ({ page, project, assista await expect(page.getByText("home hero reply")).toBeVisible() }) +test("@smoke home composer submits a slash-prefixed prompt via the fallback path", async ({ + page, + project, + assistant, +}) => { + // Guards the #603 PR2 simplification of submit.ts: removing the `!homeSkill` + // gate must not break the slash-prefix fall-through. A leading `/` that does + // not match a registered command should still fall through to the standard + // prompt path. Using an unregistered command name keeps the test independent + // of which backend slash commands are bundled in the fixture. + await project.open() + + const home = page.locator('[data-component="session-new-home"]') + const prompt = home.locator(sessionComposerDockSelector).locator(promptSelector) + await expect(prompt).toBeVisible() + await assistant.reply("slash hero reply") + await page.keyboard.type("/pr2skillcheck verify slash submit") + await page.keyboard.press("Enter") + + await expect.poll(() => page.url(), { timeout: 30_000 }).toContain("/session/") + await expect(page.getByText("slash hero reply")).toBeVisible() +}) + test("@smoke home composer shows unified single-row bar with brand orange send", async ({ page, project }) => { await project.open() @@ -54,15 +73,23 @@ test("@smoke home composer shows unified single-row bar with brand orange send", // no DockTray tray surface above the input await expect(composer.locator('[data-dock-surface="tray"]')).toHaveCount(0) - // brand orange enables only when input has content, type first const prompt = home.locator(promptSelector) - await prompt.click() - await page.keyboard.type("x") - const send = composer.locator('[data-action="prompt-submit"]') + + // send is disabled while the prompt is blank — guards the readiness rule + // that #603 PR2 simplified after removing the selectedSkill bypass. await expect(send).toBeVisible() + await expect(send).toBeDisabled() + + // brand orange enables only when input has content + await prompt.click() + await page.keyboard.type("x") await expect(send).toBeEnabled() + // clearing the prompt returns send to disabled + await page.keyboard.press("Backspace") + await expect(send).toBeDisabled() + // WorkspaceChip present on home const workspaceChip = page.getByRole("button", { name: /Switch workspace|切换工作目录/i }) await expect(workspaceChip).toBeVisible() diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index 8f14b7986..d06a13c01 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -45,7 +45,6 @@ import { PromptDragOverlay } from "./prompt-input/drag-overlay" import { promptPlaceholder } from "./prompt-input/placeholder" import { promptSendDisabled } from "./prompt-input/readiness" import { ImagePreview } from "@opencode-ai/ui/image-preview" -import type { PawworkSkillName } from "@/components/session/pawwork-skill-meta" interface PromptInputProps { class?: string @@ -64,7 +63,6 @@ interface PromptInputProps { sessionIDControlled?: boolean actionReady?: () => boolean abortReady?: () => boolean - selectedSkill?: () => PawworkSkillName | undefined } const EXAMPLES = [ @@ -242,7 +240,6 @@ export const PromptInput: Component = (props) => { commentCount: commentCount(), example: suggest() ? language.t(EXAMPLES[store.placeholder]) : "", suggest: suggest(), - selectedSkill: props.selectedSkill?.(), t: (key, params) => language.t(key as Parameters[0], params as never), }) : language.t("prompt.loading"), @@ -458,7 +455,6 @@ export const PromptInput: Component = (props) => { resetHistoryNavigation(true) }, setMode: (mode) => setStore("mode", mode), - selectedSkill: props.selectedSkill, setPopover: (popover) => setStore("popover", popover), newSessionWorktree: () => props.newSessionWorktree, onNewSessionWorktreeReset: props.onNewSessionWorktreeReset, @@ -689,7 +685,6 @@ export const PromptInput: Component = (props) => { actionReady: actionReady(), abortReady: abortReady(), blank: blank(), - selectedSkill: !!props.selectedSkill?.(), })} aria-label={stopping() ? language.t("prompt.action.stop") : language.t("prompt.action.send")} /> diff --git a/packages/app/src/components/prompt-input/home-override.test.ts b/packages/app/src/components/prompt-input/home-override.test.ts deleted file mode 100644 index f25d15367..000000000 --- a/packages/app/src/components/prompt-input/home-override.test.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { describe, expect, test } from "bun:test" -import { buildHomeOverride } from "./home-override" - -describe("buildHomeOverride", () => { - test("returns undefined when no Skill is selected", () => { - expect(buildHomeOverride(undefined, "")).toBeUndefined() - expect(buildHomeOverride(undefined, " some text ")).toBeUndefined() - }) - - test("returns plain /skill-name for Skill-only send with empty text", () => { - expect(buildHomeOverride("document-processing", "")).toBe("/document-processing") - }) - - test("treats whitespace-only text as empty and returns plain /skill-name", () => { - expect(buildHomeOverride("data-analysis", " ")).toBe("/data-analysis") - expect(buildHomeOverride("data-analysis", "\n\t ")).toBe("/data-analysis") - }) - - test("packages Skill + user text with single space and trims the user text", () => { - expect(buildHomeOverride("writing-assistant", "hello world")).toBe( - "/writing-assistant hello world", - ) - expect(buildHomeOverride("writing-assistant", " hello world ")).toBe( - "/writing-assistant hello world", - ) - }) - - test("preserves user slash-like text as plain prompt text (Gate 5 is the caller's job)", () => { - expect(buildHomeOverride("document-processing", "/review this")).toBe( - "/document-processing /review this", - ) - }) -}) diff --git a/packages/app/src/components/prompt-input/home-override.ts b/packages/app/src/components/prompt-input/home-override.ts deleted file mode 100644 index a931adca2..000000000 --- a/packages/app/src/components/prompt-input/home-override.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { PawworkSkillName } from "@/components/session/pawwork-skill-meta" - -export function buildHomeOverride( - homeSkill: PawworkSkillName | undefined, - text: string, -): string | undefined { - if (!homeSkill) return undefined - const trimmed = text.trim() - if (trimmed.length === 0) return `/${homeSkill}` - return `/${homeSkill} ${trimmed}` -} diff --git a/packages/app/src/components/prompt-input/placeholder.test.ts b/packages/app/src/components/prompt-input/placeholder.test.ts index b22742afc..5f6aa59e9 100644 --- a/packages/app/src/components/prompt-input/placeholder.test.ts +++ b/packages/app/src/components/prompt-input/placeholder.test.ts @@ -45,70 +45,4 @@ describe("promptPlaceholder", () => { }) expect(value).toBe("prompt.placeholder.simple") }) - - test("selected Skill picks the per-Skill key in normal mode", () => { - expect( - promptPlaceholder({ - mode: "normal", - commentCount: 0, - example: "example", - suggest: true, - selectedSkill: "document-processing", - t, - }), - ).toBe("session.new.placeholder.document") - expect( - promptPlaceholder({ - mode: "normal", - commentCount: 0, - example: "example", - suggest: false, - selectedSkill: "data-analysis", - t, - }), - ).toBe("session.new.placeholder.analysis") - expect( - promptPlaceholder({ - mode: "normal", - commentCount: 0, - example: "example", - suggest: true, - selectedSkill: "writing-assistant", - t, - }), - ).toBe("session.new.placeholder.writing") - }) - - test("selected Skill wins over suggest but loses to shell mode and to comment context", () => { - expect( - promptPlaceholder({ - mode: "shell", - commentCount: 0, - example: "example", - suggest: true, - selectedSkill: "document-processing", - t, - }), - ).toBe("prompt.placeholder.shell") - expect( - promptPlaceholder({ - mode: "normal", - commentCount: 2, - example: "example", - suggest: true, - selectedSkill: "data-analysis", - t, - }), - ).toBe("prompt.placeholder.summarizeComments") - expect( - promptPlaceholder({ - mode: "normal", - commentCount: 1, - example: "example", - suggest: true, - selectedSkill: "data-analysis", - t, - }), - ).toBe("prompt.placeholder.summarizeComment") - }) }) diff --git a/packages/app/src/components/prompt-input/placeholder.ts b/packages/app/src/components/prompt-input/placeholder.ts index 74a197537..395fee51b 100644 --- a/packages/app/src/components/prompt-input/placeholder.ts +++ b/packages/app/src/components/prompt-input/placeholder.ts @@ -1,25 +1,15 @@ -import type { PawworkSkillName } from "@/components/session/pawwork-skill-meta" - type PromptPlaceholderInput = { mode: "normal" | "shell" commentCount: number example: string suggest: boolean - selectedSkill?: PawworkSkillName t: (key: string, params?: Record) => string } -const SKILL_PLACEHOLDER_KEY: Record = { - "document-processing": "session.new.placeholder.document", - "data-analysis": "session.new.placeholder.analysis", - "writing-assistant": "session.new.placeholder.writing", -} - export function promptPlaceholder(input: PromptPlaceholderInput) { if (input.mode === "shell") return input.t("prompt.placeholder.shell") if (input.commentCount > 1) return input.t("prompt.placeholder.summarizeComments") if (input.commentCount === 1) return input.t("prompt.placeholder.summarizeComment") - if (input.selectedSkill) return input.t(SKILL_PLACEHOLDER_KEY[input.selectedSkill]) if (!input.suggest) return input.t("prompt.placeholder.simple") return input.t("prompt.placeholder.normal", { example: input.example }) } diff --git a/packages/app/src/components/prompt-input/readiness.test.ts b/packages/app/src/components/prompt-input/readiness.test.ts index 740be41b7..a93d6c1b8 100644 --- a/packages/app/src/components/prompt-input/readiness.test.ts +++ b/packages/app/src/components/prompt-input/readiness.test.ts @@ -57,7 +57,6 @@ describe("promptSendDisabled", () => { actionReady: false, abortReady: true, blank: true, - selectedSkill: false, }), ).toBe(false) }) @@ -69,7 +68,6 @@ describe("promptSendDisabled", () => { actionReady: false, abortReady: true, blank: false, - selectedSkill: false, }), ).toBe(true) }) diff --git a/packages/app/src/components/prompt-input/readiness.ts b/packages/app/src/components/prompt-input/readiness.ts index 6c73b1260..5f0a92a06 100644 --- a/packages/app/src/components/prompt-input/readiness.ts +++ b/packages/app/src/components/prompt-input/readiness.ts @@ -16,8 +16,7 @@ export function promptSendDisabled(input: { actionReady: boolean abortReady: boolean blank: boolean - selectedSkill: boolean }) { if (input.stopping) return !input.abortReady - return !input.actionReady || (input.blank && !input.selectedSkill) + return !input.actionReady || input.blank } diff --git a/packages/app/src/components/prompt-input/submit.ts b/packages/app/src/components/prompt-input/submit.ts index f395ae9cb..e276da681 100644 --- a/packages/app/src/components/prompt-input/submit.ts +++ b/packages/app/src/components/prompt-input/submit.ts @@ -5,7 +5,6 @@ import { Binary } from "@opencode-ai/util/binary" import { useNavigate, useParams } from "@solidjs/router" import { batch, type Accessor } from "solid-js" import type { FileSelection } from "@/context/file" -import type { PawworkSkillName } from "@/components/session/pawwork-skill-meta" import { useGlobalSync } from "@/context/global-sync" import { useLanguage } from "@/context/language" import { useLayout } from "@/context/layout" @@ -20,7 +19,6 @@ import { Identifier } from "@/utils/id" import { Worktree as WorktreeState } from "@/utils/worktree" import { buildRequestParts } from "./build-request-parts" import { setCursorPosition } from "./editor-dom" -import { buildHomeOverride } from "./home-override" import { formatServerError } from "@/utils/server-errors" import { canSubmitPrompt } from "@/pages/session/session-action-readiness" import { type PromptRouteScope, promptScopeForSession } from "@/pages/session/prompt-route-scope" @@ -43,7 +41,6 @@ export type FollowupDraft = { model: { providerID: string; modelID: string } locale?: string variant?: string - outgoingTextOverride?: string } type FollowupSendInput = { @@ -59,7 +56,7 @@ type FollowupSendInput = { const draftText = (prompt: Prompt) => prompt.map((part) => ("content" in part ? part.content : "")).join("") export function followupCommandText(draft: FollowupDraft) { - return draft.outgoingTextOverride ?? draftText(draft.prompt) + return draftText(draft.prompt) } const draftImages = (prompt: Prompt) => prompt.filter((part): part is ImageAttachmentPart => part.type === "image") @@ -87,7 +84,7 @@ export async function sendFollowupDraft(input: FollowupSendInput) { const [head, ...tail] = text.split(" ") const cmd = head?.startsWith("/") ? head.slice(1) : undefined - if (!input.draft.outgoingTextOverride && cmd && input.sync.data.command.find((item) => item.name === cmd)) { + if (cmd && input.sync.data.command.find((item) => item.name === cmd)) { setBusy() try { if (!(await wait())) { @@ -203,7 +200,6 @@ type PromptSubmitInput = { addToHistory: (prompt: Prompt, mode: "normal" | "shell") => void resetHistoryNavigation: () => void setMode: (mode: "normal" | "shell") => void - selectedSkill?: () => PawworkSkillName | undefined setPopover: (popover: "at" | "slash" | null) => void newSessionWorktree?: Accessor onNewSessionWorktreeReset?: () => void @@ -347,9 +343,8 @@ export function createPromptSubmit(input: PromptSubmitInput) { const images = input.imageAttachments().slice() const mode = input.mode() const creatingNewSession = isNewSession() - const homeSkill = creatingNewSession && mode === "normal" ? input.selectedSkill?.() : undefined - if (text.trim().length === 0 && images.length === 0 && input.commentCount() === 0 && !homeSkill) { + if (text.trim().length === 0 && images.length === 0 && input.commentCount() === 0) { if (input.working()) abort(event instanceof KeyboardEvent ? "emptyEnter" : "stopButton") return } @@ -375,9 +370,7 @@ export function createPromptSubmit(input: PromptSubmitInput) { return } - if (!homeSkill) { - input.addToHistory(currentPrompt, mode) - } + input.addToHistory(currentPrompt, mode) input.resetHistoryNavigation() promptProbe.start() @@ -468,7 +461,6 @@ export function createPromptSubmit(input: PromptSubmitInput) { const locale = language.intl() const agent = creatingNewSession ? "build" : currentAgent!.name const context = prompt.context.items().slice() - const outgoingTextOverride = buildHomeOverride(homeSkill, text) const draft: FollowupDraft = { sessionID: session.id, sessionDirectory, @@ -478,7 +470,6 @@ export function createPromptSubmit(input: PromptSubmitInput) { model, locale, variant, - outgoingTextOverride, } const clearInput = () => { @@ -536,7 +527,7 @@ export function createPromptSubmit(input: PromptSubmitInput) { return } - if (!homeSkill && text.startsWith("/")) { + if (text.startsWith("/")) { const [cmdName, ...args] = text.split(" ") const commandName = cmdName.slice(1) const customCommand = sync.data.command.find((c) => c.name === commandName) diff --git a/packages/app/src/components/session/pawwork-skill-meta.test.ts b/packages/app/src/components/session/pawwork-skill-meta.test.ts deleted file mode 100644 index 9e1e4cebe..000000000 --- a/packages/app/src/components/session/pawwork-skill-meta.test.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { describe, expect, test } from "bun:test" -import { pawworkSkillCards } from "./pawwork-skill-meta" - -describe("pawworkSkillCards", () => { - test("names are document-processing / data-analysis / writing-assistant in this order", () => { - expect(pawworkSkillCards.map((c) => c.name)).toEqual([ - "document-processing", - "data-analysis", - "writing-assistant", - ]) - }) - - test("each card has the fields the home view and sidebar fallback rely on", () => { - for (const card of pawworkSkillCards) { - expect(card).toHaveProperty("iconName") - expect(card).toHaveProperty("homeIcon") - expect(card).toHaveProperty("homeIconClass") - expect(card).toHaveProperty("titleKey") - expect(card).toHaveProperty("descriptionKey") - } - }) -}) diff --git a/packages/app/src/components/session/pawwork-skill-meta.ts b/packages/app/src/components/session/pawwork-skill-meta.ts deleted file mode 100644 index 7d0713311..000000000 --- a/packages/app/src/components/session/pawwork-skill-meta.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { IconProps } from "@opencode-ai/ui/icon" -import type { JSX } from "solid-js" - -type PawworkSkillCard = { - readonly name: "document-processing" | "data-analysis" | "writing-assistant" - readonly iconName: IconProps["name"] - readonly homeIcon: IconProps["name"] - readonly homeIconClass: string - readonly homeIconStyle?: JSX.CSSProperties - readonly titleKey: string - readonly descriptionKey: string -} - -// Writing accent (`#8B5FBF`) lives as inline style because Tailwind v4 is -// configured with `--color-*: initial`, so palette utilities like -// `text-violet-500` resolve to no CSS variable and render black. -export const pawworkSkillCards: readonly PawworkSkillCard[] = [ - { - name: "document-processing", - iconName: "doc-processing", - homeIcon: "doc-processing", - homeIconClass: "text-warning", - titleKey: "session.new.card.document.title", - descriptionKey: "session.new.card.document.description", - }, - { - name: "data-analysis", - iconName: "bar-chart", - homeIcon: "bar-chart", - homeIconClass: "text-icon-success-base", - titleKey: "session.new.card.analysis.title", - descriptionKey: "session.new.card.analysis.description", - }, - { - name: "writing-assistant", - iconName: "pencil-line", - homeIcon: "pencil-line", - homeIconClass: "", - homeIconStyle: { color: "#8B5FBF" }, - titleKey: "session.new.card.writing.title", - descriptionKey: "session.new.card.writing.description", - }, -] - -export type PawworkSkillName = PawworkSkillCard["name"] diff --git a/packages/app/src/components/session/session-new-view.tsx b/packages/app/src/components/session/session-new-view.tsx index e3c622c1b..68093199d 100644 --- a/packages/app/src/components/session/session-new-view.tsx +++ b/packages/app/src/components/session/session-new-view.tsx @@ -1,21 +1,12 @@ -import { Icon } from "@opencode-ai/ui/icon" -import { For, createSignal, Show, type JSX } from "solid-js" +import { Show, type JSX } from "solid-js" import { useLanguage } from "@/context/language" -import { pawworkSkillCards, type PawworkSkillName } from "./pawwork-skill-meta" type ComposerCtx = { onModeChange: (mode: "normal" | "shell") => void - selectedSkill: () => PawworkSkillName | undefined } export function NewSessionView(props: { composer?: (ctx: ComposerCtx) => JSX.Element }) { const language = useLanguage() - const [selectedSkill, setSelectedSkill] = createSignal() - const [mode, setMode] = createSignal<"normal" | "shell">("normal") - - const toggleSkill = (name: PawworkSkillName) => { - setSelectedSkill((prev) => (prev === name ? undefined : name)) - } return (
@@ -24,35 +15,9 @@ export function NewSessionView(props: { composer?: (ctx: ComposerCtx) => JSX.Ele
- {props.composer!({ onModeChange: setMode, selectedSkill })} + {props.composer!({ onModeChange: () => {} })}
- -
- - {(card) => { - const isSelected = () => mode() === "normal" && selectedSkill() === card.name - return ( - - ) - }} - -
) diff --git a/packages/app/src/i18n/en.ts b/packages/app/src/i18n/en.ts index 0b5d14057..5abfe393e 100644 --- a/packages/app/src/i18n/en.ts +++ b/packages/app/src/i18n/en.ts @@ -671,16 +671,6 @@ export const dict = { "session.new.title": "What do you want to do?", "session.new.reassurance": "Files and conversations stay on your computer", - "session.new.card.document.title": "Process docs", - "session.new.card.document.description": "Edit, convert, and extract from Word, Excel, PowerPoint, and PDF files.", - "session.new.card.analysis.title": "Analyze data", - "session.new.card.analysis.description": - "Summarize spreadsheets, build charts, and answer questions from your files.", - "session.new.card.writing.title": "Start writing", - "session.new.card.writing.description": "Draft emails, reports, plans, and polished work copy.", - "session.new.placeholder.document": "Share a document and tell me what to organize, convert, or extract…", - "session.new.placeholder.analysis": "Share your data and tell me what to summarize, chart, or answer…", - "session.new.placeholder.writing": "Tell me what you'd like to write and I'll draft, polish, or rewrite…", "session.new.worktree.main": "Main branch", "session.new.worktree.mainWithBranch": "Main branch ({{branch}})", "session.new.worktree.create": "Create new worktree", diff --git a/packages/app/src/i18n/parity.test.ts b/packages/app/src/i18n/parity.test.ts index 6e1c81efd..4b97e7440 100644 --- a/packages/app/src/i18n/parity.test.ts +++ b/packages/app/src/i18n/parity.test.ts @@ -7,12 +7,6 @@ const keys = [ "command.session.previous.unseen", "command.session.next.unseen", "session.new.title", - "session.new.card.document.title", - "session.new.card.document.description", - "session.new.card.analysis.title", - "session.new.card.analysis.description", - "session.new.card.writing.title", - "session.new.card.writing.description", "session.panel.addTab", "session.panel.utility", "session.panel.files", diff --git a/packages/app/src/i18n/zh.ts b/packages/app/src/i18n/zh.ts index 1f0eae11b..7bdf57d22 100644 --- a/packages/app/src/i18n/zh.ts +++ b/packages/app/src/i18n/zh.ts @@ -625,15 +625,6 @@ export const dict = { "session.revertDock.restore": "恢复消息", "session.new.title": "今天想做什么?", "session.new.reassurance": "文件和对话仅在本机处理", - "session.new.card.document.title": "处理文档", - "session.new.card.document.description": "编辑、转换并提取 Word、Excel、PowerPoint 和 PDF 文件内容。", - "session.new.card.analysis.title": "分析数据", - "session.new.card.analysis.description": "汇总表格、生成图表,并回答文件里的业务问题。", - "session.new.card.writing.title": "开始写作", - "session.new.card.writing.description": "起草邮件、报告、方案和更成熟的工作文案。", - "session.new.placeholder.document": "把文档交给我,告诉我你想要整理、转换或提炼什么…", - "session.new.placeholder.analysis": "把数据交给我,告诉我你想汇总、可视化或回答什么问题…", - "session.new.placeholder.writing": "告诉我你想写什么,我来起草、润色或改写…", "session.new.worktree.main": "主分支", "session.new.worktree.mainWithBranch": "主分支({{branch}})", "session.new.worktree.create": "创建新的工作树", diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index cde9270d3..a9be7dff4 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -5,7 +5,6 @@ import { useLocal } from "@/context/local" import { useFile } from "@/context/file" import { showToast } from "@opencode-ai/ui/toast" import { useLocation, useSearchParams } from "@solidjs/router" -import type { PawworkSkillName } from "@/components/session/pawwork-skill-meta" import { useComments } from "@/context/comments" import { useGlobalSync } from "@/context/global-sync" import { useLanguage } from "@/context/language" @@ -576,7 +575,6 @@ export default function Page() { variant: "session" | "home", ctx?: { onModeChange: (mode: "normal" | "shell") => void - selectedSkill: () => PawworkSkillName | undefined }, ) => ( void onResponseSubmit: () => void onModeChange?: (mode: "normal" | "shell") => void - selectedSkill?: () => PawworkSkillName | undefined displaySessionID?: string displaySessionKey?: string followup?: { @@ -242,7 +240,6 @@ export function SessionComposerRegion(props: { onModeChange={props.onModeChange} actionReady={() => props.actionReady ?? true} abortReady={() => props.abortReady ?? props.actionReady ?? true} - selectedSkill={props.selectedSkill} /> } diff --git a/packages/app/src/pages/session/session-action-readiness.test.ts b/packages/app/src/pages/session/session-action-readiness.test.ts index d5d1114a2..2ed4fc99a 100644 --- a/packages/app/src/pages/session/session-action-readiness.test.ts +++ b/packages/app/src/pages/session/session-action-readiness.test.ts @@ -15,14 +15,13 @@ const slashDraft = { text: "/release now" } const normalDraft = { text: "continue" } const leadingWhitespaceSlashDraft = { text: " /release now" } -const queuedDraft = (input: { prompt: FollowupDraft["prompt"]; outgoingTextOverride?: string }): FollowupDraft => ({ +const queuedDraft = (input: { prompt: FollowupDraft["prompt"] }): FollowupDraft => ({ sessionID: "ses_1", sessionDirectory: "/repo", prompt: input.prompt, context: [], agent: "agent", model: { providerID: "provider", modelID: "model" }, - outgoingTextOverride: input.outgoingTextOverride, }) describe("session action readiness", () => { @@ -66,13 +65,8 @@ describe("session action readiness", () => { { type: "text", content: "/release now", start: 0, end: 12 }, ], }) - const draftWithOverride = queuedDraft({ - prompt: [{ type: "text", content: "normal visible text", start: 0, end: 19 }], - outgoingTextOverride: "/release now", - }) expect(followupCommandText(draftWithLeadingImage)).toBe("/release now") - expect(followupCommandText(draftWithOverride)).toBe("/release now") expect( canSendFollowupDraft({ draft: { text: followupCommandText(draftWithLeadingImage) }, diff --git a/packages/app/src/pages/session/session-composer-region.tsx b/packages/app/src/pages/session/session-composer-region.tsx index b1e75ecd8..0de71fd7f 100644 --- a/packages/app/src/pages/session/session-composer-region.tsx +++ b/packages/app/src/pages/session/session-composer-region.tsx @@ -1,5 +1,4 @@ import type { ComponentProps } from "solid-js" -import type { PawworkSkillName } from "@/components/session/pawwork-skill-meta" import { SessionComposerRegion, type createSessionComposerState } from "@/pages/session/composer" type ComposerRegionProps = ComponentProps @@ -19,7 +18,6 @@ export function SessionPageComposerRegion(props: { onSubmit: () => void onResponseSubmit: () => void onModeChange?: (mode: "normal" | "shell") => void - selectedSkill?: () => PawworkSkillName | undefined followup?: ComposerRegionProps["followup"] revert?: ComposerRegionProps["revert"] setPromptDockRef: (el: HTMLDivElement) => void diff --git a/packages/app/src/pages/session/session-main-view.tsx b/packages/app/src/pages/session/session-main-view.tsx index 1fb18ca8d..989525787 100644 --- a/packages/app/src/pages/session/session-main-view.tsx +++ b/packages/app/src/pages/session/session-main-view.tsx @@ -1,7 +1,6 @@ import { Match, Show, Switch, type ComponentProps, type JSX } from "solid-js" import { Tabs } from "@opencode-ai/ui/tabs" import { NewSessionView, SessionHeader } from "@/components/session" -import type { PawworkSkillName } from "@/components/session/pawwork-skill-meta" import type { useLanguage } from "@/context/language" import type { createSizing } from "@/pages/session/helpers" import { MessageTimeline } from "@/pages/session/message-timeline" @@ -51,7 +50,6 @@ export function SessionMainView(props: { composerSession: JSX.Element composerHome: (ctx: { onModeChange: (mode: "normal" | "shell") => void - selectedSkill: () => PawworkSkillName | undefined }) => JSX.Element canReview: () => boolean reviewDiffs: ReturnType["reviewDiffs"] diff --git a/packages/app/src/pages/session/use-session-followups.test.ts b/packages/app/src/pages/session/use-session-followups.test.ts index 8d9c0433a..fd29c5d15 100644 --- a/packages/app/src/pages/session/use-session-followups.test.ts +++ b/packages/app/src/pages/session/use-session-followups.test.ts @@ -59,7 +59,7 @@ beforeAll(async () => { })) mock.module("@/components/prompt-input/submit", () => ({ followupCommandText: (item: FollowupDraft) => - item.outgoingTextOverride ?? item.prompt.map((part) => ("content" in part ? part.content : "")).join(""), + item.prompt.map((part) => ("content" in part ? part.content : "")).join(""), sendFollowupDraft: (input: unknown) => sendFollowupDraftImpl(input), })) diff --git a/packages/opencode/test/config/e2e-smoke-tagging.test.ts b/packages/opencode/test/config/e2e-smoke-tagging.test.ts index eaf4daf2f..4c3ed2508 100644 --- a/packages/opencode/test/config/e2e-smoke-tagging.test.ts +++ b/packages/opencode/test/config/e2e-smoke-tagging.test.ts @@ -5,8 +5,9 @@ import path from "node:path" const repoRoot = path.resolve(import.meta.dir, "../../../../") const expectedSmokeTests = [ "packages/app/e2e/app/home.spec.ts:@smoke home composer shows unified single-row bar with brand orange send", + "packages/app/e2e/app/home.spec.ts:@smoke home composer submits a slash-prefixed prompt via the fallback path", "packages/app/e2e/app/home.spec.ts:@smoke home hero prompt starts a session", - "packages/app/e2e/app/home.spec.ts:@smoke home renders the hero composer and starter cards", + "packages/app/e2e/app/home.spec.ts:@smoke home renders hero composer without skill-card shortcuts", "packages/app/e2e/app/home.spec.ts:@smoke project home status panel can open the server picker dialog", "packages/app/e2e/app/navigation.spec.ts:@smoke project route redirects to /session", "packages/app/e2e/app/root-redirect.spec.ts:@smoke root route falls back to backend project when local store is empty",