@kangentic/protocol 0.18.0 → 0.19.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.
- package/dist/index.cjs +14 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +12 -0
- package/dist/wire/framing.d.ts +15 -0
- package/dist/wire/messages.d.ts +14 -6
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -39,6 +39,7 @@ __export(index_exports, {
|
|
|
39
39
|
PUSH_CATEGORIES: () => PUSH_CATEGORIES,
|
|
40
40
|
PUSH_ENVELOPE_MAX_AGE_MS: () => PUSH_ENVELOPE_MAX_AGE_MS,
|
|
41
41
|
PUSH_ENVELOPE_MAX_FUTURE_SKEW_MS: () => PUSH_ENVELOPE_MAX_FUTURE_SKEW_MS,
|
|
42
|
+
RESPONSE_TOO_LARGE_ERROR_CODE: () => RESPONSE_TOO_LARGE_ERROR_CODE,
|
|
42
43
|
SecretstreamState: () => SecretstreamState,
|
|
43
44
|
SessionFrameKind: () => SessionFrameKind,
|
|
44
45
|
UNSUPPORTED_VERB_ERROR_CODE: () => UNSUPPORTED_VERB_ERROR_CODE,
|
|
@@ -58,6 +59,7 @@ __export(index_exports, {
|
|
|
58
59
|
deriveSessionSlotId: () => deriveSessionSlotId,
|
|
59
60
|
deriveShortAuthenticationString: () => deriveShortAuthenticationString,
|
|
60
61
|
encodeMessage: () => encodeMessage,
|
|
62
|
+
encodeMessageFailure: () => encodeMessageFailure,
|
|
61
63
|
encodePairingQrPayload: () => encodePairingQrPayload,
|
|
62
64
|
encodeProtocolVersion: () => encodeProtocolVersion,
|
|
63
65
|
encodeRosterEntryForSigning: () => encodeRosterEntryForSigning,
|
|
@@ -5010,6 +5012,7 @@ var FRAME_FORMAT_DEFLATE = 1;
|
|
|
5010
5012
|
var JSON_OPEN_BRACE = 123;
|
|
5011
5013
|
var DEFLATE_HEADER_LENGTH = 5;
|
|
5012
5014
|
var UNSUPPORTED_VERB_ERROR_CODE = "unsupported-verb";
|
|
5015
|
+
var RESPONSE_TOO_LARGE_ERROR_CODE = "response-too-large";
|
|
5013
5016
|
var UNSUPPORTED_VERB_ERROR_NAME = "UnsupportedVerbError";
|
|
5014
5017
|
var UnsupportedVerbError = class extends Error {
|
|
5015
5018
|
requestId;
|
|
@@ -5046,6 +5049,15 @@ function encodeMessage(message) {
|
|
|
5046
5049
|
}
|
|
5047
5050
|
return frame;
|
|
5048
5051
|
}
|
|
5052
|
+
function encodeMessageFailure(message) {
|
|
5053
|
+
try {
|
|
5054
|
+
if (new TextEncoder().encode(JSON.stringify(message)).length <= MAX_FRAME_LENGTH) return null;
|
|
5055
|
+
encodeMessage(message);
|
|
5056
|
+
return null;
|
|
5057
|
+
} catch (error) {
|
|
5058
|
+
return error instanceof Error ? error.message : String(error);
|
|
5059
|
+
}
|
|
5060
|
+
}
|
|
5049
5061
|
function decodeMessage(bytes) {
|
|
5050
5062
|
if (bytes.length > MAX_FRAME_LENGTH) {
|
|
5051
5063
|
throw new Error(`Bridge message frame exceeds ${MAX_FRAME_LENGTH} bytes`);
|
|
@@ -6246,6 +6258,7 @@ function isBridgeEvent(value) {
|
|
|
6246
6258
|
PUSH_CATEGORIES,
|
|
6247
6259
|
PUSH_ENVELOPE_MAX_AGE_MS,
|
|
6248
6260
|
PUSH_ENVELOPE_MAX_FUTURE_SKEW_MS,
|
|
6261
|
+
RESPONSE_TOO_LARGE_ERROR_CODE,
|
|
6249
6262
|
SecretstreamState,
|
|
6250
6263
|
SessionFrameKind,
|
|
6251
6264
|
UNSUPPORTED_VERB_ERROR_CODE,
|
|
@@ -6265,6 +6278,7 @@ function isBridgeEvent(value) {
|
|
|
6265
6278
|
deriveSessionSlotId,
|
|
6266
6279
|
deriveShortAuthenticationString,
|
|
6267
6280
|
encodeMessage,
|
|
6281
|
+
encodeMessageFailure,
|
|
6268
6282
|
encodePairingQrPayload,
|
|
6269
6283
|
encodeProtocolVersion,
|
|
6270
6284
|
encodeRosterEntryForSigning,
|
package/dist/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export { SecretstreamState, deriveSecretstreamPair, FrameTag, type SecretstreamD
|
|
|
9
9
|
export { deriveShortAuthenticationString, type ShortAuthenticationString } from './crypto/sas';
|
|
10
10
|
export { deriveSessionSlotId, derivePairingSlotId } from './crypto/slot';
|
|
11
11
|
export type { JsonValue, BridgeMessage, HeartbeatMessage, CapabilityRequestMessage, CapabilityResponseMessage, CapabilityErrorCode, EventMessage } from './wire/messages';
|
|
12
|
-
export { encodeMessage, decodeMessage, UnsupportedVerbError, isUnsupportedVerbError, UNSUPPORTED_VERB_ERROR_CODE, MAX_FRAME_LENGTH, MAX_DECODED_LENGTH, COMPRESSION_THRESHOLD, } from './wire/framing';
|
|
12
|
+
export { encodeMessage, encodeMessageFailure, decodeMessage, UnsupportedVerbError, isUnsupportedVerbError, UNSUPPORTED_VERB_ERROR_CODE, RESPONSE_TOO_LARGE_ERROR_CODE, MAX_FRAME_LENGTH, MAX_DECODED_LENGTH, COMPRESSION_THRESHOLD, } from './wire/framing';
|
|
13
13
|
export { isJsonValue, isRecord } from './wire/json-value';
|
|
14
14
|
export { SessionFrameKind, wrapSessionFrame, unwrapSessionFrame } from './wire/session-frame';
|
|
15
15
|
export { parseCapabilityRequestPayload, parseReadStreamResponsePayload, parseReadBoardResponsePayload, parseReadDiffResponsePayload, parseTranscriptWindowResponsePayload, parseRegisterPushRequestPayload, parseStartSessionResponsePayload, parsePauseSessionResponsePayload, isReadStreamSessionStatusWire, type CapabilityRequestPayloadMap, type CapabilityResponsePayloadMap, type ReadStreamRequestPayload, type ReadStreamResponsePayload, type ReadStreamSessionStatusWire, type TranscriptWindowResponsePayload, type ReadBoardRequestPayload, type ReadBoardView, type ReadBoardProjectSummary, type ReadBoardProjectGroup, type ReadBoardProjectListResponsePayload, type ReadBoardSnapshotResponsePayload, type ReadBoardArchivedResponsePayload, type ReadBoardResponsePayload, type ReadDiffScope, type ReadDiffRequestPayload, type ReadDiffResponsePayload, type SendUserMessageRequestPayload, type SendUserMessageResponsePayload, type MoveTaskRequestPayload, type MoveTaskResponsePayload, type AnswerPermissionPromptRequestPayload, type AnswerPermissionPromptResponsePayload, type InteractiveTerminalRequestPayload, type InteractiveTerminalResponsePayload, type BoardToolRequestPayload, type BoardToolResponsePayload, type RegisterPushRequestPayload, type RegisterPushResponsePayload, type StartSessionRequestPayload, type StartSessionResponsePayload, type StartSessionOutcome, type PauseSessionRequestPayload, type PauseSessionResponsePayload, } from './wire/payloads';
|
package/dist/index.mjs
CHANGED
|
@@ -4883,6 +4883,7 @@ var FRAME_FORMAT_DEFLATE = 1;
|
|
|
4883
4883
|
var JSON_OPEN_BRACE = 123;
|
|
4884
4884
|
var DEFLATE_HEADER_LENGTH = 5;
|
|
4885
4885
|
var UNSUPPORTED_VERB_ERROR_CODE = "unsupported-verb";
|
|
4886
|
+
var RESPONSE_TOO_LARGE_ERROR_CODE = "response-too-large";
|
|
4886
4887
|
var UNSUPPORTED_VERB_ERROR_NAME = "UnsupportedVerbError";
|
|
4887
4888
|
var UnsupportedVerbError = class extends Error {
|
|
4888
4889
|
requestId;
|
|
@@ -4919,6 +4920,15 @@ function encodeMessage(message) {
|
|
|
4919
4920
|
}
|
|
4920
4921
|
return frame;
|
|
4921
4922
|
}
|
|
4923
|
+
function encodeMessageFailure(message) {
|
|
4924
|
+
try {
|
|
4925
|
+
if (new TextEncoder().encode(JSON.stringify(message)).length <= MAX_FRAME_LENGTH) return null;
|
|
4926
|
+
encodeMessage(message);
|
|
4927
|
+
return null;
|
|
4928
|
+
} catch (error) {
|
|
4929
|
+
return error instanceof Error ? error.message : String(error);
|
|
4930
|
+
}
|
|
4931
|
+
}
|
|
4922
4932
|
function decodeMessage(bytes) {
|
|
4923
4933
|
if (bytes.length > MAX_FRAME_LENGTH) {
|
|
4924
4934
|
throw new Error(`Bridge message frame exceeds ${MAX_FRAME_LENGTH} bytes`);
|
|
@@ -6118,6 +6128,7 @@ export {
|
|
|
6118
6128
|
PUSH_CATEGORIES,
|
|
6119
6129
|
PUSH_ENVELOPE_MAX_AGE_MS,
|
|
6120
6130
|
PUSH_ENVELOPE_MAX_FUTURE_SKEW_MS,
|
|
6131
|
+
RESPONSE_TOO_LARGE_ERROR_CODE,
|
|
6121
6132
|
SecretstreamState,
|
|
6122
6133
|
SessionFrameKind,
|
|
6123
6134
|
UNSUPPORTED_VERB_ERROR_CODE,
|
|
@@ -6137,6 +6148,7 @@ export {
|
|
|
6137
6148
|
deriveSessionSlotId,
|
|
6138
6149
|
deriveShortAuthenticationString,
|
|
6139
6150
|
encodeMessage,
|
|
6151
|
+
encodeMessageFailure,
|
|
6140
6152
|
encodePairingQrPayload,
|
|
6141
6153
|
encodeProtocolVersion,
|
|
6142
6154
|
encodeRosterEntryForSigning,
|
package/dist/wire/framing.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export declare const MAX_DECODED_LENGTH: number;
|
|
|
6
6
|
export declare const COMPRESSION_THRESHOLD: number;
|
|
7
7
|
/** The `code` a desktop puts on its refusal of a verb its build does not know. */
|
|
8
8
|
export declare const UNSUPPORTED_VERB_ERROR_CODE: CapabilityErrorCode;
|
|
9
|
+
/** The `code` a desktop puts on its refusal of a response that would not fit the frame caps above. */
|
|
10
|
+
export declare const RESPONSE_TOO_LARGE_ERROR_CODE: CapabilityErrorCode;
|
|
9
11
|
/**
|
|
10
12
|
* Thrown by `decodeMessage` for a capability-request whose envelope is
|
|
11
13
|
* well-formed (a string `requestId`, a string `verb`, a JSON `payload`) but
|
|
@@ -34,4 +36,17 @@ export declare class UnsupportedVerbError extends Error {
|
|
|
34
36
|
*/
|
|
35
37
|
export declare function isUnsupportedVerbError(error: unknown): error is UnsupportedVerbError;
|
|
36
38
|
export declare function encodeMessage(message: BridgeMessage): Uint8Array;
|
|
39
|
+
/**
|
|
40
|
+
* Why `encodeMessage` would throw for `message`, or null when it would not,
|
|
41
|
+
* without keeping the frame. A sender with side effects asks this BEFORE
|
|
42
|
+
* committing them, so it can send something smaller instead of committing to
|
|
43
|
+
* a message it cannot send (the desktop re-takes a shorter terminal seed).
|
|
44
|
+
*
|
|
45
|
+
* Exact, not an estimate. Raw UTF-8 JSON at or under MAX_FRAME_LENGTH always
|
|
46
|
+
* fits, because `encodeMessage` only switches to deflate when deflate is
|
|
47
|
+
* smaller, so that common case costs one stringify. A larger message runs the
|
|
48
|
+
* real encode, deflate included, and a sender that then sends it pays that
|
|
49
|
+
* encode a second time. Measured terminal seeds are far under the threshold.
|
|
50
|
+
*/
|
|
51
|
+
export declare function encodeMessageFailure(message: BridgeMessage): string | null;
|
|
37
52
|
export declare function decodeMessage(bytes: Uint8Array): BridgeMessage;
|
package/dist/wire/messages.d.ts
CHANGED
|
@@ -32,13 +32,21 @@ export interface CapabilityRequestMessage {
|
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
34
|
* A stable key a client can branch on, beside the human-readable `error`.
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
35
|
+
* A union rather than a bare string so a new code is a deliberate addition
|
|
36
|
+
* here, not a typo at a call site.
|
|
37
|
+
*
|
|
38
|
+
* - `unsupported-verb`: the desktop's build does not know the verb (see
|
|
39
|
+
* `UnsupportedVerbError` in framing.ts), so a newer phone can tell "desktop
|
|
40
|
+
* is old" from "desktop is unreachable" and show the right copy.
|
|
41
|
+
* - `response-too-large`: the answer would not fit the frame caps
|
|
42
|
+
* (MAX_DECODED_LENGTH before compression, MAX_FRAME_LENGTH after), so the
|
|
43
|
+
* desktop refused instead of sending it. The request was valid and its
|
|
44
|
+
* target still exists, so a client must not read it as the target being
|
|
45
|
+
* gone (a session ending, a project removed). It is a backstop. A desktop
|
|
46
|
+
* shrinks a `read-stream` terminal seed to fit rather than refuse it, so a
|
|
47
|
+
* phone's terminal subscribe is never answered with this code.
|
|
40
48
|
*/
|
|
41
|
-
export type CapabilityErrorCode = 'unsupported-verb';
|
|
49
|
+
export type CapabilityErrorCode = 'unsupported-verb' | 'response-too-large';
|
|
42
50
|
export interface CapabilityResponseMessage {
|
|
43
51
|
type: 'capability-response';
|
|
44
52
|
requestId: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kangentic/protocol",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.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",
|