sunpeak 0.16.1 → 0.16.3
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 +2 -1
- package/bin/commands/build.mjs +106 -2
- package/bin/commands/dev.mjs +57 -64
- package/bin/commands/start.mjs +215 -0
- package/bin/sunpeak.js +10 -1
- package/dist/chatgpt/index.cjs +2 -2
- package/dist/chatgpt/index.js +2 -2
- package/dist/claude/index.cjs +1 -1
- package/dist/claude/index.js +1 -1
- package/dist/{index-BvQ_ZuOO.cjs → index-Bll1bszc.cjs} +2 -2
- package/dist/{index-BvQ_ZuOO.cjs.map → index-Bll1bszc.cjs.map} +1 -1
- package/dist/{index-CTGEqlgk.js → index-CACtnwu2.js} +2 -2
- package/dist/{index-CTGEqlgk.js.map → index-CACtnwu2.js.map} +1 -1
- package/dist/{index-BjnAsaqp.js → index-CLcr8IyR.js} +2 -2
- package/dist/index-CLcr8IyR.js.map +1 -0
- package/dist/{index-C9CVbGFt.cjs → index-CaQmwZJc.cjs} +2 -2
- package/dist/index-CaQmwZJc.cjs.map +1 -0
- package/dist/index.cjs +5 -5
- package/dist/index.js +6 -6
- package/dist/mcp/index.cjs +1671 -82
- package/dist/mcp/index.cjs.map +1 -1
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.js +1672 -83
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/production-server.d.ts +156 -0
- package/dist/platform/chatgpt/index.cjs +1 -1
- package/dist/platform/chatgpt/index.js +1 -1
- package/dist/{protocol-DFbsCx7E.js → protocol-BD5jDQEx.js} +8 -1
- package/dist/{protocol-DFbsCx7E.js.map → protocol-BD5jDQEx.js.map} +1 -1
- package/dist/{protocol-CL4_Npj5.cjs → protocol-BOjXuK6l.cjs} +8 -1
- package/dist/{protocol-CL4_Npj5.cjs.map → protocol-BOjXuK6l.cjs.map} +1 -1
- package/dist/simulator/index.cjs +1 -1
- package/dist/simulator/index.js +1 -1
- package/dist/{simulator-C0H_k092.js → simulator-B7rw83zP.js} +2 -2
- package/dist/{simulator-C0H_k092.js.map → simulator-B7rw83zP.js.map} +1 -1
- package/dist/{simulator-B56j5P8W.cjs → simulator-DjZNa1MI.cjs} +2 -2
- package/dist/{simulator-B56j5P8W.cjs.map → simulator-DjZNa1MI.cjs.map} +1 -1
- package/dist/{use-app-BuufpXTQ.cjs → use-app-BpAJqzdE.cjs} +2 -2
- package/dist/{use-app-BuufpXTQ.cjs.map → use-app-BpAJqzdE.cjs.map} +1 -1
- package/dist/{use-app-BThbgFFT.js → use-app-WOUdh1PR.js} +2 -2
- package/dist/{use-app-BThbgFFT.js.map → use-app-WOUdh1PR.js.map} +1 -1
- package/package.json +1 -1
- package/template/README.md +13 -12
- package/template/package.json +1 -0
- package/template/src/server.ts +7 -5
- package/dist/index-BjnAsaqp.js.map +0 -1
- package/dist/index-C9CVbGFt.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -88,7 +88,8 @@ Commands for managing MCP Apps:
|
|
|
88
88
|
|
|
89
89
|
- `sunpeak new [name] [resources]` - Create a new project
|
|
90
90
|
- `sunpeak dev` - Start dev server with MCP endpoint and live simulator
|
|
91
|
-
- `sunpeak build` - Build resources for production
|
|
91
|
+
- `sunpeak build` - Build resources and compile tools for production
|
|
92
|
+
- `sunpeak start` - Start the production MCP server (real handlers, auth, Zod validation)
|
|
92
93
|
- `sunpeak upgrade` - Upgrade sunpeak to latest version
|
|
93
94
|
|
|
94
95
|
## Example App
|
package/bin/commands/build.mjs
CHANGED
|
@@ -340,10 +340,114 @@ ${jsContents}
|
|
|
340
340
|
|
|
341
341
|
console.log('\n✓ All resources built successfully!');
|
|
342
342
|
console.log('\nBuilt resources:');
|
|
343
|
-
for (const { kebabName
|
|
344
|
-
const files = readdirSync(distOutDir);
|
|
343
|
+
for (const { kebabName } of resourceFiles) {
|
|
345
344
|
console.log(` ${kebabName}`);
|
|
346
345
|
}
|
|
346
|
+
|
|
347
|
+
// ========================================================================
|
|
348
|
+
// Compile server-side code (tools + server entry) for `sunpeak start`
|
|
349
|
+
// ========================================================================
|
|
350
|
+
|
|
351
|
+
const toolsDir = path.join(projectRoot, 'src/tools');
|
|
352
|
+
const serverEntryPath = path.join(projectRoot, 'src/server.ts');
|
|
353
|
+
|
|
354
|
+
// Find tool files
|
|
355
|
+
const toolFiles = existsSync(toolsDir)
|
|
356
|
+
? readdirSync(toolsDir).filter(f => f.endsWith('.ts'))
|
|
357
|
+
: [];
|
|
358
|
+
|
|
359
|
+
const hasServerEntry = existsSync(serverEntryPath);
|
|
360
|
+
|
|
361
|
+
if (toolFiles.length > 0 || hasServerEntry) {
|
|
362
|
+
console.log('\nCompiling server-side code...');
|
|
363
|
+
|
|
364
|
+
let esbuild;
|
|
365
|
+
try {
|
|
366
|
+
const esbuildPath = resolveEsmEntry(require, 'esbuild');
|
|
367
|
+
esbuild = await import(esbuildPath);
|
|
368
|
+
} catch {
|
|
369
|
+
console.warn('Warning: esbuild not found — skipping tool/server compilation.');
|
|
370
|
+
console.warn('Install esbuild to enable `sunpeak start`: npm install -D esbuild');
|
|
371
|
+
esbuild = null;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (esbuild) {
|
|
375
|
+
const toolsOutDir = path.join(distDir, 'tools');
|
|
376
|
+
if (toolFiles.length > 0) {
|
|
377
|
+
mkdirSync(toolsOutDir, { recursive: true });
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Compile each tool file
|
|
381
|
+
for (const toolFile of toolFiles) {
|
|
382
|
+
const toolName = toolFile.replace(/\.ts$/, '');
|
|
383
|
+
const toolPath = path.join(toolsDir, toolFile);
|
|
384
|
+
|
|
385
|
+
try {
|
|
386
|
+
await esbuild.build({
|
|
387
|
+
entryPoints: [toolPath],
|
|
388
|
+
bundle: true,
|
|
389
|
+
format: 'esm',
|
|
390
|
+
platform: 'node',
|
|
391
|
+
target: 'node18',
|
|
392
|
+
outfile: path.join(toolsOutDir, `${toolName}.js`),
|
|
393
|
+
// Externalize bare specifiers (node_modules) — resolve at runtime
|
|
394
|
+
plugins: [{
|
|
395
|
+
name: 'externalize-bare-specifiers',
|
|
396
|
+
setup(build) {
|
|
397
|
+
build.onResolve({ filter: /.*/ }, (args) => {
|
|
398
|
+
if (args.kind !== 'import-statement') return;
|
|
399
|
+
if (!args.path.startsWith('.') && !args.path.startsWith('/')) {
|
|
400
|
+
return { external: true };
|
|
401
|
+
}
|
|
402
|
+
return undefined;
|
|
403
|
+
});
|
|
404
|
+
},
|
|
405
|
+
}],
|
|
406
|
+
loader: { '.tsx': 'tsx', '.ts': 'ts' },
|
|
407
|
+
logLevel: 'warning',
|
|
408
|
+
});
|
|
409
|
+
console.log(`✓ Compiled tools/${toolName}.js`);
|
|
410
|
+
} catch (err) {
|
|
411
|
+
console.error(`Failed to compile tool ${toolName}:`, err.message);
|
|
412
|
+
process.exit(1);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Compile server entry if present
|
|
417
|
+
if (hasServerEntry) {
|
|
418
|
+
try {
|
|
419
|
+
await esbuild.build({
|
|
420
|
+
entryPoints: [serverEntryPath],
|
|
421
|
+
bundle: true,
|
|
422
|
+
format: 'esm',
|
|
423
|
+
platform: 'node',
|
|
424
|
+
target: 'node18',
|
|
425
|
+
outfile: path.join(distDir, 'server.js'),
|
|
426
|
+
plugins: [{
|
|
427
|
+
name: 'externalize-bare-specifiers',
|
|
428
|
+
setup(build) {
|
|
429
|
+
build.onResolve({ filter: /.*/ }, (args) => {
|
|
430
|
+
if (args.kind !== 'import-statement') return;
|
|
431
|
+
if (!args.path.startsWith('.') && !args.path.startsWith('/')) {
|
|
432
|
+
return { external: true };
|
|
433
|
+
}
|
|
434
|
+
return undefined;
|
|
435
|
+
});
|
|
436
|
+
},
|
|
437
|
+
}],
|
|
438
|
+
loader: { '.tsx': 'tsx', '.ts': 'ts' },
|
|
439
|
+
logLevel: 'warning',
|
|
440
|
+
});
|
|
441
|
+
console.log(`✓ Compiled server.js`);
|
|
442
|
+
} catch (err) {
|
|
443
|
+
console.error(`Failed to compile server entry:`, err.message);
|
|
444
|
+
process.exit(1);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
console.log('\n✓ Build complete!');
|
|
347
451
|
}
|
|
348
452
|
|
|
349
453
|
// Allow running directly
|
package/bin/commands/dev.mjs
CHANGED
|
@@ -149,9 +149,6 @@ export async function dev(projectRoot = process.cwd(), args = []) {
|
|
|
149
149
|
// Parse --no-begging flag
|
|
150
150
|
const noBegging = args.includes('--no-begging');
|
|
151
151
|
|
|
152
|
-
// Parse --prod-mcp flag (serve production build files over MCP instead of Vite HMR)
|
|
153
|
-
const prodMcp = args.includes('--prod-mcp');
|
|
154
|
-
|
|
155
152
|
console.log(`Starting Vite dev server on port ${port}...`);
|
|
156
153
|
|
|
157
154
|
// Check if we're in the sunpeak workspace (directory is named "template")
|
|
@@ -296,33 +293,29 @@ export async function dev(projectRoot = process.cwd(), args = []) {
|
|
|
296
293
|
});
|
|
297
294
|
}
|
|
298
295
|
|
|
299
|
-
// Start MCP server with its own Vite instance
|
|
296
|
+
// Start MCP server with its own Vite instance for HMR
|
|
300
297
|
if (simulations.length > 0) {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
298
|
+
console.log(`\nStarting MCP server with ${simulations.length} simulation(s) (Vite HMR)...`);
|
|
299
|
+
|
|
300
|
+
// Virtual entry module plugin for MCP
|
|
301
|
+
const sunpeakEntryPlugin = () => ({
|
|
302
|
+
name: 'sunpeak-entry',
|
|
303
|
+
resolveId(id) {
|
|
304
|
+
if (id.startsWith('virtual:sunpeak-entry')) {
|
|
305
|
+
return id;
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
load(id) {
|
|
309
|
+
if (id.startsWith('virtual:sunpeak-entry')) {
|
|
310
|
+
const url = new URL(id.replace('virtual:sunpeak-entry', 'http://x'));
|
|
311
|
+
const srcPath = url.searchParams.get('src');
|
|
312
|
+
const componentName = url.searchParams.get('component');
|
|
313
|
+
|
|
314
|
+
if (!srcPath || !componentName) {
|
|
315
|
+
return 'console.error("Missing src or component param");';
|
|
313
316
|
}
|
|
314
|
-
},
|
|
315
|
-
load(id) {
|
|
316
|
-
if (id.startsWith('virtual:sunpeak-entry')) {
|
|
317
|
-
const url = new URL(id.replace('virtual:sunpeak-entry', 'http://x'));
|
|
318
|
-
const srcPath = url.searchParams.get('src');
|
|
319
|
-
const componentName = url.searchParams.get('component');
|
|
320
|
-
|
|
321
|
-
if (!srcPath || !componentName) {
|
|
322
|
-
return 'console.error("Missing src or component param");';
|
|
323
|
-
}
|
|
324
317
|
|
|
325
|
-
|
|
318
|
+
return `
|
|
326
319
|
import { createElement } from 'react';
|
|
327
320
|
import { createRoot } from 'react-dom/client';
|
|
328
321
|
import { AppProvider } from 'sunpeak';
|
|
@@ -349,52 +342,52 @@ if (import.meta.hot) {
|
|
|
349
342
|
import.meta.hot.accept();
|
|
350
343
|
}
|
|
351
344
|
`;
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
});
|
|
355
348
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
},
|
|
349
|
+
// Create Vite dev server in middleware mode for MCP
|
|
350
|
+
// Use separate cache directory to avoid conflicts with main dev server
|
|
351
|
+
const mcpViteServer = await createServer({
|
|
352
|
+
root: projectRoot,
|
|
353
|
+
cacheDir: 'node_modules/.vite-mcp',
|
|
354
|
+
plugins: [react(), tailwindcss(), sunpeakEntryPlugin()],
|
|
355
|
+
resolve: {
|
|
356
|
+
alias: {
|
|
357
|
+
...(isTemplate && {
|
|
358
|
+
sunpeak: parentSrc,
|
|
359
|
+
}),
|
|
368
360
|
},
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
361
|
+
},
|
|
362
|
+
server: {
|
|
363
|
+
middlewareMode: true,
|
|
364
|
+
allowedHosts: true,
|
|
365
|
+
watch: {
|
|
366
|
+
// Only watch files that affect the UI bundle (not JSON, tests, etc.)
|
|
367
|
+
// MCP resources reload on next tool call, not on file change
|
|
368
|
+
ignored: (filePath) => {
|
|
369
|
+
if (!filePath.includes('.')) return false; // Watch directories
|
|
370
|
+
if (/\.(tsx?|css)$/.test(filePath)) {
|
|
371
|
+
return /\.(test|spec)\.tsx?$/.test(filePath); // Ignore tests
|
|
372
|
+
}
|
|
373
|
+
return true; // Ignore everything else
|
|
382
374
|
},
|
|
383
375
|
},
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
}
|
|
376
|
+
},
|
|
377
|
+
optimizeDeps: {
|
|
378
|
+
include: ['react', 'react-dom/client'],
|
|
379
|
+
},
|
|
380
|
+
appType: 'custom',
|
|
381
|
+
});
|
|
390
382
|
|
|
391
383
|
const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
|
|
384
|
+
|
|
392
385
|
const mcpHandle = runMCPServer({
|
|
393
386
|
name: pkg.name || 'Sunpeak',
|
|
394
387
|
version: pkg.version || '0.1.0',
|
|
395
388
|
simulations,
|
|
396
389
|
port: 8000,
|
|
397
|
-
|
|
390
|
+
viteServer: mcpViteServer,
|
|
398
391
|
});
|
|
399
392
|
|
|
400
393
|
// Build production bundles and watch for changes.
|
|
@@ -406,13 +399,13 @@ if (import.meta.hot) {
|
|
|
406
399
|
|
|
407
400
|
// Handle signals - close both servers
|
|
408
401
|
process.on('SIGINT', async () => {
|
|
409
|
-
|
|
402
|
+
await mcpViteServer.close();
|
|
410
403
|
await server.close();
|
|
411
404
|
process.exit(0);
|
|
412
405
|
});
|
|
413
406
|
|
|
414
407
|
process.on('SIGTERM', async () => {
|
|
415
|
-
|
|
408
|
+
await mcpViteServer.close();
|
|
416
409
|
await server.close();
|
|
417
410
|
process.exit(0);
|
|
418
411
|
});
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, readFileSync, readdirSync } from 'fs';
|
|
3
|
+
import { join, dirname } from 'path';
|
|
4
|
+
import { createRequire } from 'module';
|
|
5
|
+
import { pathToFileURL } from 'url';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Start a production MCP server from built artifacts.
|
|
9
|
+
*
|
|
10
|
+
* Discovers compiled tools from dist/tools/, resources from dist/{name}/,
|
|
11
|
+
* and optional server entry from dist/server.js. Registers tools with
|
|
12
|
+
* real handlers and Zod schemas, serves pre-built resource HTML.
|
|
13
|
+
*
|
|
14
|
+
* Run `sunpeak build` before `sunpeak start`.
|
|
15
|
+
*/
|
|
16
|
+
export async function start(projectRoot = process.cwd(), args = []) {
|
|
17
|
+
const pkgJsonPath = join(projectRoot, 'package.json');
|
|
18
|
+
if (!existsSync(pkgJsonPath)) {
|
|
19
|
+
console.error('Error: No package.json found in current directory');
|
|
20
|
+
console.error('Make sure you are in a Sunpeak project directory');
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
|
|
25
|
+
const distDir = join(projectRoot, 'dist');
|
|
26
|
+
|
|
27
|
+
if (!existsSync(distDir)) {
|
|
28
|
+
console.error('Error: No dist/ directory found. Run `sunpeak build` first.');
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Parse port from args or env
|
|
33
|
+
let port = parseInt(process.env.PORT || '8000');
|
|
34
|
+
const portArgIndex = args.findIndex(arg => arg === '--port' || arg === '-p');
|
|
35
|
+
if (portArgIndex !== -1 && args[portArgIndex + 1]) {
|
|
36
|
+
port = parseInt(args[portArgIndex + 1]);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Import production server from sunpeak
|
|
40
|
+
const isTemplate = projectRoot.endsWith('/template') || projectRoot.endsWith('\\template');
|
|
41
|
+
let sunpeakMcp;
|
|
42
|
+
if (isTemplate) {
|
|
43
|
+
// In workspace dev mode — import from TypeScript source via dynamic import
|
|
44
|
+
// We compile on the fly using the parent's Vite (same pattern as dev.mjs)
|
|
45
|
+
const parentSrc = join(projectRoot, '../src');
|
|
46
|
+
const require = createRequire(pkgJsonPath);
|
|
47
|
+
const vite = await import(findEsmEntry(require, 'vite'));
|
|
48
|
+
const loaderServer = await vite.createServer({
|
|
49
|
+
root: join(projectRoot, '..'),
|
|
50
|
+
server: { middlewareMode: true },
|
|
51
|
+
appType: 'custom',
|
|
52
|
+
logLevel: 'silent',
|
|
53
|
+
});
|
|
54
|
+
sunpeakMcp = await loaderServer.ssrLoadModule('./src/mcp/index.ts');
|
|
55
|
+
await loaderServer.close();
|
|
56
|
+
} else {
|
|
57
|
+
const require = createRequire(pkgJsonPath);
|
|
58
|
+
const sunpeakBase = require.resolve('sunpeak').replace(/dist\/index\.(c)?js$/, '');
|
|
59
|
+
sunpeakMcp = await import(pathToFileURL(join(sunpeakBase, 'dist/mcp/index.js')).href);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const { startProductionHttpServer } = sunpeakMcp;
|
|
63
|
+
|
|
64
|
+
// ========================================================================
|
|
65
|
+
// Discover built resources
|
|
66
|
+
// ========================================================================
|
|
67
|
+
|
|
68
|
+
const resources = [];
|
|
69
|
+
const entries = readdirSync(distDir, { withFileTypes: true });
|
|
70
|
+
|
|
71
|
+
for (const entry of entries) {
|
|
72
|
+
if (!entry.isDirectory() || entry.name === 'tools' || entry.name === 'build-output') continue;
|
|
73
|
+
|
|
74
|
+
const name = entry.name;
|
|
75
|
+
const jsonPath = join(distDir, name, `${name}.json`);
|
|
76
|
+
const htmlPath = join(distDir, name, `${name}.html`);
|
|
77
|
+
|
|
78
|
+
if (!existsSync(jsonPath) || !existsSync(htmlPath)) continue;
|
|
79
|
+
|
|
80
|
+
const meta = JSON.parse(readFileSync(jsonPath, 'utf-8'));
|
|
81
|
+
const html = readFileSync(htmlPath, 'utf-8');
|
|
82
|
+
|
|
83
|
+
resources.push({
|
|
84
|
+
name: meta.name ?? name,
|
|
85
|
+
uri: meta.uri ?? `ui://${name}`,
|
|
86
|
+
html,
|
|
87
|
+
description: meta.description,
|
|
88
|
+
_meta: meta._meta,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (resources.length === 0) {
|
|
93
|
+
console.error('Error: No built resources found in dist/. Run `sunpeak build` first.');
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
console.log(`Found ${resources.length} resource(s): ${resources.map(r => r.name).join(', ')}`);
|
|
98
|
+
|
|
99
|
+
// ========================================================================
|
|
100
|
+
// Load compiled tool modules
|
|
101
|
+
// ========================================================================
|
|
102
|
+
|
|
103
|
+
const toolsDir = join(distDir, 'tools');
|
|
104
|
+
const tools = [];
|
|
105
|
+
|
|
106
|
+
if (existsSync(toolsDir)) {
|
|
107
|
+
const toolFiles = readdirSync(toolsDir).filter(f => f.endsWith('.js'));
|
|
108
|
+
|
|
109
|
+
for (const file of toolFiles) {
|
|
110
|
+
const toolName = file.replace(/\.js$/, '');
|
|
111
|
+
const toolPath = pathToFileURL(join(toolsDir, file)).href;
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
const mod = await import(toolPath);
|
|
115
|
+
const tool = mod.tool;
|
|
116
|
+
const schema = mod.schema;
|
|
117
|
+
const handler = mod.default;
|
|
118
|
+
|
|
119
|
+
if (!tool) {
|
|
120
|
+
console.warn(`Warning: No "tool" export in ${file}. Skipping.`);
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (!handler || typeof handler !== 'function') {
|
|
124
|
+
console.warn(`Warning: No default handler export in ${file}. Skipping.`);
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
tools.push({ name: toolName, tool, schema, handler });
|
|
129
|
+
} catch (err) {
|
|
130
|
+
console.error(`Failed to load tool ${toolName}:`, err.message);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (tools.length === 0) {
|
|
137
|
+
console.error('Error: No compiled tools found in dist/tools/. Run `sunpeak build` first.');
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
console.log(`Found ${tools.length} tool(s): ${tools.map(t => t.name).join(', ')}`);
|
|
142
|
+
|
|
143
|
+
// ========================================================================
|
|
144
|
+
// Load server entry (optional)
|
|
145
|
+
// ========================================================================
|
|
146
|
+
|
|
147
|
+
const serverEntryPath = join(distDir, 'server.js');
|
|
148
|
+
let auth = undefined;
|
|
149
|
+
let serverConfig = {};
|
|
150
|
+
|
|
151
|
+
if (existsSync(serverEntryPath)) {
|
|
152
|
+
try {
|
|
153
|
+
const serverEntry = await import(pathToFileURL(serverEntryPath).href);
|
|
154
|
+
if (typeof serverEntry.auth === 'function') {
|
|
155
|
+
auth = serverEntry.auth;
|
|
156
|
+
console.log('Loaded auth from server entry');
|
|
157
|
+
}
|
|
158
|
+
if (serverEntry.server) {
|
|
159
|
+
serverConfig = serverEntry.server;
|
|
160
|
+
}
|
|
161
|
+
} catch (err) {
|
|
162
|
+
console.error('Failed to load server entry:', err.message);
|
|
163
|
+
process.exit(1);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ========================================================================
|
|
168
|
+
// Start production MCP server
|
|
169
|
+
// ========================================================================
|
|
170
|
+
|
|
171
|
+
const name = serverConfig.name ?? pkg.name ?? 'sunpeak-app';
|
|
172
|
+
const version = serverConfig.version ?? pkg.version ?? '0.1.0';
|
|
173
|
+
|
|
174
|
+
console.log(`\nStarting ${name} v${version} on port ${port}...`);
|
|
175
|
+
|
|
176
|
+
startProductionHttpServer(
|
|
177
|
+
{ name, version, tools, resources, auth },
|
|
178
|
+
port
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Resolve ESM entry point for a package (same utility as build.mjs)
|
|
184
|
+
*/
|
|
185
|
+
function findEsmEntry(require, packageName) {
|
|
186
|
+
const resolvedPath = require.resolve(packageName);
|
|
187
|
+
let dir = dirname(resolvedPath);
|
|
188
|
+
while (dir !== dirname(dir)) {
|
|
189
|
+
const pkgPath = join(dir, 'package.json');
|
|
190
|
+
if (existsSync(pkgPath)) {
|
|
191
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
192
|
+
if (pkg.name === packageName) {
|
|
193
|
+
const exports = pkg.exports;
|
|
194
|
+
if (exports?.['.']?.import) {
|
|
195
|
+
const importEntry = exports['.'].import;
|
|
196
|
+
const esmPath = typeof importEntry === 'string' ? importEntry : importEntry.default;
|
|
197
|
+
if (esmPath) return pathToFileURL(join(dir, esmPath)).href;
|
|
198
|
+
}
|
|
199
|
+
if (pkg.module) return pathToFileURL(join(dir, pkg.module)).href;
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
dir = dirname(dir);
|
|
204
|
+
}
|
|
205
|
+
return pathToFileURL(resolvedPath).href;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Allow running directly
|
|
209
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
210
|
+
const args = process.argv.slice(2);
|
|
211
|
+
start(process.cwd(), args).catch(error => {
|
|
212
|
+
console.error('Error:', error.message);
|
|
213
|
+
process.exit(1);
|
|
214
|
+
});
|
|
215
|
+
}
|
package/bin/sunpeak.js
CHANGED
|
@@ -65,6 +65,13 @@ function getVersion() {
|
|
|
65
65
|
}
|
|
66
66
|
break;
|
|
67
67
|
|
|
68
|
+
case 'start':
|
|
69
|
+
{
|
|
70
|
+
const { start } = await import(join(COMMANDS_DIR, 'start.mjs'));
|
|
71
|
+
await start(process.cwd(), args);
|
|
72
|
+
}
|
|
73
|
+
break;
|
|
74
|
+
|
|
68
75
|
case 'upgrade':
|
|
69
76
|
{
|
|
70
77
|
const { upgrade } = await import(join(COMMANDS_DIR, 'upgrade.mjs'));
|
|
@@ -90,7 +97,9 @@ Usage:
|
|
|
90
97
|
sunpeak new [name] [resources] Create a new project
|
|
91
98
|
sunpeak dev Start dev server + MCP endpoint
|
|
92
99
|
--no-begging Suppress GitHub star message
|
|
93
|
-
sunpeak build Build resources
|
|
100
|
+
sunpeak build Build resources + tools for production
|
|
101
|
+
sunpeak start Start production MCP server
|
|
102
|
+
--port, -p Server port (default: 8000, or PORT env)
|
|
94
103
|
sunpeak upgrade Upgrade sunpeak to latest version
|
|
95
104
|
sunpeak --version Show version number
|
|
96
105
|
|
package/dist/chatgpt/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const simulator = require("../simulator-
|
|
4
|
-
const chatgpt_index = require("../index-
|
|
3
|
+
const simulator = require("../simulator-DjZNa1MI.cjs");
|
|
4
|
+
const chatgpt_index = require("../index-Bll1bszc.cjs");
|
|
5
5
|
const simulatorUrl = require("../simulator-url-rgg_KYOg.cjs");
|
|
6
6
|
const discovery = require("../discovery-DmB8_4QL.cjs");
|
|
7
7
|
exports.IframeResource = simulator.IframeResource;
|
package/dist/chatgpt/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { I, M, a, S, T, j, m } from "../simulator-
|
|
2
|
-
import { C } from "../index-
|
|
1
|
+
import { I, M, a, S, T, j, m } from "../simulator-B7rw83zP.js";
|
|
2
|
+
import { C } from "../index-CACtnwu2.js";
|
|
3
3
|
import { c } from "../simulator-url-CuLqtnSS.js";
|
|
4
4
|
import { b, a as a2, c as c2, d, e, f, g, h, i, t } from "../discovery-CH80W5l9.js";
|
|
5
5
|
export {
|
package/dist/claude/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const simulator = require("../simulator-
|
|
3
|
+
const simulator = require("../simulator-DjZNa1MI.cjs");
|
|
4
4
|
exports.ClaudeSimulator = simulator.Simulator;
|
|
5
5
|
//# sourceMappingURL=index.cjs.map
|
package/dist/claude/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const simulator = require("./simulator-
|
|
2
|
+
const simulator = require("./simulator-DjZNa1MI.cjs");
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const React = require("react");
|
|
5
5
|
const simulatorUrl = require("./simulator-url-rgg_KYOg.cjs");
|
|
@@ -521,4 +521,4 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
|
|
|
521
521
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
522
522
|
exports.ChatGPTSimulator = ChatGPTSimulator;
|
|
523
523
|
exports.index = index;
|
|
524
|
-
//# sourceMappingURL=index-
|
|
524
|
+
//# sourceMappingURL=index-Bll1bszc.cjs.map
|