Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0baefa25fe |
@@ -42,6 +42,8 @@ import { writeHeapSnapshot } from "v8"
|
||||
import { PromptRefProvider, usePromptRef } from "./context/prompt"
|
||||
import { registerKiloCommands } from "@/kilocode/kilo-commands" // kilocode_change
|
||||
import { initializeTUIDependencies } from "@kilocode/kilo-gateway/tui" // kilocode_change
|
||||
import { FocusProvider, useFocused } from "@tui/util/focus" // kilocode_change
|
||||
import { notify } from "@tui/util/notify" // kilocode_change
|
||||
|
||||
async function getTerminalBackgroundColor(): Promise<"dark" | "light"> {
|
||||
// can't set raw mode if not a TTY
|
||||
@@ -159,7 +161,9 @@ export function tui(input: {
|
||||
<FrecencyProvider>
|
||||
<PromptHistoryProvider>
|
||||
<PromptRefProvider>
|
||||
<App />
|
||||
<FocusProvider>
|
||||
<App />
|
||||
</FocusProvider>
|
||||
</PromptRefProvider>
|
||||
</PromptHistoryProvider>
|
||||
</FrecencyProvider>
|
||||
@@ -740,6 +744,25 @@ function App() {
|
||||
})
|
||||
})
|
||||
|
||||
// kilocode_change start - Terminal notifications when input is needed and window is unfocused
|
||||
const focus = useFocused()
|
||||
sdk.event.on("permission.asked", (evt) => {
|
||||
if (focus.focused()) return
|
||||
notify(
|
||||
"Permission Required",
|
||||
`${evt.properties.permission} approval needed`,
|
||||
sync.data.config,
|
||||
evt.properties.sessionID,
|
||||
)
|
||||
})
|
||||
|
||||
sdk.event.on("question.asked", (evt) => {
|
||||
if (focus.focused()) return
|
||||
const body = evt.properties.questions[0]?.header ?? "The agent is asking a question"
|
||||
notify("Question", body, sync.data.config, evt.properties.sessionID)
|
||||
})
|
||||
// kilocode_change end
|
||||
|
||||
return (
|
||||
<box
|
||||
width={dimensions().width}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// kilocode_change - new file
|
||||
import { useRenderer } from "@opentui/solid"
|
||||
import { createSignal, onCleanup } from "solid-js"
|
||||
import { createSimpleContext } from "../context/helper"
|
||||
|
||||
export const { use: useFocused, provider: FocusProvider } = createSimpleContext({
|
||||
name: "Focus",
|
||||
init: () => {
|
||||
const renderer = useRenderer()
|
||||
const [focused, setFocused] = createSignal(true)
|
||||
|
||||
const onFocus = () => setFocused(true)
|
||||
const onBlur = () => setFocused(false)
|
||||
renderer.on("focus", onFocus)
|
||||
renderer.on("blur", onBlur)
|
||||
|
||||
onCleanup(() => {
|
||||
renderer.removeListener("focus", onFocus)
|
||||
renderer.removeListener("blur", onBlur)
|
||||
})
|
||||
|
||||
return { focused }
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,41 @@
|
||||
// kilocode_change - new file
|
||||
import type { Config } from "@kilocode/sdk/v2"
|
||||
|
||||
const alertedAt = new Map<string, number>()
|
||||
const COOLDOWN_MS = 5000
|
||||
|
||||
/** Strip control characters to prevent escape sequence injection in OSC payloads. */
|
||||
const sanitize = (s: string) => s.replace(/[\x00-\x1f\x7f-\x9f]/g, "")
|
||||
|
||||
export function notify(title: string, body: string, config: Config, sessionID: string) {
|
||||
const now = Date.now()
|
||||
const last = alertedAt.get(sessionID) ?? 0
|
||||
if (now - last < COOLDOWN_MS) return
|
||||
|
||||
// Prune stale entries to prevent unbounded growth of the alertedAt map
|
||||
for (const [key, time] of alertedAt) {
|
||||
if (now - time >= COOLDOWN_MS) alertedAt.delete(key)
|
||||
}
|
||||
|
||||
alertedAt.set(sessionID, now)
|
||||
|
||||
// bell and osc default to enabled (opt-out via `notifications.bell: false` / `notifications.osc: false`)
|
||||
const bell = config.tui?.notifications?.bell !== false
|
||||
const osc = config.tui?.notifications?.osc !== false
|
||||
|
||||
if (bell) {
|
||||
process.stdout.write("\x07")
|
||||
}
|
||||
|
||||
if (osc) {
|
||||
const safe = `${sanitize(title)}: ${sanitize(body)}`
|
||||
|
||||
// OSC 9 is widely supported; terminals that don't understand it simply ignore it
|
||||
process.stdout.write(`\x1b]9;${safe}\x07`)
|
||||
|
||||
// Kitty uses its own OSC 99 notification protocol
|
||||
if (process.env["TERM_PROGRAM"] === "kitty") {
|
||||
process.stdout.write(`\x1b]99;i=1:d=0;${safe}\x1b\\`)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1015,6 +1015,18 @@ export namespace Config {
|
||||
.enum(["auto", "stacked"])
|
||||
.optional()
|
||||
.describe("Control diff rendering style: 'auto' adapts to terminal width, 'stacked' always shows single column"),
|
||||
// kilocode_change start
|
||||
notifications: z
|
||||
.object({
|
||||
bell: z.boolean().optional().describe("Enable terminal bell when input is needed and window is unfocused"),
|
||||
osc: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe("Enable OSC 9/99 notifications for iTerm2/Kitty when input is needed and window is unfocused"),
|
||||
})
|
||||
.optional()
|
||||
.describe("Notification settings for the TUI"),
|
||||
// kilocode_change end
|
||||
})
|
||||
|
||||
export const Server = z
|
||||
|
||||
@@ -1719,6 +1719,19 @@ export type Config = {
|
||||
* Control diff rendering style: 'auto' adapts to terminal width, 'stacked' always shows single column
|
||||
*/
|
||||
diff_style?: "auto" | "stacked"
|
||||
/**
|
||||
* Notification settings for the TUI
|
||||
*/
|
||||
notifications?: {
|
||||
/**
|
||||
* Enable terminal bell when input is needed and window is unfocused
|
||||
*/
|
||||
bell?: boolean
|
||||
/**
|
||||
* Enable OSC 9/99 notifications for iTerm2/Kitty when input is needed and window is unfocused
|
||||
*/
|
||||
osc?: boolean
|
||||
}
|
||||
}
|
||||
server?: ServerConfig
|
||||
/**
|
||||
|
||||
@@ -10157,6 +10157,20 @@
|
||||
"description": "Control diff rendering style: 'auto' adapts to terminal width, 'stacked' always shows single column",
|
||||
"type": "string",
|
||||
"enum": ["auto", "stacked"]
|
||||
},
|
||||
"notifications": {
|
||||
"description": "Notification settings for the TUI",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"bell": {
|
||||
"description": "Enable terminal bell when input is needed and window is unfocused",
|
||||
"type": "boolean"
|
||||
},
|
||||
"osc": {
|
||||
"description": "Enable OSC 9/99 notifications for iTerm2/Kitty when input is needed and window is unfocused",
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user