sunpeak 0.4.2 → 0.5.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 (60) hide show
  1. package/README.md +2 -2
  2. package/bin/sunpeak.js +1 -1
  3. package/dist/chatgpt/chatgpt-simulator-types.d.ts +1 -1
  4. package/dist/chatgpt/chatgpt-simulator.d.ts +4 -15
  5. package/dist/chatgpt/index.d.ts +1 -1
  6. package/dist/chatgpt/mock-openai.d.ts +4 -16
  7. package/dist/index.cjs +70 -42
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.js +70 -42
  10. package/dist/index.js.map +1 -1
  11. package/dist/mcp/index.cjs +45 -112
  12. package/dist/mcp/index.cjs.map +1 -1
  13. package/dist/mcp/index.d.ts +2 -1
  14. package/dist/mcp/index.js +45 -112
  15. package/dist/mcp/index.js.map +1 -1
  16. package/dist/mcp/server.d.ts +2 -4
  17. package/dist/mcp/types.d.ts +16 -62
  18. package/dist/providers/index.d.ts +1 -3
  19. package/dist/providers/openai/index.d.ts +7 -0
  20. package/dist/{chatgpt/openai-provider.d.ts → providers/openai/provider.d.ts} +1 -1
  21. package/dist/{chatgpt/openai-types.d.ts → providers/openai/types.d.ts} +3 -32
  22. package/dist/providers/types.d.ts +4 -5
  23. package/dist/runtime/index.d.ts +7 -0
  24. package/dist/runtime/provider-detection.d.ts +17 -0
  25. package/dist/types/index.d.ts +2 -1
  26. package/dist/types/runtime.d.ts +34 -0
  27. package/dist/types/simulation.d.ts +47 -0
  28. package/package.json +2 -2
  29. package/template/README.md +1 -1
  30. package/template/dev/main.tsx +6 -2
  31. package/template/mcp/server.ts +8 -9
  32. package/template/package.json +1 -1
  33. package/template/scripts/build-all.mjs +43 -0
  34. package/template/scripts/validate.mjs +16 -7
  35. package/template/src/components/album/albums.tsx +7 -7
  36. package/template/src/components/card/card.tsx +4 -0
  37. package/template/src/components/index.ts +1 -1
  38. package/template/src/components/resources/AlbumsResource.tsx +13 -0
  39. package/template/src/{App.tsx → components/resources/CounterResource.tsx} +5 -14
  40. package/template/src/components/{simulations/carousel-simulation.tsx → resources/PlacesResource.tsx} +11 -17
  41. package/template/src/components/resources/index.ts +3 -0
  42. package/template/src/index-albums.tsx +9 -0
  43. package/template/src/index-carousel.tsx +9 -0
  44. package/template/src/index-counter.tsx +9 -0
  45. package/template/src/simulations/albums-simulation.ts +157 -0
  46. package/template/src/simulations/carousel-simulation.ts +94 -0
  47. package/template/src/simulations/counter-simulation.ts +43 -0
  48. package/template/src/simulations/index.ts +11 -0
  49. package/template/src/simulations/simulation-configs.ts +23 -0
  50. package/template/src/simulations/simulations.ts +36 -0
  51. package/template/src/simulations/types.ts +12 -0
  52. package/template/vite.config.build.ts +20 -14
  53. package/dist/chatgpt/mcp-provider.d.ts +0 -25
  54. package/template/data/albums.json +0 -112
  55. package/template/data/places.json +0 -49
  56. package/template/src/components/simulations/albums-simulation.tsx +0 -20
  57. package/template/src/components/simulations/app-simulation.tsx +0 -13
  58. package/template/src/components/simulations/index.tsx +0 -14
  59. package/template/src/index.chatgpt.tsx +0 -8
  60. package/template/src/index.ts +0 -3
