File size: 3,825 Bytes
4e23b01 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | import { ErrorCodes, Error2 } from '@moonshot-ai/agent-core-v2';
import { errEnvelope } from '../protocol/envelope';
import { ErrorCode } from '../protocol/error-codes';
export class TimeoutError extends Error {
constructor(readonly ms: number) {
super(`call timed out after ${ms}ms`);
this.name = 'TimeoutError';
}
}
export function withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {
if (ms <= 0) return promise;
let timer: ReturnType<typeof setTimeout> | undefined;
const timeout = new Promise<never>((_resolve, reject) => {
timer = setTimeout(() => reject(new TimeoutError(ms)), ms);
timer.unref?.();
});
return Promise.race([promise, timeout]).finally(() => {
if (timer !== undefined) clearTimeout(timer);
}) as Promise<T>;
}
const KIMI_TO_PROTOCOL: Record<string, ErrorCode> = {
[ErrorCodes.SESSION_NOT_FOUND]: ErrorCode.SESSION_NOT_FOUND,
[ErrorCodes.AGENT_NOT_FOUND]: ErrorCode.SESSION_NOT_FOUND,
[ErrorCodes.SESSION_UNDO_UNAVAILABLE]: ErrorCode.SESSION_UNDO_UNAVAILABLE,
[ErrorCodes.REQUEST_INVALID]: ErrorCode.VALIDATION_FAILED,
[ErrorCodes.CONFIG_INVALID]: ErrorCode.VALIDATION_FAILED,
[ErrorCodes.NOT_IMPLEMENTED]: ErrorCode.INTERNAL_ERROR,
[ErrorCodes.PROMPT_NOT_FOUND]: ErrorCode.PROMPT_NOT_FOUND,
[ErrorCodes.FS_PATH_NOT_FOUND]: ErrorCode.FS_PATH_NOT_FOUND,
[ErrorCodes.SESSION_BUSY]: ErrorCode.SESSION_BUSY,
[ErrorCodes.PROMPT_ID_CONFLICT]: ErrorCode.PROMPT_ID_CONFLICT,
[ErrorCodes.GOAL_ALREADY_EXISTS]: ErrorCode.GOAL_ALREADY_EXISTS,
[ErrorCodes.GOAL_NOT_FOUND]: ErrorCode.GOAL_NOT_FOUND,
[ErrorCodes.GOAL_STATUS_INVALID]: ErrorCode.GOAL_STATUS_INVALID,
[ErrorCodes.GOAL_NOT_RESUMABLE]: ErrorCode.GOAL_NOT_RESUMABLE,
[ErrorCodes.GOAL_OBJECTIVE_EMPTY]: ErrorCode.GOAL_OBJECTIVE_EMPTY,
[ErrorCodes.GOAL_OBJECTIVE_TOO_LONG]: ErrorCode.GOAL_OBJECTIVE_TOO_LONG,
[ErrorCodes.GOAL_UNSUPPORTED_AGENT]: ErrorCode.GOAL_UNSUPPORTED_AGENT,
[ErrorCodes.OS_FS_NOT_FOUND]: ErrorCode.FS_PATH_NOT_FOUND,
[ErrorCodes.OS_FS_NOT_DIRECTORY]: ErrorCode.FS_PATH_NOT_FOUND,
[ErrorCodes.OS_FS_IS_DIRECTORY]: ErrorCode.FS_IS_DIRECTORY,
[ErrorCodes.OS_FS_ALREADY_EXISTS]: ErrorCode.FS_ALREADY_EXISTS,
[ErrorCodes.OS_FS_PERMISSION_DENIED]: ErrorCode.FS_PERMISSION_DENIED,
[ErrorCodes.STORAGE_IO_FAILED]: ErrorCode.PERSISTENCE_FAILURE,
[ErrorCodes.STORAGE_LOCKED]: ErrorCode.PERSISTENCE_FAILURE,
};
export function mapError(err: unknown, requestId: string): ReturnType<typeof errEnvelope> {
if (err instanceof Error2) {
const code = KIMI_TO_PROTOCOL[err.code] ?? ErrorCode.INTERNAL_ERROR;
return errEnvelope(code, err.message, requestId, err.stack);
}
if (err instanceof TimeoutError) {
return errEnvelope(ErrorCode.INTERNAL_ERROR, err.message, requestId, err.stack);
}
return errEnvelope(
ErrorCode.INTERNAL_ERROR,
err instanceof Error ? err.message : String(err),
requestId,
err instanceof Error ? err.stack : undefined,
);
}
export function validationEnvelope(
details: { path: string; message: string }[],
requestId: string,
): {
code: number;
msg: string;
data: null;
request_id: string;
details: { path: string; message: string }[];
} {
const first = details[0];
const msg =
first === undefined
? 'validation failed'
: first.path === ''
? first.message
: `${first.path}: ${first.message}`;
return {
code: ErrorCode.VALIDATION_FAILED,
msg,
data: null,
request_id: requestId,
details,
};
}
export function assertSerializable(value: unknown): unknown {
if (value === undefined) return null;
try {
JSON.stringify(value);
} catch (error) {
throw new Error2(
ErrorCodes.INTERNAL,
`result not serializable: ${error instanceof Error ? error.message : String(error)}`,
);
}
return value;
}
|