@skybridge/vite-plugin 0.0.0-dev.09043e8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Alpic
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,22 @@
1
+ # @skybridge/vite-plugin
2
+
3
+ The Vite plugin behind [Skybridge](https://skybridge.tech): it discovers view
4
+ modules, serves them as virtual entries, applies the `data-llm` transform, and
5
+ tells `skybridge build` which packages to leave unbundled.
6
+
7
+ Its `evals` option wires up [`@skybridge/test`](https://www.npmjs.com/package/@skybridge/test),
8
+ which boots the server and extends vitest's assertions with chat-oriented
9
+ matchers for checking that a prompt reaches the right tool.
10
+
11
+ Projects created with `npm create skybridge` already have it wired up.
12
+
13
+ ```ts
14
+ import { defineConfig } from "vite";
15
+ import { skybridge } from "@skybridge/vite-plugin";
16
+
17
+ export default defineConfig({
18
+ plugins: [skybridge()],
19
+ });
20
+ ```
21
+
22
+ See the [documentation](https://docs.skybridge.tech) for the options it accepts.
@@ -0,0 +1,4 @@
1
+ import type { TestProject } from "vitest/node";
2
+ import "./types.js";
3
+ export default function setup(project: TestProject): Promise<(() => Promise<void>) | undefined>;
4
+ //# sourceMappingURL=global-setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global-setup.d.ts","sourceRoot":"","sources":["../../src/evals/global-setup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,YAAY,CAAC;AAEpB,wBAA8B,KAAK,CAAC,OAAO,EAAE,WAAW,8CAwBvD"}
@@ -0,0 +1,25 @@
1
+ import { startServer } from "./server-harness.js";
2
+ import "./types.js";
3
+ export default async function setup(project) {
4
+ const options = project.config.provide?.skybridgeEvals;
5
+ if (options === undefined) {
6
+ return;
7
+ }
8
+ if (options.server !== undefined) {
9
+ project.provide("skybridgeEvalsUrl", options.server);
10
+ return;
11
+ }
12
+ if (options.project === undefined) {
13
+ throw new Error("The evals plugin needs either `server` or `project`");
14
+ }
15
+ const server = await startServer(options.project);
16
+ project.provide("skybridgeEvalsUrl", server.url);
17
+ return async () => {
18
+ const output = server.output().trim();
19
+ await server.stop();
20
+ if (output !== "") {
21
+ console.log(`\n--- server output ---\n${output}\n---`);
22
+ }
23
+ };
24
+ }
25
+ //# sourceMappingURL=global-setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global-setup.js","sourceRoot":"","sources":["../../src/evals/global-setup.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,YAAY,CAAC;AAEpB,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,KAAK,CAAC,OAAoB;IACtD,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,cAAc,CAAC;IACvD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO;IACT,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACjC,OAAO,CAAC,OAAO,CAAC,mBAAmB,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QACrD,OAAO;IACT,CAAC;IACD,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAClD,OAAO,CAAC,OAAO,CAAC,mBAAmB,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAEjD,OAAO,KAAK,IAAI,EAAE;QAChB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;QACtC,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,4BAA4B,MAAM,OAAO,CAAC,CAAC;QACzD,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ export type { ChatAssertion, ChatMatchers } from "./matchers.js";
2
+ export type { ChatLike, ToolCall, ToolDefinition } from "./types.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/evals/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACjE,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/evals/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ import type { ToolInput, ToolNames } from "skybridge/server";
2
+ import type { ChatLike } from "./types.js";
3
+ /**
4
+ * Assertions about the tool calls a conversation produced. Kept off vitest's
5
+ * global `Matchers` so they never appear on unrelated `expect()` calls, and so
6
+ * this stays the one place later tool-call helpers are added.
7
+ */
8
+ export interface ChatMatchers<App> {
9
+ toHaveCalledToolOnce<Name extends ToolNames<App>>(name: Name, args?: Partial<ToolInput<App, Name>>): void;
10
+ toHaveCalledToolWith<Name extends ToolNames<App>>(name: Name, args: Partial<ToolInput<App, Name>>): void;
11
+ toNeverHaveCalledTool<Name extends ToolNames<App>>(name: Name): void;
12
+ toHaveFailedToolCall<Name extends ToolNames<App>>(name: Name): void;
13
+ }
14
+ export interface ChatAssertion<App> extends ChatMatchers<App> {
15
+ not: ChatMatchers<App>;
16
+ }
17
+ declare module "vitest" {
18
+ interface ExpectStatic {
19
+ chat<App>(chat: ChatLike<App>): ChatAssertion<App>;
20
+ }
21
+ }
22
+ //# sourceMappingURL=matchers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../../src/evals/matchers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7D,OAAO,KAAK,EAAE,QAAQ,EAAY,MAAM,YAAY,CAAC;AAErD;;;;GAIG;AACH,MAAM,WAAW,YAAY,CAAC,GAAG;IAC/B,oBAAoB,CAAC,IAAI,SAAS,SAAS,CAAC,GAAG,CAAC,EAC9C,IAAI,EAAE,IAAI,EACV,IAAI,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,GACnC,IAAI,CAAC;IACR,oBAAoB,CAAC,IAAI,SAAS,SAAS,CAAC,GAAG,CAAC,EAC9C,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,GAClC,IAAI,CAAC;IACR,qBAAqB,CAAC,IAAI,SAAS,SAAS,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IACrE,oBAAoB,CAAC,IAAI,SAAS,SAAS,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;CACrE;AAED,MAAM,WAAW,aAAa,CAAC,GAAG,CAAE,SAAQ,YAAY,CAAC,GAAG,CAAC;IAC3D,GAAG,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC;CACxB;AAED,OAAO,QAAQ,QAAQ,CAAC;IACtB,UAAU,YAAY;QACpB,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;KACpD;CACF"}
@@ -0,0 +1,78 @@
1
+ import { expect } from "vitest";
2
+ function attemptedCalls(chat, name) {
3
+ return chat.toolCalls.filter((call) => String(call.name) === name);
4
+ }
5
+ function acceptedCalls(chat, name) {
6
+ return attemptedCalls(chat, name).filter((call) => call.failed === undefined);
7
+ }
8
+ function observed(chat) {
9
+ if (chat.toolCalls.length === 0) {
10
+ return " (no tool was called)";
11
+ }
12
+ return chat.toolCalls
13
+ .map((call, index) => ` ${index + 1}. ${call.name} ${JSON.stringify(call.arguments)}${call.failed === undefined ? "" : ` (failed: ${call.failed})`}`)
14
+ .join("\n");
15
+ }
16
+ function definitions(chat) {
17
+ return chat.toolDefinitions
18
+ .map((tool) => ` - ${tool.name}: ${tool.description ?? ""}\n arguments: ${JSON.stringify(tool.inputSchema)}`)
19
+ .join("\n");
20
+ }
21
+ function report(chat, summary) {
22
+ return `${summary}
23
+
24
+ Calls the model actually made:
25
+ ${observed(chat)}
26
+
27
+ Tool definitions the model was looking at:
28
+ ${definitions(chat)}`;
29
+ }
30
+ expect.extend({
31
+ toHaveCalledToolOnce(received, name, args) {
32
+ const matching = acceptedCalls(received, name);
33
+ const argsMatch = args === undefined ||
34
+ (matching.length === 1 &&
35
+ this.equals(matching[0]?.arguments, expect.objectContaining(args)));
36
+ const pass = matching.length === 1 && argsMatch;
37
+ return {
38
+ pass,
39
+ message: () => report(received, pass
40
+ ? `Expected "${name}" not to be called exactly once.`
41
+ : matching.length === 1
42
+ ? `Expected "${name}" to be called once with ${JSON.stringify(args)}, but it was called with ${JSON.stringify(matching[0]?.arguments)}.`
43
+ : `Expected "${name}" to be called exactly once by a call that succeeded, but ${matching.length} such calls were made.`),
44
+ };
45
+ },
46
+ toHaveCalledToolWith(received, name, args) {
47
+ const pass = acceptedCalls(received, name).some((call) => this.equals(call.arguments, expect.objectContaining(args)));
48
+ return {
49
+ pass,
50
+ message: () => report(received, pass
51
+ ? `Expected no call to "${name}" with ${JSON.stringify(args)}.`
52
+ : `Expected "${name}" to be called with ${JSON.stringify(args)}.`),
53
+ };
54
+ },
55
+ toHaveFailedToolCall(received, name) {
56
+ const attempted = attemptedCalls(received, name);
57
+ const failed = attempted.filter((call) => call.failed !== undefined);
58
+ return {
59
+ pass: failed.length > 0,
60
+ message: () => report(received, failed.length > 0
61
+ ? `Expected every call to "${name}" to succeed.`
62
+ : attempted.length === 0
63
+ ? `Expected "${name}" to be called and fail, but it was never called.`
64
+ : `Expected "${name}" to fail, but all ${attempted.length} calls succeeded.`),
65
+ };
66
+ },
67
+ toNeverHaveCalledTool(received, name) {
68
+ const matching = attemptedCalls(received, name);
69
+ return {
70
+ pass: matching.length === 0,
71
+ message: () => report(received, matching.length === 0
72
+ ? `Expected "${name}" to be called at least once.`
73
+ : `Expected "${name}" never to be called, but it was called ${matching.length} times.`),
74
+ };
75
+ },
76
+ });
77
+ expect.chat = (chat) => expect(chat);
78
+ //# sourceMappingURL=matchers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matchers.js","sourceRoot":"","sources":["../../src/evals/matchers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export interface RunningServer {
2
+ url: string;
3
+ /** Everything the server wrote to stdout/stderr, for failure reports. */
4
+ output: () => string;
5
+ stop: () => Promise<void>;
6
+ }
7
+ /**
8
+ * Spawns the project's server with `__PORT=0` and an IPC channel, and waits
9
+ * for the `skybridge:listening` message carrying the port the OS picked.
10
+ * Binding and reporting both happen in the child, so there is no window in
11
+ * which another process can steal the port.
12
+ */
13
+ export declare function startServer({ cwd, command, env, }: {
14
+ cwd: string;
15
+ command: string[];
16
+ env?: Record<string, string>;
17
+ }): Promise<RunningServer>;
18
+ //# sourceMappingURL=server-harness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-harness.d.ts","sourceRoot":"","sources":["../../src/evals/server-harness.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,yEAAyE;IACzE,MAAM,EAAE,MAAM,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAiBD;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,EAChC,GAAG,EACH,OAAO,EACP,GAAQ,GACT,EAAE;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B,GAAG,OAAO,CAAC,aAAa,CAAC,CA4EzB"}
@@ -0,0 +1,79 @@
1
+ import { spawn } from "node:child_process";
2
+ import { resolve } from "node:path";
3
+ function hasExited(child) {
4
+ return child.exitCode !== null || child.signalCode !== null;
5
+ }
6
+ function isListeningMessage(message) {
7
+ return (typeof message === "object" &&
8
+ message !== null &&
9
+ message.type === "skybridge:listening" &&
10
+ typeof message.port === "number");
11
+ }
12
+ /**
13
+ * Spawns the project's server with `__PORT=0` and an IPC channel, and waits
14
+ * for the `skybridge:listening` message carrying the port the OS picked.
15
+ * Binding and reporting both happen in the child, so there is no window in
16
+ * which another process can steal the port.
17
+ */
18
+ export async function startServer({ cwd, command, env = {}, }) {
19
+ const timeoutMs = 60_000;
20
+ const [bin, ...args] = command;
21
+ if (bin === undefined) {
22
+ throw new Error("Empty server command");
23
+ }
24
+ const executable = bin.startsWith(".") ? resolve(cwd, bin) : bin;
25
+ const child = spawn(executable, args, {
26
+ cwd,
27
+ env: {
28
+ ...process.env,
29
+ NODE_ENV: "production",
30
+ ...env,
31
+ __PORT: "0",
32
+ },
33
+ stdio: ["ignore", "pipe", "pipe", "ipc"],
34
+ });
35
+ let captured = "";
36
+ const output = () => captured;
37
+ child.stdout?.on("data", (chunk) => {
38
+ captured += chunk;
39
+ });
40
+ child.stderr?.on("data", (chunk) => {
41
+ captured += chunk;
42
+ });
43
+ const stop = async () => {
44
+ if (hasExited(child)) {
45
+ return;
46
+ }
47
+ const exited = new Promise((resolveExit) => {
48
+ child.once("exit", () => resolveExit());
49
+ });
50
+ child.kill("SIGTERM");
51
+ const forced = setTimeout(() => child.kill("SIGKILL"), 3_000);
52
+ await exited;
53
+ clearTimeout(forced);
54
+ };
55
+ const port = await new Promise((resolvePort, reject) => {
56
+ const timer = setTimeout(() => {
57
+ reject(new Error(`Server did not report a port in ${timeoutMs}ms. \`command\` must start the server process directly (node, tsx): wrappers such as \`pnpm run\` do not forward the IPC channel the readiness signal uses. It must also run a skybridge version that sends skybridge:listening.\n${output()}`));
58
+ }, timeoutMs);
59
+ child.on("message", (message) => {
60
+ if (isListeningMessage(message)) {
61
+ clearTimeout(timer);
62
+ resolvePort(message.port);
63
+ }
64
+ });
65
+ child.on("error", (error) => {
66
+ clearTimeout(timer);
67
+ reject(new Error(`Failed to spawn ${command.join(" ")}: ${error.message}`));
68
+ });
69
+ child.on("exit", () => {
70
+ clearTimeout(timer);
71
+ reject(new Error(`Server exited with code ${child.exitCode} before reporting its port:\n${output()}`));
72
+ });
73
+ }).catch(async (error) => {
74
+ await stop();
75
+ throw error;
76
+ });
77
+ return { url: `http://127.0.0.1:${port}/mcp`, output, stop };
78
+ }
79
+ //# sourceMappingURL=server-harness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-harness.js","sourceRoot":"","sources":["../../src/evals/server-harness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { ToolInput, ToolNames } from "skybridge/server";
2
+ import type { EvalsOptions } from "../plugin.js";
3
+ /**
4
+ * One recorded call, typed against the project's own registry: `name` is a
5
+ * union of the project's tool names and `arguments` is discriminated on it.
6
+ * `failed` carries the server's reason when the call did not go through.
7
+ */
8
+ export type ToolCall<App> = {
9
+ [Name in ToolNames<App>]: {
10
+ name: Name;
11
+ arguments: ToolInput<App, Name>;
12
+ failed?: string;
13
+ };
14
+ }[ToolNames<App>];
15
+ export interface ToolDefinition {
16
+ name: string;
17
+ description?: string;
18
+ inputSchema: Record<string, unknown>;
19
+ }
20
+ /** The part of a conversation the matchers assert on. */
21
+ export interface ChatLike<App> {
22
+ readonly toolCalls: ToolCall<App>[];
23
+ readonly toolDefinitions: ToolDefinition[];
24
+ }
25
+ declare module "vitest" {
26
+ interface ProvidedContext {
27
+ skybridgeEvals: EvalsOptions | undefined;
28
+ skybridgeEvalsUrl: string | undefined;
29
+ }
30
+ }
31
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/evals/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD;;;;GAIG;AACH,MAAM,MAAM,QAAQ,CAAC,GAAG,IAAI;KACzB,IAAI,IAAI,SAAS,CAAC,GAAG,CAAC,GAAG;QACxB,IAAI,EAAE,IAAI,CAAC;QACX,SAAS,EAAE,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB;CACF,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;AAElB,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,yDAAyD;AACzD,MAAM,WAAW,QAAQ,CAAC,GAAG;IAC3B,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;IACpC,QAAQ,CAAC,eAAe,EAAE,cAAc,EAAE,CAAC;CAC5C;AAED,OAAO,QAAQ,QAAQ,CAAC;IACtB,UAAU,eAAe;QACvB,cAAc,EAAE,YAAY,GAAG,SAAS,CAAC;QACzC,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;KACvC;CACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/evals/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export { type EvalsOptions, type SkybridgePluginOptions, skybridge, } from "./plugin.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,sBAAsB,EAC3B,SAAS,GACV,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { skybridge, } from "./plugin.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,SAAS,GACV,MAAM,aAAa,CAAC"}
@@ -0,0 +1,63 @@
1
+ import type { Plugin } from "vite";
2
+ /**
3
+ * Options for the eval runner, wired in through the `evals` plugin option and
4
+ * consumed by `@skybridge/test`. Defined here so the runtime package can
5
+ * import the shape while this package keeps no dependency on it.
6
+ */
7
+ export interface EvalsOptions {
8
+ model?: string;
9
+ temperature?: number;
10
+ systemPrompt?: string;
11
+ maxSteps?: number;
12
+ server?: string;
13
+ project?: {
14
+ cwd: string;
15
+ command: string[];
16
+ env?: Record<string, string>;
17
+ };
18
+ }
19
+ /** Options for the {@link skybridge} Vite plugin. */
20
+ export interface SkybridgePluginOptions {
21
+ /** Directory scanned for view modules. Defaults to `"src/views"`. */
22
+ viewsDir?: string;
23
+ /**
24
+ * Package names to leave unbundled when `skybridge build` bundles the server
25
+ * for deployment. Use it for dependencies esbuild can't resolve or load —
26
+ * typically optional native modules pulled in by a transitive dependency.
27
+ */
28
+ serverExternal?: string[];
29
+ /**
30
+ * Runs the app's eval scenarios against a real model: which model to use,
31
+ * and how to boot the server they talk to. Point vitest at this config to
32
+ * run them. Requires `@skybridge/test` as a dev dependency.
33
+ */
34
+ evals?: EvalsOptions;
35
+ }
36
+ /**
37
+ * Vite plugin that wires a Skybridge project's view files into Vite.
38
+ *
39
+ * For each `.tsx` / `.jsx` file in `viewsDir` with a default export, the
40
+ * plugin:
41
+ * - exposes a virtual entry that calls {@link mountView} with the view's
42
+ * default export,
43
+ * - generates `.skybridge/views.d.ts` to augment {@link ViewNameRegistry} so
44
+ * {@link ViewName} narrows to the actual view names,
45
+ * - rewrites `<DataLLM>` JSX so the host can extract its content,
46
+ * - warns in dev if a view file is missing a default export.
47
+ *
48
+ * Add it to your `vite.config.ts` alongside `@vitejs/plugin-react`.
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * // vite.config.ts
53
+ * import { defineConfig } from "vite";
54
+ * import react from "@vitejs/plugin-react";
55
+ * import { skybridge } from "@skybridge/vite-plugin";
56
+ *
57
+ * export default defineConfig({
58
+ * plugins: [react(), skybridge({ viewsDir: "src/views" })],
59
+ * });
60
+ * ```
61
+ */
62
+ export declare function skybridge(options?: SkybridgePluginOptions): Plugin;
63
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,MAAM,CAAC;AAOlD;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE;QACR,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAC9B,CAAC;CACH;AAED,qDAAqD;AACrD,MAAM,WAAW,sBAAsB;IACrC,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B;;;;OAIG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAmBD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,SAAS,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM,CAElE"}
package/dist/plugin.js ADDED
@@ -0,0 +1,214 @@
1
+ import { isAbsolute, relative, resolve } from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { assertUniqueViewNames, discoverViewsSync, hasDefaultExport, scanViewsSync, writeViewsDts, } from "skybridge/views";
4
+ import { transform as dataLlmTransform } from "./transform-data-llm.js";
5
+ const VIRTUAL_PREFIX = "/_skybridge/view/";
6
+ const VIRTUAL_MODULE_PREFIX = "\0skybridge:view:";
7
+ function buildVirtualEntry(viewFilePath) {
8
+ const normalized = viewFilePath.replace(/\\/g, "/");
9
+ return [
10
+ `import { mountView } from "skybridge/web";`,
11
+ `import Component from "${normalized}";`,
12
+ `import { createElement } from "react";`,
13
+ `mountView(createElement(Component));`,
14
+ ].join("\n");
15
+ }
16
+ function getViewEntryPattern(viewsDir) {
17
+ const escaped = viewsDir.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
18
+ return new RegExp(`${escaped}\\/(?:[^/]+\\.(?:jsx|tsx)|[^/]+\\/index\\.(?:tsx|jsx))(?:\\?.*)?$`);
19
+ }
20
+ /**
21
+ * Vite plugin that wires a Skybridge project's view files into Vite.
22
+ *
23
+ * For each `.tsx` / `.jsx` file in `viewsDir` with a default export, the
24
+ * plugin:
25
+ * - exposes a virtual entry that calls {@link mountView} with the view's
26
+ * default export,
27
+ * - generates `.skybridge/views.d.ts` to augment {@link ViewNameRegistry} so
28
+ * {@link ViewName} narrows to the actual view names,
29
+ * - rewrites `<DataLLM>` JSX so the host can extract its content,
30
+ * - warns in dev if a view file is missing a default export.
31
+ *
32
+ * Add it to your `vite.config.ts` alongside `@vitejs/plugin-react`.
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * // vite.config.ts
37
+ * import { defineConfig } from "vite";
38
+ * import react from "@vitejs/plugin-react";
39
+ * import { skybridge } from "@skybridge/vite-plugin";
40
+ *
41
+ * export default defineConfig({
42
+ * plugins: [react(), skybridge({ viewsDir: "src/views" })],
43
+ * });
44
+ * ```
45
+ */
46
+ export function skybridge(options) {
47
+ return viewsPlugin(options);
48
+ }
49
+ function here(file) {
50
+ return fileURLToPath(new URL(file, import.meta.url));
51
+ }
52
+ function viewsPlugin(options) {
53
+ const rawViewsDir = options?.viewsDir ?? "src/views";
54
+ let resolvedViewsDir;
55
+ let projectRoot;
56
+ let viewMap = new Map();
57
+ let viewEntryPattern;
58
+ return {
59
+ name: "skybridge",
60
+ enforce: "pre",
61
+ // Read by `skybridge build` to resolve viewsDir before `tsc -b` runs, and
62
+ // to feed esbuild's external list when bundling the server.
63
+ api: { viewsDir: rawViewsDir, serverExternal: options?.serverExternal },
64
+ config(config) {
65
+ projectRoot = config.root || process.cwd();
66
+ resolvedViewsDir = isAbsolute(rawViewsDir)
67
+ ? rawViewsDir
68
+ : resolve(projectRoot, rawViewsDir);
69
+ viewEntryPattern = getViewEntryPattern(resolvedViewsDir);
70
+ const views = discoverViewsSync(resolvedViewsDir);
71
+ viewMap = new Map(views.map((v) => [v.name, v]));
72
+ writeViewsDts(projectRoot, views);
73
+ const input = {};
74
+ for (const view of views) {
75
+ input[view.name] = `${VIRTUAL_PREFIX}${view.name}`;
76
+ }
77
+ const base = {
78
+ base: "/assets",
79
+ // Fixes "Invalid hook call" on createStore by forcing a single
80
+ // copy of React. Under pnpm's isolated node_modules, zustand
81
+ // inside `skybridge` resolves React from skybridge's own
82
+ // dependencies while the host app loads its own copy
83
+ resolve: {
84
+ dedupe: ["react", "react-dom"],
85
+ },
86
+ build: {
87
+ outDir: "dist/assets",
88
+ emptyOutDir: true,
89
+ manifest: true,
90
+ minify: true,
91
+ cssCodeSplit: false,
92
+ rollupOptions: {
93
+ input,
94
+ },
95
+ },
96
+ // Pre-bundle view deps at startup so the first tool invocation
97
+ // doesn't hit Vite's on-demand re-optimization path (which sends
98
+ // `full-reload` over HMR — in our iframe flow the parent host
99
+ // can't honour a reload, and the view silently never mounts).
100
+ optimizeDeps: {
101
+ // Scan view files so transitive user deps (zod, tailwind, etc.)
102
+ // get pre-bundled at startup.
103
+ entries: [
104
+ `${resolvedViewsDir}/*.{tsx,jsx}`,
105
+ `${resolvedViewsDir}/*/index.{tsx,jsx}`,
106
+ ],
107
+ include: ["react", "react-dom/client", "react/jsx-runtime"],
108
+ },
109
+ experimental: {
110
+ renderBuiltUrl: (filename, { hostType }) => {
111
+ // Views render inside a host sandbox iframe, so `import.meta.url`
112
+ // points at the sandbox domain rather than the Skybridge server.
113
+ // JS asset references have to be resolved at runtime against
114
+ // `window.skybridge.serverUrl` so they follow tunnels too.
115
+ if (hostType === "js") {
116
+ return {
117
+ runtime: `window.skybridge.serverUrl + "/assets/${filename}"`,
118
+ };
119
+ }
120
+ // CSS has nowhere to evaluate a runtime expression — `vite:css-post`
121
+ // throws on one. It doesn't need it either: the stylesheet is served
122
+ // from `${serverUrl}/assets/…` and a relative `url()` resolves
123
+ // against the stylesheet's own URL, tunnel origin included.
124
+ return { relative: true };
125
+ },
126
+ },
127
+ };
128
+ return {
129
+ ...base,
130
+ test: {
131
+ setupFiles: [here("./evals/matchers.js")],
132
+ globalSetup: [here("./evals/global-setup.js")],
133
+ provide: { skybridgeEvals: options?.evals },
134
+ },
135
+ };
136
+ },
137
+ resolveId(id) {
138
+ if (id.startsWith(VIRTUAL_PREFIX)) {
139
+ const name = id.slice(VIRTUAL_PREFIX.length);
140
+ if (viewMap.has(name)) {
141
+ return `${VIRTUAL_MODULE_PREFIX}${name}`;
142
+ }
143
+ }
144
+ return null;
145
+ },
146
+ load(id) {
147
+ if (id.startsWith(VIRTUAL_MODULE_PREFIX)) {
148
+ const name = id.slice(VIRTUAL_MODULE_PREFIX.length);
149
+ const view = viewMap.get(name);
150
+ if (view) {
151
+ return buildVirtualEntry(view.filePath);
152
+ }
153
+ }
154
+ return null;
155
+ },
156
+ configureServer(server) {
157
+ if (!resolvedViewsDir) {
158
+ const root = server.config.root || process.cwd();
159
+ resolvedViewsDir = isAbsolute(rawViewsDir)
160
+ ? rawViewsDir
161
+ : resolve(root, rawViewsDir);
162
+ projectRoot = root;
163
+ viewEntryPattern = getViewEntryPattern(resolvedViewsDir);
164
+ }
165
+ server.watcher.add(resolvedViewsDir);
166
+ // Track which view files we've already warned about so a rescan
167
+ // triggered by an unrelated edit doesn't re-emit the same warning.
168
+ let knownInvalid = new Set();
169
+ const rescan = () => {
170
+ try {
171
+ // Surface broken view files. Without this, files lacking a
172
+ // default export are silently dropped from the input and the
173
+ // user has no idea why their widget never mounts.
174
+ const { valid, invalid } = scanViewsSync(resolvedViewsDir);
175
+ const nextInvalid = new Set(invalid.map((v) => v.filePath));
176
+ for (const filePath of nextInvalid) {
177
+ if (!knownInvalid.has(filePath)) {
178
+ server.config.logger.warn(`[skybridge] view file "${relative(projectRoot, filePath)}" is missing a default export — it won't be served until fixed.`);
179
+ }
180
+ }
181
+ for (const filePath of knownInvalid) {
182
+ if (!nextInvalid.has(filePath)) {
183
+ server.config.logger.info(`[skybridge] view file "${relative(projectRoot, filePath)}" resolved.`);
184
+ }
185
+ }
186
+ knownInvalid = nextInvalid;
187
+ assertUniqueViewNames(valid);
188
+ viewMap = new Map(valid.map((v) => [v.name, v]));
189
+ writeViewsDts(projectRoot, valid);
190
+ }
191
+ catch (err) {
192
+ // assertUniqueViewNames throws on duplicate view names. Catch so
193
+ // chokidar's listener chain doesn't surface it as unhandled and
194
+ // crash the dev server — previous viewMap stays active until
195
+ // the user fixes the conflict.
196
+ const message = err instanceof Error ? err.message : String(err);
197
+ server.config.logger.error(`[skybridge] view rescan failed: ${message}`);
198
+ }
199
+ };
200
+ // Initial scan emits warnings for broken files that exist at startup.
201
+ rescan();
202
+ server.watcher.on("add", rescan);
203
+ server.watcher.on("change", rescan);
204
+ server.watcher.on("unlink", rescan);
205
+ },
206
+ async transform(code, id) {
207
+ if (viewEntryPattern?.test(id) && !hasDefaultExport(code)) {
208
+ this.warn(`View file "${id.split("/").pop()}" is missing a default export.`);
209
+ }
210
+ return await dataLlmTransform(code, id);
211
+ },
212
+ };
213
+ }
214
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export declare const transform: (code: string, id: string) => Promise<{
2
+ code: string;
3
+ map: {
4
+ version: number;
5
+ sources: string[];
6
+ names: string[];
7
+ sourceRoot?: string | undefined;
8
+ sourcesContent?: string[] | undefined;
9
+ mappings: string;
10
+ file: string;
11
+ } | null;
12
+ } | null>;
13
+ //# sourceMappingURL=transform-data-llm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform-data-llm.d.ts","sourceRoot":"","sources":["../src/transform-data-llm.ts"],"names":[],"mappings":"AA+HA,eAAO,MAAM,SAAS,GAAU,MAAM,MAAM,EAAE,IAAI,MAAM;;;;;;;;;;;SA+BvD,CAAC"}
@@ -0,0 +1,96 @@
1
+ const LLM_IMPORT_SOURCE = "skybridge/web";
2
+ function createBabelPlugin(t) {
3
+ return {
4
+ name: "data-llm-babel",
5
+ visitor: {
6
+ Program: {
7
+ enter(path, state) {
8
+ state.hasDataLLMImport = false;
9
+ state.needsDataLLMImport = false;
10
+ for (const node of path.node.body) {
11
+ if (!t.isImportDeclaration(node)) {
12
+ continue;
13
+ }
14
+ if (node.source.value !== LLM_IMPORT_SOURCE) {
15
+ continue;
16
+ }
17
+ const hasSpecifier = node.specifiers.some((s) => t.isImportSpecifier(s) &&
18
+ t.isIdentifier(s.imported, { name: "DataLLM" }));
19
+ if (hasSpecifier) {
20
+ state.hasDataLLMImport = true;
21
+ break;
22
+ }
23
+ }
24
+ },
25
+ exit(path, state) {
26
+ if (state.needsDataLLMImport && !state.hasDataLLMImport) {
27
+ const importDecl = t.importDeclaration([
28
+ t.importSpecifier(t.identifier("DataLLM"), t.identifier("DataLLM")),
29
+ ], t.stringLiteral(LLM_IMPORT_SOURCE));
30
+ path.node.body.unshift(importDecl);
31
+ }
32
+ },
33
+ },
34
+ JSXElement(path, state) {
35
+ const opening = path.node.openingElement;
36
+ const attributes = opening.attributes;
37
+ const llmAttributeIndex = attributes.findIndex((attribute) => t.isJSXAttribute(attribute) &&
38
+ t.isJSXIdentifier(attribute.name, { name: "data-llm" }));
39
+ if (llmAttributeIndex === -1) {
40
+ return;
41
+ }
42
+ const llmAttribute = attributes[llmAttributeIndex];
43
+ let contentExpression;
44
+ if (t.isStringLiteral(llmAttribute.value)) {
45
+ contentExpression = llmAttribute.value;
46
+ }
47
+ else if (t.isJSXExpressionContainer(llmAttribute.value)) {
48
+ contentExpression = llmAttribute.value.expression;
49
+ }
50
+ else {
51
+ return;
52
+ }
53
+ const contentAttr = t.jsxAttribute(t.jsxIdentifier("content"), t.isStringLiteral(contentExpression)
54
+ ? contentExpression
55
+ : t.jsxExpressionContainer(contentExpression));
56
+ const filteredAttributes = attributes.filter((_, index) => index !== llmAttributeIndex);
57
+ const newOpening = t.jsxOpeningElement(opening.name, filteredAttributes, opening.selfClosing);
58
+ const elementWithoutLlm = t.jsxElement(newOpening, path.node.closingElement, path.node.children, path.node.selfClosing);
59
+ const llmOpening = t.jsxOpeningElement(t.jsxIdentifier("DataLLM"), [
60
+ contentAttr,
61
+ ]);
62
+ const llmClosing = t.jsxClosingElement(t.jsxIdentifier("DataLLM"));
63
+ const wrapped = t.jsxElement(llmOpening, llmClosing, [elementWithoutLlm], false);
64
+ state.needsDataLLMImport = true;
65
+ path.replaceWith(wrapped);
66
+ },
67
+ },
68
+ };
69
+ }
70
+ export const transform = async (code, id) => {
71
+ if (!/\.(jsx|tsx)$/.test(id)) {
72
+ return null;
73
+ }
74
+ if (id.includes("node_modules")) {
75
+ return null;
76
+ }
77
+ // Dynamic import to ensure @babel/core is only loaded in Node.js context
78
+ const { types: t, transformSync } = await import("@babel/core");
79
+ const babelOptions = {
80
+ plugins: [createBabelPlugin(t)],
81
+ parserOpts: {
82
+ plugins: ["jsx", "typescript"],
83
+ },
84
+ filename: id,
85
+ sourceFileName: id,
86
+ };
87
+ const result = transformSync(code, babelOptions);
88
+ if (!result?.code) {
89
+ return null;
90
+ }
91
+ return {
92
+ code: result.code,
93
+ map: result.map || null,
94
+ };
95
+ };
96
+ //# sourceMappingURL=transform-data-llm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform-data-llm.js","sourceRoot":"","sources":["../src/transform-data-llm.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@skybridge/vite-plugin",
3
+ "version": "0.0.0-dev.09043e8",
4
+ "description": "The Skybridge Vite plugin: view discovery, data-llm transforms, and eval wiring",
5
+ "license": "ISC",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/alpic-ai/skybridge.git"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./evals": {
17
+ "types": "./dist/evals/index.d.ts",
18
+ "default": "./dist/evals/index.js"
19
+ }
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "dependencies": {
25
+ "@babel/core": "^7.29.7"
26
+ },
27
+ "peerDependencies": {
28
+ "skybridge": "^2.0.0",
29
+ "vite": ">=7.3.1",
30
+ "vitest": ">=4.1.0"
31
+ },
32
+ "devDependencies": {
33
+ "@types/babel__core": "^7.20.5",
34
+ "@types/node": "^24.13.3",
35
+ "typescript": "^5.9.3",
36
+ "vite": "^8.1.5",
37
+ "vitest": "^4.1.10",
38
+ "skybridge": "0.0.0-dev.09043e8"
39
+ },
40
+ "engines": {
41
+ "node": ">=22.23.1"
42
+ },
43
+ "peerDependenciesMeta": {
44
+ "vitest": {
45
+ "optional": true
46
+ }
47
+ },
48
+ "scripts": {
49
+ "build": "tsc -p tsconfig.json",
50
+ "format": "biome check --write --error-on-warnings",
51
+ "test": "pnpm run test:format && pnpm run test:types && pnpm run test:unit",
52
+ "test:format": "biome ci",
53
+ "test:types": "tsc --noEmit -p tsconfig.test.json",
54
+ "test:unit": "vitest run"
55
+ }
56
+ }