sunpeak 0.7.10 → 0.8.1

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.
Files changed (114) hide show
  1. package/README.md +9 -11
  2. package/bin/commands/deploy.mjs +18 -9
  3. package/bin/commands/login.mjs +73 -55
  4. package/bin/commands/logout.mjs +26 -12
  5. package/bin/commands/pull.mjs +60 -39
  6. package/bin/commands/push.mjs +73 -49
  7. package/bin/commands/upgrade.mjs +203 -0
  8. package/bin/sunpeak.js +62 -31
  9. package/dist/chatgpt/chatgpt-simulator.d.ts +2 -1
  10. package/dist/index.cjs +15 -12
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.js +15 -12
  13. package/dist/index.js.map +1 -1
  14. package/dist/mcp/entry.cjs +41 -9
  15. package/dist/mcp/entry.cjs.map +1 -1
  16. package/dist/mcp/entry.js +42 -10
  17. package/dist/mcp/entry.js.map +1 -1
  18. package/dist/mcp/index.cjs +1 -1
  19. package/dist/mcp/index.js +1 -1
  20. package/dist/server-B9YgCQdS.cjs +5067 -0
  21. package/dist/server-B9YgCQdS.cjs.map +1 -0
  22. package/dist/server-DVmTC-SF.js +5068 -0
  23. package/dist/server-DVmTC-SF.js.map +1 -0
  24. package/dist/style.css +1 -1
  25. package/dist/types/simulation.d.ts +1 -1
  26. package/package.json +17 -17
  27. package/template/.sunpeak/dev.tsx +78 -15
  28. package/template/.sunpeak/vite-env.d.ts +1 -0
  29. package/template/README.md +6 -6
  30. package/template/dist/albums.js +4 -4
  31. package/template/dist/albums.json +1 -1
  32. package/template/dist/carousel.js +8 -8
  33. package/template/dist/carousel.json +1 -1
  34. package/template/dist/counter.js +4 -4
  35. package/template/dist/counter.json +1 -1
  36. package/template/dist/map.js +4 -4
  37. package/template/dist/map.json +1 -1
  38. package/template/node_modules/.bin/tsx +2 -2
  39. package/template/node_modules/.bin/vite +2 -2
  40. package/template/node_modules/.bin/vitest +2 -2
  41. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Avatar.js +7 -7
  42. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Avatar.js.map +1 -1
  43. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Button.js +6 -6
  44. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Checkbox.js +6 -6
  45. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Checkbox.js.map +1 -1
  46. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Icon.js +3 -3
  47. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Input.js +3 -3
  48. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_SegmentedControl.js +9 -9
  49. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_SegmentedControl.js.map +1 -1
  50. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Select.js +33 -33
  51. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Select.js.map +1 -1
  52. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Textarea.js +7 -7
  53. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Textarea.js.map +1 -1
  54. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_theme.js +2 -2
  55. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_theme.js.map +1 -1
  56. package/template/node_modules/.vite/deps/_metadata.json +60 -60
  57. package/template/node_modules/.vite/deps/{chunk-CQ3GYAYB.js → chunk-2DZGWGIP.js} +5 -5
  58. package/template/node_modules/.vite/deps/{chunk-CQ3GYAYB.js.map → chunk-2DZGWGIP.js.map} +1 -1
  59. package/template/node_modules/.vite/deps/{chunk-4TLBUCVB.js → chunk-BUOVMFCD.js} +6 -6
  60. package/template/node_modules/.vite/deps/{chunk-4TLBUCVB.js.map → chunk-BUOVMFCD.js.map} +2 -2
  61. package/template/node_modules/.vite/deps/{chunk-BAG6OO6S.js → chunk-DYQDWJMS.js} +5 -5
  62. package/template/node_modules/.vite/deps/{chunk-BAG6OO6S.js.map → chunk-DYQDWJMS.js.map} +1 -1
  63. package/template/node_modules/.vite/deps/{chunk-YOJ6QPGS.js → chunk-JAGHY6H6.js} +3 -3
  64. package/template/node_modules/.vite/deps/{chunk-YOJ6QPGS.js.map → chunk-JAGHY6H6.js.map} +1 -1
  65. package/template/node_modules/.vite/deps/{chunk-PTVT3RFX.js → chunk-JGVISENQ.js} +6 -6
  66. package/template/node_modules/.vite/deps/{chunk-PTVT3RFX.js.map → chunk-JGVISENQ.js.map} +1 -1
  67. package/template/node_modules/.vite/deps/{chunk-LR7NKCX5.js → chunk-SPYXUHEY.js} +44 -44
  68. package/template/node_modules/.vite/deps/{chunk-LR7NKCX5.js.map → chunk-SPYXUHEY.js.map} +1 -1
  69. package/template/node_modules/.vite/deps/{chunk-SGWD4VEU.js → chunk-TSEQUROC.js} +113 -107
  70. package/template/node_modules/.vite/deps/chunk-TSEQUROC.js.map +7 -0
  71. package/template/node_modules/.vite/deps/{chunk-XB525PXG.js → chunk-UM3ZGDFR.js} +747 -747
  72. package/template/node_modules/.vite/deps/{chunk-XB525PXG.js.map → chunk-UM3ZGDFR.js.map} +1 -1
  73. package/template/node_modules/.vite/deps/{chunk-KFGKZMLK.js → chunk-XZTIOEPG.js} +7 -7
  74. package/template/node_modules/.vite/deps/{chunk-KFGKZMLK.js.map → chunk-XZTIOEPG.js.map} +2 -2
  75. package/template/node_modules/.vite/deps/embla-carousel-react.js +3 -3
  76. package/template/node_modules/.vite/deps/embla-carousel-react.js.map +1 -1
  77. package/template/node_modules/.vite/deps/react-dom.js +2 -2
  78. package/template/node_modules/.vite/deps/react-dom_client.js +11 -11
  79. package/template/node_modules/.vite/deps/react-dom_client.js.map +2 -2
  80. package/template/node_modules/.vite/deps/react.js +1 -1
  81. package/template/node_modules/.vite/deps/react_jsx-dev-runtime.js +5 -5
  82. package/template/node_modules/.vite/deps/react_jsx-dev-runtime.js.map +1 -1
  83. package/template/node_modules/.vite/deps/react_jsx-runtime.js +2 -2
  84. package/template/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  85. package/template/package.json +11 -11
  86. package/template/src/components/map/map-view.test.tsx +1 -1
  87. package/template/src/components/map/map-view.tsx +1 -1
  88. package/template/src/components/map/map.tsx +1 -1
  89. package/template/src/components/map/place-card.test.tsx +1 -1
  90. package/template/src/components/map/place-card.tsx +1 -1
  91. package/template/src/components/map/place-carousel.test.tsx +1 -1
  92. package/template/src/components/map/place-carousel.tsx +1 -1
  93. package/template/src/components/map/place-inspector.test.tsx +1 -1
  94. package/template/src/components/map/place-inspector.tsx +1 -1
  95. package/template/src/components/map/place-list.test.tsx +1 -1
  96. package/template/src/components/map/place-list.tsx +1 -1
  97. package/template/src/components/map/types.ts +18 -0
  98. package/template/src/resources/index.ts +39 -4
  99. package/template/src/simulations/albums-show-simulation.json +131 -0
  100. package/template/src/simulations/carousel-show-simulation.json +68 -0
  101. package/template/src/simulations/counter-show-simulation.json +20 -0
  102. package/template/src/simulations/index.ts +17 -12
  103. package/template/src/simulations/map-show-simulation.json +123 -0
  104. package/template/src/vite-env.d.ts +1 -0
  105. package/template/tsconfig.json +1 -1
  106. package/dist/server-BOYwNazb.cjs +0 -930
  107. package/dist/server-BOYwNazb.cjs.map +0 -1
  108. package/dist/server-C6vMGV6H.js +0 -931
  109. package/dist/server-C6vMGV6H.js.map +0 -1
  110. package/template/node_modules/.vite/deps/chunk-SGWD4VEU.js.map +0 -7
  111. package/template/src/simulations/albums-simulation.ts +0 -147
  112. package/template/src/simulations/carousel-simulation.ts +0 -84
  113. package/template/src/simulations/counter-simulation.ts +0 -34
  114. package/template/src/simulations/map-simulation.ts +0 -154
