sunpeak 0.16.1 → 0.16.2
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 +104 -8
- package/bin/commands/start.mjs +215 -0
- package/bin/sunpeak.js +11 -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 +1579 -3
- package/dist/mcp/index.cjs.map +1 -1
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.js +1580 -4
- 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
|
@@ -178,7 +178,7 @@ export async function dev(projectRoot = process.cwd(), args = []) {
|
|
|
178
178
|
sunpeakMcp = await import(pathToFileURL(join(sunpeakBase, 'dist/mcp/index.js')).href);
|
|
179
179
|
sunpeakDiscovery = await import(pathToFileURL(join(sunpeakBase, 'dist/lib/discovery-cli.js')).href);
|
|
180
180
|
}
|
|
181
|
-
const { FAVICON_BUFFER: faviconBuffer, runMCPServer } = sunpeakMcp;
|
|
181
|
+
const { FAVICON_BUFFER: faviconBuffer, runMCPServer, startProductionHttpServer } = sunpeakMcp;
|
|
182
182
|
const { findResourceDirs, findSimulationFilesFlat, findToolFiles, extractResourceExport, extractToolExport } = sunpeakDiscovery;
|
|
183
183
|
|
|
184
184
|
// Vite plugin to serve the sunpeak favicon
|
|
@@ -389,13 +389,109 @@ if (import.meta.hot) {
|
|
|
389
389
|
}
|
|
390
390
|
|
|
391
391
|
const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
392
|
+
|
|
393
|
+
let mcpHandle = null;
|
|
394
|
+
|
|
395
|
+
if (prodMcp) {
|
|
396
|
+
// --prod-mcp: Use real tool handlers via Vite SSR
|
|
397
|
+
// Load full tool modules (handler + schema + config) from TypeScript source
|
|
398
|
+
const ssrLoader = await createServer({
|
|
399
|
+
root: projectRoot,
|
|
400
|
+
server: { middlewareMode: true },
|
|
401
|
+
appType: 'custom',
|
|
402
|
+
logLevel: 'silent',
|
|
403
|
+
resolve: {
|
|
404
|
+
alias: {
|
|
405
|
+
...(isTemplate && { sunpeak: parentSrc }),
|
|
406
|
+
},
|
|
407
|
+
},
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
const prodTools = [];
|
|
411
|
+
for (const { name: toolName, path: toolPath } of toolFiles) {
|
|
412
|
+
try {
|
|
413
|
+
const relativePath = './' + toolPath.replace(projectRoot + '/', '').replace(projectRoot + '\\', '');
|
|
414
|
+
const mod = await ssrLoader.ssrLoadModule(relativePath);
|
|
415
|
+
if (mod.tool && mod.default) {
|
|
416
|
+
prodTools.push({
|
|
417
|
+
name: toolName,
|
|
418
|
+
tool: mod.tool,
|
|
419
|
+
schema: mod.schema,
|
|
420
|
+
handler: mod.default,
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
} catch (err) {
|
|
424
|
+
console.warn(`Warning: Could not load tool handler ${toolName}: ${err.message}`);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Load server entry if present
|
|
429
|
+
const serverEntryPath = join(projectRoot, 'src/server.ts');
|
|
430
|
+
let auth = undefined;
|
|
431
|
+
let serverConfig = {};
|
|
432
|
+
if (existsSync(serverEntryPath)) {
|
|
433
|
+
try {
|
|
434
|
+
const serverMod = await ssrLoader.ssrLoadModule('./src/server.ts');
|
|
435
|
+
if (typeof serverMod.auth === 'function') {
|
|
436
|
+
auth = serverMod.auth;
|
|
437
|
+
console.log('Loaded auth from src/server.ts');
|
|
438
|
+
}
|
|
439
|
+
if (serverMod.server) serverConfig = serverMod.server;
|
|
440
|
+
} catch (err) {
|
|
441
|
+
console.warn(`Warning: Could not load server entry: ${err.message}`);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
await ssrLoader.close();
|
|
446
|
+
|
|
447
|
+
// Build production resources from dist/
|
|
448
|
+
const prodResources = [];
|
|
449
|
+
for (const { key } of resourceDirs) {
|
|
450
|
+
const meta = resourceMap.get(key);
|
|
451
|
+
if (!meta) continue;
|
|
452
|
+
const htmlPath = join(projectRoot, `dist/${key}/${key}.html`);
|
|
453
|
+
const jsonPath = join(projectRoot, `dist/${key}/${key}.json`);
|
|
454
|
+
if (!existsSync(htmlPath)) continue;
|
|
455
|
+
|
|
456
|
+
const html = readFileSync(htmlPath, 'utf-8');
|
|
457
|
+
let uri = `ui://${meta.name ?? key}`;
|
|
458
|
+
let _meta = meta._meta;
|
|
459
|
+
|
|
460
|
+
// Use URI from build JSON if available (has cache-bust timestamp)
|
|
461
|
+
if (existsSync(jsonPath)) {
|
|
462
|
+
try {
|
|
463
|
+
const buildMeta = JSON.parse(readFileSync(jsonPath, 'utf-8'));
|
|
464
|
+
if (buildMeta.uri) uri = buildMeta.uri;
|
|
465
|
+
} catch {}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
prodResources.push({
|
|
469
|
+
name: meta.name ?? key,
|
|
470
|
+
uri,
|
|
471
|
+
html,
|
|
472
|
+
description: meta.description,
|
|
473
|
+
_meta,
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
const name = serverConfig.name ?? pkg.name ?? 'Sunpeak';
|
|
478
|
+
const version = serverConfig.version ?? pkg.version ?? '0.1.0';
|
|
479
|
+
|
|
480
|
+
console.log(`Starting production MCP server with ${prodTools.length} tool(s)...`);
|
|
481
|
+
startProductionHttpServer(
|
|
482
|
+
{ name, version, tools: prodTools, resources: prodResources, auth },
|
|
483
|
+
8000
|
|
484
|
+
);
|
|
485
|
+
} else {
|
|
486
|
+
// Default: simulation-based MCP server with fixture data
|
|
487
|
+
mcpHandle = runMCPServer({
|
|
488
|
+
name: pkg.name || 'Sunpeak',
|
|
489
|
+
version: pkg.version || '0.1.0',
|
|
490
|
+
simulations,
|
|
491
|
+
port: 8000,
|
|
492
|
+
...(mcpViteServer && { viteServer: mcpViteServer }),
|
|
493
|
+
});
|
|
494
|
+
}
|
|
399
495
|
|
|
400
496
|
// Build production bundles and watch for changes.
|
|
401
497
|
// Tunnel clients (e.g. Claude via ngrok) get the pre-built HTML since they can't
|
|
@@ -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,10 @@ 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
|
-
|
|
100
|
+
--prod-mcp Use real tool handlers (not fixtures)
|
|
101
|
+
sunpeak build Build resources + tools for production
|
|
102
|
+
sunpeak start Start production MCP server
|
|
103
|
+
--port, -p Server port (default: 8000, or PORT env)
|
|
94
104
|
sunpeak upgrade Upgrade sunpeak to latest version
|
|
95
105
|
sunpeak --version Show version number
|
|
96
106
|
|
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
|