@yanlinglabs/winter-agent-runtime 0.0.29 → 0.0.30
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/embedded-worker.js +6 -4
- package/dist/embedded.js +6 -4
- package/dist/engine.d.ts +16 -0
- package/dist/{index-jz5d90c6.js → index-51673qbw.js} +151 -120
- package/dist/{index-gmxxtqpe.js → index-9df1q7j4.js} +30 -12
- package/dist/{index-8jgwp1px.js → index-9s68t0pd.js} +170 -11
- package/dist/index-bgeqc7ax.js +52 -0
- package/dist/{index-eyddzcgs.js → index-wsfqsrh5.js} +2 -2
- package/dist/index-z6s3r4xm.js +903 -0
- package/dist/index.js +4 -2
- package/dist/mcp/client.d.ts +20 -1
- package/dist/mcp/lifecycle.d.ts +8 -0
- package/dist/mcp/transports/http.d.ts +10 -1
- package/dist/mcp/transports/sse.d.ts +4 -2
- package/dist/mcp-auth/account.d.ts +33 -0
- package/dist/mcp-auth/config.d.ts +6 -0
- package/dist/mcp-auth/constants.d.ts +30 -0
- package/dist/mcp-auth/discovery.d.ts +72 -0
- package/dist/mcp-auth/engine-wiring.d.ts +52 -0
- package/dist/mcp-auth/errors.d.ts +37 -0
- package/dist/mcp-auth/fetch-policy.d.ts +33 -0
- package/dist/mcp-auth/login.d.ts +59 -0
- package/dist/mcp-auth/records.d.ts +73 -0
- package/dist/mcp-auth/refresh.d.ts +34 -0
- package/dist/mcp-auth/revoke.d.ts +15 -0
- package/dist/mcp-auth/session-provider.d.ts +55 -0
- package/dist/mcp-auth/store.d.ts +85 -0
- package/dist/mcp-auth/test-fixture-as.d.ts +72 -0
- package/dist/mcp-auth.d.ts +14 -0
- package/dist/mcp-auth.js +493 -0
- package/dist/mcp-client.d.ts +12 -2
- package/dist/mcp-client.js +15 -2
- package/dist/production-wiring.d.ts +6 -0
- package/dist/provider/host-credentials.d.ts +48 -0
- package/dist/provider/keychain-store.d.ts +29 -1
- package/dist/provider/session-provider.d.ts +1 -1
- package/dist/store/dialect.d.ts +1 -1
- package/dist/testing.js +5 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -4
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
mcpOAuthTokenAccount2,
|
|
3
|
+
MCP_OAUTH_EXPIRY_SKEW_MS2,
|
|
4
|
+
MCP_OAUTH_SESSION_CACHE_MS2,
|
|
5
|
+
readTokenRecordLenient,
|
|
6
|
+
refreshMcpOAuthToken2
|
|
7
|
+
} from "./index-z6s3r4xm.js";
|
|
8
|
+
|
|
1
9
|
// src/process-groups.ts
|
|
2
10
|
var live = new Map;
|
|
3
11
|
var listeners = new Set;
|
|
@@ -109,8 +117,117 @@ function toWireElicitContent(content) {
|
|
|
109
117
|
return out;
|
|
110
118
|
}
|
|
111
119
|
|
|
120
|
+
// src/mcp-auth/session-provider.ts
|
|
121
|
+
class McpNeedsAuthError extends Error {
|
|
122
|
+
serverName;
|
|
123
|
+
constructor(serverName, why, hint) {
|
|
124
|
+
super(`MCP server "${serverName}" needs sign-in (${why}). ${hint}`);
|
|
125
|
+
this.name = "McpNeedsAuthError";
|
|
126
|
+
this.serverName = serverName;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
class McpAuthRefreshUnavailableError extends Error {
|
|
131
|
+
constructor(serverName) {
|
|
132
|
+
super(`MCP server "${serverName}": its sign-in could not be refreshed right now (the authorization server did not answer); reconnect it later`);
|
|
133
|
+
this.name = "McpAuthRefreshUnavailableError";
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function createSessionAuthProvider(opts) {
|
|
137
|
+
const { serverName, oauth } = opts;
|
|
138
|
+
const account = mcpOAuthTokenAccount2(opts.serverUrl);
|
|
139
|
+
const now = oauth.now ?? Date.now;
|
|
140
|
+
let cached;
|
|
141
|
+
let refreshing;
|
|
142
|
+
const needsAuth = (why) => new McpNeedsAuthError(serverName, why, oauth.signInHint(serverName));
|
|
143
|
+
let refreshedGeneration;
|
|
144
|
+
const usable = (record) => {
|
|
145
|
+
if (record.expiresAt === undefined)
|
|
146
|
+
return true;
|
|
147
|
+
const margin = record.refreshToken !== undefined && record.generation !== refreshedGeneration ? MCP_OAUTH_EXPIRY_SKEW_MS2 : 0;
|
|
148
|
+
return record.expiresAt - now() > margin;
|
|
149
|
+
};
|
|
150
|
+
async function read(force) {
|
|
151
|
+
if (!force && cached !== undefined && now() - cached.readAt < MCP_OAUTH_SESSION_CACHE_MS2 && (cached.record === null || usable(cached.record)))
|
|
152
|
+
return cached.record;
|
|
153
|
+
const record = await readTokenRecordLenient(oauth.store, account);
|
|
154
|
+
cached = { record, readAt: now() };
|
|
155
|
+
return record;
|
|
156
|
+
}
|
|
157
|
+
async function ask(generation, stepUpScope) {
|
|
158
|
+
const request = { server: serverName, account, generation, ...stepUpScope !== undefined ? { stepUpScope } : {} };
|
|
159
|
+
if (oauth.askHost !== undefined) {
|
|
160
|
+
const answer = await oauth.askHost(request).catch(() => ({ ok: false, reason: "transient" }));
|
|
161
|
+
if (answer !== "unhandled")
|
|
162
|
+
return answer;
|
|
163
|
+
if (oauth.hostOwnsRefresh === true)
|
|
164
|
+
return { ok: false, reason: "transient" };
|
|
165
|
+
}
|
|
166
|
+
if (oauth.hostOwnsRefresh === true)
|
|
167
|
+
return { ok: false, reason: "transient" };
|
|
168
|
+
const result = await refreshMcpOAuthToken2({ account, store: oauth.store, generation, ...stepUpScope !== undefined ? { stepUpScope } : {}, ...oauth.fetch !== undefined ? { fetch: oauth.fetch } : {}, ...oauth.now !== undefined ? { now: oauth.now } : {} });
|
|
169
|
+
return result.ok ? { ok: true } : result;
|
|
170
|
+
}
|
|
171
|
+
function refresh(generation) {
|
|
172
|
+
refreshing ??= ask(generation).finally(() => {
|
|
173
|
+
refreshing = undefined;
|
|
174
|
+
});
|
|
175
|
+
return refreshing;
|
|
176
|
+
}
|
|
177
|
+
async function refreshed(record) {
|
|
178
|
+
if (record.refreshToken === undefined)
|
|
179
|
+
throw needsAuth("the stored token has expired and there is no refresh token");
|
|
180
|
+
const answer = await refresh(record.generation);
|
|
181
|
+
if (!answer.ok) {
|
|
182
|
+
if (answer.reason === "needs_auth")
|
|
183
|
+
throw needsAuth("the sign-in could not be refreshed");
|
|
184
|
+
throw new McpAuthRefreshUnavailableError(serverName);
|
|
185
|
+
}
|
|
186
|
+
const next = await read(true);
|
|
187
|
+
if (next === null || next.generation === record.generation)
|
|
188
|
+
throw needsAuth("the refreshed sign-in was not found");
|
|
189
|
+
refreshedGeneration = next.generation;
|
|
190
|
+
return next;
|
|
191
|
+
}
|
|
192
|
+
async function current() {
|
|
193
|
+
const record = await read(false);
|
|
194
|
+
if (record === null)
|
|
195
|
+
return;
|
|
196
|
+
if (usable(record))
|
|
197
|
+
return record.accessToken;
|
|
198
|
+
return (await refreshed(record)).accessToken;
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
token: current,
|
|
202
|
+
async preflight() {
|
|
203
|
+
await current();
|
|
204
|
+
},
|
|
205
|
+
async onUnauthorized() {
|
|
206
|
+
const before = cached?.record ?? null;
|
|
207
|
+
const record = await read(true);
|
|
208
|
+
if (record === null)
|
|
209
|
+
throw needsAuth("the server requires a sign-in");
|
|
210
|
+
if (before === null || record.accessToken !== before.accessToken)
|
|
211
|
+
return;
|
|
212
|
+
await refreshed(record);
|
|
213
|
+
},
|
|
214
|
+
async reportInsufficientScope(scope) {
|
|
215
|
+
const record = await read(true).catch(() => null);
|
|
216
|
+
if (record === null || scope === undefined || scope.trim() === "")
|
|
217
|
+
return;
|
|
218
|
+
await ask(record.generation, scope).catch(() => {
|
|
219
|
+
return;
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
function mcpSignInHint(brand, serverName) {
|
|
225
|
+
const cli = brand.homeDirName.replace(/^\./, "");
|
|
226
|
+
return `Sign in with \`${cli} mcp login ${serverName}\` (or ${brand.productName} Settings -> MCP), then reconnect the server.`;
|
|
227
|
+
}
|
|
228
|
+
|
|
112
229
|
// src/mcp/client.ts
|
|
113
|
-
import { Client, ProtocolError, ProtocolErrorCode, SdkError, SdkErrorCode, SdkHttpError, SseError, UnauthorizedError, UnsupportedProtocolVersionError } from "@modelcontextprotocol/client";
|
|
230
|
+
import { Client, InsufficientScopeError, ProtocolError, ProtocolErrorCode, SdkError, SdkErrorCode, SdkHttpError, SseError, UnauthorizedError, UnsupportedProtocolVersionError } from "@modelcontextprotocol/client";
|
|
114
231
|
|
|
115
232
|
// src/mcp/transports/stdio.ts
|
|
116
233
|
import { spawn } from "node:child_process";
|
|
@@ -261,19 +378,22 @@ function buildStdioTransport(cfg, cwd) {
|
|
|
261
378
|
|
|
262
379
|
// src/mcp/transports/http.ts
|
|
263
380
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/client";
|
|
381
|
+
var refusingRedirectsFetch = (url, init) => fetch(url, { ...init, redirect: "error" });
|
|
264
382
|
function buildHttpTransport(cfg, opts = {}) {
|
|
265
383
|
const requestInit = { ...cfg.headers !== undefined ? { headers: cfg.headers } : {}, ...opts.refuseRedirects === true ? { redirect: "error" } : {} };
|
|
266
384
|
const transport = new StreamableHTTPClientTransport(new URL(cfg.url), {
|
|
267
|
-
...Object.keys(requestInit).length > 0 ? { requestInit } : {}
|
|
385
|
+
...Object.keys(requestInit).length > 0 ? { requestInit } : {},
|
|
386
|
+
...opts.authProvider !== undefined ? { authProvider: opts.authProvider, fetch: refusingRedirectsFetch } : {}
|
|
268
387
|
});
|
|
269
388
|
return transport;
|
|
270
389
|
}
|
|
271
390
|
|
|
272
391
|
// src/mcp/transports/sse.ts
|
|
273
392
|
import { SSEClientTransport } from "@modelcontextprotocol/client";
|
|
274
|
-
function buildSseTransport(cfg) {
|
|
393
|
+
function buildSseTransport(cfg, opts = {}) {
|
|
275
394
|
const transport = new SSEClientTransport(new URL(cfg.url), {
|
|
276
|
-
...cfg.headers !== undefined ? { requestInit: { headers: cfg.headers } } : {}
|
|
395
|
+
...cfg.headers !== undefined ? { requestInit: { headers: cfg.headers } } : {},
|
|
396
|
+
...opts.authProvider !== undefined ? { authProvider: opts.authProvider, fetch: refusingRedirectsFetch } : {}
|
|
277
397
|
});
|
|
278
398
|
return transport;
|
|
279
399
|
}
|
|
@@ -310,6 +430,12 @@ function toSdkNegotiationMode(mode) {
|
|
|
310
430
|
function classifyConnectError(err, facts = { transportClosed: false, pinned: false }) {
|
|
311
431
|
if (err instanceof McpConnectError2)
|
|
312
432
|
return err;
|
|
433
|
+
if (err instanceof McpNeedsAuthError)
|
|
434
|
+
return new McpConnectError2("needs_auth", err.message);
|
|
435
|
+
if (err instanceof McpAuthRefreshUnavailableError)
|
|
436
|
+
return new McpConnectError2("auth_refresh_failed", err.message);
|
|
437
|
+
if (err instanceof InsufficientScopeError)
|
|
438
|
+
return new McpConnectError2("needs_auth", "the server requires additional permission (403 insufficient_scope); sign in again to grant it", 403);
|
|
313
439
|
if (err instanceof UnauthorizedError)
|
|
314
440
|
return new McpConnectError2("needs_auth", err.message);
|
|
315
441
|
if (err instanceof SdkError && err.code === SdkErrorCode.RequestTimeout)
|
|
@@ -367,7 +493,7 @@ function autoProbeTimeoutMs(connectTimeoutMs) {
|
|
|
367
493
|
return Math.max(1, Math.min(AUTO_PROBE_TIMEOUT_CAP_MS, Math.floor(connectTimeoutMs / 3)));
|
|
368
494
|
}
|
|
369
495
|
function retriesAsLegacy(err) {
|
|
370
|
-
if (err.code === "needs_auth" || err.code === "spawn_failed" || err.code === "version_mismatch")
|
|
496
|
+
if (err.code === "needs_auth" || err.code === "auth_refresh_failed" || err.code === "spawn_failed" || err.code === "version_mismatch")
|
|
371
497
|
return false;
|
|
372
498
|
return err.httpStatus !== 401 && err.httpStatus !== 403;
|
|
373
499
|
}
|
|
@@ -428,10 +554,11 @@ async function connectOnce(opts, mode, connectTimeoutMs, probeTimeoutMs) {
|
|
|
428
554
|
throw new McpConnectError2("spawn_failed", `mcp client: server "${name}" is configured as type "sdk" but no in-process server instance was supplied to connectMcpServer`);
|
|
429
555
|
}
|
|
430
556
|
transport = await buildSdkTransport(opts.inProcessServer);
|
|
431
|
-
} else if (config.type === "http") {
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
557
|
+
} else if (config.type === "http" || config.type === "sse") {
|
|
558
|
+
if (opts.auth !== undefined)
|
|
559
|
+
await boundedPreflight(opts.auth, connectTimeoutMs);
|
|
560
|
+
const authProvider = opts.auth !== undefined ? { token: () => opts.auth.token(), onUnauthorized: () => opts.auth.onUnauthorized() } : undefined;
|
|
561
|
+
transport = config.type === "http" ? buildHttpTransport(config, { ...opts.refuseHttpRedirects === true ? { refuseRedirects: true } : {}, ...authProvider !== undefined ? { authProvider } : {} }) : buildSseTransport(config, authProvider !== undefined ? { authProvider } : {});
|
|
435
562
|
} else {
|
|
436
563
|
if (opts.cwd === undefined) {
|
|
437
564
|
throw new McpConnectError2("spawn_failed", `mcp client: stdio server "${name}" has no session cwd to start in; it is never started in the host process's cwd`);
|
|
@@ -516,10 +643,13 @@ async function connectOnce(opts, mode, connectTimeoutMs, probeTimeoutMs) {
|
|
|
516
643
|
}
|
|
517
644
|
};
|
|
518
645
|
} catch (err) {
|
|
646
|
+
const scopeChallenge = insufficientScopeOf(err);
|
|
647
|
+
if (scopeChallenge !== undefined && opts.auth !== undefined)
|
|
648
|
+
await opts.auth.reportInsufficientScope(scopeChallenge.requiredScope).catch(() => {});
|
|
519
649
|
const stderrTail = transport instanceof WinterStdioTransport ? transport.stderrTail.trim() : "";
|
|
520
650
|
const facts = { transportClosed: transport instanceof WinterStdioTransport && transport.exitedOnItsOwn, pinned: typeof mode === "object" };
|
|
521
651
|
try {
|
|
522
|
-
await transport
|
|
652
|
+
await transport?.close();
|
|
523
653
|
} catch {}
|
|
524
654
|
const classified = classifyConnectError(err, facts);
|
|
525
655
|
if (stderrTail === "" || classified.message.includes(stderrTail))
|
|
@@ -529,5 +659,34 @@ async function connectOnce(opts, mode, connectTimeoutMs, probeTimeoutMs) {
|
|
|
529
659
|
${stderrTail}`, classified.httpStatus);
|
|
530
660
|
}
|
|
531
661
|
}
|
|
662
|
+
function boundedPreflight(auth, timeoutMs) {
|
|
663
|
+
let timer;
|
|
664
|
+
const outer = new Promise((_, reject) => {
|
|
665
|
+
timer = setTimeout(() => reject(new McpConnectError2("timeout", `mcp client: the sign-in check exceeded ${timeoutMs}ms`)), timeoutMs);
|
|
666
|
+
timer.unref?.();
|
|
667
|
+
});
|
|
668
|
+
return Promise.race([auth.preflight(), outer]).finally(() => {
|
|
669
|
+
if (timer !== undefined)
|
|
670
|
+
clearTimeout(timer);
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
function insufficientScopeOf(err) {
|
|
674
|
+
for (let e = err, depth = 0;e !== undefined && e !== null && depth < 4; e = e.cause, depth++) {
|
|
675
|
+
if (e instanceof InsufficientScopeError)
|
|
676
|
+
return e;
|
|
677
|
+
}
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
function classifyMcpAuthFailure(err) {
|
|
681
|
+
for (let e = err, depth = 0;e !== undefined && e !== null && depth < 4; e = e.cause, depth++) {
|
|
682
|
+
if (e instanceof InsufficientScopeError)
|
|
683
|
+
return "insufficient_scope";
|
|
684
|
+
if (e instanceof McpNeedsAuthError || e instanceof UnauthorizedError)
|
|
685
|
+
return "needs_auth";
|
|
686
|
+
if (e instanceof SdkHttpError && e.status === 401)
|
|
687
|
+
return "needs_auth";
|
|
688
|
+
}
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
532
691
|
|
|
533
|
-
export { trackProcessGroup, liveProcessGroups, onProcessGroupChange, createElicitationAsker2, McpConnectError2, resolveVersionNegotiation2, connectMcpServer2 };
|
|
692
|
+
export { trackProcessGroup, liveProcessGroups, onProcessGroupChange, createElicitationAsker2, createSessionAuthProvider, mcpSignInHint, McpConnectError2, resolveVersionNegotiation2, connectMcpServer2, insufficientScopeOf, classifyMcpAuthFailure };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import {
|
|
2
|
+
evaluateMcpAuthUrl2,
|
|
3
|
+
isLoopbackMcpServer
|
|
4
|
+
} from "./index-z6s3r4xm.js";
|
|
5
|
+
|
|
6
|
+
// src/mcp-auth/config.ts
|
|
7
|
+
var OAUTH_KEYS = new Set(["clientId", "clientSecretRef", "callbackPort", "authServerMetadataUrl", "scopes"]);
|
|
8
|
+
var SECRET_REF_KEYS = new Set(["kind"]);
|
|
9
|
+
function isPlainObject(value) {
|
|
10
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11
|
+
}
|
|
12
|
+
function validateMcpOAuthConfig2(oauth, serverUrl) {
|
|
13
|
+
if (!isPlainObject(oauth))
|
|
14
|
+
return "MCP server config 'oauth' must be an object";
|
|
15
|
+
for (const key of Object.keys(oauth)) {
|
|
16
|
+
if (key === "clientSecret")
|
|
17
|
+
return `MCP server config 'oauth.clientSecret' is refused: a client secret never lives in a config -- store it in the Keychain (the host's sign-in door) and mark it with 'oauth.clientSecretRef': { kind: "keychain" }`;
|
|
18
|
+
if (!OAUTH_KEYS.has(key))
|
|
19
|
+
return `MCP server config 'oauth' has an unknown key ${JSON.stringify(key)} (expected clientId, clientSecretRef, callbackPort, authServerMetadataUrl, scopes)`;
|
|
20
|
+
}
|
|
21
|
+
const { clientId, clientSecretRef, callbackPort, authServerMetadataUrl, scopes } = oauth;
|
|
22
|
+
if (clientId !== undefined && (typeof clientId !== "string" || clientId.trim() === ""))
|
|
23
|
+
return "MCP server config 'oauth.clientId' must be a non-empty string";
|
|
24
|
+
if (clientSecretRef !== undefined) {
|
|
25
|
+
if (clientId === undefined)
|
|
26
|
+
return "MCP server config 'oauth.clientSecretRef' needs 'oauth.clientId': a secret belongs to a pre-registered client";
|
|
27
|
+
if (!isPlainObject(clientSecretRef))
|
|
28
|
+
return `MCP server config 'oauth.clientSecretRef' must be { kind: "keychain" }`;
|
|
29
|
+
for (const key of Object.keys(clientSecretRef)) {
|
|
30
|
+
if (!SECRET_REF_KEYS.has(key))
|
|
31
|
+
return `MCP server config 'oauth.clientSecretRef' has the key ${JSON.stringify(key)}, which is refused: it is { kind: "keychain" } only -- the secret's Keychain account is derived from the server URL, never named by a config`;
|
|
32
|
+
}
|
|
33
|
+
if (clientSecretRef.kind !== "keychain")
|
|
34
|
+
return `MCP server config 'oauth.clientSecretRef.kind' must be "keychain"`;
|
|
35
|
+
}
|
|
36
|
+
if (callbackPort !== undefined && (typeof callbackPort !== "number" || !Number.isInteger(callbackPort) || callbackPort < 1 || callbackPort > 65535)) {
|
|
37
|
+
return "MCP server config 'oauth.callbackPort' must be an integer port (1-65535)";
|
|
38
|
+
}
|
|
39
|
+
if (authServerMetadataUrl !== undefined) {
|
|
40
|
+
if (typeof authServerMetadataUrl !== "string")
|
|
41
|
+
return "MCP server config 'oauth.authServerMetadataUrl' must be a URL string";
|
|
42
|
+
const verdict = evaluateMcpAuthUrl2(authServerMetadataUrl, { allowLoopback: serverUrl !== undefined && isLoopbackMcpServer(serverUrl) });
|
|
43
|
+
if (!verdict.ok)
|
|
44
|
+
return `MCP server config 'oauth.authServerMetadataUrl' is refused: ${verdict.reason}`;
|
|
45
|
+
}
|
|
46
|
+
if (scopes !== undefined && (!Array.isArray(scopes) || scopes.some((s) => typeof s !== "string" || s === "" || /\s/.test(s)))) {
|
|
47
|
+
return "MCP server config 'oauth.scopes' must be an array of scope tokens (non-empty, no whitespace)";
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { validateMcpOAuthConfig2 };
|
|
@@ -9,14 +9,14 @@ import {
|
|
|
9
9
|
resolveEngineSession2,
|
|
10
10
|
resolveProductionWinterHome2,
|
|
11
11
|
resolveProductionStoreHome
|
|
12
|
-
} from "./index-
|
|
12
|
+
} from "./index-51673qbw.js";
|
|
13
13
|
import {
|
|
14
14
|
registerDefaultChildEngineFactory,
|
|
15
15
|
loadResumedChain,
|
|
16
16
|
buildProductionWiring,
|
|
17
17
|
withAutoSkillPermissions,
|
|
18
18
|
restoreChildRoster
|
|
19
|
-
} from "./index-
|
|
19
|
+
} from "./index-9df1q7j4.js";
|
|
20
20
|
|
|
21
21
|
// src/embedded.ts
|
|
22
22
|
import { splitFrames, encodeFrame } from "@yanlinglabs/winter-agent-sdk";
|