From 35dd730dcc3c7160d3324eaf42e4c97120004284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Catriel=20M=C3=BCller?= Date: Thu, 11 Jun 2026 23:18:42 -0300 Subject: [PATCH 1/8] feat: kilo console dialogs --- .../src/components/ConfirmDialog.tsx | 22 ++- .../src/components/PromptDialog.tsx | 73 +++++++++ .../routes/projects/ProjectConsoleRoute.tsx | 138 ++++++++++++++---- .../kilo-console/src/styles/providers.css | 37 ++++- 4 files changed, 233 insertions(+), 37 deletions(-) create mode 100644 packages/kilo-console/src/components/PromptDialog.tsx diff --git a/packages/kilo-console/src/components/ConfirmDialog.tsx b/packages/kilo-console/src/components/ConfirmDialog.tsx index 6fba52e63a..2ed84f88b9 100644 --- a/packages/kilo-console/src/components/ConfirmDialog.tsx +++ b/packages/kilo-console/src/components/ConfirmDialog.tsx @@ -1,4 +1,4 @@ -import { Show } from "solid-js" +import { createUniqueId, Show } from "solid-js" import { Button } from "@kilocode/kilo-web-ui/button" import { Icon } from "@kilocode/kilo-web-ui/icon" @@ -14,21 +14,31 @@ type Props = { } export function ConfirmDialog(props: Props) { + const id = createUniqueId() + const title = `${id}-title` + const message = `${id}-message` + return ( -
-
+
event.key === "Escape" && props.onCancel()}> +
-

{props.title}

- {(text) =>

{text()}

}
+

{props.title}

+ {(text) =>

{text()}

}
- + +
+ +
+
+ + ) +} diff --git a/packages/kilo-console/src/routes/projects/ProjectConsoleRoute.tsx b/packages/kilo-console/src/routes/projects/ProjectConsoleRoute.tsx index 7f576e7fb6..3de3088e68 100644 --- a/packages/kilo-console/src/routes/projects/ProjectConsoleRoute.tsx +++ b/packages/kilo-console/src/routes/projects/ProjectConsoleRoute.tsx @@ -2,7 +2,9 @@ import { A, useLocation, useParams } from "@solidjs/router" import { createEffect, createMemo, createResource, createSignal, For, onCleanup, Show } from "solid-js" import { Card } from "@kilocode/kilo-web-ui/card" import { Icon } from "@kilocode/kilo-web-ui/icon" +import { ConfirmDialog } from "../../components/ConfirmDialog" import { LoadingScreen } from "../../components/LoadingScreen" +import { PromptDialog } from "../../components/PromptDialog" import { createProjectPty, createProjectWorktree, @@ -41,6 +43,15 @@ type Context = { kind: "local" | "worktree" } +type Editor = + | { kind: "create"; value: string } + | { kind: "rename"; item: Context; value: string } + +type Pending = { + kind: "delete" | "reset" + item: Context +} + function discoverable(search: URLSearchParams) { if (search.get("server")) return false return ui.has(window.location.port) @@ -131,6 +142,8 @@ export function ProjectConsoleRoute() { const [unread, setUnread] = createSignal(new Set()) const [closing, setClosing] = createSignal(new Set()) const [labelRev, setLabelRev] = createSignal(0) + const [editor, setEditor] = createSignal() + const [pending, setPending] = createSignal() const events = { timer: undefined as number | undefined } const project = () => params.project ?? "" const query = createMemo(() => { @@ -322,10 +335,26 @@ export function ProjectConsoleRoute() { } function addWorktree() { + if (!projectInput()) return + setEditor({ kind: "create", value: "" }) + } + + function submitEditor() { + const state = editor() + if (!state) return + if (state.kind === "rename") { + const value = state.value.trim() + if (value) window.localStorage.setItem(labelKey(state.item.dir), value) + if (!value) window.localStorage.removeItem(labelKey(state.item.dir)) + setLabelRev((revision) => revision + 1) + setEditor(undefined) + return + } + const input = projectInput() - const data = snap() - if (!input || !data) return - const name = window.prompt("Worktree name") ?? undefined + if (!input) return + const name = state.value.trim() || undefined + setEditor(undefined) run("Creating worktree", async () => { const next = await createProjectWorktree(input, name) setSelected(next.directory) @@ -395,27 +424,12 @@ export function ProjectConsoleRoute() { function renameWorktree(item: Context) { if (item.kind === "local") return - const input = window.prompt("Worktree label", displayLabel(item)) - if (input === null) return - const next = input.trim() - if (next) window.localStorage.setItem(labelKey(item.dir), next) - else window.localStorage.removeItem(labelKey(item.dir)) - setLabelRev((value) => value + 1) + setEditor({ kind: "rename", item, value: displayLabel(item) }) } function removeWorktree(item: Context) { - const input = projectInput() - if (!input || item.kind === "local") return - if (!window.confirm(`Remove worktree ${displayLabel(item)}?`)) return - run("Removing worktree", async () => { - await removeProjectWorktree(input, item.dir) - window.localStorage.removeItem(labelKey(item.dir)) - setLabelRev((value) => value + 1) - if (selected() === item.dir) { - setSelected(input.dir) - remember(input.dir) - } - }) + if (!projectInput() || item.kind === "local") return + setPending({ kind: "delete", item }) } function removeSelected() { @@ -425,11 +439,60 @@ export function ProjectConsoleRoute() { } function resetSelected() { - const input = projectInput() const item = current() - if (!input || !item || item.kind === "local") return - if (!window.confirm(`Reset worktree ${displayLabel(item)}?`)) return - run("Resetting worktree", async () => resetProjectWorktree(input, item.dir)) + if (!projectInput() || !item || item.kind === "local") return + setPending({ kind: "reset", item }) + } + + function confirmWorktree() { + const state = pending() + const input = projectInput() + if (!state || !input) return + setPending(undefined) + if (state.kind === "reset") { + run("Resetting worktree", async () => resetProjectWorktree(input, state.item.dir)) + return + } + + run("Removing worktree", async () => { + await removeProjectWorktree(input, state.item.dir) + window.localStorage.removeItem(labelKey(state.item.dir)) + setLabelRev((revision) => revision + 1) + if (selected() === state.item.dir) { + setSelected(input.dir) + remember(input.dir) + } + }) + } + + function updateEditor(value: string) { + setEditor((state) => { + if (!state) return state + return { ...state, value } + }) + } + + function editorTitle() { + const state = editor() + if (!state || state.kind === "create") return "Create worktree" + return `Rename ${displayLabel(state.item)}` + } + + function editorMessage() { + if (editor()?.kind === "rename") return "Leave the name blank to restore the generated worktree name." + return "Choose a recognizable name, or leave it blank to generate one automatically." + } + + function pendingTitle() { + const state = pending() + if (!state) return "" + const action = state.kind === "reset" ? "Reset" : "Delete" + return `${action} worktree ${displayLabel(state.item)}?` + } + + function pendingMessage() { + if (pending()?.kind === "reset") return "This discards all uncommitted changes in the worktree." + return "This removes the worktree directory and its files from the project." } createEffect(() => { @@ -744,7 +807,7 @@ export function ProjectConsoleRoute() { Reset
@@ -780,6 +843,29 @@ export function ProjectConsoleRoute() { {(item) =>
{item()?.patch ?? ""}
}
+ + setEditor(undefined)} + onConfirm={submitEditor} + /> + setPending(undefined)} + onConfirm={confirmWorktree} + /> ) } diff --git a/packages/kilo-console/src/styles/providers.css b/packages/kilo-console/src/styles/providers.css index 179400632e..548e16af5f 100644 --- a/packages/kilo-console/src/styles/providers.css +++ b/packages/kilo-console/src/styles/providers.css @@ -408,7 +408,7 @@ } .kilo-console .confirm-dialog { - width: min(48rem, 100%); + width: min(28rem, 100%); overflow: hidden; border: 1px solid var(--border-weak-base); border-radius: var(--radius-lg); @@ -435,16 +435,21 @@ height: 3rem; } -.kilo-console .confirm-body h2 { +.kilo-console .confirm-body h2, +.kilo-console .prompt-copy h2 { margin: 0; color: var(--text-strong); - font-size: clamp(1.15rem, 2vw, 1.35rem); - line-height: 1.35; + font-size: 0.875rem; + font-weight: 500; + line-height: 1.25rem; } -.kilo-console .confirm-body p { +.kilo-console .confirm-body p, +.kilo-console .prompt-copy p { margin: 0.5rem 0 0; color: var(--text-weak); + font-size: 0.75rem; + line-height: 1.625; } .kilo-console .confirm-actions { @@ -455,3 +460,25 @@ background: color-mix(in srgb, var(--background-base) 65%, transparent); padding: 1rem; } + +.kilo-console .prompt-form { + margin: 0; +} + +.kilo-console .prompt-body { + display: grid; + gap: 1rem; + padding: 1.5rem; +} + +.kilo-console .prompt-field { + display: grid; + gap: 0.5rem; + color: var(--text-strong); + font-size: 0.75rem; + font-weight: 500; +} + +.kilo-console .prompt-field input { + height: 2rem; +} From 9a187d5aad5c3bf90a6dac589a0b26069057c3b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Catriel=20M=C3=BCller?= Date: Fri, 12 Jun 2026 01:08:09 -0300 Subject: [PATCH 2/8] feat: improve Kilo Console project review --- .changeset/neat-worktree-dialogs.md | 5 + .changeset/resize-console-context.md | 6 + .changeset/rich-worktree-review.md | 5 + packages/kilo-console/src/client.ts | 5 +- packages/kilo-console/src/index.tsx | 6 + .../kilo-console/src/layouts/ConfigLayout.tsx | 7 - .../src/routes/config/ConfigSidebar.tsx | 3 +- .../src/routes/config/ConsoleUiRoute.tsx | 100 +++++++++ .../src/routes/config/sections.tsx | 10 + .../src/routes/config/state/console.test.ts | 36 +++ .../src/routes/config/state/console.ts | 80 +++++++ .../routes/projects/ProjectConsoleRoute.tsx | 209 +++++++++++++----- packages/kilo-console/src/styles/cli-ui.css | 14 ++ .../src/styles/project-console.css | 155 +++++++------ packages/opencode/src/config/config.ts | 10 + .../test/kilocode/config/console-ui.test.ts | 20 ++ packages/sdk/js/src/v2/gen/types.gen.ts | 7 + packages/sdk/openapi.json | 34 +++ 18 files changed, 587 insertions(+), 125 deletions(-) create mode 100644 .changeset/neat-worktree-dialogs.md create mode 100644 .changeset/resize-console-context.md create mode 100644 .changeset/rich-worktree-review.md create mode 100644 packages/kilo-console/src/routes/config/ConsoleUiRoute.tsx create mode 100644 packages/kilo-console/src/routes/config/state/console.test.ts create mode 100644 packages/kilo-console/src/routes/config/state/console.ts create mode 100644 packages/opencode/test/kilocode/config/console-ui.test.ts diff --git a/.changeset/neat-worktree-dialogs.md b/.changeset/neat-worktree-dialogs.md new file mode 100644 index 0000000000..b57f336d6b --- /dev/null +++ b/.changeset/neat-worktree-dialogs.md @@ -0,0 +1,5 @@ +--- +"@kilocode/kilo-console": patch +--- + +Replace native worktree prompts with consistent dialogs for creating, renaming, resetting, and deleting worktrees. diff --git a/.changeset/resize-console-context.md b/.changeset/resize-console-context.md new file mode 100644 index 0000000000..bb9dca3f1b --- /dev/null +++ b/.changeset/resize-console-context.md @@ -0,0 +1,6 @@ +--- +"@kilocode/kilo-console": patch +"@kilocode/cli": patch +--- + +Configure the project context sidebar width and default diff layout from Global Settings. diff --git a/.changeset/rich-worktree-review.md b/.changeset/rich-worktree-review.md new file mode 100644 index 0000000000..bffd4bb44d --- /dev/null +++ b/.changeset/rich-worktree-review.md @@ -0,0 +1,5 @@ +--- +"@kilocode/kilo-console": patch +--- + +Review worktree changes in a richer panel with per-file stats and syntax-highlighted diffs. diff --git a/packages/kilo-console/src/client.ts b/packages/kilo-console/src/client.ts index 9a3eb36489..adca1648a7 100644 --- a/packages/kilo-console/src/client.ts +++ b/packages/kilo-console/src/client.ts @@ -52,6 +52,7 @@ export type ProjectConsoleQuery = ProjectQuery & { export type ProjectConsoleSnapshot = { project: ProjectItem + config: EffectiveConfig vcs: VcsInfo worktrees: string[] terminals: ProjectTerminalItem[] @@ -439,7 +440,8 @@ export async function loadProjectConsole(input: ProjectConsoleQuery): Promise ) } diff --git a/packages/kilo-console/src/layouts/ConfigLayout.tsx b/packages/kilo-console/src/layouts/ConfigLayout.tsx index 8f779b9328..be9be5043e 100644 --- a/packages/kilo-console/src/layouts/ConfigLayout.tsx +++ b/packages/kilo-console/src/layouts/ConfigLayout.tsx @@ -30,13 +30,6 @@ function ConfigContent(props: { children?: JSX.Element }) { )} - - {(item) => ( - - )} -