Add a read-only Files tab browsing a task's worktree

This commit is contained in:
Ian Gulliver
2026-10-15 07:31:53 -07:00
parent 4ca6f88861
commit de5b944a0c
16 changed files with 1460 additions and 123 deletions
+127
View File
@@ -350,6 +350,44 @@ export interface paths {
patch?: never;
trace?: never;
};
"/api/tasks/{taskId}/dir": {
parameters: {
query?: never;
header?: never;
path: {
taskId: string;
};
cookie?: never;
};
/** @description One directory of the task's worktree, directories first, then by name. Entries named .git are left out; gitignored entries are included and marked. A path that leaves the worktree, through .. or a symlink, is refused. */
get: operations["getTaskDir"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/tasks/{taskId}/file": {
parameters: {
query?: never;
header?: never;
path: {
taskId: string;
};
cookie?: never;
};
/** @description A regular file in the task's worktree. Text is returned up to a size limit; binary files return no content. A path that leaves the worktree, through .. or a symlink, is refused. */
get: operations["getTaskFile"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/tasks/{taskId}/snapshots": {
parameters: {
query?: never;
@@ -722,6 +760,39 @@ export interface components {
path: string;
patch: string;
};
DirListing: {
/** @description The directory, relative to the worktree root; empty for the root. */
path: string;
entries: components["schemas"]["DirEntry"][];
/** @description The directory has more entries than were returned. */
truncated: boolean;
};
DirEntry: {
name: string;
/** @description git ignores the entry: .gitignore and the other exclude files match it or a directory above it. */
ignored: boolean;
/**
* @description What the entry is, following a symlink that stays in the worktree. other: a symlink that leaves the worktree or points nowhere, or a device, socket or pipe.
* @enum {string}
*/
type: "dir" | "file" | "other";
symlink: boolean;
/**
* Format: int64
* @description file: its size in bytes.
*/
size: number;
};
FileContent: {
path: string;
/** Format: int64 */
size: number;
/** @description The file isn't UTF-8 text; text is empty. */
binary: boolean;
/** @description text holds only the start of the file. */
truncated: boolean;
text: string;
};
Snapshot: {
id: string;
task_id: string;
@@ -1535,6 +1606,62 @@ export interface operations {
409: components["responses"]["Error"];
};
};
getTaskDir: {
parameters: {
query?: {
/** @description Slash-separated, relative to the worktree root; empty or absent for the root. */
path?: string;
};
header?: never;
path: {
taskId: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description The directory's entries. */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["DirListing"];
};
};
400: components["responses"]["Error"];
404: components["responses"]["Error"];
409: components["responses"]["Error"];
};
};
getTaskFile: {
parameters: {
query: {
/** @description Slash-separated, relative to the worktree root. */
path: string;
};
header?: never;
path: {
taskId: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description The file. */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["FileContent"];
};
};
400: components["responses"]["Error"];
404: components["responses"]["Error"];
409: components["responses"]["Error"];
};
};
listSnapshots: {
parameters: {
query?: never;