sunpeak 0.7.9 → 0.7.11

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 (79) hide show
  1. package/README.md +7 -10
  2. package/bin/commands/deploy.mjs +25 -9
  3. package/bin/commands/push.mjs +19 -14
  4. package/bin/sunpeak.js +16 -0
  5. package/dist/index.cjs +6 -0
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.js +6 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/mcp/entry.cjs +1 -1
  10. package/dist/mcp/entry.js +1 -1
  11. package/dist/mcp/index.cjs +1 -1
  12. package/dist/mcp/index.js +1 -1
  13. package/dist/server-CziiHU7V.cjs +5066 -0
  14. package/dist/server-CziiHU7V.cjs.map +1 -0
  15. package/dist/server-D8kyzuiq.js +5067 -0
  16. package/dist/server-D8kyzuiq.js.map +1 -0
  17. package/dist/style.css +1 -1
  18. package/package.json +17 -17
  19. package/template/dist/albums.js +4 -4
  20. package/template/dist/albums.json +1 -1
  21. package/template/dist/carousel.js +8 -8
  22. package/template/dist/carousel.json +1 -1
  23. package/template/dist/counter.js +4 -4
  24. package/template/dist/counter.json +1 -1
  25. package/template/dist/map.js +4 -4
  26. package/template/dist/map.json +1 -1
  27. package/template/node_modules/.bin/tsx +2 -2
  28. package/template/node_modules/.bin/vite +2 -2
  29. package/template/node_modules/.bin/vitest +2 -2
  30. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Avatar.js +7 -7
  31. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Avatar.js.map +1 -1
  32. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Button.js +6 -6
  33. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Checkbox.js +6 -6
  34. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Checkbox.js.map +1 -1
  35. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Icon.js +3 -3
  36. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Input.js +3 -3
  37. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_SegmentedControl.js +8 -8
  38. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_SegmentedControl.js.map +1 -1
  39. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Select.js +20 -20
  40. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Select.js.map +1 -1
  41. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Textarea.js +5 -5
  42. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Textarea.js.map +1 -1
  43. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_theme.js +2 -2
  44. package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_theme.js.map +1 -1
  45. package/template/node_modules/.vite/deps/_metadata.json +56 -56
  46. package/template/node_modules/.vite/deps/{chunk-CQ3GYAYB.js → chunk-2DZGWGIP.js} +5 -5
  47. package/template/node_modules/.vite/deps/{chunk-CQ3GYAYB.js.map → chunk-2DZGWGIP.js.map} +1 -1
  48. package/template/node_modules/.vite/deps/{chunk-4TLBUCVB.js → chunk-BUOVMFCD.js} +6 -6
  49. package/template/node_modules/.vite/deps/{chunk-4TLBUCVB.js.map → chunk-BUOVMFCD.js.map} +2 -2
  50. package/template/node_modules/.vite/deps/{chunk-BAG6OO6S.js → chunk-DYQDWJMS.js} +5 -5
  51. package/template/node_modules/.vite/deps/{chunk-BAG6OO6S.js.map → chunk-DYQDWJMS.js.map} +1 -1
  52. package/template/node_modules/.vite/deps/{chunk-YOJ6QPGS.js → chunk-JAGHY6H6.js} +3 -3
  53. package/template/node_modules/.vite/deps/{chunk-YOJ6QPGS.js.map → chunk-JAGHY6H6.js.map} +1 -1
  54. package/template/node_modules/.vite/deps/{chunk-PTVT3RFX.js → chunk-JGVISENQ.js} +6 -6
  55. package/template/node_modules/.vite/deps/{chunk-PTVT3RFX.js.map → chunk-JGVISENQ.js.map} +1 -1
  56. package/template/node_modules/.vite/deps/{chunk-LR7NKCX5.js → chunk-N6DVYEXK.js} +38 -38
  57. package/template/node_modules/.vite/deps/{chunk-LR7NKCX5.js.map → chunk-N6DVYEXK.js.map} +1 -1
  58. package/template/node_modules/.vite/deps/{chunk-SGWD4VEU.js → chunk-TSEQUROC.js} +113 -107
  59. package/template/node_modules/.vite/deps/chunk-TSEQUROC.js.map +7 -0
  60. package/template/node_modules/.vite/deps/{chunk-XB525PXG.js → chunk-UM3ZGDFR.js} +747 -747
  61. package/template/node_modules/.vite/deps/{chunk-XB525PXG.js.map → chunk-UM3ZGDFR.js.map} +1 -1
  62. package/template/node_modules/.vite/deps/{chunk-KFGKZMLK.js → chunk-XZTIOEPG.js} +7 -7
  63. package/template/node_modules/.vite/deps/{chunk-KFGKZMLK.js.map → chunk-XZTIOEPG.js.map} +2 -2
  64. package/template/node_modules/.vite/deps/embla-carousel-react.js +3 -3
  65. package/template/node_modules/.vite/deps/embla-carousel-react.js.map +1 -1
  66. package/template/node_modules/.vite/deps/react-dom.js +2 -2
  67. package/template/node_modules/.vite/deps/react-dom_client.js +11 -11
  68. package/template/node_modules/.vite/deps/react-dom_client.js.map +2 -2
  69. package/template/node_modules/.vite/deps/react.js +1 -1
  70. package/template/node_modules/.vite/deps/react_jsx-dev-runtime.js +5 -5
  71. package/template/node_modules/.vite/deps/react_jsx-dev-runtime.js.map +1 -1
  72. package/template/node_modules/.vite/deps/react_jsx-runtime.js +2 -2
  73. package/template/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  74. package/template/package.json +11 -11
  75. package/dist/server-BOYwNazb.cjs +0 -930
  76. package/dist/server-BOYwNazb.cjs.map +0 -1
  77. package/dist/server-C6vMGV6H.js +0 -931
  78. package/dist/server-C6vMGV6H.js.map +0 -1
  79. package/template/node_modules/.vite/deps/chunk-SGWD4VEU.js.map +0 -7
