sunpeak 0.12.8 → 0.12.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.
- package/README.md +123 -43
- package/dist/chatgpt/index.cjs +1 -1
- package/dist/chatgpt/index.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +2 -2
- package/dist/{simulator-url-CYMOGoB1.cjs → simulator-url-Bnxt0LlN.cjs} +3 -2
- package/dist/{simulator-url-CYMOGoB1.cjs.map → simulator-url-Bnxt0LlN.cjs.map} +1 -1
- package/dist/{simulator-url-DG79-dU3.js → simulator-url-CQhLDEdd.js} +2 -1
- package/dist/{simulator-url-DG79-dU3.js.map → simulator-url-CQhLDEdd.js.map} +1 -1
- package/package.json +1 -1
- package/template/dist/albums/albums.json +1 -1
- package/template/dist/carousel/carousel.json +1 -1
- package/template/dist/map/map.json +1 -1
- package/template/dist/review/review.json +1 -1
- package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Button.js +3 -3
- package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_SegmentedControl.js +1 -1
- package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Select.js +15 -15
- package/template/node_modules/.vite/deps/@openai_apps-sdk-ui_components_Textarea.js +3 -3
- package/template/node_modules/.vite/deps/_metadata.json +32 -32
- package/template/node_modules/.vite/deps/{chunk-24D227QE.js → chunk-OBBBT4IN.js} +7 -7
- package/template/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/template/tests/e2e/review.spec.ts +1 -1
- package/template/tests/simulations/review/review-diff-simulation.json +1 -1
- /package/template/node_modules/.vite/deps/{chunk-24D227QE.js.map → chunk-OBBBT4IN.js.map} +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/@openai_apps-sdk-ui_components_Avatar.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/@openai_apps-sdk-ui_components_Avatar.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/@openai_apps-sdk-ui_components_Button.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/@openai_apps-sdk-ui_components_Button.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/@openai_apps-sdk-ui_components_Checkbox.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/@openai_apps-sdk-ui_components_Checkbox.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/@openai_apps-sdk-ui_components_Icon.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/@openai_apps-sdk-ui_components_Icon.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/@openai_apps-sdk-ui_components_Input.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/@openai_apps-sdk-ui_components_Input.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/@openai_apps-sdk-ui_components_SegmentedControl.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/@openai_apps-sdk-ui_components_SegmentedControl.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/@openai_apps-sdk-ui_components_Select.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/@openai_apps-sdk-ui_components_Select.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/@openai_apps-sdk-ui_components_Textarea.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/@openai_apps-sdk-ui_components_Textarea.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/@openai_apps-sdk-ui_theme.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/@openai_apps-sdk-ui_theme.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-6CR5OFLH.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-6CR5OFLH.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-EGRHWZRV.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-EGRHWZRV.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-EXGLAROW.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-EXGLAROW.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-IFPDCKUT.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-IFPDCKUT.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-ILHRZGIS.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-ILHRZGIS.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-JSPMUVNT.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-JSPMUVNT.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-L2PWLFDO.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-L2PWLFDO.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-OMOWBQDU.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-OMOWBQDU.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-R3BTL4CL.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-R3BTL4CL.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-SPDZ46BB.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-SPDZ46BB.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-WSHFT23M.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-WSHFT23M.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-Y7UNCRGH.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-Y7UNCRGH.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-ZNFXUT4Q.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/chunk-ZNFXUT4Q.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/clsx.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/clsx.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/embla-carousel-react.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/embla-carousel-react.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/embla-carousel-wheel-gestures.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/embla-carousel-wheel-gestures.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/mapbox-gl.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/mapbox-gl.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/package.json +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/react-dom.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/react-dom.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/react-dom_client.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/react-dom_client.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/react.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/react.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/react_jsx-dev-runtime.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/react_jsx-dev-runtime.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/react_jsx-runtime.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/react_jsx-runtime.js.map +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/tailwind-merge.js +0 -0
- /package/template/node_modules/.vite-mcp/{deps_temp_c22d194e → deps_temp_e6e57b12}/tailwind-merge.js.map +0 -0
package/README.md
CHANGED
|
@@ -8,16 +8,17 @@
|
|
|
8
8
|
|
|
9
9
|
# sunpeak
|
|
10
10
|
|
|
11
|
-
[](https://www.npmjs.com/package/sunpeak)
|
|
12
|
+
[](https://www.npmjs.com/package/sunpeak)
|
|
13
|
+
[](https://github.com/Sunpeak-AI/sunpeak)
|
|
14
|
+
[](https://github.com/Sunpeak-AI/sunpeak/actions)
|
|
15
|
+
[](https://github.com/Sunpeak-AI/sunpeak/blob/main/LICENSE)
|
|
16
|
+
[](https://www.typescriptlang.org/)
|
|
17
|
+
[](https://reactjs.org/)
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
Local-first ChatGPT App framework.
|
|
19
20
|
|
|
20
|
-
Quickstart, build, test, and ship your ChatGPT App
|
|
21
|
+
Quickstart, build, test, and ship your ChatGPT App!
|
|
21
22
|
|
|
22
23
|
[Demo (Hosted)](https://sunpeak.ai/#simulator) ~
|
|
23
24
|
[Demo (Video)](https://d10djik02wlf6x.cloudfront.net/sunpeak-demo-prod.mp4) ~
|
|
@@ -43,21 +44,21 @@ pnpm add -g sunpeak
|
|
|
43
44
|
sunpeak new
|
|
44
45
|
```
|
|
45
46
|
|
|
46
|
-
To add sunpeak to an existing project, refer to the [documentation](https://docs.sunpeak.ai/add-to-existing-project).
|
|
47
|
+
To add `sunpeak` to an existing project, refer to the [documentation](https://docs.sunpeak.ai/add-to-existing-project).
|
|
47
48
|
|
|
48
49
|
## Overview
|
|
49
50
|
|
|
50
|
-
sunpeak is an npm package that helps you build ChatGPT Apps (MCP
|
|
51
|
+
`sunpeak` is an npm package that helps you build ChatGPT Apps (MCP resources) while keeping your MCP server client-agnostic. `sunpeak` consists of:
|
|
51
52
|
|
|
52
53
|
### The `sunpeak` library
|
|
53
54
|
|
|
54
55
|
1. Runtime APIs: Strongly typed APIs for interacting with the ChatGPT runtime, **architected to support future platforms** (Gemini, Claude, etc.).
|
|
55
|
-
2. ChatGPT simulator: React component replicating ChatGPT's runtime to **test Apps locally and automatically
|
|
56
|
+
2. ChatGPT simulator: React component replicating ChatGPT's runtime to **test Apps locally and automatically** via UI, props, or URL parameters.
|
|
56
57
|
3. MCP server: Serve Resources with mock data to the real ChatGPT with HMR (**no more cache issues or 5-click manual refreshes**).
|
|
57
58
|
|
|
58
59
|
### The `sunpeak` framework
|
|
59
60
|
|
|
60
|
-
Next.js for ChatGPT Apps. Using a Review
|
|
61
|
+
Next.js for ChatGPT Apps. Using an example App `my-app` with a `Review` UI (MCP resource), `sunpeak` projects look like:
|
|
61
62
|
|
|
62
63
|
```bash
|
|
63
64
|
my-app/
|
|
@@ -72,11 +73,11 @@ my-app/
|
|
|
72
73
|
└── package.json
|
|
73
74
|
```
|
|
74
75
|
|
|
75
|
-
1. Project scaffold: Complete development setup with the sunpeak library.
|
|
76
|
-
2. UI components: Production-ready components following ChatGPT design guidelines and using OpenAI apps-sdk-ui React components.
|
|
76
|
+
1. Project scaffold: Complete development setup with the `sunpeak` library.
|
|
77
|
+
2. UI components: Production-ready components following ChatGPT design guidelines and using OpenAI `apps-sdk-ui` React components.
|
|
77
78
|
3. Convention over configuration:
|
|
78
|
-
1. Create
|
|
79
|
-
2. Create test state (
|
|
79
|
+
1. Create a UI by creating a `-resource.tsx` component file ([example](#resource-component)) and `-resource.json` MCP metadata file ([example](#resource-mcp-metadata)).
|
|
80
|
+
2. Create test state (`Simulation`s) for local dev, ChatGPT dev, automated testing, and demos by creating a `-simulation.json` file. ([example](#simulation))
|
|
80
81
|
|
|
81
82
|
### The `sunpeak` CLI
|
|
82
83
|
|
|
@@ -93,46 +94,76 @@ Think Docker Hub for ChatGPT Apps:
|
|
|
93
94
|
</div>
|
|
94
95
|
|
|
95
96
|
1. Tag your app builds with version numbers and environment names (like `v1.0.0` and `prod`)
|
|
96
|
-
2. `push` built Apps to a central location
|
|
97
|
-
3. `pull` built Apps to be run in different environments, like your production MCP server.
|
|
97
|
+
2. `sunpeak push` built Apps to a central location
|
|
98
|
+
3. `sunpeak pull` built Apps to be run in different environments, like your production MCP server.
|
|
98
99
|
4. Share your fully-functional demo Apps with teammates, prospects, and strangers!
|
|
99
100
|
|
|
100
|
-
##
|
|
101
|
+
## Example App
|
|
101
102
|
|
|
102
|
-
Example
|
|
103
|
+
Example `Resource`, `Simulation`, and testing file (using `ChatGPTSimulator`) for an MCP resource called "Review".
|
|
103
104
|
|
|
104
|
-
### Resource Component
|
|
105
|
+
### `Resource` Component
|
|
105
106
|
|
|
106
|
-
|
|
107
|
+
```bash
|
|
108
|
+
my-app/
|
|
109
|
+
├── src/resources/
|
|
110
|
+
│ └── review/
|
|
111
|
+
│ ├── review-resource.tsx # This one!
|
|
112
|
+
│ └── review-resource.json
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
React component (`.tsx`) defining a UI (MCP resource) in your ChatGPT App.
|
|
107
116
|
|
|
108
117
|
```tsx
|
|
109
118
|
// src/resources/review-resource.tsx
|
|
110
|
-
|
|
119
|
+
|
|
120
|
+
import { useWidgetProps, useWidgetState } from 'sunpeak';
|
|
121
|
+
import { Button } from '@openai/apps-sdk-ui/components/Button';
|
|
111
122
|
|
|
112
123
|
export function ReviewResource() {
|
|
124
|
+
const data = useWidgetProps<{ title: string; changes: string[] }>();
|
|
125
|
+
const [state, setState] = useWidgetState<{ decision: string | null }>(() => ({
|
|
126
|
+
decision: null,
|
|
127
|
+
}));
|
|
128
|
+
|
|
113
129
|
return (
|
|
114
|
-
<
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
130
|
+
<div>
|
|
131
|
+
<h1>{data.title}</h1>
|
|
132
|
+
<ul>
|
|
133
|
+
{data.changes.map((change, i) => (
|
|
134
|
+
<li key={i}>{change}</li>
|
|
135
|
+
))}
|
|
136
|
+
</ul>
|
|
137
|
+
{state.decision ? (
|
|
138
|
+
<p>{state.decision === 'approved' ? 'Approved!' : 'Rejected'}</p>
|
|
139
|
+
) : (
|
|
140
|
+
<>
|
|
141
|
+
<Button onClick={() => setState({ decision: 'approved' })}>Approve</Button>
|
|
142
|
+
<Button onClick={() => setState({ decision: 'rejected' })}>Reject</Button>
|
|
143
|
+
</>
|
|
144
|
+
)}
|
|
145
|
+
</div>
|
|
124
146
|
);
|
|
125
147
|
}
|
|
126
148
|
```
|
|
127
149
|
|
|
128
|
-
### Resource MCP Metadata
|
|
150
|
+
### `Resource` MCP Metadata
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
my-app/
|
|
154
|
+
├── src/resources/
|
|
155
|
+
│ └── review/
|
|
156
|
+
│ ├── review-resource.tsx
|
|
157
|
+
│ └── review-resource.json # This one!
|
|
158
|
+
```
|
|
129
159
|
|
|
130
|
-
MCP metadata for your UI. Version your resource metadata alongside the resource itself.
|
|
160
|
+
MCP metadata (`.json`) for your UI. Version your resource metadata alongside the resource itself.
|
|
131
161
|
|
|
132
|
-
This is just an official [MCP
|
|
162
|
+
This is just an official [MCP resource object](https://modelcontextprotocol.io/specification/2025-11-25/server/resources#resource).
|
|
133
163
|
|
|
134
164
|
```jsonc
|
|
135
165
|
// src/resources/review-resource.json
|
|
166
|
+
|
|
136
167
|
{
|
|
137
168
|
"name": "review",
|
|
138
169
|
"title": "Review",
|
|
@@ -147,21 +178,28 @@ This is just an official [MCP Resource object](https://modelcontextprotocol.io/s
|
|
|
147
178
|
}
|
|
148
179
|
```
|
|
149
180
|
|
|
150
|
-
### Simulation
|
|
181
|
+
### `Simulation`
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
├── tests/simulations/
|
|
185
|
+
│ └── review/
|
|
186
|
+
│ ├── review-{scenario1}-simulation.json # These!
|
|
187
|
+
│ └── review-{scenario2}-simulation.json # These!
|
|
188
|
+
```
|
|
151
189
|
|
|
152
|
-
`sunpeak` object
|
|
190
|
+
`sunpeak` testing object (`.json`) defining key App-owned states.
|
|
153
191
|
|
|
154
|
-
|
|
192
|
+
Testing a ChatGPT App requires setting a lot of state: state in your **backend**, **MCP tools**, **stored widget runtime**, and ChatGPT itself.
|
|
155
193
|
|
|
156
|
-
Simulation files contain an [official MCP
|
|
194
|
+
`Simulation` files contain an [official MCP tool object](https://modelcontextprotocol.io/specification/2025-11-25/server/tools#tool), an [official MCP CallToolResult object](https://modelcontextprotocol.io/specification/2025-11-25/server/tools#structured-content), and a [sunpeak widgetState object](https://docs.sunpeak.ai/api-reference/hooks/use-widget-state) so you can define **backend**, **tool**, and **stored widget runtime** states for testing.
|
|
157
195
|
|
|
158
196
|
```jsonc
|
|
159
197
|
// tests/simulations/review-diff-simulation.json
|
|
198
|
+
|
|
160
199
|
{
|
|
161
|
-
|
|
162
|
-
// Official MCP Tool object.
|
|
200
|
+
// Official MCP tool object.
|
|
163
201
|
"tool": {
|
|
164
|
-
"name": "diff
|
|
202
|
+
"name": "review-diff",
|
|
165
203
|
"description": "Show a review dialog for a proposed code diff",
|
|
166
204
|
"inputSchema": { "type": "object", "properties": {}, "additionalProperties": false },
|
|
167
205
|
"title": "Diff Review",
|
|
@@ -176,13 +214,55 @@ Simulation files contain an [official MCP Tool object](https://modelcontextproto
|
|
|
176
214
|
// Official MCP CallToolResult object.
|
|
177
215
|
"callToolResult": {
|
|
178
216
|
"structuredContent": {
|
|
217
|
+
"title": "Refactor Authentication Module",
|
|
179
218
|
// ...
|
|
180
219
|
},
|
|
181
220
|
"_meta": {},
|
|
182
221
|
},
|
|
222
|
+
// Initial widget state object (persisted in ChatGPT).
|
|
223
|
+
"widgetState": {
|
|
224
|
+
// ...
|
|
225
|
+
},
|
|
183
226
|
}
|
|
184
227
|
```
|
|
185
228
|
|
|
229
|
+
### `ChatGPTSimulator`
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
├── tests/e2e/
|
|
233
|
+
│ └── review.spec.ts # This! (not pictured above for simplicity)
|
|
234
|
+
└── package.json
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
The `ChatGPTSimulator` allows you to set **ChatGPT state** (like light/dark mode) via URL params, which can be rendered alongside your `Simulation`s and tested via pre-configured Playwright end-to-end tests (`.spec.ts`).
|
|
238
|
+
|
|
239
|
+
Using the `ChatGPTSimulator` and `Simulation`s, you can test all possible App states locally and automatically!
|
|
240
|
+
|
|
241
|
+
```ts
|
|
242
|
+
// tests/e2e/review.spec.ts
|
|
243
|
+
|
|
244
|
+
import { test, expect } from '@playwright/test';
|
|
245
|
+
import { createSimulatorUrl } from 'sunpeak/chatgpt';
|
|
246
|
+
|
|
247
|
+
test.describe('Review Resource', () => {
|
|
248
|
+
test.describe('Light Mode', () => {
|
|
249
|
+
test('should render review title with correct styles', async ({ page }) => {
|
|
250
|
+
params = { simulation: 'review-diff', theme: 'light' }; // Set sim & ChatGPT state.
|
|
251
|
+
await page.goto(createSimulatorUrl(params));
|
|
252
|
+
await page.waitForLoadState('networkidle');
|
|
253
|
+
|
|
254
|
+
const title = page.locator('h1:has-text("Refactor Authentication Module")');
|
|
255
|
+
await expect(title).toBeVisible();
|
|
256
|
+
|
|
257
|
+
const color = await title.evaluate((el) => window.getComputedStyle(el).color);
|
|
258
|
+
|
|
259
|
+
// Light mode should render dark text.
|
|
260
|
+
expect(color).toBe('rgb(13, 13, 13)');
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
```
|
|
265
|
+
|
|
186
266
|
## Resources
|
|
187
267
|
|
|
188
268
|
- [ChatGPT Apps SDK Design Guidelines](https://developers.openai.com/apps-sdk/concepts/design-guidelines)
|
package/dist/chatgpt/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const simulatorUrl = require("../simulator-url-
|
|
3
|
+
const simulatorUrl = require("../simulator-url-Bnxt0LlN.cjs");
|
|
4
4
|
exports.ChatGPTSimulator = simulatorUrl.ChatGPTSimulator;
|
|
5
5
|
exports.IframeResource = simulatorUrl.IframeResource;
|
|
6
6
|
exports.ThemeProvider = simulatorUrl.ThemeProvider;
|
package/dist/chatgpt/index.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const simulatorUrl = require("./simulator-url-
|
|
3
|
+
const simulatorUrl = require("./simulator-url-Bnxt0LlN.cjs");
|
|
4
4
|
const React = require("react");
|
|
5
5
|
function _interopNamespaceDefault(e) {
|
|
6
6
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as clsx } from "./simulator-url-
|
|
2
|
-
import { C, I, S, T, c, v, s, q, i, r, w, t, e, f, g, h, j, u, k, l, m, n, d, b, o, p } from "./simulator-url-
|
|
1
|
+
import { a as clsx } from "./simulator-url-CQhLDEdd.js";
|
|
2
|
+
import { C, I, S, T, c, v, s, q, i, r, w, t, e, f, g, h, j, u, k, l, m, n, d, b, o, p } from "./simulator-url-CQhLDEdd.js";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
const MOBILE_BREAKPOINT = 768;
|
|
5
5
|
function useIsMobile() {
|
|
@@ -5620,7 +5620,7 @@ const useEscCloseStack = (listening, cb) => {
|
|
|
5620
5620
|
}, [id, listening, latestCallback]);
|
|
5621
5621
|
};
|
|
5622
5622
|
const __vite_import_meta_env__ = { "DEV": false, "MODE": "production" };
|
|
5623
|
-
const META_ENV = typeof { url: typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("simulator-url-
|
|
5623
|
+
const META_ENV = typeof { url: typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("simulator-url-Bnxt0LlN.cjs", document.baseURI).href } !== "undefined" ? __vite_import_meta_env__ : void 0;
|
|
5624
5624
|
const NODE_ENV = typeof process !== "undefined" && process.env?.NODE_ENV ? process.env?.NODE_ENV : "production";
|
|
5625
5625
|
const isDev = NODE_ENV === "development" || !!META_ENV?.DEV;
|
|
5626
5626
|
const isJSDomLike = typeof navigator !== "undefined" && /(jsdom|happy-dom)/i.test(navigator.userAgent) || typeof globalThis.happyDOM === "object";
|
|
@@ -8744,6 +8744,7 @@ function ChatGPTSimulator({
|
|
|
8744
8744
|
mock.setWidgetStateExternal(selectedSim.widgetState);
|
|
8745
8745
|
}
|
|
8746
8746
|
mock.toolOutput = selectedSim.callToolResult?.structuredContent ?? null;
|
|
8747
|
+
mock.toolResponseMetadata = selectedSim.callToolResult?._meta ?? null;
|
|
8747
8748
|
}
|
|
8748
8749
|
}, [selectedSimulationName, selectedSim, mock]);
|
|
8749
8750
|
const theme = useTheme() ?? DEFAULT_THEME;
|
|
@@ -9280,4 +9281,4 @@ exports.useWidgetAPI = useWidgetAPI;
|
|
|
9280
9281
|
exports.useWidgetGlobal = useWidgetGlobal;
|
|
9281
9282
|
exports.useWidgetProps = useWidgetProps;
|
|
9282
9283
|
exports.useWidgetState = useWidgetState;
|
|
9283
|
-
//# sourceMappingURL=simulator-url-
|
|
9284
|
+
//# sourceMappingURL=simulator-url-Bnxt0LlN.cjs.map
|