Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions packages/kilo-vscode/src/KiloProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,9 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
case "compact":
await this.handleCompact(message.sessionID, message.providerID, message.modelID)
break
case "export":
await this.handleExport(message.sessionID)
break
case "requestAgents":
this.fetchAndSendAgents().catch((e) => console.error("[Kilo New] fetchAndSendAgents failed:", e))
break
Expand Down Expand Up @@ -2601,6 +2604,41 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
}
}

/** Handle export session request from the webview. */
private async handleExport(sessionID?: string): Promise<void> {
if (!this.client) {
this.postMessage({ type: "error", message: "Not connected to CLI backend" })
return
}
const target = sessionID || this.currentSession?.id
if (!target) return

try {
const dir = this.getWorkspaceDirectory(target)
const { data: info } = await this.client.session.get(
{ sessionID: target, directory: dir },
{ throwOnError: true },
)
const { data: msgs } = await this.client.session.messages(
{ sessionID: target, directory: dir },
{ throwOnError: true },
)
const payload = { info, messages: msgs.map((m) => ({ info: m.info, parts: m.parts })) }
const filename = `${info.title?.replace(/[^a-zA-Z0-9-_ ]/g, "") || "session"}-${target.slice(-8)}.json`
const uri = await vscode.window.showSaveDialog({
defaultUri: vscode.Uri.file(filename),
filters: { JSON: ["json"] },
title: "Export Session",
})
if (!uri) return
await vscode.workspace.fs.writeFile(uri, new TextEncoder().encode(JSON.stringify(payload, null, 2)))
vscode.window.showInformationMessage(`Session exported to ${uri.fsPath}`)
} catch (error) {
console.error("[Kilo New] KiloProvider: Failed to export session:", error)
this.postMessage({ type: "error", message: getErrorMessage(error) || "Failed to export session" })
}
}

// Permission + question handlers extracted to kilo-provider/handlers/permission.ts and question.ts

private get permissionCtx(): PermissionContext {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,12 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
window.addEventListener("compactSession", onCompact)
onCleanup(() => window.removeEventListener("compactSession", onCompact))

const onExport = () => {
session.export()
}
window.addEventListener("exportSession", onExport)
onCleanup(() => window.removeEventListener("exportSession", onExport))

const isBusy = () => session.status() !== "idle"
const isDisabled = () => !server.isConnected()
const hasInput = () => text().trim().length > 0 || imageAttach.images().length > 0 || reviewComments().length > 0
Expand Down
20 changes: 20 additions & 0 deletions packages/kilo-vscode/webview-ui/src/context/session.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ interface SessionContextValue {
) => void
abort: () => void
compact: () => void
export: () => void
respondToPermission: (
permissionId: string,
response: "once" | "always" | "reject",
Expand Down Expand Up @@ -1510,6 +1511,24 @@ export const SessionProvider: ParentComponent = (props) => {
})
}

function exportSession() {
if (!server.isConnected()) {
console.warn("[Kilo New] Cannot export: not connected")
return
}

const sessionID = currentSessionID()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: /export fails for imported cloud session previews

currentSessionID() can be the synthetic cloud:${cloudSessionId} value set in handleCloudSessionDataLoaded(). This branch forwards that ID straight to the extension, but handleExport() then calls client.session.get() / client.session.messages() against the local backend, so exporting a cloud preview always errors. Either disable /export while cloudPreviewId() is set or add the same import-aware handling that sendMessage() / sendCommand() already use.

if (!sessionID) {
console.warn("[Kilo New] Cannot export: no current session")
return
}

vscode.postMessage({
type: "export",
sessionID,
})
}

function respondToPermission(
permissionId: string,
response: "once" | "always" | "reject",
Expand Down Expand Up @@ -1870,6 +1889,7 @@ export const SessionProvider: ParentComponent = (props) => {
sendCommand,
abort,
compact,
export: exportSession,
respondToPermission,
replyToQuestion,
rejectQuestion,
Expand Down
8 changes: 8 additions & 0 deletions packages/kilo-vscode/webview-ui/src/hooks/useSlashCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ export function useSlashCommand(vscode: VSCodeContext, exclude?: Set<string>): S
window.dispatchEvent(new CustomEvent("compactSession"))
},
},
{
name: "export",
description: "Export session to JSON file for debugging",
hints: ["debug", "save", "json"],
action: () => {
window.dispatchEvent(new CustomEvent("exportSession"))
},
},
{
name: "settings",
description: "Open settings",
Expand Down
2 changes: 2 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ export const dict = {
"revert.disabled.agentBusy": "Wait for agent to finish",
"command.session.compact": "Compact session",
"command.session.compact.description": "Summarize the session to reduce context size",
"command.session.export": "Export session",
"command.session.export.description": "Export session to JSON file for debugging",
"command.session.fork": "Fork from message",
"command.session.fork.description": "Create a new session from a previous message",
"command.session.share": "Share session",
Expand Down
6 changes: 6 additions & 0 deletions packages/kilo-vscode/webview-ui/src/types/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1651,6 +1651,11 @@ export interface CompactRequest {
modelID?: string
}

export interface ExportRequest {
type: "export"
sessionID: string
}

export interface OpenSettingsPanelRequest {
type: "openSettingsPanel"
tab?: string
Expand Down Expand Up @@ -2350,6 +2355,7 @@ export type WebviewMessage =
| WebviewReadyRequest
| RequestProvidersMessage
| CompactRequest
| ExportRequest
| RequestAgentsMessage
| RequestSkillsMessage
| RequestCommandsMessage
Expand Down
Loading