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