sunpeak 0.16.3 → 0.16.5
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 +3 -1
- package/bin/commands/build.mjs +1 -0
- package/bin/commands/dev.mjs +2 -0
- package/dist/chatgpt/globals.css +0 -8
- package/dist/mcp/index.cjs +61 -48
- package/dist/mcp/index.cjs.map +1 -1
- package/dist/mcp/index.js +61 -48
- package/dist/mcp/index.js.map +1 -1
- package/dist/style.css +0 -8
- package/package.json +1 -1
- package/template/package.json +0 -3
- package/template/src/components/avatar.tsx +1 -1
- package/template/src/resources/albums/components/album-card.tsx +2 -2
- package/template/src/resources/albums/components/album-carousel.tsx +3 -3
- package/template/src/resources/albums/components/film-strip.tsx +2 -2
- package/template/src/resources/albums/components/fullscreen-viewer.tsx +1 -1
- package/template/src/resources/carousel/components/card.tsx +2 -2
- package/template/src/resources/carousel/components/carousel.tsx +3 -3
- package/template/src/resources/map/components/map-view.tsx +1 -1
- package/template/src/resources/map/components/map.tsx +3 -3
- package/template/src/resources/map/components/place-card.tsx +2 -2
- package/template/src/resources/map/components/place-carousel.tsx +1 -1
- package/template/src/resources/map/components/place-inspector.tsx +4 -4
- package/template/src/resources/map/components/place-list.tsx +2 -2
- package/template/src/resources/review/review.tsx +59 -29
- package/template/src/tools/review-diff.ts +3 -1
- package/template/src/tools/review-post.ts +3 -1
- package/template/src/tools/review-purchase.ts +3 -1
- package/template/src/tools/show-albums.ts +3 -1
- package/template/src/tools/show-carousel.ts +3 -1
- package/template/src/tools/show-map.ts +3 -1
- package/template/tsconfig.json +7 -2
- package/template/vitest.config.ts +1 -0
- package/template/node_modules/.bin/nodemon +0 -21
- package/template/node_modules/.bin/tsx +0 -21
package/README.md
CHANGED
|
@@ -141,7 +141,9 @@ export const schema = {
|
|
|
141
141
|
title: z.string().describe('Title describing the changes'),
|
|
142
142
|
};
|
|
143
143
|
|
|
144
|
-
|
|
144
|
+
type Args = z.infer<z.ZodObject<typeof schema>>;
|
|
145
|
+
|
|
146
|
+
export default async function (args: Args, extra: ToolHandlerExtra) {
|
|
145
147
|
return { structuredContent: { title: args.title, sections: [] } };
|
|
146
148
|
}
|
|
147
149
|
```
|
package/bin/commands/build.mjs
CHANGED
|
@@ -241,6 +241,7 @@ export async function build(projectRoot = process.cwd()) {
|
|
|
241
241
|
resolve: {
|
|
242
242
|
conditions: ['style', 'import', 'module', 'browser', 'default'],
|
|
243
243
|
alias: {
|
|
244
|
+
'@': path.resolve(projectRoot, 'src'),
|
|
244
245
|
// In workspace dev mode, use local sunpeak source
|
|
245
246
|
...(isTemplate && {
|
|
246
247
|
sunpeak: parentSrc,
|
package/bin/commands/dev.mjs
CHANGED
|
@@ -201,6 +201,7 @@ export async function dev(projectRoot = process.cwd(), args = []) {
|
|
|
201
201
|
plugins: [react(), tailwindcss(), sunpeakFaviconPlugin()],
|
|
202
202
|
resolve: {
|
|
203
203
|
alias: {
|
|
204
|
+
'@': path.resolve(projectRoot, 'src'),
|
|
204
205
|
// In workspace dev mode, use local sunpeak source
|
|
205
206
|
...(isTemplate && {
|
|
206
207
|
sunpeak: parentSrc,
|
|
@@ -354,6 +355,7 @@ if (import.meta.hot) {
|
|
|
354
355
|
plugins: [react(), tailwindcss(), sunpeakEntryPlugin()],
|
|
355
356
|
resolve: {
|
|
356
357
|
alias: {
|
|
358
|
+
'@': path.resolve(projectRoot, 'src'),
|
|
357
359
|
...(isTemplate && {
|
|
358
360
|
sunpeak: parentSrc,
|
|
359
361
|
}),
|
package/dist/chatgpt/globals.css
CHANGED
|
@@ -1368,10 +1368,6 @@
|
|
|
1368
1368
|
background-color: #0000;
|
|
1369
1369
|
}
|
|
1370
1370
|
|
|
1371
|
-
.bg-white {
|
|
1372
|
-
background-color: var(--color-white);
|
|
1373
|
-
}
|
|
1374
|
-
|
|
1375
1371
|
.bg-gradient-to-l {
|
|
1376
1372
|
--tw-gradient-position: to left in oklab;
|
|
1377
1373
|
background-image: linear-gradient(var(--tw-gradient-stops));
|
|
@@ -1672,10 +1668,6 @@
|
|
|
1672
1668
|
white-space: pre-wrap;
|
|
1673
1669
|
}
|
|
1674
1670
|
|
|
1675
|
-
.text-\[\#000000\] {
|
|
1676
|
-
color: #000;
|
|
1677
|
-
}
|
|
1678
|
-
|
|
1679
1671
|
.text-\[var\(--color-text-danger\)\] {
|
|
1680
1672
|
color: var(--color-text-danger);
|
|
1681
1673
|
}
|
package/dist/mcp/index.cjs
CHANGED
|
@@ -15520,27 +15520,30 @@ function createAppServer(config, simulations, viteMode) {
|
|
|
15520
15520
|
},
|
|
15521
15521
|
{ capabilities: { resources: {}, tools: {} } }
|
|
15522
15522
|
);
|
|
15523
|
-
const
|
|
15523
|
+
const registeredUriSet = /* @__PURE__ */ new Set();
|
|
15524
|
+
const resourceHandles = /* @__PURE__ */ new Map();
|
|
15525
|
+
const toolHandles = [];
|
|
15524
15526
|
for (const simulation of simulations) {
|
|
15525
15527
|
const resource = simulation.resource;
|
|
15526
15528
|
const tool = simulation.tool;
|
|
15527
15529
|
const toolResult = simulation.toolResult ?? { structuredContent: null };
|
|
15528
15530
|
const uri2 = resource.uri ?? `ui://${resource.name}`;
|
|
15531
|
+
const resourceName = resource.name;
|
|
15529
15532
|
const resourceMeta = resource._meta ?? {};
|
|
15530
15533
|
const toolMeta = tool._meta ?? {};
|
|
15531
|
-
if (!
|
|
15532
|
-
|
|
15534
|
+
if (!registeredUriSet.has(uri2)) {
|
|
15535
|
+
registeredUriSet.add(uri2);
|
|
15533
15536
|
const listMeta = viteMode ? injectViteCSP(resourceMeta) : resourceMeta;
|
|
15534
15537
|
console.log(`[MCP] RegisterResource: ${uri2}`);
|
|
15535
|
-
|
|
15536
|
-
|
|
15537
|
-
resource.name,
|
|
15538
|
+
const handle = mcpServer.registerResource(
|
|
15539
|
+
resourceName,
|
|
15538
15540
|
uri2,
|
|
15539
15541
|
{
|
|
15542
|
+
mimeType: EI,
|
|
15540
15543
|
description: resource.description,
|
|
15541
15544
|
_meta: listMeta
|
|
15542
15545
|
},
|
|
15543
|
-
async (
|
|
15546
|
+
async (readUri, extra) => {
|
|
15544
15547
|
const prodBuild = needsProdBuild(
|
|
15545
15548
|
extra?.requestInfo?.headers ?? {}
|
|
15546
15549
|
);
|
|
@@ -15549,17 +15552,18 @@ function createAppServer(config, simulations, viteMode) {
|
|
|
15549
15552
|
try {
|
|
15550
15553
|
content = getResourceHtml(simulation, viteMode, prodBuild);
|
|
15551
15554
|
} catch (error) {
|
|
15552
|
-
console.error(`[MCP] ReadResource error for ${
|
|
15555
|
+
console.error(`[MCP] ReadResource error for ${readUri.href}:`, error);
|
|
15553
15556
|
throw error;
|
|
15554
15557
|
}
|
|
15555
15558
|
const sizeKB = (content.length / 1024).toFixed(1);
|
|
15556
15559
|
console.log(
|
|
15557
|
-
`[MCP] ReadResource: ${
|
|
15560
|
+
`[MCP] ReadResource: ${readUri.href} → ${sizeKB}KB${prodBuild ? " (prod build)" : " (vite)"}`
|
|
15558
15561
|
);
|
|
15559
15562
|
return {
|
|
15560
15563
|
contents: [
|
|
15561
15564
|
{
|
|
15562
|
-
|
|
15565
|
+
// Use readUri (not closure variable) so the response URI matches after updates
|
|
15566
|
+
uri: readUri.href,
|
|
15563
15567
|
mimeType: EI,
|
|
15564
15568
|
text: content,
|
|
15565
15569
|
_meta: readMeta
|
|
@@ -15568,20 +15572,22 @@ function createAppServer(config, simulations, viteMode) {
|
|
|
15568
15572
|
};
|
|
15569
15573
|
}
|
|
15570
15574
|
);
|
|
15575
|
+
resourceHandles.set(resourceName, handle);
|
|
15571
15576
|
}
|
|
15572
|
-
|
|
15577
|
+
const fullToolMeta = {
|
|
15578
|
+
...toolMeta,
|
|
15579
|
+
ui: {
|
|
15580
|
+
resourceUri: uri2,
|
|
15581
|
+
// Preserve tool visibility from simulation metadata if declared
|
|
15582
|
+
...toolMeta.ui?.visibility ? { visibility: toolMeta.ui.visibility } : {}
|
|
15583
|
+
}
|
|
15584
|
+
};
|
|
15585
|
+
const toolHandle = hk(
|
|
15573
15586
|
mcpServer,
|
|
15574
15587
|
tool.name,
|
|
15575
15588
|
{
|
|
15576
15589
|
description: tool.description,
|
|
15577
|
-
_meta:
|
|
15578
|
-
...toolMeta,
|
|
15579
|
-
ui: {
|
|
15580
|
-
resourceUri: uri2,
|
|
15581
|
-
// Preserve tool visibility from simulation metadata if declared
|
|
15582
|
-
...toolMeta.ui?.visibility ? { visibility: toolMeta.ui.visibility } : {}
|
|
15583
|
-
}
|
|
15584
|
-
}
|
|
15590
|
+
_meta: fullToolMeta
|
|
15585
15591
|
},
|
|
15586
15592
|
async (extra) => {
|
|
15587
15593
|
const args = extra.request?.params?.arguments ?? {};
|
|
@@ -15602,12 +15608,13 @@ function createAppServer(config, simulations, viteMode) {
|
|
|
15602
15608
|
};
|
|
15603
15609
|
}
|
|
15604
15610
|
);
|
|
15611
|
+
toolHandles.push({ handle: toolHandle, resourceName, toolMeta: fullToolMeta });
|
|
15605
15612
|
}
|
|
15606
|
-
const registeredUris = Array.from(
|
|
15613
|
+
const registeredUris = Array.from(registeredUriSet).join(", ");
|
|
15607
15614
|
console.log(
|
|
15608
15615
|
`[MCP] Registered ${simulations.length} tool(s) and resource(s)${viteMode ? " (vite mode)" : ""}: ${registeredUris}`
|
|
15609
15616
|
);
|
|
15610
|
-
return mcpServer;
|
|
15617
|
+
return { server: mcpServer, resourceHandles, toolHandles };
|
|
15611
15618
|
}
|
|
15612
15619
|
const SESSION_IDLE_TIMEOUT_MS$1 = 5 * 60 * 1e3;
|
|
15613
15620
|
function isLocalConnection(req) {
|
|
@@ -15626,10 +15633,8 @@ const cleanupInterval = setInterval(() => {
|
|
|
15626
15633
|
const now = Date.now();
|
|
15627
15634
|
for (const [id2, session] of sessions) {
|
|
15628
15635
|
if (now - session.lastActivity > SESSION_IDLE_TIMEOUT_MS$1) {
|
|
15629
|
-
|
|
15630
|
-
session.
|
|
15631
|
-
session.server.close();
|
|
15632
|
-
console.log(`[MCP] Session expired: ${id2.substring(0, 8)}... (${sessions.size} active)`);
|
|
15636
|
+
console.log(`[MCP] Session expired: ${id2.substring(0, 8)}...`);
|
|
15637
|
+
void session.server.close();
|
|
15633
15638
|
}
|
|
15634
15639
|
}
|
|
15635
15640
|
}, 6e4);
|
|
@@ -15676,11 +15681,18 @@ async function handleMcpRequest(req, res, config, simulations, viteMode) {
|
|
|
15676
15681
|
}
|
|
15677
15682
|
if (req.method === "POST") {
|
|
15678
15683
|
const isLocal = isLocalConnection(req);
|
|
15679
|
-
const server = createAppServer(config, simulations, viteMode);
|
|
15684
|
+
const { server, resourceHandles, toolHandles } = createAppServer(config, simulations, viteMode);
|
|
15680
15685
|
const transport = new StreamableHTTPServerTransport({
|
|
15681
15686
|
sessionIdGenerator: () => node_crypto.randomUUID(),
|
|
15682
15687
|
onsessioninitialized: (id2) => {
|
|
15683
|
-
sessions.set(id2, {
|
|
15688
|
+
sessions.set(id2, {
|
|
15689
|
+
server,
|
|
15690
|
+
transport,
|
|
15691
|
+
isLocal,
|
|
15692
|
+
lastActivity: Date.now(),
|
|
15693
|
+
resourceHandles,
|
|
15694
|
+
toolHandles
|
|
15695
|
+
});
|
|
15684
15696
|
const origin = isLocal ? "local" : "tunnel";
|
|
15685
15697
|
console.log(
|
|
15686
15698
|
`[MCP] Session started: ${id2.substring(0, 8)}... (${origin}, ${sessions.size} active)`
|
|
@@ -15695,13 +15707,12 @@ async function handleMcpRequest(req, res, config, simulations, viteMode) {
|
|
|
15695
15707
|
const id2 = transport.sessionId;
|
|
15696
15708
|
console.error(`[MCP] Transport error${id2 ? ` (${id2.substring(0, 8)}...)` : ""}:`, error);
|
|
15697
15709
|
};
|
|
15698
|
-
transport.onclose =
|
|
15710
|
+
transport.onclose = () => {
|
|
15699
15711
|
const id2 = transport.sessionId;
|
|
15700
15712
|
if (id2 && sessions.has(id2)) {
|
|
15701
15713
|
sessions.delete(id2);
|
|
15702
15714
|
console.log(`[MCP] Session closed: ${id2.substring(0, 8)}... (${sessions.size} active)`);
|
|
15703
15715
|
}
|
|
15704
|
-
await server.close();
|
|
15705
15716
|
};
|
|
15706
15717
|
await server.connect(transport);
|
|
15707
15718
|
await transport.handleRequest(req, res, parsedBody);
|
|
@@ -15796,16 +15807,24 @@ function runMCPServer(config) {
|
|
|
15796
15807
|
process.on("SIGINT", () => void shutdown());
|
|
15797
15808
|
return {
|
|
15798
15809
|
invalidateResources() {
|
|
15799
|
-
|
|
15810
|
+
if (sessions.size === 0) return;
|
|
15811
|
+
const timestamp = Date.now();
|
|
15800
15812
|
for (const [, session] of sessions) {
|
|
15801
|
-
|
|
15802
|
-
|
|
15803
|
-
|
|
15813
|
+
for (const [name, handle] of session.resourceHandles) {
|
|
15814
|
+
handle.update({ uri: `ui://${name}-${timestamp}` });
|
|
15815
|
+
}
|
|
15816
|
+
for (const { handle, resourceName, toolMeta } of session.toolHandles) {
|
|
15817
|
+
const newUri = `ui://${resourceName}-${timestamp}`;
|
|
15818
|
+
handle.update({
|
|
15819
|
+
_meta: {
|
|
15820
|
+
...toolMeta,
|
|
15821
|
+
ui: { ...toolMeta.ui, resourceUri: newUri },
|
|
15822
|
+
"ui/resourceUri": newUri
|
|
15823
|
+
}
|
|
15824
|
+
});
|
|
15804
15825
|
}
|
|
15805
15826
|
}
|
|
15806
|
-
|
|
15807
|
-
console.log(`[MCP] Notified ${notified} session(s) of resource changes`);
|
|
15808
|
-
}
|
|
15827
|
+
console.log(`[MCP] Cache-busted ${sessions.size} session(s) with timestamp ${timestamp}`);
|
|
15809
15828
|
}
|
|
15810
15829
|
};
|
|
15811
15830
|
}
|
|
@@ -15916,10 +15935,8 @@ function createMcpHandler(config) {
|
|
|
15916
15935
|
const now = Date.now();
|
|
15917
15936
|
for (const [id2, session] of sessions2) {
|
|
15918
15937
|
if (now - session.lastActivity > SESSION_IDLE_TIMEOUT_MS) {
|
|
15919
|
-
|
|
15920
|
-
session.
|
|
15921
|
-
session.server.close();
|
|
15922
|
-
console.log(`[MCP] Session expired: ${id2.substring(0, 8)}... (${sessions2.size} active)`);
|
|
15938
|
+
console.log(`[MCP] Session expired: ${id2.substring(0, 8)}...`);
|
|
15939
|
+
void session.server.close();
|
|
15923
15940
|
}
|
|
15924
15941
|
}
|
|
15925
15942
|
}, 6e4);
|
|
@@ -15997,13 +16014,12 @@ function createMcpHandler(config) {
|
|
|
15997
16014
|
const id2 = transport.sessionId;
|
|
15998
16015
|
console.error(`[MCP] Transport error${id2 ? ` (${id2.substring(0, 8)}...)` : ""}:`, error);
|
|
15999
16016
|
};
|
|
16000
|
-
transport.onclose =
|
|
16017
|
+
transport.onclose = () => {
|
|
16001
16018
|
const id2 = transport.sessionId;
|
|
16002
16019
|
if (id2 && sessions2.has(id2)) {
|
|
16003
16020
|
sessions2.delete(id2);
|
|
16004
16021
|
console.log(`[MCP] Session closed: ${id2.substring(0, 8)}... (${sessions2.size} active)`);
|
|
16005
16022
|
}
|
|
16006
|
-
await server.close();
|
|
16007
16023
|
};
|
|
16008
16024
|
await server.connect(transport);
|
|
16009
16025
|
await transport.handleRequest(req, res, parsedBody);
|
|
@@ -16019,10 +16035,8 @@ function createHandler(config) {
|
|
|
16019
16035
|
const now = Date.now();
|
|
16020
16036
|
for (const [id2, session] of sessions2) {
|
|
16021
16037
|
if (now - session.lastActivity > SESSION_IDLE_TIMEOUT_MS) {
|
|
16022
|
-
|
|
16023
|
-
session.
|
|
16024
|
-
session.server.close();
|
|
16025
|
-
console.log(`[MCP] Session expired: ${id2.substring(0, 8)}... (${sessions2.size} active)`);
|
|
16038
|
+
console.log(`[MCP] Session expired: ${id2.substring(0, 8)}...`);
|
|
16039
|
+
void session.server.close();
|
|
16026
16040
|
}
|
|
16027
16041
|
}
|
|
16028
16042
|
}, 6e4);
|
|
@@ -16077,12 +16091,11 @@ function createHandler(config) {
|
|
|
16077
16091
|
transport.onerror = (error) => {
|
|
16078
16092
|
console.error("[MCP] Transport error:", error);
|
|
16079
16093
|
};
|
|
16080
|
-
transport.onclose =
|
|
16094
|
+
transport.onclose = () => {
|
|
16081
16095
|
const id2 = transport.sessionId;
|
|
16082
16096
|
if (id2 && sessions2.has(id2)) {
|
|
16083
16097
|
sessions2.delete(id2);
|
|
16084
16098
|
}
|
|
16085
|
-
await server.close();
|
|
16086
16099
|
};
|
|
16087
16100
|
await server.connect(transport);
|
|
16088
16101
|
const response = await transport.handleRequest(req, { parsedBody, authInfo });
|