sunpeak 0.20.2 → 0.20.6
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/README.md +59 -89
- package/bin/commands/dev.mjs +23 -4
- package/bin/commands/inspect.mjs +111 -4
- package/bin/commands/new.mjs +33 -9
- package/bin/commands/test-init.mjs +25 -23
- package/bin/commands/test.mjs +4 -3
- package/bin/lib/eval/eval-runner.mjs +27 -1
- package/bin/lib/eval/model-registry.mjs +6 -1
- package/bin/lib/test/base-config.mjs +11 -4
- package/bin/sunpeak.js +16 -15
- package/dist/chatgpt/index.cjs +1 -1
- package/dist/chatgpt/index.js +1 -1
- package/dist/claude/index.cjs +1 -1
- package/dist/claude/index.js +1 -1
- package/dist/host/chatgpt/index.cjs +1 -1
- package/dist/host/chatgpt/index.js +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/inspector/index.cjs +1 -1
- package/dist/inspector/index.js +1 -1
- package/dist/{inspector-BBDa5yCm.js → inspector-60Na_Zc4.js} +2 -2
- package/dist/inspector-60Na_Zc4.js.map +1 -0
- package/dist/{inspector-DAA1Wiyh.cjs → inspector-D0qOqYX2.cjs} +2 -2
- package/dist/{inspector-BBDa5yCm.js.map → inspector-D0qOqYX2.cjs.map} +1 -1
- package/dist/mcp/index.cjs +24 -3
- package/dist/mcp/index.cjs.map +1 -1
- package/dist/mcp/index.js +24 -3
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/types.d.ts +1 -0
- package/dist/{use-app-DPkj5Jp_.cjs → use-app-B33mckz4.cjs} +7 -3
- package/dist/use-app-B33mckz4.cjs.map +1 -0
- package/dist/{use-app-Cr0auUa1.js → use-app-kv5GQr0G.js} +7 -3
- package/dist/use-app-kv5GQr0G.js.map +1 -0
- package/package.json +3 -3
- package/template/README.md +21 -23
- package/template/dist/albums/albums.html +1 -1
- package/template/dist/albums/albums.json +1 -1
- package/template/dist/carousel/carousel.html +1 -1
- package/template/dist/carousel/carousel.json +1 -1
- package/template/dist/map/map.html +1 -1
- package/template/dist/map/map.json +1 -1
- package/template/dist/review/review.html +1 -1
- package/template/dist/review/review.json +1 -1
- package/template/node_modules/.vite/deps/_metadata.json +3 -3
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js +6 -2
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js +6 -2
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/_metadata.json +22 -22
- package/template/package.json +2 -1
- package/template/tests/e2e/visual.spec.ts +2 -2
- package/template/tests/evals/albums.eval.ts +1 -1
- package/template/tests/evals/map.eval.ts +1 -1
- package/template/tests/evals/review.eval.ts +4 -2
- package/dist/inspector-DAA1Wiyh.cjs.map +0 -1
- package/dist/use-app-Cr0auUa1.js.map +0 -1
- package/dist/use-app-DPkj5Jp_.cjs.map +0 -1
|
@@ -112,9 +112,35 @@ export async function discoverAndConvertTools(client) {
|
|
|
112
112
|
const tools = {};
|
|
113
113
|
|
|
114
114
|
for (const t of mcpTools) {
|
|
115
|
+
// Clean up the MCP inputSchema for AI provider compatibility.
|
|
116
|
+
// OpenAI rejects $schema, additionalProperties: {} (empty schema has no type),
|
|
117
|
+
// and other JSON Schema features that MCP servers may include.
|
|
118
|
+
const rawSchema = t.inputSchema || { type: 'object', properties: {} };
|
|
119
|
+
const cleanSchema = { ...rawSchema };
|
|
120
|
+
delete cleanSchema.$schema;
|
|
121
|
+
if (
|
|
122
|
+
cleanSchema.additionalProperties != null &&
|
|
123
|
+
typeof cleanSchema.additionalProperties === 'object' &&
|
|
124
|
+
Object.keys(cleanSchema.additionalProperties).length === 0
|
|
125
|
+
) {
|
|
126
|
+
// Empty additionalProperties ({}) causes OpenAI to report type: "None".
|
|
127
|
+
// Remove it so the schema is a plain { type: "object", properties: {...} }.
|
|
128
|
+
delete cleanSchema.additionalProperties;
|
|
129
|
+
}
|
|
130
|
+
if (!cleanSchema.type) cleanSchema.type = 'object';
|
|
131
|
+
if (!cleanSchema.properties) cleanSchema.properties = {};
|
|
132
|
+
// Remove `required` so the model isn't forced to ask the user for every
|
|
133
|
+
// parameter before calling a tool. Eval prompts are intentionally vague
|
|
134
|
+
// ("show me photo albums") and the model should call the tool with
|
|
135
|
+
// reasonable defaults, not refuse because required fields are missing.
|
|
136
|
+
delete cleanSchema.required;
|
|
137
|
+
|
|
115
138
|
tools[t.name] = aiTool({
|
|
116
139
|
description: t.description || '',
|
|
117
|
-
|
|
140
|
+
// Set both so the tool works with ai v4/v5 (reads `parameters`)
|
|
141
|
+
// and ai v6 (reads `inputSchema`). tool() passes through both.
|
|
142
|
+
inputSchema: jsonSchema(cleanSchema),
|
|
143
|
+
parameters: jsonSchema(cleanSchema),
|
|
118
144
|
execute: async (args) => {
|
|
119
145
|
const result = await client.callTool({ name: t.name, arguments: args });
|
|
120
146
|
// Return a simplified version for the model to consume
|
|
@@ -44,7 +44,12 @@ export async function resolveModel(modelId) {
|
|
|
44
44
|
// that creates model instances: openai('gpt-4o'), anthropic('claude-...'), google('gemini-...')
|
|
45
45
|
if (pkg === '@ai-sdk/openai') {
|
|
46
46
|
const { openai } = provider;
|
|
47
|
-
|
|
47
|
+
// @ai-sdk/openai v3 defaults to the Responses API, which requires strict
|
|
48
|
+
// JSON Schema (additionalProperties: false at every level, all properties
|
|
49
|
+
// required) — incompatible with arbitrary MCP server schemas. Use .chat()
|
|
50
|
+
// (Chat Completions API) when available. v1/v2 default to Chat Completions
|
|
51
|
+
// already and may not have .chat(), so fall back to the default.
|
|
52
|
+
return typeof openai.chat === 'function' ? openai.chat(modelId) : openai(modelId);
|
|
48
53
|
}
|
|
49
54
|
if (pkg === '@ai-sdk/anthropic') {
|
|
50
55
|
const { anthropic } = provider;
|
|
@@ -5,8 +5,6 @@
|
|
|
5
5
|
* Produces a config with per-host Playwright projects, sensible defaults for
|
|
6
6
|
* MCP App testing, and a webServer entry to launch the inspector backend.
|
|
7
7
|
*/
|
|
8
|
-
import { getPortSync } from '../get-port.mjs';
|
|
9
|
-
|
|
10
8
|
/**
|
|
11
9
|
* @param {Object} options
|
|
12
10
|
* @param {string[]} options.hosts - Host shells to create projects for
|
|
@@ -63,10 +61,19 @@ export function createBaseConfig({ hosts, testDir, webServer, port, use, globalS
|
|
|
63
61
|
/**
|
|
64
62
|
* Resolve ports for the inspector and sandbox proxy.
|
|
65
63
|
* Respects env vars for CI where validate.mjs assigns unique ports.
|
|
64
|
+
*
|
|
65
|
+
* Uses FIXED default ports (no dynamic probing) so all Playwright workers
|
|
66
|
+
* resolve the same baseURL. Dynamic port probing (getPortSync) caused flaky
|
|
67
|
+
* tests: the main process would pick port X, start the webServer on it, then
|
|
68
|
+
* worker processes re-evaluating the config would find X occupied and resolve
|
|
69
|
+
* to random ports Y/Z — causing ERR_CONNECTION_REFUSED.
|
|
70
|
+
*
|
|
71
|
+
* If the default port is busy, Playwright's reuseExistingServer (local) reuses
|
|
72
|
+
* it, or strictPort (CI) fails fast with a clear error.
|
|
66
73
|
*/
|
|
67
74
|
export function resolvePorts() {
|
|
68
|
-
const port = parsePort(process.env.SUNPEAK_TEST_PORT) ??
|
|
69
|
-
const sandboxPort = parsePort(process.env.SUNPEAK_SANDBOX_PORT) ??
|
|
75
|
+
const port = parsePort(process.env.SUNPEAK_TEST_PORT) ?? 6776;
|
|
76
|
+
const sandboxPort = parsePort(process.env.SUNPEAK_SANDBOX_PORT) ?? 24680;
|
|
70
77
|
return { port, sandboxPort };
|
|
71
78
|
}
|
|
72
79
|
|
package/bin/sunpeak.js
CHANGED
|
@@ -102,22 +102,11 @@ function getVersion() {
|
|
|
102
102
|
{
|
|
103
103
|
const resources = discoverResources();
|
|
104
104
|
console.log(`
|
|
105
|
-
☀️ 🏔️ sunpeak -
|
|
105
|
+
☀️ 🏔️ sunpeak - App framework, testing framework, and inspector for MCP Apps
|
|
106
106
|
|
|
107
|
-
|
|
108
|
-
pnpm add -g sunpeak
|
|
107
|
+
Usage: npx sunpeak <command>
|
|
109
108
|
|
|
110
|
-
|
|
111
|
-
sunpeak inspect Inspect any MCP server in the inspector
|
|
112
|
-
--server, -s <url|cmd> MCP server URL or stdio command (required)
|
|
113
|
-
--simulations <dir> Simulation JSON directory
|
|
114
|
-
sunpeak test Run e2e tests against the inspector
|
|
115
|
-
init Scaffold test infrastructure into a project
|
|
116
|
-
--unit Run unit tests (vitest)
|
|
117
|
-
--live Run live tests against real hosts
|
|
118
|
-
--eval Run evals against LLM models
|
|
119
|
-
|
|
120
|
-
App framework (for sunpeak projects):
|
|
109
|
+
App framework:
|
|
121
110
|
sunpeak new [name] [resources] Create a new project
|
|
122
111
|
sunpeak dev Start dev server + inspector + MCP endpoint
|
|
123
112
|
--no-begging Suppress GitHub star message
|
|
@@ -125,8 +114,20 @@ App framework (for sunpeak projects):
|
|
|
125
114
|
sunpeak start Start production MCP server
|
|
126
115
|
--port, -p Server port (default: 8000, or PORT env)
|
|
127
116
|
sunpeak upgrade Upgrade sunpeak to latest version
|
|
128
|
-
sunpeak --version Show version number
|
|
129
117
|
|
|
118
|
+
Testing (works with any MCP server):
|
|
119
|
+
sunpeak test Run e2e tests against the inspector
|
|
120
|
+
init Scaffold test infrastructure into a project
|
|
121
|
+
--unit Run unit tests (vitest)
|
|
122
|
+
--live Run live tests against real hosts
|
|
123
|
+
--eval Run evals against LLM models
|
|
124
|
+
|
|
125
|
+
Inspector (works with any MCP server):
|
|
126
|
+
sunpeak inspect Inspect any MCP server in the inspector
|
|
127
|
+
--server, -s <url|cmd> MCP server URL or stdio command (required)
|
|
128
|
+
--simulations <dir> Simulation JSON directory
|
|
129
|
+
|
|
130
|
+
sunpeak --version Show version number
|
|
130
131
|
Resources: ${resources.join(', ')} (comma/space separated)
|
|
131
132
|
Example: sunpeak new sunpeak-app "${resources.slice(0, 2).join(',')}"
|
|
132
133
|
`);
|
package/dist/chatgpt/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("../chunk-9hOWP6kD.cjs");
|
|
3
|
-
const require_inspector = require("../inspector-
|
|
3
|
+
const require_inspector = require("../inspector-D0qOqYX2.cjs");
|
|
4
4
|
const require_inspector_url = require("../inspector-url-C3LTKgXt.cjs");
|
|
5
5
|
const require_discovery = require("../discovery-Clu4uHp1.cjs");
|
|
6
6
|
//#region src/chatgpt/index.ts
|
package/dist/chatgpt/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as __exportAll } from "../chunk-D6g4UhsZ.js";
|
|
2
|
-
import { _ as McpAppHost, d as ThemeProvider, f as useThemeContext, g as extractResourceCSP, h as IframeResource, n as resolveServerToolResult, t as Inspector, v as SCREEN_WIDTHS } from "../inspector-
|
|
2
|
+
import { _ as McpAppHost, d as ThemeProvider, f as useThemeContext, g as extractResourceCSP, h as IframeResource, n as resolveServerToolResult, t as Inspector, v as SCREEN_WIDTHS } from "../inspector-60Na_Zc4.js";
|
|
3
3
|
import { t as createInspectorUrl } from "../inspector-url-CyQcuBI9.js";
|
|
4
4
|
import { c as toPascalCase, i as findResourceKey, n as extractSimulationKey, r as findResourceDirs, s as getComponentName, t as extractResourceKey } from "../discovery-Cgoegt62.js";
|
|
5
5
|
//#region src/chatgpt/index.ts
|
package/dist/claude/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../chunk-9hOWP6kD.cjs");
|
|
3
|
-
const require_inspector = require("../inspector-
|
|
3
|
+
const require_inspector = require("../inspector-D0qOqYX2.cjs");
|
|
4
4
|
exports.Inspector = require_inspector.Inspector;
|
package/dist/claude/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as Inspector } from "../inspector-
|
|
1
|
+
import { t as Inspector } from "../inspector-60Na_Zc4.js";
|
|
2
2
|
export { Inspector };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../../chunk-9hOWP6kD.cjs");
|
|
3
|
-
const require_use_app = require("../../use-app-
|
|
3
|
+
const require_use_app = require("../../use-app-B33mckz4.cjs");
|
|
4
4
|
let react = require("react");
|
|
5
5
|
//#region src/host/chatgpt/openai-types.ts
|
|
6
6
|
/**
|
package/dist/index.cjs
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("./chunk-9hOWP6kD.cjs");
|
|
3
3
|
const require_protocol = require("./protocol-C8pFDmcy.cjs");
|
|
4
|
-
const require_use_app = require("./use-app-
|
|
5
|
-
const require_inspector = require("./inspector-
|
|
4
|
+
const require_use_app = require("./use-app-B33mckz4.cjs");
|
|
5
|
+
const require_inspector = require("./inspector-D0qOqYX2.cjs");
|
|
6
6
|
const require_host_index = require("./host/index.cjs");
|
|
7
7
|
const require_inspector_index = require("./inspector/index.cjs");
|
|
8
8
|
const require_chatgpt_index = require("./chatgpt/index.cjs");
|
|
9
9
|
let react = require("react");
|
|
10
10
|
react = require_chunk.__toESM(react, 1);
|
|
11
11
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
12
|
-
//#region ../../node_modules/.pnpm/@modelcontextprotocol+ext-apps@1.
|
|
12
|
+
//#region ../../node_modules/.pnpm/@modelcontextprotocol+ext-apps@1.6.0_@modelcontextprotocol+sdk@1.29.0_zod@4.3.6__react-_1fd7d0151a0915598274278e5ddb69e9/node_modules/@modelcontextprotocol/ext-apps/dist/src/react/index.js
|
|
13
13
|
var m = require_protocol.union([require_protocol.literal("light"), require_protocol.literal("dark")]).describe("Color theme preference for the host environment."), N$1 = require_protocol.union([
|
|
14
14
|
require_protocol.literal("inline"),
|
|
15
15
|
require_protocol.literal("fullscreen"),
|