From a9524b3e30a8527cec9521bcf8440f5bc786e8ad Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Tue, 30 Dec 2025 22:03:04 +0000 Subject: [PATCH] Load complete background process output and fix dialog layout --- .../src/background-processes/manager.ts | 13 +++++---- .../src/server/routes/background-processes.ts | 2 ++ .../background-process-output-dialog.tsx | 28 ++++++++++--------- packages/ui/src/lib/api-client.ts | 5 +++- 4 files changed, 28 insertions(+), 20 deletions(-) diff --git a/packages/server/src/background-processes/manager.ts b/packages/server/src/background-processes/manager.ts index 878a0409..18d79e7f 100644 --- a/packages/server/src/background-processes/manager.ts +++ b/packages/server/src/background-processes/manager.ts @@ -166,7 +166,7 @@ export class BackgroundProcessManager { async readOutput( workspaceId: string, processId: string, - options: { method?: "full" | "tail" | "head" | "grep"; pattern?: string; lines?: number }, + options: { method?: "full" | "tail" | "head" | "grep"; pattern?: string; lines?: number; maxBytes?: number }, ) { const outputPath = this.getOutputPath(workspaceId, processId) if (!existsSync(outputPath)) { @@ -178,7 +178,7 @@ export class BackgroundProcessManager { const method = options.method ?? "full" const lineCount = options.lines ?? 10 - const raw = await this.readOutputBytes(outputPath, sizeBytes) + const raw = await this.readOutputBytes(outputPath, sizeBytes, options.maxBytes) let content = raw switch (method) { @@ -198,10 +198,11 @@ export class BackgroundProcessManager { content = raw } + const effectiveMaxBytes = options.maxBytes return { id: processId, content, - truncated: sizeBytes > MAX_OUTPUT_BYTES, + truncated: effectiveMaxBytes !== undefined && sizeBytes > effectiveMaxBytes, sizeBytes, } } @@ -280,12 +281,12 @@ export class BackgroundProcessManager { return "error" } - private async readOutputBytes(outputPath: string, sizeBytes: number): Promise { - if (sizeBytes <= MAX_OUTPUT_BYTES) { + private async readOutputBytes(outputPath: string, sizeBytes: number, maxBytes?: number): Promise { + if (maxBytes === undefined || sizeBytes <= maxBytes) { return await fs.readFile(outputPath, "utf-8") } - const start = Math.max(0, sizeBytes - MAX_OUTPUT_BYTES) + const start = Math.max(0, sizeBytes - maxBytes) const file = await fs.open(outputPath, "r") const buffer = Buffer.alloc(sizeBytes - start) await file.read(buffer, 0, buffer.length, start) diff --git a/packages/server/src/server/routes/background-processes.ts b/packages/server/src/server/routes/background-processes.ts index 5603326b..c9520416 100644 --- a/packages/server/src/server/routes/background-processes.ts +++ b/packages/server/src/server/routes/background-processes.ts @@ -16,6 +16,7 @@ const OutputQuerySchema = z.object({ mode: z.enum(["full", "tail", "head", "grep"]).optional(), pattern: z.string().optional(), lines: z.coerce.number().int().positive().max(2000).optional(), + maxBytes: z.coerce.number().int().positive().optional(), }) export function registerBackgroundProcessRoutes(app: FastifyInstance, deps: RouteDeps) { @@ -66,6 +67,7 @@ export function registerBackgroundProcessRoutes(app: FastifyInstance, deps: Rout method, pattern: query.pattern, lines: query.lines, + maxBytes: query.maxBytes, }) } catch (error) { reply.code(400) diff --git a/packages/ui/src/components/background-process-output-dialog.tsx b/packages/ui/src/components/background-process-output-dialog.tsx index 40fdfedd..be7cfd6b 100644 --- a/packages/ui/src/components/background-process-output-dialog.tsx +++ b/packages/ui/src/components/background-process-output-dialog.tsx @@ -26,7 +26,7 @@ export function BackgroundProcessOutputDialog(props: BackgroundProcessOutputDial setLoading(true) serverApi - .fetchBackgroundProcessOutput(props.instanceId, process.id, { method: "full" }) + .fetchBackgroundProcessOutput(props.instanceId, process.id, { method: "full", maxBytes: undefined }) .then((response) => { if (!active) return setOutput(response.content) @@ -65,18 +65,20 @@ export function BackgroundProcessOutputDialog(props: BackgroundProcessOutputDial
-
-
- Background Output - - - {props.process?.title} · {props.process?.id} - - {props.process?.command} - -
+
+
+ Background Output + + + {props.process?.title} · {props.process?.id} + + + {props.process?.command} + + +
-
@@ -88,7 +90,7 @@ export function BackgroundProcessOutputDialog(props: BackgroundProcessOutputDial

Output truncated for display.

-
+                
                   {output()}
                 
diff --git a/packages/ui/src/lib/api-client.ts b/packages/ui/src/lib/api-client.ts index 4ed51c1e..f85d63e1 100644 --- a/packages/ui/src/lib/api-client.ts +++ b/packages/ui/src/lib/api-client.ts @@ -247,7 +247,7 @@ export const serverApi = { fetchBackgroundProcessOutput( instanceId: string, processId: string, - options?: { method?: "full" | "tail" | "head" | "grep"; pattern?: string; lines?: number }, + options?: { method?: "full" | "tail" | "head" | "grep"; pattern?: string; lines?: number; maxBytes?: number }, ): Promise { const params = new URLSearchParams() if (options?.method) { @@ -259,6 +259,9 @@ export const serverApi = { if (options?.lines) { params.set("lines", String(options.lines)) } + if (options?.maxBytes !== undefined) { + params.set("maxBytes", String(options.maxBytes)) + } const query = params.toString() const suffix = query ? `?${query}` : "" return request(