mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-24 16:02:55 +08:00
Merge branch 'main' into imanolmaiztegui/kilo-opencode-v1.14.34
This commit is contained in:
@@ -1,5 +1,15 @@
|
||||
# @kilocode/cli
|
||||
|
||||
## 7.3.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#10285](https://github.com/Kilo-Org/kilocode/pull/10285) [`d23e162`](https://github.com/Kilo-Org/kilocode/commit/d23e162051f118beb993f84cebad1002d974ad79) - Capture aggregate usage telemetry for experimental Morph-backed codebase search.
|
||||
|
||||
- [#10358](https://github.com/Kilo-Org/kilocode/pull/10358) [`413222f`](https://github.com/Kilo-Org/kilocode/commit/413222f0137a29c5cf09666ea3b515032c81f9b8) - Resume interrupted CLI turns automatically after network recovery while giving users 10 seconds to cancel.
|
||||
|
||||
- [#10293](https://github.com/Kilo-Org/kilocode/pull/10293) [`af115af`](https://github.com/Kilo-Org/kilocode/commit/af115afe20893f4d24d22a40411ebdbd398781d7) - Harden Mermaid diagram rendering with upstream security fixes.
|
||||
|
||||
## 7.3.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "7.3.0",
|
||||
"version": "7.3.1",
|
||||
"name": "@kilocode/cli",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { RGBA } from "@opentui/core"
|
||||
import { For, type JSX } from "solid-js"
|
||||
import { useTheme, tint } from "@tui/context/theme"
|
||||
import { tui } from "../../../../kilocode/cli/logo"
|
||||
|
||||
// Shadow markers (rendered chars in parens):
|
||||
// _ = full shadow cell (space with bg=shadow)
|
||||
@@ -9,16 +10,10 @@ import { useTheme, tint } from "@tui/context/theme"
|
||||
// ~ = shadow top only (▀ with fg=shadow)
|
||||
const SHADOW_MARKER = /[_^~]/
|
||||
|
||||
const ASCII_LOGO = [
|
||||
`██ ▄█▀ ██ ██ ▄████▄ ▄█████ ██ ██ `,
|
||||
`████ ██ ██ ██~~██ ██~~~~ ██ ██ `,
|
||||
`██ ▀█▄ ██ ██████ ▀████▀ ▀█████ ██████ ██ `,
|
||||
`~~ ~~ ~~ ~~~~~~ ~~~~ ~~~~~ ~~~~~~ ~~ `,
|
||||
]
|
||||
|
||||
export function KiloLogo() {
|
||||
const { theme } = useTheme()
|
||||
const yellow = RGBA.fromHex("#F8F675")
|
||||
const logo = tui()
|
||||
|
||||
const renderLine = (line: string): JSX.Element[] => {
|
||||
const shadow = tint(theme.background, yellow, 0.25)
|
||||
@@ -79,7 +74,7 @@ export function KiloLogo() {
|
||||
|
||||
return (
|
||||
<box>
|
||||
<For each={ASCII_LOGO}>{(line) => <box flexDirection="row">{renderLine(line)}</box>}</For>
|
||||
<For each={logo}>{(line) => <box flexDirection="row">{renderLine(line)}</box>}</For>
|
||||
</box>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -85,6 +85,7 @@ import { formatTranscript } from "../../util/transcript"
|
||||
import { UI } from "@/cli/ui.ts"
|
||||
import { useTuiConfig } from "../../context/tui-config"
|
||||
import { splitDiffHunks } from "@/kilocode/tui/diff" // kilocode_change
|
||||
import { session as banner } from "@/kilocode/cli/logo" // kilocode_change
|
||||
|
||||
import { formatMarkdownTables } from "../../util/markdown" // kilocode_change
|
||||
import { bell } from "@/kilocode/bell" // kilocode_change
|
||||
@@ -358,19 +359,12 @@ export function Session() {
|
||||
// Allow exit when in child session (prompt is hidden)
|
||||
const exit = useExit()
|
||||
|
||||
// kilocode_change start
|
||||
createEffect(() => {
|
||||
const title = Locale.truncate(session()?.title ?? "", 50)
|
||||
// kilocode_change start
|
||||
return exit.message.set(
|
||||
[
|
||||
``,
|
||||
` ██ ▄█▀ ██ ██ ▄████▄ ${UI.Style.TEXT_DIM}${title}${UI.Style.TEXT_NORMAL}`,
|
||||
` ████ ██ ██ ██ ██ ${UI.Style.TEXT_DIM}kilo -s ${session()?.id}${UI.Style.TEXT_NORMAL}`,
|
||||
` ██ ▀█▄ ██ ██████ ▀████▀ `,
|
||||
].join("\n"),
|
||||
)
|
||||
// kilocode_change end
|
||||
return exit.message.set(banner(title, session()?.id, UI.Style.TEXT_DIM, UI.Style.TEXT_NORMAL))
|
||||
})
|
||||
// kilocode_change end
|
||||
|
||||
// kilocode_change start - double ctrl+c to exit for child sessions
|
||||
const [exitPress, setExitPress] = createSignal(0)
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
// kilocode_change start
|
||||
import { plain } from "../kilocode/cli/logo"
|
||||
|
||||
export const logo = {
|
||||
left: ["", "", ""],
|
||||
right: [
|
||||
"██ ▄█▀ ██ ██ ▄████▄ ▄█████ ██ ██ ",
|
||||
`████ ██ ██ ██ ██ ██ ██ ██ `,
|
||||
`██ ▀█▄ ██ ██████ ▀████▀ ▀█████ ██████ ██ `,
|
||||
],
|
||||
right: plain(),
|
||||
}
|
||||
// kilocode_change end
|
||||
|
||||
|
||||
@@ -2,15 +2,13 @@ import z from "zod"
|
||||
import { EOL } from "os"
|
||||
import { NamedError } from "@opencode-ai/core/util/error"
|
||||
import { logo as glyphs } from "./logo"
|
||||
import { tui } from "../kilocode/cli/logo" // kilocode_change
|
||||
|
||||
// kilocode_change start
|
||||
const wordmark = [
|
||||
// kilocode_change start
|
||||
`██ ▄█▀ ██ ██ ▄████▄ ▄█████ ██ ██ `,
|
||||
`████ ██ ██ ██~~██ ██~~~~ ██ ██ `,
|
||||
`██ ▀█▄ ██ ██████ ▀████▀ ▀█████ ██████ ██ `,
|
||||
`~~ ~~ ~~ ~~~~~~ ~~~~ ~~~~~ ~~~~~~ ~~ `,
|
||||
// kilocode_change end
|
||||
...tui(),
|
||||
]
|
||||
// kilocode_change end
|
||||
|
||||
export const CancelledError = NamedError.create("UICancelledError", z.void())
|
||||
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
// kilocode_change - new file
|
||||
const yes = new Set(["1", "true", "yes", "on"])
|
||||
const no = new Set(["0", "false", "no", "off"])
|
||||
|
||||
const modern = {
|
||||
tui: [
|
||||
`██ ██ ██🬺🬏 ██ ██ ██🬺🬏 ████ ██ ██🬺🬏 `,
|
||||
`████🬺🬏 ~~██ ██ ~~ ██~~██ ██~~~~ ██ ~~██ `,
|
||||
`██ ██ ██████ 🬁🬬████ 🬁🬬██~~ 🬁🬬████ 🬁🬬████ ██████ `,
|
||||
`~~ ~~ ~~~~~~ ~~~~ ~~ ~~~~ ~~~~ ~~~~~~ `,
|
||||
],
|
||||
plain: [
|
||||
`██ ██ ██🬺🬏 ██ ██ ██🬺🬏 ████ ██ ██🬺🬏 `,
|
||||
`████🬺🬏 ██ ██ ██ ██ ██ ██ ██ `,
|
||||
`██ ██ ██████ 🬁🬬████ 🬁🬬██ 🬁🬬████ 🬁🬬████ ██████ `,
|
||||
],
|
||||
exit: [
|
||||
` ██ ██ ██🬺🬏 ██ ██ ██🬺🬏 `,
|
||||
` ████🬺🬏 ██ ██ ██ ██ `,
|
||||
` ██ ██ ██████ 🬁🬬████ 🬁🬬██ `,
|
||||
],
|
||||
}
|
||||
|
||||
const fallback = {
|
||||
tui: [
|
||||
`██ ██ ████ ██ ██ ██ ████ ██ ████ `,
|
||||
`████ ~~██ ██ ~~ ██~~██ ██~~~~ ██ ~~██ `,
|
||||
`██ ██ ██████ ██████ ██~~ ████ ████ ██████ `,
|
||||
`~~ ~~ ~~~~~~ ~~~~~ ~~ ~~~~ ~~~~ ~~~~~~ `,
|
||||
],
|
||||
plain: [
|
||||
`██ ██ ████ ██ ██ ███ ████ ██ ████ `,
|
||||
`████ ██ ██ ██ ██ ██ ██ ██ `,
|
||||
`██ ██ ██████ ██████ ██ ████ ██████ ██████ `,
|
||||
],
|
||||
exit: [
|
||||
` ██ ██ ████ ██ ██ ██ `,
|
||||
` ████ ██ ██ ██ ██ `,
|
||||
` ██ ██ ██████ ██████ ██ `,
|
||||
],
|
||||
}
|
||||
|
||||
function flag(value: string | undefined) {
|
||||
const key = value?.toLowerCase()
|
||||
if (!key) return
|
||||
if (yes.has(key)) return true
|
||||
if (no.has(key)) return false
|
||||
}
|
||||
|
||||
export function supports(env = process.env, platform = process.platform) {
|
||||
const override = flag(env.KILO_UNICODE_LOGO)
|
||||
if (override !== undefined) return override
|
||||
// Terminals do not expose font glyph coverage over SSH, so prefer the safe logo for remote sessions.
|
||||
if (env.TERM === "dumb") return false
|
||||
if (env.SSH_TTY) return false
|
||||
if (env.SSH_CLIENT) return false
|
||||
if (env.SSH_CONNECTION) return false
|
||||
if (env.ConEmuPID) return false
|
||||
if (env.ANSICON) return false
|
||||
return true
|
||||
}
|
||||
|
||||
export function tui(env = process.env, platform = process.platform) {
|
||||
return supports(env, platform) ? modern.tui : fallback.tui
|
||||
}
|
||||
|
||||
export function plain(env = process.env, platform = process.platform) {
|
||||
return supports(env, platform) ? modern.plain : fallback.plain
|
||||
}
|
||||
|
||||
export function session(
|
||||
title: string,
|
||||
id: string | undefined,
|
||||
dim: string,
|
||||
normal: string,
|
||||
env = process.env,
|
||||
platform = process.platform,
|
||||
) {
|
||||
const logo = supports(env, platform) ? modern.exit : fallback.exit
|
||||
return [
|
||||
``,
|
||||
`${logo[0]}${dim}${title}${normal}`,
|
||||
`${logo[1]}${dim}kilo -s ${id}${normal}`,
|
||||
logo[2],
|
||||
].join("\n")
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { plain, session, supports, tui } from "../../src/kilocode/cli/logo"
|
||||
|
||||
describe("kilocode logo", () => {
|
||||
test("falls back on remote terminals", () => {
|
||||
expect(supports({ SSH_TTY: "/dev/pts/0" }, "linux")).toBe(false)
|
||||
expect(supports({ SSH_CLIENT: "127.0.0.1 12345 22" }, "linux")).toBe(false)
|
||||
expect(supports({ SSH_CONNECTION: "127.0.0.1 12345 127.0.0.1 22" }, "linux")).toBe(false)
|
||||
})
|
||||
|
||||
test("allows Windows Terminal locally", () => {
|
||||
expect(supports({}, "win32")).toBe(true)
|
||||
expect(supports({ WT_SESSION: "session" }, "linux")).toBe(true)
|
||||
})
|
||||
|
||||
test("allows an override", () => {
|
||||
expect(supports({ KILO_UNICODE_LOGO: "1", SSH_TTY: "/dev/pts/0" }, "linux")).toBe(true)
|
||||
expect(supports({ KILO_UNICODE_LOGO: "0" }, "linux")).toBe(false)
|
||||
})
|
||||
|
||||
test("uses modern and fallback logo variants", () => {
|
||||
expect(tui({ KILO_UNICODE_LOGO: "1" }, "linux").join("\n")).toContain("🬺🬏")
|
||||
expect(tui({ SSH_TTY: "/dev/pts/0" }, "linux").join("\n")).not.toContain("🬺🬏")
|
||||
expect(plain({ SSH_TTY: "/dev/pts/0" }, "linux").join("\n")).not.toContain("🬁🬬")
|
||||
})
|
||||
|
||||
test("formats child session exit logo", () => {
|
||||
const out = session("Title", "ses_test", "<dim>", "<reset>", { SSH_TTY: "/dev/pts/0" }, "linux")
|
||||
expect(out).toContain("<dim>Title<reset>")
|
||||
expect(out).not.toContain("🬺🬏")
|
||||
})
|
||||
})
|
||||
@@ -1524,6 +1524,7 @@ unix(
|
||||
30_000,
|
||||
)
|
||||
|
||||
// kilocode_change start - cancel persists aborted shell result when shell ignores TERM
|
||||
unix(
|
||||
"cancel persists aborted shell result when shell ignores TERM",
|
||||
() =>
|
||||
@@ -1531,12 +1532,32 @@ unix(
|
||||
provideTmpdirInstance(
|
||||
(_dir) =>
|
||||
Effect.gen(function* () {
|
||||
const { prompt, chat } = yield* boot()
|
||||
const { prompt, chat, sessions } = yield* boot()
|
||||
|
||||
const sh = yield* prompt
|
||||
.shell({ sessionID: chat.id, agent: "build", command: "trap '' TERM; sleep 30" })
|
||||
.shell({
|
||||
sessionID: chat.id,
|
||||
agent: "build",
|
||||
command: "trap '' TERM; printf started; sleep 10; printf not-killed",
|
||||
})
|
||||
.pipe(Effect.forkChild)
|
||||
yield* Effect.sleep(50)
|
||||
yield* waitFor(
|
||||
"shell start output",
|
||||
sessions
|
||||
.messages({ sessionID: chat.id })
|
||||
.pipe(
|
||||
Effect.map((msgs) =>
|
||||
msgs
|
||||
.flatMap((msg) => msg.parts)
|
||||
.find(
|
||||
(part) =>
|
||||
part.type === "tool" &&
|
||||
part.state.status === "running" &&
|
||||
(part.state.metadata?.output ?? "").includes("started"),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
yield* prompt.cancel(chat.id)
|
||||
|
||||
@@ -1546,7 +1567,9 @@ unix(
|
||||
expect(exit.value.info.role).toBe("assistant")
|
||||
const tool = completedTool(exit.value.parts)
|
||||
if (tool) {
|
||||
expect(tool.state.output).toContain("started")
|
||||
expect(tool.state.output).toContain("User aborted the command")
|
||||
expect(tool.state.output).not.toContain("not-killed")
|
||||
}
|
||||
}
|
||||
}),
|
||||
@@ -1555,6 +1578,7 @@ unix(
|
||||
),
|
||||
30_000,
|
||||
)
|
||||
// kilocode_change end
|
||||
|
||||
unix(
|
||||
"cancel finalizes interrupted bash tool output through normal truncation",
|
||||
|
||||
Reference in New Issue
Block a user