package/README.md CHANGED
@@ -53,12 +53,15 @@ sunpeak is an npm package consisting of:
53
53
  1. Runtime APIs - Strongly typed, multi-platform APIs for interacting with the ChatGPT runtime, architected to support future platforms (Gemini, Claude).
54
54
  2. ChatGPT simulator - React component replicating ChatGPT's runtime.
55
55
  3. MCP server - Mock data MCP server for testing local Resources in the real ChatGPT.
56
- 2. **The `sunpeak` framework** (`./template`). An end-to-end framework for ChatGPT Apps, from quickstart to shipped. This templated npm package includes:
57
- 1. Project scaffold - Complete development setup with build, test, and mcp tooling.
56
+ 2. **The `sunpeak` framework** (`./template`). Next.js for ChatGPT Apps. This templated npm package includes:
57
+ 1. Project scaffold - Complete development setup with build, test, and mcp tooling, including the sunpeak library.
58
58
  2. UI components - Production-ready components following ChatGPT design guidelines and using OpenAI apps-sdk-ui React components.
59
- 3. CLI utility (`./bin`) - Commands for working with the sunpeak framework.
59
+ 3. **The `sunpeak` CLI** (`./bin`). Commands for managing ChatGPT Apps. Includes a client for the [sunpeak Resource Repository](https://app.sunpeak.ai/) (ECR for ChatGPT Apps). The repository helps you & your CI/CD decouple your App from your client-agnostic MCP server:
60
+ 1. Tag your app builds with version numbers and environment names (like `v1.0.0` and `prod`)
61
+ 2. `push` built Apps to a central location
62
+ 3. `pull` built Apps to be run in different environments
60
63
 
61
- Note that the `sunpeak` library can be used without the framework.
64
+ Note that each `sunpeak` component can be used in isolation if preferred, though the most seamless experience combines all 3.
62
65
 
63
66
  ## Example Component
64
67
 
@@ -81,12 +84,6 @@ export function MCPResource() {
81
84
  }
82
85
  ```
83
86
 
84
- ## Contributing
85
-
86
- We welcome your contributions!
87
-
88
- For development quickstart on this package, see [DEVELOPMENT.md](./DEVELOPMENT.md).
89
-
90
87
  ## Resources
91
88
 
92
89
  - [ChatGPT Apps SDK Design Guidelines](https://developers.openai.com/apps-sdk/concepts/design-guidelines)
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { push } from './push.mjs';
2
+ import { push, findResources } from './push.mjs';
3
3
 
4
4
  /**
5
5
  * Deploy command - same as push but with tag="prod"
@@ -17,33 +17,48 @@ Usage:
17
17
 
18
18
  Options:
19
19
  -r, --repository <owner/repo> Repository name (defaults to git remote origin)
20
- -t, --tag <name> Tag to assign (defaults to "prod")
20
+ -t, --tag <name> Additional tag(s) to assign (always includes "prod")
21
21
  -h, --help Show this help message
22
22
 
23
23
  Arguments:
24
24
  file Optional JS file to deploy (e.g., dist/carousel.js)
25
- If not provided, deploys all resources from dist/
25
+ If not provided, looks for resources in current
26
+ directory first, then falls back to dist/
26
27
 
27
28
  Examples:
28
29
  sunpeak deploy Push all resources with "prod" tag
29
30
  sunpeak deploy dist/carousel.js Deploy a single resource
30
31
  sunpeak deploy -r myorg/my-app Deploy to "myorg/my-app" repository
31
- sunpeak deploy -t production Deploy with custom tag
32
+ sunpeak deploy -t v1.0 Deploy with "prod" and "v1.0" tags
32
33
 
33
34
  This command is equivalent to: sunpeak push --tag prod
34
35
  `);
