Files
Codewhale/crates/tui/extension-host/dist/protocol.mjs
T
CodeWhale BotandClaude Opus 5.5 4cf2d2cfff feat: integrate the verified 0.10.3 combined Engine batch [skip ci]
Lands the 0.10.3 program work that two Codex sessions left uncommitted on
canonical main (chats 01a176ff "Review latest MCP updates" / 01a176e0 "DSH
plugin compatibility"), on top of contributor PR #7086, which merged as itself (5c3d461d8a)
immediately before this commit. The pieces share compiler inputs
(the crate-split moves touch most of them), so they land as one verified
tree rather than as intermediate commits that would not build.

Contents:
- Crate split slices: `codewhale-net`, `codewhale-notify` and
  `codewhale-sandbox` crates; runtime config, config persistence, oauth,
  settings, catalog cache and Codex model roster moved from tui to runtime;
  hooks, extension host config and instruction budget to config; callers
  rewired, re-export facades removed (CW-6129).
- Follow-up repairs to #7086 instruction budgets (per-scope budgets,
  canonical source labels, `instruction_assembly` session snapshot).
- MCP: official SDK 2.4 host backend by default with `server/discover`
  and legacy fallback, metadata/output schema handling, OAuth issuer
  binding, Engine/CU server modernization (CW-6713, CW-7543, CW-7544,
  CW-7546).
- DSH plugin compatibility from the authorized exception lane `26ba80b06a`:
  shared compatibility table, native command lifecycle, reviewed imports,
  Native-only filesystem sandbox (CW-7054).
- Computer Use plugin-only cutover: vendored bundle removed, marketplace
  install from the independent release (CW-6732).
- Image-heavy sessions: 256 KiB read budget, outbound image omission with
  receipts, one smaller retry on HTTP 413 (CW-7550).
- Typed review operation (`core/engine/review.rs`, `runtime_api/review.rs`)
  used by Platform structured reviews.
