| author | |
| committer | |
| log | 13eeb07f5f4b582e2ff824db382ff8917489c5c6 |
| tree | 8978958fc97729744578a5ba50c9889d194a99ed |
| parent | 1e9bac7f6e783fe0498ddeb8392c5f4b50aad19d |
4 files changed, 22 insertions(+), 43 deletions(-)
apps/server/src/orchestration/Layers/OrchestrationEngine.ts+1-8| ... | ... | @@ -49,13 +49,6 @@ function commandToAggregateRef(command: OrchestrationCommand): { |
| 49 | 49 | } |
| 50 | 50 | } |
| 51 | 51 | |
| 52 | function formatDispatchError(error: OrchestrationDispatchError): string { | |
| 53 | if (error instanceof Error && error.message.length > 0) { | |
| 54 | return error.message; | |
| 55 | } | |
| 56 | return String(error); | |
| 57 | } | |
| 58 | ||
| 59 | 52 | const makeOrchestrationEngine = Effect.gen(function* () { |
| 60 | 53 | const sql = yield* SqlClient.SqlClient; |
| 61 | 54 | const eventStore = yield* OrchestrationEventStore; |
| ... | ... | @@ -191,7 +184,7 @@ const makeOrchestrationEngine = Effect.gen(function* () { |
| 191 | 184 | acceptedAt: new Date().toISOString(), |
| 192 | 185 | resultSequence: readModel.snapshotSequence, |
| 193 | 186 | status: "rejected", |
| 194 | error: formatDispatchError(error), | |
| 187 | error: error.message, | |
| 195 | 188 | }) |
| 196 | 189 | .pipe(Effect.catch(() => Effect.void)); |
| 197 | 190 | } |
apps/server/src/orchestration/Layers/ProviderCommandReactor.ts+7-20| ... | ... | @@ -16,7 +16,7 @@ import { Cache, Cause, Duration, Effect, Layer, Option, Queue, Schema, Stream } |
| 16 | 16 | |
| 17 | 17 | import { resolveThreadWorkspaceCwd } from "../../checkpointing/Utils.ts"; |
| 18 | 18 | import { GitCore } from "../../git/Services/GitCore.ts"; |
| 19 | import { ProviderAdapterRequestError } from "../../provider/Errors.ts"; | |
| 19 | import { ProviderAdapterRequestError, ProviderServiceError } from "../../provider/Errors.ts"; | |
| 20 | 20 | import { TextGeneration } from "../../git/Services/TextGeneration.ts"; |
| 21 | 21 | import { ProviderService } from "../../provider/Services/ProviderService.ts"; |
| 22 | 22 | import { OrchestrationEngineService } from "../Services/OrchestrationEngine.ts"; |
| ... | ... | @@ -73,18 +73,8 @@ const DEFAULT_RUNTIME_MODE: RuntimeMode = "full-access"; |
| 73 | 73 | const WORKTREE_BRANCH_PREFIX = "t3code"; |
| 74 | 74 | const TEMP_WORKTREE_BRANCH_PATTERN = new RegExp(`^${WORKTREE_BRANCH_PREFIX}\\/[0-9a-f]{8}$`); |
| 75 | 75 | |
| 76 | function toErrorMessage(error: unknown): string { | |
| 77 | if (error instanceof Error && error.message.trim().length > 0) { | |
| 78 | return error.message; | |
| 79 | } | |
| 80 | try { | |
| 81 | return JSON.stringify(error); | |
| 82 | } catch { | |
| 83 | return String(error); | |
| 84 | } | |
| 85 | } | |
| 86 | ||
| 87 | function isUnknownPendingApprovalRequestError(error: unknown): boolean { | |
| 76 | function isUnknownPendingApprovalRequestError(cause: Cause.Cause<ProviderServiceError>): boolean { | |
| 77 | const error = Cause.squash(cause); | |
| 88 | 78 | if (Schema.is(ProviderAdapterRequestError)(error)) { |
| 89 | 79 | const detail = error.detail.toLowerCase(); |
| 90 | 80 | return ( |
| ... | ... | @@ -92,7 +82,7 @@ function isUnknownPendingApprovalRequestError(error: unknown): boolean { |
| 92 | 82 | detail.includes("unknown pending permission request") |
| 93 | 83 | ); |
| 94 | 84 | } |
| 95 | const message = toErrorMessage(error).toLowerCase(); | |
| 85 | const message = Cause.pretty(cause); | |
| 96 | 86 | return ( |
| 97 | 87 | message.includes("unknown pending approval request") || |
| 98 | 88 | message.includes("unknown pending permission request") |
| ... | ... | @@ -539,19 +529,17 @@ const make = Effect.gen(function* () { |
| 539 | 529 | .pipe( |
| 540 | 530 | Effect.catchCause((cause) => |
| 541 | 531 | Effect.gen(function* () { |
| 542 | const error = Cause.squash(cause); | |
| 543 | const detail = toErrorMessage(error); | |
| 544 | 532 | yield* appendProviderFailureActivity({ |
| 545 | 533 | threadId: event.payload.threadId, |
| 546 | 534 | kind: "provider.approval.respond.failed", |
| 547 | 535 | summary: "Provider approval response failed", |
| 548 | detail, | |
| 536 | detail: Cause.pretty(cause), | |
| 549 | 537 | turnId: null, |
| 550 | 538 | createdAt: event.payload.createdAt, |
| 551 | 539 | requestId: event.payload.requestId, |
| 552 | 540 | }); |
| 553 | 541 | |
| 554 | if (!isUnknownPendingApprovalRequestError(error)) return; | |
| 542 | if (!isUnknownPendingApprovalRequestError(cause)) return; | |
| 555 | 543 | }), |
| 556 | 544 | ), |
| 557 | 545 | ); |
| ... | ... | @@ -586,12 +574,11 @@ const make = Effect.gen(function* () { |
| 586 | 574 | .pipe( |
| 587 | 575 | Effect.catchCause((cause) => |
| 588 | 576 | Effect.gen(function* () { |
| 589 | const error = Cause.squash(cause); | |
| 590 | 577 | yield* appendProviderFailureActivity({ |
| 591 | 578 | threadId: event.payload.threadId, |
| 592 | 579 | kind: "provider.user-input.respond.failed", |
| 593 | 580 | summary: "Provider user input response failed", |
| 594 | detail: toErrorMessage(error), | |
| 581 | detail: Cause.pretty(cause), | |
| 595 | 582 | turnId: null, |
| 596 | 583 | createdAt: event.payload.createdAt, |
| 597 | 584 | requestId: event.payload.requestId, |
apps/server/src/provider/Layers/CodexAdapter.ts+11-5| ... | ... | @@ -1338,11 +1338,17 @@ const makeCodexAdapter = (options?: CodexAdapterLiveOptions) => |
| 1338 | 1338 | new Error(`Invalid attachment id '${attachment.id}'.`), |
| 1339 | 1339 | ); |
| 1340 | 1340 | } |
| 1341 | const bytes = yield* fileSystem | |
| 1342 | .readFile(attachmentPath) | |
| 1343 | .pipe( | |
| 1344 | Effect.mapError((cause) => toRequestError(input.threadId, "turn/start", cause)), | |
| 1345 | ); | |
| 1341 | const bytes = yield* fileSystem.readFile(attachmentPath).pipe( | |
| 1342 | Effect.mapError( | |
| 1343 | (cause) => | |
| 1344 | new ProviderAdapterRequestError({ | |
| 1345 | provider: PROVIDER, | |
| 1346 | method: "turn/start", | |
| 1347 | detail: toMessage(cause, "Failed to read attachment file."), | |
| 1348 | cause, | |
| 1349 | }), | |
| 1350 | ), | |
| 1351 | ); | |
| 1346 | 1352 | return { |
| 1347 | 1353 | type: "image" as const, |
| 1348 | 1354 | url: `data:${attachment.mimeType};base64,${Buffer.from(bytes).toString("base64")}`, |
apps/server/src/wsServer.ts+3-10| ... | ... | @@ -99,8 +99,7 @@ export interface ServerShape { |
| 99 | 99 | */ |
| 100 | 100 | export class Server extends ServiceMap.Service<Server, ServerShape>()("t3/wsServer/Server") {} |
| 101 | 101 | |
| 102 | const isServerNotRunningError = (error: unknown): boolean => { | |
| 103 | if (!(error instanceof Error)) return false; | |
| 102 | const isServerNotRunningError = (error: Error): boolean => { | |
| 104 | 103 | const maybeCode = (error as NodeJS.ErrnoException).code; |
| 105 | 104 | return ( |
| 106 | 105 | maybeCode === "ERR_SERVER_NOT_RUNNING" || error.message.toLowerCase().includes("not running") |
| ... | ... | @@ -196,12 +195,6 @@ function stripRequestTag<T extends { _tag: string }>(body: T) { |
| 196 | 195 | return Struct.omit(body, ["_tag"]); |
| 197 | 196 | } |
| 198 | 197 | |
| 199 | function messageFromCause(cause: Cause.Cause<unknown>): string { | |
| 200 | const squashed = Cause.squash(cause); | |
| 201 | const message = squashed instanceof Error ? squashed.message.trim() : String(squashed).trim(); | |
| 202 | return message.length > 0 ? message : Cause.pretty(cause); | |
| 203 | } | |
| 204 | ||
| 205 | 198 | export type ServerCoreRuntimeServices = |
| 206 | 199 | | OrchestrationEngineService |
| 207 | 200 | | ProjectionSnapshotQuery |
| ... | ... | @@ -943,7 +936,7 @@ export const createServer = Effect.fn(function* (): Effect.fn.Return< |
| 943 | 936 | if (request._tag === "Failure") { |
| 944 | 937 | const errorResponse = yield* encodeResponse({ |
| 945 | 938 | id: "unknown", |
| 946 | error: { message: `Invalid request format: ${messageFromCause(request.cause)}` }, | |
| 939 | error: { message: `Invalid request format: ${Cause.pretty(request.cause)}` }, | |
| 947 | 940 | }); |
| 948 | 941 | ws.send(errorResponse); |
| 949 | 942 | return; |
| ... | ... | @@ -953,7 +946,7 @@ export const createServer = Effect.fn(function* (): Effect.fn.Return< |
| 953 | 946 | if (result._tag === "Failure") { |
| 954 | 947 | const errorResponse = yield* encodeResponse({ |
| 955 | 948 | id: request.value.id, |
| 956 | error: { message: messageFromCause(result.cause) }, | |
| 949 | error: { message: Cause.pretty(result.cause) }, | |
| 957 | 950 | }); |
| 958 | 951 | ws.send(errorResponse); |
| 959 | 952 | return; |