mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-24 16:02:55 +08:00
Merge pull request #9331 from Kilo-Org/docs/generated-screenshot-refs
Reference generated screenshots in docs
This commit is contained in:
@@ -30,6 +30,12 @@ Use the Markdoc image tag format:
|
||||
|
||||
Note that this site is served under kilo.ai/docs so the `/docs` prefix **must** be present in every image path.
|
||||
|
||||
#### Generated screenshots
|
||||
|
||||
When updating screenshots for active docs pages, prefer generated screenshot-test assets from `packages/kilo-docs/public/img/screenshot-tests/` and reference them as `/docs/img/screenshot-tests/...`. Only replace a hand-captured image when the generated screenshot matches the docs content closely. Do not replace screenshots in VSCode Legacy docs tabs or sections.
|
||||
|
||||
If a docs page references a generated VS Code visual-regression screenshot, record that usage in `packages/kilo-vscode/tests/visual-regression.spec.ts` by adding the story ID to the `DOCS` map. Keep `packages/kilo-vscode/tests/visual-regression.spec.mts` in sync while that file exists. If no matching generated screenshot exists, add or update a Storybook story in `packages/kilo-vscode/webview-ui/src/stories/` and let visual-regression CI generate the baseline.
|
||||
|
||||
Image attributes:
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
|
||||
@@ -9,7 +9,7 @@ description: "Track and manage tasks with AI-generated todo lists"
|
||||
|
||||
**Why it matters**: Complex workflows have lots of moving parts. Without structure, it's easy to miss steps, duplicate work, or forget what comes next.
|
||||
|
||||
{% image src="/docs/img/task-todo-list/task-todo-list-1.png" alt="Task Todo List overview showing interactive checklist in Kilo Code" width="500" /%}
|
||||
{% image src="/docs/img/screenshot-tests/kilo-vscode/visual-regression/composite-webview/todo-write-docs-overview-chromium-linux.png" alt="Task Todo List overview showing interactive checklist in Kilo Code" width="420" /%}
|
||||
|
||||
## How to trigger todo lists
|
||||
|
||||
@@ -53,7 +53,7 @@ Kilo updates the list when:
|
||||
**1. Task Header Summary**
|
||||
Quick progress overview with your next important item
|
||||
|
||||
{% image src="/docs/img/task-todo-list/task-header.png" alt="Task header summary showing todo list progress" width="500" /%}
|
||||
{% image src="/docs/img/screenshot-tests/kilo-vscode/visual-regression/chat/task-header-with-todos-chromium-linux.png" alt="Task header summary showing todo list progress" width="420" /%}
|
||||
|
||||
Click the task header summary to expand the full list inline and jump to the current item.
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ platform: new
|
||||
|
||||
Workflows (also called **slash commands** in the new extension) automate repetitive tasks by defining step-by-step instructions for Kilo Code to execute.
|
||||
|
||||
{% image src="/docs/img/slash-commands/workflows.png" alt="Workflows tab in Kilo Code" width="600" caption="Workflows tab in Kilo Code" /%}
|
||||
{% image src="/docs/img/screenshot-tests/kilo-vscode/visual-regression/settings/agent-behaviour-workflows-chromium-linux.png" alt="Workflows tab in Kilo Code" width="420" caption="Workflows tab in Kilo Code" /%}
|
||||
|
||||
## Creating Workflows
|
||||
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5ab73f8c0585e9f889c51073428aa0e7082d7aecdc3d5b0c459720c1b860c436
|
||||
size 4890
|
||||
oid sha256:d34153690f8aa4ef7e06e12385a184c151843f3ae75a9955619a6d7e88dc8c8b
|
||||
size 7981
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d4d7ac9d6322d2cf673a6353cb07cf9979ad55351769ba9d90eed386170f6c42
|
||||
size 40854
|
||||
@@ -186,6 +186,12 @@ New webview features must use **`@kilocode/kilo-ui`** components instead of raw
|
||||
- **Prefer kilo-ui styles**: Always reuse existing kilo-ui CSS variables, tokens, and component styles instead of writing custom CSS. If a style doesn't exist in kilo-ui yet, add it there and reuse it rather than inlining or duplicating styles in the webview.
|
||||
- **Icons**: kilo-ui has 75+ custom SVG icons in [`packages/ui/src/components/icon.tsx`](../../packages/ui/src/components/icon.tsx). To list all available icon names: `node -e "const c=require('fs').readFileSync('../../packages/ui/src/components/icon.tsx','utf8');[...c.matchAll(/^\\s{2}[\"']?([\\w-]+)[\"']?:\\s*\x60/gm)].map(m=>m[1]).sort().forEach(n=>console.log(n))"`. Icon names use both hyphenated (`arrow-left`) and bare-word (`brain`, `console`, `providers`) keys.
|
||||
|
||||
## Docs Screenshot Stories
|
||||
|
||||
When adding or updating Storybook stories for screenshots used by docs, make the story content match the docs page closely before replacing the docs image. Do not replace screenshots from VSCode Legacy docs tabs or sections.
|
||||
|
||||
Generated screenshot baselines live under `packages/kilo-docs/public/img/screenshot-tests/` and are referenced from docs as `/docs/img/screenshot-tests/...`. If a generated VS Code visual-regression screenshot is used in docs, add the docs usage to the `DOCS` map in `tests/visual-regression.spec.ts` and keep `tests/visual-regression.spec.mts` in sync while that file exists.
|
||||
|
||||
## Debugging
|
||||
|
||||
- Extension logs: "Extension Host" output channel (not Debug Console)
|
||||
|
||||
@@ -53,6 +53,27 @@ const SKIP = new Set<string>([
|
||||
"composite-webview--permission-dock-config-preloaded",
|
||||
])
|
||||
|
||||
const DOCS = new Map<string, string[]>([
|
||||
[
|
||||
"chat--task-header-with-todos",
|
||||
[
|
||||
"packages/kilo-docs/pages/code-with-ai/features/task-todo-list.md:/docs/img/screenshot-tests/kilo-vscode/visual-regression/chat/task-header-with-todos-chromium-linux.png",
|
||||
],
|
||||
],
|
||||
[
|
||||
"composite-webview--todo-write-docs-overview",
|
||||
[
|
||||
"packages/kilo-docs/pages/code-with-ai/features/task-todo-list.md:/docs/img/screenshot-tests/kilo-vscode/visual-regression/composite-webview/todo-write-docs-overview-chromium-linux.png",
|
||||
],
|
||||
],
|
||||
[
|
||||
"settings--agent-behaviour-workflows",
|
||||
[
|
||||
"packages/kilo-docs/pages/customize/workflows.md:/docs/img/screenshot-tests/kilo-vscode/visual-regression/settings/agent-behaviour-workflows-chromium-linux.png",
|
||||
],
|
||||
],
|
||||
])
|
||||
|
||||
// Generate one test() per story so Playwright's scheduler can distribute
|
||||
// them freely across workers — no manual sharding needed.
|
||||
// Skip fetching stories on macOS since test.skip() above already marks the file skipped.
|
||||
@@ -60,6 +81,10 @@ const stories = IS_DARWIN ? [] : (await fetchStories()).filter((s) => !SKIP.has(
|
||||
|
||||
for (const story of stories) {
|
||||
test(`${story.title} / ${story.name}`, async ({ page }) => {
|
||||
for (const ref of DOCS.get(story.id) ?? []) {
|
||||
test.info().annotations.push({ type: "docs", description: ref })
|
||||
}
|
||||
|
||||
// Narrow stories (IDs ending in "-200") use a 200px viewport
|
||||
// The "-200" suffix comes from the export name convention (e.g. Default200, WithThinking200)
|
||||
const narrow = story.id.endsWith("-200")
|
||||
@@ -74,6 +99,6 @@ for (const story of stories) {
|
||||
|
||||
const [component, variant] = story.id.split("--")
|
||||
const root = page.locator("#storybook-root")
|
||||
await expect(root).toHaveScreenshot(["visual-regression", component!, `${variant}.png`])
|
||||
await expect(root).toHaveScreenshot(["visual-regression", component!, `${variant}-chromium-linux.png`])
|
||||
})
|
||||
}
|
||||
|
||||
@@ -54,6 +54,27 @@ const SKIP = new Set<string>([
|
||||
"composite-webview--permission-dock-config-preloaded",
|
||||
])
|
||||
|
||||
const DOCS = new Map<string, string[]>([
|
||||
[
|
||||
"chat--task-header-with-todos",
|
||||
[
|
||||
"packages/kilo-docs/pages/code-with-ai/features/task-todo-list.md:/docs/img/screenshot-tests/kilo-vscode/visual-regression/chat/task-header-with-todos-chromium-linux.png",
|
||||
],
|
||||
],
|
||||
[
|
||||
"composite-webview--todo-write-docs-overview",
|
||||
[
|
||||
"packages/kilo-docs/pages/code-with-ai/features/task-todo-list.md:/docs/img/screenshot-tests/kilo-vscode/visual-regression/composite-webview/todo-write-docs-overview-chromium-linux.png",
|
||||
],
|
||||
],
|
||||
[
|
||||
"settings--agent-behaviour-workflows",
|
||||
[
|
||||
"packages/kilo-docs/pages/customize/workflows.md:/docs/img/screenshot-tests/kilo-vscode/visual-regression/settings/agent-behaviour-workflows-chromium-linux.png",
|
||||
],
|
||||
],
|
||||
])
|
||||
|
||||
// Generate one test() per story so Playwright's scheduler can distribute
|
||||
// them freely across workers — no manual sharding needed.
|
||||
// Skip fetching stories on macOS since test.skip() above already marks the file skipped.
|
||||
@@ -61,6 +82,10 @@ const stories = IS_DARWIN ? [] : (await fetchStories()).filter((s) => !SKIP.has(
|
||||
|
||||
for (const story of stories) {
|
||||
test(`${story.title} / ${story.name}`, async ({ page }) => {
|
||||
for (const ref of DOCS.get(story.id) ?? []) {
|
||||
test.info().annotations.push({ type: "docs", description: ref })
|
||||
}
|
||||
|
||||
// Narrow stories (IDs ending in "-200") use a 200px viewport
|
||||
const narrow = story.id.endsWith("-200")
|
||||
await page.setViewportSize({ width: narrow ? 200 : 420, height: 720 })
|
||||
@@ -74,6 +99,6 @@ for (const story of stories) {
|
||||
|
||||
const [component, variant] = story.id.split("--")
|
||||
const root = page.locator("#storybook-root")
|
||||
await expect(root).toHaveScreenshot(["visual-regression", component!, `${variant!}.png`])
|
||||
await expect(root).toHaveScreenshot(["visual-regression", component!, `${variant!}-chromium-linux.png`])
|
||||
})
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ const MOCK_PROVIDERS = {
|
||||
name: "Anthropic: Claude Sonnet 4.6",
|
||||
inputPrice: 0.003,
|
||||
outputPrice: 0.015,
|
||||
limit: { context: 200000, output: 8192 },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -16,7 +16,7 @@ import { SuggestBar } from "../components/chat/SuggestBar"
|
||||
import { MessageList } from "../components/chat/MessageList"
|
||||
import { SessionContext } from "../context/session"
|
||||
import { ServerContext } from "../context/server"
|
||||
import type { QuestionRequest, SuggestionRequest, TodoItem } from "../types/messages"
|
||||
import type { Message, Part, QuestionRequest, SuggestionRequest, TodoItem } from "../types/messages"
|
||||
|
||||
const SESSION_ID = "story-session-chat-001"
|
||||
|
||||
@@ -449,10 +449,141 @@ export const MessageListSubagentToQueuedUserSpacing: Story = {
|
||||
// TaskHeader with todos
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const headerNow = 1_700_000_000_000
|
||||
const headerUserID = "user-task-header-001"
|
||||
const headerAssistantID = "asst-task-header-001"
|
||||
const headerMessages: Message[] = [
|
||||
{
|
||||
id: headerUserID,
|
||||
sessionID: SESSION_ID,
|
||||
role: "user",
|
||||
content: "Can you use the update_todo_list tool to create a CLI interface implementation plan?",
|
||||
createdAt: new Date(headerNow - 12000).toISOString(),
|
||||
time: { created: headerNow - 12000 },
|
||||
},
|
||||
{
|
||||
id: headerAssistantID,
|
||||
sessionID: SESSION_ID,
|
||||
role: "assistant",
|
||||
parentID: headerUserID,
|
||||
content: "I'll track the CLI interface implementation with a todo list.",
|
||||
createdAt: new Date(headerNow - 10000).toISOString(),
|
||||
time: { created: headerNow - 10000 },
|
||||
modelID: "anthropic/claude-sonnet-4-6",
|
||||
providerID: "kilo",
|
||||
mode: "default",
|
||||
agent: "code",
|
||||
path: { cwd: "/project", root: "/project" },
|
||||
},
|
||||
]
|
||||
const headerParts: Record<string, Part[]> = {
|
||||
[headerAssistantID]: [
|
||||
{
|
||||
id: "part-header-read-001",
|
||||
sessionID: SESSION_ID,
|
||||
messageID: headerAssistantID,
|
||||
type: "tool",
|
||||
tool: "read",
|
||||
state: {
|
||||
status: "completed",
|
||||
input: { filePath: "packages/opencode/src/cli/index.ts" },
|
||||
output: "export async function main() { /* existing CLI bootstrap */ }",
|
||||
title: "Read CLI entrypoint",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "part-header-text-001",
|
||||
sessionID: SESSION_ID,
|
||||
messageID: headerAssistantID,
|
||||
type: "text",
|
||||
text: "I found the existing command registration and argument parsing flow.",
|
||||
},
|
||||
{
|
||||
id: "part-header-glob-001",
|
||||
sessionID: SESSION_ID,
|
||||
messageID: headerAssistantID,
|
||||
type: "tool",
|
||||
tool: "glob",
|
||||
state: {
|
||||
status: "completed",
|
||||
input: { pattern: "packages/opencode/src/**/*.ts" },
|
||||
output:
|
||||
"packages/opencode/src/cli/index.ts\npackages/opencode/src/command/run.ts\npackages/opencode/src/config/config.ts",
|
||||
title: "Find CLI files",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "part-header-edit-001",
|
||||
sessionID: SESSION_ID,
|
||||
messageID: headerAssistantID,
|
||||
type: "tool",
|
||||
tool: "edit",
|
||||
state: {
|
||||
status: "completed",
|
||||
input: { filePath: "packages/opencode/src/cli/index.ts" },
|
||||
output: "Updated the command registry to expose the new interface hook.",
|
||||
title: "Update CLI registry",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "part-header-bash-001",
|
||||
sessionID: SESSION_ID,
|
||||
messageID: headerAssistantID,
|
||||
type: "tool",
|
||||
tool: "bash",
|
||||
state: {
|
||||
status: "completed",
|
||||
input: { command: "bun run check-types:webview", description: "Typecheck webview" },
|
||||
output: "Checked 1 project. No type errors found.",
|
||||
title: "Run typecheck",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "part-header-write-001",
|
||||
sessionID: SESSION_ID,
|
||||
messageID: headerAssistantID,
|
||||
type: "tool",
|
||||
tool: "write",
|
||||
state: {
|
||||
status: "completed",
|
||||
input: { filePath: "packages/opencode/src/cli/interface.ts" },
|
||||
output: "Created the CLI interface implementation scaffold.",
|
||||
title: "Create interface scaffold",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "part-header-text-002",
|
||||
sessionID: SESSION_ID,
|
||||
messageID: headerAssistantID,
|
||||
type: "text",
|
||||
text: "Next I am wiring the implementation into the existing command path.",
|
||||
},
|
||||
{
|
||||
id: "part-header-bash-002",
|
||||
sessionID: SESSION_ID,
|
||||
messageID: headerAssistantID,
|
||||
type: "tool",
|
||||
tool: "bash",
|
||||
state: {
|
||||
status: "running",
|
||||
input: { command: "bun test packages/opencode/test/cli.test.ts", description: "Run CLI tests" },
|
||||
title: "Run CLI tests",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const mockTodosInProgress: TodoItem[] = [
|
||||
{ id: "1", content: "Create a haiku about Jan", status: "completed" },
|
||||
{ id: "2", content: "Create a poem about Henk", status: "in_progress" },
|
||||
{ id: "3", content: "Write a limerick about the team", status: "pending" },
|
||||
{ id: "1", content: "Project setup and architecture backlog", status: "completed" },
|
||||
{ id: "2", content: "Configuration schema for target jobs", status: "completed" },
|
||||
{ id: "3", content: "Core scanning logic", status: "completed" },
|
||||
{ id: "4", content: "Build invocation and error handling", status: "completed" },
|
||||
{ id: "5", content: "CLI interface implementation", status: "in_progress" },
|
||||
{ id: "6", content: "Storage layer implementation", status: "pending" },
|
||||
{ id: "7", content: "Character profiles and prompt types", status: "pending" },
|
||||
{ id: "8", content: "Local tests and integration tests", status: "pending" },
|
||||
{ id: "9", content: "Migration guide", status: "pending" },
|
||||
{ id: "10", content: "Release validation", status: "pending" },
|
||||
]
|
||||
|
||||
const mockTodosAllDone: TodoItem[] = [
|
||||
@@ -465,19 +596,22 @@ export const TaskHeaderWithTodos: Story = {
|
||||
render: () => {
|
||||
const session = {
|
||||
...mockSessionValue({ id: SESSION_ID, status: "busy" }),
|
||||
messages: () => [{ id: "msg-001" }] as any[],
|
||||
messages: () => headerMessages,
|
||||
currentSession: () => ({
|
||||
id: SESSION_ID,
|
||||
title: "Writing poems about the team",
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
title: "Task: Can you use the update_todo_list tool to create a CLI interface implementation?",
|
||||
createdAt: new Date(headerNow - 12000).toISOString(),
|
||||
updatedAt: new Date(headerNow).toISOString(),
|
||||
}),
|
||||
todos: () => mockTodosInProgress,
|
||||
getParts: (id: string) => headerParts[id] ?? [],
|
||||
contextUsage: () => ({ tokens: 34300, percentage: 17 }),
|
||||
costBreakdown: () => [{ label: "Session", cost: 0.64 }],
|
||||
}
|
||||
return (
|
||||
<StoryProviders sessionID={SESSION_ID} status="busy" noPadding>
|
||||
<SessionContext.Provider value={session as any}>
|
||||
<div style={{ width: "380px" }}>
|
||||
<div style={{ width: "100%" }}>
|
||||
<TaskHeader />
|
||||
</div>
|
||||
</SessionContext.Provider>
|
||||
|
||||
@@ -292,6 +292,52 @@ const todoWriteCompleted: ToolPart = {
|
||||
},
|
||||
}
|
||||
|
||||
const docsTodos = [
|
||||
{
|
||||
id: "1",
|
||||
content: "Project setup and core architecture (package.json, tsconfig, documentation, type definitions)",
|
||||
status: "completed",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
content: "Configuration system (scraper config, targets.json, validation utilities)",
|
||||
status: "completed",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
content: "Core scraping engine (browser manager, orchestrator, selector engine, content extractor)",
|
||||
status: "completed",
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
content: "Utility modules (DOM utils, retry logic, URL handling, validation)",
|
||||
status: "completed",
|
||||
},
|
||||
{ id: "5", content: "CLI interface implementation", status: "in_progress" },
|
||||
{ id: "6", content: "Storage layer implementation (database and file storage)", status: "pending" },
|
||||
{ id: "7", content: "Chart extractors for specific chart types", status: "pending" },
|
||||
{ id: "8", content: "Logging and error handling systems", status: "pending" },
|
||||
{ id: "9", content: "Test suites (unit and integration tests)", status: "pending" },
|
||||
{ id: "10", content: "Main entry point and final integration", status: "pending" },
|
||||
]
|
||||
|
||||
const todoWriteDocsOverview: ToolPart = {
|
||||
id: "part-todo-docs-001",
|
||||
sessionID: SESSION_ID,
|
||||
messageID: ASST_MSG_ID,
|
||||
type: "tool",
|
||||
callID: "call-todo-docs-001",
|
||||
tool: "todowrite",
|
||||
state: {
|
||||
status: "completed",
|
||||
input: { todos: docsTodos },
|
||||
output: "Updated 10 todos",
|
||||
title: "Todo List Updated",
|
||||
metadata: { todos: docsTodos },
|
||||
time: { start: now - 3000, end: now - 2800 },
|
||||
},
|
||||
}
|
||||
|
||||
const todoWritePermission: PermissionRequest = {
|
||||
id: "perm-todo-001",
|
||||
sessionID: SESSION_ID,
|
||||
@@ -609,6 +655,18 @@ export const TodoWriteCompleted: Story = {
|
||||
},
|
||||
}
|
||||
|
||||
export const TodoWriteDocsOverview: Story = {
|
||||
name: "TodoWrite — docs overview",
|
||||
render: () => {
|
||||
const data = dataWith([todoWriteDocsOverview])
|
||||
return (
|
||||
<StoryProviders data={data} sessionID={SESSION_ID}>
|
||||
<AssistantMessage message={baseAssistantMessage} />
|
||||
</StoryProviders>
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 12. Permission dock — edit tool with file patterns
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user