Skip to content

Commit b9ef64c

Browse files
committed
webplus -> openai
1 parent 5fb4ae5 commit b9ef64c

File tree

10 files changed

+100
-244
lines changed

10 files changed

+100
-244
lines changed

src/pizzaz-albums/index.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import React from "react";
22
import { createRoot } from "react-dom/client";
33
import useEmblaCarousel from "embla-carousel-react";
4-
import { ArrowLeft, ArrowRight, Maximize2 } from "lucide-react";
4+
import { ArrowLeft, ArrowRight } from "lucide-react";
55
import albumsData from "./albums.json";
66
import { useMaxHeight } from "../use-max-height";
7-
import { useWebplusGlobal } from "../use-webplus-global";
7+
import { useOpenAiGlobal } from "../use-openai-global";
88
import FullscreenViewer from "./FullscreenViewer";
99
import AlbumCard from "./AlbumCard";
1010

@@ -111,7 +111,7 @@ function AlbumsCarousel({ onSelect }) {
111111
}
112112

113113
function App() {
114-
const displayMode = useWebplusGlobal("displayMode");
114+
const displayMode = useOpenAiGlobal("displayMode");
115115
const [selectedAlbum, setSelectedAlbum] = React.useState(null);
116116
const maxHeight = useMaxHeight() ?? undefined;
117117

src/pizzaz/Sidebar.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from "react";
22
import useEmblaCarousel from "embla-carousel-react";
3-
import { useWebplusGlobal } from "../use-webplus-global";
3+
import { useOpenAiGlobal } from "../use-openai-global";
44
import { Filter, Settings2, Star } from "lucide-react";
55
import { AnimatePresence, motion } from "framer-motion";
66

@@ -45,7 +45,7 @@ function PlaceListItem({ place, isSelected, onClick }) {
4545

4646
export default function Sidebar({ places, selectedId, onSelect }) {
4747
const [emblaRef] = useEmblaCarousel({ dragFree: true, loop: false });
48-
const displayMode = useWebplusGlobal("displayMode");
48+
const displayMode = useOpenAiGlobal("displayMode");
4949
const forceMobile = displayMode !== "fullscreen";
5050
const scrollRef = React.useRef(null);
5151
const [showBottomFade, setShowBottomFade] = React.useState(false);

src/pizzaz/index.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import markers from "./markers.json";
66
import { AnimatePresence } from "framer-motion";
77
import Inspector from "./Inspector";
88
import Sidebar from "./Sidebar";
9-
import { useWebplusGlobal } from "../use-webplus-global";
9+
import { useOpenAiGlobal } from "../use-openai-global";
1010
import { useMaxHeight } from "../use-max-height";
1111
import { Maximize2 } from "lucide-react";
1212
import {
@@ -51,7 +51,7 @@ export default function App() {
5151
center: markerCoords.length > 0 ? markerCoords[0] : [0, 0],
5252
zoom: markerCoords.length > 0 ? 12 : 2,
5353
}));
54-
const displayMode = useWebplusGlobal("displayMode");
54+
const displayMode = useOpenAiGlobal("displayMode");
5555
const allowInspector = displayMode === "fullscreen";
5656
const maxHeight = useMaxHeight() ?? undefined;
5757

src/types.ts

Lines changed: 42 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,64 @@
1-
type UnknownObject = Record<string, unknown>;
2-
3-
export type WidgetState = UnknownObject;
4-
5-
export type SetWidgetState = (state: WidgetState) => Promise<void>;
6-
7-
export type Theme = "light" | "dark";
8-
9-
export type SafeAreaInsets = {
10-
top: number;
11-
bottom: number;
12-
left: number;
13-
right: number;
14-
};
15-
16-
export type SafeArea = {
17-
insets: SafeAreaInsets;
18-
};
19-
20-
export type UserAgent = {
21-
//
22-
};
23-
24-
export type WebplusGlobals = {
1+
export type OpenAiGlobals<
2+
ToolInput = UnknownObject,
3+
ToolOutput = UnknownObject,
4+
ToolResponseMetadata = UnknownObject,
5+
WidgetState = UnknownObject
6+
> = {
257
// visuals
268
theme: Theme;
279

2810
userAgent: UserAgent;
11+
locale: string;
2912

3013
// layout
3114
maxHeight: number;
3215
displayMode: DisplayMode;
3316
safeArea: SafeArea;
3417

3518
// state
36-
toolInput: UnknownObject;
37-
toolOutput: UnknownObject;
38-
widgetState: UnknownObject | null;
39-
setWidgetState: SetWidgetState;
19+
toolInput: ToolInput;
20+
toolOutput: ToolOutput | null;
21+
toolResponseMetadata: ToolResponseMetadata | null;
22+
widgetState: WidgetState | null;
23+
setWidgetState: (state: WidgetState) => Promise<void>;
4024
};
4125

4226
// currently copied from types.ts in chatgpt/web-sandbox.
4327
// Will eventually use a public package.
4428
type API = {
45-
// Calling APIs
46-
streamCompletion: StreamCompletion;
47-
callCompletion: CallCompletion;
4829
callTool: CallTool;
49-
sendFollowUpMessage: SendFollowUpMessage;
30+
sendFollowUpMessage: (args: { prompt: string }) => Promise<void>;
31+
openExternal(payload: { href: string }): void;
5032

5133
// Layout controls
5234
requestDisplayMode: RequestDisplayMode;
5335
};
5436

37+
export type UnknownObject = Record<string, unknown>;
38+
39+
export type Theme = "light" | "dark";
40+
41+
export type SafeAreaInsets = {
42+
top: number;
43+
bottom: number;
44+
left: number;
45+
right: number;
46+
};
47+
48+
export type SafeArea = {
49+
insets: SafeAreaInsets;
50+
};
51+
52+
export type DeviceType = "mobile" | "tablet" | "desktop" | "unknown";
53+
54+
export type UserAgent = {
55+
device: { type: DeviceType };
56+
capabilities: {
57+
hover: boolean;
58+
touch: boolean;
59+
};
60+
};
61+
5562
/** Display mode */
5663
export type DisplayMode = "pip" | "inline" | "fullscreen";
5764
export type RequestDisplayMode = (args: { mode: DisplayMode }) => Promise<{
@@ -72,106 +79,23 @@ export type CallTool = (
7279
args: Record<string, unknown>
7380
) => Promise<CallToolResponse>;
7481

75-
// Subest of the the params for sampling/createMessage
76-
export type ModelHintName = "thinking-none" | "thinking-low" | "thinking-high";
77-
78-
export type CompletionStreamOptions = {
79-
systemPrompt?: string | null;
80-
modelType?: ModelHintName;
81-
};
82-
83-
export type Annotations = {
84-
audience?: ("user" | "assistant")[] | null;
85-
priority?: number | null;
86-
};
87-
88-
export type TextContent = {
89-
type: "text";
90-
text: string;
91-
annotations?: Annotations | null;
92-
_meta?: Record<string, never> | null;
93-
};
94-
95-
export type ImageContent = {
96-
type: "image";
97-
data: string;
98-
mimeType: string;
99-
annotations?: Annotations | null;
100-
_meta?: Record<string, never> | null;
101-
};
102-
103-
export type AudioContent = {
104-
type: "audio";
105-
data: string;
106-
mimeType: string;
107-
annotations?: Annotations | null;
108-
_meta?: Record<string, never> | null;
109-
};
110-
111-
export type SamplingMessage = {
112-
role: "user" | "assistant";
113-
content: TextContent | ImageContent | AudioContent;
114-
};
115-
116-
export type ModelHint = {
117-
name: ModelHintName;
118-
};
119-
120-
export type ModelPreferences = {
121-
hints: ModelHint[];
122-
};
123-
124-
export type CreateMessageRequestParams = {
125-
messages: SamplingMessage[];
126-
modelPreferences: ModelPreferences;
127-
systemPrompt?: string | null;
128-
metadata?: Record<string, string> | null;
129-
};
130-
131-
export type CreateMessageResponse = {
132-
content: TextContent | ImageContent | AudioContent;
133-
model: string;
134-
role: "assistant";
135-
stopReason?: string;
136-
};
137-
138-
// this is the MCP sample stream
139-
export type StreamCompletion = (
140-
request: CreateMessageRequestParams
141-
) => AsyncIterable<CreateMessageResponse>;
142-
143-
export type CallCompletion = (
144-
request: CreateMessageRequestParams
145-
) => Promise<CreateMessageResponse>;
146-
147-
export type SendFollowUpMessage = (args: { prompt: string }) => Promise<void>;
148-
14982
/** Extra events */
150-
export const SET_GLOBALS_EVENT_TYPE = "webplus:set_globals";
83+
export const SET_GLOBALS_EVENT_TYPE = "openai:set_globals";
15184
export class SetGlobalsEvent extends CustomEvent<{
152-
globals: Partial<WebplusGlobals>;
85+
globals: Partial<OpenAiGlobals>;
15386
}> {
15487
readonly type = SET_GLOBALS_EVENT_TYPE;
15588
}
15689

157-
export const TOOL_RESPONSE_EVENT_TYPE = "webplus:tool_response";
158-
export class ToolResponseEvent extends CustomEvent<{
159-
tool: { name: string; args: UnknownObject };
160-
}> {
161-
readonly type = TOOL_RESPONSE_EVENT_TYPE;
162-
}
163-
16490
/**
16591
* Global oai object injected by the web sandbox for communicating with chatgpt host page.
16692
*/
16793
declare global {
16894
interface Window {
169-
webplus: API & WebplusGlobals;
170-
openai: API & WebplusGlobals;
95+
openai: API & OpenAiGlobals;
17196
}
17297

17398
interface WindowEventMap {
17499
[SET_GLOBALS_EVENT_TYPE]: SetGlobalsEvent;
175-
[TOOL_RESPONSE_EVENT_TYPE]: ToolResponseEvent;
176100
}
177101
}

src/use-display-mode.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { useWebplusGlobal } from "./use-webplus-global";
1+
import { useOpenAiGlobal } from "./use-openai-global";
22
import { type DisplayMode } from "./types";
33

44
export const useDisplayMode = (): DisplayMode | null => {
5-
return useWebplusGlobal("displayMode");
5+
return useOpenAiGlobal("displayMode");
66
};

src/use-max-height.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { useWebplusGlobal } from "./use-webplus-global";
1+
import { useOpenAiGlobal } from "./use-openai-global";
22

33
export const useMaxHeight = (): number | null => {
4-
return useWebplusGlobal("maxHeight");
4+
return useOpenAiGlobal("maxHeight");
55
};

src/use-openai-global.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { useSyncExternalStore } from "react";
2+
import {
3+
SET_GLOBALS_EVENT_TYPE,
4+
SetGlobalsEvent,
5+
type OpenAiGlobals,
6+
} from "./types";
7+
8+
export function useOpenAiGlobal<K extends keyof OpenAiGlobals>(
9+
key: K
10+
): OpenAiGlobals[K] | null {
11+
return useSyncExternalStore(
12+
(onChange) => {
13+
if (typeof window === "undefined") {
14+
return () => {};
15+
}
16+
17+
const handleSetGlobal = (event: SetGlobalsEvent) => {
18+
const value = event.detail.globals[key];
19+
if (value === undefined) {
20+
return;
21+
}
22+
23+
onChange();
24+
};
25+
26+
window.addEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal, {
27+
passive: true,
28+
});
29+
30+
return () => {
31+
window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal);
32+
};
33+
},
34+
() => window.openai?.[key] ?? null,
35+
() => window.openai?.[key] ?? null
36+
);
37+
}

0 commit comments

Comments
 (0)