error.test.ts 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. import { describe, expect, test } from "bun:test"
  2. import { RequestError } from "@agentclientprotocol/sdk"
  3. import * as ACPError from "../../src/acp/error"
  4. describe("acp.error", () => {
  5. test("maps validation failures to invalid params", () => {
  6. const cases: ACPError.Error[] = [
  7. new ACPError.SessionNotFoundError({ sessionId: "ses_missing" }),
  8. new ACPError.InvalidConfigOptionError({ configId: "temperature" }),
  9. new ACPError.InvalidModelError({ providerId: "anthropic", modelId: "claude-missing" }),
  10. new ACPError.InvalidEffortError({ effort: "extreme" }),
  11. new ACPError.InvalidModeError({ mode: "turbo" }),
  12. ]
  13. expect(cases.map((error) => ACPError.toRequestError(error).code)).toEqual([
  14. -32602, -32602, -32602, -32602, -32602,
  15. ])
  16. })
  17. test("includes safe validation details", () => {
  18. expect(ACPError.toRequestError(new ACPError.SessionNotFoundError({ sessionId: "ses_123" }))).toMatchObject({
  19. code: -32602,
  20. data: { sessionId: "ses_123" },
  21. })
  22. expect(ACPError.toRequestError(new ACPError.InvalidModelError({ modelId: "gpt-missing" }))).toMatchObject({
  23. code: -32602,
  24. data: { modelId: "gpt-missing" },
  25. })
  26. })
  27. test("maps auth required to the SDK auth error", () => {
  28. const requestError = ACPError.toRequestError(new ACPError.AuthRequiredError({ providerId: "anthropic" }))
  29. expect(requestError).toBeInstanceOf(RequestError)
  30. expect(requestError.code).toBe(-32000)
  31. expect(requestError.message).toBe("Authentication required: provider authentication required")
  32. expect(requestError.data).toEqual({ providerId: "anthropic" })
  33. })
  34. test("maps unsupported operations to method not found", () => {
  35. const requestError = ACPError.toRequestError(
  36. new ACPError.UnsupportedOperationError({ method: "session/new" }),
  37. )
  38. expect(requestError.code).toBe(-32601)
  39. expect(requestError.data).toEqual({ method: "session/new" })
  40. })
  41. test("maps service failures to safe internal errors", () => {
  42. const requestError = ACPError.toRequestError(
  43. new ACPError.ServiceFailureError({ service: "provider", safeMessage: "Provider request failed" }),
  44. )
  45. expect(requestError.code).toBe(-32603)
  46. expect(requestError.message).toBe("Internal error: Provider request failed")
  47. expect(requestError.data).toEqual({ service: "provider" })
  48. })
  49. test("wraps unknown defects without leaking raw details", () => {
  50. const requestError = ACPError.toRequestError(
  51. ACPError.fromUnknownDefect(new Error("stack has sk-ant-secret and oauth refresh token")),
  52. )
  53. const serialized = JSON.stringify(requestError.toErrorResponse())
  54. expect(requestError.code).toBe(-32603)
  55. expect(requestError.message).toBe("Internal error: Internal service failure")
  56. expect(serialized).not.toContain("sk-ant-secret")
  57. expect(serialized).not.toContain("oauth refresh token")
  58. expect(serialized).not.toContain("stack")
  59. })
  60. })