refactor(query): deepen dispatch policy seam with structured result contract (#3066)
* refactor(query): deepen dispatch policy seam with structured result contract Closes #3065. - unify query dispatch outcome as typed success/failure union - include error kind/details + final exit_code in failure path - align native and fallback paths under one dispatch policy seam - make CLI query path consume seam result (thin adapter) - add ADR + context term for Dispatch Policy Module * refactor(query): strengthen dispatch seam with shared error mapper and typed details - add query-dispatch-error-mapper module shared by native/fallback paths - remove ad-hoc inline mapping in dispatch/fallback executors - lock error-details schema in mapper + dispatch tests - document structured dispatch contract in QUERY-HANDLERS.md * fix(query): return structured fallback failure when path resolution throws - guard resolveGsdToolsPath in cjs dispatch path - map thrown resolution errors to fallback_failure result - add regression test for structured failure contract
This commit is contained in:
51
sdk/src/query/query-dispatch-error-mapper.ts
Normal file
51
sdk/src/query/query-dispatch-error-mapper.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import type { QueryDispatchError, QueryDispatchErrorKind, QueryDispatchResult } from './query-dispatch-contract.js';
|
||||
|
||||
export function toDispatchFailure(
|
||||
error: QueryDispatchError,
|
||||
stderr: string[] = [],
|
||||
): QueryDispatchResult {
|
||||
return {
|
||||
ok: false,
|
||||
stderr,
|
||||
exit_code: error.code,
|
||||
error,
|
||||
};
|
||||
}
|
||||
|
||||
export function mapNativeDispatchError(error: unknown, command: string, args: string[]): QueryDispatchError {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
const kind: QueryDispatchErrorKind = message.includes('timed out after')
|
||||
? 'native_timeout'
|
||||
: 'native_failure';
|
||||
return {
|
||||
kind,
|
||||
code: 1,
|
||||
message: `Error: ${message}`,
|
||||
details: {
|
||||
command,
|
||||
args,
|
||||
...(kind === 'native_timeout' ? { timeout_ms: parseTimeoutMs(message) } : {}),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function mapFallbackDispatchError(error: unknown, command: string, args: string[]): QueryDispatchError {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
return {
|
||||
kind: 'fallback_failure',
|
||||
code: 1,
|
||||
message: `Error: gsd-tools.cjs fallback failed: ${message}`,
|
||||
details: {
|
||||
command,
|
||||
args,
|
||||
backend: 'cjs',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function parseTimeoutMs(message: string): number | undefined {
|
||||
const m = message.match(/timed out after\s+(\d+)ms/i);
|
||||
if (!m) return undefined;
|
||||
const n = Number.parseInt(m[1], 10);
|
||||
return Number.isFinite(n) ? n : undefined;
|
||||
}
|
||||
Reference in New Issue
Block a user