package/dist/style.css CHANGED
@@ -1,4 +1,4 @@
1
- /*! tailwindcss v4.1.17 | MIT License | https://tailwindcss.com */
1
+ /*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */
2
2
  @layer properties {
3
3
  @supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
4
4
  *, :before, :after, ::backdrop {
@@ -42,6 +42,6 @@ export interface Simulation {
42
42
  userMessage?: string;
43
43
  simulationGlobals?: SimulationGlobals;
44
44
  tool: Tool;
45
- resource: Resource;
45
+ resource?: Resource;
46
46
  toolCall?: SimulationCallToolResult;
47
47
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sunpeak",
3
- "version": "0.7.10",
3
+ "version": "0.8.1",
4
4
  "description": "The ChatGPT App framework. Quickstart, build, & test your ChatGPT App locally!",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -57,40 +57,40 @@
57
57
  "author": "Sunpeak AI",
58
58
  "license": "MIT",
59
59
  "peerDependencies": {
60
- "@openai/apps-sdk-ui": "^0.2.0",
60
+ "@openai/apps-sdk-ui": "^0.2.1",
61
61
  "react": "^18.0.0 || ^19.0.0",
62
62
  "react-dom": "^18.0.0 || ^19.0.0"
63
63
  },
64
64
  "dependencies": {
65
- "@modelcontextprotocol/sdk": "^0.5.0",
65
+ "@modelcontextprotocol/sdk": "^1.25.1",
66
66
  "clsx": "^2.1.1",
67
67
  "tailwind-merge": "^3.4.0",
68
- "zod": "^3.23.8"
68
+ "zod": "^3.25.76"
69
69
  },
70
70
  "devDependencies": {
71
- "@playwright/test": "^1.56.1",
72
- "@tailwindcss/vite": "^4.1.17",
71
+ "@playwright/test": "^1.57.0",
72
+ "@tailwindcss/vite": "^4.1.18",
73
73
  "@testing-library/jest-dom": "^6.9.1",
74
- "@testing-library/react": "^16.3.0",
74
+ "@testing-library/react": "^16.3.1",
75
75
  "@testing-library/user-event": "^14.6.1",
76
- "@types/node": "^24.10.1",
76
+ "@types/node": "^22.15.3",
77
77
  "@types/react": "^19.2.7",
78
78
  "@types/react-dom": "^19.2.3",
79
- "@typescript-eslint/eslint-plugin": "^8.47.0",
80
- "@typescript-eslint/parser": "^8.47.0",
81
- "@vitejs/plugin-react": "^4.3.4",
82
- "eslint": "^9.39.1",
79
+ "@typescript-eslint/eslint-plugin": "^8.50.1",
80
+ "@typescript-eslint/parser": "^8.50.1",
81
+ "@vitejs/plugin-react": "^4.5.2",
82
+ "eslint": "^9.39.2",
83
83
  "eslint-config-prettier": "^10.1.8",
84
84
  "eslint-plugin-react": "^7.37.5",
85
85
  "eslint-plugin-react-hooks": "^7.0.1",
86
- "jsdom": "^27.2.0",
87
- "prettier": "^3.6.2",
86
+ "jsdom": "^27.3.0",
87
+ "prettier": "^3.7.4",
88
88
  "react": "^19.2.0",
89
89
  "react-dom": "^19.2.0",
90
- "tailwindcss": "^4.1.17",
90
+ "tailwindcss": "^4.1.18",
91
91
  "ts-node": "^10.9.2",
92
- "tsx": "^4.20.6",
93
- "typescript": "^5.6.3",
92
+ "tsx": "^4.21.0",
93
+ "typescript": "^5.9.3",
94
94
  "vite": "^5.4.21",
95
95
  "vite-plugin-dts": "^4.5.4",
96
96
  "vitest": "^4.0.12"
@@ -1,44 +1,107 @@
1
1
  /**
2
2
  * Bootstrap file for Sunpeak dev server
3
3
  * This file bootstraps the ChatGPT simulator for development
4
+ *
5
+ * Auto-discovers simulations and resources by file naming convention:
6
+ * - simulations/{resource}-{tool}-simulation.json (e.g., albums-show-simulation.json)
7
+ * - resources/{resource}-resource.json
8
+ * - resources/{Resource}Resource component (PascalCase)
4
9
  */
5
10
  import { StrictMode } from 'react';
6
11
  import { createRoot } from 'react-dom/client';
7
12
  import { ChatGPTSimulator, type Simulation } from 'sunpeak';
8
- import { SIMULATIONS } from '../src/simulations';
9
- import * as Resources from '../src/resources';
13
+ import resourceComponents from '../src/resources';
10
14
  import '../src/styles/globals.css';
11
15
 
16
+ // Auto-discover all simulation and resource JSON files
17
+ const simulationModules = import.meta.glob('../src/simulations/*-simulation.json', {
18
+ eager: true,
19
+ });
20
+ const resourceModules = import.meta.glob('../src/resources/*-resource.json', { eager: true });
21
+
22
+ // Build resource map from discovered files
23
+ type ResourceData = { name: string; [key: string]: unknown };
24
+ const resourcesMap = new Map<string, ResourceData>();
25
+ for (const [path, module] of Object.entries(resourceModules)) {
26
+ // Extract key from path: '../src/resources/counter-resource.json' -> 'counter'
27
+ const match = path.match(/\/([^/]+)-resource\.json$/);
28
+ const key = match?.[1];
29
+ if (key) {
30
+ resourcesMap.set(key, (module as { default: ResourceData }).default);
31
+ }
32
+ }
33
+
34
+ // Get sorted resource keys for best-match lookup (longest first)
35
+ const resourceKeys = Array.from(resourcesMap.keys()).sort((a, b) => b.length - a.length);
36
+
37
+ /**
38
+ * Find the best matching resource for a simulation key.
39
+ * Matches the longest resource name that is a prefix of the simulation key.
40
+ * e.g., 'albums-show' matches 'albums' (not 'album' if both exist)
41
+ */
42
+ function findResourceKey(simulationKey: string): string | undefined {
43
+ // Simulation key format: {resource}-{tool} (e.g., 'albums-show')
44
+ // Find the longest resource name that matches as a prefix followed by '-'
45
+ for (const resourceKey of resourceKeys) {
46
+ if (simulationKey === resourceKey || simulationKey.startsWith(resourceKey + '-')) {
47
+ return resourceKey;
48
+ }
49
+ }
50
+ return undefined;
51
+ }
52
+
12
53
  /**
13
54
  * Convert resource name to component name
14
55
  * Example: 'carousel' -> 'CarouselResource', 'counter' -> 'CounterResource'
15
56
  */
16
- function getResourceComponentFromName(name: string): React.ComponentType {
17
- // Convert name to PascalCase and append 'Resource'
57
+ function getResourceComponent(name: string): React.ComponentType {
18
58
  const pascalName = name.charAt(0).toUpperCase() + name.slice(1);
19
59
  const componentName = `${pascalName}Resource`;
20
60
 
21
- const component = Resources[componentName as keyof typeof Resources];
61
+ const component = resourceComponents[componentName];
22
62
 
23
63
  if (!component) {
24
64
  throw new Error(
25
65
  `Resource component "${componentName}" not found for resource "${name}". ` +
26
- `Make sure it's exported from src/resources/index.ts`
66
+ `Make sure src/resources/${name}-resource.tsx exists with a default export.`
27
67
  );
28
68
  }
29
69
 
30
- return component as React.ComponentType;
70
+ return component;
31
71
  }
32
72
 
33
- // Package the resource component with the simulation
34
- const simulations: Simulation[] = Object.values(
35
- SIMULATIONS as Record<string, Omit<Simulation, 'resourceComponent'>>
36
- ).map((simulation) => ({
37
- ...simulation,
38
- resourceComponent: getResourceComponentFromName(simulation.resource.name),
39
- }));
73
+ // Build simulations array from discovered files
74
+ type SimulationData = Omit<Simulation, 'resourceComponent' | 'resource'>;
75
+ const simulations: Simulation[] = [];
76
+
77
+ for (const [path, module] of Object.entries(simulationModules)) {
78
+ // Extract simulation key from path: '../src/simulations/albums-show-simulation.json' -> 'albums-show'
79
+ const match = path.match(/\/([^/]+)-simulation\.json$/);
80
+ const simulationKey = match?.[1];
81
+ if (!simulationKey) continue;
82
+
83
+ const simulation = (module as { default: SimulationData }).default;
84
+
85
+ // Find matching resource by best prefix match
86
+ const resourceKey = findResourceKey(simulationKey);
87
+ if (!resourceKey) {
88
+ console.warn(
89
+ `No matching resource found for simulation "${simulationKey}". ` +
90
+ `Expected a resource file like src/resources/${simulationKey.split('-')[0]}-resource.json`
91
+ );
92
+ continue;
93
+ }
94
+
95
+ const resource = resourcesMap.get(resourceKey)!;
96
+
97
+ simulations.push({
98
+ ...simulation,
99
+ resource,
100
+ resourceComponent: getResourceComponent(resource.name),
101
+ });
102
+ }
40
103
 
41
- // Read app config from package.json or use defaults
104
+ // Read app config from environment or use defaults
42
105
  const appName = import.meta.env?.VITE_APP_NAME || 'Sunpeak';
43
106
  const appIcon = import.meta.env?.VITE_APP_ICON || '🌄';
44
107
 
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />
@@ -8,7 +8,7 @@ For an initial overview of your new app and the sunpeak API, refer to the [docum
8
8
 
9
9
  ```bash
10
10
  pnpm install
11
- pnpm dev
11
+ sunpeak dev
12
12
  ```
13
13
 
14
14
  That's it! Edit the resource files in [./src/resources/](./src/resources/) to build your resource UI.
@@ -16,9 +16,9 @@ That's it! Edit the resource files in [./src/resources/](./src/resources/) to bu
16
16
  ## Commands
17
17
 
18
18
  ```bash
19
- pnpm dev # Start development server
20
- pnpm build # Build all resources for production
21
- pnpm mcp # Start MCP server with auto-reload
19
+ sunpeak dev # Start development server
20
+ sunpeak build # Build all resources for production
21
+ sunpeak mcp # Start MCP server with auto-reload
22
22
  pnpm test # Run tests with Vitest
23
23
  ```
24
24
 
@@ -62,7 +62,7 @@ Test your app directly in ChatGPT using the built-in MCP server:
62
62
 
63
63
  ```bash
64
64
  # Start the MCP server (rebuilds and restarts on file changes).
65
- pnpm mcp
65
+ sunpeak mcp
66
66
 
67
67
  # In another terminal, run a tunnel. For example:
68
68
  ngrok http 6766
@@ -79,7 +79,7 @@ When you make changes to the UI, refresh your app in ChatGPT after the MCP serve
79
79
  Build your app for production:
80
80
 
81
81
  ```bash
82
- pnpm build
82
+ sunpeak build
83
83
  ```
84
84
 
85
85
  This creates optimized builds in `dist/`: