devframe 0.7.16 → 0.8.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/bin/devframe.mjs +8 -0
- package/dist/adapters/build.d.mts +1 -1
- package/dist/adapters/build.mjs +4 -4
- package/dist/adapters/cac.d.mts +1 -1
- package/dist/adapters/cac.mjs +1 -1
- package/dist/adapters/cli.d.mts +1 -1
- package/dist/adapters/cli.mjs +1 -1
- package/dist/adapters/dev.d.mts +2 -2
- package/dist/adapters/dev.mjs +1 -1
- package/dist/adapters/embedded.d.mts +1 -1
- package/dist/adapters/mcp.d.mts +51 -3
- package/dist/adapters/mcp.mjs +2 -2
- package/dist/agent-tool-name-C3b5vEwJ.mjs +34 -0
- package/dist/{cac-CPaOy3LD.mjs → cac-B1LM3zit.mjs} +18 -13
- package/dist/cli/main.d.mts +11 -0
- package/dist/cli/main.mjs +284 -0
- package/dist/client/index.d.mts +40 -11
- package/dist/client/index.mjs +129 -19
- package/dist/constants.d.mts +13 -6
- package/dist/constants.mjs +13 -6
- package/dist/{context-DY72brRI.mjs → context-CQefP2jR.mjs} +3 -2
- package/dist/{context-CzqPrJSz.d.mts → context-DFzmxCLa.d.mts} +1 -1
- package/dist/{revoke-BtQDKTp7.mjs → crypto-token-XCqTSMg9.mjs} +1 -35
- package/dist/{dev-BCeaQuGE.mjs → dev-BSHFZGZr.mjs} +22 -11
- package/dist/{devframe-Ckhf3kFw.d.mts → devframe-qgCKL683.d.mts} +77 -15
- package/dist/diagnostics-B5-qHeqD.mjs +94 -0
- package/dist/{diagnostics-BXwBQmoN.mjs → diagnostics-hwjXp_UV.mjs} +8 -0
- package/dist/{dump-Cz7yVvsB.mjs → dump-CgZShDRB.mjs} +82 -6
- package/dist/fetch-CK0S253E.mjs +534 -0
- package/dist/helpers/vite.d.mts +15 -14
- package/dist/helpers/vite.mjs +8 -8
- package/dist/{host-h3-CgOetlNE.mjs → host-h3-Kz7t5Xab.mjs} +83 -28
- package/dist/http-Dvgxujcu.mjs +38 -0
- package/dist/{index-8dndvIxR.d.mts → index-B7RgLw--.d.mts} +11 -6
- package/dist/{index-DgsLFhZg.d.mts → index-Dbw1p5ch.d.mts} +27 -3
- package/dist/{index-YDSJgsyG.d.mts → index-vAX6bYuc.d.mts} +1 -1
- package/dist/index.d.mts +5 -5
- package/dist/instance-registry-D6fxYu36.mjs +190 -0
- package/dist/node/auth.d.mts +2 -2
- package/dist/node/auth.mjs +2 -2
- package/dist/node/hub-internals.d.mts +2 -2
- package/dist/node/hub-internals.mjs +1 -1
- package/dist/node/index.d.mts +124 -6
- package/dist/node/index.mjs +5 -4
- package/dist/recipes/common-rpc-functions.d.mts +33 -33
- package/dist/recipes/common-rpc-functions.mjs +6 -6
- package/dist/recipes/interactive-auth.d.mts +2 -2
- package/dist/recipes/interactive-auth.mjs +23 -15
- package/dist/revoke-DZbJ7Cl0.mjs +35 -0
- package/dist/rpc/dump.d.mts +1 -1
- package/dist/rpc/dump.mjs +1 -1
- package/dist/rpc/index.d.mts +3 -3
- package/dist/rpc/index.mjs +4 -4
- package/dist/rpc/transports/ws-client.d.mts +1 -1
- package/dist/rpc/transports/ws-client.mjs +1 -1
- package/dist/rpc/transports/ws-server.d.mts +2 -2
- package/dist/rpc/transports/ws-server.mjs +50 -3
- package/dist/{serialization-DpLXCy13.mjs → serialization-C8Mnw9hK.mjs} +1 -1
- package/dist/{server-DykHCza_.mjs → server-CXaDDUl0.mjs} +2 -2
- package/dist/{server-B0wiP_Oi.d.mts → server-E9z4ZWbd.d.mts} +4 -3
- package/dist/simple-schema-BDzLeJDk.d.mts +102 -0
- package/dist/simple-schema-DQPZrAaZ.mjs +154 -0
- package/dist/{state-WX3HT5a3.mjs → state-BeUHDDjk.mjs} +13 -6
- package/dist/{storage-gEnj9ASQ.mjs → storage-Dzoc3NVC.mjs} +2 -66
- package/dist/{transports-BmDVn4SF.mjs → transports-vhizgqXM.mjs} +1 -1
- package/dist/types/index.d.mts +4 -4
- package/dist/{types-CrzNxXKq.d.mts → types-CnJSgRVa.d.mts} +33 -19
- package/dist/utils/agent-tool-name.d.mts +27 -0
- package/dist/utils/agent-tool-name.mjs +34 -0
- package/dist/utils/events.d.mts +1 -1
- package/dist/utils/shared-state.d.mts +1 -1
- package/dist/utils/simple-schema.d.mts +2 -0
- package/dist/utils/simple-schema.mjs +154 -0
- package/dist/utils/streaming-channel.d.mts +1 -1
- package/dist/{ws-client-DSXiI2h7.d.mts → ws-client-B6Tnr0ic.d.mts} +1 -1
- package/dist/{ws-server-9-wn7MNQ.d.mts → ws-server-J-zkiOyp.d.mts} +24 -3
- package/package.json +18 -7
- package/skills/devframe/SKILL.md +4 -3
- package/dist/build-server-C7vTKjiQ.mjs +0 -359
- package/dist/http-_pPbryTQ.mjs +0 -114
package/dist/client/index.mjs
CHANGED
|
@@ -20,11 +20,14 @@ const DEVFRAME_CONNECTION_META_FILENAME = "__connection.json";
|
|
|
20
20
|
const DEVFRAME_CONNECTION_KEY = "__DEVFRAME_CONNECTION__";
|
|
21
21
|
const DEVFRAME_RPC_DUMP_MANIFEST_FILENAME = "__rpc-dump/index.json";
|
|
22
22
|
/**
|
|
23
|
-
* Page-URL
|
|
24
|
-
* "magic link" auth. A host can print a link like
|
|
25
|
-
* the client reads the code, exchanges it for a
|
|
26
|
-
* from the URL.
|
|
27
|
-
*
|
|
23
|
+
* Page-URL **fragment** parameter carrying a one-time authentication code (OTP)
|
|
24
|
+
* for "magic link" auth. A host can print a link like
|
|
25
|
+
* `<origin>/#devframe_otp=<code>`; the client reads the code, exchanges it for a
|
|
26
|
+
* token, and strips the parameter from the URL. The code rides the fragment
|
|
27
|
+
* (never the query string) so the browser never transmits it to the server,
|
|
28
|
+
* keeping it out of access logs and `Referer` headers. See `buildOtpAuthUrl`
|
|
29
|
+
* (node) and the `authenticateWithUrlOtp` / `consumeOtpFromUrl` client utilities
|
|
30
|
+
* (or `connectDevframe`'s `otpParam`).
|
|
28
31
|
*/
|
|
29
32
|
const DEVFRAME_OTP_URL_PARAM = "devframe_otp";
|
|
30
33
|
/**
|
|
@@ -35,6 +38,10 @@ const DEVFRAME_OTP_URL_PARAM = "devframe_otp";
|
|
|
35
38
|
* trusted before its own `anonymous:devframe:auth` handshake call arrives.
|
|
36
39
|
*/
|
|
37
40
|
const DEVFRAME_AUTH_TOKEN_QUERY_PARAM = "devframe_auth_token";
|
|
41
|
+
/** External viewer origin requested during connection bootstrap. */
|
|
42
|
+
const DEVFRAME_VIEWER_ORIGIN_QUERY_PARAM = "devframe_viewer_origin";
|
|
43
|
+
/** Token that authorizes an external viewer origin registration. */
|
|
44
|
+
const DEVFRAME_VIEWER_ORIGIN_TOKEN_QUERY_PARAM = "devframe_viewer_origin_token";
|
|
38
45
|
//#endregion
|
|
39
46
|
//#region src/utils/diagnostics-reporter.ts
|
|
40
47
|
const formatAnsi = ansiFormatter(colors);
|
|
@@ -68,6 +75,14 @@ const diagnostics = defineDiagnostics({
|
|
|
68
75
|
DF0028: {
|
|
69
76
|
why: (p) => `Function "${p.name}" with type "${p.type}" cannot use \`snapshot: true\`. Only "query" functions support this sugar; "static" functions have equivalent default behavior already.`,
|
|
70
77
|
fix: "Remove `snapshot: true`, or change the function type to `query`."
|
|
78
|
+
},
|
|
79
|
+
DF0043: {
|
|
80
|
+
why: (p) => `RPC function "${p.name}" received an invalid argument at position ${p.index}: ${p.issues}`,
|
|
81
|
+
fix: "Pass a value that satisfies the `args` schema declared for this function."
|
|
82
|
+
},
|
|
83
|
+
DF0044: {
|
|
84
|
+
why: (p) => `RPC function "${p.name}" returned a value that failed its \`returns\` schema: ${p.issues}`,
|
|
85
|
+
fix: "Make the handler return a value that satisfies the `returns` schema, or relax the schema."
|
|
71
86
|
}
|
|
72
87
|
}
|
|
73
88
|
});
|
|
@@ -92,6 +107,70 @@ function isPlainErrorShape(value) {
|
|
|
92
107
|
return typeof value === "object" && value !== null && typeof value.message === "string" && typeof value.name === "string";
|
|
93
108
|
}
|
|
94
109
|
//#endregion
|
|
110
|
+
//#region src/rpc/validate-io.ts
|
|
111
|
+
/**
|
|
112
|
+
* Run a single [Standard Schema](https://standardschema.dev) validator,
|
|
113
|
+
* awaiting the result when the validator is asynchronous.
|
|
114
|
+
*/
|
|
115
|
+
async function runStandardSchema(schema, value) {
|
|
116
|
+
const result = schema["~standard"].validate(value);
|
|
117
|
+
return result instanceof Promise ? await result : result;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Render Standard Schema issues into a single human-readable line for a
|
|
121
|
+
* diagnostic message, prefixing each with its dotted path when present.
|
|
122
|
+
*/
|
|
123
|
+
function formatIssues(issues) {
|
|
124
|
+
return issues.map((issue) => {
|
|
125
|
+
const path = issue.path?.map((segment) => typeof segment === "object" ? segment.key : segment).join(".");
|
|
126
|
+
return path ? `${path}: ${issue.message}` : issue.message;
|
|
127
|
+
}).join("; ");
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Validate positional arguments against their declared schemas. Only
|
|
131
|
+
* indices with a schema are checked; extra arguments pass through
|
|
132
|
+
* untouched. Throws `DF0038` on the first failing argument.
|
|
133
|
+
*
|
|
134
|
+
* Validation guards the payload without rewriting it: the original values
|
|
135
|
+
* are handed to the handler unchanged, so a schema that describes a subset
|
|
136
|
+
* of an object never silently strips the sender's extra fields (and any
|
|
137
|
+
* declared transforms stay a purely type-level concern).
|
|
138
|
+
*
|
|
139
|
+
* @internal
|
|
140
|
+
*/
|
|
141
|
+
async function validateRpcArgs(name, argsSchema, args) {
|
|
142
|
+
const original = args.slice();
|
|
143
|
+
if (!argsSchema || argsSchema.length === 0) return original;
|
|
144
|
+
for (let index = 0; index < argsSchema.length; index++) {
|
|
145
|
+
const schema = argsSchema[index];
|
|
146
|
+
if (!schema) continue;
|
|
147
|
+
const result = await runStandardSchema(schema, args[index]);
|
|
148
|
+
if (result.issues) throw diagnostics.DF0043({
|
|
149
|
+
name,
|
|
150
|
+
index,
|
|
151
|
+
issues: formatIssues(result.issues)
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
return original;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Validate a handler's resolved return value against its declared schema.
|
|
158
|
+
* Throws `DF0039` when the value fails the schema, otherwise returns the
|
|
159
|
+
* original value unchanged (guard-only, never rewriting the payload — see
|
|
160
|
+
* {@link validateRpcArgs}). Passes through when no return schema is set.
|
|
161
|
+
*
|
|
162
|
+
* @internal
|
|
163
|
+
*/
|
|
164
|
+
async function validateRpcReturn(name, returnSchema, value) {
|
|
165
|
+
if (!returnSchema) return value;
|
|
166
|
+
const result = await runStandardSchema(returnSchema, value);
|
|
167
|
+
if (result.issues) throw diagnostics.DF0044({
|
|
168
|
+
name,
|
|
169
|
+
issues: formatIssues(result.issues)
|
|
170
|
+
});
|
|
171
|
+
return value;
|
|
172
|
+
}
|
|
173
|
+
//#endregion
|
|
95
174
|
//#region src/rpc/handler.ts
|
|
96
175
|
async function getRpcResolvedSetupResult(definition, context) {
|
|
97
176
|
if (!definition.setup) return {};
|
|
@@ -118,10 +197,22 @@ async function getRpcResolvedSetupResult(definition, context) {
|
|
|
118
197
|
return await definition.__promise;
|
|
119
198
|
}
|
|
120
199
|
async function getRpcHandler(definition, context) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
200
|
+
let handler = definition.handler;
|
|
201
|
+
if (!handler) {
|
|
202
|
+
const result = await getRpcResolvedSetupResult(definition, context);
|
|
203
|
+
if (!result.handler) throw diagnostics.DF0024({ name: definition.name });
|
|
204
|
+
handler = result.handler;
|
|
205
|
+
}
|
|
206
|
+
const argsSchema = definition.args;
|
|
207
|
+
const returnSchema = definition.returns;
|
|
208
|
+
if (!argsSchema && !returnSchema) return handler;
|
|
209
|
+
const inner = handler;
|
|
210
|
+
const validating = async (...args) => {
|
|
211
|
+
const validatedArgs = await validateRpcArgs(definition.name, argsSchema, args);
|
|
212
|
+
const output = await inner(...validatedArgs);
|
|
213
|
+
return await validateRpcReturn(definition.name, returnSchema, output);
|
|
214
|
+
};
|
|
215
|
+
return validating;
|
|
125
216
|
}
|
|
126
217
|
//#endregion
|
|
127
218
|
//#region src/rpc/cache.ts
|
|
@@ -344,6 +435,21 @@ function storeAuthToken(token) {
|
|
|
344
435
|
}
|
|
345
436
|
//#endregion
|
|
346
437
|
//#region src/client/connection.ts
|
|
438
|
+
/**
|
|
439
|
+
* Allow an external viewer to connect by registering its browser origin with
|
|
440
|
+
* the Devframe host. Returns `false` if the host did not provide an origin
|
|
441
|
+
* registration token.
|
|
442
|
+
*/
|
|
443
|
+
async function registerDevframeViewerOrigin(connection, origin = globalThis.location?.origin) {
|
|
444
|
+
const token = connection.connectionMeta.viewerOriginToken;
|
|
445
|
+
if (!token || !origin) return false;
|
|
446
|
+
const url = new URL(connection.metaBaseUrl);
|
|
447
|
+
url.searchParams.set(DEVFRAME_VIEWER_ORIGIN_QUERY_PARAM, origin);
|
|
448
|
+
url.searchParams.set(DEVFRAME_VIEWER_ORIGIN_TOKEN_QUERY_PARAM, token);
|
|
449
|
+
const response = await fetch(url, { cache: "no-store" });
|
|
450
|
+
if (!response.ok) throw new Error(`Failed to register external viewer origin (${response.status}).`);
|
|
451
|
+
return true;
|
|
452
|
+
}
|
|
347
453
|
function resolveMetaBaseUrl(baseURL) {
|
|
348
454
|
const metaPath = withBase(DEVFRAME_CONNECTION_META_FILENAME, baseURL);
|
|
349
455
|
try {
|
|
@@ -446,12 +552,14 @@ function isCallableStatus(status) {
|
|
|
446
552
|
//#endregion
|
|
447
553
|
//#region src/client/otp.ts
|
|
448
554
|
/**
|
|
449
|
-
* Read a one-time authentication code (OTP) from the current page URL's
|
|
450
|
-
*
|
|
555
|
+
* Read a one-time authentication code (OTP) from the current page URL's
|
|
556
|
+
* fragment, without side effects. Returns `undefined` when the parameter is
|
|
557
|
+
* absent.
|
|
451
558
|
*/
|
|
452
559
|
function readOtpFromUrl(param = DEVFRAME_OTP_URL_PARAM) {
|
|
453
560
|
try {
|
|
454
|
-
|
|
561
|
+
const hash = globalThis.location?.hash?.replace(/^#/, "") ?? "";
|
|
562
|
+
return new URLSearchParams(hash).get(param) || void 0;
|
|
455
563
|
} catch {
|
|
456
564
|
return;
|
|
457
565
|
}
|
|
@@ -459,16 +567,18 @@ function readOtpFromUrl(param = DEVFRAME_OTP_URL_PARAM) {
|
|
|
459
567
|
function stripParamFromUrl(param) {
|
|
460
568
|
try {
|
|
461
569
|
const url = new URL(globalThis.location.href);
|
|
462
|
-
|
|
463
|
-
|
|
570
|
+
const fragment = new URLSearchParams(url.hash.replace(/^#/, ""));
|
|
571
|
+
if (!fragment.has(param)) return;
|
|
572
|
+
fragment.delete(param);
|
|
573
|
+
url.hash = fragment.toString();
|
|
464
574
|
globalThis.history?.replaceState(globalThis.history.state, "", url.href);
|
|
465
575
|
} catch {}
|
|
466
576
|
}
|
|
467
577
|
/**
|
|
468
|
-
* Read the one-time code from the page URL and remove it from the
|
|
469
|
-
* (and the current history entry), so the single-use code isn't
|
|
470
|
-
* URL, browser history, or a `Referer`. Returns the code, or
|
|
471
|
-
* absent.
|
|
578
|
+
* Read the one-time code from the page URL fragment and remove it from the
|
|
579
|
+
* address bar (and the current history entry), so the single-use code isn't
|
|
580
|
+
* left in the URL, browser history, or a `Referer`. Returns the code, or
|
|
581
|
+
* `undefined` when absent.
|
|
472
582
|
*/
|
|
473
583
|
function consumeOtpFromUrl(param = DEVFRAME_OTP_URL_PARAM) {
|
|
474
584
|
const code = readOtpFromUrl(param);
|
|
@@ -2504,4 +2614,4 @@ async function getDevframeRpcClient(options = {}) {
|
|
|
2504
2614
|
//#region src/client/index.ts
|
|
2505
2615
|
const connectDevframe = getDevframeRpcClient;
|
|
2506
2616
|
//#endregion
|
|
2507
|
-
export { DevframeConnectionError, authenticateWithUrlOtp, connectDevframe, consumeOtpFromUrl, createClientSettings, createRpcStreamingClientHost, createScopedClientContext, getDevframeConnection, getDevframeRpcClient, isCallableStatus, readOtpFromUrl, setupDevframeConnection };
|
|
2617
|
+
export { DevframeConnectionError, authenticateWithUrlOtp, connectDevframe, consumeOtpFromUrl, createClientSettings, createRpcStreamingClientHost, createScopedClientContext, getDevframeConnection, getDevframeRpcClient, isCallableStatus, readOtpFromUrl, registerDevframeViewerOrigin, resolveWsUrl, setupDevframeConnection };
|
package/dist/constants.d.mts
CHANGED
|
@@ -35,11 +35,14 @@ declare const DEVFRAME_RPC_DUMP_DIRNAME = "__rpc-dump";
|
|
|
35
35
|
*/
|
|
36
36
|
declare const REMOTE_CONNECTION_KEY = "devframe-remote-connection";
|
|
37
37
|
/**
|
|
38
|
-
* Page-URL
|
|
39
|
-
* "magic link" auth. A host can print a link like
|
|
40
|
-
* the client reads the code, exchanges it for a
|
|
41
|
-
* from the URL.
|
|
42
|
-
*
|
|
38
|
+
* Page-URL **fragment** parameter carrying a one-time authentication code (OTP)
|
|
39
|
+
* for "magic link" auth. A host can print a link like
|
|
40
|
+
* `<origin>/#devframe_otp=<code>`; the client reads the code, exchanges it for a
|
|
41
|
+
* token, and strips the parameter from the URL. The code rides the fragment
|
|
42
|
+
* (never the query string) so the browser never transmits it to the server,
|
|
43
|
+
* keeping it out of access logs and `Referer` headers. See `buildOtpAuthUrl`
|
|
44
|
+
* (node) and the `authenticateWithUrlOtp` / `consumeOtpFromUrl` client utilities
|
|
45
|
+
* (or `connectDevframe`'s `otpParam`).
|
|
43
46
|
*/
|
|
44
47
|
declare const DEVFRAME_OTP_URL_PARAM = "devframe_otp";
|
|
45
48
|
/**
|
|
@@ -50,6 +53,10 @@ declare const DEVFRAME_OTP_URL_PARAM = "devframe_otp";
|
|
|
50
53
|
* trusted before its own `anonymous:devframe:auth` handshake call arrives.
|
|
51
54
|
*/
|
|
52
55
|
declare const DEVFRAME_AUTH_TOKEN_QUERY_PARAM = "devframe_auth_token";
|
|
56
|
+
/** External viewer origin requested during connection bootstrap. */
|
|
57
|
+
declare const DEVFRAME_VIEWER_ORIGIN_QUERY_PARAM = "devframe_viewer_origin";
|
|
58
|
+
/** Token that authorizes an external viewer origin registration. */
|
|
59
|
+
declare const DEVFRAME_VIEWER_ORIGIN_TOKEN_QUERY_PARAM = "devframe_viewer_origin_token";
|
|
53
60
|
/**
|
|
54
61
|
* Prefix that marks an RPC method as callable before a connection is
|
|
55
62
|
* trusted. This is the *only* rule the pre-trust gate applies — there is no
|
|
@@ -66,4 +73,4 @@ declare const ANONYMOUS_RPC_PREFIX = "anonymous:";
|
|
|
66
73
|
*/
|
|
67
74
|
declare function isAnonymousRpcMethod(name: string): boolean;
|
|
68
75
|
//#endregion
|
|
69
|
-
export { ANONYMOUS_RPC_PREFIX, DEVFRAME_AUTH_TOKEN_QUERY_PARAM, DEVFRAME_CONNECTION_KEY, DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_DIRNAME, DEVFRAME_DOCK_IMPORTS_FILENAME, DEVFRAME_DOCK_IMPORTS_VIRTUAL_ID, DEVFRAME_MCP_ROUTE, DEVFRAME_MOUNT_PATH, DEVFRAME_MOUNT_PATH_NO_TRAILING_SLASH, DEVFRAME_OTP_URL_PARAM, DEVFRAME_RPC_DUMP_DIRNAME, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME, DEVFRAME_WS_ROUTE, REMOTE_CONNECTION_KEY, isAnonymousRpcMethod };
|
|
76
|
+
export { ANONYMOUS_RPC_PREFIX, DEVFRAME_AUTH_TOKEN_QUERY_PARAM, DEVFRAME_CONNECTION_KEY, DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_DIRNAME, DEVFRAME_DOCK_IMPORTS_FILENAME, DEVFRAME_DOCK_IMPORTS_VIRTUAL_ID, DEVFRAME_MCP_ROUTE, DEVFRAME_MOUNT_PATH, DEVFRAME_MOUNT_PATH_NO_TRAILING_SLASH, DEVFRAME_OTP_URL_PARAM, DEVFRAME_RPC_DUMP_DIRNAME, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME, DEVFRAME_VIEWER_ORIGIN_QUERY_PARAM, DEVFRAME_VIEWER_ORIGIN_TOKEN_QUERY_PARAM, DEVFRAME_WS_ROUTE, REMOTE_CONNECTION_KEY, isAnonymousRpcMethod };
|
package/dist/constants.mjs
CHANGED
|
@@ -35,11 +35,14 @@ const DEVFRAME_RPC_DUMP_DIRNAME = "__rpc-dump";
|
|
|
35
35
|
*/
|
|
36
36
|
const REMOTE_CONNECTION_KEY = "devframe-remote-connection";
|
|
37
37
|
/**
|
|
38
|
-
* Page-URL
|
|
39
|
-
* "magic link" auth. A host can print a link like
|
|
40
|
-
* the client reads the code, exchanges it for a
|
|
41
|
-
* from the URL.
|
|
42
|
-
*
|
|
38
|
+
* Page-URL **fragment** parameter carrying a one-time authentication code (OTP)
|
|
39
|
+
* for "magic link" auth. A host can print a link like
|
|
40
|
+
* `<origin>/#devframe_otp=<code>`; the client reads the code, exchanges it for a
|
|
41
|
+
* token, and strips the parameter from the URL. The code rides the fragment
|
|
42
|
+
* (never the query string) so the browser never transmits it to the server,
|
|
43
|
+
* keeping it out of access logs and `Referer` headers. See `buildOtpAuthUrl`
|
|
44
|
+
* (node) and the `authenticateWithUrlOtp` / `consumeOtpFromUrl` client utilities
|
|
45
|
+
* (or `connectDevframe`'s `otpParam`).
|
|
43
46
|
*/
|
|
44
47
|
const DEVFRAME_OTP_URL_PARAM = "devframe_otp";
|
|
45
48
|
/**
|
|
@@ -50,6 +53,10 @@ const DEVFRAME_OTP_URL_PARAM = "devframe_otp";
|
|
|
50
53
|
* trusted before its own `anonymous:devframe:auth` handshake call arrives.
|
|
51
54
|
*/
|
|
52
55
|
const DEVFRAME_AUTH_TOKEN_QUERY_PARAM = "devframe_auth_token";
|
|
56
|
+
/** External viewer origin requested during connection bootstrap. */
|
|
57
|
+
const DEVFRAME_VIEWER_ORIGIN_QUERY_PARAM = "devframe_viewer_origin";
|
|
58
|
+
/** Token that authorizes an external viewer origin registration. */
|
|
59
|
+
const DEVFRAME_VIEWER_ORIGIN_TOKEN_QUERY_PARAM = "devframe_viewer_origin_token";
|
|
53
60
|
/**
|
|
54
61
|
* Prefix that marks an RPC method as callable before a connection is
|
|
55
62
|
* trusted. This is the *only* rule the pre-trust gate applies — there is no
|
|
@@ -68,4 +75,4 @@ function isAnonymousRpcMethod(name) {
|
|
|
68
75
|
return name.startsWith(ANONYMOUS_RPC_PREFIX);
|
|
69
76
|
}
|
|
70
77
|
//#endregion
|
|
71
|
-
export { ANONYMOUS_RPC_PREFIX, DEVFRAME_AUTH_TOKEN_QUERY_PARAM, DEVFRAME_CONNECTION_KEY, DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_DIRNAME, DEVFRAME_DOCK_IMPORTS_FILENAME, DEVFRAME_DOCK_IMPORTS_VIRTUAL_ID, DEVFRAME_MCP_ROUTE, DEVFRAME_MOUNT_PATH, DEVFRAME_MOUNT_PATH_NO_TRAILING_SLASH, DEVFRAME_OTP_URL_PARAM, DEVFRAME_RPC_DUMP_DIRNAME, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME, DEVFRAME_WS_ROUTE, REMOTE_CONNECTION_KEY, isAnonymousRpcMethod };
|
|
78
|
+
export { ANONYMOUS_RPC_PREFIX, DEVFRAME_AUTH_TOKEN_QUERY_PARAM, DEVFRAME_CONNECTION_KEY, DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_DIRNAME, DEVFRAME_DOCK_IMPORTS_FILENAME, DEVFRAME_DOCK_IMPORTS_VIRTUAL_ID, DEVFRAME_MCP_ROUTE, DEVFRAME_MOUNT_PATH, DEVFRAME_MOUNT_PATH_NO_TRAILING_SLASH, DEVFRAME_OTP_URL_PARAM, DEVFRAME_RPC_DUMP_DIRNAME, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME, DEVFRAME_VIEWER_ORIGIN_QUERY_PARAM, DEVFRAME_VIEWER_ORIGIN_TOKEN_QUERY_PARAM, DEVFRAME_WS_ROUTE, REMOTE_CONNECTION_KEY, isAnonymousRpcMethod };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { n as randomToken } from "./crypto-token-XCqTSMg9.mjs";
|
|
2
|
+
import { t as createStorage } from "./storage-Dzoc3NVC.mjs";
|
|
3
|
+
import { n as revokeAuthToken, t as revokeActiveConnectionsForToken } from "./revoke-DZbJ7Cl0.mjs";
|
|
3
4
|
import { join } from "pathe";
|
|
4
5
|
//#region src/node/hub-internals/context.ts
|
|
5
6
|
const internalContextMap = /* @__PURE__ */ new WeakMap();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { b as DevframeNodeContext, ht as SharedState } from "./devframe-
|
|
1
|
+
import { b as DevframeNodeContext, ht as SharedState } from "./devframe-qgCKL683.mjs";
|
|
2
2
|
//#region src/node/hub-internals/context.d.ts
|
|
3
3
|
interface InternalAnonymousAuthStorage {
|
|
4
4
|
trusted: Record<string, {
|
|
@@ -42,38 +42,4 @@ function timingSafeEqual(a, b) {
|
|
|
42
42
|
return mismatch === 0;
|
|
43
43
|
}
|
|
44
44
|
//#endregion
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Flip `isTrusted` to false on any live WS clients connected with `token`
|
|
48
|
-
* and broadcast the `auth:revoked` event so they can react.
|
|
49
|
-
*
|
|
50
|
-
* Shared between persisted-auth revocation and remote-dock token revocation.
|
|
51
|
-
*/
|
|
52
|
-
async function revokeActiveConnectionsForToken(context, token) {
|
|
53
|
-
const rpcHost = context.rpc;
|
|
54
|
-
if (!rpcHost?._rpcGroup) return;
|
|
55
|
-
const affectedSessionIds = /* @__PURE__ */ new Set();
|
|
56
|
-
for (const client of rpcHost._rpcGroup.clients) if (client.$meta.clientAuthToken === token) {
|
|
57
|
-
affectedSessionIds.add(client.$meta.id);
|
|
58
|
-
client.$meta.isTrusted = false;
|
|
59
|
-
client.$meta.clientAuthToken = void 0;
|
|
60
|
-
}
|
|
61
|
-
if (affectedSessionIds.size === 0) return;
|
|
62
|
-
await rpcHost.broadcast({
|
|
63
|
-
method: "devframe:auth:revoked",
|
|
64
|
-
args: [],
|
|
65
|
-
filter: (client) => affectedSessionIds.has(client.$meta.id)
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Revoke an auth token: remove from storage and notify all connected clients
|
|
70
|
-
* using this token that they are no longer trusted.
|
|
71
|
-
*/
|
|
72
|
-
async function revokeAuthToken(context, storage, token) {
|
|
73
|
-
storage.mutate((state) => {
|
|
74
|
-
delete state.trusted[token];
|
|
75
|
-
});
|
|
76
|
-
await revokeActiveConnectionsForToken(context, token);
|
|
77
|
-
}
|
|
78
|
-
//#endregion
|
|
79
|
-
export { timingSafeEqual as a, randomToken as i, revokeAuthToken as n, randomDigits as r, revokeActiveConnectionsForToken as t };
|
|
45
|
+
export { randomToken as n, timingSafeEqual as r, randomDigits as t };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { DEVFRAME_CONNECTION_META_FILENAME } from "./constants.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { n as createHostContext, t as createH3DevframeHost } from "./host-h3-Kz7t5Xab.mjs";
|
|
3
|
+
import { t as diagnostics } from "./diagnostics-B5-qHeqD.mjs";
|
|
4
|
+
import { r as registerDevframeInstance } from "./instance-registry-D6fxYu36.mjs";
|
|
5
|
+
import { i as normalizeHttpServerUrl, t as startHttpAndWs } from "./server-CXaDDUl0.mjs";
|
|
5
6
|
import { n as resolveBasePath, t as normalizeBasePath } from "./_shared-bWRzeSa0.mjs";
|
|
6
7
|
import { t as open } from "./open-Deb5xmIT.mjs";
|
|
7
8
|
import { mountStaticHandler } from "./utils/serve-static.mjs";
|
|
@@ -294,7 +295,7 @@ async function createDevServer(def, options = {}) {
|
|
|
294
295
|
const mcpPath = joinURL(basePath, mcpRoute);
|
|
295
296
|
let mountMcpHttp;
|
|
296
297
|
try {
|
|
297
|
-
({mountMcpHttp} = await import("./http-
|
|
298
|
+
({mountMcpHttp} = await import("./http-Dvgxujcu.mjs"));
|
|
298
299
|
} catch (error) {
|
|
299
300
|
const reason = error instanceof Error ? error.message : String(error);
|
|
300
301
|
throw diagnostics.DF0017({
|
|
@@ -344,13 +345,23 @@ async function createDevServer(def, options = {}) {
|
|
|
344
345
|
await maybeOpenBrowser(def, flags, `${info.origin}${basePath}`, options.openBrowser, authHandler);
|
|
345
346
|
}
|
|
346
347
|
});
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
started.
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
348
|
+
const registration = registerDevframeInstance({
|
|
349
|
+
pid: process$1.pid,
|
|
350
|
+
port: started.port,
|
|
351
|
+
origin: normalizeHttpServerUrl(host, started.port),
|
|
352
|
+
basePath,
|
|
353
|
+
id: def.id,
|
|
354
|
+
name: def.name,
|
|
355
|
+
rootDir: process$1.cwd(),
|
|
356
|
+
mcp: mcpConfig ? { path: joinURL(basePath, withoutLeadingSlash(mcpConfig.path ?? "__mcp")) } : null,
|
|
357
|
+
startedAt: Date.now()
|
|
358
|
+
});
|
|
359
|
+
const closeServer = started.close;
|
|
360
|
+
started.close = async () => {
|
|
361
|
+
registration.unregister();
|
|
362
|
+
await mcpDispose?.();
|
|
363
|
+
await closeServer();
|
|
364
|
+
};
|
|
354
365
|
return started;
|
|
355
366
|
}
|
|
356
367
|
/**
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { _ as RpcFunctionDefinition, v as RpcFunctionDefinitionAny } from "./types-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { _ as RpcFunctionDefinition, v as RpcFunctionDefinitionAny } from "./types-CnJSgRVa.mjs";
|
|
2
|
+
import { w as RpcFunctionsCollectorBase } from "./index-Dbw1p5ch.mjs";
|
|
3
|
+
import { n as DevframeNodeRpcSessionMeta } from "./ws-server-J-zkiOyp.mjs";
|
|
4
4
|
import { CAC } from "cac";
|
|
5
|
-
import {
|
|
5
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
6
6
|
import { Peer } from "crossws";
|
|
7
7
|
import { BirpcReturn } from "birpc";
|
|
8
8
|
import { Diagnostic, DiagnosticDefinition, defineDiagnostics } from "nostics";
|
|
@@ -10,11 +10,12 @@ import { Diagnostic, DiagnosticDefinition, defineDiagnostics } from "nostics";
|
|
|
10
10
|
/**
|
|
11
11
|
* Schema map for typed CLI flags. Keys are flag names in camelCase —
|
|
12
12
|
* this matches CAC's parsed-flag output ( `--no-open` → `noOpen` ). Each
|
|
13
|
-
* value is
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* value is any [Standard Schema](https://standardschema.dev/) validator
|
|
14
|
+
* (valibot, zod, arktype, devframe's built-in `s`, …) used to both (a)
|
|
15
|
+
* derive the CAC option type when the flag is registered and (b) validate
|
|
16
|
+
* the parsed value before it's forwarded to `setup(ctx, { flags })`.
|
|
16
17
|
*/
|
|
17
|
-
type CliFlagsSchema = Record<string,
|
|
18
|
+
type CliFlagsSchema = Record<string, StandardSchemaV1>;
|
|
18
19
|
/**
|
|
19
20
|
* Identity helper that preserves the literal schema-map type — use this
|
|
20
21
|
* so `InferCliFlags<typeof myFlags>` resolves to the right object shape.
|
|
@@ -37,8 +38,8 @@ type CliFlagsSchema = Record<string, GenericSchema>;
|
|
|
37
38
|
*/
|
|
38
39
|
declare function defineCliFlags<T extends CliFlagsSchema>(flags: T): T;
|
|
39
40
|
/** Extract the parsed-output type from a {@link CliFlagsSchema}. */
|
|
40
|
-
type InferCliFlags<T extends CliFlagsSchema> = { [K in keyof T]: InferOutput<T[K]>; };
|
|
41
|
-
/** Validate
|
|
41
|
+
type InferCliFlags<T extends CliFlagsSchema> = { [K in keyof T]: StandardSchemaV1.InferOutput<T[K]>; };
|
|
42
|
+
/** Validate the raw cac-parsed bag against a {@link CliFlagsSchema}. */
|
|
42
43
|
declare function parseCliFlags(schema: CliFlagsSchema, raw: Record<string, unknown>): {
|
|
43
44
|
flags: Record<string, unknown>;
|
|
44
45
|
issues?: string[];
|
|
@@ -138,6 +139,14 @@ interface AgentTool {
|
|
|
138
139
|
tags?: readonly string[];
|
|
139
140
|
/** Present for `kind === 'rpc'` — points to the RPC function name. */
|
|
140
141
|
rpcName?: string;
|
|
142
|
+
/**
|
|
143
|
+
* Positional Standard Schemas describing a `kind: 'tool'` entry's
|
|
144
|
+
* arguments — carried on the tool itself (mirroring how `rpcName` defers
|
|
145
|
+
* an RPC-backed tool's schemas to `ctx.rpc.definitions`) so consumers
|
|
146
|
+
* (e.g. the MCP adapter) convert Standard Schema → JSON Schema on demand,
|
|
147
|
+
* same as RPC `args`.
|
|
148
|
+
*/
|
|
149
|
+
args?: readonly StandardSchemaV1[];
|
|
141
150
|
/** JSON Schema describing the input (positional args synthesized to an object). */
|
|
142
151
|
inputSchema?: unknown;
|
|
143
152
|
/** JSON Schema describing the output. */
|
|
@@ -160,6 +169,17 @@ interface AgentToolInput {
|
|
|
160
169
|
description: string;
|
|
161
170
|
safety?: 'read' | 'action' | 'destructive';
|
|
162
171
|
tags?: readonly string[];
|
|
172
|
+
/**
|
|
173
|
+
* Positional Standard Schemas describing the tool's arguments — the same
|
|
174
|
+
* shape RPC definitions carry (any [Standard Schema](https://standardschema.dev/)
|
|
175
|
+
* validator: valibot, zod, arktype, devframe's built-in `s` builder, …).
|
|
176
|
+
* Each is advertised under `arg0` / `arg1` / … on the tool's JSON-Schema
|
|
177
|
+
* input, matching how the agent bridge coerces the incoming payload back
|
|
178
|
+
* into positional arguments. Purely descriptive: the handler still
|
|
179
|
+
* receives the caller's args object as-is.
|
|
180
|
+
*/
|
|
181
|
+
args?: readonly StandardSchemaV1[];
|
|
182
|
+
/** Raw JSON-Schema input override. Prefer {@link args}. */
|
|
163
183
|
inputSchema?: unknown;
|
|
164
184
|
outputSchema?: unknown;
|
|
165
185
|
examples?: readonly {
|
|
@@ -227,6 +247,33 @@ interface AgentManifest {
|
|
|
227
247
|
interface AgentHandle {
|
|
228
248
|
unregister: () => void;
|
|
229
249
|
}
|
|
250
|
+
/**
|
|
251
|
+
* A lazy source of agent tools, queried at `list()` / `getTool()` /
|
|
252
|
+
* `invoke()` time — the same on-demand projection the host applies to
|
|
253
|
+
* `agent`-flagged RPC definitions. Use a provider when tools *derive from*
|
|
254
|
+
* other state (a command registry, a plugin catalog): the underlying state
|
|
255
|
+
* stays the single source of truth and nothing needs to be kept in sync.
|
|
256
|
+
*
|
|
257
|
+
* Providers should namespace tool ids like any other tool; on an id
|
|
258
|
+
* collision the earlier source wins (registered tools, then RPC tools,
|
|
259
|
+
* then providers in registration order).
|
|
260
|
+
*
|
|
261
|
+
* @experimental
|
|
262
|
+
*/
|
|
263
|
+
type AgentToolProvider = () => readonly AgentToolInput[];
|
|
264
|
+
/**
|
|
265
|
+
* Handle returned by `registerToolProvider`.
|
|
266
|
+
*
|
|
267
|
+
* @experimental
|
|
268
|
+
*/
|
|
269
|
+
interface AgentToolProviderHandle extends AgentHandle {
|
|
270
|
+
/**
|
|
271
|
+
* Signal that the provider's tool set changed. Fires
|
|
272
|
+
* `agent:manifest:changed` so protocol adapters (e.g. MCP) emit
|
|
273
|
+
* `tools/list_changed`.
|
|
274
|
+
*/
|
|
275
|
+
notifyChanged: () => void;
|
|
276
|
+
}
|
|
230
277
|
/**
|
|
231
278
|
* Events emitted by `DevframeAgentHost`.
|
|
232
279
|
*
|
|
@@ -262,6 +309,11 @@ interface DevframeAgentHost {
|
|
|
262
309
|
registerTool: (tool: AgentToolInput) => AgentHandle;
|
|
263
310
|
/** Unregister a previously registered tool by id. */
|
|
264
311
|
unregisterTool: (id: string) => boolean;
|
|
312
|
+
/**
|
|
313
|
+
* Register a lazy tool source, queried on demand — see
|
|
314
|
+
* {@link AgentToolProvider}.
|
|
315
|
+
*/
|
|
316
|
+
registerToolProvider: (provider: AgentToolProvider) => AgentToolProviderHandle;
|
|
265
317
|
/** Register a readable resource. */
|
|
266
318
|
registerResource: (resource: AgentResourceInput) => AgentHandle;
|
|
267
319
|
/** Unregister a previously registered resource by id. */
|
|
@@ -1362,6 +1414,15 @@ interface ConnectionMeta {
|
|
|
1362
1414
|
* > from a publicly reachable static `__connection.json`.
|
|
1363
1415
|
*/
|
|
1364
1416
|
authToken?: string;
|
|
1417
|
+
/**
|
|
1418
|
+
* Session-scoped token that lets a trusted external viewer register its
|
|
1419
|
+
* browser origin before opening the WebSocket. The host includes it in the
|
|
1420
|
+
* connection metadata, which the viewer obtains through the host page.
|
|
1421
|
+
*
|
|
1422
|
+
* Treat this as a bearer credential. Keep connection metadata containing the
|
|
1423
|
+
* token same-origin until the requesting origin has been verified.
|
|
1424
|
+
*/
|
|
1425
|
+
viewerOriginToken?: string;
|
|
1365
1426
|
}
|
|
1366
1427
|
//#endregion
|
|
1367
1428
|
//#region src/types/utils.d.ts
|
|
@@ -1579,10 +1640,11 @@ interface DevframeCliOptions {
|
|
|
1579
1640
|
*/
|
|
1580
1641
|
configure?: (cli: CAC) => void;
|
|
1581
1642
|
/**
|
|
1582
|
-
* Typed CLI flags for the default `dev` command, backed by
|
|
1583
|
-
*
|
|
1584
|
-
*
|
|
1585
|
-
* `
|
|
1643
|
+
* Typed CLI flags for the default `dev` command, backed by any
|
|
1644
|
+
* [Standard Schema](https://standardschema.dev/) validator (valibot,
|
|
1645
|
+
* zod, arktype, or devframe's built-in `s`). The adapter registers
|
|
1646
|
+
* matching `--kebab-key` options on CAC, validates the parsed values,
|
|
1647
|
+
* and forwards the typed bag to `setup(ctx, { flags })`.
|
|
1586
1648
|
*
|
|
1587
1649
|
* Use {@link defineCliFlags} to preserve the literal schema-map
|
|
1588
1650
|
* shape, and {@link InferCliFlags} to recover the typed output at the
|
|
@@ -1737,4 +1799,4 @@ interface DevframeDefinition {
|
|
|
1737
1799
|
}
|
|
1738
1800
|
declare function defineDevframe(d: DevframeDefinition): DevframeDefinition;
|
|
1739
1801
|
//#endregion
|
|
1740
|
-
export { DevframeRpcServerFunctions as $, DevframeSettingsStore as A,
|
|
1802
|
+
export { DevframeRpcServerFunctions as $, DevframeSettingsStore as A, DevframeAgentHostEvents as At, DevframeDefineDiagnosticsOptions as B, DevframeServicesHost as C, AgentResourceContent as Ct, DevframeScopedStreamingHost as D, AgentToolProvider as Dt, DevframeScopedNodeRpc as E, AgentToolInput as Et, ScopedSharedStates as F, InferCliFlags as Ft, RpcBroadcastOptions as G, DevframeDiagnosticsHost as H, SettingsForNamespace as I, defineCliFlags as It, RpcSharedStateHost as J, RpcFunctionsHost as K, DevframeViewHost as L, parseCliFlags as Lt, ScopedClientFunctions as M, EventUnsubscribe as Mt, ScopedRpcFn as N, EventsMap as Nt, DevframeSettings as O, AgentToolProviderHandle as Ot, ScopedServerFunctions as P, CliFlagsSchema as Pt, DevframeRpcClientFunctions as Q, DevframeHost as R, DevframeServiceOf as S, AgentResource as St, DevframeScopedNodeContext as T, AgentTool as Tt, DevframeDiagnosticsLogger as U, DevframeDiagnosticsDefinition as V, DevframeNodeRpcSession as W, RpcStreamingChannelOptions as X, RpcStreamingChannel as Y, RpcStreamingHost as Z, ConnectionMeta as _, SharedStateOptions as _t, DevframeDockDefaults as a, StreamReader as at, DevframeNodeContext as b, AgentHandle as bt, DevframeSetupInfo as c, createStreamReader as ct, McpRouteOptions as d, ImmutableArray as dt, DevframeRpcSharedStates as et, defineDevframe as f, ImmutableMap as ft, Thenable as g, SharedStateEvents as gt, PartialWithoutId as h, SharedState as ht, DevframeDeploymentKind as i, StreamErrorPayload as it, ScopedBroadcastOptions as j, EventEmitter as jt, DevframeSettingsRegistry as k, DevframeAgentHost as kt, DevframeSpaOptions as l, createStreamSink as lt, EntriesToObject as m, ImmutableSet as mt, DevframeCliOptions as n, CreateStreamReaderOptions as nt, DevframeDuplicationStrategy as o, StreamSink as ot, DevframeAuthHandler as p, ImmutableObject as pt, RpcSharedStateGetOptions as q, DevframeDefinition as r, CreateStreamSinkOptions as rt, DevframeRuntime as s, StreamSinkEvents as st, DevframeBrowserContext as t, BufferedChunk as tt, DevframeWsOptions as u, Immutable as ut, ConnectionMetaWebsocket as v, SharedStatePatch as vt, DevframeServicesRegistry as w, AgentResourceInput as wt, DevframeServiceId as x, AgentManifest as xt, DevframeCapabilities as y, createSharedState as yt, DevframeStorageScope as z };
|