@unbound-app/debugger-protocol 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,11 @@
1
- import { l as EvalResult, o as DeviceInfo, p as PluginPushResult } from "./index-Ctl4b3sx.mjs";
2
- import { AddonManifest } from "@unbound-app/types";
1
+ import { l as EvalResult, o as DeviceInfo, p as PluginPushResult } from "./index-CDo0GkFG.mjs";
2
+ import { PushedManifest } from "@unbound-app/types";
3
3
  type PluginPush = {
4
4
  addonId: string;
5
5
  bundle: string;
6
- manifest: AddonManifest;
6
+ manifest: PushedManifest;
7
7
  bytecode?: Record<string, string>;
8
+ files?: Record<string, string>;
8
9
  };
9
10
  export declare class ControllerClient {
10
11
  private ws;
@@ -1,4 +1,4 @@
1
- import { AddonManifest } from "@unbound-app/types";
1
+ import { PushedManifest } from "@unbound-app/types";
2
2
  /**
3
3
  * The wire protocol shared by the bridge, the device and controllers: every frame is a JSON-encoded
4
4
  * {@link BridgeMessage}. Dependency-free at runtime so the React Native client can bundle it.
@@ -16,17 +16,20 @@ type EvalResult = {
16
16
  type: 'eval-result';
17
17
  /** The `id` of the {@link EvalRequest} this answers. */
18
18
  id: string;
19
- ok: boolean;
20
- /** Present when `ok`; the inspected return value. */
21
- value?: string;
22
- /** Present when `!ok`; the inspected error. */
23
- error?: string;
24
19
  /**
25
20
  * Console output captured during this eval, so callers see its side effects too. Populated by
26
21
  * the controller that owns the request, not sent by the device.
27
22
  */
28
23
  logs?: LogMessage[];
29
- };
24
+ } & ({
25
+ ok: true;
26
+ /** The inspected return value. */
27
+ value: string;
28
+ } | {
29
+ ok: false;
30
+ /** The inspected error. */
31
+ error: string;
32
+ });
30
33
  /**
31
34
  * A request to hot-reload a plugin on the device, sent controller → bridge → device. Carries the
32
35
  * freshly built bundle and manifest so the device swaps them in without a re-fetch.
@@ -37,19 +40,25 @@ type PluginPushRequest = {
37
40
  id: string;
38
41
  addonId: string;
39
42
  bundle: string;
40
- manifest: AddonManifest;
43
+ /** The manifest as authored; the device validates it before swapping anything in. */
44
+ manifest: PushedManifest;
41
45
  /** The bundle compiled to Hermes bytecode, base64-encoded, by bytecode version; its digests are in `manifest.bytecode`. */
42
46
  bytecode?: Record<string, string>;
47
+ /** Each extra file the manifest lists beside the bundle, such as an image, base64-encoded, by path. */
48
+ files?: Record<string, string>;
43
49
  };
44
50
  /** The outcome of a {@link PluginPushRequest}, sent device → bridge → the one waiting controller. */
45
51
  type PluginPushResult = {
46
52
  type: 'plugin-push-result';
47
53
  /** The `id` of the {@link PluginPushRequest} this answers. */
48
54
  id: string;
49
- ok: boolean;
50
- /** Present when `!ok`; the reload failure, inspected. */
51
- error?: string;
52
- };
55
+ } & ({
56
+ ok: true;
57
+ } | {
58
+ ok: false;
59
+ /** The reload failure, inspected. */
60
+ error: string;
61
+ });
53
62
  /** A `console.*` / `nativeLoggingHook` line, streamed device → bridge → all controllers. */
54
63
  type LogMessage = {
55
64
  type: 'log';
@@ -72,10 +81,13 @@ type DeviceHello = {
72
81
  /** Bridge → controller, once on attach and whenever the device connects, drops or says hello. */
73
82
  type DeviceStatus = {
74
83
  type: 'device-status';
75
- connected: boolean;
84
+ } & ({
85
+ connected: false;
86
+ } | {
87
+ connected: true;
76
88
  /** Present once the connected device has said hello. */
77
89
  device?: DeviceInfo;
78
- };
90
+ });
79
91
  /** Every framed message on the wire. */
80
92
  type BridgeMessage = EvalRequest | EvalResult | PluginPushRequest | PluginPushResult | LogMessage | DeviceHello | DeviceStatus;
81
93
  /** The default port the bridge listens on and controllers dial. */
package/dist/index.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as DeviceHello, c as EvalRequest, d as MAX_EVAL_TIMEOUT_MS, f as PluginPushRequest, g as serializeMessage, h as parseMessage, i as DEFAULT_EVAL_TIMEOUT_MS, l as EvalResult, m as _default, n as CONTROLLER_ENDPOINT_MARKER, o as DeviceInfo, p as PluginPushResult, r as DEFAULT_BRIDGE_PORT, s as DeviceStatus, t as BridgeMessage, u as LogMessage } from "./index-Ctl4b3sx.mjs";
1
+ import { a as DeviceHello, c as EvalRequest, d as MAX_EVAL_TIMEOUT_MS, f as PluginPushRequest, g as serializeMessage, h as parseMessage, i as DEFAULT_EVAL_TIMEOUT_MS, l as EvalResult, m as _default, n as CONTROLLER_ENDPOINT_MARKER, o as DeviceInfo, p as PluginPushResult, r as DEFAULT_BRIDGE_PORT, s as DeviceStatus, t as BridgeMessage, u as LogMessage } from "./index-CDo0GkFG.mjs";
2
2
  export { BridgeMessage, CONTROLLER_ENDPOINT_MARKER, DEFAULT_BRIDGE_PORT, DEFAULT_EVAL_TIMEOUT_MS, DeviceHello, DeviceInfo, DeviceStatus, EvalRequest, EvalResult, LogMessage, MAX_EVAL_TIMEOUT_MS, PluginPushRequest, PluginPushResult, _default as default, parseMessage, serializeMessage };
