@termlink/protocol 0.1.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/LICENSE +21 -0
- package/README.md +8 -0
- package/dist/commands.d.ts +997 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +96 -0
- package/dist/commands.js.map +1 -0
- package/dist/common.d.ts +109 -0
- package/dist/common.d.ts.map +1 -0
- package/dist/common.js +76 -0
- package/dist/common.js.map +1 -0
- package/dist/events.d.ts +1268 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +98 -0
- package/dist/events.js.map +1 -0
- package/dist/frames.d.ts +49 -0
- package/dist/frames.d.ts.map +1 -0
- package/dist/frames.js +143 -0
- package/dist/frames.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/input.d.ts +91 -0
- package/dist/input.d.ts.map +1 -0
- package/dist/input.js +42 -0
- package/dist/input.js.map +1 -0
- package/dist/items.d.ts +224 -0
- package/dist/items.d.ts.map +1 -0
- package/dist/items.js +76 -0
- package/dist/items.js.map +1 -0
- package/package.json +34 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"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"}
|
package/dist/events.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { HostInfo, PROTOCOL_VERSION, SessionInfo, TerminalSize } from "./common.js";
|
|
3
|
+
import { DecisionEffect, InputRequest } from "./input.js";
|
|
4
|
+
import { DeltaField, Item } from "./items.js";
|
|
5
|
+
const event = (type, payload) => z.object({
|
|
6
|
+
v: z.literal(PROTOCOL_VERSION),
|
|
7
|
+
kind: z.literal("evt"),
|
|
8
|
+
type: z.literal(type),
|
|
9
|
+
ts: z.number(),
|
|
10
|
+
sessionId: z.string().optional(),
|
|
11
|
+
/** Present only on durable session events; increases by one per session. */
|
|
12
|
+
seq: z.number().int().positive().optional(),
|
|
13
|
+
payload,
|
|
14
|
+
});
|
|
15
|
+
export const Usage = z.object({
|
|
16
|
+
inputTokens: z.number().int(),
|
|
17
|
+
outputTokens: z.number().int(),
|
|
18
|
+
costUsd: z.number().optional(),
|
|
19
|
+
});
|
|
20
|
+
// Host channel: delivered to every connection, never sequenced.
|
|
21
|
+
export const HostReadyEvent = event("host.ready", HostInfo);
|
|
22
|
+
export const SessionCreatedEvent = event("session.created", z.object({ session: SessionInfo }));
|
|
23
|
+
export const SessionUpdatedEvent = event("session.updated", z.object({ session: SessionInfo }));
|
|
24
|
+
export const SessionClosedEvent = event("session.closed", z.object({
|
|
25
|
+
session: SessionInfo,
|
|
26
|
+
reason: z.string().nullable(),
|
|
27
|
+
/** Terminal sessions: how the shell exited. Null when it was killed. */
|
|
28
|
+
exitCode: z.number().int().nullable().optional(),
|
|
29
|
+
}));
|
|
30
|
+
// Session channel: delivered to connections attached to the session.
|
|
31
|
+
export const TurnStartedEvent = event("turn.started", z.object({
|
|
32
|
+
turnId: z.string(),
|
|
33
|
+
/** The user message item that opened this turn. It arrives just before, with turnId null. */
|
|
34
|
+
userItemId: z.string().optional(),
|
|
35
|
+
}));
|
|
36
|
+
export const TurnCompletedEvent = event("turn.completed", z.object({
|
|
37
|
+
turnId: z.string(),
|
|
38
|
+
status: z.enum(["completed", "interrupted", "failed"]),
|
|
39
|
+
usage: Usage.optional(),
|
|
40
|
+
error: z.string().optional(),
|
|
41
|
+
}));
|
|
42
|
+
export const ItemStartedEvent = event("item.started", z.object({ turnId: z.string().nullable(), item: Item }));
|
|
43
|
+
export const ItemDeltaEvent = event("item.delta", z.object({ itemId: z.string(), field: DeltaField, delta: z.string() }));
|
|
44
|
+
/** Full snapshot of an item still in progress. Used for catch-up after attach. */
|
|
45
|
+
export const ItemUpdatedEvent = event("item.updated", z.object({ item: Item }));
|
|
46
|
+
/** Final, authoritative state of an item. May arrive without a matching item.started. */
|
|
47
|
+
export const ItemCompletedEvent = event("item.completed", z.object({ turnId: z.string().nullable(), item: Item }));
|
|
48
|
+
export const InputRequiredEvent = event("input.required", z.object({ request: InputRequest }));
|
|
49
|
+
export const InputResolvedEvent = event("input.resolved", z.object({
|
|
50
|
+
requestId: z.string(),
|
|
51
|
+
decisionId: z.string().nullable(),
|
|
52
|
+
effect: DecisionEffect,
|
|
53
|
+
by: z.enum(["user", "policy", "host"]),
|
|
54
|
+
}));
|
|
55
|
+
export const ErrorEvent = event("error", z.object({ code: z.string(), message: z.string() }));
|
|
56
|
+
/** Provider-specific data with no common shape yet. Clients may ignore it. */
|
|
57
|
+
export const ProviderEvent = event("provider.event", z.object({ name: z.string(), data: z.unknown() }));
|
|
58
|
+
// Terminal channel: delivered to connections attached to a terminal session. Never sequenced.
|
|
59
|
+
/** The PTY size changed. */
|
|
60
|
+
export const TerminalSizeEvent = event("terminal.size", TerminalSize);
|
|
61
|
+
/**
|
|
62
|
+
* Clear your terminal: the whole screen follows as output bytes. Sent to everyone
|
|
63
|
+
* attached when a client attaches, since the relay cannot address one client.
|
|
64
|
+
*/
|
|
65
|
+
export const TerminalResetEvent = event("terminal.reset", TerminalSize);
|
|
66
|
+
export const AgentEvent = z.discriminatedUnion("type", [
|
|
67
|
+
HostReadyEvent,
|
|
68
|
+
SessionCreatedEvent,
|
|
69
|
+
SessionUpdatedEvent,
|
|
70
|
+
SessionClosedEvent,
|
|
71
|
+
TurnStartedEvent,
|
|
72
|
+
TurnCompletedEvent,
|
|
73
|
+
ItemStartedEvent,
|
|
74
|
+
ItemDeltaEvent,
|
|
75
|
+
ItemUpdatedEvent,
|
|
76
|
+
ItemCompletedEvent,
|
|
77
|
+
InputRequiredEvent,
|
|
78
|
+
InputResolvedEvent,
|
|
79
|
+
ErrorEvent,
|
|
80
|
+
ProviderEvent,
|
|
81
|
+
TerminalSizeEvent,
|
|
82
|
+
TerminalResetEvent,
|
|
83
|
+
]);
|
|
84
|
+
/** Session events that get a seq and are kept for replay. Everything else is ephemeral. */
|
|
85
|
+
export const DURABLE_EVENT_TYPES = [
|
|
86
|
+
"turn.started",
|
|
87
|
+
"turn.completed",
|
|
88
|
+
"item.started",
|
|
89
|
+
"item.completed",
|
|
90
|
+
"input.required",
|
|
91
|
+
"input.resolved",
|
|
92
|
+
"error",
|
|
93
|
+
];
|
|
94
|
+
const durable = new Set(DURABLE_EVENT_TYPES);
|
|
95
|
+
export function isDurableEvent(type) {
|
|
96
|
+
return durable.has(type);
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,KAAK,GAAG,CAAwC,IAAO,EAAE,OAAU,EAAE,EAAE,CAC3E,CAAC,CAAC,MAAM,CAAC;IACP,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC;IAC9B,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;IACtB,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;IACrB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,4EAA4E;IAC5E,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC3C,OAAO;CACR,CAAC,CAAC;AAEL,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IAC7B,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IAC9B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC/B,CAAC,CAAC;AAGH,gEAAgE;AAChE,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;AAC5D,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,CAAC,iBAAiB,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;AAChG,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,CAAC,iBAAiB,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;AAChG,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CACrC,gBAAgB,EAChB,CAAC,CAAC,MAAM,CAAC;IACP,OAAO,EAAE,WAAW;IACpB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,wEAAwE;IACxE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CACjD,CAAC,CACH,CAAC;AAEF,qEAAqE;AACrE,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CACnC,cAAc,EACd,CAAC,CAAC,MAAM,CAAC;IACP,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,6FAA6F;IAC7F,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClC,CAAC,CACH,CAAC;AACF,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CACrC,gBAAgB,EAChB,CAAC,CAAC,MAAM,CAAC;IACP,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;IACtD,KAAK,EAAE,KAAK,CAAC,QAAQ,EAAE;IACvB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC7B,CAAC,CACH,CAAC;AACF,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CACnC,cAAc,EACd,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CACxD,CAAC;AACF,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CACjC,YAAY,EACZ,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CACvE,CAAC;AACF,kFAAkF;AAClF,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAChF,yFAAyF;AACzF,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CACrC,gBAAgB,EAChB,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CACxD,CAAC;AACF,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;AAC/F,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CACrC,gBAAgB,EAChB,CAAC,CAAC,MAAM,CAAC;IACP,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,MAAM,EAAE,cAAc;IACtB,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;CACvC,CAAC,CACH,CAAC;AACF,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;AAC9F,8EAA8E;AAC9E,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAExG,8FAA8F;AAC9F,4BAA4B;AAC5B,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;AACtE;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CAAC,gBAAgB,EAAE,YAAY,CAAC,CAAC;AAExE,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IACrD,cAAc;IACd,mBAAmB;IACnB,mBAAmB;IACnB,kBAAkB;IAClB,gBAAgB;IAChB,kBAAkB;IAClB,gBAAgB;IAChB,cAAc;IACd,gBAAgB;IAChB,kBAAkB;IAClB,kBAAkB;IAClB,kBAAkB;IAClB,UAAU;IACV,aAAa;IACb,iBAAiB;IACjB,kBAAkB;CACnB,CAAC,CAAC;AAMH,2FAA2F;AAC3F,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,cAAc;IACd,gBAAgB;IAChB,cAAc;IACd,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,OAAO;CACgC,CAAC;AAE1C,MAAM,OAAO,GAAG,IAAI,GAAG,CAAS,mBAAmB,CAAC,CAAC;AAErD,MAAM,UAAU,cAAc,CAAC,IAAe;IAC5C,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC"}
|
package/dist/frames.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* One piece of a message too large for a single transport frame. The TermLink relay
|
|
4
|
+
* caps frames at 64 KiB, so both sides split larger messages and reassemble them.
|
|
5
|
+
* `data` pieces concatenated in index order are the original message's JSON text.
|
|
6
|
+
*/
|
|
7
|
+
export declare const Chunk: z.ZodObject<{
|
|
8
|
+
v: z.ZodLiteral<1>;
|
|
9
|
+
kind: z.ZodLiteral<"chunk">;
|
|
10
|
+
id: z.ZodString;
|
|
11
|
+
index: z.ZodNumber;
|
|
12
|
+
total: z.ZodNumber;
|
|
13
|
+
data: z.ZodString;
|
|
14
|
+
}, z.core.$strip>;
|
|
15
|
+
export type Chunk = z.infer<typeof Chunk>;
|
|
16
|
+
/** Frame limit that fits under the relay's 64 KiB with room to spare. */
|
|
17
|
+
export declare const RELAY_FRAME_BYTES: number;
|
|
18
|
+
/** Serializes a message into one or more text frames, each at most `maxBytes` of UTF-8. */
|
|
19
|
+
export declare function encodeFrames(message: unknown, maxBytes: number, makeId: () => string): string[];
|
|
20
|
+
/**
|
|
21
|
+
* Reassembles chunked messages. push() returns the parsed message once a frame
|
|
22
|
+
* completes one (a whole message completes immediately), or undefined while
|
|
23
|
+
* pieces are still missing. Incomplete messages are dropped after `timeoutMs`.
|
|
24
|
+
*/
|
|
25
|
+
export declare class FrameAssembler {
|
|
26
|
+
#private;
|
|
27
|
+
constructor(options?: {
|
|
28
|
+
maxMessageBytes?: number;
|
|
29
|
+
timeoutMs?: number;
|
|
30
|
+
});
|
|
31
|
+
/** Throws on a frame that is not JSON or a message that grows past the size limit. */
|
|
32
|
+
push(frame: string, now?: number): unknown;
|
|
33
|
+
}
|
|
34
|
+
export declare const TERMINAL_FRAME_OUTPUT: 1;
|
|
35
|
+
export declare const TERMINAL_FRAME_INPUT: 2;
|
|
36
|
+
export type TerminalFrameKind = typeof TERMINAL_FRAME_OUTPUT | typeof TERMINAL_FRAME_INPUT;
|
|
37
|
+
export interface TerminalFrame {
|
|
38
|
+
kind: TerminalFrameKind;
|
|
39
|
+
sessionId: string;
|
|
40
|
+
payload: Uint8Array;
|
|
41
|
+
}
|
|
42
|
+
/** Largest payload per frame: the relay's limit less the header and some room. */
|
|
43
|
+
export declare const TERMINAL_FRAME_PAYLOAD_BYTES: number;
|
|
44
|
+
export declare function encodeTerminalFrame(kind: TerminalFrameKind, sessionId: string, payload: Uint8Array): Uint8Array;
|
|
45
|
+
/** Returns null for anything that is not a terminal frame. */
|
|
46
|
+
export declare function decodeTerminalFrame(data: Uint8Array): TerminalFrame | null;
|
|
47
|
+
/** Splits a byte run into frames that each fit under the relay's frame limit. */
|
|
48
|
+
export declare function encodeTerminalFrames(kind: TerminalFrameKind, sessionId: string, payload: Uint8Array, maxPayloadBytes?: number): Uint8Array[];
|
|
49
|
+
//# sourceMappingURL=frames.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frames.d.ts","sourceRoot":"","sources":["../src/frames.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;GAIG;AACH,eAAO,MAAM,KAAK;;;;;;;iBAOhB,CAAC;AACH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,KAAK,CAAC,CAAC;AAE1C,yEAAyE;AACzE,eAAO,MAAM,iBAAiB,QAAY,CAAC;AAS3C,2FAA2F;AAC3F,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,MAAM,GAAG,MAAM,EAAE,CA0B/F;AASD;;;;GAIG;AACH,qBAAa,cAAc;;IAKzB,YAAY,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAO,EAGzE;IAED,sFAAsF;IACtF,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,OAAO,CAuB7C;CAOF;AAWD,eAAO,MAAM,qBAAqB,EAAG,CAAU,CAAC;AAChD,eAAO,MAAM,oBAAoB,EAAG,CAAU,CAAC;AAC/C,MAAM,MAAM,iBAAiB,GAAG,OAAO,qBAAqB,GAAG,OAAO,oBAAoB,CAAC;AAE3F,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,iBAAiB,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,UAAU,CAAC;CACrB;AAED,kFAAkF;AAClF,eAAO,MAAM,4BAA4B,QAA0B,CAAC;AAIpE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,UAAU,CAS/G;AAED,8DAA8D;AAC9D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,GAAG,aAAa,GAAG,IAAI,CAO1E;AAED,iFAAiF;AACjF,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,iBAAiB,EACvB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,UAAU,EACnB,eAAe,SAA+B,GAC7C,UAAU,EAAE,CAOd"}
|
package/dist/frames.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { PROTOCOL_VERSION } from "./common.js";
|
|
3
|
+
/**
|
|
4
|
+
* One piece of a message too large for a single transport frame. The TermLink relay
|
|
5
|
+
* caps frames at 64 KiB, so both sides split larger messages and reassemble them.
|
|
6
|
+
* `data` pieces concatenated in index order are the original message's JSON text.
|
|
7
|
+
*/
|
|
8
|
+
export const Chunk = z.object({
|
|
9
|
+
v: z.literal(PROTOCOL_VERSION),
|
|
10
|
+
kind: z.literal("chunk"),
|
|
11
|
+
id: z.string().min(1).max(64),
|
|
12
|
+
index: z.number().int().min(0),
|
|
13
|
+
total: z.number().int().min(1).max(100_000),
|
|
14
|
+
data: z.string(),
|
|
15
|
+
});
|
|
16
|
+
/** Frame limit that fits under the relay's 64 KiB with room to spare. */
|
|
17
|
+
export const RELAY_FRAME_BYTES = 60 * 1024;
|
|
18
|
+
const encoder = new TextEncoder();
|
|
19
|
+
const byteLength = (text) => encoder.encode(text).length;
|
|
20
|
+
function isHighSurrogate(code) {
|
|
21
|
+
return code >= 0xd800 && code <= 0xdbff;
|
|
22
|
+
}
|
|
23
|
+
/** Serializes a message into one or more text frames, each at most `maxBytes` of UTF-8. */
|
|
24
|
+
export function encodeFrames(message, maxBytes, makeId) {
|
|
25
|
+
const json = JSON.stringify(message);
|
|
26
|
+
if (byteLength(json) <= maxBytes)
|
|
27
|
+
return [json];
|
|
28
|
+
const id = makeId();
|
|
29
|
+
// Frame overhead besides `data`, with room for the index and total digits.
|
|
30
|
+
const overhead = byteLength(JSON.stringify({ v: PROTOCOL_VERSION, kind: "chunk", id, index: 0, total: 0, data: "" })) + 16;
|
|
31
|
+
const budget = maxBytes - overhead;
|
|
32
|
+
if (budget < 64)
|
|
33
|
+
throw new Error(`frame limit ${maxBytes} is too small`);
|
|
34
|
+
const parts = [];
|
|
35
|
+
let rest = json;
|
|
36
|
+
while (rest.length > 0) {
|
|
37
|
+
let size = Math.min(rest.length, budget);
|
|
38
|
+
for (;;) {
|
|
39
|
+
// Never split a surrogate pair across frames.
|
|
40
|
+
if (size < rest.length && isHighSurrogate(rest.charCodeAt(size - 1)))
|
|
41
|
+
size--;
|
|
42
|
+
if (byteLength(JSON.stringify(rest.slice(0, size))) <= budget || size <= 1)
|
|
43
|
+
break;
|
|
44
|
+
size = Math.floor(size / 2);
|
|
45
|
+
}
|
|
46
|
+
parts.push(rest.slice(0, size));
|
|
47
|
+
rest = rest.slice(size);
|
|
48
|
+
}
|
|
49
|
+
return parts.map((data, index) => JSON.stringify({ v: PROTOCOL_VERSION, kind: "chunk", id, index, total: parts.length, data }));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Reassembles chunked messages. push() returns the parsed message once a frame
|
|
53
|
+
* completes one (a whole message completes immediately), or undefined while
|
|
54
|
+
* pieces are still missing. Incomplete messages are dropped after `timeoutMs`.
|
|
55
|
+
*/
|
|
56
|
+
export class FrameAssembler {
|
|
57
|
+
#pending = new Map();
|
|
58
|
+
#maxMessageBytes;
|
|
59
|
+
#timeoutMs;
|
|
60
|
+
constructor(options = {}) {
|
|
61
|
+
this.#maxMessageBytes = options.maxMessageBytes ?? 16 * 1024 * 1024;
|
|
62
|
+
this.#timeoutMs = options.timeoutMs ?? 60_000;
|
|
63
|
+
}
|
|
64
|
+
/** Throws on a frame that is not JSON or a message that grows past the size limit. */
|
|
65
|
+
push(frame, now = Date.now()) {
|
|
66
|
+
const data = JSON.parse(frame);
|
|
67
|
+
const chunk = Chunk.safeParse(data);
|
|
68
|
+
if (!chunk.success)
|
|
69
|
+
return data;
|
|
70
|
+
this.#expire(now);
|
|
71
|
+
const { id, index, total, data: piece } = chunk.data;
|
|
72
|
+
let pending = this.#pending.get(id);
|
|
73
|
+
if (!pending) {
|
|
74
|
+
pending = { parts: new Array(total), received: 0, bytes: 0, startedAt: now };
|
|
75
|
+
this.#pending.set(id, pending);
|
|
76
|
+
}
|
|
77
|
+
if (index >= pending.parts.length || pending.parts[index] !== undefined)
|
|
78
|
+
return undefined;
|
|
79
|
+
pending.parts[index] = piece;
|
|
80
|
+
pending.received++;
|
|
81
|
+
pending.bytes += piece.length;
|
|
82
|
+
if (pending.bytes > this.#maxMessageBytes) {
|
|
83
|
+
this.#pending.delete(id);
|
|
84
|
+
throw new Error(`chunked message ${id} exceeds ${this.#maxMessageBytes} bytes`);
|
|
85
|
+
}
|
|
86
|
+
if (pending.received < pending.parts.length)
|
|
87
|
+
return undefined;
|
|
88
|
+
this.#pending.delete(id);
|
|
89
|
+
return JSON.parse(pending.parts.join(""));
|
|
90
|
+
}
|
|
91
|
+
#expire(now) {
|
|
92
|
+
for (const [id, pending] of this.#pending) {
|
|
93
|
+
if (now - pending.startedAt > this.#timeoutMs)
|
|
94
|
+
this.#pending.delete(id);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Terminal bytes travel in WebSocket binary frames, not in JSON, so nothing is base64
|
|
99
|
+
// encoded or parsed on the way. Every frame names its session, because the relay merges
|
|
100
|
+
// all clients into one host socket and no per-connection numbering is possible.
|
|
101
|
+
//
|
|
102
|
+
// byte 0 kind: 1 = output (host -> client), 2 = input (client -> host)
|
|
103
|
+
// byte 1 length n of the session id
|
|
104
|
+
// byte 2.. session id, n ASCII bytes
|
|
105
|
+
// the rest PTY bytes as they are
|
|
106
|
+
export const TERMINAL_FRAME_OUTPUT = 1;
|
|
107
|
+
export const TERMINAL_FRAME_INPUT = 2;
|
|
108
|
+
/** Largest payload per frame: the relay's limit less the header and some room. */
|
|
109
|
+
export const TERMINAL_FRAME_PAYLOAD_BYTES = RELAY_FRAME_BYTES - 128;
|
|
110
|
+
const TERMINAL_FRAME_KINDS = [TERMINAL_FRAME_OUTPUT, TERMINAL_FRAME_INPUT];
|
|
111
|
+
export function encodeTerminalFrame(kind, sessionId, payload) {
|
|
112
|
+
const id = encoder.encode(sessionId);
|
|
113
|
+
if (id.length === 0 || id.length > 255)
|
|
114
|
+
throw new Error(`session id is ${id.length} bytes; 1-255 allowed`);
|
|
115
|
+
const frame = new Uint8Array(2 + id.length + payload.length);
|
|
116
|
+
frame[0] = kind;
|
|
117
|
+
frame[1] = id.length;
|
|
118
|
+
frame.set(id, 2);
|
|
119
|
+
frame.set(payload, 2 + id.length);
|
|
120
|
+
return frame;
|
|
121
|
+
}
|
|
122
|
+
/** Returns null for anything that is not a terminal frame. */
|
|
123
|
+
export function decodeTerminalFrame(data) {
|
|
124
|
+
if (data.length < 3)
|
|
125
|
+
return null;
|
|
126
|
+
const kind = data[0] ?? 0;
|
|
127
|
+
const idLength = data[1] ?? 0;
|
|
128
|
+
if (!TERMINAL_FRAME_KINDS.includes(kind) || idLength === 0 || data.length < 2 + idLength)
|
|
129
|
+
return null;
|
|
130
|
+
const sessionId = new TextDecoder().decode(data.subarray(2, 2 + idLength));
|
|
131
|
+
return { kind: kind, sessionId, payload: data.subarray(2 + idLength) };
|
|
132
|
+
}
|
|
133
|
+
/** Splits a byte run into frames that each fit under the relay's frame limit. */
|
|
134
|
+
export function encodeTerminalFrames(kind, sessionId, payload, maxPayloadBytes = TERMINAL_FRAME_PAYLOAD_BYTES) {
|
|
135
|
+
if (payload.length <= maxPayloadBytes)
|
|
136
|
+
return [encodeTerminalFrame(kind, sessionId, payload)];
|
|
137
|
+
const frames = [];
|
|
138
|
+
for (let offset = 0; offset < payload.length; offset += maxPayloadBytes) {
|
|
139
|
+
frames.push(encodeTerminalFrame(kind, sessionId, payload.subarray(offset, offset + maxPayloadBytes)));
|
|
140
|
+
}
|
|
141
|
+
return frames;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=frames.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frames.js","sourceRoot":"","sources":["../src/frames.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC"}
|
package/dist/input.d.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** What a decision does. The host maps it back to the provider's own vocabulary. */
|
|
3
|
+
export declare const DecisionEffect: z.ZodEnum<{
|
|
4
|
+
allow: "allow";
|
|
5
|
+
allow_session: "allow_session";
|
|
6
|
+
cancel: "cancel";
|
|
7
|
+
deny: "deny";
|
|
8
|
+
}>;
|
|
9
|
+
export type DecisionEffect = z.infer<typeof DecisionEffect>;
|
|
10
|
+
export declare const Decision: z.ZodObject<{
|
|
11
|
+
id: z.ZodString;
|
|
12
|
+
label: z.ZodString;
|
|
13
|
+
effect: z.ZodEnum<{
|
|
14
|
+
allow: "allow";
|
|
15
|
+
allow_session: "allow_session";
|
|
16
|
+
cancel: "cancel";
|
|
17
|
+
deny: "deny";
|
|
18
|
+
}>;
|
|
19
|
+
}, z.core.$strip>;
|
|
20
|
+
export type Decision = z.infer<typeof Decision>;
|
|
21
|
+
export declare const Question: z.ZodObject<{
|
|
22
|
+
id: z.ZodString;
|
|
23
|
+
question: z.ZodString;
|
|
24
|
+
options: z.ZodArray<z.ZodObject<{
|
|
25
|
+
label: z.ZodString;
|
|
26
|
+
description: z.ZodOptional<z.ZodString>;
|
|
27
|
+
}, z.core.$strip>>;
|
|
28
|
+
multiSelect: z.ZodBoolean;
|
|
29
|
+
}, z.core.$strip>;
|
|
30
|
+
export type Question = z.infer<typeof Question>;
|
|
31
|
+
export declare const InputKind: z.ZodEnum<{
|
|
32
|
+
command_approval: "command_approval";
|
|
33
|
+
file_approval: "file_approval";
|
|
34
|
+
plan_approval: "plan_approval";
|
|
35
|
+
question: "question";
|
|
36
|
+
tool_approval: "tool_approval";
|
|
37
|
+
}>;
|
|
38
|
+
export type InputKind = z.infer<typeof InputKind>;
|
|
39
|
+
/**
|
|
40
|
+
* Anything that blocks a turn until a person answers. The host decides which
|
|
41
|
+
* decisions exist; clients render them and reply with a decisionId.
|
|
42
|
+
*/
|
|
43
|
+
export declare const InputRequest: z.ZodObject<{
|
|
44
|
+
requestId: z.ZodString;
|
|
45
|
+
kind: z.ZodEnum<{
|
|
46
|
+
command_approval: "command_approval";
|
|
47
|
+
file_approval: "file_approval";
|
|
48
|
+
plan_approval: "plan_approval";
|
|
49
|
+
question: "question";
|
|
50
|
+
tool_approval: "tool_approval";
|
|
51
|
+
}>;
|
|
52
|
+
itemId: z.ZodOptional<z.ZodString>;
|
|
53
|
+
title: z.ZodString;
|
|
54
|
+
body: z.ZodOptional<z.ZodString>;
|
|
55
|
+
command: z.ZodOptional<z.ZodString>;
|
|
56
|
+
cwd: z.ZodOptional<z.ZodString>;
|
|
57
|
+
changes: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
58
|
+
path: z.ZodString;
|
|
59
|
+
action: z.ZodEnum<{
|
|
60
|
+
add: "add";
|
|
61
|
+
delete: "delete";
|
|
62
|
+
modify: "modify";
|
|
63
|
+
rename: "rename";
|
|
64
|
+
}>;
|
|
65
|
+
movePath: z.ZodOptional<z.ZodString>;
|
|
66
|
+
diff: z.ZodOptional<z.ZodString>;
|
|
67
|
+
}, z.core.$strip>>>;
|
|
68
|
+
toolName: z.ZodOptional<z.ZodString>;
|
|
69
|
+
toolInput: z.ZodOptional<z.ZodUnknown>;
|
|
70
|
+
questions: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
71
|
+
id: z.ZodString;
|
|
72
|
+
question: z.ZodString;
|
|
73
|
+
options: z.ZodArray<z.ZodObject<{
|
|
74
|
+
label: z.ZodString;
|
|
75
|
+
description: z.ZodOptional<z.ZodString>;
|
|
76
|
+
}, z.core.$strip>>;
|
|
77
|
+
multiSelect: z.ZodBoolean;
|
|
78
|
+
}, z.core.$strip>>>;
|
|
79
|
+
decisions: z.ZodArray<z.ZodObject<{
|
|
80
|
+
id: z.ZodString;
|
|
81
|
+
label: z.ZodString;
|
|
82
|
+
effect: z.ZodEnum<{
|
|
83
|
+
allow: "allow";
|
|
84
|
+
allow_session: "allow_session";
|
|
85
|
+
cancel: "cancel";
|
|
86
|
+
deny: "deny";
|
|
87
|
+
}>;
|
|
88
|
+
}, z.core.$strip>>;
|
|
89
|
+
}, z.core.$strip>;
|
|
90
|
+
export type InputRequest = z.infer<typeof InputRequest>;
|
|
91
|
+
//# sourceMappingURL=input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../src/input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,oFAAoF;AACpF,eAAO,MAAM,cAAc;;;;;EAAuD,CAAC;AACnF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D,eAAO,MAAM,QAAQ;;;;;;;;;iBAInB,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAC;AAEhD,eAAO,MAAM,QAAQ;;;;;;;;iBAKnB,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAC;AAEhD,eAAO,MAAM,SAAS;;;;;;EAMpB,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AAElD;;;GAGG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAcvB,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC"}
|
package/dist/input.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { FileChange } from "./items.js";
|
|
3
|
+
/** What a decision does. The host maps it back to the provider's own vocabulary. */
|
|
4
|
+
export const DecisionEffect = z.enum(["allow", "allow_session", "deny", "cancel"]);
|
|
5
|
+
export const Decision = z.object({
|
|
6
|
+
id: z.string(),
|
|
7
|
+
label: z.string(),
|
|
8
|
+
effect: DecisionEffect,
|
|
9
|
+
});
|
|
10
|
+
export const Question = z.object({
|
|
11
|
+
id: z.string(),
|
|
12
|
+
question: z.string(),
|
|
13
|
+
options: z.array(z.object({ label: z.string(), description: z.string().optional() })),
|
|
14
|
+
multiSelect: z.boolean(),
|
|
15
|
+
});
|
|
16
|
+
export const InputKind = z.enum([
|
|
17
|
+
"command_approval",
|
|
18
|
+
"file_approval",
|
|
19
|
+
"tool_approval",
|
|
20
|
+
"question",
|
|
21
|
+
"plan_approval",
|
|
22
|
+
]);
|
|
23
|
+
/**
|
|
24
|
+
* Anything that blocks a turn until a person answers. The host decides which
|
|
25
|
+
* decisions exist; clients render them and reply with a decisionId.
|
|
26
|
+
*/
|
|
27
|
+
export const InputRequest = z.object({
|
|
28
|
+
requestId: z.string(),
|
|
29
|
+
kind: InputKind,
|
|
30
|
+
/** The item this request is about, when there is one. */
|
|
31
|
+
itemId: z.string().optional(),
|
|
32
|
+
title: z.string(),
|
|
33
|
+
body: z.string().optional(),
|
|
34
|
+
command: z.string().optional(),
|
|
35
|
+
cwd: z.string().optional(),
|
|
36
|
+
changes: z.array(FileChange).optional(),
|
|
37
|
+
toolName: z.string().optional(),
|
|
38
|
+
toolInput: z.unknown().optional(),
|
|
39
|
+
questions: z.array(Question).optional(),
|
|
40
|
+
decisions: z.array(Decision).min(1),
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.js","sourceRoot":"","sources":["../src/input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,oFAAoF;AACpF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;AAGnF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,MAAM,EAAE,cAAc;CACvB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACrF,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE;CACzB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC;IAC9B,kBAAkB;IAClB,eAAe;IACf,eAAe;IACf,UAAU;IACV,eAAe;CAChB,CAAC,CAAC;AAGH;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,IAAI,EAAE,SAAS;IACf,yDAAyD;IACzD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1B,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,QAAQ,EAAE;IACvC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACjC,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE;IACvC,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;CACpC,CAAC,CAAC"}
|