Bladeren bron

effect(core): track stderr truncation; polish AppProcess callers (#27353)

Kit Langton 3 maanden geleden
bovenliggende
commit
42e6b7d541

+ 4 - 2
packages/core/src/process.ts

@@ -31,7 +31,8 @@ export interface RunResult {
   readonly exitCode: number
   readonly stdout: Buffer
   readonly stderr: Buffer
-  readonly truncated: boolean
+  readonly stdoutTruncated: boolean
+  readonly stderrTruncated: boolean
 }
 
 export type Interface = ChildProcessSpawner["Service"] & {
@@ -147,7 +148,8 @@ export const layer = Layer.effect(
             exitCode,
             stdout: stdout.buffer,
             stderr: stderr.buffer,
-            truncated: stdout.truncated,
+            stdoutTruncated: stdout.truncated,
+            stderrTruncated: stderr.truncated,
           } satisfies RunResult
         }),
       )

+ 21 - 3
packages/core/test/process/process.test.ts

@@ -20,7 +20,8 @@ describe("AppProcess", () => {
         const result = yield* svc.run(cmd("-e", "process.stdout.write('hi\\n')"))
         expect(result.exitCode).toBe(0)
         expect(result.stdout.toString("utf8")).toBe("hi\n")
-        expect(result.truncated).toBe(false)
+        expect(result.stdoutTruncated).toBe(false)
+        expect(result.stderrTruncated).toBe(false)
       }),
     )
 
@@ -84,17 +85,34 @@ describe("AppProcess", () => {
     )
 
     it.effect(
-      "truncates output when maxOutputBytes is set",
+      "truncates stdout when maxOutputBytes is set",
       Effect.gen(function* () {
         const svc = yield* AppProcess.Service
         const result = yield* svc.run(cmd("-e", "process.stdout.write('0123456789')"), { maxOutputBytes: 5 })
         expect(result.exitCode).toBe(0)
-        expect(result.truncated).toBe(true)
+        expect(result.stdoutTruncated).toBe(true)
+        expect(result.stderrTruncated).toBe(false)
         expect(result.stdout.length).toBe(5)
         expect(result.stdout.toString("utf8")).toBe("01234")
       }),
     )
 
+    it.effect(
+      "truncates stderr when maxErrorBytes is set",
+      Effect.gen(function* () {
+        const svc = yield* AppProcess.Service
+        const result = yield* svc.run(
+          cmd("-e", "process.stderr.write('0123456789')"),
+          { maxErrorBytes: 5 },
+        )
+        expect(result.exitCode).toBe(0)
+        expect(result.stdoutTruncated).toBe(false)
+        expect(result.stderrTruncated).toBe(true)
+        expect(result.stderr.length).toBe(5)
+        expect(result.stderr.toString("utf8")).toBe("01234")
+      }),
+    )
+
     it.effect(
       "result includes command description",
       Effect.gen(function* () {

+ 2 - 1
packages/opencode/src/format/index.ts

@@ -5,6 +5,7 @@ import { InstanceState } from "@/effect/instance-state"
 import path from "path"
 import { mergeDeep } from "remeda"
 import { Config } from "@/config/config"
+import { errorMessage } from "@/util/error"
 import * as Log from "@opencode-ai/core/util/log"
 import * as Formatter from "./formatter"
 
@@ -100,7 +101,7 @@ export const layer = Layer.effect(
                         command: cmd,
                         ...item.environment,
                         file: filepath,
-                        cause: error.message,
+                        cause: errorMessage(error.cause ?? error),
                       })
                       return undefined
                     }),

+ 1 - 1
packages/opencode/src/git/index.ts

@@ -124,7 +124,7 @@ export const layer = Layer.effect(
           text: () => result.stdout.toString("utf8"),
           stdout: result.stdout,
           stderr: result.stderr,
-          truncated: result.truncated,
+          truncated: result.stdoutTruncated || result.stderrTruncated,
         } satisfies Result
       },
       Effect.catch((err) => Effect.succeed(fail(err))),

+ 2 - 1
packages/opencode/src/installation/index.ts

@@ -1,6 +1,7 @@
 import { Effect, Layer, Schema, Context, Stream } from "effect"
 import { FetchHttpClient, HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http"
 import { withTransientReadRetry } from "@/util/effect-http-client"
+import { errorMessage } from "@/util/error"
 import { ChildProcess } from "effect/unstable/process"
 import { AppProcess } from "@opencode-ai/core/process"
 import path from "path"
@@ -124,7 +125,7 @@ export const layer: Layer.Layer<Service, never, HttpClient.HttpClient | AppProce
           stderr: result.stderr.toString("utf8"),
         }
       },
-      Effect.catch(() => Effect.succeed({ code: 1, stdout: "", stderr: "" })),
+      Effect.catch((err) => Effect.succeed({ code: 1, stdout: "", stderr: errorMessage(err) })),
     )
 
     const getBrewFormula = Effect.fnUntraced(function* () {