sunpeak 0.16.18 → 0.16.21

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 (71) hide show
  1. package/README.md +1 -1
  2. package/dist/chatgpt/index.cjs +1 -1
  3. package/dist/chatgpt/index.js +1 -1
  4. package/dist/claude/index.cjs +1 -1
  5. package/dist/claude/index.js +1 -1
  6. package/dist/{platform → host}/chatgpt/index.cjs +1 -1
  7. package/dist/host/chatgpt/index.cjs.map +1 -0
  8. package/dist/{platform → host}/chatgpt/index.d.ts +2 -2
  9. package/dist/{platform → host}/chatgpt/index.js +1 -1
  10. package/dist/host/chatgpt/index.js.map +1 -0
  11. package/dist/{platform → host}/chatgpt/use-create-file.d.ts +2 -2
  12. package/dist/{platform → host}/chatgpt/use-file-download.d.ts +2 -2
  13. package/dist/{platform → host}/chatgpt/use-open-modal.d.ts +2 -2
  14. package/dist/{platform → host}/chatgpt/use-request-checkout.d.ts +2 -2
  15. package/dist/{platform → host}/index.cjs +5 -3
  16. package/dist/host/index.cjs.map +1 -0
  17. package/dist/{platform → host}/index.d.ts +15 -11
  18. package/dist/{platform → host}/index.js +5 -3
  19. package/dist/host/index.js.map +1 -0
  20. package/dist/{index-C_uYg-eE.js → index-B4aC3vjH.js} +2 -2
  21. package/dist/index-B4aC3vjH.js.map +1 -0
  22. package/dist/{index-CJ3nfg7Q.cjs → index-CKabCJyV.cjs} +2 -2
  23. package/dist/index-CKabCJyV.cjs.map +1 -0
  24. package/dist/{index-BITfgMxk.js → index-CX6Z4bED.js} +2 -2
  25. package/dist/index-CX6Z4bED.js.map +1 -0
  26. package/dist/{index-DxCrGGzy.cjs → index-bKBBCBK6.cjs} +2 -2
  27. package/dist/index-bKBBCBK6.cjs.map +1 -0
  28. package/dist/index.cjs +193 -6294
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.ts +4 -2
  31. package/dist/index.js +189 -6290
  32. package/dist/index.js.map +1 -1
  33. package/dist/mcp/index.cjs +656 -6758
  34. package/dist/mcp/index.cjs.map +1 -1
  35. package/dist/mcp/index.js +658 -6760
  36. package/dist/mcp/index.js.map +1 -1
  37. package/dist/{protocol-CfvM5B6z.cjs → protocol-DkDHRwOW.cjs} +50 -5
  38. package/dist/{protocol-CfvM5B6z.cjs.map → protocol-DkDHRwOW.cjs.map} +1 -1
  39. package/dist/{protocol-CF-P_kw5.js → protocol-uge7qFev.js} +102 -57
  40. package/dist/{protocol-CF-P_kw5.js.map → protocol-uge7qFev.js.map} +1 -1
  41. package/dist/simulator/index.cjs +1 -1
  42. package/dist/simulator/index.js +1 -1
  43. package/dist/simulator-D8t-r7HH.js +3222 -0
  44. package/dist/simulator-D8t-r7HH.js.map +1 -0
  45. package/dist/simulator-FFNttkqL.cjs +3237 -0
  46. package/dist/simulator-FFNttkqL.cjs.map +1 -0
  47. package/dist/use-app-C9gpzIQO.js +349 -0
  48. package/dist/use-app-C9gpzIQO.js.map +1 -0
  49. package/dist/use-app-D09O2swh.cjs +348 -0
  50. package/dist/use-app-D09O2swh.cjs.map +1 -0
  51. package/package.json +25 -13
  52. package/template/node_modules/.bin/vite +2 -2
  53. package/template/node_modules/.bin/vitest +2 -2
  54. package/template/package.json +5 -5
  55. package/dist/index-BITfgMxk.js.map +0 -1
  56. package/dist/index-CJ3nfg7Q.cjs.map +0 -1
  57. package/dist/index-C_uYg-eE.js.map +0 -1
  58. package/dist/index-DxCrGGzy.cjs.map +0 -1
  59. package/dist/platform/chatgpt/index.cjs.map +0 -1
  60. package/dist/platform/chatgpt/index.js.map +0 -1
  61. package/dist/platform/index.cjs.map +0 -1
  62. package/dist/platform/index.js.map +0 -1
  63. package/dist/simulator-DfTsXTK4.js +0 -9323
  64. package/dist/simulator-DfTsXTK4.js.map +0 -1
  65. package/dist/simulator-mbqealxY.cjs +0 -9338
  66. package/dist/simulator-mbqealxY.cjs.map +0 -1
  67. package/dist/use-app-CaTJmpgj.cjs +0 -6449
  68. package/dist/use-app-CaTJmpgj.cjs.map +0 -1
  69. package/dist/use-app-DTTzqi-0.js +0 -6450
  70. package/dist/use-app-DTTzqi-0.js.map +0 -1
  71. /package/dist/{platform → host}/chatgpt/openai-types.d.ts +0 -0
package/README.md CHANGED
@@ -49,7 +49,7 @@ sunpeak new
49
49
 
50
50
  ### The `sunpeak` library
51
51
 
52
- 1. Runtime APIs: Strongly typed React hooks for interacting with the host runtime (`useApp`, `useToolData`, `useAppState`, `useHostContext`, `useUpdateModelContext`, `useAppTools`), architected to **support generic and platform-specific features** (ChatGPT, Claude, etc.). Platform-specific hooks like `useUploadFile`, `useRequestModal`, and `useRequestCheckout` are available via `sunpeak/platform/chatgpt`, with `isChatGPT()` / `isClaude()` platform detection via `sunpeak/platform`.
52
+ 1. Runtime APIs: Strongly typed React hooks for interacting with the host runtime (`useApp`, `useToolData`, `useAppState`, `useHostContext`, `useUpdateModelContext`, `useAppTools`), architected to **support generic and platform-specific features** (ChatGPT, Claude, etc.). Host-specific hooks like `useUploadFile`, `useRequestModal`, and `useRequestCheckout` are available via `sunpeak/host/chatgpt`, with `isChatGPT()` / `isClaude()` host detection via `sunpeak/host`.
53
53
  2. Multi-host simulator: React component replicating host runtimes (ChatGPT, Claude) to **test Apps locally and automatically** via UI, props, or URL parameters.
54
54
  3. MCP server: Serve Resources with mock data to hosts like ChatGPT and Claude with HMR (**no more cache issues or 5-click manual refreshes**).
55
55
 
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const simulator = require("../simulator-mbqealxY.cjs");
3
+ const simulator = require("../simulator-FFNttkqL.cjs");
4
4
  const simulatorUrl = require("../simulator-url-DcSYRl-P.cjs");
