@agent-relay/protocol 0.1.2
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/channels.d.ts +137 -0
- package/dist/channels.d.ts.map +1 -0
- package/dist/channels.js +154 -0
- package/dist/channels.js.map +1 -0
- package/dist/framing.d.ts +80 -0
- package/dist/framing.d.ts.map +1 -0
- package/dist/framing.js +206 -0
- package/dist/framing.js.map +1 -0
- package/dist/id-generator.d.ts +35 -0
- package/dist/id-generator.d.ts.map +1 -0
- package/dist/id-generator.js +60 -0
- package/dist/id-generator.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/relay-pty-schemas.d.ts +258 -0
- package/dist/relay-pty-schemas.d.ts.map +1 -0
- package/dist/relay-pty-schemas.js +60 -0
- package/dist/relay-pty-schemas.js.map +1 -0
- package/dist/types.d.ts +341 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channel and User Protocol Types
|
|
3
|
+
*
|
|
4
|
+
* Extends the Agent Relay Protocol to support:
|
|
5
|
+
* - First-class user entities (humans, not just AI agents)
|
|
6
|
+
* - Channels for group communication
|
|
7
|
+
* - Direct messaging between any combination of users and agents
|
|
8
|
+
*/
|
|
9
|
+
import { PROTOCOL_VERSION, type EntityType, type MessageAttachment, type ChannelJoinEnvelope, type ChannelLeaveEnvelope, type ChannelMessageEnvelope } from './types.js';
|
|
10
|
+
export type { MessageAttachment, ChannelJoinPayload, ChannelLeavePayload, ChannelMessagePayload, ChannelJoinEnvelope, ChannelLeaveEnvelope, ChannelMessageEnvelope, } from './types.js';
|
|
11
|
+
export { PROTOCOL_VERSION };
|
|
12
|
+
/**
|
|
13
|
+
* Extended message types for channels.
|
|
14
|
+
*/
|
|
15
|
+
export type ChannelMessageType = 'CHANNEL_JOIN' | 'CHANNEL_LEAVE' | 'CHANNEL_MESSAGE' | 'CHANNEL_INFO' | 'CHANNEL_MEMBERS' | 'CHANNEL_TYPING';
|
|
16
|
+
/**
|
|
17
|
+
* Channel member info.
|
|
18
|
+
*/
|
|
19
|
+
export interface ChannelMember {
|
|
20
|
+
name: string;
|
|
21
|
+
entityType: EntityType;
|
|
22
|
+
displayName?: string;
|
|
23
|
+
avatarUrl?: string;
|
|
24
|
+
status?: 'online' | 'away' | 'offline';
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Payload for CHANNEL_INFO.
|
|
28
|
+
* Contains metadata about a channel.
|
|
29
|
+
*/
|
|
30
|
+
export interface ChannelInfoPayload {
|
|
31
|
+
/** Channel identifier */
|
|
32
|
+
channel: string;
|
|
33
|
+
/** Human-readable channel name */
|
|
34
|
+
name: string;
|
|
35
|
+
/** Optional description */
|
|
36
|
+
description?: string;
|
|
37
|
+
/** Optional current topic */
|
|
38
|
+
topic?: string;
|
|
39
|
+
/** List of members */
|
|
40
|
+
members: ChannelMember[];
|
|
41
|
+
/** When the channel was created */
|
|
42
|
+
createdAt: string;
|
|
43
|
+
/** Whether the channel is private */
|
|
44
|
+
isPrivate?: boolean;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Payload for CHANNEL_MEMBERS.
|
|
48
|
+
* List of members in a channel.
|
|
49
|
+
*/
|
|
50
|
+
export interface ChannelMembersPayload {
|
|
51
|
+
channel: string;
|
|
52
|
+
members: ChannelMember[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Payload for CHANNEL_TYPING.
|
|
56
|
+
* Indicates someone is typing in a channel.
|
|
57
|
+
*/
|
|
58
|
+
export interface ChannelTypingPayload {
|
|
59
|
+
channel: string;
|
|
60
|
+
isTyping: boolean;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Check if an entity type represents a user.
|
|
64
|
+
*/
|
|
65
|
+
export declare function isUserEntity(entityType: EntityType | undefined): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Check if an entity type represents an agent.
|
|
68
|
+
* Undefined defaults to agent for backwards compatibility.
|
|
69
|
+
*/
|
|
70
|
+
export declare function isAgentEntity(entityType: EntityType | undefined): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Type guard to check if an envelope is a channel message.
|
|
73
|
+
*/
|
|
74
|
+
export declare function isChannelMessage(envelope: {
|
|
75
|
+
type: string;
|
|
76
|
+
}): envelope is ChannelMessageEnvelope;
|
|
77
|
+
/**
|
|
78
|
+
* Type guard to check if an envelope is a channel join.
|
|
79
|
+
*/
|
|
80
|
+
export declare function isChannelJoin(envelope: {
|
|
81
|
+
type: string;
|
|
82
|
+
}): envelope is ChannelJoinEnvelope;
|
|
83
|
+
/**
|
|
84
|
+
* Type guard to check if an envelope is a channel leave.
|
|
85
|
+
*/
|
|
86
|
+
export declare function isChannelLeave(envelope: {
|
|
87
|
+
type: string;
|
|
88
|
+
}): envelope is ChannelLeaveEnvelope;
|
|
89
|
+
/**
|
|
90
|
+
* Create a CHANNEL_JOIN envelope.
|
|
91
|
+
*/
|
|
92
|
+
export declare function createChannelJoinEnvelope(from: string, channel: string, options?: {
|
|
93
|
+
displayName?: string;
|
|
94
|
+
avatarUrl?: string;
|
|
95
|
+
}): ChannelJoinEnvelope;
|
|
96
|
+
/**
|
|
97
|
+
* Create a CHANNEL_LEAVE envelope.
|
|
98
|
+
*/
|
|
99
|
+
export declare function createChannelLeaveEnvelope(from: string, channel: string, reason?: string): ChannelLeaveEnvelope;
|
|
100
|
+
/**
|
|
101
|
+
* Create a CHANNEL_MESSAGE envelope.
|
|
102
|
+
*/
|
|
103
|
+
export declare function createChannelMessageEnvelope(from: string, channel: string, body: string, options?: {
|
|
104
|
+
thread?: string;
|
|
105
|
+
mentions?: string[];
|
|
106
|
+
attachments?: MessageAttachment[];
|
|
107
|
+
data?: Record<string, unknown>;
|
|
108
|
+
}): ChannelMessageEnvelope;
|
|
109
|
+
/**
|
|
110
|
+
* Parse a DM channel name to extract participants.
|
|
111
|
+
* DM channels follow the format: dm:<participant1>:<participant2>:...
|
|
112
|
+
*/
|
|
113
|
+
export declare function parseDmChannel(channel: string): string[] | null;
|
|
114
|
+
/**
|
|
115
|
+
* Create a DM channel name from participants.
|
|
116
|
+
* Participants are sorted alphabetically for consistency.
|
|
117
|
+
*/
|
|
118
|
+
export declare function createDmChannelName(...participants: string[]): string;
|
|
119
|
+
/**
|
|
120
|
+
* Check if a channel is a DM (direct message).
|
|
121
|
+
*/
|
|
122
|
+
export declare function isDmChannel(channel: string): boolean;
|
|
123
|
+
/**
|
|
124
|
+
* Check if a channel is private.
|
|
125
|
+
*/
|
|
126
|
+
export declare function isPrivateChannel(channel: string): boolean;
|
|
127
|
+
/**
|
|
128
|
+
* Check if a channel is a public channel (starts with #).
|
|
129
|
+
*/
|
|
130
|
+
export declare function isPublicChannel(channel: string): boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Normalize channel name for storage/lookup.
|
|
133
|
+
* - Removes leading # from public channels
|
|
134
|
+
* - Sorts participants in DM channels
|
|
135
|
+
*/
|
|
136
|
+
export declare function normalizeChannelName(channel: string): string;
|
|
137
|
+
//# sourceMappingURL=channels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channels.d.ts","sourceRoot":"","sources":["../src/channels.ts"],"names":[],"mappings":"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"}
|
package/dist/channels.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channel and User Protocol Types
|
|
3
|
+
*
|
|
4
|
+
* Extends the Agent Relay Protocol to support:
|
|
5
|
+
* - First-class user entities (humans, not just AI agents)
|
|
6
|
+
* - Channels for group communication
|
|
7
|
+
* - Direct messaging between any combination of users and agents
|
|
8
|
+
*/
|
|
9
|
+
import { generateId } from './id-generator.js';
|
|
10
|
+
import { PROTOCOL_VERSION, } from './types.js';
|
|
11
|
+
// Re-export for convenience
|
|
12
|
+
export { PROTOCOL_VERSION };
|
|
13
|
+
/**
|
|
14
|
+
* Check if an entity type represents a user.
|
|
15
|
+
*/
|
|
16
|
+
export function isUserEntity(entityType) {
|
|
17
|
+
return entityType === 'user';
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Check if an entity type represents an agent.
|
|
21
|
+
* Undefined defaults to agent for backwards compatibility.
|
|
22
|
+
*/
|
|
23
|
+
export function isAgentEntity(entityType) {
|
|
24
|
+
return entityType === 'agent' || entityType === undefined;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Type guard to check if an envelope is a channel message.
|
|
28
|
+
*/
|
|
29
|
+
export function isChannelMessage(envelope) {
|
|
30
|
+
return envelope.type === 'CHANNEL_MESSAGE';
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Type guard to check if an envelope is a channel join.
|
|
34
|
+
*/
|
|
35
|
+
export function isChannelJoin(envelope) {
|
|
36
|
+
return envelope.type === 'CHANNEL_JOIN';
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Type guard to check if an envelope is a channel leave.
|
|
40
|
+
*/
|
|
41
|
+
export function isChannelLeave(envelope) {
|
|
42
|
+
return envelope.type === 'CHANNEL_LEAVE';
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Create a CHANNEL_JOIN envelope.
|
|
46
|
+
*/
|
|
47
|
+
export function createChannelJoinEnvelope(from, channel, options) {
|
|
48
|
+
return {
|
|
49
|
+
v: PROTOCOL_VERSION,
|
|
50
|
+
type: 'CHANNEL_JOIN',
|
|
51
|
+
id: generateId(),
|
|
52
|
+
ts: Date.now(),
|
|
53
|
+
from,
|
|
54
|
+
payload: {
|
|
55
|
+
channel,
|
|
56
|
+
displayName: options?.displayName,
|
|
57
|
+
avatarUrl: options?.avatarUrl,
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Create a CHANNEL_LEAVE envelope.
|
|
63
|
+
*/
|
|
64
|
+
export function createChannelLeaveEnvelope(from, channel, reason) {
|
|
65
|
+
return {
|
|
66
|
+
v: PROTOCOL_VERSION,
|
|
67
|
+
type: 'CHANNEL_LEAVE',
|
|
68
|
+
id: generateId(),
|
|
69
|
+
ts: Date.now(),
|
|
70
|
+
from,
|
|
71
|
+
payload: {
|
|
72
|
+
channel,
|
|
73
|
+
reason,
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Create a CHANNEL_MESSAGE envelope.
|
|
79
|
+
*/
|
|
80
|
+
export function createChannelMessageEnvelope(from, channel, body, options) {
|
|
81
|
+
return {
|
|
82
|
+
v: PROTOCOL_VERSION,
|
|
83
|
+
type: 'CHANNEL_MESSAGE',
|
|
84
|
+
id: generateId(),
|
|
85
|
+
ts: Date.now(),
|
|
86
|
+
from,
|
|
87
|
+
payload: {
|
|
88
|
+
channel,
|
|
89
|
+
body,
|
|
90
|
+
thread: options?.thread,
|
|
91
|
+
mentions: options?.mentions,
|
|
92
|
+
attachments: options?.attachments,
|
|
93
|
+
data: options?.data,
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Parse a DM channel name to extract participants.
|
|
99
|
+
* DM channels follow the format: dm:<participant1>:<participant2>:...
|
|
100
|
+
*/
|
|
101
|
+
export function parseDmChannel(channel) {
|
|
102
|
+
if (!channel.startsWith('dm:')) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
const parts = channel.split(':').slice(1);
|
|
106
|
+
return parts.length >= 2 ? parts : null;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Create a DM channel name from participants.
|
|
110
|
+
* Participants are sorted alphabetically for consistency.
|
|
111
|
+
*/
|
|
112
|
+
export function createDmChannelName(...participants) {
|
|
113
|
+
if (participants.length < 2) {
|
|
114
|
+
throw new Error('DM requires at least 2 participants');
|
|
115
|
+
}
|
|
116
|
+
const sorted = [...participants].sort();
|
|
117
|
+
return `dm:${sorted.join(':')}`;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Check if a channel is a DM (direct message).
|
|
121
|
+
*/
|
|
122
|
+
export function isDmChannel(channel) {
|
|
123
|
+
return channel.startsWith('dm:');
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Check if a channel is private.
|
|
127
|
+
*/
|
|
128
|
+
export function isPrivateChannel(channel) {
|
|
129
|
+
return channel.startsWith('private:');
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Check if a channel is a public channel (starts with #).
|
|
133
|
+
*/
|
|
134
|
+
export function isPublicChannel(channel) {
|
|
135
|
+
return channel.startsWith('#');
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Normalize channel name for storage/lookup.
|
|
139
|
+
* - Removes leading # from public channels
|
|
140
|
+
* - Sorts participants in DM channels
|
|
141
|
+
*/
|
|
142
|
+
export function normalizeChannelName(channel) {
|
|
143
|
+
if (channel.startsWith('#')) {
|
|
144
|
+
return channel.slice(1);
|
|
145
|
+
}
|
|
146
|
+
if (channel.startsWith('dm:')) {
|
|
147
|
+
const participants = parseDmChannel(channel);
|
|
148
|
+
if (participants) {
|
|
149
|
+
return createDmChannelName(...participants);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return channel;
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=channels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channels.js","sourceRoot":"","sources":["../src/channels.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frame encoding/decoding for the Agent Relay protocol.
|
|
3
|
+
* @agent-relay/sdk
|
|
4
|
+
*
|
|
5
|
+
* Wire format:
|
|
6
|
+
* - 1 byte: format indicator (0 = JSON, 1 = MessagePack)
|
|
7
|
+
* - 4 bytes: big-endian payload length
|
|
8
|
+
* - N bytes: payload (JSON or MessagePack encoded)
|
|
9
|
+
*
|
|
10
|
+
* Legacy format (for backwards compatibility):
|
|
11
|
+
* - 4 bytes: big-endian payload length
|
|
12
|
+
* - N bytes: JSON payload
|
|
13
|
+
*/
|
|
14
|
+
import type { Envelope } from './types.js';
|
|
15
|
+
export declare const MAX_FRAME_BYTES: number;
|
|
16
|
+
export declare const HEADER_SIZE = 5;
|
|
17
|
+
export declare const LEGACY_HEADER_SIZE = 4;
|
|
18
|
+
export type WireFormat = 'json' | 'msgpack';
|
|
19
|
+
/**
|
|
20
|
+
* Initialize MessagePack support.
|
|
21
|
+
* Install @msgpack/msgpack to enable: npm install @msgpack/msgpack
|
|
22
|
+
*/
|
|
23
|
+
export declare function initMessagePack(): Promise<boolean>;
|
|
24
|
+
/**
|
|
25
|
+
* Check if MessagePack is available.
|
|
26
|
+
*/
|
|
27
|
+
export declare function hasMessagePack(): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Encode a message envelope into a framed buffer.
|
|
30
|
+
*
|
|
31
|
+
* @param envelope - The envelope to encode
|
|
32
|
+
* @param format - Wire format to use (default: 'json')
|
|
33
|
+
* @returns Framed buffer ready for socket write
|
|
34
|
+
*/
|
|
35
|
+
export declare function encodeFrame(envelope: Envelope, format?: WireFormat): Buffer;
|
|
36
|
+
/**
|
|
37
|
+
* Encode a frame in legacy format (no format byte, JSON only).
|
|
38
|
+
* Used for backwards compatibility with older clients.
|
|
39
|
+
*/
|
|
40
|
+
export declare function encodeFrameLegacy(envelope: Envelope): Buffer;
|
|
41
|
+
/**
|
|
42
|
+
* Ring buffer-based frame parser for streaming data.
|
|
43
|
+
*/
|
|
44
|
+
export declare class FrameParser {
|
|
45
|
+
private ring;
|
|
46
|
+
private head;
|
|
47
|
+
private tail;
|
|
48
|
+
private readonly capacity;
|
|
49
|
+
private readonly maxFrameBytes;
|
|
50
|
+
private format;
|
|
51
|
+
private legacyMode;
|
|
52
|
+
constructor(maxFrameBytes?: number);
|
|
53
|
+
/**
|
|
54
|
+
* Set the expected wire format for parsing.
|
|
55
|
+
*/
|
|
56
|
+
setFormat(format: WireFormat): void;
|
|
57
|
+
/**
|
|
58
|
+
* Enable legacy mode (4-byte header, JSON only).
|
|
59
|
+
*/
|
|
60
|
+
setLegacyMode(legacy: boolean): void;
|
|
61
|
+
/**
|
|
62
|
+
* Get current unread bytes in buffer.
|
|
63
|
+
*/
|
|
64
|
+
get pendingBytes(): number;
|
|
65
|
+
/**
|
|
66
|
+
* Push data into the parser and extract complete frames.
|
|
67
|
+
*
|
|
68
|
+
* @param data - Incoming data buffer
|
|
69
|
+
* @returns Array of parsed envelope frames
|
|
70
|
+
*/
|
|
71
|
+
push(data: Buffer): Envelope[];
|
|
72
|
+
private extractFrames;
|
|
73
|
+
private decodePayload;
|
|
74
|
+
private compact;
|
|
75
|
+
/**
|
|
76
|
+
* Reset parser state.
|
|
77
|
+
*/
|
|
78
|
+
reset(): void;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=framing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framing.d.ts","sourceRoot":"","sources":["../src/framing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,eAAO,MAAM,eAAe,QAAc,CAAC;AAC3C,eAAO,MAAM,WAAW,IAAI,CAAC;AAC7B,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;AAS5C;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAgBxD;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAExC;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAE,UAAmB,GAAG,MAAM,CAsBnF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAY5D;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,UAAU,CAAS;gBAEf,aAAa,GAAE,MAAwB;IAMnD;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAInC;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAIpC;;OAEG;IACH,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED;;;;;OAKG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE;IAiB9B,OAAO,CAAC,aAAa;IA8CrB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,OAAO;IAWf;;OAEG;IACH,KAAK,IAAI,IAAI;CAId"}
|
package/dist/framing.js
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frame encoding/decoding for the Agent Relay protocol.
|
|
3
|
+
* @agent-relay/sdk
|
|
4
|
+
*
|
|
5
|
+
* Wire format:
|
|
6
|
+
* - 1 byte: format indicator (0 = JSON, 1 = MessagePack)
|
|
7
|
+
* - 4 bytes: big-endian payload length
|
|
8
|
+
* - N bytes: payload (JSON or MessagePack encoded)
|
|
9
|
+
*
|
|
10
|
+
* Legacy format (for backwards compatibility):
|
|
11
|
+
* - 4 bytes: big-endian payload length
|
|
12
|
+
* - N bytes: JSON payload
|
|
13
|
+
*/
|
|
14
|
+
export const MAX_FRAME_BYTES = 1024 * 1024; // 1 MiB
|
|
15
|
+
export const HEADER_SIZE = 5; // 1 byte format + 4 bytes length
|
|
16
|
+
export const LEGACY_HEADER_SIZE = 4; // For backwards compatibility
|
|
17
|
+
// Format indicator bytes
|
|
18
|
+
const FORMAT_JSON = 0;
|
|
19
|
+
const FORMAT_MSGPACK = 1;
|
|
20
|
+
// Optional MessagePack - loaded dynamically if available
|
|
21
|
+
let msgpack = null;
|
|
22
|
+
/**
|
|
23
|
+
* Initialize MessagePack support.
|
|
24
|
+
* Install @msgpack/msgpack to enable: npm install @msgpack/msgpack
|
|
25
|
+
*/
|
|
26
|
+
export async function initMessagePack() {
|
|
27
|
+
if (msgpack)
|
|
28
|
+
return true;
|
|
29
|
+
try {
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
31
|
+
const mod = await import('@msgpack/msgpack');
|
|
32
|
+
const encode = mod.encode || mod.default?.encode;
|
|
33
|
+
const decode = mod.decode || mod.default?.decode;
|
|
34
|
+
if (encode && decode) {
|
|
35
|
+
msgpack = { encode, decode };
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Check if MessagePack is available.
|
|
46
|
+
*/
|
|
47
|
+
export function hasMessagePack() {
|
|
48
|
+
return msgpack !== null;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Encode a message envelope into a framed buffer.
|
|
52
|
+
*
|
|
53
|
+
* @param envelope - The envelope to encode
|
|
54
|
+
* @param format - Wire format to use (default: 'json')
|
|
55
|
+
* @returns Framed buffer ready for socket write
|
|
56
|
+
*/
|
|
57
|
+
export function encodeFrame(envelope, format = 'json') {
|
|
58
|
+
let data;
|
|
59
|
+
let formatByte;
|
|
60
|
+
if (format === 'msgpack' && msgpack) {
|
|
61
|
+
const encoded = msgpack.encode(envelope);
|
|
62
|
+
data = Buffer.from(encoded.buffer, encoded.byteOffset, encoded.byteLength);
|
|
63
|
+
formatByte = FORMAT_MSGPACK;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
data = Buffer.from(JSON.stringify(envelope), 'utf-8');
|
|
67
|
+
formatByte = FORMAT_JSON;
|
|
68
|
+
}
|
|
69
|
+
if (data.length > MAX_FRAME_BYTES) {
|
|
70
|
+
throw new Error(`Frame too large: ${data.length} > ${MAX_FRAME_BYTES}`);
|
|
71
|
+
}
|
|
72
|
+
const header = Buffer.alloc(HEADER_SIZE);
|
|
73
|
+
header.writeUInt8(formatByte, 0);
|
|
74
|
+
header.writeUInt32BE(data.length, 1);
|
|
75
|
+
return Buffer.concat([header, data]);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Encode a frame in legacy format (no format byte, JSON only).
|
|
79
|
+
* Used for backwards compatibility with older clients.
|
|
80
|
+
*/
|
|
81
|
+
export function encodeFrameLegacy(envelope) {
|
|
82
|
+
const json = JSON.stringify(envelope);
|
|
83
|
+
const data = Buffer.from(json, 'utf-8');
|
|
84
|
+
if (data.length > MAX_FRAME_BYTES) {
|
|
85
|
+
throw new Error(`Frame too large: ${data.length} > ${MAX_FRAME_BYTES}`);
|
|
86
|
+
}
|
|
87
|
+
const header = Buffer.alloc(LEGACY_HEADER_SIZE);
|
|
88
|
+
header.writeUInt32BE(data.length, 0);
|
|
89
|
+
return Buffer.concat([header, data]);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Ring buffer-based frame parser for streaming data.
|
|
93
|
+
*/
|
|
94
|
+
export class FrameParser {
|
|
95
|
+
ring;
|
|
96
|
+
head = 0;
|
|
97
|
+
tail = 0;
|
|
98
|
+
capacity;
|
|
99
|
+
maxFrameBytes;
|
|
100
|
+
format = 'json';
|
|
101
|
+
legacyMode = false;
|
|
102
|
+
constructor(maxFrameBytes = MAX_FRAME_BYTES) {
|
|
103
|
+
this.maxFrameBytes = maxFrameBytes;
|
|
104
|
+
this.capacity = maxFrameBytes * 2 + HEADER_SIZE;
|
|
105
|
+
this.ring = Buffer.allocUnsafe(this.capacity);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Set the expected wire format for parsing.
|
|
109
|
+
*/
|
|
110
|
+
setFormat(format) {
|
|
111
|
+
this.format = format;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Enable legacy mode (4-byte header, JSON only).
|
|
115
|
+
*/
|
|
116
|
+
setLegacyMode(legacy) {
|
|
117
|
+
this.legacyMode = legacy;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Get current unread bytes in buffer.
|
|
121
|
+
*/
|
|
122
|
+
get pendingBytes() {
|
|
123
|
+
return this.tail - this.head;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Push data into the parser and extract complete frames.
|
|
127
|
+
*
|
|
128
|
+
* @param data - Incoming data buffer
|
|
129
|
+
* @returns Array of parsed envelope frames
|
|
130
|
+
*/
|
|
131
|
+
push(data) {
|
|
132
|
+
const spaceAtEnd = this.capacity - this.tail;
|
|
133
|
+
if (data.length > spaceAtEnd) {
|
|
134
|
+
this.compact();
|
|
135
|
+
if (data.length > this.capacity - this.tail) {
|
|
136
|
+
throw new Error(`Buffer overflow: data ${data.length} exceeds capacity`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
data.copy(this.ring, this.tail);
|
|
140
|
+
this.tail += data.length;
|
|
141
|
+
return this.extractFrames();
|
|
142
|
+
}
|
|
143
|
+
extractFrames() {
|
|
144
|
+
const frames = [];
|
|
145
|
+
const headerSize = this.legacyMode ? LEGACY_HEADER_SIZE : HEADER_SIZE;
|
|
146
|
+
while (this.pendingBytes >= headerSize) {
|
|
147
|
+
let formatByte = FORMAT_JSON;
|
|
148
|
+
let frameLength;
|
|
149
|
+
if (this.legacyMode) {
|
|
150
|
+
frameLength = this.ring.readUInt32BE(this.head);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
formatByte = this.ring.readUInt8(this.head);
|
|
154
|
+
frameLength = this.ring.readUInt32BE(this.head + 1);
|
|
155
|
+
}
|
|
156
|
+
if (frameLength > this.maxFrameBytes) {
|
|
157
|
+
throw new Error(`Frame too large: ${frameLength} > ${this.maxFrameBytes}`);
|
|
158
|
+
}
|
|
159
|
+
const totalLength = headerSize + frameLength;
|
|
160
|
+
if (this.pendingBytes < totalLength) {
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
const payloadStart = this.head + headerSize;
|
|
164
|
+
const payloadEnd = this.head + totalLength;
|
|
165
|
+
let envelope;
|
|
166
|
+
try {
|
|
167
|
+
envelope = this.decodePayload(formatByte, payloadStart, payloadEnd);
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
throw new Error(`Invalid frame payload: ${err}`);
|
|
171
|
+
}
|
|
172
|
+
this.head += totalLength;
|
|
173
|
+
frames.push(envelope);
|
|
174
|
+
}
|
|
175
|
+
if (this.head > this.capacity / 2 && this.pendingBytes < this.capacity / 4) {
|
|
176
|
+
this.compact();
|
|
177
|
+
}
|
|
178
|
+
return frames;
|
|
179
|
+
}
|
|
180
|
+
decodePayload(formatByte, start, end) {
|
|
181
|
+
if (formatByte === FORMAT_MSGPACK && msgpack) {
|
|
182
|
+
return msgpack.decode(this.ring.subarray(start, end));
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
return JSON.parse(this.ring.toString('utf-8', start, end));
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
compact() {
|
|
189
|
+
if (this.head === 0)
|
|
190
|
+
return;
|
|
191
|
+
const unread = this.pendingBytes;
|
|
192
|
+
if (unread > 0) {
|
|
193
|
+
this.ring.copy(this.ring, 0, this.head, this.tail);
|
|
194
|
+
}
|
|
195
|
+
this.head = 0;
|
|
196
|
+
this.tail = unread;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Reset parser state.
|
|
200
|
+
*/
|
|
201
|
+
reset() {
|
|
202
|
+
this.head = 0;
|
|
203
|
+
this.tail = 0;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=framing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"framing.js","sourceRoot":"","sources":["../src/framing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Monotonic ID Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates unique, lexicographically sortable IDs that are faster than UUID v4.
|
|
5
|
+
*
|
|
6
|
+
* Format: <timestamp-base36>-<counter-base36>-<nodeId>
|
|
7
|
+
* Example: "lxyz5g8-0001-7d2a"
|
|
8
|
+
*
|
|
9
|
+
* Properties:
|
|
10
|
+
* - Lexicographically sortable by time
|
|
11
|
+
* - Unique across processes (node prefix)
|
|
12
|
+
* - ~16x faster than UUID v4
|
|
13
|
+
* - Shorter (20-24 chars vs 36 chars)
|
|
14
|
+
*/
|
|
15
|
+
export declare class IdGenerator {
|
|
16
|
+
private counter;
|
|
17
|
+
private readonly prefix;
|
|
18
|
+
private lastTs;
|
|
19
|
+
constructor(nodeId?: string);
|
|
20
|
+
/**
|
|
21
|
+
* Generate a unique, monotonically increasing ID.
|
|
22
|
+
*/
|
|
23
|
+
next(): string;
|
|
24
|
+
/**
|
|
25
|
+
* Generate a short ID (just timestamp + counter, no node prefix).
|
|
26
|
+
* Use when you don't need cross-process uniqueness.
|
|
27
|
+
*/
|
|
28
|
+
short(): string;
|
|
29
|
+
}
|
|
30
|
+
export declare const idGen: IdGenerator;
|
|
31
|
+
/**
|
|
32
|
+
* Generate a unique ID (drop-in replacement for uuid()).
|
|
33
|
+
*/
|
|
34
|
+
export declare function generateId(): string;
|
|
35
|
+
//# sourceMappingURL=id-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"id-generator.d.ts","sourceRoot":"","sources":["../src/id-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,MAAM,CAAK;gBAEP,MAAM,CAAC,EAAE,MAAM;IAK3B;;OAEG;IACH,IAAI,IAAI,MAAM;IAcd;;;OAGG;IACH,KAAK,IAAI,MAAM;CAYhB;AAGD,eAAO,MAAM,KAAK,aAAoB,CAAC;AAEvC;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC"}
|