@kangentic/protocol 0.5.0 → 0.6.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.
@@ -45,10 +45,19 @@ export type ActivityEventPayload = {
45
45
  } | {
46
46
  type: 'event';
47
47
  event: SessionEventWire;
48
- } | {
48
+ }
49
+ /**
50
+ * `options`, when present on a pending push, carries the prompt dialog's
51
+ * numbered option labels in keystroke order (options[0] is answered with
52
+ * "1\r"). Absent from pre-0.6.0 desktops and whenever no numbered dialog
53
+ * could be parsed from the PTY frame; the phone then falls back to its
54
+ * blind approve/deny keystrokes.
55
+ */
56
+ | {
49
57
  type: 'permission';
50
58
  promptId: string;
51
59
  pending: boolean;
60
+ options?: string[];
52
61
  }
53
62
  /**
54
63
  * The streamed session's PTY exited. Pushed once by the desktop's
package/dist/index.cjs CHANGED
@@ -5437,6 +5437,15 @@ function parseReadStreamResponsePayload(payload) {
5437
5437
  usage: payload.usage === null || payload.usage === void 0 ? null : parseSessionUsageWire(payload.usage),
5438
5438
  awaitedPromptId: payload.awaitedPromptId ?? null
5439
5439
  };
5440
+ if (payload.awaitedPromptOptions !== void 0) {
5441
+ if (payload.awaitedPromptOptions === null) {
5442
+ response.awaitedPromptOptions = null;
5443
+ } else if (Array.isArray(payload.awaitedPromptOptions) && payload.awaitedPromptOptions.every((option) => typeof option === "string")) {
5444
+ response.awaitedPromptOptions = payload.awaitedPromptOptions;
5445
+ } else {
5446
+ throw new Error('read-stream response has an invalid "awaitedPromptOptions"');
5447
+ }
5448
+ }
5440
5449
  if (payload.ptyDimensions !== void 0) {
5441
5450
  response.ptyDimensions = parseTerminalDimensionsWire(payload.ptyDimensions);
5442
5451
  }
@@ -5514,12 +5523,16 @@ function parseReadBoardResponsePayload(payload) {
5514
5523
  if (!Array.isArray(payload.columns)) throw new Error('read-board response is missing "columns"');
5515
5524
  if (!Array.isArray(payload.tasks)) throw new Error('read-board response is missing "tasks"');
5516
5525
  if (!Array.isArray(payload.backlog)) throw new Error('read-board response is missing "backlog"');
5526
+ if (payload.showTicketNumbers !== void 0 && typeof payload.showTicketNumbers !== "boolean") {
5527
+ throw new Error('read-board response has a non-boolean "showTicketNumbers"');
5528
+ }
5517
5529
  return {
5518
5530
  projectId: payload.projectId,
5519
5531
  columns: payload.columns.map((column) => parseBoardColumnWire(column)),
5520
5532
  tasks: payload.tasks.map((task) => parseBoardTaskWire(task)),
5521
5533
  backlog: payload.backlog.map((item) => parseBacklogItemWire(item)),
5522
- ...payload.projectColor !== void 0 ? { projectColor: parseAccentColor(payload.projectColor, "read-board snapshot") } : {}
5534
+ ...payload.projectColor !== void 0 ? { projectColor: parseAccentColor(payload.projectColor, "read-board snapshot") } : {},
5535
+ ...payload.showTicketNumbers !== void 0 ? { showTicketNumbers: payload.showTicketNumbers } : {}
5523
5536
  };
5524
5537
  }
5525
5538
  function parseReadBoardRequestPayload(payload) {
@@ -5895,7 +5908,13 @@ function parseActivityEventPayload(payload) {
5895
5908
  case "permission": {
5896
5909
  if (typeof payload.promptId !== "string") throw new Error('permission payload is missing "promptId"');
5897
5910
  if (typeof payload.pending !== "boolean") throw new Error('permission payload is missing "pending"');
5898
- return { type: "permission", promptId: payload.promptId, pending: payload.pending };
5911
+ if (payload.options === void 0) {
5912
+ return { type: "permission", promptId: payload.promptId, pending: payload.pending };
5913
+ }
5914
+ if (!Array.isArray(payload.options) || !payload.options.every((option) => typeof option === "string")) {
5915
+ throw new Error('permission payload has an invalid "options"');
5916
+ }
5917
+ return { type: "permission", promptId: payload.promptId, pending: payload.pending, options: payload.options };
5899
5918
  }
5900
5919
  case "session-ended": {
5901
5920
  if (typeof payload.intentional !== "boolean") throw new Error('session-ended payload is missing "intentional"');
package/dist/index.mjs CHANGED
@@ -5326,6 +5326,15 @@ function parseReadStreamResponsePayload(payload) {
5326
5326
  usage: payload.usage === null || payload.usage === void 0 ? null : parseSessionUsageWire(payload.usage),
5327
5327
  awaitedPromptId: payload.awaitedPromptId ?? null
5328
5328
  };
5329
+ if (payload.awaitedPromptOptions !== void 0) {
5330
+ if (payload.awaitedPromptOptions === null) {
5331
+ response.awaitedPromptOptions = null;
5332
+ } else if (Array.isArray(payload.awaitedPromptOptions) && payload.awaitedPromptOptions.every((option) => typeof option === "string")) {
5333
+ response.awaitedPromptOptions = payload.awaitedPromptOptions;
5334
+ } else {
5335
+ throw new Error('read-stream response has an invalid "awaitedPromptOptions"');
5336
+ }
5337
+ }
5329
5338
  if (payload.ptyDimensions !== void 0) {
5330
5339
  response.ptyDimensions = parseTerminalDimensionsWire(payload.ptyDimensions);
5331
5340
  }
@@ -5403,12 +5412,16 @@ function parseReadBoardResponsePayload(payload) {
5403
5412
  if (!Array.isArray(payload.columns)) throw new Error('read-board response is missing "columns"');
5404
5413
  if (!Array.isArray(payload.tasks)) throw new Error('read-board response is missing "tasks"');
5405
5414
  if (!Array.isArray(payload.backlog)) throw new Error('read-board response is missing "backlog"');
5415
+ if (payload.showTicketNumbers !== void 0 && typeof payload.showTicketNumbers !== "boolean") {
5416
+ throw new Error('read-board response has a non-boolean "showTicketNumbers"');
5417
+ }
5406
5418
  return {
5407
5419
  projectId: payload.projectId,
5408
5420
  columns: payload.columns.map((column) => parseBoardColumnWire(column)),
5409
5421
  tasks: payload.tasks.map((task) => parseBoardTaskWire(task)),
5410
5422
  backlog: payload.backlog.map((item) => parseBacklogItemWire(item)),
5411
- ...payload.projectColor !== void 0 ? { projectColor: parseAccentColor(payload.projectColor, "read-board snapshot") } : {}
5423
+ ...payload.projectColor !== void 0 ? { projectColor: parseAccentColor(payload.projectColor, "read-board snapshot") } : {},
5424
+ ...payload.showTicketNumbers !== void 0 ? { showTicketNumbers: payload.showTicketNumbers } : {}
5412
5425
  };
5413
5426
  }
5414
5427
  function parseReadBoardRequestPayload(payload) {
@@ -5784,7 +5797,13 @@ function parseActivityEventPayload(payload) {
5784
5797
  case "permission": {
5785
5798
  if (typeof payload.promptId !== "string") throw new Error('permission payload is missing "promptId"');
5786
5799
  if (typeof payload.pending !== "boolean") throw new Error('permission payload is missing "pending"');
5787
- return { type: "permission", promptId: payload.promptId, pending: payload.pending };
5800
+ if (payload.options === void 0) {
5801
+ return { type: "permission", promptId: payload.promptId, pending: payload.pending };
5802
+ }
5803
+ if (!Array.isArray(payload.options) || !payload.options.every((option) => typeof option === "string")) {
5804
+ throw new Error('permission payload has an invalid "options"');
5805
+ }
5806
+ return { type: "permission", promptId: payload.promptId, pending: payload.pending, options: payload.options };
5788
5807
  }
5789
5808
  case "session-ended": {
5790
5809
  if (typeof payload.intentional !== "boolean") throw new Error('session-ended payload is missing "intentional"');
@@ -48,6 +48,15 @@ export interface ReadStreamResponsePayload {
48
48
  usage: SessionUsageWire | null;
49
49
  /** The live outstanding permission-prompt id (see answer-permission-prompt), or null when none is pending. */
