fix(goal): preserve structured domain error codes

This commit is contained in:
Tianyi Cui
2026-07-19 18:56:11 +08:00
parent a525776015
commit e9940d35cf
2 changed files with 8 additions and 5 deletions
+6 -4
View File
@@ -1,5 +1,6 @@
/** Runtime constructors and protocol constants for the goal domain. */ /** Runtime constructors and protocol constants for the goal domain. */
import { HarnessError } from '@deepseek-ai/dsh-llm'
import type { GoalErrorCode, GoalId as GoalIdType } from './types.ts' import type { GoalErrorCode, GoalId as GoalIdType } from './types.ts'
/** Version of the goal change metadata embedded in `context/message`. */ /** Version of the goal change metadata embedded in `context/message`. */
@@ -15,13 +16,14 @@ export function GoalId(id: string): GoalIdType {
} }
/** Error returned by the goal domain boundary. */ /** Error returned by the goal domain boundary. */
export class GoalError extends Error { export class GoalError extends HarnessError {
/** /**
* @param message - human-readable rejection reason. * @param message - human-readable rejection reason.
* @param code - stable machine-routable classification. * @param code - stable machine-routable classification.
*/ */
constructor(message: string, public readonly code: GoalErrorCode) { // Keep the constructor to narrow HarnessError's string code at this boundary.
super(message) // eslint-disable-next-line @typescript-eslint/no-useless-constructor -- type-only narrowing
this.name = 'GoalError' constructor(message: string, code: GoalErrorCode) {
super(message, code)
} }
} }
+2 -1
View File
@@ -2,7 +2,7 @@ import { describe, expect, it, vi } from 'vitest'
import { Context } from 'cordis' import { Context } from 'cordis'
import AgentRegistry, { agentEvents } from '@deepseek-ai/dsh-agent' import AgentRegistry, { agentEvents } from '@deepseek-ai/dsh-agent'
import type { Agent, AgentStatus, InjectOptions } from '@deepseek-ai/dsh-agent' import type { Agent, AgentStatus, InjectOptions } from '@deepseek-ai/dsh-agent'
import type { ContentBlock, MessageSource } from '@deepseek-ai/dsh-llm' import { HarnessError, type ContentBlock, type MessageSource } from '@deepseek-ai/dsh-llm'
import SessionStore, { Session, SessionId } from '@deepseek-ai/dsh-session' import SessionStore, { Session, SessionId } from '@deepseek-ai/dsh-session'
import GoalService, { import GoalService, {
GoalError, GoalError,
@@ -161,6 +161,7 @@ describe('GoalService creation and replay', () => {
code: 'GOAL_INVALID_MAX_ROUNDS', code: 'GOAL_INVALID_MAX_ROUNDS',
})) }))
expect(() => ctx.goals.resolveCreate({ objective: 'x', maxGoalRounds: 1.5 })).toThrow(GoalError) expect(() => ctx.goals.resolveCreate({ objective: 'x', maxGoalRounds: 1.5 })).toThrow(GoalError)
expect(() => ctx.goals.resolveCreate({ objective: 'x', maxGoalRounds: 1.5 })).toThrow(HarnessError)
expect(() => ctx.goals.resolveCreate({ objective: 'x', maxGoalRounds: Number.MAX_SAFE_INTEGER + 1 })).toThrow(GoalError) expect(() => ctx.goals.resolveCreate({ objective: 'x', maxGoalRounds: Number.MAX_SAFE_INTEGER + 1 })).toThrow(GoalError)
expect(ctx.goals.create(agent, { objective: 'x' }).maxGoalRounds).toBe(256) expect(ctx.goals.create(agent, { objective: 'x' }).maxGoalRounds).toBe(256)
}) })