|
|
@@ -9,6 +9,9 @@ import {
|
|
|
ApiProviderError,
|
|
|
isApiProviderError,
|
|
|
extractApiProviderErrorProperties,
|
|
|
+ ConsecutiveMistakeError,
|
|
|
+ isConsecutiveMistakeError,
|
|
|
+ extractConsecutiveMistakeErrorProperties,
|
|
|
} from "../telemetry.js"
|
|
|
|
|
|
describe("telemetry error utilities", () => {
|
|
|
@@ -389,4 +392,185 @@ describe("telemetry error utilities", () => {
|
|
|
expect(properties).toHaveProperty("errorCode", 0)
|
|
|
})
|
|
|
})
|
|
|
+
|
|
|
+ describe("ConsecutiveMistakeError", () => {
|
|
|
+ it("should create an error with correct properties", () => {
|
|
|
+ const error = new ConsecutiveMistakeError("Test error", "task-123", 5, 3, "no_tools_used")
|
|
|
+
|
|
|
+ expect(error.message).toBe("Test error")
|
|
|
+ expect(error.name).toBe("ConsecutiveMistakeError")
|
|
|
+ expect(error.taskId).toBe("task-123")
|
|
|
+ expect(error.consecutiveMistakeCount).toBe(5)
|
|
|
+ expect(error.consecutiveMistakeLimit).toBe(3)
|
|
|
+ expect(error.reason).toBe("no_tools_used")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should create an error with provider and modelId", () => {
|
|
|
+ const error = new ConsecutiveMistakeError(
|
|
|
+ "Test error",
|
|
|
+ "task-123",
|
|
|
+ 5,
|
|
|
+ 3,
|
|
|
+ "no_tools_used",
|
|
|
+ "anthropic",
|
|
|
+ "claude-3-sonnet-20240229",
|
|
|
+ )
|
|
|
+
|
|
|
+ expect(error.message).toBe("Test error")
|
|
|
+ expect(error.name).toBe("ConsecutiveMistakeError")
|
|
|
+ expect(error.taskId).toBe("task-123")
|
|
|
+ expect(error.consecutiveMistakeCount).toBe(5)
|
|
|
+ expect(error.consecutiveMistakeLimit).toBe(3)
|
|
|
+ expect(error.reason).toBe("no_tools_used")
|
|
|
+ expect(error.provider).toBe("anthropic")
|
|
|
+ expect(error.modelId).toBe("claude-3-sonnet-20240229")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should be an instance of Error", () => {
|
|
|
+ const error = new ConsecutiveMistakeError("Test error", "task-123", 3, 3)
|
|
|
+ expect(error).toBeInstanceOf(Error)
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should handle zero values", () => {
|
|
|
+ const error = new ConsecutiveMistakeError("Zero test", "task-000", 0, 0)
|
|
|
+
|
|
|
+ expect(error.taskId).toBe("task-000")
|
|
|
+ expect(error.consecutiveMistakeCount).toBe(0)
|
|
|
+ expect(error.consecutiveMistakeLimit).toBe(0)
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should default reason to unknown when not provided", () => {
|
|
|
+ const error = new ConsecutiveMistakeError("Test error", "task-123", 3, 3)
|
|
|
+ expect(error.reason).toBe("unknown")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should accept tool_repetition reason", () => {
|
|
|
+ const error = new ConsecutiveMistakeError("Test error", "task-123", 3, 3, "tool_repetition")
|
|
|
+ expect(error.reason).toBe("tool_repetition")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should accept no_tools_used reason", () => {
|
|
|
+ const error = new ConsecutiveMistakeError("Test error", "task-123", 3, 3, "no_tools_used")
|
|
|
+ expect(error.reason).toBe("no_tools_used")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should have undefined provider and modelId when not provided", () => {
|
|
|
+ const error = new ConsecutiveMistakeError("Test error", "task-123", 3, 3, "no_tools_used")
|
|
|
+ expect(error.provider).toBeUndefined()
|
|
|
+ expect(error.modelId).toBeUndefined()
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ describe("isConsecutiveMistakeError", () => {
|
|
|
+ it("should return true for ConsecutiveMistakeError instances", () => {
|
|
|
+ const error = new ConsecutiveMistakeError("Test error", "task-123", 3, 3)
|
|
|
+ expect(isConsecutiveMistakeError(error)).toBe(true)
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should return false for regular Error instances", () => {
|
|
|
+ const error = new Error("Test error")
|
|
|
+ expect(isConsecutiveMistakeError(error)).toBe(false)
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should return false for ApiProviderError instances", () => {
|
|
|
+ const error = new ApiProviderError("Test error", "OpenRouter", "gpt-4", "createMessage")
|
|
|
+ expect(isConsecutiveMistakeError(error)).toBe(false)
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should return false for null and undefined", () => {
|
|
|
+ expect(isConsecutiveMistakeError(null)).toBe(false)
|
|
|
+ expect(isConsecutiveMistakeError(undefined)).toBe(false)
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should return false for non-error objects", () => {
|
|
|
+ expect(isConsecutiveMistakeError({})).toBe(false)
|
|
|
+ expect(
|
|
|
+ isConsecutiveMistakeError({
|
|
|
+ taskId: "task-123",
|
|
|
+ consecutiveMistakeCount: 3,
|
|
|
+ consecutiveMistakeLimit: 3,
|
|
|
+ }),
|
|
|
+ ).toBe(false)
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should return false for Error with wrong name", () => {
|
|
|
+ const error = new Error("Test error")
|
|
|
+ error.name = "CustomError"
|
|
|
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
+ ;(error as any).taskId = "task-123"
|
|
|
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
+ ;(error as any).consecutiveMistakeCount = 3
|
|
|
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
+ ;(error as any).consecutiveMistakeLimit = 3
|
|
|
+ expect(isConsecutiveMistakeError(error)).toBe(false)
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ describe("extractConsecutiveMistakeErrorProperties", () => {
|
|
|
+ it("should extract all properties from ConsecutiveMistakeError", () => {
|
|
|
+ const error = new ConsecutiveMistakeError("Test error", "task-123", 5, 3, "no_tools_used")
|
|
|
+ const properties = extractConsecutiveMistakeErrorProperties(error)
|
|
|
+
|
|
|
+ expect(properties).toEqual({
|
|
|
+ taskId: "task-123",
|
|
|
+ consecutiveMistakeCount: 5,
|
|
|
+ consecutiveMistakeLimit: 3,
|
|
|
+ reason: "no_tools_used",
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should extract all properties including provider and modelId", () => {
|
|
|
+ const error = new ConsecutiveMistakeError(
|
|
|
+ "Test error",
|
|
|
+ "task-123",
|
|
|
+ 5,
|
|
|
+ 3,
|
|
|
+ "no_tools_used",
|
|
|
+ "anthropic",
|
|
|
+ "claude-3-sonnet-20240229",
|
|
|
+ )
|
|
|
+ const properties = extractConsecutiveMistakeErrorProperties(error)
|
|
|
+
|
|
|
+ expect(properties).toEqual({
|
|
|
+ taskId: "task-123",
|
|
|
+ consecutiveMistakeCount: 5,
|
|
|
+ consecutiveMistakeLimit: 3,
|
|
|
+ reason: "no_tools_used",
|
|
|
+ provider: "anthropic",
|
|
|
+ modelId: "claude-3-sonnet-20240229",
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should not include provider and modelId when undefined", () => {
|
|
|
+ const error = new ConsecutiveMistakeError("Test error", "task-123", 5, 3, "no_tools_used")
|
|
|
+ const properties = extractConsecutiveMistakeErrorProperties(error)
|
|
|
+
|
|
|
+ expect(properties).not.toHaveProperty("provider")
|
|
|
+ expect(properties).not.toHaveProperty("modelId")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should handle zero values correctly", () => {
|
|
|
+ const error = new ConsecutiveMistakeError("Zero test", "task-000", 0, 0)
|
|
|
+ const properties = extractConsecutiveMistakeErrorProperties(error)
|
|
|
+
|
|
|
+ expect(properties).toEqual({
|
|
|
+ taskId: "task-000",
|
|
|
+ consecutiveMistakeCount: 0,
|
|
|
+ consecutiveMistakeLimit: 0,
|
|
|
+ reason: "unknown",
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should handle large numbers", () => {
|
|
|
+ const error = new ConsecutiveMistakeError("Large test", "task-large", 1000, 500, "tool_repetition")
|
|
|
+ const properties = extractConsecutiveMistakeErrorProperties(error)
|
|
|
+
|
|
|
+ expect(properties).toEqual({
|
|
|
+ taskId: "task-large",
|
|
|
+ consecutiveMistakeCount: 1000,
|
|
|
+ consecutiveMistakeLimit: 500,
|
|
|
+ reason: "tool_repetition",
|
|
|
+ })
|
|
|
+ })
|
|
|
+ })
|
|
|
})
|