50
50
  awaitedPromptId: string | null;
51
+ /**
52
+ * The awaited prompt's numbered option labels, parsed by the desktop from
53
+ * the pending dialog's PTY frame, in keystroke order: options[0] is the
54
+ * row answered with "1\r", options[1] with "2\r", and so on. Absent from
55
+ * pre-0.6.0 desktops; absent or null means unknown (no numbered dialog
56
+ * could be parsed), and the phone falls back to its blind
57
+ * approve/deny keystrokes. Only meaningful while awaitedPromptId is set.
58
+ */
59
+ awaitedPromptOptions?: string[] | null;
51
60
  /**
52
61
  * The PTY grid the scrollback bytes are laid out for. Absent from
53
62
  * pre-0.4.0 desktops; the phone then falls back to inferring a width
@@ -103,6 +112,12 @@ export interface ReadBoardSnapshotResponsePayload {
103
112
  backlog: BacklogItemWire[];
104
113
  /** The project's accent color ("#rrggbb"); same semantics as ReadBoardProjectSummary.color. Absent from pre-0.5.0 desktops. */
105
114
  projectColor?: string;
115
+ /**
116
+ * The desktop's Layout "Ticket Numbers" setting: whether task cards
117
+ * display their #N number. Absent from pre-0.6.0 desktops (treat as
118
+ * true, the desktop default).
119
+ */
120
+ showTicketNumbers?: boolean;
106
121
  }
107
122
  export type ReadBoardResponsePayload = ReadBoardProjectListResponsePayload | ReadBoardSnapshotResponsePayload;
108
123
  /** Phone-side narrowing of a read-board response (project list or board snapshot). Throws on a malformed required field. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kangentic/protocol",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Kangentic mobile bridge wire protocol: framing, Noise-based pairing and session handshakes, signed device roster, and capability verbs shared between desktop and mobile.",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",