From 4f43cc07491d9e3f99c2c6c9075c8bf47c7ea4f6 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 9 Jul 2026 01:37:29 +0000 Subject: [PATCH] Add starter prompt suggestions to the empty conversation state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Render a row of clickable starter-prompt chips beneath the centered composer on the empty conversation state (only while the composer is empty). Clicking a chip seeds the composer with a fuller prompt via the existing controlled-draft channel and focuses the input — it does not auto-send, so the user can edit before submitting. - New EmptyStateSuggestions component (4 build-oriented suggestions) - Wired into ChatDisplay's empty-state block; hides once the composer has content - 8 new i18n keys across all 7 locales - CDP assertion driving the full path (render -> click -> composer seeded -> suggestions hide) Closes #72 --- .../components/app-shell/ChatDisplay.tsx | 11 ++ .../app-shell/EmptyStateSuggestions.tsx | 80 +++++++++++++ docs/loop/feature-ledger.md | 1 + e2e/assertions/starter-suggestions.assert.ts | 107 ++++++++++++++++++ packages/shared/src/i18n/locales/de.json | 8 ++ packages/shared/src/i18n/locales/en.json | 8 ++ packages/shared/src/i18n/locales/es.json | 8 ++ packages/shared/src/i18n/locales/hu.json | 8 ++ packages/shared/src/i18n/locales/ja.json | 8 ++ packages/shared/src/i18n/locales/pl.json | 8 ++ packages/shared/src/i18n/locales/zh-Hans.json | 8 ++ 11 files changed, 255 insertions(+) create mode 100644 apps/electron/src/renderer/components/app-shell/EmptyStateSuggestions.tsx create mode 100644 e2e/assertions/starter-suggestions.assert.ts diff --git a/apps/electron/src/renderer/components/app-shell/ChatDisplay.tsx b/apps/electron/src/renderer/components/app-shell/ChatDisplay.tsx index 487dfc210..16ab5cedc 100644 --- a/apps/electron/src/renderer/components/app-shell/ChatDisplay.tsx +++ b/apps/electron/src/renderer/components/app-shell/ChatDisplay.tsx @@ -19,6 +19,7 @@ import { toast } from "sonner" import { ScrollArea } from "@/components/ui/scroll-area" import { cn } from "@/lib/utils" +import { EmptyStateSuggestions } from "@/components/app-shell/EmptyStateSuggestions" import { Markdown, CollapsibleMarkdownProvider, StreamingMarkdown, type RenderMode } from "@/components/markdown" import { AnimatedCollapsibleContent } from "@/components/ui/collapsible" import { @@ -1698,6 +1699,16 @@ export const ChatDisplay = React.forwardRef {t('chat.emptyTitle')} {renderChatInputZone('mt-0 px-0 pb-0 @xs/panel:px-0')} + {(inputValue ?? '').trim().length === 0 ? ( + { + onInputChange?.(prompt) + // Let the controlled value propagate to the composer, then focus. + requestAnimationFrame(() => textareaRef.current?.focus()) + }} + /> + ) : null} ) : null} diff --git a/apps/electron/src/renderer/components/app-shell/EmptyStateSuggestions.tsx b/apps/electron/src/renderer/components/app-shell/EmptyStateSuggestions.tsx new file mode 100644 index 000000000..998e21a6f --- /dev/null +++ b/apps/electron/src/renderer/components/app-shell/EmptyStateSuggestions.tsx @@ -0,0 +1,80 @@ +import * as React from 'react' +import { useTranslation } from 'react-i18next' +import { BookOpen, Hammer, Bug, FlaskConical, type LucideIcon } from 'lucide-react' +import { cn } from '@/lib/utils' + +/** + * Starter prompt suggestions shown on the empty conversation state, beneath the + * centered composer. Mirrors the "prompt suggestions" surface in Claude Code + * Desktop / ChatGPT / Codex: a few clickable starting points that populate the + * composer (they do NOT auto-send, so the user can edit before submitting). + * + * Each suggestion pairs a short, localized label with a fuller prompt. Clicking + * one calls `onSelect(prompt)` — the parent seeds the (controlled) composer via + * the same draft channel used elsewhere, then focuses the input. + */ + +interface SuggestionDef { + /** Stable id → i18n keys `chat.suggestions..title` / `.prompt`. */ + id: string + icon: LucideIcon +} + +/** The fixed set of starter suggestions. Order here is the render order. */ +const SUGGESTIONS: readonly SuggestionDef[] = [ + { id: 'explain', icon: BookOpen }, + { id: 'build', icon: Hammer }, + { id: 'fix', icon: Bug }, + { id: 'tests', icon: FlaskConical }, +] as const + +export interface EmptyStateSuggestionsProps { + /** Called with the full prompt text when a suggestion is chosen. */ + onSelect: (prompt: string) => void + /** Hide the surface entirely (e.g. no connection / input disabled). */ + disabled?: boolean + className?: string +} + +export function EmptyStateSuggestions({ + onSelect, + disabled = false, + className, +}: EmptyStateSuggestionsProps) { + const { t } = useTranslation() + + if (disabled) return null + + return ( +
+ {SUGGESTIONS.map(({ id, icon: Icon }) => { + const title = t(`chat.suggestions.${id}.title`) + const prompt = t(`chat.suggestions.${id}.prompt`) + return ( + + ) + })} +
+ ) +} diff --git a/docs/loop/feature-ledger.md b/docs/loop/feature-ledger.md index d9d86cc61..5d79c3d4a 100644 --- a/docs/loop/feature-ledger.md +++ b/docs/loop/feature-ledger.md @@ -33,6 +33,7 @@ log, not the system of record. | slug | title | source | feasibility | status | issue | pr | branch | updated | notes | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| starter-suggestions | Starter prompt suggestions on the empty conversation | Claude Code Desktop "prompt suggestions" / ChatGPT & Codex example prompts | frontend-only | pr-open | [#72](https://github.com/modelstudioai/openwork/issues/72) | [#73](https://github.com/modelstudioai/openwork/pull/73) | loop/starter-suggestions | 2026-07-09 | New `EmptyStateSuggestions` chip row rendered under the centered empty-state composer in `ChatDisplay` (only while composer is empty). Clicking a chip seeds the composer via the existing controlled draft channel (`onInputChange`) + focuses it — does NOT auto-send. 4 suggestions, 8 new i18n keys ×7 locales. typecheck:all / `bun test` zero-delta vs main (11 electron-typecheck + 56-test pre-existing baseline byte-identical); renderer build ✅; i18n parity ✅; lint 0 errors on touched files. CDP assertion `e2e/assertions/starter-suggestions.assert.ts` included; **could not execute locally** (Electron binary egress-blocked: `github.com` releases 403). | | interface-zoom | Interface zoom (⌘+/⌘-/⌘0) to scale the whole app | Claude Desktop / VS Code / Codex desktop View→Zoom In/Out/Actual Size | frontend-only | pr-open | [#68](https://github.com/modelstudioai/openwork/issues/68) | [#69](https://github.com/modelstudioai/openwork/pull/69) | loop/interface-zoom | 2026-07-08 | New `ZoomProvider` (mirrors `ReduceMotionProvider`) scales whole renderer via `document.documentElement.style.zoom`, discrete 50–200% steps, persisted in localStorage (`craft-zoom-level`). 3 View actions `view.zoomIn/Out/Reset` (`mod+=`/`mod+-`/`mod+0`) → auto in Command Palette + Shortcuts ref, wired via `ZoomHotkeys` bridge. Stepper in Appearance→Interface. 5 i18n keys ×7 locales. typecheck/`bun test` zero-delta vs main (56-failure set byte-identical); renderer build ✅; lint 0 errors; i18n parity ✅ (1549 keys). CDP assertion included; **could not run locally** (org egress 403 on Electron binary download — same block as #51). Distinct from chat-text-size (#64)/conversation-width (#62): scales entire UI, not just chat text. | | high-contrast | "Increase contrast" accessibility setting in Appearance | macOS Accessibility "Increase contrast" / Windows contrast themes / VS Code High Contrast | frontend-only | pr-open | [#66](https://github.com/modelstudioai/openwork/issues/66) | [#67](https://github.com/modelstudioai/openwork/pull/67) | loop/high-contrast | 2026-07-07 | Companion to merged reduce-motion. Renderer-only pref (`craft-high-contrast` localStorage) → `HighContrastProvider` context → `data-high-contrast` on `` → CSS overrides of theme tokens (`--border`/`--input`/`--muted-foreground`/`--ring`) gated on `:root[data-high-contrast='true']` (higher specificity beats theme `:root` injection; works light+dark since tokens derive from `--foreground`). Toggle in Appearance→Interface below Reduce motion; 2 i18n keys ×7 locales. typecheck:all/`bun test` zero-delta vs main (11 electron / 56 test pre-existing failures byte-identical); i18n parity OK; renderer build ✅ (verified rule in bundled CSS). CDP assertion written (`high-contrast.assert.ts`); **not run locally** — egress 403 blocks Electron binary download (same env block as #51). | | chat-text-size | "Chat text size" setting (Small / Default / Large) in Appearance | Claude Desktop "Chat font" + anthropics/claude-code #50543/#48887; ChatGPT desktop font-size requests | frontend-only | pr-open | [#64](https://github.com/modelstudioai/openwork/issues/64) | [#65](https://github.com/modelstudioai/openwork/pull/65) | loop/chat-text-size | 2026-07-07 | Renderer-only pref (localStorage `craft-chat-text-size`) reflected onto `` as `data-chat-text-size` + `--chat-font-scale` CSS var (0.9/1/1.15). Transcript container gets `.chat-text-scope` with `font-size: calc(1em * var(--chat-font-scale))` — em-relative ⇒ neutral at Default, scales only conversation text (chrome untouched). New `ChatTextSizeProvider`; segmented control in Appearance→Interface; `SettingsSegmentedControl` gained optional `testId`/`data-value`; 5 new i18n keys ×7 locales. typecheck/`bun test` **zero-delta vs main** (11 pre-existing tsc errors + 56 pre-existing fail-lines byte-identical); renderer build ✅; i18n parity ✅. CDP assertion authored (drives control, asserts attr/CSS-var/localStorage + probe computed font-size ratio ~1.15/0.9); **could not execute** — Electron runtime binary download is org-egress-policy 403 (same block as #51). | diff --git a/e2e/assertions/starter-suggestions.assert.ts b/e2e/assertions/starter-suggestions.assert.ts new file mode 100644 index 000000000..329ea8b4a --- /dev/null +++ b/e2e/assertions/starter-suggestions.assert.ts @@ -0,0 +1,107 @@ +/** + * Feature assertion: starter prompt suggestions on the empty conversation state. + * + * Drives the real built app over CDP through the full path: + * boot into the empty draft chat → the suggestion chips render → click one → + * the composer is populated with that suggestion's (fuller) prompt → the + * suggestions surface disappears once the composer has content. + * + * This proves the feature actually *does* something (seeds the composer), not + * merely that the chips render. + */ + +import type { Assertion } from '../runner'; + +const SUGGESTIONS = '[data-testid="empty-suggestions"]'; +const CHIP = '[data-testid="empty-suggestion"]'; +const COMPOSER = '[role="textbox"][aria-multiline="true"]'; + +/** Visible chips only (defensive against hidden/duplicated nodes). */ +const VISIBLE_CHIPS_EXPR = `[...document.querySelectorAll(${JSON.stringify( + CHIP, +)})].filter((el) => el.offsetParent !== null)`; + +/** Trimmed text of the (visible) composer, with zero-width chars stripped. */ +const COMPOSER_TEXT_EXPR = `(() => { + const el = [...document.querySelectorAll(${JSON.stringify( + COMPOSER, + )})].find((n) => n.offsetParent !== null); + if (!el) return null; + return (el.textContent || '').replace(/[\\u200B-\\u200D\\uFEFF]/g, '').trim(); +})()`; + +const assertion: Assertion = { + name: 'empty-state starter suggestions seed the composer', + async run(app) { + const { session } = app; + + // App fully mounted. + await session.waitForFunction( + '!document.getElementById("_loader") && (document.getElementById("root")?.childElementCount ?? 0) > 0', + { timeoutMs: 30000, message: 'React UI did not mount' }, + ); + + // Reach the ready AppShell (not onboarding / workspace-picker). The empty + // draft chat — with its centered composer — is the default landing view. + await session.waitForSelector('[aria-label="Craft menu"]', { + timeoutMs: 30000, + message: 'app did not reach the ready AppShell state', + }); + + // 1. The suggestions surface renders on the empty conversation. + await session.waitForSelector(SUGGESTIONS, { + timeoutMs: 15000, + message: 'starter suggestions did not render on the empty conversation', + }); + + // 2. It shows the full set of chips (4). + await session.waitForFunction(`${VISIBLE_CHIPS_EXPR}.length === 4`, { + timeoutMs: 8000, + message: 'expected 4 visible starter-suggestion chips', + }); + + // 3. The composer starts empty. + const before = await session.evaluate(COMPOSER_TEXT_EXPR); + if (before == null) throw new Error('could not locate the composer text box'); + if (before.length !== 0) { + throw new Error(`composer was not empty at start (saw: ${JSON.stringify(before)})`); + } + + // 4. Capture the first chip's visible label, then click it. + const label = await session.evaluate( + `(() => { const el = ${VISIBLE_CHIPS_EXPR}[0]; return el ? (el.textContent || '').trim() : null; })()`, + ); + if (!label) throw new Error('could not read the first suggestion label'); + + const clicked = await session.evaluate( + `(() => { const el = ${VISIBLE_CHIPS_EXPR}[0]; if (!el) return false; el.click(); return true; })()`, + ); + if (!clicked) throw new Error('failed to click the first suggestion chip'); + + // 5. The composer is populated with the suggestion's prompt. The prompt is a + // full sentence, so it must be non-empty and longer than the short label — + // proving it seeded the *prompt*, not merely echoed the chip title. + await session.waitForFunction( + `(() => { + const text = ${COMPOSER_TEXT_EXPR}; + return typeof text === 'string' && text.length > ${label.length} && text.length > 20; + })()`, + { + timeoutMs: 8000, + message: 'clicking a suggestion did not populate the composer with its prompt', + }, + ); + + // 6. Once the composer has content, the suggestions surface goes away + // (matching the empty-state-only behavior of the feature). + await session.waitForFunction( + `!document.querySelector(${JSON.stringify(SUGGESTIONS)})`, + { + timeoutMs: 8000, + message: 'suggestions did not hide after the composer was populated', + }, + ); + }, +}; + +export default assertion; diff --git a/packages/shared/src/i18n/locales/de.json b/packages/shared/src/i18n/locales/de.json index 17c5a3667..4d9aafac6 100644 --- a/packages/shared/src/i18n/locales/de.json +++ b/packages/shared/src/i18n/locales/de.json @@ -145,6 +145,14 @@ "chat.contextUsage.title": "Kontextfenster", "chat.contextUsage.usedOfTotal": "{{used}} verwendet, {{total}} gesamt", "chat.emptyTitle": "Was sollen wir bauen?", + "chat.suggestions.explain.title": "Diese Codebasis erklären", + "chat.suggestions.explain.prompt": "Gib mir einen Überblick über diese Codebasis – ihren Zweck, die wichtigsten Komponenten und wie die Teile zusammenspielen.", + "chat.suggestions.build.title": "Ein Feature bauen", + "chat.suggestions.build.prompt": "Hilf mir, ein neues Feature zu bauen. Frag mich, was es können soll, schlage dann einen Ansatz vor und setze ihn um.", + "chat.suggestions.fix.title": "Einen Bug beheben", + "chat.suggestions.fix.prompt": "Hilf mir, einen Bug zu finden und zu beheben. Ich beschreibe das Problem und du untersuchst den relevanten Code.", + "chat.suggestions.tests.title": "Tests schreiben", + "chat.suggestions.tests.prompt": "Schreibe Tests für einen Teil meines Projekts. Sag mir, was abzudecken ist, und füge gründliche, bestehende Tests hinzu.", "chat.enterSessionName": "Sitzungsname eingeben...", "chat.expandComposer": "Editor vergrößern", "chat.failedToStopSharing": "Freigabe konnte nicht beendet werden", diff --git a/packages/shared/src/i18n/locales/en.json b/packages/shared/src/i18n/locales/en.json index 9387fb9f6..9257bd253 100644 --- a/packages/shared/src/i18n/locales/en.json +++ b/packages/shared/src/i18n/locales/en.json @@ -145,6 +145,14 @@ "chat.contextUsage.title": "Context window", "chat.contextUsage.usedOfTotal": "{{used}} used, {{total}} total", "chat.emptyTitle": "What should we build?", + "chat.suggestions.explain.title": "Explain this codebase", + "chat.suggestions.explain.prompt": "Give me a high-level overview of this codebase — its purpose, main components, and how the pieces fit together.", + "chat.suggestions.build.title": "Build a feature", + "chat.suggestions.build.prompt": "Help me build a new feature. Ask me what it should do, then propose an approach and implement it.", + "chat.suggestions.fix.title": "Fix a bug", + "chat.suggestions.fix.prompt": "Help me track down and fix a bug. I'll describe what's going wrong and you investigate the relevant code.", + "chat.suggestions.tests.title": "Write tests", + "chat.suggestions.tests.prompt": "Write tests for a part of my project. Point me at what to cover and add thorough, passing tests.", "chat.enterSessionName": "Enter session name...", "chat.expandComposer": "Expand composer", "chat.failedToStopSharing": "Failed to stop sharing", diff --git a/packages/shared/src/i18n/locales/es.json b/packages/shared/src/i18n/locales/es.json index d7e5bbef6..cb29839b4 100644 --- a/packages/shared/src/i18n/locales/es.json +++ b/packages/shared/src/i18n/locales/es.json @@ -145,6 +145,14 @@ "chat.contextUsage.title": "Ventana de contexto", "chat.contextUsage.usedOfTotal": "{{used}} usados, {{total}} en total", "chat.emptyTitle": "¿Qué deberíamos construir?", + "chat.suggestions.explain.title": "Explicar este código", + "chat.suggestions.explain.prompt": "Dame una visión general de este código: su propósito, sus componentes principales y cómo encajan las piezas.", + "chat.suggestions.build.title": "Crear una función", + "chat.suggestions.build.prompt": "Ayúdame a crear una nueva función. Pregúntame qué debe hacer, propón un enfoque e impleméntalo.", + "chat.suggestions.fix.title": "Corregir un error", + "chat.suggestions.fix.prompt": "Ayúdame a localizar y corregir un error. Yo describo qué falla y tú investigas el código relevante.", + "chat.suggestions.tests.title": "Escribir pruebas", + "chat.suggestions.tests.prompt": "Escribe pruebas para una parte de mi proyecto. Indícame qué cubrir y añade pruebas completas que pasen.", "chat.enterSessionName": "Introduce el nombre de la sesión...", "chat.expandComposer": "Ampliar el editor", "chat.failedToStopSharing": "Error al detener la compartición", diff --git a/packages/shared/src/i18n/locales/hu.json b/packages/shared/src/i18n/locales/hu.json index 6fc2c48f8..8cb7c9802 100644 --- a/packages/shared/src/i18n/locales/hu.json +++ b/packages/shared/src/i18n/locales/hu.json @@ -145,6 +145,14 @@ "chat.contextUsage.title": "Kontextusablak", "chat.contextUsage.usedOfTotal": "{{used}} felhasználva, összesen {{total}}", "chat.emptyTitle": "Mit építsünk?", + "chat.suggestions.explain.title": "Kódbázis bemutatása", + "chat.suggestions.explain.prompt": "Adj áttekintést erről a kódbázisról – a céljáról, a fő komponenseiről, és arról, hogyan illeszkednek össze a részek.", + "chat.suggestions.build.title": "Funkció létrehozása", + "chat.suggestions.build.prompt": "Segíts egy új funkció elkészítésében. Kérdezd meg, mit kell csinálnia, majd javasolj megközelítést és valósítsd meg.", + "chat.suggestions.fix.title": "Hiba javítása", + "chat.suggestions.fix.prompt": "Segíts megtalálni és kijavítani egy hibát. Leírom, mi a probléma, te pedig vizsgáld meg az érintett kódot.", + "chat.suggestions.tests.title": "Tesztek írása", + "chat.suggestions.tests.prompt": "Írj teszteket a projektem egy részéhez. Mondd meg, mit fedjek le, és adj hozzá alapos, sikeresen lefutó teszteket.", "chat.enterSessionName": "Add meg a munkamenet nevét...", "chat.expandComposer": "Szerkesztő kibontása", "chat.failedToStopSharing": "A megosztás leállítása sikertelen", diff --git a/packages/shared/src/i18n/locales/ja.json b/packages/shared/src/i18n/locales/ja.json index efd83d76f..6403e4f48 100644 --- a/packages/shared/src/i18n/locales/ja.json +++ b/packages/shared/src/i18n/locales/ja.json @@ -145,6 +145,14 @@ "chat.contextUsage.title": "コンテキストウィンドウ", "chat.contextUsage.usedOfTotal": "{{used}} 使用済み、合計 {{total}}", "chat.emptyTitle": "何を構築しましょうか?", + "chat.suggestions.explain.title": "このコードベースを解説する", + "chat.suggestions.explain.prompt": "このコードベースの概要を教えてください。目的、主要なコンポーネント、そして各部分がどう組み合わさっているかを説明してください。", + "chat.suggestions.build.title": "機能を作る", + "chat.suggestions.build.prompt": "新しい機能の実装を手伝ってください。まず何をするべきか確認し、方針を提案してから実装してください。", + "chat.suggestions.fix.title": "バグを修正する", + "chat.suggestions.fix.prompt": "バグの特定と修正を手伝ってください。症状を説明するので、関連するコードを調査してください。", + "chat.suggestions.tests.title": "テストを書く", + "chat.suggestions.tests.prompt": "プロジェクトの一部にテストを追加してください。カバーすべき範囲を伝えるので、網羅的でパスするテストを書いてください。", "chat.enterSessionName": "セッション名を入力...", "chat.expandComposer": "エディターを拡大", "chat.failedToStopSharing": "共有の停止に失敗しました", diff --git a/packages/shared/src/i18n/locales/pl.json b/packages/shared/src/i18n/locales/pl.json index d792904ad..dd286ddac 100644 --- a/packages/shared/src/i18n/locales/pl.json +++ b/packages/shared/src/i18n/locales/pl.json @@ -145,6 +145,14 @@ "chat.contextUsage.title": "Okno kontekstu", "chat.contextUsage.usedOfTotal": "Użyto {{used}}, łącznie {{total}}", "chat.emptyTitle": "Co powinniśmy zbudować?", + "chat.suggestions.explain.title": "Wyjaśnij tę bazę kodu", + "chat.suggestions.explain.prompt": "Przedstaw mi ogólny obraz tej bazy kodu — jej cel, główne komponenty i to, jak elementy do siebie pasują.", + "chat.suggestions.build.title": "Zbuduj funkcję", + "chat.suggestions.build.prompt": "Pomóż mi zbudować nową funkcję. Zapytaj, co ma robić, a następnie zaproponuj podejście i je wdróż.", + "chat.suggestions.fix.title": "Napraw błąd", + "chat.suggestions.fix.prompt": "Pomóż mi znaleźć i naprawić błąd. Opiszę, co jest nie tak, a ty zbadaj odpowiedni kod.", + "chat.suggestions.tests.title": "Napisz testy", + "chat.suggestions.tests.prompt": "Napisz testy dla części mojego projektu. Wskaż, co pokryć, i dodaj dokładne, przechodzące testy.", "chat.enterSessionName": "Wprowadź nazwę sesji...", "chat.expandComposer": "Rozwiń edytor", "chat.failedToStopSharing": "Nie udało się zatrzymać udostępniania", diff --git a/packages/shared/src/i18n/locales/zh-Hans.json b/packages/shared/src/i18n/locales/zh-Hans.json index 127b6c2c8..2c1c4f4d1 100644 --- a/packages/shared/src/i18n/locales/zh-Hans.json +++ b/packages/shared/src/i18n/locales/zh-Hans.json @@ -145,6 +145,14 @@ "chat.contextUsage.title": "上下文窗口", "chat.contextUsage.usedOfTotal": "已用 {{used}},共 {{total}}", "chat.emptyTitle": "我们该构建什么", + "chat.suggestions.explain.title": "解读这个代码库", + "chat.suggestions.explain.prompt": "请从整体上介绍这个代码库——它的用途、主要组成部分,以及各部分如何协同工作。", + "chat.suggestions.build.title": "构建一个功能", + "chat.suggestions.build.prompt": "帮我构建一个新功能。先问清楚它需要做什么,然后提出方案并实现它。", + "chat.suggestions.fix.title": "修复一个 Bug", + "chat.suggestions.fix.prompt": "帮我定位并修复一个 Bug。我来描述出现的问题,你负责排查相关代码。", + "chat.suggestions.tests.title": "编写测试", + "chat.suggestions.tests.prompt": "为我项目的某个部分编写测试。告诉我需要覆盖的范围,并补充完整且能通过的测试。", "chat.enterSessionName": "输入会话名称...", "chat.expandComposer": "展开输入框", "chat.failedToStopSharing": "无法停止共享",