mirror of
https://github.com/cline/cline.git
synced 2026-08-29 03:52:41 +08:00
Fix task export button: resolve the SDK session folder reliably (#12772)
* Restore task export to markdown and show download button in all builds * Render untyped tool outputs and object tool inputs as JSON in task export * Open the task's SDK session folder from the export button and show it in all builds * Keep the task header session-folder button dev-only
This commit is contained in:
@@ -29,7 +29,7 @@ service TaskService {
|
||||
rpc newTask(NewTaskRequest) returns (String);
|
||||
// Shows a task with the specified ID
|
||||
rpc showTaskWithId(StringRequest) returns (TaskResponse);
|
||||
// Exports a task with the given ID to markdown
|
||||
// Opens the on-disk session directory (messages json, logs) for the task with the given ID
|
||||
rpc exportTaskWithId(StringRequest) returns (Empty);
|
||||
// Toggles the favorite status of a task
|
||||
rpc toggleTaskFavorite(TaskFavoriteRequest) returns (Empty);
|
||||
|
||||
@@ -1799,16 +1799,9 @@ export class Controller {
|
||||
}
|
||||
|
||||
async exportTaskWithId(id: string): Promise<void> {
|
||||
const historyItem = (await this.taskHistory.listHistory({ hydrate: false })).find((item) => item.sessionId === id)
|
||||
if (!historyItem) {
|
||||
throw new Error(`Task not found in history: ${id}`)
|
||||
}
|
||||
|
||||
const taskDirPath = historyItem.messagesPath
|
||||
? path.dirname(historyItem.messagesPath)
|
||||
: this.taskHistory.getLegacyTaskDirPath(id)
|
||||
const taskDirPath = await this.taskHistory.getTaskDirPath(id)
|
||||
if (!taskDirPath) {
|
||||
throw new Error(`Task history item has no artifact path: ${id}`)
|
||||
throw new Error(`Task not found in history: ${id}`)
|
||||
}
|
||||
|
||||
await fs.access(taskDirPath)
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { existsSync } from "node:fs"
|
||||
import path from "node:path"
|
||||
import type { ClineCoreListHistoryOptions, SessionHistoryRecord } from "@cline/core"
|
||||
import type { Message as SdkMessage } from "@cline/llms"
|
||||
import { formatDisplayUserInput, parseUserInputMode } from "@cline/shared"
|
||||
import { resolveSessionDataDir } from "@cline/shared/storage"
|
||||
import type { ClineMessage } from "@shared/ExtensionMessage"
|
||||
import type { HistoryItem } from "@shared/HistoryItem"
|
||||
import getFolderSize from "get-folder-size"
|
||||
@@ -473,6 +475,33 @@ export class SdkTaskHistory {
|
||||
return clineMessages
|
||||
}
|
||||
|
||||
/**
|
||||
* Absolute path of the directory holding the task's on-disk artifacts: the SDK
|
||||
* session folder (manifest json + messages json) for SDK tasks, or the legacy
|
||||
* tasks/<id> folder for pre-SDK tasks. Undefined when the task is unknown.
|
||||
*/
|
||||
async getTaskDirPath(taskId: string): Promise<string | undefined> {
|
||||
const sdkRecord = await this.getSdkRecord(taskId)
|
||||
if (sdkRecord) {
|
||||
const messagesPath = typeof sdkRecord.messagesPath === "string" ? sdkRecord.messagesPath.trim() : ""
|
||||
if (messagesPath) {
|
||||
return path.dirname(messagesPath)
|
||||
}
|
||||
// Older records may lack messagesPath; fall back to the canonical
|
||||
// session directory when it exists on disk.
|
||||
const sessionDir = path.join(resolveSessionDataDir(), taskId)
|
||||
if (existsSync(sessionDir)) {
|
||||
return sessionDir
|
||||
}
|
||||
}
|
||||
return this.getLegacyTaskDirPath(taskId)
|
||||
}
|
||||
|
||||
getLegacyTaskDirPath(taskId: string): string | undefined {
|
||||
const legacyTask = this.findLegacyTask(taskId)
|
||||
return legacyTask ? taskDirPath(taskId, legacyTask.dataDir) : undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* The persisted session status ("completed" | "cancelled" | "failed" | ...).
|
||||
* Persisted messages cannot distinguish a completed conversation from one
|
||||
@@ -513,11 +542,6 @@ export class SdkTaskHistory {
|
||||
return appendLegacyResumeWarning(fallbackMessages as { role: string; content: unknown }[])
|
||||
}
|
||||
|
||||
getLegacyTaskDirPath(taskId: string): string | undefined {
|
||||
const legacyTask = this.findLegacyTask(taskId)
|
||||
return legacyTask ? taskDirPath(taskId, legacyTask.dataDir) : undefined
|
||||
}
|
||||
|
||||
private async updateSession(sessionId: string, item: HistoryItem): Promise<void> {
|
||||
const { metadata: writtenMetadata, updated } = await this.withHistoryHost(async (host) => {
|
||||
const existing = await host.get(sessionId)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
declare module "@cline/shared/storage" {
|
||||
export function resolveGlobalSettingsPath(): string
|
||||
export function resolveSessionDataDir(): string
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user