skybridge 0.0.0-dev.ba8c3af → 0.0.0-dev.baa9b4b
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/cli/resolve-views-dir.d.ts +1 -0
- package/dist/cli/resolve-views-dir.js +17 -0
- package/dist/cli/resolve-views-dir.js.map +1 -0
- package/dist/commands/build.js +1 -16
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/dev.js +16 -0
- package/dist/commands/dev.js.map +1 -1
- package/dist/web/bridges/adaptor.d.ts +48 -0
- package/dist/web/bridges/adaptor.js +308 -0
- package/dist/web/bridges/adaptor.js.map +1 -0
- package/dist/web/bridges/adaptor.test.d.ts +1 -0
- package/dist/web/bridges/adaptor.test.js +205 -0
- package/dist/web/bridges/adaptor.test.js.map +1 -0
- package/dist/web/bridges/apps-sdk/bridge.d.ts +1 -1
- package/dist/web/bridges/apps-sdk/bridge.js +3 -4
- package/dist/web/bridges/apps-sdk/bridge.js.map +1 -1
- package/dist/web/bridges/apps-sdk/index.d.ts +0 -1
- package/dist/web/bridges/apps-sdk/index.js +0 -1
- package/dist/web/bridges/apps-sdk/index.js.map +1 -1
- package/dist/web/bridges/get-adaptor.d.ts +6 -4
- package/dist/web/bridges/get-adaptor.js +24 -9
- package/dist/web/bridges/get-adaptor.js.map +1 -1
- package/dist/web/bridges/get-adaptor.test.d.ts +1 -0
- package/dist/web/bridges/get-adaptor.test.js +48 -0
- package/dist/web/bridges/get-adaptor.test.js.map +1 -0
- package/dist/web/bridges/host-context-stores.d.ts +27 -0
- package/dist/web/bridges/host-context-stores.js +73 -0
- package/dist/web/bridges/host-context-stores.js.map +1 -0
- package/dist/web/bridges/mcp-app/bridge.d.ts +1 -1
- package/dist/web/bridges/mcp-app/bridge.js +1 -4
- package/dist/web/bridges/mcp-app/bridge.js.map +1 -1
- package/dist/web/bridges/mcp-app/bridge.test.d.ts +1 -0
- package/dist/web/bridges/mcp-app/bridge.test.js +21 -0
- package/dist/web/bridges/mcp-app/bridge.test.js.map +1 -0
- package/dist/web/bridges/mcp-app/index.d.ts +0 -1
- package/dist/web/bridges/mcp-app/index.js +0 -1
- package/dist/web/bridges/mcp-app/index.js.map +1 -1
- package/dist/web/bridges/types.d.ts +15 -0
- package/dist/web/bridges/types.js +14 -1
- package/dist/web/bridges/types.js.map +1 -1
- package/dist/web/bridges/types.test.d.ts +1 -0
- package/dist/web/bridges/types.test.js +19 -0
- package/dist/web/bridges/types.test.js.map +1 -0
- package/dist/web/components/modal-provider.js +4 -3
- package/dist/web/components/modal-provider.js.map +1 -1
- package/dist/web/create-store.test.js +7 -5
- package/dist/web/create-store.test.js.map +1 -1
- package/dist/web/data-llm.test.js +8 -5
- package/dist/web/data-llm.test.js.map +1 -1
- package/dist/web/hooks/use-call-tool.test.js +36 -23
- package/dist/web/hooks/use-call-tool.test.js.map +1 -1
- package/dist/web/hooks/use-display-mode.test.js +55 -20
- package/dist/web/hooks/use-display-mode.test.js.map +1 -1
- package/dist/web/hooks/use-download.test.js +11 -3
- package/dist/web/hooks/use-download.test.js.map +1 -1
- package/dist/web/hooks/use-files.test.js +10 -2
- package/dist/web/hooks/use-files.test.js.map +1 -1
- package/dist/web/hooks/use-layout.test.js +59 -26
- package/dist/web/hooks/use-layout.test.js.map +1 -1
- package/dist/web/hooks/use-open-external.test.js +19 -5
- package/dist/web/hooks/use-open-external.test.js.map +1 -1
- package/dist/web/hooks/use-request-close.test.js +34 -40
- package/dist/web/hooks/use-request-close.test.js.map +1 -1
- package/dist/web/hooks/use-request-modal.test.js +10 -0
- package/dist/web/hooks/use-request-modal.test.js.map +1 -1
- package/dist/web/hooks/use-request-size.test.js +35 -53
- package/dist/web/hooks/use-request-size.test.js.map +1 -1
- package/dist/web/hooks/use-set-open-in-app-url.test.js +28 -8
- package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -1
- package/dist/web/hooks/use-tool-info.test.js +37 -27
- package/dist/web/hooks/use-tool-info.test.js.map +1 -1
- package/dist/web/hooks/use-user.test.js +81 -35
- package/dist/web/hooks/use-user.test.js.map +1 -1
- package/dist/web/hooks/use-view-state.test.js +6 -2
- package/dist/web/hooks/use-view-state.test.js.map +1 -1
- package/package.json +1 -1
- package/dist/web/bridges/apps-sdk/adaptor.d.ts +0 -28
- package/dist/web/bridges/apps-sdk/adaptor.js +0 -113
- package/dist/web/bridges/apps-sdk/adaptor.js.map +0 -1
- package/dist/web/bridges/mcp-app/adaptor.d.ts +0 -52
- package/dist/web/bridges/mcp-app/adaptor.js +0 -280
- package/dist/web/bridges/mcp-app/adaptor.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function resolveViewsDir(root: string): Promise<string | undefined>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export async function resolveViewsDir(root) {
|
|
2
|
+
const { loadConfigFromFile } = await import("vite");
|
|
3
|
+
const loaded = await loadConfigFromFile({ command: "build", mode: "production" }, undefined, root);
|
|
4
|
+
const isPluginCandidate = (value) => typeof value === "object" && value !== null;
|
|
5
|
+
const plugins = [];
|
|
6
|
+
const walk = (value) => {
|
|
7
|
+
if (Array.isArray(value)) {
|
|
8
|
+
value.forEach(walk);
|
|
9
|
+
}
|
|
10
|
+
else if (isPluginCandidate(value)) {
|
|
11
|
+
plugins.push(value);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
walk(loaded?.config.plugins ?? []);
|
|
15
|
+
return plugins.find((p) => p.name === "skybridge")?.api?.viewsDir;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=resolve-views-dir.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-views-dir.js","sourceRoot":"","sources":["../../src/cli/resolve-views-dir.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAY;IAEZ,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,MAAM,kBAAkB,CACrC,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,EACxC,SAAS,EACT,IAAI,CACL,CAAC;IAEF,MAAM,iBAAiB,GAAG,CACxB,KAAc,EAC2C,EAAE,CAC3D,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;IAE9C,MAAM,OAAO,GAA0D,EAAE,CAAC;IAC1E,MAAM,IAAI,GAAG,CAAC,KAAc,EAAE,EAAE;QAC9B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;aAAM,IAAI,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IACnC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC;AACpE,CAAC","sourcesContent":["export async function resolveViewsDir(\n root: string,\n): Promise<string | undefined> {\n const { loadConfigFromFile } = await import(\"vite\");\n const loaded = await loadConfigFromFile(\n { command: \"build\", mode: \"production\" },\n undefined,\n root,\n );\n\n const isPluginCandidate = (\n value: unknown,\n ): value is { name?: string; api?: { viewsDir?: string } } =>\n typeof value === \"object\" && value !== null;\n\n const plugins: Array<{ name?: string; api?: { viewsDir?: string } }> = [];\n const walk = (value: unknown) => {\n if (Array.isArray(value)) {\n value.forEach(walk);\n } else if (isPluginCandidate(value)) {\n plugins.push(value);\n }\n };\n walk(loaded?.config.plugins ?? []);\n return plugins.find((p) => p.name === \"skybridge\")?.api?.viewsDir;\n}\n"]}
|
package/dist/commands/build.js
CHANGED
|
@@ -5,24 +5,9 @@ import { Command } from "@oclif/core";
|
|
|
5
5
|
import { Box, render, Text } from "ink";
|
|
6
6
|
import { useEffect } from "react";
|
|
7
7
|
import { Header } from "../cli/header.js";
|
|
8
|
+
import { resolveViewsDir } from "../cli/resolve-views-dir.js";
|
|
8
9
|
import { useExecuteSteps } from "../cli/use-execute-steps.js";
|
|
9
10
|
import { scanAndWriteViewsDts } from "../web/plugin/scan-views.js";
|
|
10
|
-
async function resolveViewsDir(root) {
|
|
11
|
-
const { loadConfigFromFile } = await import("vite");
|
|
12
|
-
const loaded = await loadConfigFromFile({ command: "build", mode: "production" }, undefined, root);
|
|
13
|
-
const isPluginCandidate = (value) => typeof value === "object" && value !== null;
|
|
14
|
-
const plugins = [];
|
|
15
|
-
const walk = (value) => {
|
|
16
|
-
if (Array.isArray(value)) {
|
|
17
|
-
value.forEach(walk);
|
|
18
|
-
}
|
|
19
|
-
else if (isPluginCandidate(value)) {
|
|
20
|
-
plugins.push(value);
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
walk(loaded?.config.plugins ?? []);
|
|
24
|
-
return plugins.find((p) => p.name === "skybridge")?.api?.viewsDir;
|
|
25
|
-
}
|
|
26
11
|
export const commandSteps = [
|
|
27
12
|
{
|
|
28
13
|
label: "Scanning views",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.tsx"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { Command } from \"@oclif/core\";\nimport { Box, render, Text } from \"ink\";\nimport { useEffect } from \"react\";\nimport { Header } from \"../cli/header.js\";\nimport { type CommandStep, useExecuteSteps } from \"../cli/use-execute-steps.js\";\nimport { scanAndWriteViewsDts } from \"../web/plugin/scan-views.js\";\n\nasync function resolveViewsDir(root: string): Promise<string | undefined> {\n const { loadConfigFromFile } = await import(\"vite\");\n const loaded = await loadConfigFromFile(\n { command: \"build\", mode: \"production\" },\n undefined,\n root,\n );\n\n const isPluginCandidate = (\n value: unknown,\n ): value is { name?: string; api?: { viewsDir?: string } } =>\n typeof value === \"object\" && value !== null;\n\n const plugins: Array<{ name?: string; api?: { viewsDir?: string } }> = [];\n const walk = (value: unknown) => {\n if (Array.isArray(value)) {\n value.forEach(walk);\n } else if (isPluginCandidate(value)) {\n plugins.push(value);\n }\n };\n walk(loaded?.config.plugins ?? []);\n return plugins.find((p) => p.name === \"skybridge\")?.api?.viewsDir;\n}\n\nexport const commandSteps: CommandStep[] = [\n {\n label: \"Scanning views\",\n run: async () => {\n const root = process.cwd();\n const viewsDir = await resolveViewsDir(root);\n scanAndWriteViewsDts(root, viewsDir);\n },\n },\n {\n label: \"Compiling server\",\n run: () => rmSync(\"dist\", { recursive: true, force: true }),\n command: \"tsc -b --force\",\n },\n {\n label: \"Building views\",\n command: \"vite build\",\n },\n {\n label: \"Emitting manifest module\",\n // Inline the Vite manifest as a JS module so the server can `import` it\n // instead of `readFileSync(process.cwd() + ...)` at runtime — required for\n // workerd, where neither cwd nor the assets directory is readable.\n // The path mirrors `skybridge start`'s entry convention (dist/server.js)\n // so the import in the user's entry resolves to a sibling file.\n run: () => {\n const root = process.cwd();\n const manifest = readFileSync(\n path.join(root, \"dist\", \"assets\", \".vite\", \"manifest.json\"),\n \"utf-8\",\n );\n writeFileSync(\n path.join(root, \"dist\", \"vite-manifest.js\"),\n `export default ${manifest};\\n`,\n );\n },\n },\n\n {\n label: \"Emitting Cloudflare redirects\",\n // Cloudflare's `assets.directory` maps URL → file literally — no\n // mount-strip like `app.use(\"/assets\", express.static(...))`. Rewrite\n // `/assets/assets/*` to `/assets/*` before lookup; status 200 =\n // server-side rewrite, not HTTP redirect.\n run: () => {\n const root = process.cwd();\n writeFileSync(\n path.join(root, \"dist\", \"assets\", \"_redirects\"),\n \"/assets/assets/* /assets/:splat 200\\n\",\n );\n },\n },\n {\n label: \"Emitting Cloudflare headers\",\n // Cloudflare's static asset handler bypasses the worker entirely, so\n // `app.use(\"/assets\", cors())` never fires for asset requests. Attach\n // CORS at the edge so cross-origin view iframes can load JS/CSS.\n run: () => {\n const root = process.cwd();\n writeFileSync(\n path.join(root, \"dist\", \"assets\", \"_headers\"),\n \"/assets/*\\n Access-Control-Allow-Origin: *\\n\",\n );\n },\n },\n];\n\nexport default class Build extends Command {\n static override description = \"Build the views and MCP server\";\n static override examples = [\"skybridge build\"];\n static override flags = {};\n\n public async run(): Promise<void> {\n const App = () => {\n const { currentStep, status, error, execute } =\n useExecuteSteps(commandSteps);\n\n useEffect(() => {\n execute();\n }, [execute]);\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header version={this.config.version}>\n <Text color=\"green\"> → building for production…</Text>\n </Header>\n\n {commandSteps.map((step, index) => {\n const isCurrent = index === currentStep && status === \"running\";\n const isCompleted = index < currentStep || status === \"success\";\n const isError = status === \"error\" && index === currentStep;\n\n return (\n <Box key={step.label} marginBottom={0}>\n <Text color={isError ? \"red\" : isCompleted ? \"green\" : \"grey\"}>\n {isError ? \"✗\" : isCompleted ? \"✓\" : isCurrent ? \"⟳\" : \"○\"}{\" \"}\n {step.label}\n </Text>\n </Box>\n );\n })}\n\n {status === \"success\" && (\n <Box marginTop={1}>\n <Text color=\"green\" bold>\n ✓ Build completed successfully!\n </Text>\n </Box>\n )}\n\n {status === \"error\" && error && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"red\" bold>\n ✗ Build failed\n </Text>\n <Box marginTop={1} flexDirection=\"column\">\n {error.split(\"\\n\").map((line) => (\n <Text key={line} color=\"red\">\n {line}\n </Text>\n ))}\n </Box>\n </Box>\n )}\n </Box>\n );\n };\n\n render(<App />, {\n exitOnCtrlC: true,\n patchConsole: false,\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.tsx"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { Command } from \"@oclif/core\";\nimport { Box, render, Text } from \"ink\";\nimport { useEffect } from \"react\";\nimport { Header } from \"../cli/header.js\";\nimport { resolveViewsDir } from \"../cli/resolve-views-dir.js\";\nimport { type CommandStep, useExecuteSteps } from \"../cli/use-execute-steps.js\";\nimport { scanAndWriteViewsDts } from \"../web/plugin/scan-views.js\";\n\nexport const commandSteps: CommandStep[] = [\n {\n label: \"Scanning views\",\n run: async () => {\n const root = process.cwd();\n const viewsDir = await resolveViewsDir(root);\n scanAndWriteViewsDts(root, viewsDir);\n },\n },\n {\n label: \"Compiling server\",\n run: () => rmSync(\"dist\", { recursive: true, force: true }),\n command: \"tsc -b --force\",\n },\n {\n label: \"Building views\",\n command: \"vite build\",\n },\n {\n label: \"Emitting manifest module\",\n // Inline the Vite manifest as a JS module so the server can `import` it\n // instead of `readFileSync(process.cwd() + ...)` at runtime — required for\n // workerd, where neither cwd nor the assets directory is readable.\n // The path mirrors `skybridge start`'s entry convention (dist/server.js)\n // so the import in the user's entry resolves to a sibling file.\n run: () => {\n const root = process.cwd();\n const manifest = readFileSync(\n path.join(root, \"dist\", \"assets\", \".vite\", \"manifest.json\"),\n \"utf-8\",\n );\n writeFileSync(\n path.join(root, \"dist\", \"vite-manifest.js\"),\n `export default ${manifest};\\n`,\n );\n },\n },\n\n {\n label: \"Emitting Cloudflare redirects\",\n // Cloudflare's `assets.directory` maps URL → file literally — no\n // mount-strip like `app.use(\"/assets\", express.static(...))`. Rewrite\n // `/assets/assets/*` to `/assets/*` before lookup; status 200 =\n // server-side rewrite, not HTTP redirect.\n run: () => {\n const root = process.cwd();\n writeFileSync(\n path.join(root, \"dist\", \"assets\", \"_redirects\"),\n \"/assets/assets/* /assets/:splat 200\\n\",\n );\n },\n },\n {\n label: \"Emitting Cloudflare headers\",\n // Cloudflare's static asset handler bypasses the worker entirely, so\n // `app.use(\"/assets\", cors())` never fires for asset requests. Attach\n // CORS at the edge so cross-origin view iframes can load JS/CSS.\n run: () => {\n const root = process.cwd();\n writeFileSync(\n path.join(root, \"dist\", \"assets\", \"_headers\"),\n \"/assets/*\\n Access-Control-Allow-Origin: *\\n\",\n );\n },\n },\n];\n\nexport default class Build extends Command {\n static override description = \"Build the views and MCP server\";\n static override examples = [\"skybridge build\"];\n static override flags = {};\n\n public async run(): Promise<void> {\n const App = () => {\n const { currentStep, status, error, execute } =\n useExecuteSteps(commandSteps);\n\n useEffect(() => {\n execute();\n }, [execute]);\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header version={this.config.version}>\n <Text color=\"green\"> → building for production…</Text>\n </Header>\n\n {commandSteps.map((step, index) => {\n const isCurrent = index === currentStep && status === \"running\";\n const isCompleted = index < currentStep || status === \"success\";\n const isError = status === \"error\" && index === currentStep;\n\n return (\n <Box key={step.label} marginBottom={0}>\n <Text color={isError ? \"red\" : isCompleted ? \"green\" : \"grey\"}>\n {isError ? \"✗\" : isCompleted ? \"✓\" : isCurrent ? \"⟳\" : \"○\"}{\" \"}\n {step.label}\n </Text>\n </Box>\n );\n })}\n\n {status === \"success\" && (\n <Box marginTop={1}>\n <Text color=\"green\" bold>\n ✓ Build completed successfully!\n </Text>\n </Box>\n )}\n\n {status === \"error\" && error && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"red\" bold>\n ✗ Build failed\n </Text>\n <Box marginTop={1} flexDirection=\"column\">\n {error.split(\"\\n\").map((line) => (\n <Text key={line} color=\"red\">\n {line}\n </Text>\n ))}\n </Box>\n </Box>\n )}\n </Box>\n );\n };\n\n render(<App />, {\n exitOnCtrlC: true,\n patchConsole: false,\n });\n }\n}\n"]}
|
package/dist/commands/dev.js
CHANGED
|
@@ -3,12 +3,14 @@ import { Command, Flags } from "@oclif/core";
|
|
|
3
3
|
import { Box, render, Text } from "ink";
|
|
4
4
|
import { resolvePort } from "../cli/detect-port.js";
|
|
5
5
|
import { Header } from "../cli/header.js";
|
|
6
|
+
import { resolveViewsDir } from "../cli/resolve-views-dir.js";
|
|
6
7
|
import { startTunnelControlServer } from "../cli/tunnel-control-server.js";
|
|
7
8
|
import { useMessages } from "../cli/use-messages.js";
|
|
8
9
|
import { useNodemon } from "../cli/use-nodemon.js";
|
|
9
10
|
import { useOpenBrowser } from "../cli/use-open-browser.js";
|
|
10
11
|
import { useTunnel } from "../cli/use-tunnel.js";
|
|
11
12
|
import { useTypeScriptCheck } from "../cli/use-typescript-check.js";
|
|
13
|
+
import { scanAndWriteViewsDts } from "../web/plugin/scan-views.js";
|
|
12
14
|
export default class Dev extends Command {
|
|
13
15
|
static description = "Start development server";
|
|
14
16
|
static examples = ["skybridge"];
|
|
@@ -35,6 +37,20 @@ export default class Dev extends Command {
|
|
|
35
37
|
};
|
|
36
38
|
async run() {
|
|
37
39
|
const { flags } = await this.parse(Dev);
|
|
40
|
+
// Generate .skybridge/views.d.ts before render() spawns `tsc --noEmit
|
|
41
|
+
// --watch`. Vite's plugin config hook writes the same file when nodemon
|
|
42
|
+
// boots the server, but tsc starts in parallel — if .skybridge/ doesn't
|
|
43
|
+
// exist at tsc startup, its watcher never picks up the late-created file
|
|
44
|
+
// and the dev UI reports phantom TS errors forever.
|
|
45
|
+
const root = process.cwd();
|
|
46
|
+
try {
|
|
47
|
+
scanAndWriteViewsDts(root, await resolveViewsDir(root));
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// Best-effort: if the scan fails (e.g. broken vite config, duplicate
|
|
51
|
+
// view names) tsc may show phantom errors, but the dev server should
|
|
52
|
+
// still start so the developer can fix the underlying issue.
|
|
53
|
+
}
|
|
38
54
|
const { port, fallback, envWarning } = await resolvePort(flags.port);
|
|
39
55
|
if (envWarning) {
|
|
40
56
|
this.warn(envWarning);
|
package/dist/commands/dev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Command, Flags } from \"@oclif/core\";\nimport { Box, render, Text } from \"ink\";\nimport { resolvePort } from \"../cli/detect-port.js\";\nimport { Header } from \"../cli/header.js\";\nimport { startTunnelControlServer } from \"../cli/tunnel-control-server.js\";\nimport { useMessages } from \"../cli/use-messages.js\";\nimport { useNodemon } from \"../cli/use-nodemon.js\";\nimport { useOpenBrowser } from \"../cli/use-open-browser.js\";\nimport { useTunnel } from \"../cli/use-tunnel.js\";\nimport { useTypeScriptCheck } from \"../cli/use-typescript-check.js\";\n\nexport default class Dev extends Command {\n static override description = \"Start development server\";\n static override examples = [\"skybridge\"];\n static override flags = {\n port: Flags.integer({\n char: \"p\",\n description: \"Port to run the server on\",\n min: 1,\n }),\n tunnel: Flags.boolean({\n description: \"Open an Alpic tunnel for remote testing\",\n default: false,\n }),\n open: Flags.boolean({\n description: \"Open DevTools in the browser when the server is ready\",\n default: process.env.SKYBRIDGE_OPEN !== \"false\",\n allowNo: true,\n }),\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Show tunnel logs\",\n default: false,\n }),\n };\n\n public async run(): Promise<void> {\n const { flags } = await this.parse(Dev);\n\n const { port, fallback, envWarning } = await resolvePort(flags.port);\n if (envWarning) {\n this.warn(envWarning);\n }\n\n const {\n port: controlPort,\n manager: tunnelManager,\n close: closeTunnelControl,\n } = await startTunnelControlServer(() => port);\n\n const env = {\n ...process.env,\n __PORT: String(port),\n __TUNNEL_CONTROL_PORT: String(controlPort),\n };\n\n const App = () => {\n const tsErrors = useTypeScriptCheck();\n const [messages, pushMessage] = useMessages();\n useNodemon(env, pushMessage);\n useOpenBrowser(port, flags.open);\n const tunnelState = useTunnel(\n port,\n pushMessage,\n flags.verbose,\n flags.tunnel,\n );\n\n return (\n <Box flexDirection=\"column\" padding={1} marginLeft={1}>\n <Header version={this.config.version} />\n\n <Box>\n <Text>🏠{\" \"}</Text>\n {fallback ? (\n <Text color=\"yellow\">3000 in use, running on </Text>\n ) : (\n <Text>Running on </Text>\n )}\n <Text color=\"green\">{`http://localhost:${port}/mcp`}</Text>\n </Box>\n <Box marginBottom={1}>\n <Text color=\"#20a832\">→{\" \"}</Text>\n <Text color=\"white\" bold>\n Test locally with DevTools:{\" \"}\n </Text>\n <Text color=\"green\">{`http://localhost:${port}/`}</Text>\n </Box>\n\n {tunnelState.status === \"idle\" && (\n <Box>\n <Text>🌍{\" \"}</Text>\n <Text>Get a public URL and LLM Playground access with </Text>\n <Text color=\"cyan\" bold>\n --tunnel\n </Text>\n <Text>.</Text>\n </Box>\n )}\n {tunnelState.status === \"starting\" && (\n <Box>\n <Text>🌍{\" \"}</Text>\n <Text color=\"yellow\">{tunnelState.message}</Text>\n </Box>\n )}\n {tunnelState.status === \"connected\" && (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box>\n <Text>🌍{\" \"}</Text>\n <Text>Exposed on </Text>\n <Text color=\"green\">{`${tunnelState.url}/mcp`}</Text>\n </Box>\n <Box>\n <Text color=\"#20a832\">→{\" \"}</Text>\n <Text color=\"white\" bold>\n Test with an LLM on Playground:{\" \"}\n </Text>\n <Text color=\"green\">{`${tunnelState.url}/try`}</Text>\n </Box>\n </Box>\n )}\n {tunnelState.status === \"error\" && (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box>\n <Text>🌍{\" \"}</Text>\n <Text color=\"red\">\n Cannot open tunnel: {tunnelState.message}\n </Text>\n </Box>\n <Box>\n <Text color=\"#20a832\">→{\" \"}</Text>\n <Text color=\"red\">{`Try manually: npx alpic tunnel --port ${port}`}</Text>\n </Box>\n </Box>\n )}\n\n <Box>\n <Text>🛟{\" \"}</Text>\n <Text>Need help? Reach us on </Text>\n <Text color=\"white\" underline>\n https://discord.alpic.ai\n </Text>\n </Box>\n\n {tsErrors.length > 0 && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"red\" bold>\n ⚠️ TypeScript errors found:\n </Text>\n {tsErrors.map((error) => (\n <Box\n key={`${error.file}:${error.line}:${error.col}`}\n marginLeft={2}\n flexDirection=\"column\"\n >\n <Box>\n <Text color=\"white\">{error.file}</Text>\n <Text color=\"grey\">\n ({error.line},{error.col}):{\" \"}\n </Text>\n </Box>\n <Box marginLeft={2}>\n <Text color=\"red\">{error.message}</Text>\n </Box>\n </Box>\n ))}\n </Box>\n )}\n {messages.length > 0 && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"white\" bold>\n Logs:\n </Text>\n {messages.map((message) => (\n <Box key={message.id} marginLeft={2}>\n {message.type === \"restart\" ? (\n <>\n <Text color=\"green\">✓{\" \"}</Text>\n <Text color=\"white\">{message.text}</Text>\n </>\n ) : message.type === \"error\" ? (\n <Text color=\"red\">{message.text}</Text>\n ) : (\n <Text>{message.text}</Text>\n )}\n </Box>\n ))}\n </Box>\n )}\n </Box>\n );\n };\n\n // Note: `exitOnCtrlC: false` because we own SIGINT below to guarantee\n // alpic gets killed before we exit. If anything ever calls `useInput` or\n // puts stdin into raw mode, also wire an explicit `\\x03` keypress to the\n // shutdown function — Ink will otherwise swallow Ctrl-C without ever\n // delivering SIGINT.\n const ink = render(<App />, { exitOnCtrlC: false, patchConsole: true });\n\n // Synchronous-first shutdown: kill the alpic subprocess up front so we\n // can't leave it orphaned even if another SIGINT listener (e.g. nodemon's)\n // exits the process before our async cleanup completes.\n const shutdown = (code: number) => () => {\n tunnelManager.stop();\n void closeTunnelControl()\n .catch((err) => {\n console.error(\"Failed to close tunnel control server\", err);\n })\n .finally(() => {\n ink.unmount();\n process.exit(code);\n });\n };\n process.once(\"SIGINT\", shutdown(130));\n process.once(\"SIGTERM\", shutdown(143));\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAEnE,MAAM,CAAC,OAAO,OAAO,GAAI,SAAQ,OAAO;IACtC,MAAM,CAAU,WAAW,GAAG,0BAA0B,CAAC;IACzD,MAAM,CAAU,QAAQ,GAAG,CAAC,WAAW,CAAC,CAAC;IACzC,MAAM,CAAU,KAAK,GAAG;QACtB,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC;YAClB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,2BAA2B;YACxC,GAAG,EAAE,CAAC;SACP,CAAC;QACF,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC;YACpB,WAAW,EAAE,yCAAyC;YACtD,OAAO,EAAE,KAAK;SACf,CAAC;QACF,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC;YAClB,WAAW,EAAE,uDAAuD;YACpE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,OAAO;YAC/C,OAAO,EAAE,IAAI;SACd,CAAC;QACF,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,kBAAkB;YAC/B,OAAO,EAAE,KAAK;SACf,CAAC;KACH,CAAC;IAEK,KAAK,CAAC,GAAG;QACd,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAExC,sEAAsE;QACtE,wEAAwE;QACxE,wEAAwE;QACxE,yEAAyE;QACzE,oDAAoD;QACpD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,oBAAoB,CAAC,IAAI,EAAE,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1D,CAAC;QAAC,MAAM,CAAC;YACP,qEAAqE;YACrE,qEAAqE;YACrE,6DAA6D;QAC/D,CAAC;QAED,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACrE,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACxB,CAAC;QAED,MAAM,EACJ,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,kBAAkB,GAC1B,GAAG,MAAM,wBAAwB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAE/C,MAAM,GAAG,GAAG;YACV,GAAG,OAAO,CAAC,GAAG;YACd,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC;YACpB,qBAAqB,EAAE,MAAM,CAAC,WAAW,CAAC;SAC3C,CAAC;QAEF,MAAM,GAAG,GAAG,GAAG,EAAE;YACf,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAC;YACtC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,WAAW,EAAE,CAAC;YAC9C,UAAU,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;YAC7B,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACjC,MAAM,WAAW,GAAG,SAAS,CAC3B,IAAI,EACJ,WAAW,EACX,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,MAAM,CACb,CAAC;YAEF,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,aACnD,KAAC,MAAM,IAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,GAAI,EAExC,MAAC,GAAG,eACF,MAAC,IAAI,+BAAI,IAAI,IAAQ,EACpB,QAAQ,CAAC,CAAC,CAAC,CACV,KAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,yCAAgC,CACrD,CAAC,CAAC,CAAC,CACF,KAAC,IAAI,8BAAmB,CACzB,EACD,KAAC,IAAI,IAAC,KAAK,EAAC,OAAO,YAAE,oBAAoB,IAAI,MAAM,GAAQ,IACvD,EACN,MAAC,GAAG,IAAC,YAAY,EAAE,CAAC,aAClB,MAAC,IAAI,IAAC,KAAK,EAAC,SAAS,uBAAG,IAAI,IAAQ,EACpC,MAAC,IAAI,IAAC,KAAK,EAAC,OAAO,EAAC,IAAI,kDACM,GAAG,IAC1B,EACP,KAAC,IAAI,IAAC,KAAK,EAAC,OAAO,YAAE,oBAAoB,IAAI,GAAG,GAAQ,IACpD,EAEL,WAAW,CAAC,MAAM,KAAK,MAAM,IAAI,CAChC,MAAC,GAAG,eACF,MAAC,IAAI,+BAAI,IAAI,IAAQ,EACrB,KAAC,IAAI,mEAAwD,EAC7D,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,EAAC,IAAI,+BAEhB,EACP,KAAC,IAAI,oBAAS,IACV,CACP,EACA,WAAW,CAAC,MAAM,KAAK,UAAU,IAAI,CACpC,MAAC,GAAG,eACF,MAAC,IAAI,+BAAI,IAAI,IAAQ,EACrB,KAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,YAAE,WAAW,CAAC,OAAO,GAAQ,IAC7C,CACP,EACA,WAAW,CAAC,MAAM,KAAK,WAAW,IAAI,CACrC,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,YAAY,EAAE,CAAC,aACzC,MAAC,GAAG,eACF,MAAC,IAAI,+BAAI,IAAI,IAAQ,EACrB,KAAC,IAAI,8BAAmB,EACxB,KAAC,IAAI,IAAC,KAAK,EAAC,OAAO,YAAE,GAAG,WAAW,CAAC,GAAG,MAAM,GAAQ,IACjD,EACN,MAAC,GAAG,eACF,MAAC,IAAI,IAAC,KAAK,EAAC,SAAS,uBAAG,IAAI,IAAQ,EACpC,MAAC,IAAI,IAAC,KAAK,EAAC,OAAO,EAAC,IAAI,sDACU,GAAG,IAC9B,EACP,KAAC,IAAI,IAAC,KAAK,EAAC,OAAO,YAAE,GAAG,WAAW,CAAC,GAAG,MAAM,GAAQ,IACjD,IACF,CACP,EACA,WAAW,CAAC,MAAM,KAAK,OAAO,IAAI,CACjC,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,YAAY,EAAE,CAAC,aACzC,MAAC,GAAG,eACF,MAAC,IAAI,+BAAI,IAAI,IAAQ,EACrB,MAAC,IAAI,IAAC,KAAK,EAAC,KAAK,qCACM,WAAW,CAAC,OAAO,IACnC,IACH,EACN,MAAC,GAAG,eACF,MAAC,IAAI,IAAC,KAAK,EAAC,SAAS,uBAAG,IAAI,IAAQ,EACpC,KAAC,IAAI,IAAC,KAAK,EAAC,KAAK,YAAE,yCAAyC,IAAI,EAAE,GAAQ,IACtE,IACF,CACP,EAED,MAAC,GAAG,eACF,MAAC,IAAI,+BAAI,IAAI,IAAQ,EACrB,KAAC,IAAI,0CAA+B,EACpC,KAAC,IAAI,IAAC,KAAK,EAAC,OAAO,EAAC,SAAS,+CAEtB,IACH,EAEL,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CACtB,MAAC,GAAG,IAAC,SAAS,EAAE,CAAC,EAAE,aAAa,EAAC,QAAQ,aACvC,KAAC,IAAI,IAAC,KAAK,EAAC,KAAK,EAAC,IAAI,4DAEf,EACN,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CACvB,MAAC,GAAG,IAEF,UAAU,EAAE,CAAC,EACb,aAAa,EAAC,QAAQ,aAEtB,MAAC,GAAG,eACF,KAAC,IAAI,IAAC,KAAK,EAAC,OAAO,YAAE,KAAK,CAAC,IAAI,GAAQ,EACvC,MAAC,IAAI,IAAC,KAAK,EAAC,MAAM,kBACd,KAAK,CAAC,IAAI,OAAG,KAAK,CAAC,GAAG,QAAI,GAAG,IAC1B,IACH,EACN,KAAC,GAAG,IAAC,UAAU,EAAE,CAAC,YAChB,KAAC,IAAI,IAAC,KAAK,EAAC,KAAK,YAAE,KAAK,CAAC,OAAO,GAAQ,GACpC,KAZD,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,GAAG,EAAE,CAa3C,CACP,CAAC,IACE,CACP,EACA,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CACtB,MAAC,GAAG,IAAC,SAAS,EAAE,CAAC,EAAE,aAAa,EAAC,QAAQ,aACvC,KAAC,IAAI,IAAC,KAAK,EAAC,OAAO,EAAC,IAAI,4BAEjB,EACN,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CACzB,KAAC,GAAG,IAAkB,UAAU,EAAE,CAAC,YAChC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAC5B,8BACE,MAAC,IAAI,IAAC,KAAK,EAAC,OAAO,uBAAG,IAAI,IAAQ,EAClC,KAAC,IAAI,IAAC,KAAK,EAAC,OAAO,YAAE,OAAO,CAAC,IAAI,GAAQ,IACxC,CACJ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CAC7B,KAAC,IAAI,IAAC,KAAK,EAAC,KAAK,YAAE,OAAO,CAAC,IAAI,GAAQ,CACxC,CAAC,CAAC,CAAC,CACF,KAAC,IAAI,cAAE,OAAO,CAAC,IAAI,GAAQ,CAC5B,IAVO,OAAO,CAAC,EAAE,CAWd,CACP,CAAC,IACE,CACP,IACG,CACP,CAAC;QACJ,CAAC,CAAC;QAEF,sEAAsE;QACtE,yEAAyE;QACzE,yEAAyE;QACzE,qEAAqE;QACrE,qBAAqB;QACrB,MAAM,GAAG,GAAG,MAAM,CAAC,KAAC,GAAG,KAAG,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;QAExE,uEAAuE;QACvE,2EAA2E;QAC3E,wDAAwD;QACxD,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,GAAG,EAAE;YACtC,aAAa,CAAC,IAAI,EAAE,CAAC;YACrB,KAAK,kBAAkB,EAAE;iBACtB,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBACb,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,GAAG,CAAC,CAAC;YAC9D,CAAC,CAAC;iBACD,OAAO,CAAC,GAAG,EAAE;gBACZ,GAAG,CAAC,OAAO,EAAE,CAAC;gBACd,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC,CAAC,CAAC;QACP,CAAC,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QACtC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;IACzC,CAAC","sourcesContent":["import { Command, Flags } from \"@oclif/core\";\nimport { Box, render, Text } from \"ink\";\nimport { resolvePort } from \"../cli/detect-port.js\";\nimport { Header } from \"../cli/header.js\";\nimport { resolveViewsDir } from \"../cli/resolve-views-dir.js\";\nimport { startTunnelControlServer } from \"../cli/tunnel-control-server.js\";\nimport { useMessages } from \"../cli/use-messages.js\";\nimport { useNodemon } from \"../cli/use-nodemon.js\";\nimport { useOpenBrowser } from \"../cli/use-open-browser.js\";\nimport { useTunnel } from \"../cli/use-tunnel.js\";\nimport { useTypeScriptCheck } from \"../cli/use-typescript-check.js\";\nimport { scanAndWriteViewsDts } from \"../web/plugin/scan-views.js\";\n\nexport default class Dev extends Command {\n static override description = \"Start development server\";\n static override examples = [\"skybridge\"];\n static override flags = {\n port: Flags.integer({\n char: \"p\",\n description: \"Port to run the server on\",\n min: 1,\n }),\n tunnel: Flags.boolean({\n description: \"Open an Alpic tunnel for remote testing\",\n default: false,\n }),\n open: Flags.boolean({\n description: \"Open DevTools in the browser when the server is ready\",\n default: process.env.SKYBRIDGE_OPEN !== \"false\",\n allowNo: true,\n }),\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Show tunnel logs\",\n default: false,\n }),\n };\n\n public async run(): Promise<void> {\n const { flags } = await this.parse(Dev);\n\n // Generate .skybridge/views.d.ts before render() spawns `tsc --noEmit\n // --watch`. Vite's plugin config hook writes the same file when nodemon\n // boots the server, but tsc starts in parallel — if .skybridge/ doesn't\n // exist at tsc startup, its watcher never picks up the late-created file\n // and the dev UI reports phantom TS errors forever.\n const root = process.cwd();\n try {\n scanAndWriteViewsDts(root, await resolveViewsDir(root));\n } catch {\n // Best-effort: if the scan fails (e.g. broken vite config, duplicate\n // view names) tsc may show phantom errors, but the dev server should\n // still start so the developer can fix the underlying issue.\n }\n\n const { port, fallback, envWarning } = await resolvePort(flags.port);\n if (envWarning) {\n this.warn(envWarning);\n }\n\n const {\n port: controlPort,\n manager: tunnelManager,\n close: closeTunnelControl,\n } = await startTunnelControlServer(() => port);\n\n const env = {\n ...process.env,\n __PORT: String(port),\n __TUNNEL_CONTROL_PORT: String(controlPort),\n };\n\n const App = () => {\n const tsErrors = useTypeScriptCheck();\n const [messages, pushMessage] = useMessages();\n useNodemon(env, pushMessage);\n useOpenBrowser(port, flags.open);\n const tunnelState = useTunnel(\n port,\n pushMessage,\n flags.verbose,\n flags.tunnel,\n );\n\n return (\n <Box flexDirection=\"column\" padding={1} marginLeft={1}>\n <Header version={this.config.version} />\n\n <Box>\n <Text>🏠{\" \"}</Text>\n {fallback ? (\n <Text color=\"yellow\">3000 in use, running on </Text>\n ) : (\n <Text>Running on </Text>\n )}\n <Text color=\"green\">{`http://localhost:${port}/mcp`}</Text>\n </Box>\n <Box marginBottom={1}>\n <Text color=\"#20a832\">→{\" \"}</Text>\n <Text color=\"white\" bold>\n Test locally with DevTools:{\" \"}\n </Text>\n <Text color=\"green\">{`http://localhost:${port}/`}</Text>\n </Box>\n\n {tunnelState.status === \"idle\" && (\n <Box>\n <Text>🌍{\" \"}</Text>\n <Text>Get a public URL and LLM Playground access with </Text>\n <Text color=\"cyan\" bold>\n --tunnel\n </Text>\n <Text>.</Text>\n </Box>\n )}\n {tunnelState.status === \"starting\" && (\n <Box>\n <Text>🌍{\" \"}</Text>\n <Text color=\"yellow\">{tunnelState.message}</Text>\n </Box>\n )}\n {tunnelState.status === \"connected\" && (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box>\n <Text>🌍{\" \"}</Text>\n <Text>Exposed on </Text>\n <Text color=\"green\">{`${tunnelState.url}/mcp`}</Text>\n </Box>\n <Box>\n <Text color=\"#20a832\">→{\" \"}</Text>\n <Text color=\"white\" bold>\n Test with an LLM on Playground:{\" \"}\n </Text>\n <Text color=\"green\">{`${tunnelState.url}/try`}</Text>\n </Box>\n </Box>\n )}\n {tunnelState.status === \"error\" && (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box>\n <Text>🌍{\" \"}</Text>\n <Text color=\"red\">\n Cannot open tunnel: {tunnelState.message}\n </Text>\n </Box>\n <Box>\n <Text color=\"#20a832\">→{\" \"}</Text>\n <Text color=\"red\">{`Try manually: npx alpic tunnel --port ${port}`}</Text>\n </Box>\n </Box>\n )}\n\n <Box>\n <Text>🛟{\" \"}</Text>\n <Text>Need help? Reach us on </Text>\n <Text color=\"white\" underline>\n https://discord.alpic.ai\n </Text>\n </Box>\n\n {tsErrors.length > 0 && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"red\" bold>\n ⚠️ TypeScript errors found:\n </Text>\n {tsErrors.map((error) => (\n <Box\n key={`${error.file}:${error.line}:${error.col}`}\n marginLeft={2}\n flexDirection=\"column\"\n >\n <Box>\n <Text color=\"white\">{error.file}</Text>\n <Text color=\"grey\">\n ({error.line},{error.col}):{\" \"}\n </Text>\n </Box>\n <Box marginLeft={2}>\n <Text color=\"red\">{error.message}</Text>\n </Box>\n </Box>\n ))}\n </Box>\n )}\n {messages.length > 0 && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"white\" bold>\n Logs:\n </Text>\n {messages.map((message) => (\n <Box key={message.id} marginLeft={2}>\n {message.type === \"restart\" ? (\n <>\n <Text color=\"green\">✓{\" \"}</Text>\n <Text color=\"white\">{message.text}</Text>\n </>\n ) : message.type === \"error\" ? (\n <Text color=\"red\">{message.text}</Text>\n ) : (\n <Text>{message.text}</Text>\n )}\n </Box>\n ))}\n </Box>\n )}\n </Box>\n );\n };\n\n // Note: `exitOnCtrlC: false` because we own SIGINT below to guarantee\n // alpic gets killed before we exit. If anything ever calls `useInput` or\n // puts stdin into raw mode, also wire an explicit `\\x03` keypress to the\n // shutdown function — Ink will otherwise swallow Ctrl-C without ever\n // delivering SIGINT.\n const ink = render(<App />, { exitOnCtrlC: false, patchConsole: true });\n\n // Synchronous-first shutdown: kill the alpic subprocess up front so we\n // can't leave it orphaned even if another SIGINT listener (e.g. nodemon's)\n // exits the process before our async cleanup completes.\n const shutdown = (code: number) => () => {\n tunnelManager.stop();\n void closeTunnelControl()\n .catch((err) => {\n console.error(\"Failed to close tunnel control server\", err);\n })\n .finally(() => {\n ink.unmount();\n process.exit(code);\n });\n };\n process.once(\"SIGINT\", shutdown(130));\n process.once(\"SIGTERM\", shutdown(143));\n }\n}\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Adaptor, CallToolResponse, DownloadParams, DownloadResult, FileMetadata, HostContext, HostContextStore, OpenExternalOptions, RequestDisplayMode, RequestModalOptions, RequestSizeOptions, SendFollowUpMessageOptions, SetViewStateAction, UploadFileOptions } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* @internal
|
|
4
|
+
* Single composite implementation of {@link Adaptor}. Composes the MCP App
|
|
5
|
+
* bridge (always present) with an optional `window.openai` overlay. Per-method
|
|
6
|
+
* routing rules are encoded inline.
|
|
7
|
+
*/
|
|
8
|
+
export declare class HostAdaptor implements Adaptor {
|
|
9
|
+
private readonly mcp;
|
|
10
|
+
private readonly oai;
|
|
11
|
+
private readonly oaiBridge;
|
|
12
|
+
private readonly mcpStores;
|
|
13
|
+
private readonly oaiStores;
|
|
14
|
+
private _viewState;
|
|
15
|
+
private readonly viewStateListeners;
|
|
16
|
+
private _viewUUID;
|
|
17
|
+
private _polyfillDisplay;
|
|
18
|
+
private readonly polyfillDisplayListeners;
|
|
19
|
+
private unsubscribeViewUUID;
|
|
20
|
+
constructor();
|
|
21
|
+
hasAppsSdkOverlay(): boolean;
|
|
22
|
+
/** @internal Release any subscriptions held on the underlying bridges. */
|
|
23
|
+
cleanup(): void;
|
|
24
|
+
getHostContextStore: <K extends keyof HostContext>(key: K) => HostContextStore<K>;
|
|
25
|
+
callTool: <ToolArgs extends Record<string, unknown> | null = null, ToolResponse extends CallToolResponse = CallToolResponse>(name: string, args: ToolArgs) => Promise<ToolResponse>;
|
|
26
|
+
requestDisplayMode: (mode: RequestDisplayMode) => Promise<{
|
|
27
|
+
[x: string]: unknown;
|
|
28
|
+
mode: "inline" | "fullscreen" | "pip";
|
|
29
|
+
}>;
|
|
30
|
+
requestClose: () => Promise<void>;
|
|
31
|
+
requestSize: (size: RequestSizeOptions) => Promise<void>;
|
|
32
|
+
sendFollowUpMessage: (prompt: string, options?: SendFollowUpMessageOptions) => Promise<void>;
|
|
33
|
+
openExternal: (href: string, options?: OpenExternalOptions) => void;
|
|
34
|
+
download: (params: DownloadParams) => Promise<DownloadResult>;
|
|
35
|
+
setViewState: (stateOrUpdater: SetViewStateAction) => Promise<void>;
|
|
36
|
+
uploadFile: (file: File, options?: UploadFileOptions) => Promise<FileMetadata>;
|
|
37
|
+
getFileDownloadUrl: (file: FileMetadata) => Promise<{
|
|
38
|
+
downloadUrl: string;
|
|
39
|
+
}>;
|
|
40
|
+
selectFiles: () => Promise<FileMetadata[]>;
|
|
41
|
+
openModal: (options: RequestModalOptions) => void;
|
|
42
|
+
setOpenInAppUrl: (href: string) => Promise<void>;
|
|
43
|
+
closeModal: () => void;
|
|
44
|
+
private trackFileIds;
|
|
45
|
+
private subscribeToViewUUID;
|
|
46
|
+
private restoreFromLocalStorage;
|
|
47
|
+
protected persistToLocalStorage(state: Record<string, unknown> | null): void;
|
|
48
|
+
}
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { AppsSdkBridge } from "./apps-sdk/bridge.js";
|
|
2
|
+
import { buildAppsSdkOverlayStores, buildMcpContextStores, } from "./host-context-stores.js";
|
|
3
|
+
import { McpAppBridge } from "./mcp-app/bridge.js";
|
|
4
|
+
import { NotSupportedError } from "./types.js";
|
|
5
|
+
const STORAGE_PREFIX = "sb:";
|
|
6
|
+
const MAX_STORAGE_ENTRIES = 200;
|
|
7
|
+
function findStorageKey(viewUUID) {
|
|
8
|
+
const suffix = `:${viewUUID}`;
|
|
9
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
10
|
+
const key = localStorage.key(i);
|
|
11
|
+
if (key?.startsWith(STORAGE_PREFIX) && key.endsWith(suffix)) {
|
|
12
|
+
return key;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* @internal
|
|
19
|
+
* Single composite implementation of {@link Adaptor}. Composes the MCP App
|
|
20
|
+
* bridge (always present) with an optional `window.openai` overlay. Per-method
|
|
21
|
+
* routing rules are encoded inline.
|
|
22
|
+
*/
|
|
23
|
+
export class HostAdaptor {
|
|
24
|
+
mcp;
|
|
25
|
+
oai;
|
|
26
|
+
oaiBridge;
|
|
27
|
+
mcpStores;
|
|
28
|
+
oaiStores;
|
|
29
|
+
_viewState = null;
|
|
30
|
+
viewStateListeners = new Set();
|
|
31
|
+
_viewUUID = null;
|
|
32
|
+
_polyfillDisplay = { mode: "inline" };
|
|
33
|
+
polyfillDisplayListeners = new Set();
|
|
34
|
+
unsubscribeViewUUID = null;
|
|
35
|
+
constructor() {
|
|
36
|
+
this.mcp = McpAppBridge.getInstance();
|
|
37
|
+
this.mcpStores = buildMcpContextStores(this.mcp);
|
|
38
|
+
if (typeof window !== "undefined" && window.openai !== undefined) {
|
|
39
|
+
this.oai = window.openai;
|
|
40
|
+
this.oaiBridge = AppsSdkBridge.getInstance();
|
|
41
|
+
this.oaiStores = buildAppsSdkOverlayStores(this.oaiBridge);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
this.oai = null;
|
|
45
|
+
this.oaiBridge = null;
|
|
46
|
+
this.oaiStores = null;
|
|
47
|
+
}
|
|
48
|
+
this.subscribeToViewUUID();
|
|
49
|
+
}
|
|
50
|
+
hasAppsSdkOverlay() {
|
|
51
|
+
return this.oai !== null;
|
|
52
|
+
}
|
|
53
|
+
/** @internal Release any subscriptions held on the underlying bridges. */
|
|
54
|
+
cleanup() {
|
|
55
|
+
this.unsubscribeViewUUID?.();
|
|
56
|
+
this.unsubscribeViewUUID = null;
|
|
57
|
+
}
|
|
58
|
+
// ---- Adaptor interface (stubs) ----
|
|
59
|
+
getHostContextStore = (key) => {
|
|
60
|
+
if (this.oaiStores && (key === "display" || key === "viewState")) {
|
|
61
|
+
return this.oaiStores[key];
|
|
62
|
+
}
|
|
63
|
+
if (key === "display") {
|
|
64
|
+
return {
|
|
65
|
+
subscribe: (onChange) => {
|
|
66
|
+
this.polyfillDisplayListeners.add(onChange);
|
|
67
|
+
return () => {
|
|
68
|
+
this.polyfillDisplayListeners.delete(onChange);
|
|
69
|
+
};
|
|
70
|
+
},
|
|
71
|
+
getSnapshot: () => this._polyfillDisplay,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (key === "viewState") {
|
|
75
|
+
return {
|
|
76
|
+
subscribe: (onChange) => {
|
|
77
|
+
this.viewStateListeners.add(onChange);
|
|
78
|
+
return () => {
|
|
79
|
+
this.viewStateListeners.delete(onChange);
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
getSnapshot: () => this._viewState,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return this.mcpStores[key];
|
|
86
|
+
};
|
|
87
|
+
callTool = async (name, args) => {
|
|
88
|
+
const app = await this.mcp.getApp();
|
|
89
|
+
const response = await app.callServerTool({
|
|
90
|
+
name,
|
|
91
|
+
arguments: args ?? undefined,
|
|
92
|
+
});
|
|
93
|
+
return {
|
|
94
|
+
content: response.content,
|
|
95
|
+
structuredContent: response.structuredContent ?? {},
|
|
96
|
+
isError: response.isError ?? false,
|
|
97
|
+
meta: response._meta ?? {},
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
requestDisplayMode = async (mode) => {
|
|
101
|
+
const app = await this.mcp.getApp();
|
|
102
|
+
return app.requestDisplayMode({ mode });
|
|
103
|
+
};
|
|
104
|
+
requestClose = async () => {
|
|
105
|
+
const app = await this.mcp.getApp();
|
|
106
|
+
await app.requestTeardown();
|
|
107
|
+
};
|
|
108
|
+
requestSize = async (size) => {
|
|
109
|
+
const app = await this.mcp.getApp();
|
|
110
|
+
await app.sendSizeChanged(size);
|
|
111
|
+
};
|
|
112
|
+
sendFollowUpMessage = async (prompt, options) => {
|
|
113
|
+
if (this.oai && options?.scrollToBottom !== undefined) {
|
|
114
|
+
await this.oai.sendFollowUpMessage({
|
|
115
|
+
prompt,
|
|
116
|
+
scrollToBottom: options.scrollToBottom,
|
|
117
|
+
});
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const app = await this.mcp.getApp();
|
|
121
|
+
await app.sendMessage({
|
|
122
|
+
role: "user",
|
|
123
|
+
content: [{ type: "text", text: prompt }],
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
openExternal = (href, options) => {
|
|
127
|
+
if (this.oai && options?.redirectUrl === false) {
|
|
128
|
+
this.oai.openExternal({ href, redirectUrl: false });
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
this.mcp
|
|
132
|
+
.getApp()
|
|
133
|
+
.then((app) => app.openLink({ url: href }))
|
|
134
|
+
.catch((err) => {
|
|
135
|
+
console.error("Failed to open external link:", err);
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
download = async (params) => {
|
|
139
|
+
const app = await this.mcp.getApp();
|
|
140
|
+
if (!app.getHostCapabilities()?.downloadFile) {
|
|
141
|
+
console.error("[skybridge] download: host does not support ui/download-file");
|
|
142
|
+
return { isError: true };
|
|
143
|
+
}
|
|
144
|
+
return app.downloadFile(params);
|
|
145
|
+
};
|
|
146
|
+
setViewState = async (stateOrUpdater) => {
|
|
147
|
+
if (this.oai) {
|
|
148
|
+
const modelContent = typeof stateOrUpdater === "function"
|
|
149
|
+
? stateOrUpdater(this.oai.widgetState?.modelContent ?? null)
|
|
150
|
+
: stateOrUpdater;
|
|
151
|
+
await this.oai.setWidgetState({
|
|
152
|
+
privateContent: {},
|
|
153
|
+
...this.oai.widgetState,
|
|
154
|
+
modelContent,
|
|
155
|
+
});
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const newState = typeof stateOrUpdater === "function"
|
|
159
|
+
? stateOrUpdater(this._viewState)
|
|
160
|
+
: stateOrUpdater;
|
|
161
|
+
// update local state immediately so successive calls see fresh state
|
|
162
|
+
this._viewState = newState;
|
|
163
|
+
this.viewStateListeners.forEach((l) => {
|
|
164
|
+
l();
|
|
165
|
+
});
|
|
166
|
+
this.persistToLocalStorage(newState);
|
|
167
|
+
try {
|
|
168
|
+
const app = await this.mcp.getApp();
|
|
169
|
+
await app.updateModelContext({
|
|
170
|
+
structuredContent: newState,
|
|
171
|
+
content: [{ type: "text", text: JSON.stringify(newState) }],
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
console.error("Failed to update view state in MCP App.", error);
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
uploadFile = async (file, options) => {
|
|
179
|
+
if (!this.oai) {
|
|
180
|
+
throw new NotSupportedError("uploadFile");
|
|
181
|
+
}
|
|
182
|
+
const metadata = await this.oai.uploadFile(file, options);
|
|
183
|
+
await this.trackFileIds(metadata.fileId);
|
|
184
|
+
return metadata;
|
|
185
|
+
};
|
|
186
|
+
getFileDownloadUrl = (file) => {
|
|
187
|
+
if (!this.oai) {
|
|
188
|
+
return Promise.reject(new NotSupportedError("getFileDownloadUrl"));
|
|
189
|
+
}
|
|
190
|
+
return this.oai.getFileDownloadUrl(file);
|
|
191
|
+
};
|
|
192
|
+
selectFiles = async () => {
|
|
193
|
+
if (!this.oai) {
|
|
194
|
+
throw new NotSupportedError("selectFiles");
|
|
195
|
+
}
|
|
196
|
+
if (!this.oai.selectFiles) {
|
|
197
|
+
throw new Error("selectFiles is not supported by the current host version.");
|
|
198
|
+
}
|
|
199
|
+
const files = await this.oai.selectFiles();
|
|
200
|
+
if (files.length > 0) {
|
|
201
|
+
await this.trackFileIds(...files.map((f) => f.fileId));
|
|
202
|
+
}
|
|
203
|
+
return files;
|
|
204
|
+
};
|
|
205
|
+
openModal = (options) => {
|
|
206
|
+
if (this.oai) {
|
|
207
|
+
this.oai.requestModal(options);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
this._polyfillDisplay = { mode: "modal", params: options.params };
|
|
211
|
+
this.polyfillDisplayListeners.forEach((l) => {
|
|
212
|
+
l();
|
|
213
|
+
});
|
|
214
|
+
};
|
|
215
|
+
setOpenInAppUrl = (href) => {
|
|
216
|
+
if (!this.oai) {
|
|
217
|
+
return Promise.reject(new NotSupportedError("setOpenInAppUrl"));
|
|
218
|
+
}
|
|
219
|
+
const trimmed = href.trim();
|
|
220
|
+
if (!trimmed) {
|
|
221
|
+
return Promise.reject(new Error("The href parameter is required."));
|
|
222
|
+
}
|
|
223
|
+
return this.oai.setOpenInAppUrl({ href: trimmed });
|
|
224
|
+
};
|
|
225
|
+
closeModal = () => {
|
|
226
|
+
if (this.oai) {
|
|
227
|
+
return; // host owns modal lifecycle
|
|
228
|
+
}
|
|
229
|
+
this._polyfillDisplay = { mode: "inline" };
|
|
230
|
+
this.polyfillDisplayListeners.forEach((l) => {
|
|
231
|
+
l();
|
|
232
|
+
});
|
|
233
|
+
};
|
|
234
|
+
async trackFileIds(...fileIds) {
|
|
235
|
+
if (!this.oai) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const current = this.oai.widgetState;
|
|
239
|
+
const state = current
|
|
240
|
+
? { ...current }
|
|
241
|
+
: { modelContent: {}, privateContent: {} };
|
|
242
|
+
if (!state.imageIds) {
|
|
243
|
+
state.imageIds = [];
|
|
244
|
+
}
|
|
245
|
+
state.imageIds.push(...fileIds);
|
|
246
|
+
await this.oai.setWidgetState(state);
|
|
247
|
+
}
|
|
248
|
+
// ---- viewState persistence helpers (used in subsequent tasks) ----
|
|
249
|
+
subscribeToViewUUID() {
|
|
250
|
+
this.unsubscribeViewUUID = this.mcp.subscribe("toolResult")(() => {
|
|
251
|
+
const toolResult = this.mcp.getSnapshot("toolResult");
|
|
252
|
+
const viewUUID = toolResult?._meta?.viewUUID;
|
|
253
|
+
if (viewUUID && viewUUID !== this._viewUUID) {
|
|
254
|
+
this._viewUUID = viewUUID;
|
|
255
|
+
this.restoreFromLocalStorage(viewUUID);
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
restoreFromLocalStorage(viewUUID) {
|
|
260
|
+
try {
|
|
261
|
+
const existingKey = findStorageKey(viewUUID);
|
|
262
|
+
if (existingKey) {
|
|
263
|
+
const stored = localStorage.getItem(existingKey);
|
|
264
|
+
if (stored !== null) {
|
|
265
|
+
this._viewState = JSON.parse(stored);
|
|
266
|
+
this.viewStateListeners.forEach((l) => {
|
|
267
|
+
l();
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
catch (err) {
|
|
273
|
+
console.error(err);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
persistToLocalStorage(state) {
|
|
277
|
+
if (!this._viewUUID || state === null) {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
try {
|
|
281
|
+
const oldKey = findStorageKey(this._viewUUID);
|
|
282
|
+
if (oldKey) {
|
|
283
|
+
localStorage.removeItem(oldKey);
|
|
284
|
+
}
|
|
285
|
+
const newKey = `${STORAGE_PREFIX}${Date.now()}:${this._viewUUID}`;
|
|
286
|
+
localStorage.setItem(newKey, JSON.stringify(state));
|
|
287
|
+
const keys = [];
|
|
288
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
289
|
+
const key = localStorage.key(i);
|
|
290
|
+
if (key?.startsWith(STORAGE_PREFIX)) {
|
|
291
|
+
keys.push(key);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
if (keys.length <= MAX_STORAGE_ENTRIES) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
keys.sort();
|
|
298
|
+
const toRemove = keys.slice(0, keys.length - MAX_STORAGE_ENTRIES);
|
|
299
|
+
for (const key of toRemove) {
|
|
300
|
+
localStorage.removeItem(key);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
catch (err) {
|
|
304
|
+
console.error(err);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
//# sourceMappingURL=adaptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adaptor.js","sourceRoot":"","sources":["../../../src/web/bridges/adaptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EACL,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAiBnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,cAAc,GAAG,KAAK,CAAC;AAC7B,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEhC,SAAS,cAAc,CAAC,QAAgB;IACtC,MAAM,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAChC,IAAI,GAAG,EAAE,UAAU,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5D,OAAO,GAAG,CAAC;QACb,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,WAAW;IACL,GAAG,CAAe;IAClB,GAAG,CAA8B;IACjC,SAAS,CAAuB;IAEhC,SAAS,CAA2C;IACpD,SAAS,CAEjB;IAED,UAAU,GAA6B,IAAI,CAAC;IACnC,kBAAkB,GAAG,IAAI,GAAG,EAAc,CAAC;IACpD,SAAS,GAAkB,IAAI,CAAC;IAEhC,gBAAgB,GAA2B,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACrD,wBAAwB,GAAG,IAAI,GAAG,EAAc,CAAC;IAE1D,mBAAmB,GAAwB,IAAI,CAAC;IAExD;QACE,IAAI,CAAC,GAAG,GAAG,YAAY,CAAC,WAAW,EAAE,CAAC;QACtC,IAAI,CAAC,SAAS,GAAG,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEjD,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACjE,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;YACzB,IAAI,CAAC,SAAS,GAAG,aAAa,CAAC,WAAW,EAAE,CAAC;YAC7C,IAAI,CAAC,SAAS,GAAG,yBAAyB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC7D,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;YAChB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACxB,CAAC;QAED,IAAI,CAAC,mBAAmB,EAAE,CAAC;IAC7B,CAAC;IAEM,iBAAiB;QACtB,OAAO,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC;IAC3B,CAAC;IAED,0EAA0E;IACnE,OAAO;QACZ,IAAI,CAAC,mBAAmB,EAAE,EAAE,CAAC;QAC7B,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAClC,CAAC;IAED,sCAAsC;IAE/B,mBAAmB,GAAG,CAC3B,GAAM,EACe,EAAE;QACvB,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,WAAW,CAAC,EAAE,CAAC;YACjE,OAAO,IAAI,CAAC,SAAS,CACnB,GAA8B,CACR,CAAC;QAC3B,CAAC;QAED,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,OAAO;gBACL,SAAS,EAAE,CAAC,QAAoB,EAAE,EAAE;oBAClC,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;oBAC5C,OAAO,GAAG,EAAE;wBACV,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;oBACjD,CAAC,CAAC;gBACJ,CAAC;gBACD,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB;aAClB,CAAC;QAC3B,CAAC;QAED,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YACxB,OAAO;gBACL,SAAS,EAAE,CAAC,QAAoB,EAAE,EAAE;oBAClC,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;oBACtC,OAAO,GAAG,EAAE;wBACV,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;oBAC3C,CAAC,CAAC;gBACJ,CAAC;gBACD,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU;aACZ,CAAC;QAC3B,CAAC;QAED,OAAO,IAAI,CAAC,SAAS,CACnB,GAAkC,CACZ,CAAC;IAC3B,CAAC,CAAC;IAEK,QAAQ,GAAG,KAAK,EAIrB,IAAY,EACZ,IAAc,EACS,EAAE;QACzB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,cAAc,CAAC;YACxC,IAAI;YACJ,SAAS,EAAE,IAAI,IAAI,SAAS;SAC7B,CAAC,CAAC;QACH,OAAO;YACL,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB,IAAI,EAAE;YACnD,OAAO,EAAE,QAAQ,CAAC,OAAO,IAAI,KAAK;YAClC,IAAI,EAAE,QAAQ,CAAC,KAAK,IAAI,EAAE;SACX,CAAC;IACpB,CAAC,CAAC;IAEK,kBAAkB,GAAG,KAAK,EAAE,IAAwB,EAAE,EAAE;QAC7D,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QACpC,OAAO,GAAG,CAAC,kBAAkB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC;IAEK,YAAY,GAAG,KAAK,IAAmB,EAAE;QAC9C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QACpC,MAAM,GAAG,CAAC,eAAe,EAAE,CAAC;IAC9B,CAAC,CAAC;IAEK,WAAW,GAAG,KAAK,EAAE,IAAwB,EAAiB,EAAE;QACrE,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QACpC,MAAM,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC;IAEK,mBAAmB,GAAG,KAAK,EAChC,MAAc,EACd,OAAoC,EACrB,EAAE;QACjB,IAAI,IAAI,CAAC,GAAG,IAAI,OAAO,EAAE,cAAc,KAAK,SAAS,EAAE,CAAC;YACtD,MAAM,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAC;gBACjC,MAAM;gBACN,cAAc,EAAE,OAAO,CAAC,cAAc;aACvC,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QACpC,MAAM,GAAG,CAAC,WAAW,CAAC;YACpB,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;SAC1C,CAAC,CAAC;IACL,CAAC,CAAC;IAEK,YAAY,GAAG,CAAC,IAAY,EAAE,OAA6B,EAAQ,EAAE;QAC1E,IAAI,IAAI,CAAC,GAAG,IAAI,OAAO,EAAE,WAAW,KAAK,KAAK,EAAE,CAAC;YAC/C,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;YACpD,OAAO;QACT,CAAC;QACD,IAAI,CAAC,GAAG;aACL,MAAM,EAAE;aACR,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;aAC1C,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACb,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,GAAG,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;IAEK,QAAQ,GAAG,KAAK,EAAE,MAAsB,EAA2B,EAAE;QAC1E,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QACpC,IAAI,CAAC,GAAG,CAAC,mBAAmB,EAAE,EAAE,YAAY,EAAE,CAAC;YAC7C,OAAO,CAAC,KAAK,CACX,8DAA8D,CAC/D,CAAC;YACF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QACD,OAAO,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC,CAAC;IAEK,YAAY,GAAG,KAAK,EACzB,cAAkC,EACnB,EAAE;QACjB,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACb,MAAM,YAAY,GAChB,OAAO,cAAc,KAAK,UAAU;gBAClC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,YAAY,IAAI,IAAI,CAAC;gBAC5D,CAAC,CAAC,cAAc,CAAC;YACrB,MAAM,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC;gBAC5B,cAAc,EAAE,EAAE;gBAClB,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW;gBACvB,YAAY;aACb,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GACZ,OAAO,cAAc,KAAK,UAAU;YAClC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC;YACjC,CAAC,CAAC,cAAc,CAAC;QAErB,qEAAqE;QACrE,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC;QAC3B,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACpC,CAAC,EAAE,CAAC;QACN,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QAErC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;YACpC,MAAM,GAAG,CAAC,kBAAkB,CAAC;gBAC3B,iBAAiB,EAAE,QAAQ;gBAC3B,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;aAC5D,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,KAAK,CAAC,CAAC;QAClE,CAAC;IACH,CAAC,CAAC;IAEK,UAAU,GAAG,KAAK,EACvB,IAAU,EACV,OAA2B,EACJ,EAAE;QACzB,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,iBAAiB,CAAC,YAAY,CAAC,CAAC;QAC5C,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC1D,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzC,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;IAEK,kBAAkB,GAAG,CAC1B,IAAkB,EACgB,EAAE;QACpC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,iBAAiB,CAAC,oBAAoB,CAAC,CAAC,CAAC;QACrE,CAAC;QACD,OAAO,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC,CAAC;IAEK,WAAW,GAAG,KAAK,IAA6B,EAAE;QACvD,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,iBAAiB,CAAC,aAAa,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CACb,2DAA2D,CAC5D,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QAC3C,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QACzD,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEK,SAAS,GAAG,CAAC,OAA4B,EAAQ,EAAE;QACxD,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAC/B,OAAO;QACT,CAAC;QACD,IAAI,CAAC,gBAAgB,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;QAClE,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YAC1C,CAAC,EAAE,CAAC;QACN,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEK,eAAe,GAAG,CAAC,IAAY,EAAiB,EAAE;QACvD,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,iBAAiB,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAClE,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAC;QACtE,CAAC;QACD,OAAO,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC;IAEK,UAAU,GAAG,GAAS,EAAE;QAC7B,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,4BAA4B;QACtC,CAAC;QACD,IAAI,CAAC,gBAAgB,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QAC3C,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YAC1C,CAAC,EAAE,CAAC;QACN,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEM,KAAK,CAAC,YAAY,CAAC,GAAG,OAAiB;QAC7C,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC;QACrC,MAAM,KAAK,GAAuB,OAAO;YACvC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE;YAChB,CAAC,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC;QAC7C,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YACpB,KAAK,CAAC,QAAQ,GAAG,EAAE,CAAC;QACtB,CAAC;QACD,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;QAChC,MAAM,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IAED,qEAAqE;IAE7D,mBAAmB;QACzB,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE;YAC/D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;YACtD,MAAM,QAAQ,GACZ,UAAU,EAAE,KACb,EAAE,QAA8B,CAAC;YAClC,IAAI,QAAQ,IAAI,QAAQ,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC;gBAC5C,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;gBAC1B,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAAC,CAAC;YACzC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,uBAAuB,CAAC,QAAgB;QAC9C,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;YAC7C,IAAI,WAAW,EAAE,CAAC;gBAChB,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;gBACjD,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;oBACpB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;oBACrC,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;wBACpC,CAAC,EAAE,CAAC;oBACN,CAAC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAES,qBAAqB,CAAC,KAAqC;QACnE,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACtC,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC9C,IAAI,MAAM,EAAE,CAAC;gBACX,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YAClC,CAAC;YACD,MAAM,MAAM,GAAG,GAAG,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAClE,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;YACpD,MAAM,IAAI,GAAa,EAAE,CAAC;YAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7C,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBAChC,IAAI,GAAG,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;oBACpC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACjB,CAAC;YACH,CAAC;YACD,IAAI,IAAI,CAAC,MAAM,IAAI,mBAAmB,EAAE,CAAC;gBACvC,OAAO;YACT,CAAC;YACD,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,mBAAmB,CAAC,CAAC;YAClE,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;gBAC3B,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;CACF","sourcesContent":["import { AppsSdkBridge } from \"./apps-sdk/bridge.js\";\nimport type { AppsSdkWidgetState } from \"./apps-sdk/types.js\";\nimport {\n buildAppsSdkOverlayStores,\n buildMcpContextStores,\n} from \"./host-context-stores.js\";\nimport { McpAppBridge } from \"./mcp-app/bridge.js\";\nimport type {\n Adaptor,\n CallToolResponse,\n DownloadParams,\n DownloadResult,\n FileMetadata,\n HostContext,\n HostContextStore,\n OpenExternalOptions,\n RequestDisplayMode,\n RequestModalOptions,\n RequestSizeOptions,\n SendFollowUpMessageOptions,\n SetViewStateAction,\n UploadFileOptions,\n} from \"./types.js\";\nimport { NotSupportedError } from \"./types.js\";\n\nconst STORAGE_PREFIX = \"sb:\";\nconst MAX_STORAGE_ENTRIES = 200;\n\nfunction findStorageKey(viewUUID: string): string | undefined {\n const suffix = `:${viewUUID}`;\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(STORAGE_PREFIX) && key.endsWith(suffix)) {\n return key;\n }\n }\n return undefined;\n}\n\n/**\n * @internal\n * Single composite implementation of {@link Adaptor}. Composes the MCP App\n * bridge (always present) with an optional `window.openai` overlay. Per-method\n * routing rules are encoded inline.\n */\nexport class HostAdaptor implements Adaptor {\n private readonly mcp: McpAppBridge;\n private readonly oai: typeof window.openai | null;\n private readonly oaiBridge: AppsSdkBridge | null;\n\n private readonly mcpStores: ReturnType<typeof buildMcpContextStores>;\n private readonly oaiStores: ReturnType<\n typeof buildAppsSdkOverlayStores\n > | null;\n\n private _viewState: HostContext[\"viewState\"] = null;\n private readonly viewStateListeners = new Set<() => void>();\n private _viewUUID: string | null = null;\n\n private _polyfillDisplay: HostContext[\"display\"] = { mode: \"inline\" };\n private readonly polyfillDisplayListeners = new Set<() => void>();\n\n private unsubscribeViewUUID: (() => void) | null = null;\n\n constructor() {\n this.mcp = McpAppBridge.getInstance();\n this.mcpStores = buildMcpContextStores(this.mcp);\n\n if (typeof window !== \"undefined\" && window.openai !== undefined) {\n this.oai = window.openai;\n this.oaiBridge = AppsSdkBridge.getInstance();\n this.oaiStores = buildAppsSdkOverlayStores(this.oaiBridge);\n } else {\n this.oai = null;\n this.oaiBridge = null;\n this.oaiStores = null;\n }\n\n this.subscribeToViewUUID();\n }\n\n public hasAppsSdkOverlay(): boolean {\n return this.oai !== null;\n }\n\n /** @internal Release any subscriptions held on the underlying bridges. */\n public cleanup(): void {\n this.unsubscribeViewUUID?.();\n this.unsubscribeViewUUID = null;\n }\n\n // ---- Adaptor interface (stubs) ----\n\n public getHostContextStore = <K extends keyof HostContext>(\n key: K,\n ): HostContextStore<K> => {\n if (this.oaiStores && (key === \"display\" || key === \"viewState\")) {\n return this.oaiStores[\n key as \"display\" | \"viewState\"\n ] as HostContextStore<K>;\n }\n\n if (key === \"display\") {\n return {\n subscribe: (onChange: () => void) => {\n this.polyfillDisplayListeners.add(onChange);\n return () => {\n this.polyfillDisplayListeners.delete(onChange);\n };\n },\n getSnapshot: () => this._polyfillDisplay,\n } as HostContextStore<K>;\n }\n\n if (key === \"viewState\") {\n return {\n subscribe: (onChange: () => void) => {\n this.viewStateListeners.add(onChange);\n return () => {\n this.viewStateListeners.delete(onChange);\n };\n },\n getSnapshot: () => this._viewState,\n } as HostContextStore<K>;\n }\n\n return this.mcpStores[\n key as keyof typeof this.mcpStores\n ] as HostContextStore<K>;\n };\n\n public callTool = async <\n ToolArgs extends Record<string, unknown> | null = null,\n ToolResponse extends CallToolResponse = CallToolResponse,\n >(\n name: string,\n args: ToolArgs,\n ): Promise<ToolResponse> => {\n const app = await this.mcp.getApp();\n const response = await app.callServerTool({\n name,\n arguments: args ?? undefined,\n });\n return {\n content: response.content,\n structuredContent: response.structuredContent ?? {},\n isError: response.isError ?? false,\n meta: response._meta ?? {},\n } as ToolResponse;\n };\n\n public requestDisplayMode = async (mode: RequestDisplayMode) => {\n const app = await this.mcp.getApp();\n return app.requestDisplayMode({ mode });\n };\n\n public requestClose = async (): Promise<void> => {\n const app = await this.mcp.getApp();\n await app.requestTeardown();\n };\n\n public requestSize = async (size: RequestSizeOptions): Promise<void> => {\n const app = await this.mcp.getApp();\n await app.sendSizeChanged(size);\n };\n\n public sendFollowUpMessage = async (\n prompt: string,\n options?: SendFollowUpMessageOptions,\n ): Promise<void> => {\n if (this.oai && options?.scrollToBottom !== undefined) {\n await this.oai.sendFollowUpMessage({\n prompt,\n scrollToBottom: options.scrollToBottom,\n });\n return;\n }\n const app = await this.mcp.getApp();\n await app.sendMessage({\n role: \"user\",\n content: [{ type: \"text\", text: prompt }],\n });\n };\n\n public openExternal = (href: string, options?: OpenExternalOptions): void => {\n if (this.oai && options?.redirectUrl === false) {\n this.oai.openExternal({ href, redirectUrl: false });\n return;\n }\n this.mcp\n .getApp()\n .then((app) => app.openLink({ url: href }))\n .catch((err) => {\n console.error(\"Failed to open external link:\", err);\n });\n };\n\n public download = async (params: DownloadParams): Promise<DownloadResult> => {\n const app = await this.mcp.getApp();\n if (!app.getHostCapabilities()?.downloadFile) {\n console.error(\n \"[skybridge] download: host does not support ui/download-file\",\n );\n return { isError: true };\n }\n return app.downloadFile(params);\n };\n\n public setViewState = async (\n stateOrUpdater: SetViewStateAction,\n ): Promise<void> => {\n if (this.oai) {\n const modelContent =\n typeof stateOrUpdater === \"function\"\n ? stateOrUpdater(this.oai.widgetState?.modelContent ?? null)\n : stateOrUpdater;\n await this.oai.setWidgetState({\n privateContent: {},\n ...this.oai.widgetState,\n modelContent,\n });\n return;\n }\n\n const newState =\n typeof stateOrUpdater === \"function\"\n ? stateOrUpdater(this._viewState)\n : stateOrUpdater;\n\n // update local state immediately so successive calls see fresh state\n this._viewState = newState;\n this.viewStateListeners.forEach((l) => {\n l();\n });\n\n this.persistToLocalStorage(newState);\n\n try {\n const app = await this.mcp.getApp();\n await app.updateModelContext({\n structuredContent: newState,\n content: [{ type: \"text\", text: JSON.stringify(newState) }],\n });\n } catch (error) {\n console.error(\"Failed to update view state in MCP App.\", error);\n }\n };\n\n public uploadFile = async (\n file: File,\n options?: UploadFileOptions,\n ): Promise<FileMetadata> => {\n if (!this.oai) {\n throw new NotSupportedError(\"uploadFile\");\n }\n const metadata = await this.oai.uploadFile(file, options);\n await this.trackFileIds(metadata.fileId);\n return metadata;\n };\n\n public getFileDownloadUrl = (\n file: FileMetadata,\n ): Promise<{ downloadUrl: string }> => {\n if (!this.oai) {\n return Promise.reject(new NotSupportedError(\"getFileDownloadUrl\"));\n }\n return this.oai.getFileDownloadUrl(file);\n };\n\n public selectFiles = async (): Promise<FileMetadata[]> => {\n if (!this.oai) {\n throw new NotSupportedError(\"selectFiles\");\n }\n if (!this.oai.selectFiles) {\n throw new Error(\n \"selectFiles is not supported by the current host version.\",\n );\n }\n const files = await this.oai.selectFiles();\n if (files.length > 0) {\n await this.trackFileIds(...files.map((f) => f.fileId));\n }\n return files;\n };\n\n public openModal = (options: RequestModalOptions): void => {\n if (this.oai) {\n this.oai.requestModal(options);\n return;\n }\n this._polyfillDisplay = { mode: \"modal\", params: options.params };\n this.polyfillDisplayListeners.forEach((l) => {\n l();\n });\n };\n\n public setOpenInAppUrl = (href: string): Promise<void> => {\n if (!this.oai) {\n return Promise.reject(new NotSupportedError(\"setOpenInAppUrl\"));\n }\n const trimmed = href.trim();\n if (!trimmed) {\n return Promise.reject(new Error(\"The href parameter is required.\"));\n }\n return this.oai.setOpenInAppUrl({ href: trimmed });\n };\n\n public closeModal = (): void => {\n if (this.oai) {\n return; // host owns modal lifecycle\n }\n this._polyfillDisplay = { mode: \"inline\" };\n this.polyfillDisplayListeners.forEach((l) => {\n l();\n });\n };\n\n private async trackFileIds(...fileIds: string[]): Promise<void> {\n if (!this.oai) {\n return;\n }\n const current = this.oai.widgetState;\n const state: AppsSdkWidgetState = current\n ? { ...current }\n : { modelContent: {}, privateContent: {} };\n if (!state.imageIds) {\n state.imageIds = [];\n }\n state.imageIds.push(...fileIds);\n await this.oai.setWidgetState(state);\n }\n\n // ---- viewState persistence helpers (used in subsequent tasks) ----\n\n private subscribeToViewUUID(): void {\n this.unsubscribeViewUUID = this.mcp.subscribe(\"toolResult\")(() => {\n const toolResult = this.mcp.getSnapshot(\"toolResult\");\n const viewUUID = (\n toolResult?._meta as Record<string, unknown> | undefined\n )?.viewUUID as string | undefined;\n if (viewUUID && viewUUID !== this._viewUUID) {\n this._viewUUID = viewUUID;\n this.restoreFromLocalStorage(viewUUID);\n }\n });\n }\n\n private restoreFromLocalStorage(viewUUID: string): void {\n try {\n const existingKey = findStorageKey(viewUUID);\n if (existingKey) {\n const stored = localStorage.getItem(existingKey);\n if (stored !== null) {\n this._viewState = JSON.parse(stored);\n this.viewStateListeners.forEach((l) => {\n l();\n });\n }\n }\n } catch (err) {\n console.error(err);\n }\n }\n\n protected persistToLocalStorage(state: Record<string, unknown> | null): void {\n if (!this._viewUUID || state === null) {\n return;\n }\n try {\n const oldKey = findStorageKey(this._viewUUID);\n if (oldKey) {\n localStorage.removeItem(oldKey);\n }\n const newKey = `${STORAGE_PREFIX}${Date.now()}:${this._viewUUID}`;\n localStorage.setItem(newKey, JSON.stringify(state));\n const keys: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key?.startsWith(STORAGE_PREFIX)) {\n keys.push(key);\n }\n }\n if (keys.length <= MAX_STORAGE_ENTRIES) {\n return;\n }\n keys.sort();\n const toRemove = keys.slice(0, keys.length - MAX_STORAGE_ENTRIES);\n for (const key of toRemove) {\n localStorage.removeItem(key);\n }\n } catch (err) {\n console.error(err);\n }\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|