/** 所有 frame 共享字段 */ export interface JsonRpcBase { jsonrpc: '2.0'; /** ULID 或 UUID。每条 request 全局唯一。response 回传同一 id */ id: string; } /** Brain → Agent 请求 / Agent → Brain 心跳等主动消息 */ export interface JsonRpcRequest extends JsonRpcBase { method: M; params: P; /** DELTA §5.4: HMAC-SHA256(id || method || JSON.stringify(params), SKILLFM_SKILL_AUTH_SECRET) */ meta?: { hmac: string; }; } export interface JsonRpcSuccessResponse extends JsonRpcBase { result: R; meta?: { hmac: string; }; } export interface JsonRpcErrorResponse extends JsonRpcBase { error: JsonRpcError; meta?: { hmac: string; }; } export type JsonRpcResponse = JsonRpcSuccessResponse | JsonRpcErrorResponse; export type JsonRpcFrame = JsonRpcRequest | JsonRpcResponse; /** JSON-RPC 2.0 错误结构 */ export interface JsonRpcError { code: number; message: string; data?: { /** 应用层 skill 错误码(映射到 brain 侧 §3.0 错误表) */ skill_error_code?: string; retryable?: boolean; skill_meta?: SkillMetaContract; [k: string]: unknown; }; } export declare const TUNNEL_ERROR_CODES: { /** JSON-RPC 2.0 standard */ readonly INVALID_REQUEST: -32600; readonly METHOD_NOT_FOUND: -32601; readonly INVALID_PARAMS: -32602; readonly INTERNAL_ERROR: -32603; /** 应用层: skill 业务错误(agent 本地 skill 抛出的已知业务错)*/ readonly SKILL_APP_ERROR: -32000; /** Tunnel 层: agent 本地 skill daemon 不可达(brain 已连到 agent,但 agent→127.0.0.1:78xx 失败)*/ readonly TUNNEL_DEGRADED: -32100; }; export type TunnelErrorCode = (typeof TUNNEL_ERROR_CODES)[keyof typeof TUNNEL_ERROR_CODES]; /** * Brain → Agent(brain 主调,agent 被调) * 对齐 BRAIN-SKILL-CONTRACT §3 的 5 接口 + abort + health */ export type SkillTunnelServerMethod = 'skill.run' | 'skill.contribute_ctx' | 'skill.declare_must_relay' | 'skill.manifest' | 'skill.tool.invoke' | 'skill.continuation.abort' | 'skill.health'; /** Agent → Brain(agent 主调,保留给 heartbeat / 状态上报)*/ export type SkillTunnelClientMethod = 'tunnel.heartbeat' | 'tunnel.skill_update' | 'tunnel.log'; export type SkillTunnelMethod = SkillTunnelServerMethod | SkillTunnelClientMethod; /** WebSocket 子协议 ID —— 两端必须匹配 */ export declare const TUNNEL_SUBPROTOCOL: "skillfm.skill-tunnel.v1"; /** agent → brain: handshake 阶段携带的 headers(除 WS 标准头外的 SkillFM 私有头)*/ export interface TunnelHandshakeHeaders { /** 长期 agent_token(同 BRAIN §3 auth) */ 'x-agent-token': string; /** SHA-256(agent_token) 的 hex,避免 token 原文多处出现 */ 'x-agent-id': string; /** 逗号分隔 `slug@version`,告诉 brain 本节点起了哪些 skill daemon */ 'x-local-skills': string; /** 逗号分隔 `slug=http://127.0.0.1:`,本地 skill server 的 loopback URL */ 'x-local-skill-endpoints': string; /** 16 byte 随机 hex(5 分钟滑窗防重放)*/ 'x-tunnel-nonce': string; /** HMAC-SHA256(agent_token || nonce, SKILLFM_SKILL_AUTH_SECRET) */ 'x-tunnel-signature': string; /** @skillfm/local 运行时版本,brain 可拒绝过低版本 */ 'x-skillfm-local-version': string; } /** Handshake 失败时 brain 返回 HTTP 响应 body */ export interface TunnelHandshakeRejectBody { ok: false; error: 'TUNNEL.AUTH.BAD_SIGNATURE' | 'TUNNEL.AUTH.AGENT_TOKEN_REVOKED' | 'TUNNEL.AUTH.NONCE_REUSED' | 'TUNNEL.CONN.ALREADY_CONNECTED' | 'TUNNEL.VERSION.UNSUPPORTED'; message: string; /** 仅 VERSION.UNSUPPORTED 时返回 */ min_local_version?: string; } /** params for `skill.run` —— 封装现有 SkillRunRequest(见 platform/api types)*/ export interface SkillRunTunnelParams { skill_slug: string; /** 完整 SkillRunRequest(§3.1),由 brain 侧 SkillRpcClient 序列化透传。 * 本契约不重复列字段,避免 double-source-of-truth;unknown 是有意的 —— platform/api 内部 * 有详细 SkillRunRequest type,客户端透传时不需要知道每个字段。*/ request: unknown; } /** result for `skill.run` */ export interface SkillRunTunnelResult { /** SkillRunResult 或 SkillRunLlmTasks union(§3.1 v0.1.1)*/ data: unknown; skill_meta: SkillMetaContract; } export interface SkillMetaContract { skill_slug: string; skill_version: string; processing_ms: number; } /** params for `skill.tool.invoke` */ export interface SkillToolInvokeTunnelParams { skill_slug: string; tool_name: string; args: Record; /** §3.5 私有工具调用上下文(部分 SkillRunContext 字段)*/ context: unknown; request_id: string; } /** params for `tunnel.heartbeat`(agent → brain)*/ export interface HeartbeatTunnelParams { /** 本地 Unix ms 时间戳 */ ts: number; /** 本地 skill daemon 状态快照 —— 每个 slug 的 pid + 内存 + 上次 health check */ local_skill_status: Record; } export interface HeartbeatTunnelResult { /** brain 侧 Unix ms 时间戳,用于 agent 校准时钟 */ server_ts: number; } /** params for `tunnel.skill_update`(agent → brain,skill daemon 生命周期事件)*/ export interface SkillUpdateTunnelParams { event: 'started' | 'stopped' | 'upgraded' | 'crashed'; skill_slug: string; skill_version: string; /** stopped / crashed 时填 */ endpoint: string | null; occurred_at: number; } /** close code 4xxx 段 —— 应用层定义,agent 据此决定是否重连 */ export declare const TUNNEL_CLOSE_CODES: { /** 心跳超时,agent 应重连 */ readonly HEARTBEAT_TIMEOUT: 4000; /** 认证签名失败,agent 不应重连 */ readonly AUTH_BAD_SIGNATURE: 4001; /** nonce 重用检测,agent 不应重连 */ readonly AUTH_NONCE_REUSED: 4002; /** agent_token 已吊销,agent 不应重连 */ readonly AGENT_TOKEN_REVOKED: 4003; /** 协议版本不兼容,agent 应升级 @skillfm/local */ readonly VERSION_UNSUPPORTED: 4101; }; export type TunnelCloseCode = (typeof TUNNEL_CLOSE_CODES)[keyof typeof TUNNEL_CLOSE_CODES]; export declare const TUNNEL_CONSTANTS: { /** Heartbeat 发送周期(agent 侧)*/ readonly HEARTBEAT_INTERVAL_MS: 25000; /** Heartbeat 超时(brain 或 agent 侧任一未在此时间内收到对方 → 断线)*/ readonly HEARTBEAT_TIMEOUT_MS: 60000; /** handshake nonce 滑动窗口(brain 侧 Redis sorted set TTL)*/ readonly HANDSHAKE_NONCE_WINDOW_MS: 300000; /** nonce 轮转周期(agent 主动 refresh_nonce)*/ readonly NONCE_ROTATION_MS: 600000; /** Reconnect 指数退避上限 */ readonly RECONNECT_MAX_DELAY_MS: 30000; /** Reconnect 初始延迟 */ readonly RECONNECT_INITIAL_DELAY_MS: 1000; /** JSON-RPC request timeout(< WS keepalive,Q8 决议)*/ readonly RPC_REQUEST_TIMEOUT_MS: 90000; }; //# sourceMappingURL=skill-tunnel.d.ts.map