35
36
  return;
36
37
  }
37
38
 
38
- // Default tag to "prod" for deploy
39
+ // Always include "prod" tag, supplemented by any additional tags
40
+ const additionalTags = options.tags?.filter((t) => t !== 'prod') ?? [];
39
41
  const deployOptions = {
40
42
  ...options,
41
- tags: options.tags && options.tags.length > 0 ? options.tags : ['prod'],
43
+ tags: ['prod', ...additionalTags],
42
44
  };
43
45
 
44
46
  console.log('Deploying to production...');
45
47
  console.log();
46
48
 
49
+ // If no specific file provided, check current directory first, then dist/
50
+ if (!deployOptions.file) {
51
+ const cwdResources = findResources(projectRoot);
52
+ if (cwdResources.length > 0) {
53
+ // Found resources in current directory, push each one
54
+ for (const resource of cwdResources) {
55
+ await push(projectRoot, { ...deployOptions, file: resource.jsPath });
56
+ }
57
+ return;
58
+ }
59
+ // Fall back to dist/ directory (handled by push)
60
+ }
61
+
47
62
  await push(projectRoot, deployOptions);
48
63
  }
49
64
 
@@ -70,18 +85,19 @@ Usage:
70
85
 
71
86
  Options:
72
87
  -r, --repository <owner/repo> Repository name (defaults to git remote origin)
73
- -t, --tag <name> Tag to assign (defaults to "prod")
88
+ -t, --tag <name> Additional tag(s) to assign (always includes "prod")
74
89
  -h, --help Show this help message
75
90
 
76
91
  Arguments:
77
92
  file Optional JS file to deploy (e.g., dist/carousel.js)
78
- If not provided, deploys all resources from dist/
93
+ If not provided, looks for resources in current
94
+ directory first, then falls back to dist/
79
95
 
80
96
  Examples:
81
97
  sunpeak deploy Deploy all resources with "prod" tag
82
98
  sunpeak deploy dist/carousel.js Deploy a single resource
83
99
  sunpeak deploy -r myorg/my-app Deploy to "myorg/my-app" repository
84
- sunpeak deploy -t production Deploy with custom tag
100
+ sunpeak deploy -t v1.0 Deploy with "prod" and "v1.0" tags
85
101
 
86
102
  This command is equivalent to: sunpeak push --tag prod