package/README.md CHANGED
@@ -15,9 +15,9 @@
15
15
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.6-blue?style=flat-square&logo=typescript)](https://www.typescriptlang.org/)
16
16
  [![React](https://img.shields.io/badge/React-18%20%7C%2019-blue?style=flat-square&logo=react)](https://reactjs.org/)
17
17
 
18
- The ChatGPT Apps SDK.
18
+ The MCP App SDK.
19
19
 
20
- Build and test your MCP App UI locally with OpenAI apps-sdk-ui React components.
20
+ Quickstart, build, and test your ChatGPT App locally with OpenAI apps-sdk-ui React components.
21
21
 
22
22
  [Documentation](https://docs.sunpeak.ai/)
23
23
 
package/bin/sunpeak.js CHANGED
@@ -84,7 +84,7 @@ if (command === 'new') {
84
84
  init(args[0]);
85
85
  } else {
86
86
  console.log(`
87
- sunpeak - ChatGPT Apps UI SDK
87
+ sunpeak - The MCP App SDK
88
88
 
89
89
  Commands:
90
90
  new [name] Create a new project from template
@@ -1,4 +1,4 @@
1
- import { DisplayMode, Theme } from './openai-types';
1
+ import { DisplayMode, Theme } from '../types/runtime';
2
2
  export type ScreenWidth = 'mobile-s' | 'mobile-l' | 'tablet' | 'full';
3
3
  export type SimulatorConfig = {
4
4
  theme: Theme;
@@ -1,21 +1,10 @@
1
+ import { Simulation } from '../types/simulation';
1
2
  import * as React from 'react';
2
- /**
3
- * A simulation packages a component with its example data and metadata.
4
- * Each simulation represents a complete app experience in the simulator.
5
- */
6
- export interface Simulation {
7
- value: string;
8
- label: string;
9
- component: React.ComponentType;
10
- appName?: string;
11
- appIcon?: string;
12
- userMessage?: string;
13
- toolOutput?: Record<string, unknown> | null;
14
- widgetState?: Record<string, unknown> | null;
15
- }
16
3
  interface ChatGPTSimulatorProps {
17
4
  children?: React.ReactNode;
18
5
  simulations?: Simulation[];
6
+ appName?: string;
7
+ appIcon?: string;
19
8
  }
20
- export declare function ChatGPTSimulator({ children, simulations, }: ChatGPTSimulatorProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function ChatGPTSimulator({ children, simulations, appName, appIcon, }: ChatGPTSimulatorProps): import("react/jsx-runtime").JSX.Element;
21
10
  export {};
@@ -1,4 +1,4 @@
1
1
  export { ChatGPTSimulator } from './chatgpt-simulator';
2
- export type { Simulation } from './chatgpt-simulator';
2
+ export type { Simulation, SimulationCallToolResult, SimulationGlobals } from '../types/simulation';
3
3
  export { initMockOpenAI } from './mock-openai';
4
4
  export * from './theme-provider';
@@ -1,15 +1,8 @@
1
- import { OpenAiGlobals, OpenAiAPI, Theme, DisplayMode, View, ViewMode, UnknownObject } from '../types';
1
+ import { OpenAiGlobals, OpenAiAPI } from '../providers/openai';
2
+ import { Theme, DisplayMode, View, ViewMode, UnknownObject } from '../types/runtime';
2
3
  declare class MockOpenAI implements OpenAiAPI, OpenAiGlobals {
3
4
  theme: Theme;
4
- userAgent: {
5
- device: {
6
- type: "desktop";
7
- };
8
- capabilities: {
9
- hover: boolean;
10
- touch: boolean;
11
- };
12
- };
5
+ userAgent: OpenAiGlobals['userAgent'];
13
6
  locale: string;
14
7
  maxHeight: number;
15
8
  displayMode: DisplayMode;
@@ -52,10 +45,5 @@ declare class MockOpenAI implements OpenAiAPI, OpenAiGlobals {
52
45
  setWidgetStateExternal(widgetState: Record<string, unknown> | null): void;
53
46
  emitUpdate(globals: Partial<OpenAiGlobals>): void;
54
47
  }
55
- export declare function initMockOpenAI(initialData?: {
56
- theme?: Theme;
57
- displayMode?: DisplayMode;
58
- toolOutput?: Record<string, unknown> | null;
59
- widgetState?: Record<string, unknown> | null;
60
- }): MockOpenAI;
48
+ export declare function initMockOpenAI(initialData?: Partial<OpenAiGlobals>): MockOpenAI;
61
49
  export type { MockOpenAI };
package/dist/index.cjs CHANGED
@@ -23,12 +23,6 @@ function _interopNamespaceDefault(e) {
23
23
  }
24
24
  const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
25
25
  const SET_GLOBALS_EVENT_TYPE = "openai:set_globals";
26
- class SetGlobalsEvent extends CustomEvent {
27
- constructor() {
28
- super(...arguments);
29
- __publicField(this, "type", SET_GLOBALS_EVENT_TYPE);
30
- }
31
- }
32
26
  function isOpenAiAvailable() {
33
27
  return typeof window !== "undefined" && window.openai != null;
34
28
  }
@@ -85,7 +79,7 @@ function getOpenAiProvider() {
85
79
  }
86
80
  let cachedProvider = null;
87
81
  let detectionComplete = false;
88
- function getProvider() {
82
+ function detectProvider() {
89
83
  if (detectionComplete) {
90
84
  return cachedProvider;
91
85
  }
@@ -95,8 +89,18 @@ function getProvider() {
95
89
  detectionComplete = true;
96
90
  return cachedProvider;
97
91
  }
92
+ function isProviderAvailable$1() {
93
+ return detectProvider() !== null;
94
+ }
95
+ function resetProviderCache$1() {
96
+ cachedProvider = null;
97
+ detectionComplete = false;
98
+ }
99
+ function getProvider() {
100
+ return detectProvider();
101
+ }
98
102
  function isProviderAvailable() {
99
- return getProvider() !== null;
103
+ return isProviderAvailable$1();
100
104
  }
101
105
  function getGlobal(key) {
102
106
  const provider = getProvider();
@@ -112,8 +116,7 @@ function getAPI() {
112
116
  return (provider == null ? void 0 : provider.getAPI()) ?? null;
113
117
  }
114
118
  function resetProviderCache() {
115
- cachedProvider = null;
116
- detectionComplete = false;
119
+ resetProviderCache$1();
117
120
  }
118
121
  function useWidgetGlobal(key) {
119
122
  return React.useSyncExternalStore(
@@ -3395,9 +3398,9 @@ const SCREEN_WIDTHS = {
3395
3398
  function Conversation({
3396
3399
  children,
3397
3400
  screenWidth,
3398
- appName = "ChatGPT",
3401
+ appName = "Sunpeak App",
3399
3402
  appIcon,
3400
- userMessage = "Show me some interesting places to visit."
3403
+ userMessage = "What have you got for me today?"
3401
3404
  }) {
3402
3405
  const displayMode = useDisplayMode() ?? "inline";
3403
3406
  const containerWidth = screenWidth === "full" ? "100%" : `${SCREEN_WIDTHS[screenWidth]}px`;
@@ -3405,7 +3408,7 @@ function Conversation({
3405
3408
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col bg-surface w-full flex-1", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-auto", children }) });
3406
3409
  }
3407
3410
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col bg-surface w-full h-full flex-1", children: [
3408
- /* @__PURE__ */ jsxRuntime.jsx("header", { className: "h-12 border-b border-subtle bg-surface flex items-center px-4 text-lg", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground", children: "ChatGPT" }) }),
3411
+ /* @__PURE__ */ jsxRuntime.jsx("header", { className: "h-12 border-b border-subtle bg-surface flex items-center px-4 text-lg", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground", children: "SimGPT" }) }),
3409
3412
  /* @__PURE__ */ jsxRuntime.jsxs(
3410
3413
  "div",
3411
3414
  {
@@ -3476,7 +3479,7 @@ function Conversation({
3476
3479
  type: "text",
3477
3480
  name: "userInput",
3478
3481
  disabled: true,
3479
- placeholder: "Message ChatGPT",
3482
+ placeholder: "Message SimGPT",
3480
3483
  className: "w-full bg-[var(--color-background-primary)] dark:bg-[#303030] text-secondary-foreground placeholder:text-muted-foreground rounded-3xl px-5 py-3 pr-12 shadow-md light:border border-[#0000000f]"
3481
3484
  }
3482
3485
  ) }) }) })
@@ -3572,12 +3575,33 @@ function initMockOpenAI(initialData) {
3572
3575
  if ((initialData == null ? void 0 : initialData.theme) !== void 0) {
3573
3576
  mock.theme = initialData.theme;
3574
3577
  }
3578
+ if ((initialData == null ? void 0 : initialData.userAgent) !== void 0) {
3579
+ mock.userAgent = initialData.userAgent;
3580
+ }
3581
+ if ((initialData == null ? void 0 : initialData.locale) !== void 0) {
3582
+ mock.locale = initialData.locale;
3583
+ }
3584
+ if ((initialData == null ? void 0 : initialData.maxHeight) !== void 0) {
3585
+ mock.maxHeight = initialData.maxHeight;
3586
+ }
3575
3587
  if ((initialData == null ? void 0 : initialData.displayMode) !== void 0) {
3576
3588
  mock.displayMode = initialData.displayMode;
3577
3589
  }
3590
+ if ((initialData == null ? void 0 : initialData.safeArea) !== void 0) {
3591
+ mock.safeArea = initialData.safeArea;
3592
+ }
3593
+ if ((initialData == null ? void 0 : initialData.view) !== void 0) {
3594
+ mock.view = initialData.view;
3595
+ }
3596
+ if ((initialData == null ? void 0 : initialData.toolInput) !== void 0) {
3597
+ mock.toolInput = initialData.toolInput;
3598
+ }
3578
3599
  if ((initialData == null ? void 0 : initialData.toolOutput) !== void 0) {
3579
3600
  mock.toolOutput = initialData.toolOutput;
3580
3601
  }
3602
+ if ((initialData == null ? void 0 : initialData.toolResponseMetadata) !== void 0) {
3603
+ mock.toolResponseMetadata = initialData.toolResponseMetadata;
3604
+ }
3581
3605
  if ((initialData == null ? void 0 : initialData.widgetState) !== void 0) {
3582
3606
  mock.widgetState = initialData.widgetState;
3583
3607
  }
@@ -3626,38 +3650,42 @@ const DEFAULT_THEME = "dark";
3626
3650
  const DEFAULT_DISPLAY_MODE = "inline";
3627
3651
  function ChatGPTSimulator({
3628
3652
  children,
3629
- simulations = []
3653
+ simulations = [],
3654
+ appName = "Sunpeak App",
3655
+ appIcon
3630
3656
  }) {
3631
3657
  const [screenWidth, setScreenWidth] = React__namespace.useState("full");
3658
+ const getSimulationKey = (sim) => `${sim.resource.name}-${sim.tool.name}`;
3632
3659
  const [selectedKey, setSelectedKey] = React__namespace.useState(
3633
- simulations.length > 0 ? simulations[0].value : ""
3660
+ simulations.length > 0 ? getSimulationKey(simulations[0]) : ""
3634
3661
  );
3635
- const selectedSim = simulations.find((sim) => sim.value === selectedKey);
3636
- const appName = selectedSim == null ? void 0 : selectedSim.appName;
3637
- const appIcon = selectedSim == null ? void 0 : selectedSim.appIcon;
3662
+ const selectedSim = simulations.find((sim) => getSimulationKey(sim) === selectedKey);
3638
3663
  const userMessage = selectedSim == null ? void 0 : selectedSim.userMessage;
3639
- const toolOutput = (selectedSim == null ? void 0 : selectedSim.toolOutput) ?? null;
3640
- const widgetState = (selectedSim == null ? void 0 : selectedSim.widgetState) ?? null;
3641
3664
  const mock = React.useMemo(
3642
- () => initMockOpenAI({
3643
- theme: DEFAULT_THEME,
3644
- displayMode: DEFAULT_DISPLAY_MODE
3645
- }),
3646
- []
3665
+ () => {
3666
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
3667
+ return initMockOpenAI({
3668
+ theme: ((_a = selectedSim == null ? void 0 : selectedSim.simulationGlobals) == null ? void 0 : _a.theme) ?? DEFAULT_THEME,
3669
+ userAgent: (_b = selectedSim == null ? void 0 : selectedSim.simulationGlobals) == null ? void 0 : _b.userAgent,
3670
+ locale: (_c = selectedSim == null ? void 0 : selectedSim.simulationGlobals) == null ? void 0 : _c.locale,
3671
+ maxHeight: (_d = selectedSim == null ? void 0 : selectedSim.simulationGlobals) == null ? void 0 : _d.maxHeight,
3672
+ displayMode: ((_e = selectedSim == null ? void 0 : selectedSim.simulationGlobals) == null ? void 0 : _e.displayMode) ?? DEFAULT_DISPLAY_MODE,
3673
+ safeArea: (_f = selectedSim == null ? void 0 : selectedSim.simulationGlobals) == null ? void 0 : _f.safeArea,
3674
+ view: (_g = selectedSim == null ? void 0 : selectedSim.simulationGlobals) == null ? void 0 : _g.view,
3675
+ toolInput: (_h = selectedSim == null ? void 0 : selectedSim.simulationGlobals) == null ? void 0 : _h.toolInput,
3676
+ widgetState: ((_i = selectedSim == null ? void 0 : selectedSim.simulationGlobals) == null ? void 0 : _i.widgetState) ?? null,
3677
+ toolOutput: ((_j = selectedSim == null ? void 0 : selectedSim.toolCall) == null ? void 0 : _j.structuredContent) ?? null
3678
+ });
3679
+ },
3680
+ [selectedSim]
3647
3681
  );
3648
3682
  const theme = useTheme() ?? DEFAULT_THEME;
3649
3683
  const displayMode = useDisplayMode() ?? DEFAULT_DISPLAY_MODE;
3650
3684
  React.useLayoutEffect(() => {
3651
3685
  if (mock && typeof window !== "undefined") {
3652
3686
  window.openai = mock;
3653
- if (toolOutput !== void 0) {
3654
- mock.setToolOutput(toolOutput);
3655
- }
3656
- if (widgetState !== void 0) {
3657
- mock.setWidgetStateExternal(widgetState);
3658
- }
3659
3687
  }
3660
- }, [mock, toolOutput, widgetState]);
3688
+ }, [mock]);
3661
3689
  React.useEffect(() => {
3662
3690
  return () => {
3663
3691
  if (typeof window !== "undefined") {
@@ -3665,7 +3693,7 @@ function ChatGPTSimulator({
3665
3693
  }
3666
3694
  };
3667
3695
  }, []);
3668
- const SelectedComponent = selectedSim == null ? void 0 : selectedSim.component;
3696
+ const SelectedComponent = selectedSim == null ? void 0 : selectedSim.resourceComponent;
3669
3697
  const content = SelectedComponent ? /* @__PURE__ */ jsxRuntime.jsx(SelectedComponent, {}) : children;
3670
3698
  return /* @__PURE__ */ jsxRuntime.jsx(ThemeProvider, { theme, children: /* @__PURE__ */ jsxRuntime.jsx(
3671
3699
  SimpleSidebar,
@@ -3676,10 +3704,14 @@ function ChatGPTSimulator({
3676
3704
  {
3677
3705
  value: selectedKey,
3678
3706
  onChange: (value) => setSelectedKey(value),
3679
- options: simulations.map((sim) => ({
3680
- value: sim.value,
3681
- label: sim.label
3682
- }))
3707
+ options: simulations.map((sim) => {
3708
+ const resourceTitle = sim.resource.title || sim.resource.name;
3709
+ const toolTitle = sim.tool.title || sim.tool.name;
3710
+ return {
3711
+ value: getSimulationKey(sim),
3712
+ label: `${resourceTitle} ${toolTitle}`
3713
+ };
3714
+ })
3683
3715
  }
3684
3716
  ) }),
3685
3717
  /* @__PURE__ */ jsxRuntime.jsx(SidebarControl, { label: "Theme", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -3734,17 +3766,13 @@ function ChatGPTSimulator({
3734
3766
  }
3735
3767
  exports.ChatGPTSimulator = ChatGPTSimulator;
3736
3768
  exports.SCREEN_WIDTHS = SCREEN_WIDTHS;
3737
- exports.SET_GLOBALS_EVENT_TYPE = SET_GLOBALS_EVENT_TYPE;
3738
- exports.SetGlobalsEvent = SetGlobalsEvent;
3739
3769
  exports.ThemeProvider = ThemeProvider;
3740
3770
  exports.cn = cn;
3741
3771
  exports.getAPI = getAPI;
3742
3772
  exports.getGlobal = getGlobal;
3743
- exports.getOpenAiProvider = getOpenAiProvider;
3744
3773
  exports.getProvider = getProvider;
3745
3774
  exports.initMockOpenAI = initMockOpenAI;
3746
3775
  exports.isHoverAvailable = isHoverAvailable;
3747
- exports.isOpenAiAvailable = isOpenAiAvailable;
3748
3776
  exports.isPrimarilyTouchDevice = isPrimarilyTouchDevice;
3749
3777
  exports.isProviderAvailable = isProviderAvailable;
3750
3778
  exports.prefersReducedMotion = prefersReducedMotion;