package/dist/index.mjs CHANGED
@@ -34,14 +34,17 @@ function hasRequiredFields(frame) {
34
34
  switch (frame.type) {
35
35
  case "log": return "message" in frame && typeof frame.message === "string" && "level" in frame && (frame.level === 1 || frame.level === 2 || frame.level === 3);
36
36
  case "eval": return "id" in frame && typeof frame.id === "string" && "code" in frame && typeof frame.code === "string";
37
- case "eval-result":
38
- case "plugin-push-result": return "id" in frame && typeof frame.id === "string" && "ok" in frame && typeof frame.ok === "boolean";
39
- case "plugin-push": return "id" in frame && typeof frame.id === "string" && "addonId" in frame && typeof frame.addonId === "string" && "bundle" in frame && typeof frame.bundle === "string" && "manifest" in frame && typeof frame.manifest === "object" && frame.manifest !== null && (!("bytecode" in frame) || frame.bytecode === void 0 || isStringRecord(frame.bytecode));
37
+ case "eval-result": return "id" in frame && typeof frame.id === "string" && "ok" in frame && (frame.ok === true ? "value" in frame && typeof frame.value === "string" : frame.ok === false && hasError(frame));
38
+ case "plugin-push-result": return "id" in frame && typeof frame.id === "string" && "ok" in frame && (frame.ok === true || frame.ok === false && hasError(frame));
39
+ case "plugin-push": return "id" in frame && typeof frame.id === "string" && "addonId" in frame && typeof frame.addonId === "string" && "bundle" in frame && typeof frame.bundle === "string" && "manifest" in frame && typeof frame.manifest === "object" && frame.manifest !== null && (!("bytecode" in frame) || frame.bytecode === void 0 || isStringRecord(frame.bytecode)) && (!("files" in frame) || frame.files === void 0 || isStringRecord(frame.files));
40
40
  case "hello": return "device" in frame && isDeviceInfo(frame.device);
41
- case "device-status": return "connected" in frame && typeof frame.connected === "boolean" && (!("device" in frame) || frame.device === void 0 || isDeviceInfo(frame.device));
41
+ case "device-status": return "connected" in frame && (frame.connected === false || frame.connected === true && (!("device" in frame) || frame.device === void 0 || isDeviceInfo(frame.device)));
42
42
  default: return false;
43
43
  }
44
44
  }
45
+ function hasError(frame) {
46
+ return typeof frame === "object" && frame !== null && "error" in frame && typeof frame.error === "string";
47
+ }
45
48
  function isDeviceInfo(value) {
46
49
  return typeof value === "object" && value !== null && "platform" in value && typeof value.platform === "string" && "discordVersion" in value && typeof value.discordVersion === "string" && "loaderVersion" in value && typeof value.loaderVersion === "string" && "clientVersion" in value && typeof value.clientVersion === "string";
47
50
  }
@@ -1,5 +1,5 @@
1
1
  import { ControllerClient } from "./controller.mjs";
2
- import { z } from "zod";
2
+ import { StaticDecode, TObject } from "typebox";
3
3
  /**
4
4
  * One command definition feeds both surfaces: the CLI builds flags and positionals from its schema,
5
5
  * and the MCP server uses the schema as the tool's input schema.
@@ -26,15 +26,17 @@ export type CommandSurfaces = {
26
26
  mcp: true;
27
27
  };
28
28
  /** A command usable from both the CLI and (when opted in) the MCP server. */
29
- export type CommandDefinition<S extends z.ZodObject<z.ZodRawShape>> = {
29
+ export type CommandDefinition<S extends TObject = TObject> = {
30
30
  name: string;
31
31
  description: string;
32
+ /** A one-line summary for the CLI's menu, where the description is too long. */
33
+ summary?: string;
32
34
  surfaces: CommandSurfaces;
33
- /** Used directly as the MCP inputSchema; the CLI adapter derives flags from its fields. */
35
+ /** Used directly as the MCP tool's input schema; the CLI adapter derives flags from its properties. */
34
36
  schema: S;
35
- /** Which schema fields the CLI presents as positionals; the rest become flags. */
37
+ /** Which schema properties the CLI presents as positionals; the rest become flags. */
36
38
  cli?: {
37
- positionals?: (keyof z.infer<S>)[];
39
+ positionals?: (keyof StaticDecode<S>)[];
38
40
  };
39
- handler: (input: z.infer<S>, context: CommandContext) => Promise<CommandOutput>;
41
+ handler(input: StaticDecode<S>, context: CommandContext): Promise<CommandOutput>;
40
42
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unbound-app/debugger-protocol",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "The wire protocol and controller client shared by the debugger bridge, the on-device client, and the CLI.",
5
5
  "author": {
6
6
  "name": "Mario P.",
@@ -32,12 +32,13 @@
32
32
  }
33
33
  },
34
34
  "scripts": {
35
- "build": "tsdown"
35
+ "build": "tsdown",
36
+ "typecheck": "tsc --noEmit -p ."
36
37
  },
37
38
  "dependencies": {
38
- "zod": "^4.0.0"
39
+ "typebox": "^1.4.4"
39
40
  },
40
41
  "peerDependencies": {
41
- "typescript": "^5.9.3"
42
+ "typescript": "^7.0.2"
42
43
  }
43
44
  }