feat(llm): structured error taxonomy with a shared HarnessError base (RFC 005 pt 2)
Introduce HarnessError in dsh-llm (the leaf package): a stable machine-routable
code distinct from the message, cause chaining, name from the subclass, plus
isHarnessError. LlmError, ToolArgsError, and InvariantError now extend it.
Tool failures carry the structure end-to-end: ToolExecutionResult gains
error: { name, code } (populated from a thrown HarnessError), and the loop
forwards it onto the tool/result session event (which gained the same optional
field) for retry/sandbox plugins and replay. The loop's toError wraps non-Error
throws in a HarnessError(code: UNKNOWN, cause) instead of a bare Error.
Landed last and in isolation so it's a pure upgrade over the plain Error+code
the earlier PRs used — independently revertible. Graduates RFC 005 pt 2 ->
ADR 0015; RFC 005 now fully implemented.
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
import type { ContentBlock } from '@deepseek-ai/dsh-llm'
|
||||
import { assertNever } from '@deepseek-ai/dsh-llm'
|
||||
import { assertNever, HarnessError } from '@deepseek-ai/dsh-llm'
|
||||
import type { ToolDefinition, ToolExecution } from './index.ts'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -174,20 +174,17 @@ export function schemaSpecToJsonSchema(spec: SchemaSpec): JsonSchemaObject {
|
||||
|
||||
/**
|
||||
* Thrown by a {@link defineTool} tool when the model-generated arguments don't
|
||||
* match the declared {@link SchemaSpec}. The registry's execute waterfall
|
||||
* catches it and returns an `isError` result so the model can self-correct.
|
||||
*
|
||||
* Plain `Error` for now (carries a `code` field); a later change promotes the
|
||||
* harness error taxonomy and this extends a common base.
|
||||
* match the declared {@link SchemaSpec}. Extends {@link HarnessError}
|
||||
* (`code: 'INVALID_ARGS'`); the registry's execute waterfall catches it and
|
||||
* returns an `isError` ToolExecutionResult carrying the structured error, so
|
||||
* the model can self-correct and downstream plugins can route on the code.
|
||||
*/
|
||||
export class ToolArgsError extends Error {
|
||||
/** Machine-routable code; stable across the message wording. */
|
||||
readonly code = 'INVALID_ARGS'
|
||||
export class ToolArgsError extends HarnessError {
|
||||
/** The individual violation messages, in declaration order. */
|
||||
readonly violations: string[]
|
||||
|
||||
constructor(violations: string[]) {
|
||||
super(`invalid arguments: ${violations.join('; ')}`)
|
||||
super(`invalid arguments: ${violations.join('; ')}`, 'INVALID_ARGS')
|
||||
this.name = 'ToolArgsError'
|
||||
this.violations = violations
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user