- Receipt-owned Unix uninstall (Refs #7091).
- Steering (CW-7552) and Linux Shift+Enter (CW-7551, Refs #7093) source
  changes; runtime/manual proof still pending.

Fixes made during takeover verification:
- MCP: Rust now admits the legacy handshake whenever the SDK classifies the
  discovery probe as legacy (any JSON-RPC error, or a result without the
  modern supported version); before, servers answering the probe with a
  result were refused after it.
- MCP: an admitted legacy handshake reports initialize's own failure (e.g.
  401) instead of the probe's -32601.
- MCP: OAuth reactive refresh covers the side-effect-free probe.
- MCP: broker launch failures keep their diagnostic (missing command).
- Tool images must decode before delivery (truncated PNG was accepted).
- THIRD_PARTY_NOTICES lists MCP SDK 2.4.0 and DSH 0.2.1-rc.2 excerpts.
- Changelog entries for MCP, DSH, Computer Use and image validation.
- `#[cfg(test)]` on three test-only items; `cargo fmt --all`; tests updated
  to post-cutover behavior (no built-in CU, `$schema` manifests, canonical
  paths, lazy CU tools, SyncSession resets instruction assembly).

Verified on this exact tree (macOS, source sha 4353faf1 before changelog
edits; changelog/generated-doc edits only after):
- cargo check --workspace --all-targets --locked: exit 0, no warnings
- codewhale-config 806 passed; codewhale-runtime 850 passed;
  codewhale-net 52 passed; codewhale-notify 31 passed; codewhale-cli 501
  passed (nextest, 0 failed)
- codewhale-tui lib: 14515 passed, 0 failed, 21 skipped
- extension host npm test: 420 tests, 413 passed, 0 failed, 7 skipped
- web check-facts OK
Linux x86_64 (Boat VM, same source before the #7097 fold-in):
cargo check --workspace --all-targets --locked exit 0; codewhale-config
808, codewhale-runtime 849, codewhale-net 52, codewhale-notify 31,
codewhale-sandbox 100, codewhale-cli 501 passed, 0 failed. The tui lib
test binary was still compiling on the 16 GB VM at commit time.
#7097 (main) was three-way merged into approval_log.rs and clipboard.rs;
re-check after the fold-in: workspace check exit 0; tui approval_log,
clipboard, session_export, file_mention, pet_watch 213 passed.
Not run: hosted CI, clippy -D warnings, release packaging, live provider
or real MCP servers beyond local fixtures, Deepin run for #7093.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 23:28:43 -07:00

393 lines
17 KiB
JavaScript

// generated by crates/tui/extension-host/build.mjs from src/protocol.ts; do not edit.
// src/protocol.generated.ts
var PROTOCOL_VERSION = 1;
var MAGIC_ASCII = "CWX1";
var HEADER_LEN = 8;
var MAX_FRAME = 33554432;
var MAX_INFLIGHT = 256;
var ErrorCode = {
ParseError: -32700,
InvalidRequest: -32600,
MethodNotFound: -32601,
InvalidParams: -32602,
Internal: -32603,
ExecutionFailed: -32e3,
NotAvailable: -32001,
Refused: -32002,
Denied: -32003,
Cancelled: -32800
};
var METHODS = [
{ name: "host/initialize", direction: "core_to_host", request: true, params: "InitializeParams", tiers: ["plugin", "builtin"] },
{ name: "host/ping", direction: "core_to_host", request: true, params: "EmptyParams", tiers: ["plugin", "builtin"] },
{ name: "host/shutdown", direction: "core_to_host", request: true, params: "EmptyParams", tiers: ["plugin", "builtin"] },
{ name: "ext/activate", direction: "core_to_host", request: true, params: "ActivateParams", tiers: ["plugin", "builtin"] },
{ name: "ext/deactivate", direction: "core_to_host", request: true, params: "DeactivateParams", tiers: ["plugin", "builtin"] },
{ name: "tool/call", direction: "core_to_host", request: true, params: "ToolCallParams", tiers: ["plugin", "builtin"] },
{ name: "command/run", direction: "core_to_host", request: true, params: "CommandRunParams", tiers: ["plugin", "builtin"] },
{ name: "hook/evaluate", direction: "core_to_host", request: true, params: "HookEvaluateParams", tiers: ["plugin", "builtin"] },
{ name: "mcp/open", direction: "core_to_host", request: true, params: "McpOpenParams", tiers: ["builtin"] },
{ name: "mcp/request", direction: "core_to_host", request: true, params: "McpRequestParams", tiers: ["builtin"] },
{ name: "mcp/close", direction: "core_to_host", request: true, params: "McpCloseParams", tiers: ["builtin"] },
{ name: "harness/run", direction: "core_to_host", request: true, params: "HarnessRunParams", tiers: ["builtin"] },
{ name: "$/cancel", direction: "core_to_host", request: false, params: "CancelParams", tiers: ["plugin", "builtin"] },
{ name: "host/hello", direction: "host_to_core", request: false, params: "HelloParams", tiers: ["plugin", "builtin"] },
{ name: "host/ready", direction: "host_to_core", request: false, params: "EmptyParams", tiers: ["plugin", "builtin"] },
{ name: "registry/register", direction: "host_to_core", request: true, params: "RegisterParams", tiers: ["plugin", "builtin"] },
{ name: "registry/unregister", direction: "host_to_core", request: true, params: "UnregisterParams", tiers: ["plugin", "builtin"] },
{ name: "core/call", direction: "host_to_core", request: true, params: "CoreCallParams", tiers: ["plugin", "builtin"] },
{ name: "proc/launch", direction: "host_to_core", request: true, params: "ProcLaunchParams", tiers: ["builtin"] },
{ name: "proc/read", direction: "host_to_core", request: true, params: "ProcSessionParams", tiers: ["builtin"] },
{ name: "proc/write", direction: "host_to_core", request: true, params: "ProcWriteParams", tiers: ["builtin"] },
{ name: "proc/close", direction: "host_to_core", request: true, params: "ProcSessionParams", tiers: ["builtin"] },
{ name: "net/start", direction: "host_to_core", request: true, params: "ProcLaunchParams", tiers: ["builtin"] },
{ name: "net/fetch", direction: "host_to_core", request: true, params: "NetFetchParams", tiers: ["builtin"] },
{ name: "net/read", direction: "host_to_core", request: true, params: "NetReadParams", tiers: ["builtin"] },
{ name: "net/release", direction: "host_to_core", request: true, params: "NetReadParams", tiers: ["builtin"] },
{ name: "net/close", direction: "host_to_core", request: true, params: "ProcSessionParams", tiers: ["builtin"] },
{ name: "exec/redeem", direction: "host_to_core", request: true, params: "ExecutionRedeemParams", tiers: ["builtin"] },
{ name: "ext/faulted", direction: "host_to_core", request: false, params: "FaultedParams", tiers: ["plugin", "builtin"] },
{ name: "log", direction: "host_to_core", request: false, params: "LogParams", tiers: ["plugin", "builtin"] },
{ name: "$/cancel", direction: "host_to_core", request: false, params: "CancelParams", tiers: ["plugin", "builtin"] }
];
var SHAPES = {
ActivateParams: {
strict: false,
required: { owner: { ref: "OwnerRef" }, plugin_name: "string", entry: { ref: "EntryRef" } },
optional: { scope: { ref: "EntryRef" }, config: "json", data_dir: "string" }
},
CancelParams: {
strict: true,
required: { id: "uint" },
optional: {}
},
CommandRunParams: {
strict: false,
required: { handle: "uint", command_id: "string", raw_input: "string", deadline_ms: "uint" },
optional: { workspace: "string", session_id: "string", agent_id: "string", origin_turn_id: "string" }
},
CoreCallParams: {
strict: true,
required: { owner: { ref: "OwnerRef" }, ticket: "string", name: "string", input: "json" },
optional: {}
},
DeactivateParams: {
strict: false,
required: { owner: { ref: "OwnerRef" } },
optional: { entry: { ref: "EntryRef" } }
},
EmptyParams: {
strict: true,
required: {},
optional: {}
},
EntryRef: {
strict: false,
required: { path: "string", sha256: "string" },
optional: {}
},
ExecutionRedeemParams: {
strict: true,
required: { owner: { ref: "OwnerRef" }, execution_id: "string", ticket: "string" },
optional: {}
},
FaultedParams: {
strict: true,
required: { owner: { ref: "OwnerRef" }, error: "string" },
optional: {}
},
HarnessRunParams: {
strict: true,
required: { owner: { ref: "OwnerRef" }, execution_id: "string", ticket: "string", deadline_ms: "uint" },
optional: { hook: { ref: "HookDispatchWire" } }
},
HelloParams: {
strict: true,
required: { protocol: { ref: "ProtocolRange" }, host_version: "string", bundle_sha256: "string", runtime: { ref: "HelloRuntime" }, tier: { enum: ["builtin", "plugin"] }, builtin_modules: { items: { ref: "ModuleDigestWire" } } },
optional: { memory_limit_mib: "uint" }
},
HelloRuntime: {
strict: true,
required: { name: "string", version: "string" },
optional: {}
},
HookCallPayload: {
strict: true,
required: { name: "string", call_id: "string", input: "json", mode: "string", workspace: "string", model: "string" },
optional: {}
},
HookDispatchWire: {
strict: true,
required: { event: "string", dialect: "string", point: "string", query: "string" },
optional: { matcher: "string" }
},
HookEvaluateParams: {
strict: true,
required: { handle: "uint", event: "string", payload: { ref: "HookCallPayload" }, deadline_ms: "uint" },
optional: {}
},
HostLimits: {
strict: false,
required: { max_frame: "uint", max_inflight: "uint", dispose_deadline_ms: "uint", activate_deadline_ms: "uint" },
optional: {}
},
InitializeParams: {
strict: false,
required: { protocol: "uint", limits: { ref: "HostLimits" } },
optional: {}
},
LogParams: {
strict: true,
required: { level: "string", msg: "string" },
optional: { plugin_id: "string" }
},
McpCloseParams: {
strict: true,
required: { owner: { ref: "OwnerRef" }, session_id: "string", deadline_ms: "uint" },
optional: {}
},
McpHttpHeaders: {
strict: true,
required: {},
optional: { accept: "string", content_type: "string", mcp_session_id: "string", mcp_protocol_version: "string", mcp_method: "string", mcp_name: "string" }
},
McpOpenParams: {
strict: true,
required: { owner: { ref: "OwnerRef" }, session_id: "string", launch_ticket: "string", transport: "string", initialize_grant: { ref: "McpOperationGrant" }, initialized_grant: { ref: "McpOperationGrant" }, client_version: "string", deadline_ms: "uint" },
optional: { discover_grant: { ref: "McpOperationGrant" } }
},
McpOperationGrant: {
strict: true,
required: { ticket: "string", operation_id: "string", method: "string", params: "json" },
optional: { wire_id: "string" }
},
McpRequestParams: {
strict: true,
required: { owner: { ref: "OwnerRef" }, session_id: "string", grant: { ref: "McpOperationGrant" }, deadline_ms: "uint" },
optional: {}
},
ModuleDigestWire: {
strict: true,
required: { id: "string", sha256: "string" },
optional: {}
},
NetFetchParams: {
strict: true,
required: { owner: { ref: "OwnerRef" }, session_id: "string", url: "string", method: "string", headers: { ref: "McpHttpHeaders" } },
optional: { frame: "json", ticket: "string", operation_id: "string" }
},
NetReadParams: {
strict: true,
required: { owner: { ref: "OwnerRef" }, session_id: "string", response_id: "string" },
optional: {}
},
OwnerRef: {
strict: true,
required: { plugin_id: "string", generation: "uint", owner_token: "string" },
optional: {}
},
ProcLaunchParams: {
strict: true,
required: { owner: { ref: "OwnerRef" }, session_id: "string", ticket: "string" },
optional: {}
},
ProcSessionParams: {
strict: true,
required: { owner: { ref: "OwnerRef" }, session_id: "string" },
optional: {}
},
ProcWriteParams: {
strict: true,
required: { owner: { ref: "OwnerRef" }, session_id: "string", frame: "json" },
optional: { ticket: "string", operation_id: "string" }
},
ProtocolRange: {
strict: true,
required: { min: "uint", max: "uint" },
optional: {}
},
RegisterParams: {
strict: true,
required: { owner: { ref: "OwnerRef" }, kind: { enum: ["tool", "command", "hook", "prompt_section", "prompt_template", "skill_root", "avatar_pack", "shell_hook", "mcp_server"] }, spec: { ref: "RegisterSpecWire" } },
optional: { scope: { ref: "EntryRef" } }
},
RegisterSpecWire: {
strict: true,
required: { name: "string", description: "string" },
optional: { input_schema: "object", argument_hint: "string" }
},
RpcErrorWire: {
strict: true,
required: { code: "integer", message: "string" },
optional: { data: "json" }
},
ToolCallParams: {
strict: false,
required: { handle: "uint", call_id: "string", input: "json", deadline_ms: "uint" },
optional: { workspace: "string", ticket: "string", session_id: "string", agent_id: "string", origin_turn_id: "string" }
},
UnregisterParams: {
strict: true,
required: { owner: { ref: "OwnerRef" }, handle: "uint" },
optional: {}
}
};
// src/protocol.ts
var MAGIC = Buffer.from(MAGIC_ASCII, "ascii");
var FrameError = class extends Error {
constructor(message) {
super(message);
this.name = "FrameError";
}
};
var ProtocolError = class extends Error {
constructor(message) {
super(message);
this.name = "ProtocolError";
}
};
function encodeFrame(message) {
const payload = Buffer.from(JSON.stringify(message), "utf8");
if (payload.length > MAX_FRAME) {
throw new FrameError(`frame of ${payload.length} bytes exceeds MAX_FRAME ${MAX_FRAME}`);
}
const header = Buffer.alloc(HEADER_LEN);
MAGIC.copy(header, 0);
header.writeUInt32LE(payload.length, 4);
return Buffer.concat([header, payload]);
}
var FrameDecoder = class {
buffer = Buffer.alloc(0);
push(chunk) {
this.buffer = this.buffer.length === 0 ? chunk : Buffer.concat([this.buffer, chunk]);
const out = [];
while (this.buffer.length >= HEADER_LEN) {
if (!this.buffer.subarray(0, 4).equals(MAGIC)) {
throw new FrameError("bad frame magic");
}
const length = this.buffer.readUInt32LE(4);
if (length > MAX_FRAME) throw new FrameError(`frame length ${length} exceeds MAX_FRAME`);
if (this.buffer.length < HEADER_LEN + length) break;
const payload = this.buffer.subarray(HEADER_LEN, HEADER_LEN + length);
this.buffer = this.buffer.subarray(HEADER_LEN + length);
let value;
try {
value = JSON.parse(payload.toString("utf8"));
} catch (error) {
throw new FrameError(`frame payload is not JSON: ${error.message}`);
}
out.push(value);
}
return out;
}
};
function isObject(value) {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
function checkShape(where, value, shape) {
if (!isObject(value)) throw new ProtocolError(`${where}: expected an object`);
for (const [key, kind] of Object.entries(shape.required)) {
if (!(key in value)) throw new ProtocolError(`${where}: missing field \`${key}\``);
checkKind(`${where}.${key}`, value[key], kind);
}
for (const [key, kind] of Object.entries(shape.optional)) {
if (value[key] !== void 0 && value[key] !== null) checkKind(`${where}.${key}`, value[key], kind);
}
if (shape.strict) {
for (const key of Object.keys(value)) {
if (!(key in shape.required) && !(key in shape.optional)) {
throw new ProtocolError(`${where}: unknown field \`${key}\``);
}
}
}
}
function checkKind(where, value, kind) {
if (typeof kind === "object") {
if ("ref" in kind) return checkShape(where, value, SHAPES[kind.ref]);
if ("enum" in kind) {
if (typeof value !== "string" || !kind.enum.includes(value)) {
throw new ProtocolError(`${where}: expected one of ${kind.enum.map((v) => `\`${v}\``).join(", ")}`);
}
return;
}
if (!Array.isArray(value)) throw new ProtocolError(`${where}: expected an array`);
value.forEach((item, index) => checkKind(`${where}[${index}]`, item, kind.items));
return;
}
switch (kind) {
case "string":
if (typeof value !== "string") throw new ProtocolError(`${where}: expected a string`);
return;
case "uint":
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
throw new ProtocolError(`${where}: expected an unsigned integer`);
}
return;
case "integer":
if (typeof value !== "number" || !Number.isSafeInteger(value)) throw new ProtocolError(`${where}: expected an integer`);
return;
case "boolean":
if (typeof value !== "boolean") throw new ProtocolError(`${where}: expected a boolean`);
return;
case "object":
if (!isObject(value)) throw new ProtocolError(`${where}: expected an object`);
return;
case "json":
return;
}
}
function validateMessage(value, direction, tier, methods = METHODS) {
const strict = direction === "host_to_core";
if (!isObject(value)) throw new ProtocolError("message: expected an object");
if (value.jsonrpc !== "2.0") throw new ProtocolError('message: jsonrpc must be "2.0"');
const hasId = "id" in value;
if (hasId) checkKind("message.id", value.id, "uint");
if ("method" in value) {
checkShape("message", value, { strict, required: { jsonrpc: "string", method: "string" }, optional: { id: "uint", params: "json" } });
const method = value.method;
const spec = methods.find((entry) => entry.name === method && entry.direction === direction);
if (!spec) throw new ProtocolError(`unknown ${direction} method \`${method}\``);
if (!spec.tiers.includes(tier)) throw new ProtocolError(`\`${method}\` is not allowed on the ${tier} tier`);
if (spec.request !== hasId) {
throw new ProtocolError(`\`${method}\` must be ${spec.request ? "a request (with id)" : "a notification (no id)"}`);
}
const params = "params" in value ? value.params : {};
checkShape(method, params, SHAPES[spec.params]);
if (method === "host/hello" && params.runtime.name !== "bun" && params.runtime.name !== "node") {
throw new ProtocolError(`host/hello.runtime.name: unknown runtime \`${params.runtime.name}\``);
}
if (method === "registry/register") {
const { kind, spec: spec2 } = params;
const reason = kind === "tool" && spec2.input_schema == null ? "a tool registration needs `spec.input_schema`" : kind === "tool" && spec2.argument_hint != null ? "a tool registration has no `spec.argument_hint`" : kind === "command" && spec2.input_schema != null ? "a command registration has no `spec.input_schema`" : (kind === "hook" || kind === "prompt_section" || kind === "prompt_template" || kind === "skill_root" || kind === "avatar_pack" || kind === "shell_hook" || kind === "mcp_server") && (spec2.input_schema != null || spec2.argument_hint != null) ? "a hook, prompt or skill root registration has no input schema or argument hint" : void 0;
if (reason !== void 0) throw new ProtocolError(`${method}: ${reason}`);
}
return value;
}
if (!hasId) throw new ProtocolError("response: missing id");
if ("error" in value) {
checkShape("message", value, { strict, required: { jsonrpc: "string", id: "uint", error: { ref: "RpcErrorWire" } }, optional: {} });
return value;
}
if (!("result" in value)) throw new ProtocolError("response: needs result or error");
checkShape("message", value, { strict, required: { jsonrpc: "string", id: "uint", result: "json" }, optional: {} });
return value;
}
export {
ErrorCode,
FrameDecoder,
FrameError,
HEADER_LEN,
MAGIC,
MAGIC_ASCII,
MAX_FRAME,
MAX_INFLIGHT,
METHODS,
PROTOCOL_VERSION,
ProtocolError,
SHAPES,
encodeFrame,
validateMessage
};