@agentstorm/platform-protocol 0.2.5
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 +671 -0
- package/README.md +12 -0
- package/dist/agent-attention-notification.d.ts +43 -0
- package/dist/agent-attention-notification.js +141 -0
- package/dist/agent-deep-link.d.ts +8 -0
- package/dist/agent-deep-link.js +49 -0
- package/dist/agent-labels.d.ts +7 -0
- package/dist/agent-labels.js +11 -0
- package/dist/agent-lifecycle.d.ts +3 -0
- package/dist/agent-lifecycle.js +8 -0
- package/dist/agent-state-bucket.d.ts +14 -0
- package/dist/agent-state-bucket.js +41 -0
- package/dist/agent-title-limits.d.ts +2 -0
- package/dist/agent-title-limits.js +2 -0
- package/dist/agent-types.d.ts +451 -0
- package/dist/agent-types.js +22 -0
- package/dist/binary-frames/demux.d.ts +11 -0
- package/dist/binary-frames/demux.js +23 -0
- package/dist/binary-frames/file-transfer.d.ts +51 -0
- package/dist/binary-frames/file-transfer.js +108 -0
- package/dist/binary-frames/index.d.ts +4 -0
- package/dist/binary-frames/index.js +4 -0
- package/dist/binary-frames/terminal.d.ts +35 -0
- package/dist/binary-frames/terminal.js +100 -0
- package/dist/branch-slug.d.ts +14 -0
- package/dist/branch-slug.js +49 -0
- package/dist/browser-automation/capabilities.d.ts +7 -0
- package/dist/browser-automation/capabilities.js +31 -0
- package/dist/browser-automation/rpc-schemas.d.ts +1112 -0
- package/dist/browser-automation/rpc-schemas.js +462 -0
- package/dist/chat/rpc-schemas.d.ts +158 -0
- package/dist/chat/rpc-schemas.js +103 -0
- package/dist/chat/types.d.ts +30 -0
- package/dist/chat/types.js +22 -0
- package/dist/client-capabilities.d.ts +11 -0
- package/dist/client-capabilities.js +25 -0
- package/dist/connection-offer.d.ts +36 -0
- package/dist/connection-offer.js +53 -0
- package/dist/daemon-endpoints.d.ts +47 -0
- package/dist/daemon-endpoints.js +201 -0
- package/dist/error-utils.d.ts +11 -0
- package/dist/error-utils.js +27 -0
- package/dist/forge-manifest.d.ts +66 -0
- package/dist/forge-manifest.js +92 -0
- package/dist/generated/validation/ws-outbound.aot.d.ts +2 -0
- package/dist/generated/validation/ws-outbound.aot.js +65207 -0
- package/dist/git-remote.d.ts +33 -0
- package/dist/git-remote.js +94 -0
- package/dist/host-connection-schema.d.ts +11 -0
- package/dist/host-connection-schema.js +9 -0
- package/dist/literal-union.d.ts +2 -0
- package/dist/literal-union.js +2 -0
- package/dist/loop/rpc-schemas.d.ts +636 -0
- package/dist/loop/rpc-schemas.js +163 -0
- package/dist/messages.d.ts +40580 -0
- package/dist/messages.js +4999 -0
- package/dist/paseo-config-schema.d.ts +138 -0
- package/dist/paseo-config-schema.js +98 -0
- package/dist/path-utils.d.ts +2 -0
- package/dist/path-utils.js +16 -0
- package/dist/provider-config.d.ts +126 -0
- package/dist/provider-config.js +110 -0
- package/dist/provider-icon-names.d.ts +5 -0
- package/dist/provider-icon-names.js +52 -0
- package/dist/provider-manifest.d.ts +35 -0
- package/dist/provider-manifest.js +254 -0
- package/dist/schedule/cadence.d.ts +6 -0
- package/dist/schedule/cadence.js +28 -0
- package/dist/schedule/cron-expression.d.ts +13 -0
- package/dist/schedule/cron-expression.js +97 -0
- package/dist/schedule/rpc-schemas.d.ts +624 -0
- package/dist/schedule/rpc-schemas.js +155 -0
- package/dist/schedule/types.d.ts +222 -0
- package/dist/schedule/types.js +78 -0
- package/dist/terminal-activity.d.ts +21 -0
- package/dist/terminal-activity.js +25 -0
- package/dist/terminal-input-mode.d.ts +30 -0
- package/dist/terminal-input-mode.js +180 -0
- package/dist/terminal-key-input.d.ts +13 -0
- package/dist/terminal-key-input.js +210 -0
- package/dist/terminal-profiles.d.ts +6 -0
- package/dist/terminal-profiles.js +28 -0
- package/dist/terminal-snapshot.d.ts +3 -0
- package/dist/terminal-snapshot.js +178 -0
- package/dist/terminal-stream-protocol.d.ts +2 -0
- package/dist/terminal-stream-protocol.js +2 -0
- package/dist/terminal-subscription-key.d.ts +2 -0
- package/dist/terminal-subscription-key.js +9 -0
- package/dist/tool-call-display.d.ts +11 -0
- package/dist/tool-call-display.js +135 -0
- package/dist/tool-name-normalization.d.ts +9 -0
- package/dist/tool-name-normalization.js +82 -0
- package/dist/validation/ws-outbound-schema-metadata.d.ts +7570 -0
- package/dist/validation/ws-outbound-schema-metadata.js +3 -0
- package/dist/validation/ws-outbound.d.ts +12 -0
- package/dist/validation/ws-outbound.js +8 -0
- package/package.json +32 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { ChatMessageSchema, ChatRoomDetailSchema } from "./types.js";
|
|
3
|
+
export const ChatCreateRequestSchema = z.object({
|
|
4
|
+
type: z.literal("chat/create"),
|
|
5
|
+
requestId: z.string(),
|
|
6
|
+
name: z.string(),
|
|
7
|
+
purpose: z.string().optional(),
|
|
8
|
+
});
|
|
9
|
+
export const ChatListRequestSchema = z.object({
|
|
10
|
+
type: z.literal("chat/list"),
|
|
11
|
+
requestId: z.string(),
|
|
12
|
+
});
|
|
13
|
+
export const ChatInspectRequestSchema = z.object({
|
|
14
|
+
type: z.literal("chat/inspect"),
|
|
15
|
+
requestId: z.string(),
|
|
16
|
+
room: z.string(),
|
|
17
|
+
});
|
|
18
|
+
export const ChatDeleteRequestSchema = z.object({
|
|
19
|
+
type: z.literal("chat/delete"),
|
|
20
|
+
requestId: z.string(),
|
|
21
|
+
room: z.string(),
|
|
22
|
+
});
|
|
23
|
+
export const ChatPostRequestSchema = z.object({
|
|
24
|
+
type: z.literal("chat/post"),
|
|
25
|
+
requestId: z.string(),
|
|
26
|
+
room: z.string(),
|
|
27
|
+
body: z.string(),
|
|
28
|
+
authorAgentId: z.string().optional(),
|
|
29
|
+
replyToMessageId: z.string().optional(),
|
|
30
|
+
});
|
|
31
|
+
export const ChatReadRequestSchema = z.object({
|
|
32
|
+
type: z.literal("chat/read"),
|
|
33
|
+
requestId: z.string(),
|
|
34
|
+
room: z.string(),
|
|
35
|
+
limit: z.number().int().nonnegative().optional(),
|
|
36
|
+
since: z.string().optional(),
|
|
37
|
+
authorAgentId: z.string().optional(),
|
|
38
|
+
});
|
|
39
|
+
export const ChatWaitRequestSchema = z.object({
|
|
40
|
+
type: z.literal("chat/wait"),
|
|
41
|
+
requestId: z.string(),
|
|
42
|
+
room: z.string(),
|
|
43
|
+
afterMessageId: z.string().optional(),
|
|
44
|
+
timeoutMs: z.number().int().nonnegative().optional(),
|
|
45
|
+
});
|
|
46
|
+
export const ChatCreateResponseSchema = z.object({
|
|
47
|
+
type: z.literal("chat/create/response"),
|
|
48
|
+
payload: z.object({
|
|
49
|
+
requestId: z.string(),
|
|
50
|
+
room: ChatRoomDetailSchema.nullable(),
|
|
51
|
+
error: z.string().nullable(),
|
|
52
|
+
}),
|
|
53
|
+
});
|
|
54
|
+
export const ChatListResponseSchema = z.object({
|
|
55
|
+
type: z.literal("chat/list/response"),
|
|
56
|
+
payload: z.object({
|
|
57
|
+
requestId: z.string(),
|
|
58
|
+
rooms: z.array(ChatRoomDetailSchema),
|
|
59
|
+
error: z.string().nullable(),
|
|
60
|
+
}),
|
|
61
|
+
});
|
|
62
|
+
export const ChatInspectResponseSchema = z.object({
|
|
63
|
+
type: z.literal("chat/inspect/response"),
|
|
64
|
+
payload: z.object({
|
|
65
|
+
requestId: z.string(),
|
|
66
|
+
room: ChatRoomDetailSchema.nullable(),
|
|
67
|
+
error: z.string().nullable(),
|
|
68
|
+
}),
|
|
69
|
+
});
|
|
70
|
+
export const ChatDeleteResponseSchema = z.object({
|
|
71
|
+
type: z.literal("chat/delete/response"),
|
|
72
|
+
payload: z.object({
|
|
73
|
+
requestId: z.string(),
|
|
74
|
+
room: ChatRoomDetailSchema.nullable(),
|
|
75
|
+
error: z.string().nullable(),
|
|
76
|
+
}),
|
|
77
|
+
});
|
|
78
|
+
export const ChatPostResponseSchema = z.object({
|
|
79
|
+
type: z.literal("chat/post/response"),
|
|
80
|
+
payload: z.object({
|
|
81
|
+
requestId: z.string(),
|
|
82
|
+
message: ChatMessageSchema.nullable(),
|
|
83
|
+
error: z.string().nullable(),
|
|
84
|
+
}),
|
|
85
|
+
});
|
|
86
|
+
export const ChatReadResponseSchema = z.object({
|
|
87
|
+
type: z.literal("chat/read/response"),
|
|
88
|
+
payload: z.object({
|
|
89
|
+
requestId: z.string(),
|
|
90
|
+
messages: z.array(ChatMessageSchema),
|
|
91
|
+
error: z.string().nullable(),
|
|
92
|
+
}),
|
|
93
|
+
});
|
|
94
|
+
export const ChatWaitResponseSchema = z.object({
|
|
95
|
+
type: z.literal("chat/wait/response"),
|
|
96
|
+
payload: z.object({
|
|
97
|
+
requestId: z.string(),
|
|
98
|
+
messages: z.array(ChatMessageSchema),
|
|
99
|
+
timedOut: z.boolean(),
|
|
100
|
+
error: z.string().nullable(),
|
|
101
|
+
}),
|
|
102
|
+
});
|
|
103
|
+
//# sourceMappingURL=rpc-schemas.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const ChatRoomSchema: z.ZodObject<{
|
|
3
|
+
id: z.ZodString;
|
|
4
|
+
name: z.ZodString;
|
|
5
|
+
purpose: z.ZodNullable<z.ZodString>;
|
|
6
|
+
createdAt: z.ZodString;
|
|
7
|
+
updatedAt: z.ZodString;
|
|
8
|
+
}, z.core.$strip>;
|
|
9
|
+
export type ChatRoom = z.infer<typeof ChatRoomSchema>;
|
|
10
|
+
export declare const ChatMessageSchema: z.ZodObject<{
|
|
11
|
+
id: z.ZodString;
|
|
12
|
+
roomId: z.ZodString;
|
|
13
|
+
authorAgentId: z.ZodString;
|
|
14
|
+
body: z.ZodString;
|
|
15
|
+
replyToMessageId: z.ZodNullable<z.ZodString>;
|
|
16
|
+
mentionAgentIds: z.ZodArray<z.ZodString>;
|
|
17
|
+
createdAt: z.ZodString;
|
|
18
|
+
}, z.core.$strip>;
|
|
19
|
+
export type ChatMessage = z.infer<typeof ChatMessageSchema>;
|
|
20
|
+
export declare const ChatRoomDetailSchema: z.ZodObject<{
|
|
21
|
+
id: z.ZodString;
|
|
22
|
+
name: z.ZodString;
|
|
23
|
+
purpose: z.ZodNullable<z.ZodString>;
|
|
24
|
+
createdAt: z.ZodString;
|
|
25
|
+
updatedAt: z.ZodString;
|
|
26
|
+
messageCount: z.ZodNumber;
|
|
27
|
+
lastMessageAt: z.ZodNullable<z.ZodString>;
|
|
28
|
+
}, z.core.$strip>;
|
|
29
|
+
export type ChatRoomDetail = z.infer<typeof ChatRoomDetailSchema>;
|
|
30
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const ChatRoomSchema = z.object({
|
|
3
|
+
id: z.string(),
|
|
4
|
+
name: z.string(),
|
|
5
|
+
purpose: z.string().nullable(),
|
|
6
|
+
createdAt: z.string(),
|
|
7
|
+
updatedAt: z.string(),
|
|
8
|
+
});
|
|
9
|
+
export const ChatMessageSchema = z.object({
|
|
10
|
+
id: z.string(),
|
|
11
|
+
roomId: z.string(),
|
|
12
|
+
authorAgentId: z.string(),
|
|
13
|
+
body: z.string(),
|
|
14
|
+
replyToMessageId: z.string().nullable(),
|
|
15
|
+
mentionAgentIds: z.array(z.string()),
|
|
16
|
+
createdAt: z.string(),
|
|
17
|
+
});
|
|
18
|
+
export const ChatRoomDetailSchema = ChatRoomSchema.extend({
|
|
19
|
+
messageCount: z.number().int().nonnegative(),
|
|
20
|
+
lastMessageAt: z.string().nullable(),
|
|
21
|
+
});
|
|
22
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const CLIENT_CAPS: {
|
|
2
|
+
readonly selectiveAgentTimeline: "selective_agent_timeline";
|
|
3
|
+
readonly reasoningMergeEnum: "reasoning_merge_enum";
|
|
4
|
+
readonly customModeIcons: "custom_mode_icons";
|
|
5
|
+
readonly terminalReflowableSnapshot: "terminal_reflowable_snapshot";
|
|
6
|
+
readonly providerSubagents: "provider_subagents";
|
|
7
|
+
readonly projectUpdates: "project_updates";
|
|
8
|
+
readonly browserHost: "browser_host";
|
|
9
|
+
};
|
|
10
|
+
export type ClientCapability = (typeof CLIENT_CAPS)[keyof typeof CLIENT_CAPS];
|
|
11
|
+
//# sourceMappingURL=client-capabilities.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const CLIENT_CAPS = {
|
|
2
|
+
// COMPAT(selectiveAgentTimeline): added in v0.1.106. Capable clients receive
|
|
3
|
+
// agent streams only for their explicit viewed set. Remove after 2027-01-12
|
|
4
|
+
// once the supported client floor is >= v0.1.106.
|
|
5
|
+
selectiveAgentTimeline: "selective_agent_timeline",
|
|
6
|
+
reasoningMergeEnum: "reasoning_merge_enum",
|
|
7
|
+
// COMPAT(customModeIcons): added in v0.1.84. Old clients pin AgentModeIcon to
|
|
8
|
+
// a closed enum and crash rendering unknown values; daemon downgrades icons
|
|
9
|
+
// outside the legacy set to "ShieldCheck" when this cap is absent. Drop the
|
|
10
|
+
// gate when floor >= v0.1.84.
|
|
11
|
+
customModeIcons: "custom_mode_icons",
|
|
12
|
+
// COMPAT(terminalReflowableSnapshot): added in v0.1.88. The daemon attaches
|
|
13
|
+
// per-row soft-wrap flags (gridWrapped/scrollbackWrapped) to terminal snapshots
|
|
14
|
+
// only when the client advertises this, so restored content can reflow on resize.
|
|
15
|
+
// Old clients use a strict TerminalState schema and would reject the extra fields.
|
|
16
|
+
// Drop the gate (always send the flags) when floor >= v0.1.88.
|
|
17
|
+
terminalReflowableSnapshot: "terminal_reflowable_snapshot",
|
|
18
|
+
// COMPAT(providerSubagents): added in v0.1.107. The daemon emits provider-owned
|
|
19
|
+
// child descriptors and timelines only to clients that understand the new messages.
|
|
20
|
+
providerSubagents: "provider_subagents",
|
|
21
|
+
// COMPAT(projectUpdates): added in v0.1.109, remove gate after 2027-01-15.
|
|
22
|
+
projectUpdates: "project_updates",
|
|
23
|
+
browserHost: "browser_host",
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=client-capabilities.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Relay-only pairing offer.
|
|
4
|
+
*
|
|
5
|
+
* `serverId` is a stable daemon identifier scoped to `AGENTSTORM_HOME`, and is also
|
|
6
|
+
* used as the relay session identifier.
|
|
7
|
+
*/
|
|
8
|
+
export declare const ConnectionOfferV2Schema: z.ZodObject<{
|
|
9
|
+
v: z.ZodLiteral<2>;
|
|
10
|
+
serverId: z.ZodString;
|
|
11
|
+
daemonPublicKeyB64: z.ZodString;
|
|
12
|
+
relay: z.ZodObject<{
|
|
13
|
+
endpoint: z.ZodString;
|
|
14
|
+
useTls: z.ZodOptional<z.ZodBoolean>;
|
|
15
|
+
}, z.core.$strip>;
|
|
16
|
+
}, z.core.$strip>;
|
|
17
|
+
export type ConnectionOfferV2 = z.infer<typeof ConnectionOfferV2Schema>;
|
|
18
|
+
export declare const ConnectionOfferSchema: z.ZodObject<{
|
|
19
|
+
v: z.ZodLiteral<2>;
|
|
20
|
+
serverId: z.ZodString;
|
|
21
|
+
daemonPublicKeyB64: z.ZodString;
|
|
22
|
+
relay: z.ZodObject<{
|
|
23
|
+
endpoint: z.ZodString;
|
|
24
|
+
useTls: z.ZodOptional<z.ZodBoolean>;
|
|
25
|
+
}, z.core.$strip>;
|
|
26
|
+
}, z.core.$strip>;
|
|
27
|
+
export type ConnectionOffer = ConnectionOfferV2;
|
|
28
|
+
export declare function decodeOfferFragmentPayload(encoded: string): unknown;
|
|
29
|
+
/**
|
|
30
|
+
* Parse a pairing-offer URL of the form `https://app.paseo.sh/#offer=<base64url>`.
|
|
31
|
+
*
|
|
32
|
+
* Returns `null` if the input has no `#offer=` fragment. Throws if the fragment
|
|
33
|
+
* exists but the payload is malformed or fails schema validation.
|
|
34
|
+
*/
|
|
35
|
+
export declare function parseConnectionOfferFromUrl(input: string): ConnectionOffer | null;
|
|
36
|
+
//# sourceMappingURL=connection-offer.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Relay-only pairing offer.
|
|
4
|
+
*
|
|
5
|
+
* `serverId` is a stable daemon identifier scoped to `AGENTSTORM_HOME`, and is also
|
|
6
|
+
* used as the relay session identifier.
|
|
7
|
+
*/
|
|
8
|
+
export const ConnectionOfferV2Schema = z.object({
|
|
9
|
+
v: z.literal(2),
|
|
10
|
+
serverId: z.string().min(1),
|
|
11
|
+
daemonPublicKeyB64: z.string().min(1),
|
|
12
|
+
relay: z.object({
|
|
13
|
+
endpoint: z.string().min(1),
|
|
14
|
+
useTls: z.boolean().optional(),
|
|
15
|
+
}),
|
|
16
|
+
});
|
|
17
|
+
export const ConnectionOfferSchema = ConnectionOfferV2Schema;
|
|
18
|
+
function decodeBase64UrlToUtf8(input) {
|
|
19
|
+
const base64 = input.replace(/-/g, "+").replace(/_/g, "/");
|
|
20
|
+
const padded = base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), "=");
|
|
21
|
+
const binary = globalThis.atob(padded);
|
|
22
|
+
const bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0));
|
|
23
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
24
|
+
}
|
|
25
|
+
export function decodeOfferFragmentPayload(encoded) {
|
|
26
|
+
const json = decodeBase64UrlToUtf8(encoded);
|
|
27
|
+
return JSON.parse(json);
|
|
28
|
+
}
|
|
29
|
+
const OFFER_FRAGMENT_PREFIX = "#offer=";
|
|
30
|
+
function extractOfferFragmentEncoded(input) {
|
|
31
|
+
const trimmed = input.trim();
|
|
32
|
+
if (!trimmed)
|
|
33
|
+
return null;
|
|
34
|
+
const fragmentIndex = trimmed.indexOf(OFFER_FRAGMENT_PREFIX);
|
|
35
|
+
if (fragmentIndex === -1)
|
|
36
|
+
return null;
|
|
37
|
+
const encoded = trimmed.slice(fragmentIndex + OFFER_FRAGMENT_PREFIX.length).trim();
|
|
38
|
+
return encoded.length > 0 ? encoded : null;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Parse a pairing-offer URL of the form `https://app.paseo.sh/#offer=<base64url>`.
|
|
42
|
+
*
|
|
43
|
+
* Returns `null` if the input has no `#offer=` fragment. Throws if the fragment
|
|
44
|
+
* exists but the payload is malformed or fails schema validation.
|
|
45
|
+
*/
|
|
46
|
+
export function parseConnectionOfferFromUrl(input) {
|
|
47
|
+
const encoded = extractOfferFragmentEncoded(input);
|
|
48
|
+
if (!encoded)
|
|
49
|
+
return null;
|
|
50
|
+
const payload = decodeOfferFragmentPayload(encoded);
|
|
51
|
+
return ConnectionOfferSchema.parse(payload);
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=connection-offer.js.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface HostPortParts {
|
|
2
|
+
host: string;
|
|
3
|
+
port: number;
|
|
4
|
+
isIpv6: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface ConnectionUriParts extends HostPortParts {
|
|
7
|
+
useTls: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface ParsedConnectionUri extends ConnectionUriParts {
|
|
10
|
+
password?: string;
|
|
11
|
+
}
|
|
12
|
+
export type RelayRole = "server" | "client";
|
|
13
|
+
export type RelayProtocolVersion = "1" | "2";
|
|
14
|
+
export declare const CURRENT_RELAY_PROTOCOL_VERSION: RelayProtocolVersion;
|
|
15
|
+
export declare const DEFAULT_RELAY_ENDPOINT = "relay.paseo.sh:443";
|
|
16
|
+
export declare function normalizeRelayProtocolVersion(value: unknown, fallback?: RelayProtocolVersion): RelayProtocolVersion;
|
|
17
|
+
export declare function parseHostPort(input: string): HostPortParts;
|
|
18
|
+
export declare function normalizeHostPort(input: string): string;
|
|
19
|
+
export declare function parseConnectionUri(input: string): ParsedConnectionUri;
|
|
20
|
+
export declare function serializeConnectionUri(parts: ConnectionUriParts): string;
|
|
21
|
+
export declare function serializeConnectionUriForStorage(parts: ParsedConnectionUri): string;
|
|
22
|
+
export declare function normalizeLoopbackToLocalhost(endpoint: string): string;
|
|
23
|
+
export declare function deriveLabelFromEndpoint(endpoint: string): string;
|
|
24
|
+
export interface WebSocketUrlOptions {
|
|
25
|
+
useTls: boolean;
|
|
26
|
+
}
|
|
27
|
+
export declare function buildDaemonWebSocketUrl(endpoint: string, opts: WebSocketUrlOptions): string;
|
|
28
|
+
export declare function buildRelayWebSocketUrl(params: {
|
|
29
|
+
endpoint: string;
|
|
30
|
+
useTls: boolean;
|
|
31
|
+
serverId: string;
|
|
32
|
+
role: RelayRole;
|
|
33
|
+
/**
|
|
34
|
+
* Per-connection routing identifier used by the daemon to open server data sockets.
|
|
35
|
+
* Clients should NOT provide this — the relay assigns a routing ID on connect.
|
|
36
|
+
*/
|
|
37
|
+
connectionId?: string;
|
|
38
|
+
version?: RelayProtocolVersion | 1 | 2;
|
|
39
|
+
}): string;
|
|
40
|
+
/**
|
|
41
|
+
* @deprecated Migration fallback for stored relay connections/offers that predate
|
|
42
|
+
* explicit relay useTls. Delete after two release cycles.
|
|
43
|
+
*/
|
|
44
|
+
export declare function shouldUseTlsForDefaultHostedRelay(endpoint: string): boolean;
|
|
45
|
+
export declare function extractHostPortFromWebSocketUrl(wsUrl: string): string;
|
|
46
|
+
export declare function isRelayClientWebSocketUrl(url: string): boolean;
|
|
47
|
+
//# sourceMappingURL=daemon-endpoints.d.ts.map
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
export const CURRENT_RELAY_PROTOCOL_VERSION = "2";
|
|
2
|
+
export const DEFAULT_RELAY_ENDPOINT = "relay.paseo.sh:443";
|
|
3
|
+
export function normalizeRelayProtocolVersion(value, fallback = CURRENT_RELAY_PROTOCOL_VERSION) {
|
|
4
|
+
if (value == null) {
|
|
5
|
+
return fallback;
|
|
6
|
+
}
|
|
7
|
+
let normalized = "";
|
|
8
|
+
if (typeof value === "string") {
|
|
9
|
+
normalized = value.trim();
|
|
10
|
+
}
|
|
11
|
+
else if (typeof value === "number") {
|
|
12
|
+
normalized = String(value);
|
|
13
|
+
}
|
|
14
|
+
if (!normalized) {
|
|
15
|
+
return fallback;
|
|
16
|
+
}
|
|
17
|
+
if (normalized === "1" || normalized === "2") {
|
|
18
|
+
return normalized;
|
|
19
|
+
}
|
|
20
|
+
throw new Error('Relay version must be "1" or "2"');
|
|
21
|
+
}
|
|
22
|
+
function parsePort(portStr, context) {
|
|
23
|
+
const port = Number(portStr);
|
|
24
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
25
|
+
throw new Error(`${context}: port must be between 1 and 65535`);
|
|
26
|
+
}
|
|
27
|
+
return port;
|
|
28
|
+
}
|
|
29
|
+
export function parseHostPort(input) {
|
|
30
|
+
const trimmed = input.trim();
|
|
31
|
+
if (!trimmed) {
|
|
32
|
+
throw new Error("Host is required");
|
|
33
|
+
}
|
|
34
|
+
// IPv6: [::1]:6767
|
|
35
|
+
if (trimmed.startsWith("[")) {
|
|
36
|
+
const match = trimmed.match(/^\[([^\]]+)\]:(\d{1,5})$/);
|
|
37
|
+
if (!match) {
|
|
38
|
+
throw new Error("Invalid host:port (expected [::1]:6767)");
|
|
39
|
+
}
|
|
40
|
+
const host = match[1].trim();
|
|
41
|
+
if (!host)
|
|
42
|
+
throw new Error("Host is required");
|
|
43
|
+
const port = parsePort(match[2], "Invalid host:port");
|
|
44
|
+
return { host, port, isIpv6: true };
|
|
45
|
+
}
|
|
46
|
+
const match = trimmed.match(/^(.+):(\d{1,5})$/);
|
|
47
|
+
if (!match) {
|
|
48
|
+
throw new Error("Invalid host:port (expected localhost:6767)");
|
|
49
|
+
}
|
|
50
|
+
const host = match[1].trim();
|
|
51
|
+
if (!host)
|
|
52
|
+
throw new Error("Host is required");
|
|
53
|
+
const port = parsePort(match[2], "Invalid host:port");
|
|
54
|
+
return { host, port, isIpv6: false };
|
|
55
|
+
}
|
|
56
|
+
export function normalizeHostPort(input) {
|
|
57
|
+
const { host, port, isIpv6 } = parseHostPort(input);
|
|
58
|
+
return isIpv6 ? `[${host}]:${port}` : `${host}:${port}`;
|
|
59
|
+
}
|
|
60
|
+
export function parseConnectionUri(input) {
|
|
61
|
+
const trimmed = input.trim();
|
|
62
|
+
if (!trimmed) {
|
|
63
|
+
throw new Error("Connection URI is required");
|
|
64
|
+
}
|
|
65
|
+
let parsed;
|
|
66
|
+
try {
|
|
67
|
+
parsed = new URL(trimmed);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
throw new Error("Invalid connection URI");
|
|
71
|
+
}
|
|
72
|
+
if (parsed.protocol !== "tcp:") {
|
|
73
|
+
throw new Error("Connection URI protocol must be tcp:");
|
|
74
|
+
}
|
|
75
|
+
if (!parsed.hostname) {
|
|
76
|
+
throw new Error("Connection URI host is required");
|
|
77
|
+
}
|
|
78
|
+
if (!parsed.port) {
|
|
79
|
+
throw new Error("Connection URI port is required");
|
|
80
|
+
}
|
|
81
|
+
if (parsed.username || parsed.password) {
|
|
82
|
+
throw new Error("Connection URI userinfo is not supported");
|
|
83
|
+
}
|
|
84
|
+
const isIpv6 = parsed.hostname.startsWith("[") && parsed.hostname.endsWith("]");
|
|
85
|
+
const host = isIpv6 ? parsed.hostname.slice(1, -1) : parsed.hostname;
|
|
86
|
+
const password = parsed.searchParams.get("password") || undefined;
|
|
87
|
+
return {
|
|
88
|
+
host,
|
|
89
|
+
port: parsePort(parsed.port, "Invalid connection URI"),
|
|
90
|
+
isIpv6,
|
|
91
|
+
useTls: parsed.searchParams.get("ssl") === "true",
|
|
92
|
+
...(password ? { password } : {}),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
export function serializeConnectionUri(parts) {
|
|
96
|
+
return createConnectionUri(parts).toString();
|
|
97
|
+
}
|
|
98
|
+
export function serializeConnectionUriForStorage(parts) {
|
|
99
|
+
const url = createConnectionUri(parts);
|
|
100
|
+
if (parts.password) {
|
|
101
|
+
url.searchParams.set("password", parts.password);
|
|
102
|
+
}
|
|
103
|
+
return url.toString();
|
|
104
|
+
}
|
|
105
|
+
function createConnectionUri(parts) {
|
|
106
|
+
const hostPart = parts.isIpv6 ? `[${parts.host}]` : parts.host;
|
|
107
|
+
const url = new URL(`tcp://${hostPart}:${parts.port}`);
|
|
108
|
+
if (parts.useTls) {
|
|
109
|
+
url.searchParams.set("ssl", "true");
|
|
110
|
+
}
|
|
111
|
+
return url;
|
|
112
|
+
}
|
|
113
|
+
export function normalizeLoopbackToLocalhost(endpoint) {
|
|
114
|
+
const { host, port, isIpv6 } = parseHostPort(endpoint);
|
|
115
|
+
if (host === "127.0.0.1" || (!isIpv6 && host === "0.0.0.0")) {
|
|
116
|
+
return `localhost:${port}`;
|
|
117
|
+
}
|
|
118
|
+
if (isIpv6 && (host === "::1" || host === "::")) {
|
|
119
|
+
return `localhost:${port}`;
|
|
120
|
+
}
|
|
121
|
+
return endpoint;
|
|
122
|
+
}
|
|
123
|
+
export function deriveLabelFromEndpoint(endpoint) {
|
|
124
|
+
try {
|
|
125
|
+
const { host } = parseHostPort(endpoint);
|
|
126
|
+
return host || "Unnamed Host";
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return "Unnamed Host";
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
export function buildDaemonWebSocketUrl(endpoint, opts) {
|
|
133
|
+
const { host, port, isIpv6 } = parseHostPort(endpoint);
|
|
134
|
+
const protocol = opts.useTls ? "wss" : "ws";
|
|
135
|
+
const hostPart = isIpv6 ? `[${host}]` : host;
|
|
136
|
+
return new URL(`${protocol}://${hostPart}:${port}/ws`).toString();
|
|
137
|
+
}
|
|
138
|
+
export function buildRelayWebSocketUrl(params) {
|
|
139
|
+
const { host, port, isIpv6 } = parseHostPort(params.endpoint);
|
|
140
|
+
const protocol = params.useTls ? "wss" : "ws";
|
|
141
|
+
const hostPart = isIpv6 ? `[${host}]` : host;
|
|
142
|
+
const url = new URL(`${protocol}://${hostPart}:${port}/ws`);
|
|
143
|
+
url.searchParams.set("serverId", params.serverId);
|
|
144
|
+
url.searchParams.set("role", params.role);
|
|
145
|
+
url.searchParams.set("v", normalizeRelayProtocolVersion(params.version));
|
|
146
|
+
if (params.connectionId) {
|
|
147
|
+
url.searchParams.set("connectionId", params.connectionId);
|
|
148
|
+
}
|
|
149
|
+
return url.toString();
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* @deprecated Migration fallback for stored relay connections/offers that predate
|
|
153
|
+
* explicit relay useTls. Delete after two release cycles.
|
|
154
|
+
*/
|
|
155
|
+
export function shouldUseTlsForDefaultHostedRelay(endpoint) {
|
|
156
|
+
try {
|
|
157
|
+
const { port } = parseHostPort(endpoint);
|
|
158
|
+
return port === 443;
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
export function extractHostPortFromWebSocketUrl(wsUrl) {
|
|
165
|
+
const parsed = new URL(wsUrl);
|
|
166
|
+
if (parsed.protocol !== "ws:" && parsed.protocol !== "wss:") {
|
|
167
|
+
throw new Error("Invalid WebSocket URL protocol");
|
|
168
|
+
}
|
|
169
|
+
if (parsed.pathname.replace(/\/+$/, "") !== "/ws") {
|
|
170
|
+
throw new Error("Invalid WebSocket URL (expected /ws path)");
|
|
171
|
+
}
|
|
172
|
+
const host = parsed.hostname;
|
|
173
|
+
let port;
|
|
174
|
+
if (parsed.port) {
|
|
175
|
+
port = Number(parsed.port);
|
|
176
|
+
}
|
|
177
|
+
else if (parsed.protocol === "wss:") {
|
|
178
|
+
port = 443;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
port = 80;
|
|
182
|
+
}
|
|
183
|
+
if (!host) {
|
|
184
|
+
throw new Error("Invalid WebSocket URL (missing hostname)");
|
|
185
|
+
}
|
|
186
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
187
|
+
throw new Error("Invalid WebSocket URL (invalid port)");
|
|
188
|
+
}
|
|
189
|
+
const isIpv6 = host.includes(":") && !host.startsWith("[") && !host.endsWith("]");
|
|
190
|
+
return isIpv6 ? `[${host}]:${port}` : `${host}:${port}`;
|
|
191
|
+
}
|
|
192
|
+
export function isRelayClientWebSocketUrl(url) {
|
|
193
|
+
try {
|
|
194
|
+
const parsed = new URL(url);
|
|
195
|
+
return parsed.searchParams.get("role") === "client" && parsed.searchParams.has("serverId");
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=daemon-endpoints.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts a human-readable error message from an unknown error value.
|
|
3
|
+
* Handles Error instances, string errors, and other types safely.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getErrorMessage(error: unknown): string;
|
|
6
|
+
/**
|
|
7
|
+
* Extracts an error message from an unknown error value, with a fallback
|
|
8
|
+
* for when no message can be extracted.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getErrorMessageOr(error: unknown, fallback: string): string;
|
|
11
|
+
//# sourceMappingURL=error-utils.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts a human-readable error message from an unknown error value.
|
|
3
|
+
* Handles Error instances, string errors, and other types safely.
|
|
4
|
+
*/
|
|
5
|
+
export function getErrorMessage(error) {
|
|
6
|
+
if (error instanceof Error) {
|
|
7
|
+
return error.message;
|
|
8
|
+
}
|
|
9
|
+
if (typeof error === "string") {
|
|
10
|
+
return error;
|
|
11
|
+
}
|
|
12
|
+
return String(error);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Extracts an error message from an unknown error value, with a fallback
|
|
16
|
+
* for when no message can be extracted.
|
|
17
|
+
*/
|
|
18
|
+
export function getErrorMessageOr(error, fallback) {
|
|
19
|
+
if (error instanceof Error) {
|
|
20
|
+
return error.message;
|
|
21
|
+
}
|
|
22
|
+
if (typeof error === "string" && error.length > 0) {
|
|
23
|
+
return error;
|
|
24
|
+
}
|
|
25
|
+
return fallback;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=error-utils.js.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declarative manifest of the git forges Paseo knows how to present, mirroring
|
|
3
|
+
* provider-manifest.ts. Pure build-time data shared by BOTH the client (icon,
|
|
4
|
+
* brand label, PR↔MR relabel) and the server (registry host-matching, prompt
|
|
5
|
+
* branding). It is NEVER serialized over the wire, so adding a forge here is not
|
|
6
|
+
* a protocol change.
|
|
7
|
+
*
|
|
8
|
+
* Keep this a pure leaf: no imports, no zod, no functions with runtime deps.
|
|
9
|
+
* Behavioural concerns (CLI invocation, host probing, REST adapters) live in the
|
|
10
|
+
* server adapter keyed by {@link ForgeDefinition.id}; this file is only the
|
|
11
|
+
* declarative half.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Declarative sign-in recipe for a forge. The client renders install/sign-in
|
|
15
|
+
* hints from this data alone — no per-CLI switch — so a new forge wires its auth
|
|
16
|
+
* UX entirely from the manifest. Behavioural auth (the actual host probe) stays
|
|
17
|
+
* in the server adapter; this is only what the user is told to run.
|
|
18
|
+
*/
|
|
19
|
+
export interface ForgeSignInCommand {
|
|
20
|
+
/** Binary the user installs, e.g. "gh" — shown in the install-CLI hint. */
|
|
21
|
+
cli: string;
|
|
22
|
+
/** Full sign-in command, e.g. "gh auth login". */
|
|
23
|
+
command: string;
|
|
24
|
+
/**
|
|
25
|
+
* Flag that targets a self-hosted host, e.g. "--hostname". When present and a
|
|
26
|
+
* host is known, the client appends `${command} ${hostnameFlag} ${host}`.
|
|
27
|
+
* Omit when the command already targets the right host on its own.
|
|
28
|
+
*/
|
|
29
|
+
hostnameFlag?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface ForgeDefinition {
|
|
32
|
+
/** Registry id, matches the server adapter and the wire `forge` value. */
|
|
33
|
+
id: string;
|
|
34
|
+
/** Human brand name, e.g. for "Open on GitLab". */
|
|
35
|
+
displayName: string;
|
|
36
|
+
/** Short change-request noun: "PR" for GitHub, "MR" for GitLab. */
|
|
37
|
+
changeRequestAbbrev: string;
|
|
38
|
+
/** Full change-request noun: "pull request" vs "merge request". */
|
|
39
|
+
changeRequestNoun: string;
|
|
40
|
+
/** Prefix before a change-request number: "#" vs "!". */
|
|
41
|
+
changeRequestNumberPrefix: string;
|
|
42
|
+
/** Prefix before an issue number ("#" on every forge so far). */
|
|
43
|
+
issueNumberPrefix: string;
|
|
44
|
+
/** Icon key; the client falls back to a generic git icon for unknown values. */
|
|
45
|
+
iconKind: string;
|
|
46
|
+
/** Sign-in recipe, or null when the forge has no Paseo-driven sign-in. */
|
|
47
|
+
signIn: ForgeSignInCommand | null;
|
|
48
|
+
/**
|
|
49
|
+
* Public cloud hosts this forge owns exactly. A BOUNDED list, never an
|
|
50
|
+
* allowlist for self-hosted detection — self-hosted/Enterprise instances are
|
|
51
|
+
* recognized at runtime by the adapter's host probe, not by this field.
|
|
52
|
+
*/
|
|
53
|
+
cloudHosts?: string[];
|
|
54
|
+
}
|
|
55
|
+
export declare const FORGE_DEFINITIONS: ForgeDefinition[];
|
|
56
|
+
/** Forge definitions only present in dev builds (none today; mirrors providers). */
|
|
57
|
+
export declare const DEV_FORGE_DEFINITIONS: ForgeDefinition[];
|
|
58
|
+
export declare const FORGE_IDS: string[];
|
|
59
|
+
export declare function getForgeDefinition(id: string, definitions?: ForgeDefinition[]): ForgeDefinition | null;
|
|
60
|
+
/**
|
|
61
|
+
* Resolve a forge definition, synthesizing a neutral one for a forge id the
|
|
62
|
+
* client has never heard of (e.g. a self-hosted forge a newer daemon reports to
|
|
63
|
+
* an older client). The neutral shape renders generic, never GitHub-branded.
|
|
64
|
+
*/
|
|
65
|
+
export declare function getForgeDefinitionOrNeutral(id: string): ForgeDefinition;
|
|
66
|
+
//# sourceMappingURL=forge-manifest.d.ts.map
|