mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-08-28 19:11:03 +08:00
feat(vscode): add KiloClaw chat panel to VS Code extension
Integrate KiloClaw as a standalone editor panel in the VS Code extension, enabling real-time chat with the KiloClaw bot via Stream Chat. The panel follows the established Agent Manager pattern with proper panel serialization, webview lifecycle management, and a race condition guard for deferred backend connections.
This commit is contained in:
@@ -321,6 +321,7 @@
|
||||
"quick-lru": "^7.0.0",
|
||||
"simple-git": "3.35.2",
|
||||
"solid-js": "^1.9.11",
|
||||
"stream-chat": "9.38.0",
|
||||
"uri-js": "^4.4.1",
|
||||
"web-tree-sitter": "^0.24.7",
|
||||
"yaml": "2.8.3",
|
||||
|
||||
@@ -188,6 +188,9 @@ async function main() {
|
||||
"dist/agent-manager.js",
|
||||
)
|
||||
|
||||
// Build KiloClaw webview (SolidJS, standalone chat panel)
|
||||
const kiloClawCtx = await createBrowserWebviewContext("webview-ui/kiloclaw/index.tsx", "dist/kiloclaw.js")
|
||||
|
||||
// Build Diff Viewer webview (SolidJS, reuses Agent Manager diff components)
|
||||
const diffViewerCtx = await createBrowserWebviewContext("webview-ui/diff-viewer/index.tsx", "dist/diff-viewer.js")
|
||||
|
||||
@@ -204,12 +207,14 @@ async function main() {
|
||||
agentManagerCtx.watch(),
|
||||
diffViewerCtx.watch(),
|
||||
diffVirtualCtx.watch(),
|
||||
kiloClawCtx.watch(),
|
||||
])
|
||||
} else {
|
||||
await Promise.all([
|
||||
extensionCtx.rebuild(),
|
||||
webviewCtx.rebuild(),
|
||||
agentManagerCtx.rebuild(),
|
||||
kiloClawCtx.rebuild(),
|
||||
diffViewerCtx.rebuild(),
|
||||
diffVirtualCtx.rebuild(),
|
||||
])
|
||||
@@ -217,6 +222,7 @@ async function main() {
|
||||
extensionCtx.dispose(),
|
||||
webviewCtx.dispose(),
|
||||
agentManagerCtx.dispose(),
|
||||
kiloClawCtx.dispose(),
|
||||
diffViewerCtx.dispose(),
|
||||
diffVirtualCtx.dispose(),
|
||||
])
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"webview-ui/agent-manager/index.tsx",
|
||||
"webview-ui/diff-viewer/index.tsx",
|
||||
"webview-ui/diff-virtual/index.tsx",
|
||||
"webview-ui/kiloclaw/index.tsx",
|
||||
"webview-ui/src/index.tsx",
|
||||
"src/**/__tests__/**/*.{ts,spec.ts}",
|
||||
"src/**/*.test.ts",
|
||||
|
||||
@@ -91,6 +91,11 @@
|
||||
"title": "Agent Manager",
|
||||
"icon": "$(circuit-board)"
|
||||
},
|
||||
{
|
||||
"command": "kilo-code.new.kiloClawOpen",
|
||||
"title": "KiloClaw",
|
||||
"icon": "$(comment-discussion)"
|
||||
},
|
||||
{
|
||||
"command": "kilo-code.new.marketplaceButtonClicked",
|
||||
"title": "Marketplace",
|
||||
@@ -356,19 +361,24 @@
|
||||
"when": "view == kilo-code.SidebarProvider"
|
||||
},
|
||||
{
|
||||
"command": "kilo-code.new.marketplaceButtonClicked",
|
||||
"command": "kilo-code.new.kiloClawOpen",
|
||||
"group": "navigation@3",
|
||||
"when": "view == kilo-code.SidebarProvider"
|
||||
},
|
||||
{
|
||||
"command": "kilo-code.new.profileButtonClicked",
|
||||
"command": "kilo-code.new.marketplaceButtonClicked",
|
||||
"group": "navigation@4",
|
||||
"when": "view == kilo-code.SidebarProvider"
|
||||
},
|
||||
{
|
||||
"command": "kilo-code.new.settingsButtonClicked",
|
||||
"command": "kilo-code.new.profileButtonClicked",
|
||||
"group": "navigation@5",
|
||||
"when": "view == kilo-code.SidebarProvider"
|
||||
},
|
||||
{
|
||||
"command": "kilo-code.new.settingsButtonClicked",
|
||||
"group": "navigation@6",
|
||||
"when": "view == kilo-code.SidebarProvider"
|
||||
}
|
||||
],
|
||||
"scm/title": [
|
||||
@@ -874,6 +884,7 @@
|
||||
"quick-lru": "^7.0.0",
|
||||
"simple-git": "3.35.2",
|
||||
"solid-js": "^1.9.11",
|
||||
"stream-chat": "9.38.0",
|
||||
"uri-js": "^4.4.1",
|
||||
"web-tree-sitter": "^0.24.7",
|
||||
"yaml": "2.8.3",
|
||||
|
||||
@@ -2,6 +2,7 @@ import * as vscode from "vscode"
|
||||
import { KiloProvider } from "./KiloProvider"
|
||||
import { AgentManagerProvider } from "./agent-manager/AgentManagerProvider"
|
||||
import { VscodeHost } from "./agent-manager/vscode-host"
|
||||
import { KiloClawProvider } from "./kiloclaw/KiloClawProvider"
|
||||
import { DiffViewerProvider } from "./DiffViewerProvider"
|
||||
import { DiffVirtualProvider } from "./DiffVirtualProvider"
|
||||
import { SettingsEditorProvider } from "./SettingsEditorProvider"
|
||||
@@ -94,6 +95,10 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
if (process.platform === "darwin") skip.push("kilo-code.new.agentManager.runScript")
|
||||
ensureCommandsSkipShell(skip)
|
||||
|
||||
// Create KiloClaw chat provider for editor panel
|
||||
const kiloClawProvider = new KiloClawProvider(context.extensionUri, connectionService)
|
||||
context.subscriptions.push(kiloClawProvider)
|
||||
|
||||
// Create Agent Manager provider for editor panel
|
||||
const agentManagerHost = new VscodeHost(context.extensionUri, connectionService, context)
|
||||
const agentManagerProvider = new AgentManagerProvider(agentManagerHost, connectionService)
|
||||
@@ -117,6 +122,16 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
}),
|
||||
)
|
||||
|
||||
// Register serializer so KiloClaw panel restores when VS Code restarts
|
||||
context.subscriptions.push(
|
||||
vscode.window.registerWebviewPanelSerializer(KiloClawProvider.viewType, {
|
||||
deserializeWebviewPanel(panel: vscode.WebviewPanel) {
|
||||
kiloClawProvider.restorePanel(panel)
|
||||
return Promise.resolve()
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
// Register serializer so "Open in Tab" restores when VS Code restarts
|
||||
context.subscriptions.push(
|
||||
vscode.window.registerWebviewPanelSerializer("kilo-code.new.TabPanel", {
|
||||
@@ -211,6 +226,9 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
vscode.commands.registerCommand("kilo-code.new.marketplaceButtonClicked", (directory?: string) => {
|
||||
settingsEditorProvider.openPanel("marketplace", undefined, directory)
|
||||
}),
|
||||
vscode.commands.registerCommand("kilo-code.new.kiloClawOpen", () => {
|
||||
kiloClawProvider.openPanel()
|
||||
}),
|
||||
vscode.commands.registerCommand("kilo-code.new.historyButtonClicked", () => {
|
||||
const tab = activeTabProvider()
|
||||
if (tab) tab.postMessage({ type: "action", action: "historyButtonClicked" })
|
||||
|
||||
@@ -0,0 +1,357 @@
|
||||
/**
|
||||
* KiloClaw panel provider for the VS Code extension.
|
||||
*
|
||||
* Owns the Stream Chat WebSocket connection (in the extension host Node.js runtime)
|
||||
* and relays messages to/from the webview via postMessage.
|
||||
*/
|
||||
|
||||
import * as vscode from "vscode"
|
||||
import { homedir } from "os"
|
||||
import type { KiloConnectionService } from "../services/cli-backend"
|
||||
import { buildWebviewHtml } from "../utils"
|
||||
import { connect, history, presence, type ClawChatClient } from "./chat-client"
|
||||
import type {
|
||||
KiloClawInMessage,
|
||||
KiloClawOutMessage,
|
||||
KiloClawState,
|
||||
ClawStatus,
|
||||
ChatCredentials,
|
||||
ChatMessage,
|
||||
} from "./types"
|
||||
|
||||
const MAX_MESSAGES = 500
|
||||
const STATUS_POLL_MS = 10_000
|
||||
|
||||
export class KiloClawProvider implements vscode.Disposable {
|
||||
static readonly viewType = "kilo-code.new.KiloClawPanel"
|
||||
|
||||
private panel: vscode.WebviewPanel | null = null
|
||||
private chat: ClawChatClient | null = null
|
||||
private timer: ReturnType<typeof setInterval> | null = null
|
||||
private subs: Array<() => void> = []
|
||||
private messages: ChatMessage[] = []
|
||||
private status: ClawStatus | null = null
|
||||
private online = false
|
||||
private connected = false
|
||||
private disposed = false
|
||||
private initializing = false
|
||||
|
||||
constructor(
|
||||
private readonly uri: vscode.Uri,
|
||||
private readonly connection: KiloConnectionService,
|
||||
) {}
|
||||
|
||||
openPanel(): void {
|
||||
if (this.panel) {
|
||||
this.panel.reveal(vscode.ViewColumn.One)
|
||||
return
|
||||
}
|
||||
|
||||
const panel = vscode.window.createWebviewPanel(KiloClawProvider.viewType, "KiloClaw", vscode.ViewColumn.One, {
|
||||
enableScripts: true,
|
||||
retainContextWhenHidden: true,
|
||||
localResourceRoots: [this.uri],
|
||||
})
|
||||
|
||||
this.attach(panel)
|
||||
}
|
||||
|
||||
/** Restore a serialized panel after VS Code restart. */
|
||||
restorePanel(panel: vscode.WebviewPanel): void {
|
||||
this.attach(panel)
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.disposed = true
|
||||
this.cleanup()
|
||||
this.panel?.dispose()
|
||||
this.panel = null
|
||||
}
|
||||
|
||||
// --- private ---
|
||||
|
||||
private attach(panel: vscode.WebviewPanel): void {
|
||||
if (this.panel) {
|
||||
this.cleanup()
|
||||
this.panel.dispose()
|
||||
}
|
||||
this.panel = panel
|
||||
|
||||
panel.iconPath = {
|
||||
light: vscode.Uri.joinPath(this.uri, "assets", "icons", "kilo-light.svg"),
|
||||
dark: vscode.Uri.joinPath(this.uri, "assets", "icons", "kilo-dark.svg"),
|
||||
}
|
||||
|
||||
panel.webview.options = {
|
||||
enableScripts: true,
|
||||
localResourceRoots: [this.uri],
|
||||
}
|
||||
|
||||
panel.webview.html = buildWebviewHtml(panel.webview, {
|
||||
scriptUri: panel.webview.asWebviewUri(vscode.Uri.joinPath(this.uri, "dist", "kiloclaw.js")),
|
||||
styleUri: panel.webview.asWebviewUri(vscode.Uri.joinPath(this.uri, "dist", "kiloclaw.css")),
|
||||
iconsBaseUri: panel.webview.asWebviewUri(vscode.Uri.joinPath(this.uri, "assets", "icons")),
|
||||
title: "KiloClaw",
|
||||
})
|
||||
|
||||
const msgSub = panel.webview.onDidReceiveMessage((msg: KiloClawInMessage) => this.onMessage(msg))
|
||||
this.subs.push(() => msgSub.dispose())
|
||||
const disposeSub = panel.onDidDispose(() => {
|
||||
this.panel = null
|
||||
this.cleanup()
|
||||
})
|
||||
this.subs.push(() => disposeSub.dispose())
|
||||
|
||||
// Pause status polling when the panel is not visible to avoid unnecessary HTTP traffic
|
||||
const viewSub = panel.onDidChangeViewState(() => {
|
||||
if (panel.visible) this.startPolling()
|
||||
else this.stopPolling()
|
||||
})
|
||||
this.subs.push(() => viewSub.dispose())
|
||||
|
||||
// Subscribe to language changes broadcast by other KiloProvider instances
|
||||
const unsub = this.connection.onLanguageChanged((locale) => {
|
||||
this.post({ type: "kiloclaw.locale", locale })
|
||||
})
|
||||
this.subs.push(unsub)
|
||||
}
|
||||
|
||||
private post(msg: KiloClawOutMessage): void {
|
||||
this.panel?.webview.postMessage(msg)
|
||||
}
|
||||
|
||||
private async onMessage(msg: KiloClawInMessage): Promise<void> {
|
||||
switch (msg.type) {
|
||||
case "kiloclaw.ready":
|
||||
await this.init()
|
||||
break
|
||||
case "kiloclaw.send":
|
||||
await this.sendChat(msg.text)
|
||||
break
|
||||
case "kiloclaw.openExternal": {
|
||||
const uri = vscode.Uri.parse(msg.url)
|
||||
if (uri.scheme === "https" || uri.scheme === "http") {
|
||||
void vscode.env.openExternal(uri)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private get locale(): string {
|
||||
const override = vscode.workspace.getConfiguration("kilo-code.new").get<string>("language")
|
||||
return override || vscode.env.language
|
||||
}
|
||||
|
||||
private async init(): Promise<void> {
|
||||
if (this.initializing || this.disposed) return
|
||||
this.initializing = true
|
||||
|
||||
// Track whether we deferred to waitForConnection — if so, keep
|
||||
// `initializing` true so duplicate kiloclaw.ready messages are
|
||||
// harmlessly ignored until the connection arrives.
|
||||
let deferred = false
|
||||
|
||||
try {
|
||||
this.post({ type: "kiloclaw.state", state: { phase: "loading", locale: this.locale } })
|
||||
|
||||
// Ensure the CLI backend is running before trying to get the client.
|
||||
// On VS Code restart the backend hasn't started yet — connect() starts
|
||||
// it lazily (no-op if already connected).
|
||||
if (this.connection.getConnectionState() !== "connected") {
|
||||
try {
|
||||
const dir = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath ?? homedir()
|
||||
await this.connection.connect(dir)
|
||||
} catch (err) {
|
||||
// Connection failed now — wait for another provider to bring it up.
|
||||
console.debug("[Kilo New] KiloClaw connect deferred:", (err as Error)?.message ?? err)
|
||||
deferred = true
|
||||
this.waitForConnection()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
let client
|
||||
try {
|
||||
client = this.connection.getClient()
|
||||
} catch (err) {
|
||||
console.debug("[Kilo New] KiloClaw getClient deferred:", (err as Error)?.message ?? err)
|
||||
deferred = true
|
||||
this.waitForConnection()
|
||||
return
|
||||
}
|
||||
|
||||
// Fetch instance status
|
||||
const res = await client.kilo.claw.status().catch(() => null)
|
||||
if (!res?.data || (res.data as Record<string, unknown>).error) {
|
||||
this.post({ type: "kiloclaw.state", state: { phase: "noInstance", locale: this.locale } })
|
||||
return
|
||||
}
|
||||
|
||||
const data = res.data as ClawStatus & { userId?: string }
|
||||
if (!data.userId) {
|
||||
this.post({ type: "kiloclaw.state", state: { phase: "noInstance", locale: this.locale } })
|
||||
return
|
||||
}
|
||||
|
||||
this.status = data
|
||||
|
||||
// Fetch chat credentials
|
||||
const creds = await client.kilo.claw.chatCredentials().catch(() => null)
|
||||
if (!creds?.data) {
|
||||
this.post({ type: "kiloclaw.state", state: { phase: "needsUpgrade", locale: this.locale } })
|
||||
return
|
||||
}
|
||||
|
||||
const credentials = creds.data as ChatCredentials
|
||||
|
||||
// Connect to Stream Chat
|
||||
try {
|
||||
await this.connectChat(credentials)
|
||||
} catch (err: unknown) {
|
||||
const msg = err instanceof Error ? err.message : String(err)
|
||||
console.error("[Kilo New] KiloClaw chat connect failed:", msg)
|
||||
this.post({
|
||||
type: "kiloclaw.state",
|
||||
state: {
|
||||
phase: "ready",
|
||||
locale: this.locale,
|
||||
status: this.status,
|
||||
connected: false,
|
||||
online: false,
|
||||
messages: [],
|
||||
},
|
||||
})
|
||||
this.post({ type: "kiloclaw.error", error: msg || "Failed to connect to chat" })
|
||||
this.startPolling()
|
||||
return
|
||||
}
|
||||
|
||||
// Push ready state
|
||||
const state: KiloClawState = {
|
||||
phase: "ready",
|
||||
locale: this.locale,
|
||||
status: this.status,
|
||||
connected: this.connected,
|
||||
online: this.online,
|
||||
messages: this.messages,
|
||||
}
|
||||
this.post({ type: "kiloclaw.state", state })
|
||||
this.startPolling()
|
||||
} finally {
|
||||
if (!deferred) this.initializing = false
|
||||
}
|
||||
}
|
||||
|
||||
private async connectChat(creds: ChatCredentials): Promise<void> {
|
||||
this.chat = await connect(creds)
|
||||
|
||||
// Load history
|
||||
const bot = `bot-${creds.channelId.replace(/^default-/, "")}`
|
||||
this.messages = history(this.chat.channel, bot)
|
||||
this.online = presence(this.chat.channel, bot)
|
||||
this.connected = true
|
||||
|
||||
// Subscribe to events and relay to webview
|
||||
const unsub = this.chat.onMessage((msg) => {
|
||||
this.messages = [...this.messages, msg]
|
||||
if (this.messages.length > MAX_MESSAGES) {
|
||||
this.messages = this.messages.slice(-MAX_MESSAGES)
|
||||
}
|
||||
this.post({ type: "kiloclaw.message", message: msg })
|
||||
})
|
||||
this.subs.push(unsub)
|
||||
|
||||
const unsubUpdated = this.chat.onMessageUpdated((msg) => {
|
||||
const idx = this.messages.findIndex((m) => m.id === msg.id)
|
||||
if (idx === -1) {
|
||||
this.messages = [...this.messages, msg]
|
||||
if (this.messages.length > MAX_MESSAGES) {
|
||||
this.messages = this.messages.slice(-MAX_MESSAGES)
|
||||
}
|
||||
} else {
|
||||
this.messages = this.messages.map((m, i) => (i === idx ? msg : m))
|
||||
}
|
||||
this.post({ type: "kiloclaw.messageUpdated", message: msg })
|
||||
})
|
||||
this.subs.push(unsubUpdated)
|
||||
|
||||
const unsubPresence = this.chat.onPresence((val) => {
|
||||
this.online = val
|
||||
this.post({ type: "kiloclaw.presence", online: val })
|
||||
})
|
||||
this.subs.push(unsubPresence)
|
||||
}
|
||||
|
||||
private async sendChat(text: string): Promise<void> {
|
||||
if (!this.chat) {
|
||||
this.post({ type: "kiloclaw.error", error: "Chat not connected" })
|
||||
return
|
||||
}
|
||||
try {
|
||||
await this.chat.send(text)
|
||||
} catch (err) {
|
||||
console.error("[Kilo New] KiloClaw send failed:", err instanceof Error ? err.message : err)
|
||||
this.post({ type: "kiloclaw.error", error: "Failed to send message" })
|
||||
}
|
||||
}
|
||||
|
||||
private startPolling(): void {
|
||||
if (this.timer) return
|
||||
this.timer = setInterval(() => void this.poll(), STATUS_POLL_MS)
|
||||
}
|
||||
|
||||
private stopPolling(): void {
|
||||
if (!this.timer) return
|
||||
clearInterval(this.timer)
|
||||
this.timer = null
|
||||
}
|
||||
|
||||
private async poll(): Promise<void> {
|
||||
try {
|
||||
const client = this.connection.getClient()
|
||||
const res = await client.kilo.claw.status()
|
||||
if (res?.data) {
|
||||
this.status = res.data as ClawStatus
|
||||
this.post({ type: "kiloclaw.status", data: this.status })
|
||||
}
|
||||
} catch (err) {
|
||||
console.debug("[Kilo New] KiloClaw poll failed:", (err as Error)?.message ?? err)
|
||||
}
|
||||
}
|
||||
|
||||
/** Subscribe to connection state changes and re-run init() once connected. */
|
||||
private waitForConnection(): void {
|
||||
const unsub = this.connection.onStateChange((state) => {
|
||||
if (state === "connected" && !this.disposed) {
|
||||
unsub()
|
||||
this.initializing = false
|
||||
void this.init()
|
||||
}
|
||||
})
|
||||
this.subs.push(unsub)
|
||||
}
|
||||
|
||||
private cleanup(): void {
|
||||
for (const unsub of this.subs) unsub()
|
||||
this.subs = []
|
||||
|
||||
if (this.timer) {
|
||||
clearInterval(this.timer)
|
||||
this.timer = null
|
||||
}
|
||||
|
||||
if (this.chat) {
|
||||
this.chat.disconnect().catch((err) => {
|
||||
console.error("[Kilo New] KiloClaw disconnect failed:", err?.message ?? err)
|
||||
})
|
||||
this.chat = null
|
||||
}
|
||||
|
||||
this.messages = []
|
||||
this.connected = false
|
||||
this.online = false
|
||||
this.initializing = false
|
||||
this.status = null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* KiloClaw Stream Chat client wrapper for the VS Code extension host.
|
||||
*
|
||||
* Port of packages/opencode/src/kilocode/claw/client.ts adapted for Node.js.
|
||||
* No Bun patches needed — the extension host runs in standard Node.js.
|
||||
* stream-chat resolves to its Node.js CJS entry point automatically.
|
||||
*/
|
||||
|
||||
import type { Channel, Event } from "stream-chat"
|
||||
import type { ChatCredentials, ChatMessage } from "./types"
|
||||
|
||||
export type ClawChatClient = {
|
||||
channel: Channel
|
||||
disconnect: () => Promise<void>
|
||||
send: (text: string) => Promise<void>
|
||||
onMessage: (cb: (msg: ChatMessage) => void) => () => void
|
||||
onMessageUpdated: (cb: (msg: ChatMessage) => void) => () => void
|
||||
onPresence: (cb: (online: boolean) => void) => () => void
|
||||
}
|
||||
|
||||
function botId(creds: ChatCredentials): string {
|
||||
return `bot-${creds.channelId.replace(/^default-/, "")}`
|
||||
}
|
||||
|
||||
function toMessage(raw: Record<string, unknown>, bot: string): ChatMessage {
|
||||
const user = raw.user as Record<string, unknown> | undefined
|
||||
const uid = (user?.id as string) ?? (raw.user_id as string) ?? ""
|
||||
return {
|
||||
id: (raw.id as string) ?? "",
|
||||
text: (raw.text as string) ?? "",
|
||||
user: uid,
|
||||
created: raw.created_at ? new Date(raw.created_at as string).toISOString() : new Date().toISOString(),
|
||||
bot: uid === bot,
|
||||
}
|
||||
}
|
||||
|
||||
export async function connect(creds: ChatCredentials): Promise<ClawChatClient> {
|
||||
const { StreamChat } = await import("stream-chat")
|
||||
// Use a fresh instance instead of the singleton to avoid stale state
|
||||
// (cached channels, event listeners) when credentials rotate.
|
||||
const client = new StreamChat(creds.apiKey)
|
||||
|
||||
await client.connectUser({ id: creds.userId }, creds.userToken)
|
||||
|
||||
const channel = client.channel("messaging", creds.channelId)
|
||||
await channel.watch({ presence: true })
|
||||
|
||||
const bot = botId(creds)
|
||||
|
||||
return {
|
||||
channel,
|
||||
async disconnect() {
|
||||
await client.disconnectUser()
|
||||
},
|
||||
async send(text: string) {
|
||||
await channel.sendMessage({ text })
|
||||
},
|
||||
onMessage(cb) {
|
||||
const handler = (event: Event) => {
|
||||
if (event.message) cb(toMessage(event.message as unknown as Record<string, unknown>, bot))
|
||||
}
|
||||
channel.on("message.new", handler)
|
||||
return () => channel.off("message.new", handler)
|
||||
},
|
||||
onMessageUpdated(cb) {
|
||||
const handler = (event: Event) => {
|
||||
if (event.message) cb(toMessage(event.message as unknown as Record<string, unknown>, bot))
|
||||
}
|
||||
channel.on("message.updated", handler)
|
||||
return () => channel.off("message.updated", handler)
|
||||
},
|
||||
onPresence(cb) {
|
||||
const handler = (event: Event) => {
|
||||
if (event.user?.id === bot) {
|
||||
cb(event.user.online ?? false)
|
||||
}
|
||||
}
|
||||
client.on("user.presence.changed", handler)
|
||||
return () => client.off("user.presence.changed", handler)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export function history(channel: Channel, bot: string): ChatMessage[] {
|
||||
const state = channel.state.messages
|
||||
return state.map((raw) => toMessage(raw as unknown as Record<string, unknown>, bot))
|
||||
}
|
||||
|
||||
export function presence(channel: Channel, bot: string): boolean {
|
||||
const member = channel.state.members?.[bot]
|
||||
return !!member?.user?.online
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* KiloClaw VS Code extension message types.
|
||||
*
|
||||
* Defines the postMessage protocol between the extension host (Node.js)
|
||||
* and the KiloClaw webview (SolidJS). The extension host owns all network
|
||||
* connections (SDK + Stream Chat) and relays data to the webview.
|
||||
*
|
||||
* SYNC: Shared types (ClawStatus, ChatMessage, KiloClawState, KiloClawOutMessage)
|
||||
* are mirrored in webview-ui/kiloclaw/lib/types.ts — keep both in sync.
|
||||
*/
|
||||
|
||||
export type ClawStatus = {
|
||||
status: "provisioned" | "starting" | "restarting" | "running" | "stopped" | "destroying" | null
|
||||
sandboxId?: string
|
||||
flyRegion?: string
|
||||
machineSize?: { cpus: number; memory_mb: number }
|
||||
openclawVersion?: string | null
|
||||
lastStartedAt?: string | null
|
||||
lastStoppedAt?: string | null
|
||||
channelCount?: number
|
||||
secretCount?: number
|
||||
}
|
||||
|
||||
export type ChatCredentials = {
|
||||
apiKey: string
|
||||
userId: string
|
||||
userToken: string
|
||||
channelId: string
|
||||
}
|
||||
|
||||
export type ChatMessage = {
|
||||
id: string
|
||||
text: string
|
||||
user: string
|
||||
created: string // ISO string (serializable via postMessage)
|
||||
bot: boolean
|
||||
}
|
||||
|
||||
// Full state snapshot pushed to the webview
|
||||
// Every phase carries `locale` so the webview can resolve translations immediately.
|
||||
export type KiloClawState =
|
||||
| { phase: "loading"; locale: string }
|
||||
| { phase: "noInstance"; locale: string }
|
||||
| { phase: "needsUpgrade"; locale: string }
|
||||
| {
|
||||
phase: "ready"
|
||||
locale: string
|
||||
status: ClawStatus | null
|
||||
connected: boolean
|
||||
online: boolean
|
||||
messages: ChatMessage[]
|
||||
}
|
||||
|
||||
// Messages: Webview → Extension Host
|
||||
export type KiloClawInMessage =
|
||||
| { type: "kiloclaw.ready" }
|
||||
| { type: "kiloclaw.send"; text: string }
|
||||
| { type: "kiloclaw.openExternal"; url: string }
|
||||
|
||||
// Messages: Extension Host → Webview
|
||||
export type KiloClawOutMessage =
|
||||
| { type: "kiloclaw.state"; state: KiloClawState }
|
||||
| { type: "kiloclaw.message"; message: ChatMessage }
|
||||
| { type: "kiloclaw.messageUpdated"; message: ChatMessage }
|
||||
| { type: "kiloclaw.presence"; online: boolean }
|
||||
| { type: "kiloclaw.status"; data: ClawStatus | null }
|
||||
| { type: "kiloclaw.locale"; locale: string }
|
||||
| { type: "kiloclaw.error"; error: string }
|
||||
@@ -0,0 +1,63 @@
|
||||
// KiloClaw root component
|
||||
|
||||
import { Show, Switch, Match } from "solid-js"
|
||||
import { ThemeProvider } from "@kilocode/kilo-ui/theme"
|
||||
import { ClawProvider, useClaw } from "./context/claw"
|
||||
import { KiloClawLanguageProvider, useKiloClawLanguage } from "./context/language"
|
||||
import { ChatPanel } from "./components/ChatPanel"
|
||||
import { StatusSidebar } from "./components/StatusSidebar"
|
||||
import { SetupView } from "./components/SetupView"
|
||||
import { UpgradeView } from "./components/UpgradeView"
|
||||
|
||||
function Content() {
|
||||
const claw = useClaw()
|
||||
const { t } = useKiloClawLanguage()
|
||||
|
||||
return (
|
||||
<div class="kiloclaw-root">
|
||||
<Switch>
|
||||
<Match when={claw.phase() === "loading"}>
|
||||
<div class="kiloclaw-center">
|
||||
<div class="kiloclaw-loading">
|
||||
<div class="kiloclaw-spinner" />
|
||||
<span>{t("kiloClaw.loading")}</span>
|
||||
</div>
|
||||
</div>
|
||||
</Match>
|
||||
<Match when={claw.phase() === "noInstance"}>
|
||||
<SetupView />
|
||||
</Match>
|
||||
<Match when={claw.phase() === "needsUpgrade"}>
|
||||
<UpgradeView />
|
||||
</Match>
|
||||
<Match when={claw.phase() === "ready"}>
|
||||
<div class="kiloclaw-layout">
|
||||
<ChatPanel />
|
||||
<StatusSidebar />
|
||||
</div>
|
||||
</Match>
|
||||
</Switch>
|
||||
<Show when={claw.error()}>
|
||||
<div class="kiloclaw-toast">{claw.error()}</div>
|
||||
</Show>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function KiloClawApp() {
|
||||
return (
|
||||
<ThemeProvider>
|
||||
<ClawProvider>
|
||||
<LanguageBridge>
|
||||
<Content />
|
||||
</LanguageBridge>
|
||||
</ClawProvider>
|
||||
</ThemeProvider>
|
||||
)
|
||||
}
|
||||
|
||||
/** Bridges the claw context locale into the language provider. Must be below ClawProvider. */
|
||||
function LanguageBridge(props: { children: any }) {
|
||||
const claw = useClaw()
|
||||
return <KiloClawLanguageProvider locale={claw.locale}>{props.children}</KiloClawLanguageProvider>
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
// KiloClaw chat panel — message list + input
|
||||
|
||||
import { createSignal, createEffect, For, Show, createMemo, onMount } from "solid-js"
|
||||
import { useClaw } from "../context/claw"
|
||||
import { useKiloClawLanguage } from "../context/language"
|
||||
import { MessageBubble } from "./MessageBubble"
|
||||
|
||||
export function ChatPanel() {
|
||||
const claw = useClaw()
|
||||
const { t } = useKiloClawLanguage()
|
||||
const [text, setText] = createSignal("")
|
||||
let list!: HTMLDivElement
|
||||
let input!: HTMLTextAreaElement
|
||||
|
||||
const disabled = createMemo(() => {
|
||||
const s = claw.status()
|
||||
return !s || s.status !== "running" || !claw.connected()
|
||||
})
|
||||
|
||||
const placeholder = createMemo(() => {
|
||||
if (!claw.connected()) return t("kiloClaw.chat.connecting")
|
||||
const s = claw.status()
|
||||
if (!s || s.status !== "running") return t("kiloClaw.chat.notRunning")
|
||||
return t("kiloClaw.chat.placeholder")
|
||||
})
|
||||
|
||||
// Auto-scroll to bottom when messages change
|
||||
createEffect(() => {
|
||||
claw.messages()
|
||||
if (list) {
|
||||
requestAnimationFrame(() => {
|
||||
list.scrollTop = list.scrollHeight
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Focus input on mount
|
||||
onMount(() => {
|
||||
if (input && !disabled()) input.focus()
|
||||
})
|
||||
|
||||
const submit = () => {
|
||||
const val = text().trim()
|
||||
if (!val || disabled()) return
|
||||
claw.send(val)
|
||||
setText("")
|
||||
if (input) {
|
||||
input.style.height = "auto"
|
||||
}
|
||||
}
|
||||
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.key === "Enter" && !e.shiftKey) {
|
||||
e.preventDefault()
|
||||
submit()
|
||||
}
|
||||
}
|
||||
|
||||
const onInput = (e: InputEvent) => {
|
||||
const target = e.target as HTMLTextAreaElement
|
||||
setText(target.value)
|
||||
// Auto-resize
|
||||
target.style.height = "auto"
|
||||
target.style.height = Math.min(target.scrollHeight, 120) + "px"
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="kiloclaw-chat">
|
||||
{/* Header */}
|
||||
<div class="kiloclaw-chat-header">
|
||||
<div class="kiloclaw-chat-header-left">
|
||||
<span class={`kiloclaw-dot ${claw.online() ? "kiloclaw-dot-online" : "kiloclaw-dot-offline"}`} />
|
||||
<span class="kiloclaw-chat-header-title">
|
||||
KiloClaw {claw.online() ? t("kiloClaw.chat.online") : t("kiloClaw.chat.offline")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Messages */}
|
||||
<div class="kiloclaw-messages" ref={list}>
|
||||
<Show when={claw.messages().length === 0 && claw.connected()}>
|
||||
<div class="kiloclaw-empty">{t("kiloClaw.chat.empty")}</div>
|
||||
</Show>
|
||||
<For each={claw.messages()}>{(msg) => <MessageBubble message={msg} />}</For>
|
||||
</div>
|
||||
|
||||
{/* Input */}
|
||||
<div class="kiloclaw-input-wrap">
|
||||
<textarea
|
||||
ref={input}
|
||||
class="kiloclaw-input"
|
||||
placeholder={placeholder()}
|
||||
disabled={disabled()}
|
||||
value={text()}
|
||||
onInput={onInput}
|
||||
onKeyDown={onKeyDown}
|
||||
rows={1}
|
||||
/>
|
||||
<button class="kiloclaw-send-btn" disabled={disabled() || !text().trim()} onClick={submit}>
|
||||
{t("kiloClaw.chat.send")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Individual chat message bubble
|
||||
|
||||
import { Show, createMemo } from "solid-js"
|
||||
import type { ChatMessage } from "../lib/types"
|
||||
import { useKiloClawLanguage } from "../context/language"
|
||||
|
||||
function formatTime(iso: string): string {
|
||||
const d = new Date(iso)
|
||||
return d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })
|
||||
}
|
||||
|
||||
export function MessageBubble(props: { message: ChatMessage }) {
|
||||
const { t } = useKiloClawLanguage()
|
||||
const empty = createMemo(() => !props.message.text || !props.message.text.trim())
|
||||
|
||||
return (
|
||||
<div class={`kiloclaw-msg ${props.message.bot ? "kiloclaw-msg-bot" : "kiloclaw-msg-user"}`}>
|
||||
<div class="kiloclaw-msg-header">
|
||||
<span class="kiloclaw-msg-author">
|
||||
{props.message.bot ? t("kiloClaw.message.bot") : t("kiloClaw.message.you")}
|
||||
</span>
|
||||
<span class="kiloclaw-msg-time">{formatTime(props.message.created)}</span>
|
||||
</div>
|
||||
<div class="kiloclaw-msg-body">
|
||||
<Show when={!empty()} fallback={<span class="kiloclaw-msg-thinking">{t("kiloClaw.message.thinking")}</span>}>
|
||||
{props.message.text}
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// KiloClaw setup view — shown when no instance is provisioned
|
||||
|
||||
import { useClaw } from "../context/claw"
|
||||
import { useKiloClawLanguage } from "../context/language"
|
||||
|
||||
export function SetupView() {
|
||||
const claw = useClaw()
|
||||
const { t } = useKiloClawLanguage()
|
||||
|
||||
return (
|
||||
<div class="kiloclaw-center">
|
||||
<div class="kiloclaw-card">
|
||||
<h2 class="kiloclaw-card-title">{t("kiloClaw.setup.title")}</h2>
|
||||
<h3 class="kiloclaw-card-subtitle">{t("kiloClaw.setup.subtitle")}</h3>
|
||||
<p class="kiloclaw-card-text">{t("kiloClaw.setup.description1")}</p>
|
||||
<p class="kiloclaw-card-text">{t("kiloClaw.setup.description2")}</p>
|
||||
<div class="kiloclaw-card-actions">
|
||||
<button class="kiloclaw-link-btn" onClick={() => claw.openExternal("https://kilo.ai/kiloclaw")}>
|
||||
{t("kiloClaw.setup.learnMore")}
|
||||
</button>
|
||||
<button class="kiloclaw-primary-btn" onClick={() => claw.openExternal("https://app.kilo.ai/claw")}>
|
||||
{t("kiloClaw.setup.tryKiloClaw")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
// KiloClaw status sidebar — instance info, bot presence, details
|
||||
|
||||
import { Show, createMemo } from "solid-js"
|
||||
import { useClaw } from "../context/claw"
|
||||
import { useKiloClawLanguage } from "../context/language"
|
||||
|
||||
function dot(status: string | null | undefined): string {
|
||||
if (!status) return "kiloclaw-dot-offline"
|
||||
if (status === "running") return "kiloclaw-dot-online"
|
||||
if (status === "starting" || status === "restarting") return "kiloclaw-dot-warning"
|
||||
if (status === "destroying") return "kiloclaw-dot-error"
|
||||
return "kiloclaw-dot-offline"
|
||||
}
|
||||
|
||||
function uptime(started: string | null | undefined): string {
|
||||
if (!started) return "\u2014"
|
||||
const ms = Date.now() - new Date(started).getTime()
|
||||
if (ms < 0) return "\u2014"
|
||||
const seconds = Math.floor(ms / 1000)
|
||||
const minutes = Math.floor(seconds / 60)
|
||||
const hours = Math.floor(minutes / 60)
|
||||
const days = Math.floor(hours / 24)
|
||||
if (days > 0) return `${days}d ${hours % 24}h`
|
||||
if (hours > 0) return `${hours}h ${minutes % 60}m`
|
||||
if (minutes > 0) return `${minutes}m`
|
||||
return `${seconds}s`
|
||||
}
|
||||
|
||||
function capitalize(s: string | null | undefined, fallback: string): string {
|
||||
if (!s) return fallback
|
||||
return s.charAt(0).toUpperCase() + s.slice(1)
|
||||
}
|
||||
|
||||
export function StatusSidebar() {
|
||||
const claw = useClaw()
|
||||
const { t } = useKiloClawLanguage()
|
||||
const status = createMemo(() => claw.status())
|
||||
|
||||
return (
|
||||
<div class="kiloclaw-sidebar">
|
||||
<h3 class="kiloclaw-sidebar-title">{t("kiloClaw.sidebar.title")}</h3>
|
||||
|
||||
<Show when={status()}>
|
||||
<div class="kiloclaw-sidebar-section">
|
||||
<div class="kiloclaw-sidebar-label">{t("kiloClaw.sidebar.instance")}</div>
|
||||
<div class="kiloclaw-sidebar-row">
|
||||
<span class={`kiloclaw-dot ${dot(status()!.status)}`} />
|
||||
<span>
|
||||
{capitalize(status()!.status, t("kiloClaw.sidebar.unknown"))}
|
||||
<Show when={status()!.status === "running"}>
|
||||
<span class="kiloclaw-sidebar-muted"> {uptime(status()!.lastStartedAt)}</span>
|
||||
</Show>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="kiloclaw-sidebar-section">
|
||||
<div class="kiloclaw-sidebar-label">{t("kiloClaw.sidebar.bot")}</div>
|
||||
<div class="kiloclaw-sidebar-row">
|
||||
<span class={`kiloclaw-dot ${claw.online() ? "kiloclaw-dot-online" : "kiloclaw-dot-offline"}`} />
|
||||
<span>{claw.online() ? t("kiloClaw.chat.online") : t("kiloClaw.chat.offline")}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="kiloclaw-sidebar-section">
|
||||
<div class="kiloclaw-sidebar-label">{t("kiloClaw.sidebar.details")}</div>
|
||||
<div class="kiloclaw-sidebar-detail">
|
||||
<span class="kiloclaw-sidebar-muted">{t("kiloClaw.sidebar.region")}</span>
|
||||
<span>{status()!.flyRegion?.toUpperCase() ?? "\u2014"}</span>
|
||||
</div>
|
||||
<div class="kiloclaw-sidebar-detail">
|
||||
<span class="kiloclaw-sidebar-muted">{t("kiloClaw.sidebar.version")}</span>
|
||||
<span>{status()!.openclawVersion ?? "\u2014"}</span>
|
||||
</div>
|
||||
<Show
|
||||
when={
|
||||
status()!.channelCount !== null &&
|
||||
status()!.channelCount !== undefined &&
|
||||
(status()!.channelCount ?? 0) >= 1
|
||||
}
|
||||
>
|
||||
<div class="kiloclaw-sidebar-detail">
|
||||
<span class="kiloclaw-sidebar-muted">{t("kiloClaw.sidebar.channels")}</span>
|
||||
<span>{status()!.channelCount}</span>
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
<Show when={!status()}>
|
||||
<div class="kiloclaw-sidebar-section">
|
||||
<span class="kiloclaw-sidebar-muted">{t("kiloClaw.sidebar.noData")}</span>
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// KiloClaw upgrade view — shown when instance needs upgrade for chat
|
||||
|
||||
import { useClaw } from "../context/claw"
|
||||
import { useKiloClawLanguage } from "../context/language"
|
||||
|
||||
export function UpgradeView() {
|
||||
const claw = useClaw()
|
||||
const { t } = useKiloClawLanguage()
|
||||
|
||||
return (
|
||||
<div class="kiloclaw-center">
|
||||
<div class="kiloclaw-card">
|
||||
<h2 class="kiloclaw-card-title">{t("kiloClaw.upgrade.title")}</h2>
|
||||
<p class="kiloclaw-card-text">{t("kiloClaw.upgrade.description1")}</p>
|
||||
<p class="kiloclaw-card-text">
|
||||
{t("kiloClaw.upgrade.description2.before")}
|
||||
<strong>{t("kiloClaw.upgrade.description2.bold")}</strong>
|
||||
{t("kiloClaw.upgrade.description2.after")}
|
||||
</p>
|
||||
<div class="kiloclaw-card-actions">
|
||||
<div />
|
||||
<button class="kiloclaw-primary-btn" onClick={() => claw.openExternal("https://app.kilo.ai/claw")}>
|
||||
{t("kiloClaw.upgrade.openDashboard")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
// KiloClaw state context
|
||||
//
|
||||
// All data arrives from the extension host via postMessage.
|
||||
// The webview has no direct network access.
|
||||
|
||||
import { createContext, createSignal, onMount, onCleanup, useContext, type JSX } from "solid-js"
|
||||
import type { ClawStatus, ChatMessage, KiloClawOutMessage } from "../lib/types"
|
||||
|
||||
type VSCodeAPI = {
|
||||
postMessage(msg: unknown): void
|
||||
getState(): unknown
|
||||
setState(state: unknown): void
|
||||
}
|
||||
|
||||
declare function acquireVsCodeApi(): VSCodeAPI
|
||||
|
||||
const vscode = acquireVsCodeApi()
|
||||
|
||||
const MAX_MESSAGES = 500
|
||||
|
||||
type Phase = "loading" | "noInstance" | "needsUpgrade" | "ready"
|
||||
|
||||
type ClawCtx = {
|
||||
phase: () => Phase
|
||||
locale: () => string | undefined
|
||||
status: () => ClawStatus | null
|
||||
messages: () => ChatMessage[]
|
||||
online: () => boolean
|
||||
connected: () => boolean
|
||||
error: () => string | null
|
||||
send: (text: string) => void
|
||||
openExternal: (url: string) => void
|
||||
}
|
||||
|
||||
const ClawContext = createContext<ClawCtx>()
|
||||
|
||||
export function ClawProvider(props: { children: JSX.Element }) {
|
||||
const [phase, setPhase] = createSignal<Phase>("loading")
|
||||
const [locale, setLocale] = createSignal<string | undefined>(undefined)
|
||||
const [status, setStatus] = createSignal<ClawStatus | null>(null)
|
||||
const [messages, setMessages] = createSignal<ChatMessage[]>([])
|
||||
const [online, setOnline] = createSignal(false)
|
||||
const [connected, setConnected] = createSignal(false)
|
||||
const [error, setError] = createSignal<string | null>(null)
|
||||
|
||||
const handler = (event: MessageEvent) => {
|
||||
const msg = event.data as KiloClawOutMessage
|
||||
if (!msg?.type?.startsWith("kiloclaw.")) return
|
||||
|
||||
switch (msg.type) {
|
||||
case "kiloclaw.state": {
|
||||
const s = msg.state
|
||||
setPhase(s.phase)
|
||||
setLocale(s.locale)
|
||||
if (s.phase === "ready") {
|
||||
setStatus(s.status)
|
||||
setConnected(s.connected)
|
||||
setOnline(s.online)
|
||||
setMessages(s.messages)
|
||||
}
|
||||
break
|
||||
}
|
||||
case "kiloclaw.message":
|
||||
setMessages((prev) => {
|
||||
const next = [...prev, msg.message]
|
||||
return next.length > MAX_MESSAGES ? next.slice(-MAX_MESSAGES) : next
|
||||
})
|
||||
break
|
||||
case "kiloclaw.messageUpdated": {
|
||||
setMessages((prev) => {
|
||||
const idx = prev.findIndex((m) => m.id === msg.message.id)
|
||||
if (idx === -1) {
|
||||
const next = [...prev, msg.message]
|
||||
return next.length > MAX_MESSAGES ? next.slice(-MAX_MESSAGES) : next
|
||||
}
|
||||
return prev.map((m, i) => (i === idx ? msg.message : m))
|
||||
})
|
||||
break
|
||||
}
|
||||
case "kiloclaw.presence":
|
||||
setOnline(msg.online)
|
||||
break
|
||||
case "kiloclaw.status":
|
||||
setStatus(msg.data)
|
||||
break
|
||||
case "kiloclaw.locale":
|
||||
setLocale(msg.locale)
|
||||
break
|
||||
case "kiloclaw.error":
|
||||
setError(msg.error)
|
||||
// Auto-clear after 5s
|
||||
setTimeout(() => setError(null), 5000)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Register listener immediately (before mount) to catch early pushes
|
||||
window.addEventListener("message", handler)
|
||||
onCleanup(() => window.removeEventListener("message", handler))
|
||||
|
||||
onMount(() => {
|
||||
vscode.postMessage({ type: "kiloclaw.ready" })
|
||||
})
|
||||
|
||||
const ctx: ClawCtx = {
|
||||
phase,
|
||||
locale,
|
||||
status,
|
||||
messages,
|
||||
online,
|
||||
connected,
|
||||
error,
|
||||
send: (text: string) => vscode.postMessage({ type: "kiloclaw.send", text }),
|
||||
openExternal: (url: string) => vscode.postMessage({ type: "kiloclaw.openExternal", url }),
|
||||
}
|
||||
|
||||
return <ClawContext.Provider value={ctx}>{props.children}</ClawContext.Provider>
|
||||
}
|
||||
|
||||
export function useClaw(): ClawCtx {
|
||||
const ctx = useContext(ClawContext)
|
||||
if (!ctx) throw new Error("useClaw must be used within ClawProvider")
|
||||
return ctx
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// KiloClaw lightweight language context
|
||||
//
|
||||
// Self-contained i18n for the KiloClaw panel. Does not depend on
|
||||
// VSCodeProvider/ServerProvider — locale comes from the extension host
|
||||
// via the claw context, falling back to navigator.language then "en".
|
||||
|
||||
import { createContext, createMemo, useContext, type JSX } from "solid-js"
|
||||
import { normalizeLocale, resolveTemplate } from "../../src/context/language-utils"
|
||||
import type { Locale } from "../../src/context/language-utils"
|
||||
import { dict as en } from "../i18n/en"
|
||||
import { dict as ar } from "../i18n/ar"
|
||||
import { dict as br } from "../i18n/br"
|
||||
import { dict as bs } from "../i18n/bs"
|
||||
import { dict as da } from "../i18n/da"
|
||||
import { dict as de } from "../i18n/de"
|
||||
import { dict as es } from "../i18n/es"
|
||||
import { dict as fr } from "../i18n/fr"
|
||||
import { dict as ja } from "../i18n/ja"
|
||||
import { dict as ko } from "../i18n/ko"
|
||||
import { dict as nl } from "../i18n/nl"
|
||||
import { dict as no } from "../i18n/no"
|
||||
import { dict as pl } from "../i18n/pl"
|
||||
import { dict as ru } from "../i18n/ru"
|
||||
import { dict as th } from "../i18n/th"
|
||||
import { dict as tr } from "../i18n/tr"
|
||||
import { dict as zh } from "../i18n/zh"
|
||||
import { dict as zht } from "../i18n/zht"
|
||||
|
||||
const dicts: Record<Locale, Record<string, string>> = {
|
||||
en,
|
||||
ar: { ...en, ...ar },
|
||||
br: { ...en, ...br },
|
||||
bs: { ...en, ...bs },
|
||||
da: { ...en, ...da },
|
||||
de: { ...en, ...de },
|
||||
es: { ...en, ...es },
|
||||
fr: { ...en, ...fr },
|
||||
ja: { ...en, ...ja },
|
||||
ko: { ...en, ...ko },
|
||||
nl: { ...en, ...nl },
|
||||
no: { ...en, ...no },
|
||||
pl: { ...en, ...pl },
|
||||
ru: { ...en, ...ru },
|
||||
th: { ...en, ...th },
|
||||
tr: { ...en, ...tr },
|
||||
zh: { ...en, ...zh },
|
||||
zht: { ...en, ...zht },
|
||||
}
|
||||
|
||||
type LanguageCtx = {
|
||||
t: (key: string, params?: Record<string, string | number | boolean | undefined>) => string
|
||||
}
|
||||
|
||||
const LanguageContext = createContext<LanguageCtx>()
|
||||
|
||||
export function KiloClawLanguageProvider(props: { locale: () => string | undefined; children: JSX.Element }) {
|
||||
const resolved = createMemo<Locale>(() => {
|
||||
const ext = props.locale()
|
||||
if (ext) return normalizeLocale(ext)
|
||||
if (typeof navigator !== "undefined" && navigator.language) return normalizeLocale(navigator.language)
|
||||
return "en"
|
||||
})
|
||||
|
||||
const dict = createMemo(() => dicts[resolved()] ?? dicts.en)
|
||||
|
||||
const t = (key: string, params?: Record<string, string | number | boolean | undefined>) => {
|
||||
const text = dict()[key] ?? key
|
||||
return resolveTemplate(text, params)
|
||||
}
|
||||
|
||||
return <LanguageContext.Provider value={{ t }}>{props.children}</LanguageContext.Provider>
|
||||
}
|
||||
|
||||
export function useKiloClawLanguage(): LanguageCtx {
|
||||
const ctx = useContext(LanguageContext)
|
||||
if (!ctx) throw new Error("useKiloClawLanguage must be used within KiloClawLanguageProvider")
|
||||
return ctx
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
export const dict = {
|
||||
"kiloClaw.loading": "جاري تحميل KiloClaw...",
|
||||
"kiloClaw.chat.connecting": "جاري الاتصال...",
|
||||
"kiloClaw.chat.notRunning": "المثيل لا يعمل",
|
||||
"kiloClaw.chat.placeholder": "اكتب رسالة... (اضغط Enter للإرسال)",
|
||||
"kiloClaw.chat.online": "متصل",
|
||||
"kiloClaw.chat.offline": "غير متصل",
|
||||
"kiloClaw.chat.empty": "لا توجد رسائل بعد. قُل مرحباً!",
|
||||
"kiloClaw.chat.send": "إرسال",
|
||||
"kiloClaw.message.bot": "KiloClaw",
|
||||
"kiloClaw.message.you": "أنت",
|
||||
"kiloClaw.message.thinking": "يفكر...",
|
||||
"kiloClaw.setup.title": "KiloClaw",
|
||||
"kiloClaw.setup.subtitle": "ذكاء اصطناعي شخصي للحياة اليومية",
|
||||
"kiloClaw.setup.description1":
|
||||
"يمنحك KiloClaw ذكاءً اصطناعياً شخصياً يقرأ البريد الإلكتروني، ويدير تقويمك، ويراقب مشاريعك، ويتواجد في Telegram و Slack — وأي شيء تستخدمه بالفعل.",
|
||||
"kiloClaw.setup.description2": "لا يوجد تطبيق لتثبيته. لا توجد واجهة جديدة لتعلمها. فقط أرسل له رسالة كصديق.",
|
||||
"kiloClaw.setup.learnMore": "معرفة المزيد",
|
||||
"kiloClaw.setup.tryKiloClaw": "جرب KiloClaw",
|
||||
"kiloClaw.upgrade.title": "تتطلب دردشة KiloClaw ترقية",
|
||||
"kiloClaw.upgrade.description1": "تم إعداد هذا المثيل قبل تفعيل الدردشة.",
|
||||
"kiloClaw.upgrade.description2.before": "استخدم زر ",
|
||||
"kiloClaw.upgrade.description2.bold": "الترقية إلى الأحدث",
|
||||
"kiloClaw.upgrade.description2.after": " في لوحة تحكم KiloClaw لتنشيط الدردشة في الوقت الفعلي مع الروبوت الخاص بك.",
|
||||
"kiloClaw.upgrade.openDashboard": "فتح لوحة التحكم",
|
||||
"kiloClaw.sidebar.title": "KiloClaw",
|
||||
"kiloClaw.sidebar.instance": "المثيل",
|
||||
"kiloClaw.sidebar.unknown": "غير معروف",
|
||||
"kiloClaw.sidebar.bot": "الروبوت",
|
||||
"kiloClaw.sidebar.details": "التفاصيل",
|
||||
"kiloClaw.sidebar.region": "المنطقة",
|
||||
"kiloClaw.sidebar.version": "الإصدار",
|
||||
"kiloClaw.sidebar.channels": "القنوات",
|
||||
"kiloClaw.sidebar.noData": "لا توجد بيانات للمثيل",
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
export const dict = {
|
||||
"kiloClaw.loading": "Carregando KiloClaw...",
|
||||
"kiloClaw.chat.connecting": "Conectando...",
|
||||
"kiloClaw.chat.notRunning": "A instância não está em execução",
|
||||
"kiloClaw.chat.placeholder": "Digite uma mensagem... (Enter para enviar)",
|
||||
"kiloClaw.chat.online": "Online",
|
||||
"kiloClaw.chat.offline": "Offline",
|
||||
"kiloClaw.chat.empty": "Nenhuma mensagem ainda. Diga olá!",
|
||||
"kiloClaw.chat.send": "Enviar",
|
||||
"kiloClaw.message.bot": "KiloClaw",
|
||||
"kiloClaw.message.you": "Você",
|
||||
"kiloClaw.message.thinking": "Pensando...",
|
||||
"kiloClaw.setup.title": "KiloClaw",
|
||||
"kiloClaw.setup.subtitle": "IA pessoal para o dia a dia",
|
||||
"kiloClaw.setup.description1":
|
||||
"O KiloClaw oferece uma IA pessoal que lê e-mails, gerencia sua agenda, monitora seus projetos e vive no Telegram, Slack \u2014 ou qualquer ferramenta que você já use.",
|
||||
"kiloClaw.setup.description2":
|
||||
"Nenhum aplicativo para instalar. Nenhuma interface nova para aprender. Apenas envie mensagens como se fosse um amigo.",
|
||||
"kiloClaw.setup.learnMore": "Saiba mais",
|
||||
"kiloClaw.setup.tryKiloClaw": "Experimente o KiloClaw",
|
||||
"kiloClaw.upgrade.title": "O Chat do KiloClaw requer uma atualização",
|
||||
"kiloClaw.upgrade.description1": "Esta instância foi provisionada antes do chat ser ativado.",
|
||||
"kiloClaw.upgrade.description2.before": "Use o botão ",
|
||||
"kiloClaw.upgrade.description2.bold": "Atualizar para a Versão Mais Recente",
|
||||
"kiloClaw.upgrade.description2.after": " no dashboard do KiloClaw para ativar o chat em tempo real com seu bot.",
|
||||
"kiloClaw.upgrade.openDashboard": "Abrir Dashboard",
|
||||
"kiloClaw.sidebar.title": "KiloClaw",
|
||||
"kiloClaw.sidebar.instance": "Instância",
|
||||
"kiloClaw.sidebar.unknown": "Desconhecido",
|
||||
"kiloClaw.sidebar.bot": "Bot",
|
||||
"kiloClaw.sidebar.details": "Detalhes",
|
||||
"kiloClaw.sidebar.region": "Região",
|
||||
"kiloClaw.sidebar.version": "Versão",
|
||||
"kiloClaw.sidebar.channels": "Canais",
|
||||
"kiloClaw.sidebar.noData": "Sem dados da instância",
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
export const dict = {
|
||||
"kiloClaw.loading": "Učitavanje KiloClaw-a...",
|
||||
"kiloClaw.chat.connecting": "Povezivanje...",
|
||||
"kiloClaw.chat.notRunning": "Instanca nije pokrenuta",
|
||||
"kiloClaw.chat.placeholder": "Unesite poruku... (Enter za slanje)",
|
||||
"kiloClaw.chat.online": "Na mreži",
|
||||
"kiloClaw.chat.offline": "Van mreže",
|
||||
"kiloClaw.chat.empty": "Još uvijek nema poruka. Recite zdravo!",
|
||||
"kiloClaw.chat.send": "Pošalji",
|
||||
"kiloClaw.message.bot": "KiloClaw",
|
||||
"kiloClaw.message.you": "Vi",
|
||||
"kiloClaw.message.thinking": "Razmišljam...",
|
||||
"kiloClaw.setup.title": "KiloClaw",
|
||||
"kiloClaw.setup.subtitle": "Lična vještačka inteligencija za svakodnevni život",
|
||||
"kiloClaw.setup.description1":
|
||||
"KiloClaw vam pruža ličnu vještačku inteligenciju koja čita e-poštu, upravlja vašim kalendarom, nadgleda vaše projekte i živi u Telegramu, Slacku \u2014 šta god već koristite.",
|
||||
"kiloClaw.setup.description2":
|
||||
"Nema aplikacije za instaliranje. Nema novog interfejsa za učenje. Samo mu pošaljite poruku kao prijatelju.",
|
||||
"kiloClaw.setup.learnMore": "Saznajte više",
|
||||
"kiloClaw.setup.tryKiloClaw": "Isprobajte KiloClaw",
|
||||
"kiloClaw.upgrade.title": "KiloClaw Chat zahtijeva nadogradnju",
|
||||
"kiloClaw.upgrade.description1": "Ova instanca je obezbijeđena prije nego što je chat bio omogućen.",
|
||||
"kiloClaw.upgrade.description2.before": "Upotrijebite dugme ",
|
||||
"kiloClaw.upgrade.description2.bold": "Upgrade to Latest",
|
||||
"kiloClaw.upgrade.description2.after":
|
||||
" na KiloClaw kontrolnoj tabli da aktivirate chat u realnom vremenu sa vašim botom.",
|
||||
"kiloClaw.upgrade.openDashboard": "Otvori kontrolnu tablu",
|
||||
"kiloClaw.sidebar.title": "KiloClaw",
|
||||
"kiloClaw.sidebar.instance": "Instanca",
|
||||
"kiloClaw.sidebar.unknown": "Nepoznato",
|
||||
"kiloClaw.sidebar.bot": "Bot",
|
||||
"kiloClaw.sidebar.details": "Detalji",
|
||||
"kiloClaw.sidebar.region": "Regija",
|
||||
"kiloClaw.sidebar.version": "Verzija",
|
||||
"kiloClaw.sidebar.channels": "Kanali",
|
||||
"kiloClaw.sidebar.noData": "Nema podataka o instanci",
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
export const dict = {
|
||||
"kiloClaw.loading": "Indlæser KiloClaw...",
|
||||
"kiloClaw.chat.connecting": "Opretter forbindelse...",
|
||||
"kiloClaw.chat.notRunning": "Instansen kører ikke",
|
||||
"kiloClaw.chat.placeholder": "Skriv en besked... (Enter for at sende)",
|
||||
"kiloClaw.chat.online": "Online",
|
||||
"kiloClaw.chat.offline": "Offline",
|
||||
"kiloClaw.chat.empty": "Ingen beskeder endnu. Sig hej!",
|
||||
"kiloClaw.chat.send": "Send",
|
||||
"kiloClaw.message.bot": "KiloClaw",
|
||||
"kiloClaw.message.you": "Dig",
|
||||
"kiloClaw.message.thinking": "Tænker...",
|
||||
"kiloClaw.setup.title": "KiloClaw",
|
||||
"kiloClaw.setup.subtitle": "Personlig AI til hverdagen",
|
||||
"kiloClaw.setup.description1":
|
||||
"KiloClaw giver dig en personlig AI, der læser e-mails, administrerer din kalender, overvåger dine projekter og bor i Telegram, Slack \u2014 uanset hvad du allerede bruger.",
|
||||
"kiloClaw.setup.description2":
|
||||
"Ingen app at installere. Ingen ny grænseflade at lære. Bare skriv til den som en ven.",
|
||||
"kiloClaw.setup.learnMore": "Læs mere",
|
||||
"kiloClaw.setup.tryKiloClaw": "Prøv KiloClaw",
|
||||
"kiloClaw.upgrade.title": "KiloClaw Chat kræver en opgradering",
|
||||
"kiloClaw.upgrade.description1": "Denne instans blev klargjort, før chat blev aktiveret.",
|
||||
"kiloClaw.upgrade.description2.before": "Brug ",
|
||||
"kiloClaw.upgrade.description2.bold": "Opgrader til seneste",
|
||||
"kiloClaw.upgrade.description2.after":
|
||||
"-knappen på KiloClaw-kontrolpanelet for at aktivere realtidschat med din bot.",
|
||||
"kiloClaw.upgrade.openDashboard": "Åbn kontrolpanel",
|
||||
"kiloClaw.sidebar.title": "KiloClaw",
|
||||
"kiloClaw.sidebar.instance": "Instans",
|
||||
"kiloClaw.sidebar.unknown": "Ukendt",
|
||||
"kiloClaw.sidebar.bot": "Bot",
|
||||
"kiloClaw.sidebar.details": "Detaljer",
|
||||
"kiloClaw.sidebar.region": "Region",
|
||||
"kiloClaw.sidebar.version": "Version",
|
||||
"kiloClaw.sidebar.channels": "Kanaler",
|
||||
"kiloClaw.sidebar.noData": "Ingen instansdata",
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
export const dict = {
|
||||
"kiloClaw.loading": "Lade KiloClaw...",
|
||||
"kiloClaw.chat.connecting": "Verbinde...",
|
||||
"kiloClaw.chat.notRunning": "Instanz läuft nicht",
|
||||
"kiloClaw.chat.placeholder": "Schreibe eine Nachricht... (Eingabetaste zum Senden)",
|
||||
"kiloClaw.chat.online": "Online",
|
||||
"kiloClaw.chat.offline": "Offline",
|
||||
"kiloClaw.chat.empty": "Noch keine Nachrichten. Sag Hallo!",
|
||||
"kiloClaw.chat.send": "Senden",
|
||||
"kiloClaw.message.bot": "KiloClaw",
|
||||
"kiloClaw.message.you": "Du",
|
||||
"kiloClaw.message.thinking": "Denkt nach...",
|
||||
"kiloClaw.setup.title": "KiloClaw",
|
||||
"kiloClaw.setup.subtitle": "Persönliche KI für den Alltag",
|
||||
"kiloClaw.setup.description1":
|
||||
"KiloClaw gibt dir eine persönliche KI, die E-Mails liest, deinen Kalender verwaltet, deine Projekte überwacht und in Telegram, Slack lebt — was auch immer du bereits nutzt.",
|
||||
"kiloClaw.setup.description2":
|
||||
"Keine App zu installieren. Keine neue Oberfläche zu lernen. Schreib ihr einfach wie einem Freund.",
|
||||
"kiloClaw.setup.learnMore": "Mehr erfahren",
|
||||
"kiloClaw.setup.tryKiloClaw": "KiloClaw ausprobieren",
|
||||
"kiloClaw.upgrade.title": "KiloClaw Chat erfordert ein Upgrade",
|
||||
"kiloClaw.upgrade.description1": "Diese Instanz wurde bereitgestellt, bevor der Chat aktiviert wurde.",
|
||||
"kiloClaw.upgrade.description2.before": "Verwende die Schaltfläche ",
|
||||
"kiloClaw.upgrade.description2.bold": "Auf neueste Version aktualisieren",
|
||||
"kiloClaw.upgrade.description2.after": " im KiloClaw Dashboard, um den Echtzeit-Chat mit deinem Bot zu aktivieren.",
|
||||
"kiloClaw.upgrade.openDashboard": "Dashboard öffnen",
|
||||
"kiloClaw.sidebar.title": "KiloClaw",
|
||||
"kiloClaw.sidebar.instance": "Instanz",
|
||||
"kiloClaw.sidebar.unknown": "Unbekannt",
|
||||
"kiloClaw.sidebar.bot": "Bot",
|
||||
"kiloClaw.sidebar.details": "Details",
|
||||
"kiloClaw.sidebar.region": "Region",
|
||||
"kiloClaw.sidebar.version": "Version",
|
||||
"kiloClaw.sidebar.channels": "Kanäle",
|
||||
"kiloClaw.sidebar.noData": "Keine Instanzdaten",
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
export const dict = {
|
||||
// App
|
||||
"kiloClaw.loading": "Loading KiloClaw...",
|
||||
|
||||
// Chat
|
||||
"kiloClaw.chat.connecting": "Connecting...",
|
||||
"kiloClaw.chat.notRunning": "Instance is not running",
|
||||
"kiloClaw.chat.placeholder": "Type a message... (Enter to send)",
|
||||
"kiloClaw.chat.online": "Online",
|
||||
"kiloClaw.chat.offline": "Offline",
|
||||
"kiloClaw.chat.empty": "No messages yet. Say hello!",
|
||||
"kiloClaw.chat.send": "Send",
|
||||
|
||||
// Messages
|
||||
"kiloClaw.message.bot": "KiloClaw",
|
||||
"kiloClaw.message.you": "You",
|
||||
"kiloClaw.message.thinking": "Thinking...",
|
||||
|
||||
// Setup
|
||||
"kiloClaw.setup.title": "KiloClaw",
|
||||
"kiloClaw.setup.subtitle": "Personal AI for everyday life",
|
||||
"kiloClaw.setup.description1":
|
||||
"KiloClaw gives you a personal AI that reads email, manages your calendar, monitors your projects, and lives in Telegram, Slack \u2014 whatever you already use.",
|
||||
"kiloClaw.setup.description2": "No app to install. No new interface to learn. Just message it like a friend.",
|
||||
"kiloClaw.setup.learnMore": "Learn more",
|
||||
"kiloClaw.setup.tryKiloClaw": "Try KiloClaw",
|
||||
|
||||
// Upgrade
|
||||
"kiloClaw.upgrade.title": "KiloClaw Chat requires an upgrade",
|
||||
"kiloClaw.upgrade.description1": "This instance was provisioned before chat was enabled.",
|
||||
"kiloClaw.upgrade.description2.before": "Use the ",
|
||||
"kiloClaw.upgrade.description2.bold": "Upgrade to Latest",
|
||||
"kiloClaw.upgrade.description2.after": " button on the KiloClaw dashboard to activate real-time chat with your bot.",
|
||||
"kiloClaw.upgrade.openDashboard": "Open Dashboard",
|
||||
|
||||
// Sidebar
|
||||
"kiloClaw.sidebar.title": "KiloClaw",
|
||||
"kiloClaw.sidebar.instance": "Instance",
|
||||
"kiloClaw.sidebar.unknown": "Unknown",
|
||||
"kiloClaw.sidebar.bot": "Bot",
|
||||
"kiloClaw.sidebar.details": "Details",
|
||||
"kiloClaw.sidebar.region": "Region",
|
||||
"kiloClaw.sidebar.version": "Version",
|
||||
"kiloClaw.sidebar.channels": "Channels",
|
||||
"kiloClaw.sidebar.noData": "No instance data",
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
export const dict = {
|
||||
"kiloClaw.loading": "Cargando KiloClaw...",
|
||||
"kiloClaw.chat.connecting": "Conectando...",
|
||||
"kiloClaw.chat.notRunning": "La instancia no está en ejecución",
|
||||
"kiloClaw.chat.placeholder": "Escribe un mensaje... (Enter para enviar)",
|
||||
"kiloClaw.chat.online": "En línea",
|
||||
"kiloClaw.chat.offline": "Desconectado",
|
||||
"kiloClaw.chat.empty": "Aún no hay mensajes. ¡Di hola!",
|
||||
"kiloClaw.chat.send": "Enviar",
|
||||
"kiloClaw.message.bot": "KiloClaw",
|
||||
"kiloClaw.message.you": "Tú",
|
||||
"kiloClaw.message.thinking": "Pensando...",
|
||||
"kiloClaw.setup.title": "KiloClaw",
|
||||
"kiloClaw.setup.subtitle": "IA personal para la vida diaria",
|
||||
"kiloClaw.setup.description1":
|
||||
"KiloClaw te ofrece una IA personal que lee correos, gestiona tu calendario, monitorea tus proyectos y vive en Telegram, Slack \u2014 lo que sea que ya uses.",
|
||||
"kiloClaw.setup.description2":
|
||||
"No hay que instalar ninguna aplicación. No hay que aprender una nueva interfaz. Solo envíale mensajes como si fuera un amigo.",
|
||||
"kiloClaw.setup.learnMore": "Más información",
|
||||
"kiloClaw.setup.tryKiloClaw": "Probar KiloClaw",
|
||||
"kiloClaw.upgrade.title": "El chat de KiloClaw requiere una actualización",
|
||||
"kiloClaw.upgrade.description1": "Esta instancia se aprovisionó antes de que se habilitara el chat.",
|
||||
"kiloClaw.upgrade.description2.before": "Usa el botón ",
|
||||
"kiloClaw.upgrade.description2.bold": "Actualizar a la última versión",
|
||||
"kiloClaw.upgrade.description2.after": " en el panel de KiloClaw para activar el chat en tiempo real con tu bot.",
|
||||
"kiloClaw.upgrade.openDashboard": "Abrir panel",
|
||||
"kiloClaw.sidebar.title": "KiloClaw",
|
||||
"kiloClaw.sidebar.instance": "Instancia",
|
||||
"kiloClaw.sidebar.unknown": "Desconocido",
|
||||
"kiloClaw.sidebar.bot": "Bot",
|
||||
"kiloClaw.sidebar.details": "Detalles",
|
||||
"kiloClaw.sidebar.region": "Región",
|
||||
"kiloClaw.sidebar.version": "Versión",
|
||||
"kiloClaw.sidebar.channels": "Canales",
|
||||
"kiloClaw.sidebar.noData": "Sin datos de la instancia",
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
export const dict = {
|
||||
"kiloClaw.loading": "Chargement de KiloClaw...",
|
||||
"kiloClaw.chat.connecting": "Connexion en cours...",
|
||||
"kiloClaw.chat.notRunning": "L'instance n'est pas en cours d'exécution",
|
||||
"kiloClaw.chat.placeholder": "Tapez un message... (Entrée pour envoyer)",
|
||||
"kiloClaw.chat.online": "En ligne",
|
||||
"kiloClaw.chat.offline": "Hors ligne",
|
||||
"kiloClaw.chat.empty": "Aucun message pour le moment. Dites bonjour !",
|
||||
"kiloClaw.chat.send": "Envoyer",
|
||||
"kiloClaw.message.bot": "KiloClaw",
|
||||
"kiloClaw.message.you": "Vous",
|
||||
"kiloClaw.message.thinking": "Réflexion...",
|
||||
"kiloClaw.setup.title": "KiloClaw",
|
||||
"kiloClaw.setup.subtitle": "Une IA personnelle pour la vie de tous les jours",
|
||||
"kiloClaw.setup.description1":
|
||||
"KiloClaw vous offre une IA personnelle qui lit vos e-mails, gère votre calendrier, surveille vos projets et vit dans Telegram, Slack \u2014 ou tout ce que vous utilisez déjà.",
|
||||
"kiloClaw.setup.description2":
|
||||
"Aucune application à installer. Aucune nouvelle interface à apprendre. Envoyez-lui simplement des messages comme à un ami.",
|
||||
"kiloClaw.setup.learnMore": "En savoir plus",
|
||||
"kiloClaw.setup.tryKiloClaw": "Essayer KiloClaw",
|
||||
"kiloClaw.upgrade.title": "KiloClaw Chat nécessite une mise à niveau",
|
||||
"kiloClaw.upgrade.description1": "Cette instance a été provisionnée avant l'activation du chat.",
|
||||
"kiloClaw.upgrade.description2.before": "Utilisez le bouton ",
|
||||
"kiloClaw.upgrade.description2.bold": "Mettre à niveau vers la dernière version",
|
||||
"kiloClaw.upgrade.description2.after":
|
||||
" sur le tableau de bord KiloClaw pour activer le chat en temps réel avec votre bot.",
|
||||
"kiloClaw.upgrade.openDashboard": "Ouvrir le tableau de bord",
|
||||
"kiloClaw.sidebar.title": "KiloClaw",
|
||||
"kiloClaw.sidebar.instance": "Instance",
|
||||
"kiloClaw.sidebar.unknown": "Inconnu",
|
||||
"kiloClaw.sidebar.bot": "Bot",
|
||||
"kiloClaw.sidebar.details": "Détails",
|
||||
"kiloClaw.sidebar.region": "Région",
|
||||
"kiloClaw.sidebar.version": "Version",
|
||||
"kiloClaw.sidebar.channels": "Canaux",
|
||||
"kiloClaw.sidebar.noData": "Aucune donnée d'instance",
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
export const dict = {
|
||||
"kiloClaw.loading": "KiloClaw を読み込んでいます...",
|
||||
"kiloClaw.chat.connecting": "接続中...",
|
||||
"kiloClaw.chat.notRunning": "インスタンスが実行されていません",
|
||||
"kiloClaw.chat.placeholder": "メッセージを入力... (Enter で送信)",
|
||||
"kiloClaw.chat.online": "オンライン",
|
||||
"kiloClaw.chat.offline": "オフライン",
|
||||
"kiloClaw.chat.empty": "まだメッセージがありません。挨拶してみましょう!",
|
||||
"kiloClaw.chat.send": "送信",
|
||||
"kiloClaw.message.bot": "KiloClaw",
|
||||
"kiloClaw.message.you": "あなた",
|
||||
"kiloClaw.message.thinking": "考え中...",
|
||||
"kiloClaw.setup.title": "KiloClaw",
|
||||
"kiloClaw.setup.subtitle": "日常生活のためのパーソナル AI",
|
||||
"kiloClaw.setup.description1":
|
||||
"KiloClaw は、メールを読み、カレンダーを管理し、プロジェクトを監視し、Telegram や Slack など普段使っているツールで動作するパーソナル AI を提供します。",
|
||||
"kiloClaw.setup.description2":
|
||||
"アプリのインストール不要。新しいインターフェースの学習不要。友達にメッセージするように話しかけるだけ。",
|
||||
"kiloClaw.setup.learnMore": "詳しくはこちら",
|
||||
"kiloClaw.setup.tryKiloClaw": "KiloClaw を試す",
|
||||
"kiloClaw.upgrade.title": "KiloClaw チャットにはアップグレードが必要です",
|
||||
"kiloClaw.upgrade.description1": "このインスタンスはチャットが有効になる前にプロビジョニングされました。",
|
||||
"kiloClaw.upgrade.description2.before": "KiloClaw ダッシュボードの",
|
||||
"kiloClaw.upgrade.description2.bold": "最新版にアップグレード",
|
||||
"kiloClaw.upgrade.description2.after": "ボタンを使用して、ボットとのリアルタイムチャットを有効にしてください。",
|
||||
"kiloClaw.upgrade.openDashboard": "ダッシュボードを開く",
|
||||
"kiloClaw.sidebar.title": "KiloClaw",
|
||||
"kiloClaw.sidebar.instance": "インスタンス",
|
||||
"kiloClaw.sidebar.unknown": "不明",
|
||||
"kiloClaw.sidebar.bot": "ボット",
|
||||
"kiloClaw.sidebar.details": "詳細",
|
||||
"kiloClaw.sidebar.region": "リージョン",
|
||||
"kiloClaw.sidebar.version": "バージョン",
|
||||
"kiloClaw.sidebar.channels": "チャンネル",
|
||||
"kiloClaw.sidebar.noData": "インスタンスデータがありません",
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
export const dict = {
|
||||
"kiloClaw.loading": "KiloClaw 로딩 중...",
|
||||
"kiloClaw.chat.connecting": "연결 중...",
|
||||
"kiloClaw.chat.notRunning": "인스턴스가 실행 중이 아닙니다",
|
||||
"kiloClaw.chat.placeholder": "메시지를 입력하세요... (Enter로 전송)",
|
||||
"kiloClaw.chat.online": "온라인",
|
||||
"kiloClaw.chat.offline": "오프라인",
|
||||
"kiloClaw.chat.empty": "아직 메시지가 없습니다. 인사해 보세요!",
|
||||
"kiloClaw.chat.send": "전송",
|
||||
"kiloClaw.message.bot": "KiloClaw",
|
||||
"kiloClaw.message.you": "나",
|
||||
"kiloClaw.message.thinking": "생각 중...",
|
||||
"kiloClaw.setup.title": "KiloClaw",
|
||||
"kiloClaw.setup.subtitle": "일상을 위한 개인 AI",
|
||||
"kiloClaw.setup.description1":
|
||||
"KiloClaw는 이메일을 읽고, 캘린더를 관리하고, 프로젝트를 모니터링하며, Telegram, Slack 등 이미 사용 중인 도구에서 작동하는 개인 AI를 제공합니다.",
|
||||
"kiloClaw.setup.description2":
|
||||
"설치할 앱이 없습니다. 배울 새로운 인터페이스도 없습니다. 친구에게 메시지하듯 대화하세요.",
|
||||
"kiloClaw.setup.learnMore": "자세히 보기",
|
||||
"kiloClaw.setup.tryKiloClaw": "KiloClaw 사용해 보기",
|
||||
"kiloClaw.upgrade.title": "KiloClaw 채팅에 업그레이드가 필요합니다",
|
||||
"kiloClaw.upgrade.description1": "이 인스턴스는 채팅이 활성화되기 전에 프로비저닝되었습니다.",
|
||||
"kiloClaw.upgrade.description2.before": "KiloClaw 대시보드에서 ",
|
||||
"kiloClaw.upgrade.description2.bold": "최신 버전으로 업그레이드",
|
||||
"kiloClaw.upgrade.description2.after": " 버튼을 사용하여 봇과의 실시간 채팅을 활성화하세요.",
|
||||
"kiloClaw.upgrade.openDashboard": "대시보드 열기",
|
||||
"kiloClaw.sidebar.title": "KiloClaw",
|
||||
"kiloClaw.sidebar.instance": "인스턴스",
|
||||
"kiloClaw.sidebar.unknown": "알 수 없음",
|
||||
"kiloClaw.sidebar.bot": "봇",
|
||||
"kiloClaw.sidebar.details": "상세 정보",
|
||||
"kiloClaw.sidebar.region": "리전",
|
||||
"kiloClaw.sidebar.version": "버전",
|
||||
"kiloClaw.sidebar.channels": "채널",
|
||||
"kiloClaw.sidebar.noData": "인스턴스 데이터 없음",
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
export const dict = {
|
||||
"kiloClaw.loading": "KiloClaw laden...",
|
||||
"kiloClaw.chat.connecting": "Verbinden...",
|
||||
"kiloClaw.chat.notRunning": "Instantie is niet actief",
|
||||
"kiloClaw.chat.placeholder": "Typ een bericht... (Enter om te verzenden)",
|
||||
"kiloClaw.chat.online": "Online",
|
||||
"kiloClaw.chat.offline": "Offline",
|
||||
"kiloClaw.chat.empty": "Nog geen berichten. Zeg hallo!",
|
||||
"kiloClaw.chat.send": "Verzenden",
|
||||
"kiloClaw.message.bot": "KiloClaw",
|
||||
"kiloClaw.message.you": "Jij",
|
||||
"kiloClaw.message.thinking": "Aan het nadenken...",
|
||||
"kiloClaw.setup.title": "KiloClaw",
|
||||
"kiloClaw.setup.subtitle": "Persoonlijke AI voor het dagelijks leven",
|
||||
"kiloClaw.setup.description1":
|
||||
"KiloClaw biedt je een persoonlijke AI die e-mails leest, je agenda beheert, je projecten bewaakt, en actief is in Telegram, Slack \u2014 of wat je al gebruikt.",
|
||||
"kiloClaw.setup.description2":
|
||||
"Geen app om te installeren. Geen nieuwe interface om te leren. Stuur gewoon een berichtje zoals je naar een vriend zou doen.",
|
||||
"kiloClaw.setup.learnMore": "Meer informatie",
|
||||
"kiloClaw.setup.tryKiloClaw": "Probeer KiloClaw",
|
||||
"kiloClaw.upgrade.title": "KiloClaw Chat vereist een upgrade",
|
||||
"kiloClaw.upgrade.description1": "Deze instantie is ingericht voordat chat was ingeschakeld.",
|
||||
"kiloClaw.upgrade.description2.before": "Gebruik de knop ",
|
||||
"kiloClaw.upgrade.description2.bold": "Upgrade to Latest",
|
||||
"kiloClaw.upgrade.description2.after": " op het KiloClaw-dashboard om realtime chat met je bot te activeren.",
|
||||
"kiloClaw.upgrade.openDashboard": "Dashboard openen",
|
||||
"kiloClaw.sidebar.title": "KiloClaw",
|
||||
"kiloClaw.sidebar.instance": "Instantie",
|
||||
"kiloClaw.sidebar.unknown": "Onbekend",
|
||||
"kiloClaw.sidebar.bot": "Bot",
|
||||
"kiloClaw.sidebar.details": "Details",
|
||||
"kiloClaw.sidebar.region": "Regio",
|
||||
"kiloClaw.sidebar.version": "Versie",
|
||||
"kiloClaw.sidebar.channels": "Kanalen",
|
||||
"kiloClaw.sidebar.noData": "Geen instantiegegevens",
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
export const dict = {
|
||||
"kiloClaw.loading": "Laster KiloClaw...",
|
||||
"kiloClaw.chat.connecting": "Kobler til...",
|
||||
"kiloClaw.chat.notRunning": "Instansen kjører ikke",
|
||||
"kiloClaw.chat.placeholder": "Skriv en melding... (Enter for å sende)",
|
||||
"kiloClaw.chat.online": "Pålogget",
|
||||
"kiloClaw.chat.offline": "Frakoblet",
|
||||
"kiloClaw.chat.empty": "Ingen meldinger ennå. Si hei!",
|
||||
"kiloClaw.chat.send": "Send",
|
||||
"kiloClaw.message.bot": "KiloClaw",
|
||||
"kiloClaw.message.you": "Du",
|
||||
"kiloClaw.message.thinking": "Tenker...",
|
||||
"kiloClaw.setup.title": "KiloClaw",
|
||||
"kiloClaw.setup.subtitle": "Personlig AI for hverdagen",
|
||||
"kiloClaw.setup.description1":
|
||||
"KiloClaw gir deg en personlig AI som leser e-post, administrerer kalenderen din, overvåker prosjektene dine og lever i Telegram, Slack \u2014 uansett hva du allerede bruker.",
|
||||
"kiloClaw.setup.description2":
|
||||
"Ingen app å installere. Ingen nytt grensesnitt å lære. Bare skriv til den som en venn.",
|
||||
"kiloClaw.setup.learnMore": "Lær mer",
|
||||
"kiloClaw.setup.tryKiloClaw": "Prøv KiloClaw",
|
||||
"kiloClaw.upgrade.title": "KiloClaw Chat krever en oppgradering",
|
||||
"kiloClaw.upgrade.description1": "Denne instansen ble klargjort før chat ble aktivert.",
|
||||
"kiloClaw.upgrade.description2.before": "Bruk ",
|
||||
"kiloClaw.upgrade.description2.bold": "Oppgrader til nyeste",
|
||||
"kiloClaw.upgrade.description2.after": "-knappen på KiloClaw-dashbordet for å aktivere sanntidschat med boten din.",
|
||||
"kiloClaw.upgrade.openDashboard": "Åpne dashbord",
|
||||
"kiloClaw.sidebar.title": "KiloClaw",
|
||||
"kiloClaw.sidebar.instance": "Instans",
|
||||
"kiloClaw.sidebar.unknown": "Ukjent",
|
||||
"kiloClaw.sidebar.bot": "Bot",
|
||||
"kiloClaw.sidebar.details": "Detaljer",
|
||||
"kiloClaw.sidebar.region": "Region",
|
||||
"kiloClaw.sidebar.version": "Versjon",
|
||||
"kiloClaw.sidebar.channels": "Kanaler",
|
||||
"kiloClaw.sidebar.noData": "Ingen instansdata",
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
export const dict = {
|
||||
"kiloClaw.loading": "Ładowanie KiloClaw...",
|
||||
"kiloClaw.chat.connecting": "Łączenie...",
|
||||
"kiloClaw.chat.notRunning": "Instancja nie jest uruchomiona",
|
||||
"kiloClaw.chat.placeholder": "Wpisz wiadomość... (Enter, aby wysłać)",
|
||||
"kiloClaw.chat.online": "Dostępny",
|
||||
"kiloClaw.chat.offline": "Niedostępny",
|
||||
"kiloClaw.chat.empty": "Brak wiadomości. Przywitaj się!",
|
||||
"kiloClaw.chat.send": "Wyślij",
|
||||
"kiloClaw.message.bot": "KiloClaw",
|
||||
"kiloClaw.message.you": "Ty",
|
||||
"kiloClaw.message.thinking": "Myślenie...",
|
||||
"kiloClaw.setup.title": "KiloClaw",
|
||||
"kiloClaw.setup.subtitle": "Osobista SI na co dzień",
|
||||
"kiloClaw.setup.description1":
|
||||
"KiloClaw zapewnia osobistą sztuczną inteligencję, która czyta e-maile, zarządza kalendarzem, monitoruje projekty i jest dostępna w Telegramie, Slacku \u2014 czyli tam, gdzie już jesteś.",
|
||||
"kiloClaw.setup.description2":
|
||||
"Żadnych aplikacji do instalacji. Żadnego nowego interfejsu do nauki. Po prostu pisz do niej jak do przyjaciela.",
|
||||
"kiloClaw.setup.learnMore": "Dowiedz się więcej",
|
||||
"kiloClaw.setup.tryKiloClaw": "Wypróbuj KiloClaw",
|
||||
"kiloClaw.upgrade.title": "KiloClaw Chat wymaga aktualizacji",
|
||||
"kiloClaw.upgrade.description1": "Ta instancja została utworzona przed włączeniem czatu.",
|
||||
"kiloClaw.upgrade.description2.before": "Użyj przycisku ",
|
||||
"kiloClaw.upgrade.description2.bold": "Zaktualizuj do najnowszej wersji",
|
||||
"kiloClaw.upgrade.description2.after": " w panelu KiloClaw, aby aktywować czat w czasie rzeczywistym z botem.",
|
||||
"kiloClaw.upgrade.openDashboard": "Otwórz panel",
|
||||
"kiloClaw.sidebar.title": "KiloClaw",
|
||||
"kiloClaw.sidebar.instance": "Instancja",
|
||||
"kiloClaw.sidebar.unknown": "Nieznany",
|
||||
"kiloClaw.sidebar.bot": "Bot",
|
||||
"kiloClaw.sidebar.details": "Szczegóły",
|
||||
"kiloClaw.sidebar.region": "Region",
|
||||
"kiloClaw.sidebar.version": "Wersja",
|
||||
"kiloClaw.sidebar.channels": "Kanały",
|
||||
"kiloClaw.sidebar.noData": "Brak danych instancji",
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
export const dict = {
|
||||
"kiloClaw.loading": "Загрузка KiloClaw...",
|
||||
"kiloClaw.chat.connecting": "Подключение...",
|
||||
"kiloClaw.chat.notRunning": "Экземпляр не запущен",
|
||||
"kiloClaw.chat.placeholder": "Введите сообщение... (Enter для отправки)",
|
||||
"kiloClaw.chat.online": "В сети",
|
||||
"kiloClaw.chat.offline": "Не в сети",
|
||||
"kiloClaw.chat.empty": "Пока нет сообщений. Поздоровайтесь!",
|
||||
"kiloClaw.chat.send": "Отправить",
|
||||
"kiloClaw.message.bot": "KiloClaw",
|
||||
"kiloClaw.message.you": "Вы",
|
||||
"kiloClaw.message.thinking": "Думает...",
|
||||
"kiloClaw.setup.title": "KiloClaw",
|
||||
"kiloClaw.setup.subtitle": "Персональный ИИ для повседневной жизни",
|
||||
"kiloClaw.setup.description1":
|
||||
"KiloClaw предоставляет вам персональный ИИ, который читает электронную почту, управляет календарем, следит за вашими проектами и живет в Telegram, Slack \u2014 во всем, что вы уже используете.",
|
||||
"kiloClaw.setup.description2":
|
||||
"Не нужно устанавливать приложение. Не нужно изучать новый интерфейс. Просто напишите ему, как другу.",
|
||||
"kiloClaw.setup.learnMore": "Узнать больше",
|
||||
"kiloClaw.setup.tryKiloClaw": "Попробовать KiloClaw",
|
||||
"kiloClaw.upgrade.title": "Чат KiloClaw требует обновления",
|
||||
"kiloClaw.upgrade.description1": "Этот экземпляр был развернут до того, как был включен чат.",
|
||||
"kiloClaw.upgrade.description2.before": "Используйте кнопку ",
|
||||
"kiloClaw.upgrade.description2.bold": "Upgrade to Latest",
|
||||
"kiloClaw.upgrade.description2.after":
|
||||
" на панели управления KiloClaw, чтобы активировать чат в реальном времени с вашим ботом.",
|
||||
"kiloClaw.upgrade.openDashboard": "Открыть панель управления",
|
||||
"kiloClaw.sidebar.title": "KiloClaw",
|
||||
"kiloClaw.sidebar.instance": "Экземпляр",
|
||||
"kiloClaw.sidebar.unknown": "Неизвестно",
|
||||
"kiloClaw.sidebar.bot": "Бот",
|
||||
"kiloClaw.sidebar.details": "Детали",
|
||||
"kiloClaw.sidebar.region": "Регион",
|
||||
"kiloClaw.sidebar.version": "Версия",
|
||||
"kiloClaw.sidebar.channels": "Каналы",
|
||||
"kiloClaw.sidebar.noData": "Нет данных об экземпляре",
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
export const dict = {
|
||||
"kiloClaw.loading": "กำลังโหลด KiloClaw...",
|
||||
"kiloClaw.chat.connecting": "กำลังเชื่อมต่อ...",
|
||||
"kiloClaw.chat.notRunning": "อินสแตนซ์ไม่ได้ทำงานอยู่",
|
||||
"kiloClaw.chat.placeholder": "พิมพ์ข้อความ... (กด Enter เพื่อส่ง)",
|
||||
"kiloClaw.chat.online": "ออนไลน์",
|
||||
"kiloClaw.chat.offline": "ออฟไลน์",
|
||||
"kiloClaw.chat.empty": "ยังไม่มีข้อความ ทักทายสิ!",
|
||||
"kiloClaw.chat.send": "ส่ง",
|
||||
"kiloClaw.message.bot": "KiloClaw",
|
||||
"kiloClaw.message.you": "คุณ",
|
||||
"kiloClaw.message.thinking": "กำลังคิด...",
|
||||
"kiloClaw.setup.title": "KiloClaw",
|
||||
"kiloClaw.setup.subtitle": "AI ส่วนตัวสำหรับชีวิตประจำวัน",
|
||||
"kiloClaw.setup.description1":
|
||||
"KiloClaw ให้ AI ส่วนตัวที่อ่านอีเมล จัดการปฏิทิน ตรวจสอบโปรเจกต์ของคุณ และอยู่ใน Telegram, Slack \u2014 หรืออะไรก็ตามที่คุณใช้อยู่แล้ว",
|
||||
"kiloClaw.setup.description2": "ไม่ต้องติดตั้งแอป ไม่ต้องเรียนรู้อินเทอร์เฟซใหม่ แค่ส่งข้อความคุยเหมือนเป็นเพื่อน",
|
||||
"kiloClaw.setup.learnMore": "เรียนรู้เพิ่มเติม",
|
||||
"kiloClaw.setup.tryKiloClaw": "ลองใช้ KiloClaw",
|
||||
"kiloClaw.upgrade.title": "KiloClaw Chat ต้องได้รับการอัปเกรด",
|
||||
"kiloClaw.upgrade.description1": "อินสแตนซ์นี้ถูกสร้างขึ้นก่อนที่จะเปิดใช้งานแชท",
|
||||
"kiloClaw.upgrade.description2.before": "ใช้ปุ่ม ",
|
||||
"kiloClaw.upgrade.description2.bold": "อัปเกรดเป็นเวอร์ชันล่าสุด",
|
||||
"kiloClaw.upgrade.description2.after": " บนแดชบอร์ด KiloClaw เพื่อเปิดใช้งานแชทแบบเรียลไทม์กับบอทของคุณ",
|
||||
"kiloClaw.upgrade.openDashboard": "เปิดแดชบอร์ด",
|
||||
"kiloClaw.sidebar.title": "KiloClaw",
|
||||
"kiloClaw.sidebar.instance": "อินสแตนซ์",
|
||||
"kiloClaw.sidebar.unknown": "ไม่ทราบ",
|
||||
"kiloClaw.sidebar.bot": "บอท",
|
||||
"kiloClaw.sidebar.details": "รายละเอียด",
|
||||
"kiloClaw.sidebar.region": "ภูมิภาค",
|
||||
"kiloClaw.sidebar.version": "เวอร์ชัน",
|
||||
"kiloClaw.sidebar.channels": "ช่องทาง",
|
||||
"kiloClaw.sidebar.noData": "ไม่มีข้อมูลอินสแตนซ์",
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
export const dict = {
|
||||
"kiloClaw.loading": "KiloClaw yükleniyor...",
|
||||
"kiloClaw.chat.connecting": "Bağlanıyor...",
|
||||
"kiloClaw.chat.notRunning": "Örnek çalışmıyor",
|
||||
"kiloClaw.chat.placeholder": "Bir mesaj yazın... (Göndermek için Enter'a basın)",
|
||||
"kiloClaw.chat.online": "Çevrimiçi",
|
||||
"kiloClaw.chat.offline": "Çevrimdışı",
|
||||
"kiloClaw.chat.empty": "Henüz mesaj yok. Merhaba deyin!",
|
||||
"kiloClaw.chat.send": "Gönder",
|
||||
"kiloClaw.message.bot": "KiloClaw",
|
||||
"kiloClaw.message.you": "Siz",
|
||||
"kiloClaw.message.thinking": "Düşünüyor...",
|
||||
"kiloClaw.setup.title": "KiloClaw",
|
||||
"kiloClaw.setup.subtitle": "Günlük yaşam için kişisel yapay zeka",
|
||||
"kiloClaw.setup.description1":
|
||||
"KiloClaw, e-postalarınızı okuyan, takviminizi yöneten, projelerinizi izleyen ve Telegram, Slack \u2014 halihazırda ne kullanıyorsanız orada yaşayan kişisel bir yapay zeka sunar.",
|
||||
"kiloClaw.setup.description2":
|
||||
"Yüklenecek bir uygulama yok. Öğrenilecek yeni bir arayüz yok. Sadece bir arkadaşınız gibi mesajlaşın.",
|
||||
"kiloClaw.setup.learnMore": "Daha fazla bilgi edinin",
|
||||
"kiloClaw.setup.tryKiloClaw": "KiloClaw'ı Deneyin",
|
||||
"kiloClaw.upgrade.title": "KiloClaw Sohbeti yükseltme gerektiriyor",
|
||||
"kiloClaw.upgrade.description1": "Bu örnek, sohbet etkinleştirilmeden önce oluşturulmuş.",
|
||||
"kiloClaw.upgrade.description2.before":
|
||||
"Botunuzla gerçek zamanlı sohbeti etkinleştirmek için KiloClaw kontrol panelindeki ",
|
||||
"kiloClaw.upgrade.description2.bold": "Upgrade to Latest",
|
||||
"kiloClaw.upgrade.description2.after": " düğmesini kullanın.",
|
||||
"kiloClaw.upgrade.openDashboard": "Kontrol Panelini Aç",
|
||||
"kiloClaw.sidebar.title": "KiloClaw",
|
||||
"kiloClaw.sidebar.instance": "Örnek",
|
||||
"kiloClaw.sidebar.unknown": "Bilinmiyor",
|
||||
"kiloClaw.sidebar.bot": "Bot",
|
||||
"kiloClaw.sidebar.details": "Ayrıntılar",
|
||||
"kiloClaw.sidebar.region": "Bölge",
|
||||
"kiloClaw.sidebar.version": "Sürüm",
|
||||
"kiloClaw.sidebar.channels": "Kanallar",
|
||||
"kiloClaw.sidebar.noData": "Örnek verisi yok",
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
export const dict = {
|
||||
"kiloClaw.loading": "正在加载 KiloClaw...",
|
||||
"kiloClaw.chat.connecting": "连接中...",
|
||||
"kiloClaw.chat.notRunning": "实例未运行",
|
||||
"kiloClaw.chat.placeholder": "输入消息... (按 Enter 键发送)",
|
||||
"kiloClaw.chat.online": "在线",
|
||||
"kiloClaw.chat.offline": "离线",
|
||||
"kiloClaw.chat.empty": "暂无消息。打个招呼吧!",
|
||||
"kiloClaw.chat.send": "发送",
|
||||
"kiloClaw.message.bot": "KiloClaw",
|
||||
"kiloClaw.message.you": "你",
|
||||
"kiloClaw.message.thinking": "思考中...",
|
||||
"kiloClaw.setup.title": "KiloClaw",
|
||||
"kiloClaw.setup.subtitle": "日常生活中的个人 AI",
|
||||
"kiloClaw.setup.description1":
|
||||
"KiloClaw 为你提供一个个人 AI,可以阅读邮件、管理日历、监控项目,并且存在于 Telegram、Slack \u2014 任何你已经在使用的平台中。",
|
||||
"kiloClaw.setup.description2": "无需安装应用。无需学习新界面。只需像朋友一样跟它发消息。",
|
||||
"kiloClaw.setup.learnMore": "了解更多",
|
||||
"kiloClaw.setup.tryKiloClaw": "尝试 KiloClaw",
|
||||
"kiloClaw.upgrade.title": "KiloClaw 聊天需要升级",
|
||||
"kiloClaw.upgrade.description1": "此实例是在启用聊天功能之前配置的。",
|
||||
"kiloClaw.upgrade.description2.before": "使用 KiloClaw 仪表板上的 ",
|
||||
"kiloClaw.upgrade.description2.bold": "升级到最新版本",
|
||||
"kiloClaw.upgrade.description2.after": " 按钮来激活与你的机器人的实时聊天。",
|
||||
"kiloClaw.upgrade.openDashboard": "打开仪表板",
|
||||
"kiloClaw.sidebar.title": "KiloClaw",
|
||||
"kiloClaw.sidebar.instance": "实例",
|
||||
"kiloClaw.sidebar.unknown": "未知",
|
||||
"kiloClaw.sidebar.bot": "机器人",
|
||||
"kiloClaw.sidebar.details": "详情",
|
||||
"kiloClaw.sidebar.region": "区域",
|
||||
"kiloClaw.sidebar.version": "版本",
|
||||
"kiloClaw.sidebar.channels": "频道",
|
||||
"kiloClaw.sidebar.noData": "无实例数据",
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
export const dict = {
|
||||
"kiloClaw.loading": "載入 KiloClaw 中...",
|
||||
"kiloClaw.chat.connecting": "連線中...",
|
||||
"kiloClaw.chat.notRunning": "執行個體未在執行",
|
||||
"kiloClaw.chat.placeholder": "輸入訊息... (按 Enter 傳送)",
|
||||
"kiloClaw.chat.online": "上線",
|
||||
"kiloClaw.chat.offline": "離線",
|
||||
"kiloClaw.chat.empty": "尚無訊息。打個招呼吧!",
|
||||
"kiloClaw.chat.send": "傳送",
|
||||
"kiloClaw.message.bot": "KiloClaw",
|
||||
"kiloClaw.message.you": "你",
|
||||
"kiloClaw.message.thinking": "思考中...",
|
||||
"kiloClaw.setup.title": "KiloClaw",
|
||||
"kiloClaw.setup.subtitle": "日常生活中的個人 AI",
|
||||
"kiloClaw.setup.description1":
|
||||
"KiloClaw 為您提供專屬的個人 AI,它可以閱讀電子郵件、管理行事曆、監控專案,並存在於 Telegram、Slack \u2014 或任何您已經在使用的應用程式中。",
|
||||
"kiloClaw.setup.description2": "無須安裝應用程式。無須學習新介面。就像朋友一樣傳訊息給它即可。",
|
||||
"kiloClaw.setup.learnMore": "了解更多",
|
||||
"kiloClaw.setup.tryKiloClaw": "試用 KiloClaw",
|
||||
"kiloClaw.upgrade.title": "KiloClaw 聊天功能需要升級",
|
||||
"kiloClaw.upgrade.description1": "此執行個體是在啟用聊天功能之前所建立的。",
|
||||
"kiloClaw.upgrade.description2.before": "使用 KiloClaw 儀表板上的 ",
|
||||
"kiloClaw.upgrade.description2.bold": "升級至最新版",
|
||||
"kiloClaw.upgrade.description2.after": " 按鈕,以啟用與您的機器人進行即時聊天的功能。",
|
||||
"kiloClaw.upgrade.openDashboard": "開啟儀表板",
|
||||
"kiloClaw.sidebar.title": "KiloClaw",
|
||||
"kiloClaw.sidebar.instance": "執行個體",
|
||||
"kiloClaw.sidebar.unknown": "未知",
|
||||
"kiloClaw.sidebar.bot": "機器人",
|
||||
"kiloClaw.sidebar.details": "詳細資訊",
|
||||
"kiloClaw.sidebar.region": "地區",
|
||||
"kiloClaw.sidebar.version": "版本",
|
||||
"kiloClaw.sidebar.channels": "頻道",
|
||||
"kiloClaw.sidebar.noData": "無執行個體資料",
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// KiloClaw SolidJS webview entry point
|
||||
|
||||
import { render } from "solid-js/web"
|
||||
import "@kilocode/kilo-ui/styles"
|
||||
import "./kiloclaw.css"
|
||||
import { KiloClawApp } from "./KiloClawApp"
|
||||
|
||||
const root = document.getElementById("root")
|
||||
if (root) {
|
||||
render(() => <KiloClawApp />, root)
|
||||
}
|
||||
@@ -0,0 +1,381 @@
|
||||
/* KiloClaw webview styles */
|
||||
|
||||
/* Root */
|
||||
.kiloclaw-root {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Main layout: chat (left) + sidebar (right) */
|
||||
.kiloclaw-layout {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Center layout for setup/upgrade/loading */
|
||||
.kiloclaw-center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
/* Loading */
|
||||
.kiloclaw-loading {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
color: var(--vscode-descriptionForeground);
|
||||
}
|
||||
|
||||
.kiloclaw-spinner {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: 2px solid var(--vscode-progressBar-background, #0078d4);
|
||||
border-top-color: transparent;
|
||||
border-radius: 50%;
|
||||
animation: kiloclaw-spin 0.8s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes kiloclaw-spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Card (setup/upgrade views) */
|
||||
.kiloclaw-card {
|
||||
max-width: 480px;
|
||||
width: 100%;
|
||||
padding: 32px;
|
||||
border-radius: 8px;
|
||||
background: var(--vscode-editorWidget-background, var(--vscode-editor-background));
|
||||
border: 1px solid var(--vscode-editorWidget-border, var(--vscode-panel-border));
|
||||
}
|
||||
|
||||
.kiloclaw-card-title {
|
||||
margin: 0 0 4px;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--vscode-foreground);
|
||||
}
|
||||
|
||||
.kiloclaw-card-subtitle {
|
||||
margin: 0 0 16px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--vscode-foreground);
|
||||
}
|
||||
|
||||
.kiloclaw-card-text {
|
||||
margin: 0 0 12px;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
color: var(--vscode-descriptionForeground);
|
||||
}
|
||||
|
||||
.kiloclaw-card-actions {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
margin-top: 20px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.kiloclaw-link-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--vscode-textLink-foreground);
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
padding: 6px 0;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.kiloclaw-link-btn:hover {
|
||||
color: var(--vscode-textLink-activeForeground);
|
||||
}
|
||||
|
||||
.kiloclaw-primary-btn {
|
||||
background: var(--vscode-button-background);
|
||||
color: var(--vscode-button-foreground);
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 8px 20px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.kiloclaw-primary-btn:hover {
|
||||
background: var(--vscode-button-hoverBackground);
|
||||
}
|
||||
|
||||
/* Chat panel */
|
||||
.kiloclaw-chat {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Chat header */
|
||||
.kiloclaw-chat-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px 16px;
|
||||
border-bottom: 1px solid var(--vscode-panel-border);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.kiloclaw-chat-header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.kiloclaw-chat-header-title {
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--vscode-foreground);
|
||||
}
|
||||
|
||||
/* Status dots */
|
||||
.kiloclaw-dot {
|
||||
display: inline-block;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.kiloclaw-dot-online {
|
||||
background: var(--vscode-testing-iconPassed, #73c991);
|
||||
}
|
||||
|
||||
.kiloclaw-dot-offline {
|
||||
background: var(--vscode-descriptionForeground, #888);
|
||||
}
|
||||
|
||||
.kiloclaw-dot-warning {
|
||||
background: var(--vscode-editorWarning-foreground, #cca700);
|
||||
}
|
||||
|
||||
.kiloclaw-dot-error {
|
||||
background: var(--vscode-editorError-foreground, #f14c4c);
|
||||
}
|
||||
|
||||
/* Messages area */
|
||||
.kiloclaw-messages {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.kiloclaw-empty {
|
||||
color: var(--vscode-descriptionForeground);
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
padding: 40px 0;
|
||||
}
|
||||
|
||||
/* Message bubble */
|
||||
.kiloclaw-msg {
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
max-width: 85%;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.kiloclaw-msg-user {
|
||||
align-self: flex-end;
|
||||
background: var(--vscode-button-background);
|
||||
color: var(--vscode-button-foreground);
|
||||
border-bottom-right-radius: 2px;
|
||||
}
|
||||
|
||||
.kiloclaw-msg-bot {
|
||||
align-self: flex-start;
|
||||
background: var(--vscode-editorWidget-background, var(--vscode-editor-background));
|
||||
color: var(--vscode-foreground);
|
||||
border: 1px solid var(--vscode-panel-border);
|
||||
border-bottom-left-radius: 2px;
|
||||
}
|
||||
|
||||
.kiloclaw-msg-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 4px;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.kiloclaw-msg-author {
|
||||
font-weight: 600;
|
||||
font-size: 11px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.kiloclaw-msg-time {
|
||||
font-size: 10px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.kiloclaw-msg-body {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.kiloclaw-msg-thinking {
|
||||
color: var(--vscode-descriptionForeground);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Input area */
|
||||
.kiloclaw-input-wrap {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
gap: 8px;
|
||||
padding: 12px 16px;
|
||||
border-top: 1px solid var(--vscode-panel-border);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.kiloclaw-input {
|
||||
flex: 1;
|
||||
resize: none;
|
||||
border: 1px solid var(--vscode-input-border, var(--vscode-panel-border));
|
||||
border-radius: 4px;
|
||||
background: var(--vscode-input-background);
|
||||
color: var(--vscode-input-foreground);
|
||||
padding: 8px 12px;
|
||||
font-size: 13px;
|
||||
font-family: var(--vscode-font-family);
|
||||
line-height: 1.4;
|
||||
max-height: 120px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.kiloclaw-input:focus {
|
||||
outline: none;
|
||||
border-color: var(--vscode-focusBorder);
|
||||
}
|
||||
|
||||
.kiloclaw-input:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.kiloclaw-input::placeholder {
|
||||
color: var(--vscode-input-placeholderForeground);
|
||||
}
|
||||
|
||||
.kiloclaw-send-btn {
|
||||
background: var(--vscode-button-background);
|
||||
color: var(--vscode-button-foreground);
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 8px 16px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.kiloclaw-send-btn:hover:not(:disabled) {
|
||||
background: var(--vscode-button-hoverBackground);
|
||||
}
|
||||
|
||||
.kiloclaw-send-btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* Status sidebar */
|
||||
.kiloclaw-sidebar {
|
||||
width: 260px;
|
||||
flex-shrink: 0;
|
||||
border-left: 1px solid var(--vscode-panel-border);
|
||||
padding: 16px;
|
||||
overflow-y: auto;
|
||||
background: var(--vscode-sideBar-background, var(--vscode-editor-background));
|
||||
}
|
||||
|
||||
.kiloclaw-sidebar-title {
|
||||
margin: 0 0 16px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--vscode-foreground);
|
||||
}
|
||||
|
||||
.kiloclaw-sidebar-section {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.kiloclaw-sidebar-label {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
color: var(--vscode-descriptionForeground);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.kiloclaw-sidebar-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 13px;
|
||||
color: var(--vscode-foreground);
|
||||
}
|
||||
|
||||
.kiloclaw-sidebar-detail {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 13px;
|
||||
color: var(--vscode-foreground);
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
.kiloclaw-sidebar-muted {
|
||||
color: var(--vscode-descriptionForeground);
|
||||
}
|
||||
|
||||
/* Toast notification */
|
||||
.kiloclaw-toast {
|
||||
position: absolute;
|
||||
bottom: 16px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: var(--vscode-editorError-foreground, #f14c4c);
|
||||
color: #fff;
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
font-size: 13px;
|
||||
z-index: 100;
|
||||
animation: kiloclaw-fadeIn 0.2s ease;
|
||||
}
|
||||
|
||||
@keyframes kiloclaw-fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-50%) translateY(8px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(-50%) translateY(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* KiloClaw webview types.
|
||||
*
|
||||
* Mirrors the extension host types for use in the SolidJS webview.
|
||||
* All data arrives via postMessage — no direct network access.
|
||||
*
|
||||
* SYNC: These types are mirrored from src/kiloclaw/types.ts — keep both in sync.
|
||||
*/
|
||||
|
||||
export type ClawStatus = {
|
||||
status: "provisioned" | "starting" | "restarting" | "running" | "stopped" | "destroying" | null
|
||||
sandboxId?: string
|
||||
flyRegion?: string
|
||||
machineSize?: { cpus: number; memory_mb: number }
|
||||
openclawVersion?: string | null
|
||||
lastStartedAt?: string | null
|
||||
lastStoppedAt?: string | null
|
||||
channelCount?: number
|
||||
secretCount?: number
|
||||
}
|
||||
|
||||
export type ChatMessage = {
|
||||
id: string
|
||||
text: string
|
||||
user: string
|
||||
created: string
|
||||
bot: boolean
|
||||
}
|
||||
|
||||
export type KiloClawState =
|
||||
| { phase: "loading"; locale: string }
|
||||
| { phase: "noInstance"; locale: string }
|
||||
| { phase: "needsUpgrade"; locale: string }
|
||||
| {
|
||||
phase: "ready"
|
||||
locale: string
|
||||
status: ClawStatus | null
|
||||
connected: boolean
|
||||
online: boolean
|
||||
messages: ChatMessage[]
|
||||
}
|
||||
|
||||
// Messages: Extension Host -> Webview
|
||||
export type KiloClawOutMessage =
|
||||
| { type: "kiloclaw.state"; state: KiloClawState }
|
||||
| { type: "kiloclaw.message"; message: ChatMessage }
|
||||
| { type: "kiloclaw.messageUpdated"; message: ChatMessage }
|
||||
| { type: "kiloclaw.presence"; online: boolean }
|
||||
| { type: "kiloclaw.status"; data: ClawStatus | null }
|
||||
| { type: "kiloclaw.locale"; locale: string }
|
||||
| { type: "kiloclaw.error"; error: string }
|
||||
@@ -12,5 +12,5 @@
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["src/**/*", "agent-manager/**/*"]
|
||||
"include": ["src/**/*", "agent-manager/**/*", "kiloclaw/**/*"]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,446 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="384px" height="86px" viewBox="0 0 384 86" enable-background="new 0 0 384 86" xml:space="preserve"> <image id="image0" width="384" height="86" x="0" y="0"
|
||||
xlink:href="data:image/png;base64,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
|
||||
6CoAAAAASUVORK5CYII=" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 34 KiB |
Reference in New Issue
Block a user