| ... | ... | @@ -3197,6 +3197,49 @@ describe("ClaudeAdapterV2 background wake turns", () => { |
| 3197 | 3197 | ), |
| 3198 | 3198 | ); |
| 3199 | 3199 | |
| 3200 | it.effect("shows a 403 permission error instead of the login hint", () => |
| 3201 | Effect.gen(function* () { |
| 3202 | const harness = yield* makeWakeHarness; |
| 3203 | const now = yield* DateTime.now; |
| 3204 | yield* harness.runtime.startTurn( |
| 3205 | makeClaudeTestTurnInput({ |
| 3206 | threadId: harness.threadId, |
| 3207 | providerThread: harness.providerThread, |
| 3208 | now, |
| 3209 | attemptId: RunAttemptId.make("attempt-claude-permission-denied"), |
| 3210 | text: "Continue.", |
| 3211 | attachments: [], |
| 3212 | }), |
| 3213 | ); |
| 3214 | // Claude CLI 2.1.288 labels a 403 authentication_failed too. |
| 3215 | const cliText = |
| 3216 | "Failed to authenticate. API Error: 403 Your organization does not have access to this model."; |
| 3217 | yield* Queue.offerAll(harness.sdkMessages, [ |
| 3218 | makeAssistantErrorFrame({ |
| 3219 | uuid: "00000000-0000-4000-8000-000000000608", |
| 3220 | error: "authentication_failed", |
| 3221 | }), |
| 3222 | makeResultFrame({ |
| 3223 | uuid: "00000000-0000-4000-8000-000000000609", |
| 3224 | result: cliText, |
| 3225 | isError: true, |
| 3226 | apiErrorStatus: 403, |
| 3227 | terminalReason: "api_error", |
| 3228 | }), |
| 3229 | ]); |
| 3230 | |
| 3231 | const terminal = yield* Queue.take(harness.terminalReceipts); |
| 3232 | assert.equal(terminal.status, "failed"); |
| 3233 | if (terminal.status !== "failed") return; |
| 3234 | assert.equal(terminal.failure.message, cliText); |
| 3235 | assert.equal(terminal.failure.code, "api_error_403"); |
| 3236 | }).pipe( |
| 3237 | Effect.provide( |
| 3238 | Layer.mergeAll(IdAllocator.layer, McpProviderSessions.layer, NodeServices.layer), |
| 3239 | ), |
| 3240 | ), |
| 3241 | ); |
| 3242 | |
| 3200 | 3243 | it.effect.each([ |
| 3201 | 3244 | { recovered: false, expected: "Claude usage limit reached" }, |
| 3202 | 3245 | { recovered: true, expected: "Claude gave up after repeated API errors" }, |