5
5
  const discovery = require("../discovery-D1gpaVz4.cjs");
6
6
  exports.IframeResource = simulator.IframeResource;
@@ -1,4 +1,4 @@
1
- import { I, M, a, S, T, j, m, n } from "../simulator-DfTsXTK4.js";
1
+ import { I, M, a, S, T, j, m, n } from "../simulator-D8t-r7HH.js";
2
2
  import { c } from "../simulator-url-j_XV3EoP.js";
3
3
  import { b, a as a2, c as c2, d, e, f, g, h, i, t } from "../discovery-BVqD-JsT.js";
4
4
  export {
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const simulator = require("../simulator-mbqealxY.cjs");
3
+ const simulator = require("../simulator-FFNttkqL.cjs");
4
4
  exports.Simulator = simulator.Simulator;
5
5
  //# sourceMappingURL=index.cjs.map
@@ -1,4 +1,4 @@
1
- import { S } from "../simulator-DfTsXTK4.js";
1
+ import { S } from "../simulator-D8t-r7HH.js";
2
2
  export {
3
3
  S as Simulator
4
4
  };
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const React = require("react");
4
- const useApp = require("../../use-app-CaTJmpgj.cjs");
4
+ const useApp = require("../../use-app-D09O2swh.cjs");
5
5
  function getOpenAIRuntime() {
6
6
  if (typeof window !== "undefined" && "openai" in window) {
7
7
  return window.openai;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../../../src/host/chatgpt/openai-types.ts","../../../src/host/chatgpt/use-create-file.ts","../../../src/host/chatgpt/use-file-download.ts","../../../src/host/chatgpt/use-open-modal.ts","../../../src/host/chatgpt/use-request-checkout.ts"],"sourcesContent":["/**\n * TypeScript declarations for the `window.openai` ChatGPT runtime.\n *\n * These APIs are available inside ChatGPT-hosted iframes and provide\n * platform-specific capabilities beyond the MCP Apps standard.\n *\n * @see https://developers.openai.com/apps-sdk/mcp-apps-in-chatgpt\n */\n\nexport interface OpenAIUploadFileResult {\n fileId: string;\n}\n\nexport interface OpenAIFileDownloadUrlResult {\n downloadUrl: string;\n}\n\nexport interface OpenAIRequestModalParams {\n /** URL of an alternate UI template to load in the modal. Omit to reuse the current UI. */\n template?: string;\n /** Arbitrary params forwarded to the modal content. */\n params?: Record<string, unknown>;\n}\n\nexport interface OpenAICheckoutPaymentProvider {\n provider: string;\n merchant_id: string;\n supported_payment_methods: string[];\n}\n\nexport interface OpenAICheckoutTotal {\n type: string;\n display_text: string;\n amount: number;\n}\n\nexport interface OpenAICheckoutLink {\n type: 'terms_of_use' | 'privacy_policy' | string;\n url: string;\n}\n\nexport interface OpenAICheckoutSession {\n id: string;\n payment_provider: OpenAICheckoutPaymentProvider;\n status: 'ready_for_payment';\n currency: string;\n totals: OpenAICheckoutTotal[];\n links: OpenAICheckoutLink[];\n payment_mode: 'live' | 'test';\n}\n\nexport interface OpenAICheckoutOrder {\n id: string;\n checkout_session_id: string;\n status: 'completed' | string;\n permalink_url?: string;\n}\n\n/**\n * The `window.openai` runtime object injected by ChatGPT into hosted iframes.\n */\nexport interface OpenAIRuntime {\n // --- File APIs ---\n uploadFile?(file: File): Promise<OpenAIUploadFileResult>;\n getFileDownloadUrl?(params: { fileId: string }): Promise<OpenAIFileDownloadUrlResult>;\n\n // --- Modal API ---\n requestModal?(params: OpenAIRequestModalParams): Promise<void>;\n\n // --- Checkout API ---\n requestCheckout?(session: OpenAICheckoutSession): Promise<OpenAICheckoutOrder>;\n\n // --- Display ---\n requestClose?(): void;\n requestDisplayMode?(params: { mode: 'inline' | 'PiP' | 'fullscreen' }): Promise<void>;\n\n // --- Messaging ---\n sendFollowUpMessage?(params: { prompt: string }): void;\n\n // --- Other ---\n openExternal?(params: { href: string }): void;\n}\n\n/**\n * Get the `window.openai` runtime if available.\n * Returns `undefined` outside of ChatGPT or in SSR.\n */\nexport function getOpenAIRuntime(): OpenAIRuntime | undefined {\n if (typeof window !== 'undefined' && 'openai' in window) {\n return (window as unknown as { openai: OpenAIRuntime }).openai;\n }\n return undefined;\n}\n","import { useCallback } from 'react';\nimport { useApp } from '../../hooks/use-app';\nimport { getOpenAIRuntime, type OpenAIUploadFileResult } from './openai-types';\n\nexport type { OpenAIUploadFileResult as CreateFileResult };\n\n/**\n * Upload a file from the app UI into the ChatGPT conversation.\n *\n * Wraps `window.openai.uploadFile` which is only available inside ChatGPT.\n * Supported formats: `image/png`, `image/jpeg`, `image/webp`.\n *\n * Import from `sunpeak/host/chatgpt`:\n *\n * @example\n * ```tsx\n * import { useUploadFile } from 'sunpeak/host/chatgpt';\n *\n * function ImageUploader() {\n * const uploadFile = useUploadFile();\n *\n * const handleChange = async (e: React.ChangeEvent<HTMLInputElement>) => {\n * const file = e.currentTarget.files?.[0];\n * if (!file) return;\n * const { fileId } = await uploadFile(file);\n * console.log('Uploaded:', fileId);\n * };\n *\n * return <input type=\"file\" accept=\"image/*\" onChange={handleChange} />;\n * }\n * ```\n */\nexport function useUploadFile(): (file: File) => Promise<OpenAIUploadFileResult> {\n const app = useApp();\n return useCallback(\n async (file: File) => {\n if (!app) {\n throw new Error('[useUploadFile] App not connected');\n }\n const runtime = getOpenAIRuntime();\n if (!runtime?.uploadFile) {\n throw new Error('[useUploadFile] window.openai.uploadFile not available');\n }\n return runtime.uploadFile(file);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport { useApp } from '../../hooks/use-app';\nimport { getOpenAIRuntime, type OpenAIFileDownloadUrlResult } from './openai-types';\n\nexport type { OpenAIFileDownloadUrlResult as FileDownloadUrlResult };\n\n/**\n * Get a temporary download URL for a file by its ID.\n *\n * @deprecated Use {@link useDownloadFile} from `sunpeak` instead — it works\n * across all hosts via the MCP Apps SDK `app.downloadFile()` method.\n *\n * Wraps `window.openai.getFileDownloadUrl` which is only available inside\n * ChatGPT. Use this to retrieve URLs for files uploaded via {@link useUploadFile}\n * or file IDs received in tool parameters.\n *\n * Import from `sunpeak/host/chatgpt`:\n *\n * @example\n * ```tsx\n * import { useGetFileDownloadUrl } from 'sunpeak/host/chatgpt';\n *\n * function FilePreview({ fileId }: { fileId: string }) {\n * const getFileDownloadUrl = useGetFileDownloadUrl();\n * const [src, setSrc] = useState<string>();\n *\n * useEffect(() => {\n * getFileDownloadUrl({ fileId }).then(({ downloadUrl }) => setSrc(downloadUrl));\n * }, [fileId, getFileDownloadUrl]);\n *\n * return src ? <img src={src} /> : <p>Loading...</p>;\n * }\n * ```\n */\nexport function useGetFileDownloadUrl(): (params: {\n fileId: string;\n}) => Promise<OpenAIFileDownloadUrlResult> {\n const app = useApp();\n return useCallback(\n async (params: { fileId: string }) => {\n if (!app) {\n throw new Error('[useGetFileDownloadUrl] App not connected');\n }\n const runtime = getOpenAIRuntime();\n if (!runtime?.getFileDownloadUrl) {\n throw new Error('[useGetFileDownloadUrl] window.openai.getFileDownloadUrl not available');\n }\n return runtime.getFileDownloadUrl(params);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport { useApp } from '../../hooks/use-app';\nimport { getOpenAIRuntime, type OpenAIRequestModalParams } from './openai-types';\n\nexport type { OpenAIRequestModalParams as OpenModalParams };\n\n/**\n * Open a host-controlled modal in ChatGPT.\n *\n * Wraps `window.openai.requestModal` which is only available inside ChatGPT.\n * Pass a `template` URL to load alternate UI content in the modal, or omit\n * it to reuse the current UI.\n *\n * Import from `sunpeak/host/chatgpt`:\n *\n * @example\n * ```tsx\n * import { useRequestModal } from 'sunpeak/host/chatgpt';\n *\n * function CheckoutButton() {\n * const requestModal = useRequestModal();\n *\n * return (\n * <button onClick={() => requestModal({ template: 'ui://widget/checkout.html' })}>\n * Checkout\n * </button>\n * );\n * }\n * ```\n */\nexport function useRequestModal(): (params: OpenAIRequestModalParams) => Promise<void> {\n const app = useApp();\n return useCallback(\n async (params: OpenAIRequestModalParams) => {\n if (!app) {\n console.warn('[useRequestModal] App not connected');\n return;\n }\n const runtime = getOpenAIRuntime();\n if (!runtime?.requestModal) {\n throw new Error('[useRequestModal] window.openai.requestModal not available');\n }\n return runtime.requestModal(params);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport { useApp } from '../../hooks/use-app';\nimport {\n getOpenAIRuntime,\n type OpenAICheckoutSession,\n type OpenAICheckoutOrder,\n} from './openai-types';\n\nexport type { OpenAICheckoutSession as CheckoutSession };\nexport type { OpenAICheckoutOrder as CheckoutOrder };\n\n/**\n * Trigger the ChatGPT instant checkout flow.\n *\n * Wraps `window.openai.requestCheckout` which is only available inside\n * ChatGPT. Opens the host checkout UI, handles payment display, and\n * resolves with the finalized order. Rejects on error or user cancel.\n *\n * Import from `sunpeak/host/chatgpt`:\n *\n * @example\n * ```tsx\n * import { useRequestCheckout } from 'sunpeak/host/chatgpt';\n *\n * function BuyButton() {\n * const requestCheckout = useRequestCheckout();\n *\n * const handleBuy = async () => {\n * try {\n * const order = await requestCheckout({\n * id: 'session-1',\n * payment_provider: {\n * provider: 'stripe',\n * merchant_id: 'acct_xxx',\n * supported_payment_methods: ['card', 'apple_pay'],\n * },\n * status: 'ready_for_payment',\n * currency: 'USD',\n * totals: [{ type: 'total', display_text: 'Total', amount: 999 }],\n * links: [],\n * payment_mode: 'live',\n * });\n * console.log('Order completed:', order.id);\n * } catch {\n * console.log('Checkout cancelled or failed');\n * }\n * };\n *\n * return <button onClick={handleBuy}>Buy Now</button>;\n * }\n * ```\n */\nexport function useRequestCheckout(): (\n session: OpenAICheckoutSession\n) => Promise<OpenAICheckoutOrder> {\n const app = useApp();\n return useCallback(\n async (session: OpenAICheckoutSession) => {\n if (!app) {\n throw new Error('[useRequestCheckout] App not connected');\n }\n const runtime = getOpenAIRuntime();\n if (!runtime?.requestCheckout) {\n throw new Error('[useRequestCheckout] window.openai.requestCheckout not available');\n }\n return runtime.requestCheckout(session);\n },\n [app]\n );\n}\n"],"names":["useApp","useCallback"],"mappings":";;;;AAuFO,SAAS,mBAA8C;AAC5D,MAAI,OAAO,WAAW,eAAe,YAAY,QAAQ;AACvD,WAAQ,OAAgD;AAAA,EAC1D;AACA,SAAO;AACT;AC5DO,SAAS,gBAAiE;AAC/E,QAAM,MAAMA,OAAAA,OAAA;AACZ,SAAOC,MAAAA;AAAAA,IACL,OAAO,SAAe;AACpB,UAAI,CAAC,KAAK;AACR,cAAM,IAAI,MAAM,mCAAmC;AAAA,MACrD;AACA,YAAM,UAAU,iBAAA;AAChB,UAAI,CAAC,SAAS,YAAY;AACxB,cAAM,IAAI,MAAM,wDAAwD;AAAA,MAC1E;AACA,aAAO,QAAQ,WAAW,IAAI;AAAA,IAChC;AAAA,IACA,CAAC,GAAG;AAAA,EAAA;AAER;ACbO,SAAS,wBAE2B;AACzC,QAAM,MAAMD,OAAAA,OAAA;AACZ,SAAOC,MAAAA;AAAAA,IACL,OAAO,WAA+B;AACpC,UAAI,CAAC,KAAK;AACR,cAAM,IAAI,MAAM,2CAA2C;AAAA,MAC7D;AACA,YAAM,UAAU,iBAAA;AAChB,UAAI,CAAC,SAAS,oBAAoB;AAChC,cAAM,IAAI,MAAM,wEAAwE;AAAA,MAC1F;AACA,aAAO,QAAQ,mBAAmB,MAAM;AAAA,IAC1C;AAAA,IACA,CAAC,GAAG;AAAA,EAAA;AAER;ACrBO,SAAS,kBAAuE;AACrF,QAAM,MAAMD,OAAAA,OAAA;AACZ,SAAOC,MAAAA;AAAAA,IACL,OAAO,WAAqC;AAC1C,UAAI,CAAC,KAAK;AACR,gBAAQ,KAAK,qCAAqC;AAClD;AAAA,MACF;AACA,YAAM,UAAU,iBAAA;AAChB,UAAI,CAAC,SAAS,cAAc;AAC1B,cAAM,IAAI,MAAM,4DAA4D;AAAA,MAC9E;AACA,aAAO,QAAQ,aAAa,MAAM;AAAA,IACpC;AAAA,IACA,CAAC,GAAG;AAAA,EAAA;AAER;ACMO,SAAS,qBAEkB;AAChC,QAAM,MAAMD,OAAAA,OAAA;AACZ,SAAOC,MAAAA;AAAAA,IACL,OAAO,YAAmC;AACxC,UAAI,CAAC,KAAK;AACR,cAAM,IAAI,MAAM,wCAAwC;AAAA,MAC1D;AACA,YAAM,UAAU,iBAAA;AAChB,UAAI,CAAC,SAAS,iBAAiB;AAC7B,cAAM,IAAI,MAAM,kEAAkE;AAAA,MACpF;AACA,aAAO,QAAQ,gBAAgB,OAAO;AAAA,IACxC;AAAA,IACA,CAAC,GAAG;AAAA,EAAA;AAER;;;;;;"}
@@ -10,11 +10,11 @@
10
10
  *
11
11
  * @example
12
12
  * ```tsx
13
- * import { useUploadFile, useRequestModal } from 'sunpeak/platform/chatgpt';
13
+ * import { useUploadFile, useRequestModal } from 'sunpeak/host/chatgpt';
14
14
  * ```
15
15
  *
16
16
  * @see https://developers.openai.com/apps-sdk/mcp-apps-in-chatgpt
17
- * @module sunpeak/platform/chatgpt
17
+ * @module sunpeak/host/chatgpt
18
18
  */
19
19
  export { getOpenAIRuntime } from './openai-types';
20
20
  export type { OpenAIRuntime } from './openai-types';
@@ -1,5 +1,5 @@
1
1
  import { useCallback } from "react";
2
- import { u as useApp } from "../../use-app-DTTzqi-0.js";
2
+ import { u as useApp } from "../../use-app-C9gpzIQO.js";
3
3
  function getOpenAIRuntime() {
4
4
  if (typeof window !== "undefined" && "openai" in window) {
5
5
  return window.openai;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../src/host/chatgpt/openai-types.ts","../../../src/host/chatgpt/use-create-file.ts","../../../src/host/chatgpt/use-file-download.ts","../../../src/host/chatgpt/use-open-modal.ts","../../../src/host/chatgpt/use-request-checkout.ts"],"sourcesContent":["/**\n * TypeScript declarations for the `window.openai` ChatGPT runtime.\n *\n * These APIs are available inside ChatGPT-hosted iframes and provide\n * platform-specific capabilities beyond the MCP Apps standard.\n *\n * @see https://developers.openai.com/apps-sdk/mcp-apps-in-chatgpt\n */\n\nexport interface OpenAIUploadFileResult {\n fileId: string;\n}\n\nexport interface OpenAIFileDownloadUrlResult {\n downloadUrl: string;\n}\n\nexport interface OpenAIRequestModalParams {\n /** URL of an alternate UI template to load in the modal. Omit to reuse the current UI. */\n template?: string;\n /** Arbitrary params forwarded to the modal content. */\n params?: Record<string, unknown>;\n}\n\nexport interface OpenAICheckoutPaymentProvider {\n provider: string;\n merchant_id: string;\n supported_payment_methods: string[];\n}\n\nexport interface OpenAICheckoutTotal {\n type: string;\n display_text: string;\n amount: number;\n}\n\nexport interface OpenAICheckoutLink {\n type: 'terms_of_use' | 'privacy_policy' | string;\n url: string;\n}\n\nexport interface OpenAICheckoutSession {\n id: string;\n payment_provider: OpenAICheckoutPaymentProvider;\n status: 'ready_for_payment';\n currency: string;\n totals: OpenAICheckoutTotal[];\n links: OpenAICheckoutLink[];\n payment_mode: 'live' | 'test';\n}\n\nexport interface OpenAICheckoutOrder {\n id: string;\n checkout_session_id: string;\n status: 'completed' | string;\n permalink_url?: string;\n}\n\n/**\n * The `window.openai` runtime object injected by ChatGPT into hosted iframes.\n */\nexport interface OpenAIRuntime {\n // --- File APIs ---\n uploadFile?(file: File): Promise<OpenAIUploadFileResult>;\n getFileDownloadUrl?(params: { fileId: string }): Promise<OpenAIFileDownloadUrlResult>;\n\n // --- Modal API ---\n requestModal?(params: OpenAIRequestModalParams): Promise<void>;\n\n // --- Checkout API ---\n requestCheckout?(session: OpenAICheckoutSession): Promise<OpenAICheckoutOrder>;\n\n // --- Display ---\n requestClose?(): void;\n requestDisplayMode?(params: { mode: 'inline' | 'PiP' | 'fullscreen' }): Promise<void>;\n\n // --- Messaging ---\n sendFollowUpMessage?(params: { prompt: string }): void;\n\n // --- Other ---\n openExternal?(params: { href: string }): void;\n}\n\n/**\n * Get the `window.openai` runtime if available.\n * Returns `undefined` outside of ChatGPT or in SSR.\n */\nexport function getOpenAIRuntime(): OpenAIRuntime | undefined {\n if (typeof window !== 'undefined' && 'openai' in window) {\n return (window as unknown as { openai: OpenAIRuntime }).openai;\n }\n return undefined;\n}\n","import { useCallback } from 'react';\nimport { useApp } from '../../hooks/use-app';\nimport { getOpenAIRuntime, type OpenAIUploadFileResult } from './openai-types';\n\nexport type { OpenAIUploadFileResult as CreateFileResult };\n\n/**\n * Upload a file from the app UI into the ChatGPT conversation.\n *\n * Wraps `window.openai.uploadFile` which is only available inside ChatGPT.\n * Supported formats: `image/png`, `image/jpeg`, `image/webp`.\n *\n * Import from `sunpeak/host/chatgpt`:\n *\n * @example\n * ```tsx\n * import { useUploadFile } from 'sunpeak/host/chatgpt';\n *\n * function ImageUploader() {\n * const uploadFile = useUploadFile();\n *\n * const handleChange = async (e: React.ChangeEvent<HTMLInputElement>) => {\n * const file = e.currentTarget.files?.[0];\n * if (!file) return;\n * const { fileId } = await uploadFile(file);\n * console.log('Uploaded:', fileId);\n * };\n *\n * return <input type=\"file\" accept=\"image/*\" onChange={handleChange} />;\n * }\n * ```\n */\nexport function useUploadFile(): (file: File) => Promise<OpenAIUploadFileResult> {\n const app = useApp();\n return useCallback(\n async (file: File) => {\n if (!app) {\n throw new Error('[useUploadFile] App not connected');\n }\n const runtime = getOpenAIRuntime();\n if (!runtime?.uploadFile) {\n throw new Error('[useUploadFile] window.openai.uploadFile not available');\n }\n return runtime.uploadFile(file);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport { useApp } from '../../hooks/use-app';\nimport { getOpenAIRuntime, type OpenAIFileDownloadUrlResult } from './openai-types';\n\nexport type { OpenAIFileDownloadUrlResult as FileDownloadUrlResult };\n\n/**\n * Get a temporary download URL for a file by its ID.\n *\n * @deprecated Use {@link useDownloadFile} from `sunpeak` instead — it works\n * across all hosts via the MCP Apps SDK `app.downloadFile()` method.\n *\n * Wraps `window.openai.getFileDownloadUrl` which is only available inside\n * ChatGPT. Use this to retrieve URLs for files uploaded via {@link useUploadFile}\n * or file IDs received in tool parameters.\n *\n * Import from `sunpeak/host/chatgpt`:\n *\n * @example\n * ```tsx\n * import { useGetFileDownloadUrl } from 'sunpeak/host/chatgpt';\n *\n * function FilePreview({ fileId }: { fileId: string }) {\n * const getFileDownloadUrl = useGetFileDownloadUrl();\n * const [src, setSrc] = useState<string>();\n *\n * useEffect(() => {\n * getFileDownloadUrl({ fileId }).then(({ downloadUrl }) => setSrc(downloadUrl));\n * }, [fileId, getFileDownloadUrl]);\n *\n * return src ? <img src={src} /> : <p>Loading...</p>;\n * }\n * ```\n */\nexport function useGetFileDownloadUrl(): (params: {\n fileId: string;\n}) => Promise<OpenAIFileDownloadUrlResult> {\n const app = useApp();\n return useCallback(\n async (params: { fileId: string }) => {\n if (!app) {\n throw new Error('[useGetFileDownloadUrl] App not connected');\n }\n const runtime = getOpenAIRuntime();\n if (!runtime?.getFileDownloadUrl) {\n throw new Error('[useGetFileDownloadUrl] window.openai.getFileDownloadUrl not available');\n }\n return runtime.getFileDownloadUrl(params);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport { useApp } from '../../hooks/use-app';\nimport { getOpenAIRuntime, type OpenAIRequestModalParams } from './openai-types';\n\nexport type { OpenAIRequestModalParams as OpenModalParams };\n\n/**\n * Open a host-controlled modal in ChatGPT.\n *\n * Wraps `window.openai.requestModal` which is only available inside ChatGPT.\n * Pass a `template` URL to load alternate UI content in the modal, or omit\n * it to reuse the current UI.\n *\n * Import from `sunpeak/host/chatgpt`:\n *\n * @example\n * ```tsx\n * import { useRequestModal } from 'sunpeak/host/chatgpt';\n *\n * function CheckoutButton() {\n * const requestModal = useRequestModal();\n *\n * return (\n * <button onClick={() => requestModal({ template: 'ui://widget/checkout.html' })}>\n * Checkout\n * </button>\n * );\n * }\n * ```\n */\nexport function useRequestModal(): (params: OpenAIRequestModalParams) => Promise<void> {\n const app = useApp();\n return useCallback(\n async (params: OpenAIRequestModalParams) => {\n if (!app) {\n console.warn('[useRequestModal] App not connected');\n return;\n }\n const runtime = getOpenAIRuntime();\n if (!runtime?.requestModal) {\n throw new Error('[useRequestModal] window.openai.requestModal not available');\n }\n return runtime.requestModal(params);\n },\n [app]\n );\n}\n","import { useCallback } from 'react';\nimport { useApp } from '../../hooks/use-app';\nimport {\n getOpenAIRuntime,\n type OpenAICheckoutSession,\n type OpenAICheckoutOrder,\n} from './openai-types';\n\nexport type { OpenAICheckoutSession as CheckoutSession };\nexport type { OpenAICheckoutOrder as CheckoutOrder };\n\n/**\n * Trigger the ChatGPT instant checkout flow.\n *\n * Wraps `window.openai.requestCheckout` which is only available inside\n * ChatGPT. Opens the host checkout UI, handles payment display, and\n * resolves with the finalized order. Rejects on error or user cancel.\n *\n * Import from `sunpeak/host/chatgpt`:\n *\n * @example\n * ```tsx\n * import { useRequestCheckout } from 'sunpeak/host/chatgpt';\n *\n * function BuyButton() {\n * const requestCheckout = useRequestCheckout();\n *\n * const handleBuy = async () => {\n * try {\n * const order = await requestCheckout({\n * id: 'session-1',\n * payment_provider: {\n * provider: 'stripe',\n * merchant_id: 'acct_xxx',\n * supported_payment_methods: ['card', 'apple_pay'],\n * },\n * status: 'ready_for_payment',\n * currency: 'USD',\n * totals: [{ type: 'total', display_text: 'Total', amount: 999 }],\n * links: [],\n * payment_mode: 'live',\n * });\n * console.log('Order completed:', order.id);\n * } catch {\n * console.log('Checkout cancelled or failed');\n * }\n * };\n *\n * return <button onClick={handleBuy}>Buy Now</button>;\n * }\n * ```\n */\nexport function useRequestCheckout(): (\n session: OpenAICheckoutSession\n) => Promise<OpenAICheckoutOrder> {\n const app = useApp();\n return useCallback(\n async (session: OpenAICheckoutSession) => {\n if (!app) {\n throw new Error('[useRequestCheckout] App not connected');\n }\n const runtime = getOpenAIRuntime();\n if (!runtime?.requestCheckout) {\n throw new Error('[useRequestCheckout] window.openai.requestCheckout not available');\n }\n return runtime.requestCheckout(session);\n },\n [app]\n );\n}\n"],"names":[],"mappings":";;AAuFO,SAAS,mBAA8C;AAC5D,MAAI,OAAO,WAAW,eAAe,YAAY,QAAQ;AACvD,WAAQ,OAAgD;AAAA,EAC1D;AACA,SAAO;AACT;AC5DO,SAAS,gBAAiE;AAC/E,QAAM,MAAM,OAAA;AACZ,SAAO;AAAA,IACL,OAAO,SAAe;AACpB,UAAI,CAAC,KAAK;AACR,cAAM,IAAI,MAAM,mCAAmC;AAAA,MACrD;AACA,YAAM,UAAU,iBAAA;AAChB,UAAI,CAAC,SAAS,YAAY;AACxB,cAAM,IAAI,MAAM,wDAAwD;AAAA,MAC1E;AACA,aAAO,QAAQ,WAAW,IAAI;AAAA,IAChC;AAAA,IACA,CAAC,GAAG;AAAA,EAAA;AAER;ACbO,SAAS,wBAE2B;AACzC,QAAM,MAAM,OAAA;AACZ,SAAO;AAAA,IACL,OAAO,WAA+B;AACpC,UAAI,CAAC,KAAK;AACR,cAAM,IAAI,MAAM,2CAA2C;AAAA,MAC7D;AACA,YAAM,UAAU,iBAAA;AAChB,UAAI,CAAC,SAAS,oBAAoB;AAChC,cAAM,IAAI,MAAM,wEAAwE;AAAA,MAC1F;AACA,aAAO,QAAQ,mBAAmB,MAAM;AAAA,IAC1C;AAAA,IACA,CAAC,GAAG;AAAA,EAAA;AAER;ACrBO,SAAS,kBAAuE;AACrF,QAAM,MAAM,OAAA;AACZ,SAAO;AAAA,IACL,OAAO,WAAqC;AAC1C,UAAI,CAAC,KAAK;AACR,gBAAQ,KAAK,qCAAqC;AAClD;AAAA,MACF;AACA,YAAM,UAAU,iBAAA;AAChB,UAAI,CAAC,SAAS,cAAc;AAC1B,cAAM,IAAI,MAAM,4DAA4D;AAAA,MAC9E;AACA,aAAO,QAAQ,aAAa,MAAM;AAAA,IACpC;AAAA,IACA,CAAC,GAAG;AAAA,EAAA;AAER;ACMO,SAAS,qBAEkB;AAChC,QAAM,MAAM,OAAA;AACZ,SAAO;AAAA,IACL,OAAO,YAAmC;AACxC,UAAI,CAAC,KAAK;AACR,cAAM,IAAI,MAAM,wCAAwC;AAAA,MAC1D;AACA,YAAM,UAAU,iBAAA;AAChB,UAAI,CAAC,SAAS,iBAAiB;AAC7B,cAAM,IAAI,MAAM,kEAAkE;AAAA,MACpF;AACA,aAAO,QAAQ,gBAAgB,OAAO;AAAA,IACxC;AAAA,IACA,CAAC,GAAG;AAAA,EAAA;AAER;"}
@@ -6,11 +6,11 @@ export type { OpenAIUploadFileResult as CreateFileResult };
6
6
  * Wraps `window.openai.uploadFile` which is only available inside ChatGPT.
7
7
  * Supported formats: `image/png`, `image/jpeg`, `image/webp`.
8
8
  *
9
- * Import from `sunpeak/platform/chatgpt`:
9
+ * Import from `sunpeak/host/chatgpt`:
10
10
  *
11
11
  * @example
12
12
  * ```tsx
13
- * import { useUploadFile } from 'sunpeak/platform/chatgpt';
13
+ * import { useUploadFile } from 'sunpeak/host/chatgpt';
14
14
  *
15
15
  * function ImageUploader() {
16
16
  * const uploadFile = useUploadFile();
@@ -10,11 +10,11 @@ export type { OpenAIFileDownloadUrlResult as FileDownloadUrlResult };
10
10
  * ChatGPT. Use this to retrieve URLs for files uploaded via {@link useUploadFile}
11
11
  * or file IDs received in tool parameters.
12
12
  *
13
- * Import from `sunpeak/platform/chatgpt`:
13
+ * Import from `sunpeak/host/chatgpt`:
14
14
  *
15
15
  * @example
16
16
  * ```tsx
17
- * import { useGetFileDownloadUrl } from 'sunpeak/platform/chatgpt';
17
+ * import { useGetFileDownloadUrl } from 'sunpeak/host/chatgpt';
18
18
  *
19
19
  * function FilePreview({ fileId }: { fileId: string }) {
20
20
  * const getFileDownloadUrl = useGetFileDownloadUrl();
@@ -7,11 +7,11 @@ export type { OpenAIRequestModalParams as OpenModalParams };
7
7
  * Pass a `template` URL to load alternate UI content in the modal, or omit
8
8
  * it to reuse the current UI.
9
9
  *
10
- * Import from `sunpeak/platform/chatgpt`:
10
+ * Import from `sunpeak/host/chatgpt`:
11
11
  *
12
12
  * @example
13
13
  * ```tsx
14
- * import { useRequestModal } from 'sunpeak/platform/chatgpt';
14
+ * import { useRequestModal } from 'sunpeak/host/chatgpt';
15
15
  *
16
16
  * function CheckoutButton() {
17
17
  * const requestModal = useRequestModal();
@@ -8,11 +8,11 @@ export type { OpenAICheckoutOrder as CheckoutOrder };
8
8
  * ChatGPT. Opens the host checkout UI, handles payment display, and
9
9
  * resolves with the finalized order. Rejects on error or user cancel.
10
10
  *
11
- * Import from `sunpeak/platform/chatgpt`:
11
+ * Import from `sunpeak/host/chatgpt`:
12
12
  *
13
13
  * @example
14
14
  * ```tsx
15
- * import { useRequestCheckout } from 'sunpeak/platform/chatgpt';
15
+ * import { useRequestCheckout } from 'sunpeak/host/chatgpt';
16
16
  *
17
17
  * function BuyButton() {
18
18
  * const requestCheckout = useRequestCheckout();
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- function detectPlatform() {
3
+ function detectHost() {
4
4
  if (typeof window === "undefined") {
5
5
  return "unknown";
6
6
  }
@@ -17,11 +17,13 @@ function detectPlatform() {
17
17
  return "unknown";
18
18
  }
19
19
  function isChatGPT() {
20
- return detectPlatform() === "chatgpt";
20
+ return detectHost() === "chatgpt";
21
21
  }
22
22
  function isClaude() {
23
- return detectPlatform() === "claude";
23
+ return detectHost() === "claude";
24
24
  }
25
+ const detectPlatform = detectHost;
26
+ exports.detectHost = detectHost;
25
27
  exports.detectPlatform = detectPlatform;
26
28
  exports.isChatGPT = isChatGPT;
27
29
  exports.isClaude = isClaude;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../../src/host/index.ts"],"sourcesContent":["/**\n * Host detection utilities for MCP Apps.\n *\n * Use these functions to detect which host is running your app\n * and conditionally use host-specific features.\n *\n * @example\n * ```tsx\n * import { isChatGPT } from 'sunpeak/host';\n *\n * function MyResource() {\n * // Only use ChatGPT-specific features when running on ChatGPT\n * if (isChatGPT()) {\n * // Use updateModelContext, etc.\n * }\n * }\n * ```\n */\n\n/**\n * Supported hosts.\n */\nexport type Host = 'chatgpt' | 'claude' | 'unknown';\n\n/**\n * Detect the current host.\n *\n * Detection is based on:\n * 1. Host runtime objects (window.openai for ChatGPT — works in both\n * real hosts and the simulator when the ChatGPT host shell is active)\n * 2. User agent patterns as fallback\n * 3. Hostname matching as final fallback\n *\n * @returns The detected host\n */\nexport function detectHost(): Host {\n // Check if we're in a browser environment\n if (typeof window === 'undefined') {\n return 'unknown';\n }\n\n // ChatGPT injects window.openai; the simulator does the same when\n // the ChatGPT host shell is selected. This is the most reliable signal.\n if ('openai' in window) {\n return 'chatgpt';\n }\n\n // Check user agent patterns for host detection\n const ua = navigator.userAgent.toLowerCase();\n\n // ChatGPT iOS/Android apps and web\n if (ua.includes('chatgpt') || window.location.hostname.includes('chatgpt.com')) {\n return 'chatgpt';\n }\n\n // Claude apps and web\n if (ua.includes('claude') || window.location.hostname.includes('claude.ai')) {\n return 'claude';\n }\n\n return 'unknown';\n}\n\n/**\n * Check if the app is running in a ChatGPT host.\n *\n * @returns true if running in ChatGPT\n *\n * @example\n * ```tsx\n * import { isChatGPT } from 'sunpeak/host';\n *\n * function MyResource() {\n * if (isChatGPT()) {\n * // Use ChatGPT-specific features\n * }\n * }\n * ```\n */\nexport function isChatGPT(): boolean {\n return detectHost() === 'chatgpt';\n}\n\n/**\n * Check if the app is running in a Claude host.\n *\n * @returns true if running in Claude\n */\nexport function isClaude(): boolean {\n return detectHost() === 'claude';\n}\n\n/** @deprecated Use `Host` instead. */\nexport type Platform = Host;\n\n/** @deprecated Use `detectHost` instead. */\nexport const detectPlatform = detectHost;\n"],"names":[],"mappings":";;AAmCO,SAAS,aAAmB;AAEjC,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO;AAAA,EACT;AAIA,MAAI,YAAY,QAAQ;AACtB,WAAO;AAAA,EACT;AAGA,QAAM,KAAK,UAAU,UAAU,YAAA;AAG/B,MAAI,GAAG,SAAS,SAAS,KAAK,OAAO,SAAS,SAAS,SAAS,aAAa,GAAG;AAC9E,WAAO;AAAA,EACT;AAGA,MAAI,GAAG,SAAS,QAAQ,KAAK,OAAO,SAAS,SAAS,SAAS,WAAW,GAAG;AAC3E,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAkBO,SAAS,YAAqB;AACnC,SAAO,iBAAiB;AAC1B;AAOO,SAAS,WAAoB;AAClC,SAAO,iBAAiB;AAC1B;AAMO,MAAM,iBAAiB;;;;;"}
@@ -1,12 +1,12 @@
1
1
  /**
2
- * Platform detection utilities for MCP Apps.
2
+ * Host detection utilities for MCP Apps.
3
3
  *
4
- * Use these functions to detect which host platform is running your app
5
- * and conditionally use platform-specific features.
4
+ * Use these functions to detect which host is running your app
5
+ * and conditionally use host-specific features.
6
6
  *
7
7
  * @example
8
8
  * ```tsx
9
- * import { isChatGPT } from 'sunpeak/platform';
9
+ * import { isChatGPT } from 'sunpeak/host';
10
10
  *
11
11
  * function MyResource() {
12
12
  * // Only use ChatGPT-specific features when running on ChatGPT
@@ -17,21 +17,21 @@
17
17
  * ```
18
18
  */
19
19
  /**
20
- * Supported host platforms.
20
+ * Supported hosts.
21
21
  */
22
- export type Platform = 'chatgpt' | 'claude' | 'unknown';
22
+ export type Host = 'chatgpt' | 'claude' | 'unknown';
23
23
  /**
24
- * Detect the current host platform.
24
+ * Detect the current host.
25
25
  *
26
26
  * Detection is based on:
27
- * 1. Platform runtime objects (window.openai for ChatGPT — works in both
27
+ * 1. Host runtime objects (window.openai for ChatGPT — works in both
28
28
  * real hosts and the simulator when the ChatGPT host shell is active)
29
29
  * 2. User agent patterns as fallback
30
30
  * 3. Hostname matching as final fallback
31
31
  *
32
- * @returns The detected platform
32
+ * @returns The detected host
33
33
  */
34
- export declare function detectPlatform(): Platform;
34
+ export declare function detectHost(): Host;
35
35
  /**
36
36
  * Check if the app is running in a ChatGPT host.
37
37
  *
@@ -39,7 +39,7 @@ export declare function detectPlatform(): Platform;
39
39
  *
40
40
  * @example
41
41
  * ```tsx
42
- * import { isChatGPT } from 'sunpeak/platform';
42
+ * import { isChatGPT } from 'sunpeak/host';
43
43
  *
44
44
  * function MyResource() {
45
45
  * if (isChatGPT()) {
@@ -55,3 +55,7 @@ export declare function isChatGPT(): boolean;
55
55
  * @returns true if running in Claude
56
56
  */
57
57
  export declare function isClaude(): boolean;
58
+ /** @deprecated Use `Host` instead. */
59
+ export type Platform = Host;
60
+ /** @deprecated Use `detectHost` instead. */
61
+ export declare const detectPlatform: typeof detectHost;
@@ -1,4 +1,4 @@
1
- function detectPlatform() {
1
+ function detectHost() {
2
2
  if (typeof window === "undefined") {
3
3
  return "unknown";
4
4
  }
@@ -15,12 +15,14 @@ function detectPlatform() {
15
15
  return "unknown";
16
16
  }
17
17
  function isChatGPT() {
18
- return detectPlatform() === "chatgpt";
18
+ return detectHost() === "chatgpt";
19
19
  }
20
20
  function isClaude() {
21
- return detectPlatform() === "claude";
21
+ return detectHost() === "claude";
22
22
  }
23
+ const detectPlatform = detectHost;
23
24
  export {
25
+ detectHost,
24
26
  detectPlatform,
25
27
  isChatGPT,
26
28
  isClaude
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../src/host/index.ts"],"sourcesContent":["/**\n * Host detection utilities for MCP Apps.\n *\n * Use these functions to detect which host is running your app\n * and conditionally use host-specific features.\n *\n * @example\n * ```tsx\n * import { isChatGPT } from 'sunpeak/host';\n *\n * function MyResource() {\n * // Only use ChatGPT-specific features when running on ChatGPT\n * if (isChatGPT()) {\n * // Use updateModelContext, etc.\n * }\n * }\n * ```\n */\n\n/**\n * Supported hosts.\n */\nexport type Host = 'chatgpt' | 'claude' | 'unknown';\n\n/**\n * Detect the current host.\n *\n * Detection is based on:\n * 1. Host runtime objects (window.openai for ChatGPT — works in both\n * real hosts and the simulator when the ChatGPT host shell is active)\n * 2. User agent patterns as fallback\n * 3. Hostname matching as final fallback\n *\n * @returns The detected host\n */\nexport function detectHost(): Host {\n // Check if we're in a browser environment\n if (typeof window === 'undefined') {\n return 'unknown';\n }\n\n // ChatGPT injects window.openai; the simulator does the same when\n // the ChatGPT host shell is selected. This is the most reliable signal.\n if ('openai' in window) {\n return 'chatgpt';\n }\n\n // Check user agent patterns for host detection\n const ua = navigator.userAgent.toLowerCase();\n\n // ChatGPT iOS/Android apps and web\n if (ua.includes('chatgpt') || window.location.hostname.includes('chatgpt.com')) {\n return 'chatgpt';\n }\n\n // Claude apps and web\n if (ua.includes('claude') || window.location.hostname.includes('claude.ai')) {\n return 'claude';\n }\n\n return 'unknown';\n}\n\n/**\n * Check if the app is running in a ChatGPT host.\n *\n * @returns true if running in ChatGPT\n *\n * @example\n * ```tsx\n * import { isChatGPT } from 'sunpeak/host';\n *\n * function MyResource() {\n * if (isChatGPT()) {\n * // Use ChatGPT-specific features\n * }\n * }\n * ```\n */\nexport function isChatGPT(): boolean {\n return detectHost() === 'chatgpt';\n}\n\n/**\n * Check if the app is running in a Claude host.\n *\n * @returns true if running in Claude\n */\nexport function isClaude(): boolean {\n return detectHost() === 'claude';\n}\n\n/** @deprecated Use `Host` instead. */\nexport type Platform = Host;\n\n/** @deprecated Use `detectHost` instead. */\nexport const detectPlatform = detectHost;\n"],"names":[],"mappings":"AAmCO,SAAS,aAAmB;AAEjC,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO;AAAA,EACT;AAIA,MAAI,YAAY,QAAQ;AACtB,WAAO;AAAA,EACT;AAGA,QAAM,KAAK,UAAU,UAAU,YAAA;AAG/B,MAAI,GAAG,SAAS,SAAS,KAAK,OAAO,SAAS,SAAS,SAAS,aAAa,GAAG;AAC9E,WAAO;AAAA,EACT;AAGA,MAAI,GAAG,SAAS,QAAQ,KAAK,OAAO,SAAS,SAAS,SAAS,WAAW,GAAG;AAC3E,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAkBO,SAAS,YAAqB;AACnC,SAAO,iBAAiB;AAC1B;AAOO,SAAS,WAAoB;AAClC,SAAO,iBAAiB;AAC1B;AAMO,MAAM,iBAAiB;"}
@@ -1,4 +1,4 @@
1
- import { I as IframeResource, M as McpAppHost, a as SCREEN_WIDTHS, b as SidebarCheckbox, c as SidebarCollapsibleControl, d as SidebarControl, e as SidebarInput, f as SidebarSelect, g as SidebarTextarea, h as SidebarToggle, i as SimpleSidebar, S as Simulator, T as ThemeProvider, j as extractResourceCSP, k as getHostShell, l as getRegisteredHosts, r as registerHostShell, m as resolveServerToolResult, u as useSimulatorState, n as useThemeContext } from "./simulator-DfTsXTK4.js";
1
+ import { I as IframeResource, M as McpAppHost, a as SCREEN_WIDTHS, b as SidebarCheckbox, c as SidebarCollapsibleControl, d as SidebarControl, e as SidebarInput, f as SidebarSelect, g as SidebarTextarea, h as SidebarToggle, i as SimpleSidebar, S as Simulator, T as ThemeProvider, j as extractResourceCSP, k as getHostShell, l as getRegisteredHosts, r as registerHostShell, m as resolveServerToolResult, u as useSimulatorState, n as useThemeContext } from "./simulator-D8t-r7HH.js";
2
2
  import { c as createSimulatorUrl } from "./simulator-url-j_XV3EoP.js";
3
3
  import { b as buildDevSimulations, a as buildResourceMap, c as buildSimulations, d as createResourceExports, e as extractResourceKey, f as extractSimulationKey, g as findResourceDirs, h as findResourceKey, i as getComponentName, t as toPascalCase } from "./discovery-BVqD-JsT.js";
4
4
  const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -38,4 +38,4 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
38
38
  export {
39
39
  index as i
40
40
  };
41
- //# sourceMappingURL=index-C_uYg-eE.js.map
41
+ //# sourceMappingURL=index-B4aC3vjH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-B4aC3vjH.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- const simulator = require("./simulator-mbqealxY.cjs");
2
+ const simulator = require("./simulator-FFNttkqL.cjs");
3
3
  const simulatorUrl = require("./simulator-url-DcSYRl-P.cjs");
4
4
  const discovery = require("./discovery-D1gpaVz4.cjs");
5
5
  const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -37,4 +37,4 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
37
37
  useThemeContext: simulator.useThemeContext
38
38
  }, Symbol.toStringTag, { value: "Module" }));
39
39
  exports.index = index;
40
- //# sourceMappingURL=index-CJ3nfg7Q.cjs.map
40
+ //# sourceMappingURL=index-CKabCJyV.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-CKabCJyV.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,4 +1,4 @@
1
- import { I as IframeResource, M as McpAppHost, a as SCREEN_WIDTHS, S as Simulator, T as ThemeProvider, j as extractResourceCSP, m as resolveServerToolResult, n as useThemeContext } from "./simulator-DfTsXTK4.js";
1
+ import { I as IframeResource, M as McpAppHost, a as SCREEN_WIDTHS, S as Simulator, T as ThemeProvider, j as extractResourceCSP, m as resolveServerToolResult, n as useThemeContext } from "./simulator-D8t-r7HH.js";
2
2
  import { c as createSimulatorUrl } from "./simulator-url-j_XV3EoP.js";
3
3
  import { b as buildDevSimulations, a as buildResourceMap, c as buildSimulations, d as createResourceExports, e as extractResourceKey, f as extractSimulationKey, g as findResourceDirs, h as findResourceKey, i as getComponentName, t as toPascalCase } from "./discovery-BVqD-JsT.js";
4
4
  const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -26,4 +26,4 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
26
26
  export {
27
27
  index as i
28
28
  };
29
- //# sourceMappingURL=index-BITfgMxk.js.map
29
+ //# sourceMappingURL=index-CX6Z4bED.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-CX6Z4bED.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- const simulator = require("./simulator-mbqealxY.cjs");
2
+ const simulator = require("./simulator-FFNttkqL.cjs");
3
3
  const simulatorUrl = require("./simulator-url-DcSYRl-P.cjs");
4
4
  const discovery = require("./discovery-D1gpaVz4.cjs");
5
5
  const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -25,4 +25,4 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
25
25
  useThemeContext: simulator.useThemeContext
26
26
  }, Symbol.toStringTag, { value: "Module" }));
27
27
  exports.index = index;
28
- //# sourceMappingURL=index-DxCrGGzy.cjs.map
28
+ //# sourceMappingURL=index-bKBBCBK6.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-bKBBCBK6.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;"}