87
103
  `);
@@ -45,33 +45,38 @@ function getGitRepoName() {
45
45
  }
46
46
 
47
47
  /**
48
- * Find all resources in the dist folder
48
+ * Find all resources in a directory
49
49
  * Returns array of { name, jsPath, metaPath, meta }
50
50
  */
51
- function findResources(distDir) {
51
+ export function findResources(distDir) {
52
52
  if (!existsSync(distDir)) {
53
53
  return [];
54
54
  }
55
55
 
56
56
  const files = readdirSync(distDir);
57
- const jsFiles = files.filter((f) => f.endsWith('.js') && !f.endsWith('.meta.js'));
58
-
59
- return jsFiles.map((jsFile) => {
60
- const name = jsFile.replace('.js', '');
61
- const jsPath = join(distDir, jsFile);
62
- const metaPath = join(distDir, `${name}.json`);
63
-
64
- let meta = null;
65
- if (existsSync(metaPath)) {
57
+ const jsFiles = files.filter((f) => f.endsWith('.js'));
58
+ const jsonFiles = new Set(files.filter((f) => f.endsWith('.json')));
59
+
60
+ // Only include .js files that have a matching .json file
61
+ return jsFiles
62
+ .filter((jsFile) => {
63
+ const name = jsFile.replace('.js', '');
64
+ return jsonFiles.has(`${name}.json`);
65
+ })
66
+ .map((jsFile) => {
67
+ const name = jsFile.replace('.js', '');
68
+ const jsPath = join(distDir, jsFile);
69
+ const metaPath = join(distDir, `${name}.json`);
70
+
71
+ let meta = null;
66
72
  try {
67
73
  meta = JSON.parse(readFileSync(metaPath, 'utf-8'));
68
74
  } catch {
69
75
  console.warn(`Warning: Could not parse ${name}.json`);
70
76
  }
71
- }
72
77
 
73
- return { name, jsPath, metaPath, meta };
74
- });
78
+ return { name, jsPath, metaPath, meta };
79
+ });
75
80
  }
76
81
 
77
82
  /**
package/bin/sunpeak.js CHANGED
@@ -232,6 +232,15 @@ See README.md for more details.
232
232
 
233
233
  const [, , command, ...args] = process.argv;
234
234
 
235
+ /**
236
+ * Get the sunpeak version from package.json
237
+ */
238
+ function getVersion() {
239
+ const pkgPath = join(__dirname, '..', 'package.json');
240
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
241
+ return pkg.version;
242
+ }
243
+
235
244
  /**
236
245
  * Parse arguments for resource commands (push, pull, deploy)
237
246
  */
@@ -268,6 +277,12 @@ function parseResourceArgs(args) {
268
277
 
269
278
  // Main CLI handler
270
279
  (async () => {
280
+ // Handle --version / -v flags early
281
+ if (command === '--version' || command === '-v' || command === 'version') {
282
+ console.log(getVersion());
283
+ process.exit(0);
284
+ }
285
+
271
286
  // Commands that don't require a package.json
272
287
  const standaloneCommands = [
273
288
  'new',
@@ -373,6 +388,7 @@ Direct CLI commands (when sunpeak is installed):
373
388
  sunpeak push Push resources to repository
374
389
  sunpeak pull Pull resources from repository
375
390
  sunpeak deploy Push resources with "prod" tag
391
+ sunpeak --version Show version number
376
392
 
377
393
  For more information, visit: https://sunpeak.ai/
378
394
  `);
package/dist/index.cjs CHANGED
@@ -1742,6 +1742,12 @@ function RemoveScrollSideCar(props) {
1742
1742
  if ("touches" in event && moveDirection === "h" && target.type === "range") {
1743
1743
  return false;
1744
1744
  }
1745
+ var selection = window.getSelection();
1746
+ var anchorNode = selection && selection.anchorNode;
1747
+ var isTouchingSelection = anchorNode ? anchorNode === target || anchorNode.contains(target) : false;
1748
+ if (isTouchingSelection) {
1749
+ return false;
1750
+ }
1745
1751
  var canBeScrolledInMainDirection = locationCouldBeScrolled(moveDirection, target);
1746
1752
  if (!canBeScrolledInMainDirection) {
1747
1753
  return true;