sunpeak 0.16.24 → 0.16.28
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/bin/commands/build.mjs +0 -1
- package/bin/commands/dev.mjs +98 -5
- package/bin/commands/start.mjs +3 -2
- package/bin/lib/live/browser-auth.mjs +53 -17
- package/bin/lib/live/global-setup.mjs +107 -99
- package/bin/lib/live/host-page.mjs +63 -11
- package/bin/lib/live/live-config.mjs +1 -1
- package/bin/lib/sandbox-server.mjs +304 -0
- package/dist/chatgpt/chatgpt-conversation.d.ts +3 -7
- package/dist/chatgpt/globals.css +28 -9
- package/dist/chatgpt/index.cjs +55 -24
- package/dist/chatgpt/index.cjs.map +1 -1
- package/dist/chatgpt/index.js +31 -25
- package/dist/chatgpt/index.js.map +1 -1
- package/dist/chunk-9hOWP6kD.cjs +64 -0
- package/dist/chunk-D6g4UhsZ.js +35 -0
- package/dist/claude/claude-conversation.d.ts +3 -2
- package/dist/claude/index.cjs +4 -4
- package/dist/claude/index.js +3 -5
- package/dist/discovery-BxKCIgG5.cjs +332 -0
- package/dist/discovery-BxKCIgG5.cjs.map +1 -0
- package/dist/discovery-Du4LHrih.js +261 -0
- package/dist/discovery-Du4LHrih.js.map +1 -0
- package/dist/host/chatgpt/index.cjs +171 -65
- package/dist/host/chatgpt/index.cjs.map +1 -1
- package/dist/host/chatgpt/index.js +170 -70
- package/dist/host/chatgpt/index.js.map +1 -1
- package/dist/host/index.cjs +47 -19
- package/dist/host/index.cjs.map +1 -1
- package/dist/host/index.js +47 -24
- package/dist/host/index.js.map +1 -1
- package/dist/index.cjs +3103 -3725
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3026 -3746
- package/dist/index.js.map +1 -1
- package/dist/lib/discovery-cli.cjs +117 -131
- package/dist/lib/discovery-cli.cjs.map +1 -1
- package/dist/lib/discovery-cli.js +107 -111
- package/dist/lib/discovery-cli.js.map +1 -1
- package/dist/mcp/favicon.d.ts +3 -1
- package/dist/mcp/index.cjs +9821 -10270
- package/dist/mcp/index.cjs.map +1 -1
- package/dist/mcp/index.d.ts +2 -2
- package/dist/mcp/index.js +9801 -10268
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/production-server.d.ts +7 -1
- package/dist/mcp/types.d.ts +30 -1
- package/dist/protocol-DJmRaBzO.js +11080 -0
- package/dist/{protocol-DkDHRwOW.cjs.map → protocol-DJmRaBzO.js.map} +1 -1
- package/dist/protocol-jbxhzcnS.cjs +11493 -0
- package/dist/protocol-jbxhzcnS.cjs.map +1 -0
- package/dist/simulator/hosts.d.ts +11 -2
- package/dist/simulator/iframe-resource.d.ts +8 -1
- package/dist/simulator/index.cjs +79 -36
- package/dist/simulator/index.cjs.map +1 -1
- package/dist/simulator/index.js +43 -37
- package/dist/simulator/index.js.map +1 -1
- package/dist/simulator/mcp-app-host.d.ts +17 -0
- package/dist/simulator/sandbox-proxy.d.ts +38 -0
- package/dist/simulator/simulator.d.ts +7 -1
- package/dist/simulator/use-simulator-state.d.ts +2 -4
- package/dist/simulator-BYIH-xqQ.cjs +3701 -0
- package/dist/simulator-BYIH-xqQ.cjs.map +1 -0
- package/dist/simulator-CmgNnWBO.js +3575 -0
- package/dist/simulator-CmgNnWBO.js.map +1 -0
- package/dist/simulator-url-BDGD4vZD.cjs +69 -0
- package/dist/simulator-url-BDGD4vZD.cjs.map +1 -0
- package/dist/simulator-url-Bkxj43yT.js +64 -0
- package/dist/simulator-url-Bkxj43yT.js.map +1 -0
- package/dist/style.css +28 -9
- package/dist/use-app-D2h-aiyr.cjs +940 -0
- package/dist/use-app-D2h-aiyr.cjs.map +1 -0
- package/dist/use-app-X7JbGskk.js +598 -0
- package/dist/use-app-X7JbGskk.js.map +1 -0
- package/package.json +8 -8
- package/template/.sunpeak/dev.tsx +9 -3
- package/template/node_modules/.bin/vite +2 -2
- package/template/node_modules/.bin/vitest +2 -2
- package/template/package.json +5 -5
- package/template/playwright.config.ts +10 -5
- package/template/src/server.ts +16 -2
- package/template/src/tools/show-albums.ts +17 -0
- package/template/tests/e2e/albums.spec.ts +37 -5
- package/template/tests/e2e/carousel.spec.ts +6 -6
- package/template/tests/e2e/global-setup.ts +6 -21
- package/template/tests/e2e/map.spec.ts +11 -11
- package/template/tests/e2e/review.spec.ts +24 -24
- package/dist/claude/index.cjs.map +0 -1
- package/dist/claude/index.js.map +0 -1
- package/dist/discovery-BVqD-JsT.js +0 -224
- package/dist/discovery-BVqD-JsT.js.map +0 -1
- package/dist/discovery-D1gpaVz4.cjs +0 -223
- package/dist/discovery-D1gpaVz4.cjs.map +0 -1
- package/dist/index-B7Qw3Vhh.js +0 -29
- package/dist/index-B7Qw3Vhh.js.map +0 -1
- package/dist/index-BEHP_bM8.js +0 -41
- package/dist/index-BEHP_bM8.js.map +0 -1
- package/dist/index-SfudQ9Y_.cjs +0 -28
- package/dist/index-SfudQ9Y_.cjs.map +0 -1
- package/dist/index-XKHXfBiD.cjs +0 -40
- package/dist/index-XKHXfBiD.cjs.map +0 -1
- package/dist/protocol-DkDHRwOW.cjs +0 -12221
- package/dist/protocol-uge7qFev.js +0 -12223
- package/dist/protocol-uge7qFev.js.map +0 -1
- package/dist/simulator-BCq2iOT-.js +0 -3262
- package/dist/simulator-BCq2iOT-.js.map +0 -1
- package/dist/simulator-DRUsm6IZ.cjs +0 -3277
- package/dist/simulator-DRUsm6IZ.cjs.map +0 -1
- package/dist/simulator-url-DcSYRl-P.cjs +0 -53
- package/dist/simulator-url-DcSYRl-P.cjs.map +0 -1
- package/dist/simulator-url-j_XV3EoP.js +0 -54
- package/dist/simulator-url-j_XV3EoP.js.map +0 -1
- package/dist/use-app-C9gpzIQO.js +0 -349
- package/dist/use-app-C9gpzIQO.js.map +0 -1
- package/dist/use-app-D09O2swh.cjs +0 -348
- package/dist/use-app-D09O2swh.cjs.map +0 -1
|
@@ -9,7 +9,7 @@ for (const host of hosts) {
|
|
|
9
9
|
test('should render review title with correct styles', async ({ page }) => {
|
|
10
10
|
await page.goto(createSimulatorUrl({ simulation: 'review-diff', theme: 'light', host }));
|
|
11
11
|
|
|
12
|
-
const iframe = page.frameLocator('iframe');
|
|
12
|
+
const iframe = page.frameLocator('iframe').frameLocator('iframe');
|
|
13
13
|
const title = iframe.locator('h1:has-text("Refactor Authentication Module")');
|
|
14
14
|
await expect(title).toBeVisible();
|
|
15
15
|
|
|
@@ -27,7 +27,7 @@ for (const host of hosts) {
|
|
|
27
27
|
test('should render change items with type-specific styling', async ({ page }) => {
|
|
28
28
|
await page.goto(createSimulatorUrl({ simulation: 'review-diff', theme: 'light', host }));
|
|
29
29
|
|
|
30
|
-
const iframe = page.frameLocator('iframe');
|
|
30
|
+
const iframe = page.frameLocator('iframe').frameLocator('iframe');
|
|
31
31
|
const changeItem = iframe.locator('li').first();
|
|
32
32
|
await expect(changeItem).toBeVisible();
|
|
33
33
|
|
|
@@ -47,7 +47,7 @@ for (const host of hosts) {
|
|
|
47
47
|
test('should have interactive apply and cancel buttons', async ({ page }) => {
|
|
48
48
|
await page.goto(createSimulatorUrl({ simulation: 'review-diff', theme: 'light', host }));
|
|
49
49
|
|
|
50
|
-
const iframe = page.frameLocator('iframe');
|
|
50
|
+
const iframe = page.frameLocator('iframe').frameLocator('iframe');
|
|
51
51
|
|
|
52
52
|
// Find the Apply Changes button (based on simulation data)
|
|
53
53
|
const applyButton = iframe.locator('button:has-text("Apply Changes")');
|
|
@@ -84,7 +84,7 @@ for (const host of hosts) {
|
|
|
84
84
|
})
|
|
85
85
|
);
|
|
86
86
|
|
|
87
|
-
const iframe = page.frameLocator('iframe');
|
|
87
|
+
const iframe = page.frameLocator('iframe').frameLocator('iframe');
|
|
88
88
|
const expandButton = iframe.locator('button[aria-label="Enter fullscreen"]');
|
|
89
89
|
await expect(expandButton).toBeVisible();
|
|
90
90
|
|
|
@@ -168,7 +168,7 @@ for (const host of hosts) {
|
|
|
168
168
|
test('should render review title with correct styles', async ({ page }) => {
|
|
169
169
|
await page.goto(createSimulatorUrl({ simulation: 'review-diff', theme: 'dark', host }));
|
|
170
170
|
|
|
171
|
-
const iframe = page.frameLocator('iframe');
|
|
171
|
+
const iframe = page.frameLocator('iframe').frameLocator('iframe');
|
|
172
172
|
const title = iframe.locator('h1:has-text("Refactor Authentication Module")');
|
|
173
173
|
await expect(title).toBeVisible();
|
|
174
174
|
});
|
|
@@ -176,7 +176,7 @@ for (const host of hosts) {
|
|
|
176
176
|
test('should have appropriate text colors for dark mode', async ({ page }) => {
|
|
177
177
|
await page.goto(createSimulatorUrl({ simulation: 'review-diff', theme: 'dark', host }));
|
|
178
178
|
|
|
179
|
-
const iframe = page.frameLocator('iframe');
|
|
179
|
+
const iframe = page.frameLocator('iframe').frameLocator('iframe');
|
|
180
180
|
const title = iframe.locator('h1').first();
|
|
181
181
|
await expect(title).toBeVisible();
|
|
182
182
|
|
|
@@ -194,7 +194,7 @@ for (const host of hosts) {
|
|
|
194
194
|
test('should render change items in dark mode', async ({ page }) => {
|
|
195
195
|
await page.goto(createSimulatorUrl({ simulation: 'review-diff', theme: 'dark', host }));
|
|
196
196
|
|
|
197
|
-
const iframe = page.frameLocator('iframe');
|
|
197
|
+
const iframe = page.frameLocator('iframe').frameLocator('iframe');
|
|
198
198
|
const changeItem = iframe.locator('li').first();
|
|
199
199
|
await expect(changeItem).toBeVisible();
|
|
200
200
|
});
|
|
@@ -210,7 +210,7 @@ for (const host of hosts) {
|
|
|
210
210
|
await page.goto(createSimulatorUrl({ simulation: 'review-diff', theme: 'dark', host }));
|
|
211
211
|
|
|
212
212
|
// Wait for iframe content to render
|
|
213
|
-
const iframe = page.frameLocator('iframe');
|
|
213
|
+
const iframe = page.frameLocator('iframe').frameLocator('iframe');
|
|
214
214
|
await expect(iframe.locator('h1').first()).toBeVisible();
|
|
215
215
|
|
|
216
216
|
// Filter out expected iframe/MCP handshake errors
|
|
@@ -236,7 +236,7 @@ for (const host of hosts) {
|
|
|
236
236
|
})
|
|
237
237
|
);
|
|
238
238
|
|
|
239
|
-
const iframe = page.frameLocator('iframe');
|
|
239
|
+
const iframe = page.frameLocator('iframe').frameLocator('iframe');
|
|
240
240
|
// Wait for content to render first
|
|
241
241
|
await expect(iframe.locator('h1').first()).toBeVisible();
|
|
242
242
|
|
|
@@ -260,7 +260,7 @@ for (const host of hosts) {
|
|
|
260
260
|
await expect(root).not.toBeEmpty();
|
|
261
261
|
|
|
262
262
|
// Title should be visible inside the iframe
|
|
263
|
-
const iframe = page.frameLocator('iframe');
|
|
263
|
+
const iframe = page.frameLocator('iframe').frameLocator('iframe');
|
|
264
264
|
const title = iframe.locator('h1');
|
|
265
265
|
await expect(title).toBeVisible();
|
|
266
266
|
});
|
|
@@ -275,7 +275,7 @@ for (const host of hosts) {
|
|
|
275
275
|
})
|
|
276
276
|
);
|
|
277
277
|
|
|
278
|
-
const iframe = page.frameLocator('iframe');
|
|
278
|
+
const iframe = page.frameLocator('iframe').frameLocator('iframe');
|
|
279
279
|
// Content sections should be visible in fullscreen
|
|
280
280
|
const title = iframe.locator('h1');
|
|
281
281
|
await expect(title).toBeVisible();
|
|
@@ -315,15 +315,15 @@ for (const host of hosts) {
|
|
|
315
315
|
})
|
|
316
316
|
);
|
|
317
317
|
|
|
318
|
-
const iframe = page.frameLocator('iframe');
|
|
318
|
+
const iframe = page.frameLocator('iframe').frameLocator('iframe');
|
|
319
319
|
const publishButton = iframe.locator('button:has-text("Publish")');
|
|
320
320
|
await expect(publishButton).toBeVisible();
|
|
321
321
|
await publishButton.click();
|
|
322
322
|
|
|
323
323
|
// Should show the server's success message from serverTools mock
|
|
324
|
-
await expect(iframe.locator('text=Completed.')).toBeVisible();
|
|
324
|
+
await expect(iframe.locator('text=Completed.')).toBeVisible({ timeout: 10000 });
|
|
325
325
|
// Should also show what button was pressed
|
|
326
|
-
await expect(iframe.locator('text=Publishing post...')).toBeVisible();
|
|
326
|
+
await expect(iframe.locator('text=Publishing post...')).toBeVisible({ timeout: 10000 });
|
|
327
327
|
});
|
|
328
328
|
|
|
329
329
|
test('should show server cancel message when rejecting', async ({ page }) => {
|
|
@@ -335,13 +335,13 @@ for (const host of hosts) {
|
|
|
335
335
|
})
|
|
336
336
|
);
|
|
337
337
|
|
|
338
|
-
const iframe = page.frameLocator('iframe');
|
|
338
|
+
const iframe = page.frameLocator('iframe').frameLocator('iframe');
|
|
339
339
|
const cancelButton = iframe.locator('button:has-text("Cancel")');
|
|
340
340
|
await expect(cancelButton).toBeVisible();
|
|
341
341
|
await cancelButton.click();
|
|
342
342
|
|
|
343
343
|
// Server returned cancelled status via serverTools when condition
|
|
344
|
-
await expect(iframe.locator('text=Cancelled.')).toBeVisible();
|
|
344
|
+
await expect(iframe.locator('text=Cancelled.')).toBeVisible({ timeout: 10000 });
|
|
345
345
|
});
|
|
346
346
|
});
|
|
347
347
|
|
|
@@ -375,14 +375,14 @@ for (const host of hosts) {
|
|
|
375
375
|
})
|
|
376
376
|
);
|
|
377
377
|
|
|
378
|
-
const iframe = page.frameLocator('iframe');
|
|
378
|
+
const iframe = page.frameLocator('iframe').frameLocator('iframe');
|
|
379
379
|
const placeOrderButton = iframe.locator('button:has-text("Place Order")');
|
|
380
380
|
await expect(placeOrderButton).toBeVisible();
|
|
381
381
|
await placeOrderButton.click();
|
|
382
382
|
|
|
383
383
|
// After server responds, should show what the user clicked and the server result
|
|
384
|
-
await expect(iframe.locator('text=Placing order...')).toBeVisible();
|
|
385
|
-
await expect(iframe.locator('text=Completed.')).toBeVisible();
|
|
384
|
+
await expect(iframe.locator('text=Placing order...')).toBeVisible({ timeout: 10000 });
|
|
385
|
+
await expect(iframe.locator('text=Completed.')).toBeVisible({ timeout: 10000 });
|
|
386
386
|
});
|
|
387
387
|
});
|
|
388
388
|
|
|
@@ -396,14 +396,14 @@ for (const host of hosts) {
|
|
|
396
396
|
})
|
|
397
397
|
);
|
|
398
398
|
|
|
399
|
-
const iframe = page.frameLocator('iframe');
|
|
399
|
+
const iframe = page.frameLocator('iframe').frameLocator('iframe');
|
|
400
400
|
const applyButton = iframe.locator('button:has-text("Apply Changes")');
|
|
401
401
|
await expect(applyButton).toBeVisible();
|
|
402
402
|
await applyButton.click();
|
|
403
403
|
|
|
404
404
|
// Should show the decision label and server response
|
|
405
|
-
await expect(iframe.locator('text=Applying changes...')).toBeVisible();
|
|
406
|
-
await expect(iframe.locator('text=Completed.')).toBeVisible();
|
|
405
|
+
await expect(iframe.locator('text=Applying changes...')).toBeVisible({ timeout: 10000 });
|
|
406
|
+
await expect(iframe.locator('text=Completed.')).toBeVisible({ timeout: 10000 });
|
|
407
407
|
});
|
|
408
408
|
|
|
409
409
|
test('should cancel review-diff and show server cancelled', async ({ page }) => {
|
|
@@ -415,13 +415,13 @@ for (const host of hosts) {
|
|
|
415
415
|
})
|
|
416
416
|
);
|
|
417
417
|
|
|
418
|
-
const iframe = page.frameLocator('iframe');
|
|
418
|
+
const iframe = page.frameLocator('iframe').frameLocator('iframe');
|
|
419
419
|
const cancelButton = iframe.locator('button:has-text("Cancel")');
|
|
420
420
|
await expect(cancelButton).toBeVisible();
|
|
421
421
|
await cancelButton.click();
|
|
422
422
|
|
|
423
423
|
// Server returned cancelled status via when condition matching
|
|
424
|
-
await expect(iframe.locator('text=Cancelled.')).toBeVisible();
|
|
424
|
+
await expect(iframe.locator('text=Cancelled.')).toBeVisible({ timeout: 10000 });
|
|
425
425
|
});
|
|
426
426
|
});
|
|
427
427
|
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
package/dist/claude/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
function toPascalCase(str) {
|
|
2
|
-
return str.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
3
|
-
}
|
|
4
|
-
function extractResourceKey(path) {
|
|
5
|
-
const match = path.match(/([^/]+)\.tsx$/);
|
|
6
|
-
return match ? match[1] : void 0;
|
|
7
|
-
}
|
|
8
|
-
function extractSimulationKey(path) {
|
|
9
|
-
const match = path.match(/([^/]+)\.json$/);
|
|
10
|
-
return match ? match[1] : void 0;
|
|
11
|
-
}
|
|
12
|
-
function findResourceKey(simulationKey, resourceKeys) {
|
|
13
|
-
const sorted = [...resourceKeys].sort((a, b) => b.length - a.length);
|
|
14
|
-
for (const resourceKey of sorted) {
|
|
15
|
-
if (simulationKey === resourceKey || simulationKey.startsWith(resourceKey + "-")) {
|
|
16
|
-
return resourceKey;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
return void 0;
|
|
20
|
-
}
|
|
21
|
-
function getComponentName(resourceKey) {
|
|
22
|
-
return `${toPascalCase(resourceKey)}Resource`;
|
|
23
|
-
}
|
|
24
|
-
function createResourceExports(modules) {
|
|
25
|
-
const resources = {};
|
|
26
|
-
for (const [path, module] of Object.entries(modules)) {
|
|
27
|
-
const key = extractResourceKey(path);
|
|
28
|
-
if (!key) continue;
|
|
29
|
-
const exportName = getComponentName(key);
|
|
30
|
-
const mod = module;
|
|
31
|
-
const component = mod.default ?? mod[exportName];
|
|
32
|
-
if (component && (typeof component === "function" || typeof component === "object")) {
|
|
33
|
-
resources[exportName] = component;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return resources;
|
|
37
|
-
}
|
|
38
|
-
function buildResourceMap(modules) {
|
|
39
|
-
const map = /* @__PURE__ */ new Map();
|
|
40
|
-
for (const [path, module] of Object.entries(modules)) {
|
|
41
|
-
const key = extractResourceKey(path);
|
|
42
|
-
if (key) {
|
|
43
|
-
map.set(key, module.resource);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return map;
|
|
47
|
-
}
|
|
48
|
-
function buildSimulations(options) {
|
|
49
|
-
const {
|
|
50
|
-
simulationModules,
|
|
51
|
-
resourcesMap,
|
|
52
|
-
resourceComponents,
|
|
53
|
-
createSimulation,
|
|
54
|
-
onMissingResource = (key, prefix) => console.warn(
|
|
55
|
-
`No matching resource found for simulation "${key}". Expected a resource file like src/resources/${prefix}/${prefix}.tsx`
|
|
56
|
-
)
|
|
57
|
-
} = options;
|
|
58
|
-
const resourceKeys = Array.from(resourcesMap.keys());
|
|
59
|
-
const simulations = {};
|
|
60
|
-
for (const [path, module] of Object.entries(simulationModules)) {
|
|
61
|
-
const simulationKey = extractSimulationKey(path);
|
|
62
|
-
if (!simulationKey) continue;
|
|
63
|
-
const simulationData = module.default;
|
|
64
|
-
const resourceKey = findResourceKey(simulationKey, resourceKeys);
|
|
65
|
-
if (!resourceKey) {
|
|
66
|
-
onMissingResource(simulationKey, simulationKey.split("-")[0]);
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
const resource = resourcesMap.get(resourceKey);
|
|
70
|
-
const componentName = getComponentName(resourceKey);
|
|
71
|
-
const resourceComponent = resourceComponents[componentName];
|
|
72
|
-
if (!resourceComponent) {
|
|
73
|
-
console.warn(
|
|
74
|
-
`Resource component "${componentName}" not found for resource "${resourceKey}". Make sure src/resources/${resourceKey}/${resourceKey}.tsx exists with a default export.`
|
|
75
|
-
);
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
simulations[simulationKey] = createSimulation(
|
|
79
|
-
simulationKey,
|
|
80
|
-
simulationData,
|
|
81
|
-
resource,
|
|
82
|
-
resourceComponent
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
return simulations;
|
|
86
|
-
}
|
|
87
|
-
function buildDevSimulations(options) {
|
|
88
|
-
const { simulationModules, resourceComponents, toolModules, resourceModules } = options;
|
|
89
|
-
const resourceMetaByName = /* @__PURE__ */ new Map();
|
|
90
|
-
const resourceKeyByName = /* @__PURE__ */ new Map();
|
|
91
|
-
for (const [path, module] of Object.entries(resourceModules)) {
|
|
92
|
-
const key = extractResourceKey(path);
|
|
93
|
-
if (!key) continue;
|
|
94
|
-
const mod = module;
|
|
95
|
-
if (mod.resource) {
|
|
96
|
-
const name = mod.resource.name ?? key;
|
|
97
|
-
resourceMetaByName.set(name, { ...mod.resource, name });
|
|
98
|
-
resourceKeyByName.set(name, key);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
const toolsMap = /* @__PURE__ */ new Map();
|
|
102
|
-
if (toolModules) {
|
|
103
|
-
for (const [path, module] of Object.entries(toolModules)) {
|
|
104
|
-
const nameMatch = path.match(/([^/]+)\.ts$/);
|
|
105
|
-
if (!nameMatch) continue;
|
|
106
|
-
const mod = module;
|
|
107
|
-
if (mod.tool) {
|
|
108
|
-
const resourceName = mod.tool.resource;
|
|
109
|
-
toolsMap.set(nameMatch[1], { tool: mod.tool, resourceName });
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
const simulations = {};
|
|
114
|
-
for (const [path, module] of Object.entries(simulationModules)) {
|
|
115
|
-
const simKey = extractSimulationKey(path);
|
|
116
|
-
if (!simKey) continue;
|
|
117
|
-
const simulationData = module.default;
|
|
118
|
-
const toolName = typeof simulationData.tool === "string" ? simulationData.tool : simKey;
|
|
119
|
-
const toolInfo = toolsMap.get(toolName);
|
|
120
|
-
if (!toolInfo) {
|
|
121
|
-
console.warn(
|
|
122
|
-
`Tool "${toolName}" not found for simulation "${simKey}". Make sure src/tools/${toolName}.ts exists.`
|
|
123
|
-
);
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
const resourceMeta = toolInfo.resourceName ? resourceMetaByName.get(toolInfo.resourceName) : void 0;
|
|
127
|
-
const resourceKey = toolInfo.resourceName ? resourceKeyByName.get(toolInfo.resourceName) : void 0;
|
|
128
|
-
if (toolInfo.resourceName && (!resourceMeta || !resourceKey)) {
|
|
129
|
-
console.warn(
|
|
130
|
-
`Resource "${toolInfo.resourceName}" not found for tool "${toolName}". Make sure a resource with name "${toolInfo.resourceName}" exists in src/resources/.`
|
|
131
|
-
);
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
let resourceBlock = {};
|
|
135
|
-
if (resourceKey && resourceMeta) {
|
|
136
|
-
const componentName = getComponentName(resourceKey);
|
|
137
|
-
const resourceComponent = resourceComponents[componentName];
|
|
138
|
-
if (!resourceComponent) {
|
|
139
|
-
console.warn(`Resource component "${componentName}" not found for tool "${toolName}".`);
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
142
|
-
resourceBlock = {
|
|
143
|
-
resource: {
|
|
144
|
-
uri: `ui://${resourceKey}`,
|
|
145
|
-
name: resourceKey,
|
|
146
|
-
...resourceMeta.title != null ? { title: resourceMeta.title } : {},
|
|
147
|
-
...resourceMeta.description != null ? { description: resourceMeta.description } : {},
|
|
148
|
-
...resourceMeta.mimeType != null ? { mimeType: resourceMeta.mimeType } : {},
|
|
149
|
-
...resourceMeta._meta != null ? { _meta: resourceMeta._meta } : {}
|
|
150
|
-
},
|
|
151
|
-
resourceUrl: `/.sunpeak/resource-loader.html?component=${componentName}`
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
simulations[simKey] = {
|
|
155
|
-
name: simKey,
|
|
156
|
-
userMessage: simulationData.userMessage,
|
|
157
|
-
tool: {
|
|
158
|
-
name: toolName,
|
|
159
|
-
description: toolInfo.tool.description ?? "",
|
|
160
|
-
inputSchema: { type: "object" },
|
|
161
|
-
...toolInfo.tool.title != null ? { title: toolInfo.tool.title } : {},
|
|
162
|
-
...toolInfo.tool.annotations != null ? { annotations: toolInfo.tool.annotations } : {},
|
|
163
|
-
...toolInfo.tool._meta != null ? { _meta: toolInfo.tool._meta } : {}
|
|
164
|
-
},
|
|
165
|
-
...resourceBlock,
|
|
166
|
-
toolInput: simulationData.toolInput,
|
|
167
|
-
toolResult: simulationData.toolResult,
|
|
168
|
-
serverTools: simulationData.serverTools
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
return simulations;
|
|
172
|
-
}
|
|
173
|
-
function findResourceDirs(baseDir, filePattern, fs) {
|
|
174
|
-
if (!fs.existsSync(baseDir)) {
|
|
175
|
-
return [];
|
|
176
|
-
}
|
|
177
|
-
const entries = fs.readdirSync(baseDir, { withFileTypes: true });
|
|
178
|
-
return entries.filter((entry) => entry.isDirectory()).map((entry) => {
|
|
179
|
-
const key = entry.name;
|
|
180
|
-
const dir = `${baseDir}/${key}`;
|
|
181
|
-
const resourcePath = `${dir}/${filePattern(key)}`;
|
|
182
|
-
if (!fs.existsSync(resourcePath)) {
|
|
183
|
-
return null;
|
|
184
|
-
}
|
|
185
|
-
return { key, dir, resourcePath };
|
|
186
|
-
}).filter((info) => info !== null);
|
|
187
|
-
}
|
|
188
|
-
function findToolFiles(toolsDir, fs) {
|
|
189
|
-
if (!fs.existsSync(toolsDir)) {
|
|
190
|
-
return [];
|
|
191
|
-
}
|
|
192
|
-
const entries = fs.readdirSync(toolsDir, { withFileTypes: true });
|
|
193
|
-
return entries.filter(
|
|
194
|
-
(entry) => !entry.isDirectory() && entry.name.endsWith(".ts") && !entry.name.endsWith(".test.ts")
|
|
195
|
-
).map((entry) => ({
|
|
196
|
-
name: entry.name.replace(/\.ts$/, ""),
|
|
197
|
-
path: `${toolsDir}/${entry.name}`
|
|
198
|
-
}));
|
|
199
|
-
}
|
|
200
|
-
function findSimulationFilesFlat(simulationsDir, fs) {
|
|
201
|
-
if (!fs.existsSync(simulationsDir)) {
|
|
202
|
-
return [];
|
|
203
|
-
}
|
|
204
|
-
const entries = fs.readdirSync(simulationsDir, { withFileTypes: true });
|
|
205
|
-
return entries.filter((entry) => !entry.isDirectory() && entry.name.endsWith(".json")).map((entry) => ({
|
|
206
|
-
name: entry.name.replace(/\.json$/, ""),
|
|
207
|
-
path: `${simulationsDir}/${entry.name}`
|
|
208
|
-
}));
|
|
209
|
-
}
|
|
210
|
-
export {
|
|
211
|
-
buildResourceMap as a,
|
|
212
|
-
buildDevSimulations as b,
|
|
213
|
-
buildSimulations as c,
|
|
214
|
-
createResourceExports as d,
|
|
215
|
-
extractResourceKey as e,
|
|
216
|
-
extractSimulationKey as f,
|
|
217
|
-
findResourceDirs as g,
|
|
218
|
-
findResourceKey as h,
|
|
219
|
-
getComponentName as i,
|
|
220
|
-
findSimulationFilesFlat as j,
|
|
221
|
-
findToolFiles as k,
|
|
222
|
-
toPascalCase as t
|
|
223
|
-
};
|
|
224
|
-
//# sourceMappingURL=discovery-BVqD-JsT.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"discovery-BVqD-JsT.js","sources":["../src/lib/discovery.ts"],"sourcesContent":["/**\n * Discovery utilities for auto-discovering resources and simulations\n *\n * These helpers process the results of import.meta.glob() calls to extract\n * keys, build component maps, and connect simulations to resources.\n *\n * The glob calls themselves must remain in the template (Vite compile-time),\n * but all the processing logic lives here for easy updates across templates.\n *\n * Node.js utilities (findResourceDirs, findToolFiles, etc.) can be used\n * by CLI commands for build-time and runtime discovery.\n */\n\nimport type { Simulation } from '../types/simulation.js';\n\n/**\n * Convert a kebab-case string to PascalCase\n * @example toPascalCase('review') // 'Review'\n * @example toPascalCase('album-art') // 'AlbumArt'\n */\nexport function toPascalCase(str: string): string {\n return str\n .split('-')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join('');\n}\n\n/**\n * Extract the resource key from a resource file path.\n * Matches {name}.tsx (e.g., './albums/albums.tsx' → 'albums')\n */\nexport function extractResourceKey(path: string): string | undefined {\n const match = path.match(/([^/]+)\\.tsx$/);\n return match ? match[1] : undefined;\n}\n\n/**\n * Extract the simulation key from a simulation file path.\n * Matches any *.json file (e.g., './show-albums.json' → 'show-albums')\n */\nexport function extractSimulationKey(path: string): string | undefined {\n const match = path.match(/([^/]+)\\.json$/);\n return match ? match[1] : undefined;\n}\n\n/**\n * Find the best matching resource key for a simulation key.\n * Matches the longest resource name that is a prefix of the simulation key.\n * @example findResourceKey('review-diff', ['review', 'carousel']) // 'review'\n * @example findResourceKey('albums', ['albums', 'review']) // 'albums'\n */\nexport function findResourceKey(simulationKey: string, resourceKeys: string[]): string | undefined {\n // Sort by length descending to find longest match first\n const sorted = [...resourceKeys].sort((a, b) => b.length - a.length);\n for (const resourceKey of sorted) {\n if (simulationKey === resourceKey || simulationKey.startsWith(resourceKey + '-')) {\n return resourceKey;\n }\n }\n return undefined;\n}\n\n/**\n * Get the expected component export name for a resource\n * @example getComponentName('review') // 'ReviewResource'\n * @example getComponentName('album-art') // 'AlbumArtResource'\n */\nexport function getComponentName(resourceKey: string): string {\n return `${toPascalCase(resourceKey)}Resource`;\n}\n\n// --- Glob processing helpers ---\n\ntype GlobModules = Record<string, unknown>;\n\n/**\n * Process resource component modules from import.meta.glob() result.\n * Extracts components and exports them with PascalCase names.\n *\n * @example\n * const modules = import.meta.glob('./*\\/*.tsx', { eager: true });\n * export default createResourceExports(modules);\n */\nexport function createResourceExports(modules: GlobModules): Record<string, React.ComponentType> {\n const resources: Record<string, React.ComponentType> = {};\n\n for (const [path, module] of Object.entries(modules)) {\n const key = extractResourceKey(path);\n if (!key) continue;\n\n const exportName = getComponentName(key);\n const mod = module as Record<string, unknown>;\n\n // Try default export first, then named export matching the expected name\n const component = mod.default ?? mod[exportName];\n\n // Accept functions (regular components) or objects (forwardRef/memo components)\n if (component && (typeof component === 'function' || typeof component === 'object')) {\n resources[exportName] = component as React.ComponentType;\n }\n }\n\n return resources;\n}\n\n/**\n * Build a resource metadata map from import.meta.glob() result.\n * Used for connecting simulations to their resource definitions.\n *\n * @example\n * const modules = import.meta.glob('../src/resources/*\\/*.tsx', { eager: true });\n * const resourcesMap = buildResourceMap(modules);\n */\nexport function buildResourceMap<T>(modules: GlobModules): Map<string, T> {\n const map = new Map<string, T>();\n\n for (const [path, module] of Object.entries(modules)) {\n const key = extractResourceKey(path);\n if (key) {\n map.set(key, (module as { resource: T }).resource);\n }\n }\n\n return map;\n}\n\n/**\n * Options for building simulations from discovered modules\n */\nexport interface BuildSimulationsOptions<TResource, TSimulation> {\n /** Glob result of simulation JSON files */\n simulationModules: GlobModules;\n /** Map of resource key -> resource metadata */\n resourcesMap: Map<string, TResource>;\n /** Map of component name -> React component */\n resourceComponents: Record<string, React.ComponentType>;\n /** Create the final simulation object */\n createSimulation: (\n simulationKey: string,\n simulationData: unknown,\n resource: TResource,\n resourceComponent: React.ComponentType\n ) => TSimulation;\n /** Optional warning handler for missing resources */\n onMissingResource?: (simulationKey: string, expectedPrefix: string) => void;\n}\n\n/**\n * Build simulations by connecting simulation data with resources and components.\n * This is the main orchestration function for dev server bootstrap.\n */\nexport function buildSimulations<TResource, TSimulation>(\n options: BuildSimulationsOptions<TResource, TSimulation>\n): Record<string, TSimulation> {\n const {\n simulationModules,\n resourcesMap,\n resourceComponents,\n createSimulation,\n onMissingResource = (key, prefix) =>\n console.warn(\n `No matching resource found for simulation \"${key}\". ` +\n `Expected a resource file like src/resources/${prefix}/${prefix}.tsx`\n ),\n } = options;\n\n const resourceKeys = Array.from(resourcesMap.keys());\n const simulations: Record<string, TSimulation> = {};\n\n for (const [path, module] of Object.entries(simulationModules)) {\n const simulationKey = extractSimulationKey(path);\n if (!simulationKey) continue;\n\n const simulationData = (module as { default: unknown }).default;\n\n // Find matching resource\n const resourceKey = findResourceKey(simulationKey, resourceKeys);\n if (!resourceKey) {\n onMissingResource(simulationKey, simulationKey.split('-')[0]);\n continue;\n }\n\n const resource = resourcesMap.get(resourceKey)!;\n\n // Get component\n const componentName = getComponentName(resourceKey);\n const resourceComponent = resourceComponents[componentName];\n\n if (!resourceComponent) {\n console.warn(\n `Resource component \"${componentName}\" not found for resource \"${resourceKey}\". ` +\n `Make sure src/resources/${resourceKey}/${resourceKey}.tsx exists with a default export.`\n );\n continue;\n }\n\n simulations[simulationKey] = createSimulation(\n simulationKey,\n simulationData,\n resource,\n resourceComponent\n );\n }\n\n return simulations;\n}\n\n// --- Dev server helpers ---\n\n/**\n * Resource metadata from resource .tsx files\n */\nexport interface ResourceMetadata {\n name: string;\n [key: string]: unknown;\n}\n\n/**\n * Options for building dev simulations\n */\nexport interface BuildDevSimulationsOptions {\n /** Glob result of simulation JSON files */\n simulationModules: GlobModules;\n /** Resource components map from src/resources/index.ts */\n resourceComponents: Record<string, React.ComponentType>;\n /** Glob result of tool files: import.meta.glob('src/tools/*.ts', { eager: true }) */\n toolModules: GlobModules;\n /** Glob result of resource .tsx files from src/resources/ */\n resourceModules: GlobModules;\n}\n\n/**\n * Tool metadata extracted from a tool module's `tool` export\n */\ninterface ToolModuleInfo {\n tool: Record<string, unknown>;\n /** Resource name string from tool.resource (undefined for tools without UI) */\n resourceName?: string;\n}\n\n/**\n * Build simulations for the dev server from glob results.\n * Simulation JSON has `\"tool\": \"tool-name\"` string referencing a tool file.\n * Tool files have `resource: 'name'` linking to a resource discovered from resourceModules.\n */\nexport function buildDevSimulations(\n options: BuildDevSimulationsOptions\n): Record<string, Simulation> {\n const { simulationModules, resourceComponents, toolModules, resourceModules } = options;\n\n // Build resource metadata map from resource modules (keyed by resource name)\n const resourceMetaByName = new Map<string, ResourceMetadata>();\n const resourceKeyByName = new Map<string, string>();\n for (const [path, module] of Object.entries(resourceModules)) {\n const key = extractResourceKey(path);\n if (!key) continue;\n const mod = module as { resource?: ResourceMetadata };\n if (mod.resource) {\n // Use explicit name if provided, otherwise derive from directory key\n const name = mod.resource.name ?? key;\n resourceMetaByName.set(name, { ...mod.resource, name });\n resourceKeyByName.set(name, key);\n }\n }\n\n // Build tool map from tool modules\n const toolsMap = new Map<string, ToolModuleInfo>();\n if (toolModules) {\n for (const [path, module] of Object.entries(toolModules)) {\n const nameMatch = path.match(/([^/]+)\\.ts$/);\n if (!nameMatch) continue;\n const mod = module as { tool?: Record<string, unknown> };\n if (mod.tool) {\n const resourceName = mod.tool.resource as string | undefined;\n toolsMap.set(nameMatch[1], { tool: mod.tool, resourceName });\n }\n }\n }\n\n const simulations: Record<string, Simulation> = {};\n\n for (const [path, module] of Object.entries(simulationModules)) {\n const simKey = extractSimulationKey(path);\n if (!simKey) continue;\n\n const simulationData = (module as { default: Record<string, unknown> }).default;\n\n const toolName =\n typeof simulationData.tool === 'string' ? (simulationData.tool as string) : simKey;\n const toolInfo = toolsMap.get(toolName);\n if (!toolInfo) {\n console.warn(\n `Tool \"${toolName}\" not found for simulation \"${simKey}\". ` +\n `Make sure src/tools/${toolName}.ts exists.`\n );\n continue;\n }\n\n // Look up resource metadata by name (if tool has a UI)\n const resourceMeta = toolInfo.resourceName\n ? resourceMetaByName.get(toolInfo.resourceName)\n : undefined;\n const resourceKey = toolInfo.resourceName\n ? resourceKeyByName.get(toolInfo.resourceName)\n : undefined;\n\n if (toolInfo.resourceName && (!resourceMeta || !resourceKey)) {\n console.warn(\n `Resource \"${toolInfo.resourceName}\" not found for tool \"${toolName}\". ` +\n `Make sure a resource with name \"${toolInfo.resourceName}\" exists in src/resources/.`\n );\n continue;\n }\n\n // Build resource block only for UI tools\n let resourceBlock: Pick<Simulation, 'resource' | 'resourceUrl'> = {};\n if (resourceKey && resourceMeta) {\n const componentName = getComponentName(resourceKey);\n const resourceComponent = resourceComponents[componentName];\n\n if (!resourceComponent) {\n console.warn(`Resource component \"${componentName}\" not found for tool \"${toolName}\".`);\n continue;\n }\n\n resourceBlock = {\n resource: {\n uri: `ui://${resourceKey}`,\n name: resourceKey,\n ...(resourceMeta.title != null ? { title: resourceMeta.title as string } : {}),\n ...(resourceMeta.description != null\n ? { description: resourceMeta.description as string }\n : {}),\n ...(resourceMeta.mimeType != null ? { mimeType: resourceMeta.mimeType as string } : {}),\n ...(resourceMeta._meta != null\n ? { _meta: resourceMeta._meta as Record<string, unknown> }\n : {}),\n },\n resourceUrl: `/.sunpeak/resource-loader.html?component=${componentName}`,\n };\n }\n\n simulations[simKey] = {\n name: simKey,\n userMessage: simulationData.userMessage as string | undefined,\n tool: {\n name: toolName,\n description: (toolInfo.tool.description as string) ?? '',\n inputSchema: { type: 'object' as const },\n ...(toolInfo.tool.title != null ? { title: toolInfo.tool.title as string } : {}),\n ...(toolInfo.tool.annotations != null\n ? { annotations: toolInfo.tool.annotations as Record<string, unknown> }\n : {}),\n ...(toolInfo.tool._meta != null\n ? { _meta: toolInfo.tool._meta as Record<string, unknown> }\n : {}),\n },\n ...resourceBlock,\n toolInput: simulationData.toolInput as Record<string, unknown> | undefined,\n toolResult: simulationData.toolResult as Simulation['toolResult'],\n serverTools: simulationData.serverTools as Simulation['serverTools'],\n };\n }\n\n return simulations;\n}\n\n// --- Node.js utilities for CLI commands ---\n// These utilities use standard Node.js APIs and can be imported by build/push/mcp commands.\n\n/**\n * Information about a discovered resource directory\n */\nexport interface ResourceDirInfo {\n /** Resource key (directory name), e.g., 'albums', 'carousel' */\n key: string;\n /** Full path to the resource directory */\n dir: string;\n /** Full path to the main resource file (tsx or json depending on context) */\n resourcePath: string;\n}\n\n/**\n * File system operations interface for dependency injection in tests\n */\nexport interface FsOps {\n readdirSync: (\n path: string,\n options: { withFileTypes: true }\n ) => Array<{ name: string; isDirectory: () => boolean }>;\n existsSync: (path: string) => boolean;\n}\n\n/**\n * Find all resource directories in a base directory.\n * Each valid resource directory contains a file matching the expected pattern.\n *\n * @param baseDir - Base directory to scan (e.g., 'src/resources' or 'dist')\n * @param filePattern - Function to generate expected filename from resource key\n * @param fs - File system operations (for testing)\n *\n * @example\n * // Find source resources (tsx files)\n * const resources = findResourceDirs('src/resources', key => `${key}.tsx`);\n *\n * @example\n * // Find built resources (js files)\n * const resources = findResourceDirs('dist', key => `${key}.js`);\n */\nexport function findResourceDirs(\n baseDir: string,\n filePattern: (key: string) => string,\n fs: FsOps\n): ResourceDirInfo[] {\n if (!fs.existsSync(baseDir)) {\n return [];\n }\n\n const entries = fs.readdirSync(baseDir, { withFileTypes: true });\n\n return entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => {\n const key = entry.name;\n const dir = `${baseDir}/${key}`;\n const resourcePath = `${dir}/${filePattern(key)}`;\n\n if (!fs.existsSync(resourcePath)) {\n return null;\n }\n\n return { key, dir, resourcePath };\n })\n .filter((info): info is ResourceDirInfo => info !== null);\n}\n\n// --- Tool files + flat simulations discovery ---\n\n/**\n * Information about a discovered tool file\n */\nexport interface ToolFileInfo {\n /** Tool name derived from filename (e.g., 'show-albums') */\n name: string;\n /** Full path to the tool file */\n path: string;\n}\n\n/**\n * Find all tool files in a tools directory.\n * Matches *.ts files directly in the directory (not recursive).\n *\n * @example\n * findToolFiles('src/tools', fs)\n * // [{ name: 'show-albums', path: 'src/tools/show-albums.ts' }]\n */\nexport function findToolFiles(\n toolsDir: string,\n fs: Pick<FsOps, 'readdirSync' | 'existsSync'>\n): ToolFileInfo[] {\n if (!fs.existsSync(toolsDir)) {\n return [];\n }\n\n const entries = fs.readdirSync(toolsDir, { withFileTypes: true });\n\n return entries\n .filter(\n (entry) =>\n !entry.isDirectory() && entry.name.endsWith('.ts') && !entry.name.endsWith('.test.ts')\n )\n .map((entry) => ({\n name: entry.name.replace(/\\.ts$/, ''),\n path: `${toolsDir}/${entry.name}`,\n }));\n}\n\n/**\n * Information about a discovered simulation file (flat convention)\n */\nexport interface SimulationFileInfo {\n /** Filename without extension (e.g., 'show-albums') */\n name: string;\n /** Full path to the simulation file */\n path: string;\n}\n\n/**\n * Find all simulation JSON files in a flat simulations directory.\n * Matches any *.json file directly in the directory.\n *\n * @example\n * findSimulationFilesFlat('tests/simulations', fs)\n * // [{ name: 'show-albums', path: 'tests/simulations/show-albums.json' }]\n */\nexport function findSimulationFilesFlat(\n simulationsDir: string,\n fs: Pick<FsOps, 'readdirSync' | 'existsSync'>\n): SimulationFileInfo[] {\n if (!fs.existsSync(simulationsDir)) {\n return [];\n }\n\n const entries = fs.readdirSync(simulationsDir, { withFileTypes: true });\n\n return entries\n .filter((entry) => !entry.isDirectory() && entry.name.endsWith('.json'))\n .map((entry) => ({\n name: entry.name.replace(/\\.json$/, ''),\n path: `${simulationsDir}/${entry.name}`,\n }));\n}\n"],"names":[],"mappings":"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"}
|