@kangentic/protocol 0.12.0 → 0.13.1
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.
- package/dist/events/payloads.d.ts +75 -1
- package/dist/index.cjs +25 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +22 -1
- package/package.json +1 -1
|
@@ -217,17 +217,79 @@ export interface SessionEventWire {
|
|
|
217
217
|
toolId?: string;
|
|
218
218
|
detail?: string;
|
|
219
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* The system column roles, mirroring the desktop's `SWIMLANE_ROLES` /
|
|
222
|
+
* `SwimlaneRole` (`src/shared/types.ts`). This package cannot import that
|
|
223
|
+
* file (see the module doc), so the two lists are a deliberate mirror, kept
|
|
224
|
+
* in sync by `tests/unit/protocol/board-column-role-parity.test.ts` on the
|
|
225
|
+
* desktop side rather than by a shared import.
|
|
226
|
+
*/
|
|
227
|
+
export declare const BOARD_COLUMN_ROLES: readonly ["todo", "done"];
|
|
228
|
+
export type BoardColumnRoleWire = (typeof BOARD_COLUMN_ROLES)[number];
|
|
229
|
+
/** True for a column whose role is the system 'todo' role. Prefer this at a call site over a literal `=== 'todo'`, which the `(string & {})` widening leaves unchecked. */
|
|
230
|
+
export declare function isTodoRole(role: string | null | undefined): boolean;
|
|
231
|
+
/** True for a column whose role is the system 'done' role. Prefer this at a call site over a literal `=== 'done'`, which the `(string & {})` widening leaves unchecked. */
|
|
232
|
+
export declare function isDoneRole(role: string | null | undefined): boolean;
|
|
220
233
|
/** Phone-needed subset of the desktop's Swimlane row (snake_case preserved so the desktop mapper is a mechanical pick). */
|
|
221
234
|
export interface BoardColumnWire {
|
|
222
235
|
id: string;
|
|
223
236
|
name: string;
|
|
224
237
|
description: string | null;
|
|
225
|
-
|
|
238
|
+
/**
|
|
239
|
+
* `'todo'` / `'done'` are the system roles; anything else (including a
|
|
240
|
+
* future role this package predates) is a custom or not-yet-known column,
|
|
241
|
+
* which is exactly what the `(string & {})` escape hatch preserves - the
|
|
242
|
+
* literal union alone would reject a value a newer desktop legitimately
|
|
243
|
+
* sends. That widening does NOT make a typo'd comparison a compile error
|
|
244
|
+
* (a string literal is assignable to `string & {}`), so call sites should
|
|
245
|
+
* use `isTodoRole` / `isDoneRole` rather than `=== 'todo'` / `=== 'done'`.
|
|
246
|
+
*/
|
|
247
|
+
role: BoardColumnRoleWire | (string & {}) | null;
|
|
226
248
|
position: number;
|
|
227
249
|
color: string;
|
|
228
250
|
icon: string | null;
|
|
229
251
|
is_archived: boolean;
|
|
230
252
|
is_ghost: boolean;
|
|
253
|
+
/**
|
|
254
|
+
* Whether moving a task into this column spawns a successor agent
|
|
255
|
+
* session, derived desktop-side from the column's `auto_spawn` flag and
|
|
256
|
+
* role. This is INTENT, not a guarantee:
|
|
257
|
+
*
|
|
258
|
+
* - `false` - this column does not intend to spawn. Reliable enough to act
|
|
259
|
+
* on ONLY when the column's own `role` is 'todo' or 'done': those two
|
|
260
|
+
* produce a full reset or an archive, and a Board Profile cannot change a
|
|
261
|
+
* column's role, so a client MAY skip a session-swap transition entirely
|
|
262
|
+
* for them. `role` rides this same object, so
|
|
263
|
+
* `isTodoRole(column.role) || isDoneRole(column.role)` is how a client
|
|
264
|
+
* recognizes that case. A `false` that came from `auto_spawn: false` on
|
|
265
|
+
* any other column is intent only, exactly like `true`: a Board Profile
|
|
266
|
+
* can set `autoSpawn: true` for one task on that column, and the move
|
|
267
|
+
* then does spawn.
|
|
268
|
+
* - `true` - this column intends to spawn, but a handful of desktop-side
|
|
269
|
+
* conditions can suspend the old session without a successor actually
|
|
270
|
+
* landing (a board profile disabling auto_spawn for this task, a failed
|
|
271
|
+
* worktree checkout that reverts the move, a shutdown or a newer move
|
|
272
|
+
* racing this one). A client MUST NOT treat `true` as a promise; keep
|
|
273
|
+
* whatever timeout already bounds a session-swap wait and let `true`
|
|
274
|
+
* only skip a redundant one.
|
|
275
|
+
* - `null` / absent - a desktop that predates this field. A client falls
|
|
276
|
+
* back to its pre-existing behavior, the same way an absent
|
|
277
|
+
* `pr_merge_readiness` reads as "never judged".
|
|
278
|
+
*
|
|
279
|
+
* Declared OPTIONAL (`?`) so a hand-built `BoardColumnWire` literal does
|
|
280
|
+
* not have to list it. `parseBoardColumnWire` populates the key from every
|
|
281
|
+
* real wire response regardless, so the optionality costs nothing at
|
|
282
|
+
* runtime.
|
|
283
|
+
*
|
|
284
|
+
* Ordering precondition this field depends on: the phone must learn a
|
|
285
|
+
* MOVE's destination column before the old session's `session-ended`
|
|
286
|
+
* arrives, or it cannot resolve `spawns_session` against the right column.
|
|
287
|
+
* That holds today because `handleTaskMove` emits its board-changed event
|
|
288
|
+
* at the commit point rather than at settle time. See the comment above
|
|
289
|
+
* `emitBoardChanged()` in `src/main/ipc/handlers/task-move.ts`, and
|
|
290
|
+
* `docs/mobile-bridge.md`.
|
|
291
|
+
*/
|
|
292
|
+
spawns_session?: boolean | null;
|
|
231
293
|
}
|
|
232
294
|
/** Phone-needed subset of the desktop's Task row. A non-null `session_id` is the live-session signal the phone's triage view keys on. */
|
|
233
295
|
export interface BoardTaskWire {
|
|
@@ -244,6 +306,18 @@ export interface BoardTaskWire {
|
|
|
244
306
|
pr_number: number | null;
|
|
245
307
|
pr_url: string | null;
|
|
246
308
|
pr_state: string | null;
|
|
309
|
+
/**
|
|
310
|
+
* Normalized merge readiness of the linked PR: `ready` / `blocked` /
|
|
311
|
+
* `conflicting` / `queued` / `running` / `unknown`, or null when never
|
|
312
|
+
* judged. `queued` and `running` mean a blocking check is still in flight.
|
|
313
|
+
* Absent from desktops that predate it, which the parser reads as null; a
|
|
314
|
+
* value a client does not know should render as plain open.
|
|
315
|
+
*
|
|
316
|
+
* Declared OPTIONAL (`?`) so a hand-built `BoardTaskWire` literal does not
|
|
317
|
+
* have to list it. `parseBoardTaskWire` populates the key from every real
|
|
318
|
+
* wire response regardless, so the optionality costs nothing at runtime.
|
|
319
|
+
*/
|
|
320
|
+
pr_merge_readiness?: string | null;
|
|
247
321
|
base_branch: string | null;
|
|
248
322
|
labels: string[];
|
|
249
323
|
priority: number;
|
package/dist/index.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod2) => __copyProps(__defProp({}, "__esModule", { value: tr
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
BOARD_COLUMN_ROLES: () => BOARD_COLUMN_ROLES,
|
|
23
24
|
BOARD_TOOL_READ_NAMES: () => BOARD_TOOL_READ_NAMES,
|
|
24
25
|
BOARD_TOOL_WRITE_NAMES: () => BOARD_TOOL_WRITE_NAMES,
|
|
25
26
|
CAPABILITY_VERBS: () => CAPABILITY_VERBS,
|
|
@@ -69,11 +70,13 @@ __export(index_exports, {
|
|
|
69
70
|
isBoardToolWriteName: () => isBoardToolWriteName,
|
|
70
71
|
isBridgeEvent: () => isBridgeEvent,
|
|
71
72
|
isCapabilityVerb: () => isCapabilityVerb,
|
|
73
|
+
isDoneRole: () => isDoneRole,
|
|
72
74
|
isJsonValue: () => isJsonValue,
|
|
73
75
|
isPushCategory: () => isPushCategory,
|
|
74
76
|
isRecord: () => isRecord,
|
|
75
77
|
isRosterEntryExpired: () => isRosterEntryExpired,
|
|
76
78
|
isSecureRelayAddress: () => isSecureRelayAddress,
|
|
79
|
+
isTodoRole: () => isTodoRole,
|
|
77
80
|
openPairingConfirm: () => openPairingConfirm,
|
|
78
81
|
openPushEnvelope: () => openPushEnvelope,
|
|
79
82
|
parseActivityEventPayload: () => parseActivityEventPayload,
|
|
@@ -5249,6 +5252,15 @@ function openPushEnvelope(pushKey, recipientStaticPublicKey, blob) {
|
|
|
5249
5252
|
}
|
|
5250
5253
|
|
|
5251
5254
|
// src/events/payloads.ts
|
|
5255
|
+
var BOARD_COLUMN_ROLES = ["todo", "done"];
|
|
5256
|
+
var TODO_ROLE = "todo";
|
|
5257
|
+
var DONE_ROLE = "done";
|
|
5258
|
+
function isTodoRole(role) {
|
|
5259
|
+
return role === TODO_ROLE;
|
|
5260
|
+
}
|
|
5261
|
+
function isDoneRole(role) {
|
|
5262
|
+
return role === DONE_ROLE;
|
|
5263
|
+
}
|
|
5252
5264
|
var DIFF_FILE_STATUSES = ["A", "M", "D", "R", "C", "U"];
|
|
5253
5265
|
var TRANSCRIPT_SYSTEM_SUBTYPES = ["compaction", "command", "command_output", "session_boundary"];
|
|
5254
5266
|
function requireString(record, field, context) {
|
|
@@ -5415,18 +5427,26 @@ function nullableNumber(record, field) {
|
|
|
5415
5427
|
const value = record[field];
|
|
5416
5428
|
return typeof value === "number" ? value : null;
|
|
5417
5429
|
}
|
|
5430
|
+
function nullableBoolean(record, field) {
|
|
5431
|
+
const value = record[field];
|
|
5432
|
+
return typeof value === "boolean" ? value : null;
|
|
5433
|
+
}
|
|
5418
5434
|
function parseBoardColumnWire(value) {
|
|
5419
5435
|
if (!isRecord(value)) throw new Error("board column must be an object");
|
|
5420
5436
|
return {
|
|
5421
5437
|
id: requireString(value, "id", "board column"),
|
|
5422
5438
|
name: requireString(value, "name", "board column"),
|
|
5423
5439
|
description: nullableString(value, "description"),
|
|
5440
|
+
// An unrecognized role passes through rather than throwing: it is a
|
|
5441
|
+
// custom column (or a future system role this package predates), not a
|
|
5442
|
+
// malformed payload. See the BoardColumnRoleWire doc comment.
|
|
5424
5443
|
role: nullableString(value, "role"),
|
|
5425
5444
|
position: requireNumber(value, "position", "board column"),
|
|
5426
5445
|
color: requireString(value, "color", "board column"),
|
|
5427
5446
|
icon: nullableString(value, "icon"),
|
|
5428
5447
|
is_archived: requireBoolean(value, "is_archived", "board column"),
|
|
5429
|
-
is_ghost: requireBoolean(value, "is_ghost", "board column")
|
|
5448
|
+
is_ghost: requireBoolean(value, "is_ghost", "board column"),
|
|
5449
|
+
spawns_session: nullableBoolean(value, "spawns_session")
|
|
5430
5450
|
};
|
|
5431
5451
|
}
|
|
5432
5452
|
function parseBoardTaskWire(value) {
|
|
@@ -5445,6 +5465,7 @@ function parseBoardTaskWire(value) {
|
|
|
5445
5465
|
pr_number: nullableNumber(value, "pr_number"),
|
|
5446
5466
|
pr_url: nullableString(value, "pr_url"),
|
|
5447
5467
|
pr_state: nullableString(value, "pr_state"),
|
|
5468
|
+
pr_merge_readiness: nullableString(value, "pr_merge_readiness"),
|
|
5448
5469
|
base_branch: nullableString(value, "base_branch"),
|
|
5449
5470
|
labels: Array.isArray(value.labels) ? parseStringArray(value.labels, "board task labels") : [],
|
|
5450
5471
|
priority: typeof value.priority === "number" ? value.priority : 0,
|
|
@@ -6146,6 +6167,7 @@ function isBridgeEvent(value) {
|
|
|
6146
6167
|
}
|
|
6147
6168
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6148
6169
|
0 && (module.exports = {
|
|
6170
|
+
BOARD_COLUMN_ROLES,
|
|
6149
6171
|
BOARD_TOOL_READ_NAMES,
|
|
6150
6172
|
BOARD_TOOL_WRITE_NAMES,
|
|
6151
6173
|
CAPABILITY_VERBS,
|
|
@@ -6195,11 +6217,13 @@ function isBridgeEvent(value) {
|
|
|
6195
6217
|
isBoardToolWriteName,
|
|
6196
6218
|
isBridgeEvent,
|
|
6197
6219
|
isCapabilityVerb,
|
|
6220
|
+
isDoneRole,
|
|
6198
6221
|
isJsonValue,
|
|
6199
6222
|
isPushCategory,
|
|
6200
6223
|
isRecord,
|
|
6201
6224
|
isRosterEntryExpired,
|
|
6202
6225
|
isSecureRelayAddress,
|
|
6226
|
+
isTodoRole,
|
|
6203
6227
|
openPairingConfirm,
|
|
6204
6228
|
openPushEnvelope,
|
|
6205
6229
|
parseActivityEventPayload,
|
package/dist/index.d.ts
CHANGED
|
@@ -22,5 +22,5 @@ export { formatKeyFingerprint } from './roster/fingerprint';
|
|
|
22
22
|
export { CAPABILITY_VERBS, isCapabilityVerb, capabilitySetFromArray, capabilitySetToArray, type CapabilityVerb, type CapabilitySet, } from './capabilities/verbs';
|
|
23
23
|
export { BOARD_TOOL_READ_NAMES, BOARD_TOOL_WRITE_NAMES, isBoardToolReadName, isBoardToolWriteName, type BoardToolReadName, type BoardToolWriteName, type BoardToolName, } from './capabilities/board-tools';
|
|
24
24
|
export { isBridgeEvent, parseActivityEventPayload, type BridgeEvent, type TranscriptEvent, type ActivityEvent, type ActivityEventPayload, type TerminalEvent, type TerminalResizeEvent, type BoardEvent, type BoardEventPayload, type DiffEvent, } from './events/event';
|
|
25
|
-
export { parseTranscriptEntriesWire, parseTranscriptEventPayload, type TranscriptEventPayload, type TranscriptUpsertWire, isActivityStateWire, isActivityReasonWire, parseSessionUsageWire, parseSessionSummaryWire, parseSessionEventWire, parseTerminalDimensionsWire, parseBoardColumnWire, parseBoardTaskWire, parseBacklogItemWire, parseDiffFileListWire, parseDiffFileContentWire, type TranscriptBlockWire, type TranscriptEntryWire, type TranscriptTurnUsageWire, type TranscriptSystemSubtypeWire, type ActivityStateWire, type ActivityReasonWire, type SessionUsageWire, type SessionSummaryWire, type SessionEventWire, type TerminalDimensionsWire, type BoardColumnWire, type BoardTaskWire, type BacklogItemWire, type DiffFileStatusWire, type DiffFileWire, type DiffFileListWire, type DiffFileContentWire, } from './events/payloads';
|
|
25
|
+
export { parseTranscriptEntriesWire, parseTranscriptEventPayload, type TranscriptEventPayload, type TranscriptUpsertWire, isActivityStateWire, isActivityReasonWire, parseSessionUsageWire, parseSessionSummaryWire, parseSessionEventWire, parseTerminalDimensionsWire, parseBoardColumnWire, parseBoardTaskWire, parseBacklogItemWire, parseDiffFileListWire, parseDiffFileContentWire, isTodoRole, isDoneRole, BOARD_COLUMN_ROLES, type TranscriptBlockWire, type TranscriptEntryWire, type TranscriptTurnUsageWire, type TranscriptSystemSubtypeWire, type ActivityStateWire, type ActivityReasonWire, type SessionUsageWire, type SessionSummaryWire, type SessionEventWire, type TerminalDimensionsWire, type BoardColumnWire, type BoardColumnRoleWire, type BoardTaskWire, type BacklogItemWire, type DiffFileStatusWire, type DiffFileWire, type DiffFileListWire, type DiffFileContentWire, } from './events/payloads';
|
|
26
26
|
export type { Transport, TransportState, Unsubscribe } from './transport/transport';
|
package/dist/index.mjs
CHANGED
|
@@ -5131,6 +5131,15 @@ function openPushEnvelope(pushKey, recipientStaticPublicKey, blob) {
|
|
|
5131
5131
|
}
|
|
5132
5132
|
|
|
5133
5133
|
// src/events/payloads.ts
|
|
5134
|
+
var BOARD_COLUMN_ROLES = ["todo", "done"];
|
|
5135
|
+
var TODO_ROLE = "todo";
|
|
5136
|
+
var DONE_ROLE = "done";
|
|
5137
|
+
function isTodoRole(role) {
|
|
5138
|
+
return role === TODO_ROLE;
|
|
5139
|
+
}
|
|
5140
|
+
function isDoneRole(role) {
|
|
5141
|
+
return role === DONE_ROLE;
|
|
5142
|
+
}
|
|
5134
5143
|
var DIFF_FILE_STATUSES = ["A", "M", "D", "R", "C", "U"];
|
|
5135
5144
|
var TRANSCRIPT_SYSTEM_SUBTYPES = ["compaction", "command", "command_output", "session_boundary"];
|
|
5136
5145
|
function requireString(record, field, context) {
|
|
@@ -5297,18 +5306,26 @@ function nullableNumber(record, field) {
|
|
|
5297
5306
|
const value = record[field];
|
|
5298
5307
|
return typeof value === "number" ? value : null;
|
|
5299
5308
|
}
|
|
5309
|
+
function nullableBoolean(record, field) {
|
|
5310
|
+
const value = record[field];
|
|
5311
|
+
return typeof value === "boolean" ? value : null;
|
|
5312
|
+
}
|
|
5300
5313
|
function parseBoardColumnWire(value) {
|
|
5301
5314
|
if (!isRecord(value)) throw new Error("board column must be an object");
|
|
5302
5315
|
return {
|
|
5303
5316
|
id: requireString(value, "id", "board column"),
|
|
5304
5317
|
name: requireString(value, "name", "board column"),
|
|
5305
5318
|
description: nullableString(value, "description"),
|
|
5319
|
+
// An unrecognized role passes through rather than throwing: it is a
|
|
5320
|
+
// custom column (or a future system role this package predates), not a
|
|
5321
|
+
// malformed payload. See the BoardColumnRoleWire doc comment.
|
|
5306
5322
|
role: nullableString(value, "role"),
|
|
5307
5323
|
position: requireNumber(value, "position", "board column"),
|
|
5308
5324
|
color: requireString(value, "color", "board column"),
|
|
5309
5325
|
icon: nullableString(value, "icon"),
|
|
5310
5326
|
is_archived: requireBoolean(value, "is_archived", "board column"),
|
|
5311
|
-
is_ghost: requireBoolean(value, "is_ghost", "board column")
|
|
5327
|
+
is_ghost: requireBoolean(value, "is_ghost", "board column"),
|
|
5328
|
+
spawns_session: nullableBoolean(value, "spawns_session")
|
|
5312
5329
|
};
|
|
5313
5330
|
}
|
|
5314
5331
|
function parseBoardTaskWire(value) {
|
|
@@ -5327,6 +5344,7 @@ function parseBoardTaskWire(value) {
|
|
|
5327
5344
|
pr_number: nullableNumber(value, "pr_number"),
|
|
5328
5345
|
pr_url: nullableString(value, "pr_url"),
|
|
5329
5346
|
pr_state: nullableString(value, "pr_state"),
|
|
5347
|
+
pr_merge_readiness: nullableString(value, "pr_merge_readiness"),
|
|
5330
5348
|
base_branch: nullableString(value, "base_branch"),
|
|
5331
5349
|
labels: Array.isArray(value.labels) ? parseStringArray(value.labels, "board task labels") : [],
|
|
5332
5350
|
priority: typeof value.priority === "number" ? value.priority : 0,
|
|
@@ -6027,6 +6045,7 @@ function isBridgeEvent(value) {
|
|
|
6027
6045
|
}
|
|
6028
6046
|
}
|
|
6029
6047
|
export {
|
|
6048
|
+
BOARD_COLUMN_ROLES,
|
|
6030
6049
|
BOARD_TOOL_READ_NAMES,
|
|
6031
6050
|
BOARD_TOOL_WRITE_NAMES,
|
|
6032
6051
|
CAPABILITY_VERBS,
|
|
@@ -6076,11 +6095,13 @@ export {
|
|
|
6076
6095
|
isBoardToolWriteName,
|
|
6077
6096
|
isBridgeEvent,
|
|
6078
6097
|
isCapabilityVerb,
|
|
6098
|
+
isDoneRole,
|
|
6079
6099
|
isJsonValue,
|
|
6080
6100
|
isPushCategory,
|
|
6081
6101
|
isRecord,
|
|
6082
6102
|
isRosterEntryExpired,
|
|
6083
6103
|
isSecureRelayAddress,
|
|
6104
|
+
isTodoRole,
|
|
6084
6105
|
openPairingConfirm,
|
|
6085
6106
|
openPushEnvelope,
|
|
6086
6107
|
parseActivityEventPayload,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kangentic/protocol",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.1",
|
|
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",
|