@ericsanchezok/synergy-util 2.4.5 → 3.0.1
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/capability.d.ts +4 -277
- package/dist/capability.js +54 -474
- package/dist/plugin-policy.d.ts +26 -56
- package/dist/plugin-policy.js +33 -202
- package/dist/uuid.d.ts +10 -0
- package/dist/uuid.js +30 -0
- package/package.json +1 -1
- package/dist/browser-protocol.d.ts +0 -97
- package/dist/browser-protocol.js +0 -51
package/dist/plugin-policy.d.ts
CHANGED
|
@@ -1,64 +1,29 @@
|
|
|
1
|
-
import { type SynergyCapabilityManifest } from "./capability.js";
|
|
2
1
|
export type PluginSource = "local" | "official" | "npm" | "git" | "url" | "builtin";
|
|
3
|
-
export type RuntimeMode = "
|
|
4
|
-
export type TrustTier = "declarative" | "trusted-import"
|
|
2
|
+
export type RuntimeMode = "inProcess" | "process";
|
|
3
|
+
export type TrustTier = "declarative" | "trusted-import";
|
|
5
4
|
export type PolicyRisk = "low" | "medium" | "high";
|
|
6
|
-
export interface PluginPolicyManifest extends SynergyCapabilityManifest {
|
|
7
|
-
runtime?: {
|
|
8
|
-
mode?: RuntimeMode;
|
|
9
|
-
resources?: unknown;
|
|
10
|
-
};
|
|
11
|
-
trust?: {
|
|
12
|
-
requestedTier?: TrustTier;
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
export interface PluginTrustDecision {
|
|
16
|
-
tier: TrustTier;
|
|
17
|
-
source: PluginSource;
|
|
18
|
-
userTrusted: boolean;
|
|
19
|
-
verifiedIntegrity: boolean;
|
|
20
|
-
reason: string;
|
|
21
|
-
}
|
|
22
5
|
export interface RuntimeLimits {
|
|
23
6
|
startupTimeoutMs: number;
|
|
24
7
|
toolInvocationTimeoutMs: number;
|
|
25
|
-
|
|
26
|
-
bridgeRequestTimeoutMs: number;
|
|
8
|
+
hostServiceRequestTimeoutMs: number;
|
|
27
9
|
taskRunTimeoutMs: number;
|
|
28
10
|
shutdownGraceMs: number;
|
|
29
|
-
maxConcurrentRequests: number;
|
|
30
|
-
maxLogBytesPerMinute: number;
|
|
31
|
-
memoryMb: number;
|
|
32
|
-
memoryPollIntervalMs: number;
|
|
33
11
|
heartbeatIntervalMs: number;
|
|
34
|
-
heartbeatMissesBeforeKill: number;
|
|
35
12
|
}
|
|
36
13
|
export type RuntimeLimitOverrides = Partial<RuntimeLimits>;
|
|
37
14
|
export interface PluginRuntimePolicyInput {
|
|
38
|
-
thirdPartyDefaultMode?: "process" | "worker";
|
|
39
|
-
highRiskRequiresProcess?: boolean;
|
|
40
|
-
allowThirdPartyInProcess?: boolean;
|
|
41
|
-
allowWorkerMode?: boolean;
|
|
42
|
-
allowLocalInProcess?: boolean;
|
|
43
15
|
}
|
|
44
|
-
export
|
|
16
|
+
export declare const DEFAULT_PLUGIN_RUNTIME_POLICY: {};
|
|
17
|
+
export declare const DEFAULT_PLUGIN_RUNTIME_LIMITS: RuntimeLimits;
|
|
18
|
+
export interface PluginTrustDecision {
|
|
19
|
+
tier: TrustTier;
|
|
45
20
|
source: PluginSource;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
runtimeMode: RuntimeMode;
|
|
21
|
+
userTrusted: boolean;
|
|
22
|
+
verifiedIntegrity: boolean;
|
|
23
|
+
reason: string;
|
|
50
24
|
}
|
|
51
|
-
export declare const DEFAULT_PLUGIN_RUNTIME_POLICY: Required<PluginRuntimePolicyInput>;
|
|
52
|
-
export declare const DEFAULT_PLUGIN_RUNTIME_LIMITS: RuntimeLimits;
|
|
53
|
-
export declare function isTrustedPluginSource(source: PluginSource): boolean;
|
|
54
25
|
export interface ResolveRuntimeModeInput {
|
|
55
26
|
source: PluginSource;
|
|
56
|
-
manifestMode?: RuntimeMode;
|
|
57
|
-
devMode?: boolean;
|
|
58
|
-
userTrusted?: boolean;
|
|
59
|
-
risk?: PolicyRisk;
|
|
60
|
-
forceProcess?: boolean;
|
|
61
|
-
policy?: PluginRuntimePolicyInput;
|
|
62
27
|
}
|
|
63
28
|
export interface PolicyCheckResult {
|
|
64
29
|
type: "pass" | "warn" | "error";
|
|
@@ -66,6 +31,7 @@ export interface PolicyCheckResult {
|
|
|
66
31
|
}
|
|
67
32
|
export declare function resolveRuntimeMode(input: ResolveRuntimeModeInput): RuntimeMode;
|
|
68
33
|
export declare function resolveRuntimeLimits(...overrides: Array<RuntimeLimitOverrides | undefined>): RuntimeLimits;
|
|
34
|
+
export declare function isTrustedPluginSource(source: PluginSource): source is "local" | "official" | "builtin";
|
|
69
35
|
export declare function decideTrust(input: {
|
|
70
36
|
source: PluginSource;
|
|
71
37
|
userTrusted: boolean;
|
|
@@ -78,23 +44,27 @@ export declare function defaultPluginTrustDecision(input: {
|
|
|
78
44
|
verifiedIntegrity?: boolean;
|
|
79
45
|
devMode?: boolean;
|
|
80
46
|
}): PluginTrustDecision;
|
|
47
|
+
interface FlatManifest {
|
|
48
|
+
capabilities?: Array<{
|
|
49
|
+
id: string;
|
|
50
|
+
}>;
|
|
51
|
+
}
|
|
52
|
+
export interface PluginPolicyDecision {
|
|
53
|
+
source: PluginSource;
|
|
54
|
+
capabilities: string[];
|
|
55
|
+
risk: PolicyRisk;
|
|
56
|
+
trust: PluginTrustDecision;
|
|
57
|
+
runtimeMode: RuntimeMode;
|
|
58
|
+
}
|
|
81
59
|
export declare function resolvePluginPolicyDecision(input: {
|
|
82
|
-
manifest:
|
|
60
|
+
manifest: FlatManifest;
|
|
83
61
|
source: PluginSource;
|
|
84
62
|
userTrusted?: boolean;
|
|
85
63
|
verifiedIntegrity?: boolean;
|
|
86
64
|
devMode?: boolean;
|
|
87
|
-
policy?: PluginRuntimePolicyInput;
|
|
88
|
-
forceProcess?: boolean;
|
|
89
65
|
risk?: PolicyRisk;
|
|
90
66
|
}): PluginPolicyDecision;
|
|
91
67
|
export declare function trustReason(decision: PluginTrustDecision): string;
|
|
92
68
|
export declare function trustSummary(decision: PluginTrustDecision): string;
|
|
93
|
-
export declare function validateRuntimePolicy(
|
|
94
|
-
|
|
95
|
-
source: PluginSource;
|
|
96
|
-
trustTier: TrustTier;
|
|
97
|
-
risk: PolicyRisk;
|
|
98
|
-
userTrusted?: boolean;
|
|
99
|
-
policy?: PluginRuntimePolicyInput;
|
|
100
|
-
}): PolicyCheckResult[];
|
|
69
|
+
export declare function validateRuntimePolicy(): PolicyCheckResult[];
|
|
70
|
+
export {};
|
package/dist/plugin-policy.js
CHANGED
|
@@ -1,123 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
export const DEFAULT_PLUGIN_RUNTIME_POLICY = {
|
|
3
|
-
thirdPartyDefaultMode: "process",
|
|
4
|
-
highRiskRequiresProcess: true,
|
|
5
|
-
allowThirdPartyInProcess: false,
|
|
6
|
-
allowWorkerMode: true,
|
|
7
|
-
allowLocalInProcess: true,
|
|
8
|
-
};
|
|
1
|
+
export const DEFAULT_PLUGIN_RUNTIME_POLICY = {};
|
|
9
2
|
export const DEFAULT_PLUGIN_RUNTIME_LIMITS = {
|
|
10
3
|
startupTimeoutMs: 5_000,
|
|
11
4
|
toolInvocationTimeoutMs: 120_000,
|
|
12
|
-
|
|
13
|
-
bridgeRequestTimeoutMs: 120_000,
|
|
5
|
+
hostServiceRequestTimeoutMs: 120_000,
|
|
14
6
|
taskRunTimeoutMs: 120_000,
|
|
15
7
|
shutdownGraceMs: 1_500,
|
|
16
|
-
maxConcurrentRequests: 8,
|
|
17
|
-
maxLogBytesPerMinute: 128_000,
|
|
18
|
-
memoryMb: 256,
|
|
19
|
-
memoryPollIntervalMs: 10_000,
|
|
20
8
|
heartbeatIntervalMs: 5_000,
|
|
21
|
-
heartbeatMissesBeforeKill: 3,
|
|
22
9
|
};
|
|
23
|
-
const TRUSTED_SOURCES = new Set(["builtin", "official", "local"]);
|
|
24
|
-
const THIRD_PARTY_SOURCES = new Set(["npm", "git", "url"]);
|
|
25
|
-
export function isTrustedPluginSource(source) {
|
|
26
|
-
return TRUSTED_SOURCES.has(source);
|
|
27
|
-
}
|
|
28
|
-
function runtimePolicy(input) {
|
|
29
|
-
return { ...DEFAULT_PLUGIN_RUNTIME_POLICY, ...(input ?? {}) };
|
|
30
|
-
}
|
|
31
10
|
export function resolveRuntimeMode(input) {
|
|
32
|
-
|
|
33
|
-
const source = input.source;
|
|
34
|
-
const manifestMode = input.manifestMode;
|
|
35
|
-
const userTrusted = input.userTrusted ?? false;
|
|
36
|
-
const risk = input.risk ?? "low";
|
|
37
|
-
if (input.forceProcess)
|
|
38
|
-
return "process";
|
|
39
|
-
if (policy.highRiskRequiresProcess && risk === "high")
|
|
40
|
-
return "process";
|
|
41
|
-
if (manifestMode === "process")
|
|
42
|
-
return "process";
|
|
43
|
-
if (manifestMode === "worker") {
|
|
44
|
-
if (policy.allowWorkerMode && userTrusted)
|
|
45
|
-
return "worker";
|
|
46
|
-
return THIRD_PARTY_SOURCES.has(source) ? "process" : defaultTrustedMode(source, policy);
|
|
47
|
-
}
|
|
48
|
-
if (manifestMode === "in-process") {
|
|
49
|
-
if (TRUSTED_SOURCES.has(source))
|
|
50
|
-
return defaultTrustedMode(source, policy);
|
|
51
|
-
return policy.allowThirdPartyInProcess ? "in-process" : "process";
|
|
52
|
-
}
|
|
53
|
-
if (THIRD_PARTY_SOURCES.has(source)) {
|
|
54
|
-
if (policy.thirdPartyDefaultMode === "worker" && policy.allowWorkerMode && userTrusted)
|
|
55
|
-
return "worker";
|
|
56
|
-
return "process";
|
|
57
|
-
}
|
|
58
|
-
return defaultTrustedMode(source, policy);
|
|
11
|
+
return input.source === "builtin" ? "inProcess" : "process";
|
|
59
12
|
}
|
|
60
13
|
export function resolveRuntimeLimits(...overrides) {
|
|
61
|
-
const
|
|
14
|
+
const result = { ...DEFAULT_PLUGIN_RUNTIME_LIMITS };
|
|
62
15
|
for (const override of overrides) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0)
|
|
67
|
-
continue;
|
|
68
|
-
resolved[key] = Math.round(value);
|
|
16
|
+
for (const [key, value] of Object.entries(override ?? {})) {
|
|
17
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0)
|
|
18
|
+
result[key] = Math.round(value);
|
|
69
19
|
}
|
|
70
20
|
}
|
|
71
|
-
return
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
export function isTrustedPluginSource(source) {
|
|
24
|
+
return source === "builtin" || source === "official" || source === "local";
|
|
72
25
|
}
|
|
73
26
|
export function decideTrust(input) {
|
|
74
|
-
const { source, userTrusted, verifiedIntegrity, devMode } = input;
|
|
75
|
-
let tier;
|
|
76
|
-
let reason;
|
|
77
|
-
switch (source) {
|
|
78
|
-
case "builtin":
|
|
79
|
-
tier = "trusted-import";
|
|
80
|
-
reason = "builtin plugin is always trusted";
|
|
81
|
-
break;
|
|
82
|
-
case "official":
|
|
83
|
-
tier = "trusted-import";
|
|
84
|
-
reason = "official registry plugin is trusted";
|
|
85
|
-
break;
|
|
86
|
-
case "local":
|
|
87
|
-
tier = "trusted-import";
|
|
88
|
-
reason = devMode ? "local plugin in dev mode" : "local plugin";
|
|
89
|
-
break;
|
|
90
|
-
case "npm":
|
|
91
|
-
if (userTrusted && verifiedIntegrity) {
|
|
92
|
-
tier = "trusted-import";
|
|
93
|
-
reason = "user-trusted npm plugin with verified integrity";
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
tier = "sandbox";
|
|
97
|
-
reason = "npm plugin requires explicit user trust and verified integrity";
|
|
98
|
-
}
|
|
99
|
-
break;
|
|
100
|
-
case "git":
|
|
101
|
-
if (userTrusted) {
|
|
102
|
-
tier = "trusted-import";
|
|
103
|
-
reason = "user-trusted git plugin";
|
|
104
|
-
}
|
|
105
|
-
else {
|
|
106
|
-
tier = "sandbox";
|
|
107
|
-
reason = "git plugin requires explicit user trust";
|
|
108
|
-
}
|
|
109
|
-
break;
|
|
110
|
-
case "url":
|
|
111
|
-
tier = "sandbox";
|
|
112
|
-
reason = "URL-sourced plugins always run in sandbox";
|
|
113
|
-
break;
|
|
114
|
-
}
|
|
115
27
|
return {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
reason
|
|
28
|
+
source: input.source,
|
|
29
|
+
userTrusted: input.userTrusted,
|
|
30
|
+
verifiedIntegrity: input.verifiedIntegrity,
|
|
31
|
+
tier: input.userTrusted || input.source === "builtin" ? "trusted-import" : "declarative",
|
|
32
|
+
reason: input.userTrusted
|
|
33
|
+
? "plugin UI was explicitly trusted"
|
|
34
|
+
: "plugin contributes declarations only until trusted",
|
|
121
35
|
};
|
|
122
36
|
}
|
|
123
37
|
export function defaultPluginTrustDecision(input) {
|
|
@@ -129,112 +43,29 @@ export function defaultPluginTrustDecision(input) {
|
|
|
129
43
|
});
|
|
130
44
|
}
|
|
131
45
|
export function resolvePluginPolicyDecision(input) {
|
|
132
|
-
const
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
verifiedIntegrity,
|
|
140
|
-
devMode: input.devMode ?? false,
|
|
141
|
-
});
|
|
142
|
-
const runtimeMode = resolveRuntimeMode({
|
|
143
|
-
source: input.source,
|
|
144
|
-
manifestMode: input.manifest.runtime?.mode,
|
|
145
|
-
devMode: input.devMode,
|
|
146
|
-
userTrusted,
|
|
147
|
-
risk,
|
|
148
|
-
forceProcess: input.forceProcess,
|
|
149
|
-
policy: input.policy,
|
|
150
|
-
});
|
|
46
|
+
const capabilities = input.manifest.capabilities?.map((item) => item.id) ?? [];
|
|
47
|
+
const risk = input.risk ??
|
|
48
|
+
(capabilities.some((item) => ["workspace.write", "secrets", "task.delegate", "blueprint.delegate", "lightloop.delegate"].includes(item))
|
|
49
|
+
? "high"
|
|
50
|
+
: capabilities.length
|
|
51
|
+
? "medium"
|
|
52
|
+
: "low");
|
|
151
53
|
return {
|
|
152
54
|
source: input.source,
|
|
153
55
|
capabilities,
|
|
154
56
|
risk,
|
|
155
|
-
trust,
|
|
156
|
-
runtimeMode,
|
|
57
|
+
trust: defaultPluginTrustDecision(input),
|
|
58
|
+
runtimeMode: resolveRuntimeMode({ source: input.source }),
|
|
157
59
|
};
|
|
158
60
|
}
|
|
159
61
|
export function trustReason(decision) {
|
|
160
|
-
|
|
161
|
-
if (decision.userTrusted)
|
|
162
|
-
factors.push("user-trusted");
|
|
163
|
-
if (decision.verifiedIntegrity)
|
|
164
|
-
factors.push("integrity verified");
|
|
165
|
-
const factorText = factors.length > 0 ? ` (${factors.join(", ")})` : "";
|
|
166
|
-
return `${decision.reason} -> ${decision.tier}${factorText}`;
|
|
62
|
+
return decision.reason;
|
|
167
63
|
}
|
|
168
64
|
export function trustSummary(decision) {
|
|
169
|
-
|
|
170
|
-
if (decision.userTrusted)
|
|
171
|
-
metadata.push("trusted");
|
|
172
|
-
if (decision.verifiedIntegrity)
|
|
173
|
-
metadata.push("verified");
|
|
174
|
-
const meta = metadata.length > 0 ? ` [${metadata.join(", ")}]` : "";
|
|
175
|
-
return `${decision.source} -> ${decision.tier}${meta}`;
|
|
65
|
+
return `${decision.tier}: ${decision.reason}`;
|
|
176
66
|
}
|
|
177
|
-
function
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
export function validateRuntimePolicy(input) {
|
|
183
|
-
const results = [];
|
|
184
|
-
const requestedMode = input.manifest.runtime?.mode;
|
|
185
|
-
const effectiveMode = resolveRuntimeMode({
|
|
186
|
-
source: input.source,
|
|
187
|
-
manifestMode: requestedMode,
|
|
188
|
-
userTrusted: input.userTrusted,
|
|
189
|
-
risk: input.risk,
|
|
190
|
-
policy: input.policy,
|
|
191
|
-
});
|
|
192
|
-
if (requestedMode && requestedMode !== effectiveMode) {
|
|
193
|
-
results.push({
|
|
194
|
-
type: "warn",
|
|
195
|
-
message: `Plugin requested runtime mode "${requestedMode}" but Synergy will use "${effectiveMode}" for source=${input.source} and risk=${input.risk}.`,
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
const requestedTier = input.manifest.trust?.requestedTier;
|
|
199
|
-
if (input.trustTier === "sandbox" && requestedTier !== "sandbox") {
|
|
200
|
-
results.push({
|
|
201
|
-
type: "warn",
|
|
202
|
-
message: `Plugin has sandbox trust tier; effective runtime mode is "${effectiveMode}". Use process mode with explicit resource limits for strongest isolation.`,
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
if (requestedTier !== undefined && requestedTier !== input.trustTier) {
|
|
206
|
-
results.push({
|
|
207
|
-
type: "warn",
|
|
208
|
-
message: `Plugin requested trust tier "${requestedTier}" but was assigned "${input.trustTier}" (source=${input.source}). Runtime mode is "${effectiveMode}".`,
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
if (effectiveMode === "worker") {
|
|
212
|
-
const tools = input.manifest.permissions?.tools;
|
|
213
|
-
const hasShell = tools?.shell ?? false;
|
|
214
|
-
const hasFileWrite = tools?.filesystem === "write";
|
|
215
|
-
const hasMcpSpawn = tools?.mcp === "spawn";
|
|
216
|
-
const contributedTools = input.manifest.contributes?.tools ?? [];
|
|
217
|
-
const toolShell = contributedTools.some((tool) => tool.capabilities?.shell);
|
|
218
|
-
const toolFileWrite = contributedTools.some((tool) => tool.capabilities?.filesystem === "write");
|
|
219
|
-
if (hasShell || toolShell || hasFileWrite || toolFileWrite || hasMcpSpawn) {
|
|
220
|
-
const unsupported = [];
|
|
221
|
-
if (hasShell || toolShell)
|
|
222
|
-
unsupported.push("shell");
|
|
223
|
-
if (hasFileWrite || toolFileWrite)
|
|
224
|
-
unsupported.push("file_write");
|
|
225
|
-
if (hasMcpSpawn)
|
|
226
|
-
unsupported.push("mcp_spawn");
|
|
227
|
-
results.push({
|
|
228
|
-
type: "warn",
|
|
229
|
-
message: `Worker mode does not fully support: ${unsupported.join(", ")}. Use process mode for these capabilities.`,
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
if (effectiveMode === "process" && !input.manifest.runtime?.resources) {
|
|
234
|
-
results.push({
|
|
235
|
-
type: "warn",
|
|
236
|
-
message: "Process mode used without resource limits. Specify runtime.resources to prevent resource exhaustion.",
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
return results;
|
|
67
|
+
export function validateRuntimePolicy() {
|
|
68
|
+
return [
|
|
69
|
+
{ type: "pass", message: "External plugins use the process runtime; built-ins may use the inProcess runtime." },
|
|
70
|
+
];
|
|
240
71
|
}
|
package/dist/uuid.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface UUIDCrypto {
|
|
2
|
+
randomUUID?: () => string;
|
|
3
|
+
getRandomValues?: (array: Uint8Array) => Uint8Array;
|
|
4
|
+
}
|
|
5
|
+
export interface UUIDEnvironment {
|
|
6
|
+
crypto?: UUIDCrypto;
|
|
7
|
+
now?: () => number;
|
|
8
|
+
random?: () => number;
|
|
9
|
+
}
|
|
10
|
+
export declare function generateUUID(environment?: UUIDEnvironment): string;
|
package/dist/uuid.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
let fallbackCounter = 0;
|
|
2
|
+
export function generateUUID(environment) {
|
|
3
|
+
const webCrypto = environment ? environment.crypto : globalThis.crypto;
|
|
4
|
+
try {
|
|
5
|
+
if (typeof webCrypto?.randomUUID === "function")
|
|
6
|
+
return webCrypto.randomUUID();
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
// randomUUID may be exposed but blocked outside a secure context.
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
if (typeof webCrypto?.getRandomValues === "function") {
|
|
13
|
+
const bytes = webCrypto.getRandomValues(new Uint8Array(16));
|
|
14
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x40;
|
|
15
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
16
|
+
return formatUUID(bytes);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
// Fall through for runtimes without a usable Web Crypto implementation.
|
|
21
|
+
}
|
|
22
|
+
fallbackCounter += 1;
|
|
23
|
+
const now = environment?.now?.() ?? Date.now();
|
|
24
|
+
const random = environment?.random?.() ?? Math.random();
|
|
25
|
+
return `${now.toString(36)}-${fallbackCounter.toString(36)}-${random.toString(36).slice(2)}`;
|
|
26
|
+
}
|
|
27
|
+
function formatUUID(bytes) {
|
|
28
|
+
const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
29
|
+
return [hex.slice(0, 8), hex.slice(8, 12), hex.slice(12, 16), hex.slice(16, 20), hex.slice(20)].join("-");
|
|
30
|
+
}
|
package/package.json
CHANGED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
export declare const BROWSER_PROTOCOL_VERSION = 1;
|
|
2
|
-
export declare const BrowserPresentationKinds: readonly ["native", "webrtc"];
|
|
3
|
-
export type BrowserPresentationKind = (typeof BrowserPresentationKinds)[number];
|
|
4
|
-
export type BrowserPresentationPreference = "auto" | BrowserPresentationKind;
|
|
5
|
-
export declare function parseBrowserPresentationPreference(value: string | null | undefined): BrowserPresentationPreference;
|
|
6
|
-
export declare function normalizeBrowserURL(input: string, base?: string): string;
|
|
7
|
-
export interface BrowserPresentationCapabilities {
|
|
8
|
-
native: boolean;
|
|
9
|
-
webrtc: boolean;
|
|
10
|
-
}
|
|
11
|
-
export interface BrowserPresentationSelection {
|
|
12
|
-
protocolVersion: typeof BROWSER_PROTOCOL_VERSION;
|
|
13
|
-
kind: BrowserPresentationKind;
|
|
14
|
-
capabilities: BrowserPresentationCapabilities;
|
|
15
|
-
reason: "desktop-local" | "remote-client" | "requested";
|
|
16
|
-
}
|
|
17
|
-
export interface BrowserPresentationEnvironment {
|
|
18
|
-
desktop: boolean;
|
|
19
|
-
sameHost: boolean;
|
|
20
|
-
remote: boolean;
|
|
21
|
-
requested?: BrowserPresentationPreference;
|
|
22
|
-
capabilities?: Partial<BrowserPresentationCapabilities>;
|
|
23
|
-
}
|
|
24
|
-
export interface BrowserPage {
|
|
25
|
-
id: string;
|
|
26
|
-
url: string;
|
|
27
|
-
title: string;
|
|
28
|
-
isLoading: boolean;
|
|
29
|
-
lastActiveAt?: number | null;
|
|
30
|
-
}
|
|
31
|
-
export interface BrowserSession {
|
|
32
|
-
page: BrowserPage | null;
|
|
33
|
-
}
|
|
34
|
-
export interface BrowserPresentation {
|
|
35
|
-
selection: BrowserPresentationSelection;
|
|
36
|
-
}
|
|
37
|
-
export interface BrowserControl {
|
|
38
|
-
navigate(input: {
|
|
39
|
-
pageId?: string;
|
|
40
|
-
url: string;
|
|
41
|
-
}): Promise<{
|
|
42
|
-
url: string;
|
|
43
|
-
title: string;
|
|
44
|
-
}>;
|
|
45
|
-
reload(input?: {
|
|
46
|
-
pageId?: string;
|
|
47
|
-
}): Promise<void>;
|
|
48
|
-
stop(input?: {
|
|
49
|
-
pageId?: string;
|
|
50
|
-
}): Promise<void>;
|
|
51
|
-
setViewport(input: {
|
|
52
|
-
pageId?: string;
|
|
53
|
-
width: number;
|
|
54
|
-
height: number;
|
|
55
|
-
}): Promise<void>;
|
|
56
|
-
snapshot(input?: {
|
|
57
|
-
pageId?: string;
|
|
58
|
-
}): Promise<unknown>;
|
|
59
|
-
screenshot(input?: {
|
|
60
|
-
pageId?: string;
|
|
61
|
-
}): Promise<{
|
|
62
|
-
dataUrl: string;
|
|
63
|
-
width: number;
|
|
64
|
-
height: number;
|
|
65
|
-
}>;
|
|
66
|
-
}
|
|
67
|
-
export interface BrowserHost {
|
|
68
|
-
protocolVersion: typeof BROWSER_PROTOCOL_VERSION;
|
|
69
|
-
capabilities(): Promise<BrowserPresentationCapabilities> | BrowserPresentationCapabilities;
|
|
70
|
-
presentation(input: BrowserPresentationEnvironment): BrowserPresentationSelection;
|
|
71
|
-
session(input: {
|
|
72
|
-
ownerKey: string;
|
|
73
|
-
}): Promise<BrowserSession>;
|
|
74
|
-
control(input: {
|
|
75
|
-
ownerKey: string;
|
|
76
|
-
}): Promise<BrowserControl>;
|
|
77
|
-
}
|
|
78
|
-
export declare function selectBrowserPresentation(input: BrowserPresentationEnvironment): BrowserPresentationSelection;
|
|
79
|
-
export type BrowserWebRTCSignalMessage = {
|
|
80
|
-
type: "webrtc.offer";
|
|
81
|
-
pageId: string;
|
|
82
|
-
sdp: string;
|
|
83
|
-
traceId?: string;
|
|
84
|
-
} | {
|
|
85
|
-
type: "webrtc.answer";
|
|
86
|
-
pageId: string;
|
|
87
|
-
sdp: string;
|
|
88
|
-
} | {
|
|
89
|
-
type: "webrtc.ice";
|
|
90
|
-
pageId: string;
|
|
91
|
-
candidate: unknown;
|
|
92
|
-
traceId?: string;
|
|
93
|
-
} | {
|
|
94
|
-
type: "webrtc.close";
|
|
95
|
-
pageId: string;
|
|
96
|
-
traceId?: string;
|
|
97
|
-
};
|
package/dist/browser-protocol.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
export const BROWSER_PROTOCOL_VERSION = 1;
|
|
2
|
-
export const BrowserPresentationKinds = ["native", "webrtc"];
|
|
3
|
-
export function parseBrowserPresentationPreference(value) {
|
|
4
|
-
if (value === "native" || value === "webrtc")
|
|
5
|
-
return value;
|
|
6
|
-
return "auto";
|
|
7
|
-
}
|
|
8
|
-
export function normalizeBrowserURL(input, base) {
|
|
9
|
-
const raw = input.trim();
|
|
10
|
-
if (!raw)
|
|
11
|
-
throw new Error("URL is required");
|
|
12
|
-
if (/^(localhost|127\.0\.0\.1|\[::1\]|::1)(:\d+)?(\/.*)?$/i.test(raw)) {
|
|
13
|
-
return `http://${raw}`;
|
|
14
|
-
}
|
|
15
|
-
if (/^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(:\d+)?(\/.*)?$/.test(raw)) {
|
|
16
|
-
return `https://${raw}`;
|
|
17
|
-
}
|
|
18
|
-
if (base || /^[a-zA-Z][a-zA-Z\d+.-]*:/.test(raw)) {
|
|
19
|
-
try {
|
|
20
|
-
return new URL(raw, base).toString();
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
// Continue to search fallback below.
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return `https://www.google.com/search?q=${encodeURIComponent(raw)}`;
|
|
27
|
-
}
|
|
28
|
-
const defaultCapabilities = {
|
|
29
|
-
native: true,
|
|
30
|
-
webrtc: true,
|
|
31
|
-
};
|
|
32
|
-
function capabilities(input) {
|
|
33
|
-
return {
|
|
34
|
-
native: input?.native ?? defaultCapabilities.native,
|
|
35
|
-
webrtc: input?.webrtc ?? defaultCapabilities.webrtc,
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
export function selectBrowserPresentation(input) {
|
|
39
|
-
const caps = capabilities(input.capabilities);
|
|
40
|
-
const requested = input.requested ?? "auto";
|
|
41
|
-
if (requested === "native" && caps.native) {
|
|
42
|
-
return { protocolVersion: BROWSER_PROTOCOL_VERSION, kind: "native", capabilities: caps, reason: "requested" };
|
|
43
|
-
}
|
|
44
|
-
if (requested === "webrtc" && caps.webrtc) {
|
|
45
|
-
return { protocolVersion: BROWSER_PROTOCOL_VERSION, kind: "webrtc", capabilities: caps, reason: "requested" };
|
|
46
|
-
}
|
|
47
|
-
if (caps.native && input.desktop && input.sameHost && !input.remote) {
|
|
48
|
-
return { protocolVersion: BROWSER_PROTOCOL_VERSION, kind: "native", capabilities: caps, reason: "desktop-local" };
|
|
49
|
-
}
|
|
50
|
-
return { protocolVersion: BROWSER_PROTOCOL_VERSION, kind: "webrtc", capabilities: caps, reason: "remote-client" };
|
|
51
|
-
}
|