@camerontaylor/paseo-protocol 0.12.0-fork.1 → 0.13.0-fork.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/addresses.d.ts +6 -0
- package/dist/addresses.js +2 -0
- package/dist/agent-labels.d.ts +4 -0
- package/dist/agent-labels.js +17 -0
- package/dist/agent-message.d.ts +1 -0
- package/dist/agent-message.js +1 -0
- package/dist/binary-frames/demux.d.ts +4 -0
- package/dist/binary-frames/demux.js +5 -0
- package/dist/binary-frames/host-route.d.ts +12 -0
- package/dist/binary-frames/host-route.js +36 -0
- package/dist/binary-frames/index.d.ts +1 -0
- package/dist/binary-frames/index.js +1 -0
- package/dist/client-capabilities.d.ts +1 -0
- package/dist/client-capabilities.js +1 -0
- package/dist/connection-offer.d.ts +2 -0
- package/dist/connection-offer.js +3 -0
- package/dist/daemon-endpoints.js +8 -0
- package/dist/generated/validation/ws-outbound-schema-metadata.d.ts +716 -311
- package/dist/generated/validation/ws-outbound-schema-metadata.js +10 -0
- package/dist/generated/validation/ws-outbound.aot.d.ts +20 -0
- package/dist/generated/validation/ws-outbound.aot.js +116406 -114752
- package/dist/host-target.d.ts +18 -0
- package/dist/host-target.js +118 -0
- package/dist/hosts.d.ts +303 -0
- package/dist/hosts.js +117 -0
- package/dist/messages.d.ts +1961 -307
- package/dist/messages.js +70 -2
- package/dist/paseo-tool-presentation/catalog.d.ts +3 -0
- package/dist/paseo-tool-presentation/catalog.js +1 -0
- package/dist/plugin-registry.d.ts +21 -0
- package/dist/plugin-registry.js +11 -1
- package/dist/schedule/rpc-schemas.d.ts +4 -4
- package/dist/schedule/types.d.ts +1 -1
- package/dist/validation/ws-outbound-envelope.d.ts +445 -70
- package/package.json +5 -1
package/dist/agent-labels.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { AgentAddress } from "./addresses.js";
|
|
2
|
+
export declare const PARENT_SERVER_ID_LABEL = "paseo.parent-server-id";
|
|
1
3
|
export declare const PARENT_AGENT_ID_LABEL = "paseo.parent-agent-id";
|
|
2
4
|
export declare function getOpenAgentTabLabel(clientId: string): string;
|
|
3
5
|
export declare function isOpenAgentTabLabel(label: string): boolean;
|
|
@@ -7,4 +9,6 @@ export interface AgentLabelSource {
|
|
|
7
9
|
export declare function getParentAgentIdFromLabels(labels: Record<string, unknown> | null | undefined): string | null;
|
|
8
10
|
export declare function isDelegatedAgent(agent: AgentLabelSource): boolean;
|
|
9
11
|
export declare function hasOpenAgentTab(labels: Record<string, unknown> | null | undefined): boolean;
|
|
12
|
+
export declare function getParentAddressFromLabels(labels: Record<string, unknown> | null | undefined, serverId: string): AgentAddress | null;
|
|
13
|
+
export declare function parentAddressLabels(parent: AgentAddress): Record<string, string>;
|
|
10
14
|
//# sourceMappingURL=agent-labels.d.ts.map
|
package/dist/agent-labels.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export const PARENT_SERVER_ID_LABEL = "paseo.parent-server-id";
|
|
1
2
|
export const PARENT_AGENT_ID_LABEL = "paseo.parent-agent-id";
|
|
2
3
|
const OPEN_AGENT_TAB_LABEL_PREFIX = "paseo.open-agent-tab.";
|
|
3
4
|
export function getOpenAgentTabLabel(clientId) {
|
|
@@ -18,4 +19,20 @@ export function isDelegatedAgent(agent) {
|
|
|
18
19
|
export function hasOpenAgentTab(labels) {
|
|
19
20
|
return Object.entries(labels ?? {}).some(([label, value]) => isOpenAgentTabLabel(label) && value === "true");
|
|
20
21
|
}
|
|
22
|
+
// Absent parent server label means the same host.
|
|
23
|
+
export function getParentAddressFromLabels(labels, serverId) {
|
|
24
|
+
const agentId = getParentAgentIdFromLabels(labels);
|
|
25
|
+
if (!agentId)
|
|
26
|
+
return null;
|
|
27
|
+
const parentServerId = labels?.[PARENT_SERVER_ID_LABEL];
|
|
28
|
+
return {
|
|
29
|
+
serverId: typeof parentServerId === "string" && parentServerId.trim()
|
|
30
|
+
? parentServerId.trim()
|
|
31
|
+
: serverId,
|
|
32
|
+
agentId,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export function parentAddressLabels(parent) {
|
|
36
|
+
return { [PARENT_AGENT_ID_LABEL]: parent.agentId, [PARENT_SERVER_ID_LABEL]: parent.serverId };
|
|
37
|
+
}
|
|
21
38
|
//# sourceMappingURL=agent-labels.js.map
|
package/dist/agent-message.d.ts
CHANGED
package/dist/agent-message.js
CHANGED
|
@@ -4,6 +4,7 @@ export const AgentMessageSchema = z.object({
|
|
|
4
4
|
event: z.enum(["message", "finished", "errored", "permission-required", "closed"]),
|
|
5
5
|
sender: z.object({
|
|
6
6
|
id: z.string().min(1),
|
|
7
|
+
serverId: z.string().min(1).optional(),
|
|
7
8
|
title: z.string().min(1).optional(),
|
|
8
9
|
}),
|
|
9
10
|
text: z.string(),
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { type HostRouteFrame } from "./host-route.js";
|
|
1
2
|
import { type FileTransferFrame } from "./file-transfer.js";
|
|
2
3
|
import { type TerminalStreamFrame } from "./terminal.js";
|
|
3
4
|
export type BinaryFrame = {
|
|
5
|
+
kind: "host_route";
|
|
6
|
+
frame: HostRouteFrame;
|
|
7
|
+
} | {
|
|
4
8
|
kind: "terminal";
|
|
5
9
|
frame: TerminalStreamFrame;
|
|
6
10
|
} | {
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import { HOST_ROUTE_OPCODE, decodeHostRouteFrame } from "./host-route.js";
|
|
1
2
|
import { decodeFileTransferFrame, FileTransferOpcode, } from "./file-transfer.js";
|
|
2
3
|
import { decodeTerminalStreamFrame, TerminalStreamOpcode, } from "./terminal.js";
|
|
3
4
|
export function decodeBinaryFrame(bytes) {
|
|
4
5
|
switch (bytes[0]) {
|
|
6
|
+
case HOST_ROUTE_OPCODE: {
|
|
7
|
+
const frame = decodeHostRouteFrame(bytes);
|
|
8
|
+
return frame ? { kind: "host_route", frame } : null;
|
|
9
|
+
}
|
|
5
10
|
case TerminalStreamOpcode.Output:
|
|
6
11
|
case TerminalStreamOpcode.Input:
|
|
7
12
|
case TerminalStreamOpcode.Resize:
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Routing adds a bounded header; the enclosed terminal/file frame is never re-encoded. */
|
|
2
|
+
export declare const HOST_ROUTE_OPCODE = 48;
|
|
3
|
+
export declare const MAX_HOST_ROUTE_ID_BYTES = 256;
|
|
4
|
+
export declare const MAX_HOST_ROUTE_HEADER_BYTES: number;
|
|
5
|
+
export declare const MAX_ROUTED_PAYLOAD_BYTES: number;
|
|
6
|
+
export interface HostRouteFrame {
|
|
7
|
+
routeId: string;
|
|
8
|
+
payload: Uint8Array;
|
|
9
|
+
}
|
|
10
|
+
export declare function encodeHostRouteFrame(routeId: string, payload: Uint8Array): Uint8Array;
|
|
11
|
+
export declare function decodeHostRouteFrame(bytes: Uint8Array): HostRouteFrame | null;
|
|
12
|
+
//# sourceMappingURL=host-route.d.ts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { MAX_WEBSOCKET_MESSAGE_BYTES } from "../websocket-message-limit.js";
|
|
2
|
+
/** Routing adds a bounded header; the enclosed terminal/file frame is never re-encoded. */
|
|
3
|
+
export const HOST_ROUTE_OPCODE = 0x30;
|
|
4
|
+
export const MAX_HOST_ROUTE_ID_BYTES = 256;
|
|
5
|
+
export const MAX_HOST_ROUTE_HEADER_BYTES = 3 + MAX_HOST_ROUTE_ID_BYTES;
|
|
6
|
+
export const MAX_ROUTED_PAYLOAD_BYTES = MAX_WEBSOCKET_MESSAGE_BYTES - MAX_HOST_ROUTE_HEADER_BYTES;
|
|
7
|
+
export function encodeHostRouteFrame(routeId, payload) {
|
|
8
|
+
const id = new TextEncoder().encode(routeId);
|
|
9
|
+
if (!id.length || id.length > MAX_HOST_ROUTE_ID_BYTES)
|
|
10
|
+
throw new Error("Invalid host route ID");
|
|
11
|
+
if (payload.byteLength > MAX_ROUTED_PAYLOAD_BYTES)
|
|
12
|
+
throw new Error("Host frame is too large");
|
|
13
|
+
const frame = new Uint8Array(3 + id.length + payload.byteLength);
|
|
14
|
+
frame[0] = HOST_ROUTE_OPCODE;
|
|
15
|
+
new DataView(frame.buffer).setUint16(1, id.length);
|
|
16
|
+
frame.set(id, 3);
|
|
17
|
+
frame.set(payload, 3 + id.length);
|
|
18
|
+
return frame;
|
|
19
|
+
}
|
|
20
|
+
export function decodeHostRouteFrame(bytes) {
|
|
21
|
+
if (bytes[0] !== HOST_ROUTE_OPCODE || bytes.length < 3)
|
|
22
|
+
return null;
|
|
23
|
+
const length = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint16(1);
|
|
24
|
+
if (!length || length > MAX_HOST_ROUTE_ID_BYTES || bytes.length < 3 + length)
|
|
25
|
+
return null;
|
|
26
|
+
if (bytes.length - 3 - length > MAX_ROUTED_PAYLOAD_BYTES)
|
|
27
|
+
return null;
|
|
28
|
+
try {
|
|
29
|
+
const routeId = new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(3, 3 + length));
|
|
30
|
+
return { routeId, payload: bytes.subarray(3 + length) };
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=host-route.js.map
|
|
@@ -16,6 +16,7 @@ export declare const CLIENT_CAPS: {
|
|
|
16
16
|
readonly timelineReplacementInvalidation: "timeline_replacement_invalidation";
|
|
17
17
|
readonly timelineNotifications: "timeline_notifications";
|
|
18
18
|
readonly pluginTimelineItems: "plugin_timeline_items";
|
|
19
|
+
readonly workspaceSetupObservation: "workspace_setup_observation";
|
|
19
20
|
readonly workspaceSetupBlocked: "workspace_setup_blocked";
|
|
20
21
|
readonly durableAgentQueue: "durable_agent_queue";
|
|
21
22
|
readonly durableVoiceInputV1: "durable_voice_input_v1";
|
|
@@ -45,6 +45,7 @@ export const CLIENT_CAPS = {
|
|
|
45
45
|
timelineNotifications: "timeline_notifications",
|
|
46
46
|
// COMPAT(pluginTimelineItems): added in v0.8.0, remove after 2027-03-07 once client floor >= v0.8.0.
|
|
47
47
|
pluginTimelineItems: "plugin_timeline_items",
|
|
48
|
+
workspaceSetupObservation: "workspace_setup_observation",
|
|
48
49
|
// COMPAT(workspaceSetupBlocked): added in v0.8.0, remove after 2027-03-07 once client floor >= v0.8.0.
|
|
49
50
|
workspaceSetupBlocked: "workspace_setup_blocked",
|
|
50
51
|
// COMPAT(durableAgentQueue): fork addition (TM-02). The daemon only mirrors
|
|
@@ -13,6 +13,7 @@ export declare const ConnectionOfferV2Schema: z.ZodObject<{
|
|
|
13
13
|
endpoint: z.ZodString;
|
|
14
14
|
useTls: z.ZodOptional<z.ZodBoolean>;
|
|
15
15
|
}, z.core.$strip>;
|
|
16
|
+
minimumSecurityMode: z.ZodOptional<z.ZodLiteral<"protected">>;
|
|
16
17
|
}, z.core.$strip>;
|
|
17
18
|
export type ConnectionOfferV2 = z.infer<typeof ConnectionOfferV2Schema>;
|
|
18
19
|
export declare const ConnectionOfferSchema: z.ZodObject<{
|
|
@@ -23,6 +24,7 @@ export declare const ConnectionOfferSchema: z.ZodObject<{
|
|
|
23
24
|
endpoint: z.ZodString;
|
|
24
25
|
useTls: z.ZodOptional<z.ZodBoolean>;
|
|
25
26
|
}, z.core.$strip>;
|
|
27
|
+
minimumSecurityMode: z.ZodOptional<z.ZodLiteral<"protected">>;
|
|
26
28
|
}, z.core.$strip>;
|
|
27
29
|
export type ConnectionOffer = ConnectionOfferV2;
|
|
28
30
|
export declare function decodeOfferFragmentPayload(encoded: string): unknown;
|
package/dist/connection-offer.js
CHANGED
|
@@ -13,6 +13,9 @@ export const ConnectionOfferV2Schema = z.object({
|
|
|
13
13
|
endpoint: z.string().min(1),
|
|
14
14
|
useTls: z.boolean().optional(),
|
|
15
15
|
}),
|
|
16
|
+
// COMPAT(relayProtectedSecurity): added in v0.13.0. Present when the daemon requires
|
|
17
|
+
// protected endpoint security; clients pin it before their first handshake.
|
|
18
|
+
minimumSecurityMode: z.literal("protected").optional(),
|
|
16
19
|
});
|
|
17
20
|
export const ConnectionOfferSchema = ConnectionOfferV2Schema;
|
|
18
21
|
function decodeBase64UrlToUtf8(input) {
|
package/dist/daemon-endpoints.js
CHANGED
|
@@ -21,12 +21,17 @@ export function parseRelayConnectionUri(input) {
|
|
|
21
21
|
}
|
|
22
22
|
const endpoint = normalizeHostPort(url.host);
|
|
23
23
|
const password = url.searchParams.get("password") || undefined;
|
|
24
|
+
const security = url.searchParams.get("security");
|
|
25
|
+
if (security !== null && security !== "protected") {
|
|
26
|
+
throw new Error("Relay connection URI has an unsupported security mode");
|
|
27
|
+
}
|
|
24
28
|
return {
|
|
25
29
|
offer: {
|
|
26
30
|
v: 2,
|
|
27
31
|
serverId,
|
|
28
32
|
daemonPublicKeyB64: key,
|
|
29
33
|
relay: { endpoint, useTls: url.searchParams.get("ssl") === "true" },
|
|
34
|
+
...(security === "protected" ? { minimumSecurityMode: "protected" } : {}),
|
|
30
35
|
},
|
|
31
36
|
...(password ? { password } : {}),
|
|
32
37
|
};
|
|
@@ -36,6 +41,9 @@ export function serializeRelayConnectionUri(parts) {
|
|
|
36
41
|
url.searchParams.set("key", parts.offer.daemonPublicKeyB64);
|
|
37
42
|
if (parts.offer.relay.useTls)
|
|
38
43
|
url.searchParams.set("ssl", "true");
|
|
44
|
+
if (parts.offer.minimumSecurityMode) {
|
|
45
|
+
url.searchParams.set("security", parts.offer.minimumSecurityMode);
|
|
46
|
+
}
|
|
39
47
|
if (parts.password)
|
|
40
48
|
url.searchParams.set("password", parts.password);
|
|
41
49
|
return url.toString();
|