@widgetic/creator 0.3.49

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 (42) hide show
  1. package/README.md +116 -0
  2. package/dist/CreatorApp.svelte +11821 -0
  3. package/dist/CreatorApp.svelte.d.ts +41 -0
  4. package/dist/components/EditableName.svelte +94 -0
  5. package/dist/components/EditableName.svelte.d.ts +27 -0
  6. package/dist/components/SelectorDropdown.svelte +238 -0
  7. package/dist/components/SelectorDropdown.svelte.d.ts +41 -0
  8. package/dist/components/WidgetDetails.svelte +3127 -0
  9. package/dist/components/WidgetDetails.svelte.d.ts +235 -0
  10. package/dist/components/index.d.ts +0 -0
  11. package/dist/components/index.js +4 -0
  12. package/dist/constants.d.ts +1 -0
  13. package/dist/constants.js +1 -0
  14. package/dist/creator-types.d.ts +64 -0
  15. package/dist/creator-types.js +1 -0
  16. package/dist/index.d.ts +4 -0
  17. package/dist/index.js +5 -0
  18. package/dist/localCacheGate.d.ts +7 -0
  19. package/dist/localCacheGate.js +29 -0
  20. package/dist/pageHelpers.d.ts +15 -0
  21. package/dist/pageHelpers.js +194 -0
  22. package/dist/stores/userSession.d.ts +7 -0
  23. package/dist/stores/userSession.js +32 -0
  24. package/dist/stores/websocketStore.d.ts +53 -0
  25. package/dist/stores/websocketStore.js +289 -0
  26. package/dist/syncSiteAuth.d.ts +9 -0
  27. package/dist/syncSiteAuth.js +53 -0
  28. package/dist/utils/creatorDraftStorage.d.ts +17 -0
  29. package/dist/utils/creatorDraftStorage.js +87 -0
  30. package/dist/utils/embedCode.d.ts +51 -0
  31. package/dist/utils/embedCode.js +69 -0
  32. package/dist/utils/models.d.ts +4 -0
  33. package/dist/utils/models.js +94 -0
  34. package/dist/utils/operationStream.d.ts +29 -0
  35. package/dist/utils/operationStream.js +116 -0
  36. package/dist/utils/prototypes.d.ts +0 -0
  37. package/dist/utils/prototypes.js +20 -0
  38. package/dist/utils/widgeticChatUpload.d.ts +26 -0
  39. package/dist/utils/widgeticChatUpload.js +148 -0
  40. package/dist/utils.d.ts +11 -0
  41. package/dist/utils.js +38 -0
  42. package/package.json +124 -0
@@ -0,0 +1,289 @@
1
+ /**
2
+ * WebSocket Store
3
+ *
4
+ * Manages WebSocket connection for real-time events:
5
+ * - Code generation status (operation progress)
6
+ * - Widget publish status (build completion)
7
+ * - Dynamic Worker preview readiness
8
+ */
9
+ import { writable, get } from 'svelte/store';
10
+ // =============================================================================
11
+ // Stores
12
+ // =============================================================================
13
+ export const connectionState = writable({
14
+ connected: false,
15
+ joinedRooms: [],
16
+ error: null
17
+ });
18
+ export const dynamicWorkerPreviewStatus = writable({
19
+ widgetId: null,
20
+ previewUrl: null,
21
+ buildTimeMs: null,
22
+ timestamp: null
23
+ });
24
+ export const widgetPublishStatus = writable({
25
+ widgetId: null,
26
+ status: null,
27
+ version: undefined,
28
+ artifactUrl: undefined,
29
+ message: undefined,
30
+ error: undefined,
31
+ timestamp: null
32
+ });
33
+ export const codeGenerationStatus = writable({
34
+ operationId: null,
35
+ status: null,
36
+ previousStatus: null,
37
+ progress: 0,
38
+ error: null,
39
+ timestamp: null
40
+ });
41
+ export const agentHarnessOutput = writable(null);
42
+ // =============================================================================
43
+ // Socket.IO Connection
44
+ // =============================================================================
45
+ let socket = null;
46
+ let socketImportPromise = null;
47
+ let currentAuthToken = null;
48
+ let lastTokenUsed = null;
49
+ let activeUserId = null;
50
+ /** Runtime API root for embedded hosts (site PUBLIC_API_URL). Overrides VITE_API_URL. */
51
+ let runtimeApiUrl = null;
52
+ const showLogs = true;
53
+ export function setAuthToken(token) {
54
+ currentAuthToken = token;
55
+ if (token !== lastTokenUsed && socket) {
56
+ if (showLogs)
57
+ console.log('[WsStore] Token changed, will recreate socket on next connect');
58
+ if (socket.connected) {
59
+ socket.disconnect();
60
+ }
61
+ socket = null;
62
+ socketImportPromise = null;
63
+ }
64
+ }
65
+ /** Prefer host-provided API URL so embedded creator does not socket.io to localhost:3000. */
66
+ export function setWebsocketApiUrl(apiUrl) {
67
+ const normalized = apiUrl ? String(apiUrl).replace(/\/+$/, '') : null;
68
+ if (normalized === runtimeApiUrl)
69
+ return;
70
+ runtimeApiUrl = normalized;
71
+ if (socket) {
72
+ if (showLogs)
73
+ console.log('[WsStore] API URL changed, recreating socket on next connect:', runtimeApiUrl);
74
+ if (socket.connected) {
75
+ socket.disconnect();
76
+ }
77
+ socket = null;
78
+ socketImportPromise = null;
79
+ }
80
+ }
81
+ async function getSocket() {
82
+ if (socket && currentAuthToken !== lastTokenUsed) {
83
+ if (showLogs)
84
+ console.log('[WsStore] Recreating socket with new token');
85
+ if (socket.connected) {
86
+ socket.disconnect();
87
+ }
88
+ socket = null;
89
+ socketImportPromise = null;
90
+ }
91
+ if (socket)
92
+ return socket;
93
+ if (!socketImportPromise) {
94
+ socketImportPromise = import('socket.io-client').then(({ io }) => {
95
+ // Prefer runtime override (embedded hosts), then build-time VITE_API_URL
96
+ const apiUrl = (runtimeApiUrl || import.meta.env.VITE_API_URL || 'http://localhost:3000').replace(/\/+$/, '');
97
+ lastTokenUsed = currentAuthToken;
98
+ if (showLogs)
99
+ console.log('[WsStore] Creating socket with auth token:', currentAuthToken ? 'present' : 'missing', 'api:', apiUrl);
100
+ socket = io(apiUrl, {
101
+ autoConnect: false,
102
+ transports: ['websocket', 'polling'],
103
+ reconnection: true,
104
+ reconnectionAttempts: 5,
105
+ reconnectionDelay: 1000,
106
+ auth: currentAuthToken ? { token: currentAuthToken } : undefined
107
+ });
108
+ setupSocketListeners(socket);
109
+ return socket;
110
+ }).catch(err => {
111
+ console.error('[WsStore] Failed to load socket.io-client:', err);
112
+ return null;
113
+ });
114
+ }
115
+ return socketImportPromise;
116
+ }
117
+ function setupSocketListeners(sock) {
118
+ if (!sock)
119
+ return;
120
+ sock.on('connect', () => {
121
+ if (showLogs)
122
+ console.log('[WsStore] WebSocket connected');
123
+ connectionState.update(s => ({ ...s, connected: true, error: null }));
124
+ if (activeUserId) {
125
+ sock.emit('joinRoom', { room: `user-${activeUserId}` });
126
+ if (showLogs)
127
+ console.log('[WsStore] Re-joining user room after reconnect:', `user-${activeUserId}`);
128
+ }
129
+ });
130
+ sock.on('disconnect', (reason) => {
131
+ if (showLogs)
132
+ console.log('[WsStore] WebSocket disconnected:', reason);
133
+ connectionState.update(s => ({ ...s, connected: false, joinedRooms: [] }));
134
+ });
135
+ sock.on('connect_error', (err) => {
136
+ if (showLogs)
137
+ console.error('[WsStore] WebSocket connection error:', err.message);
138
+ connectionState.update(s => ({ ...s, connected: false, error: err.message }));
139
+ });
140
+ // =========================================================================
141
+ // Widget Publish Events
142
+ // =========================================================================
143
+ sock.on('widget_publish_status', (data) => {
144
+ if (showLogs)
145
+ console.log('[WsStore] Widget publish status received:', data);
146
+ widgetPublishStatus.set({
147
+ widgetId: data.widgetId ?? null,
148
+ status: data.status ?? null,
149
+ version: data.version,
150
+ artifactUrl: data.artifactUrl,
151
+ message: data.message,
152
+ error: data.error,
153
+ timestamp: new Date().toISOString()
154
+ });
155
+ });
156
+ sock.on('publish:complete', (data) => {
157
+ if (showLogs)
158
+ console.log('[WsStore] Publish complete received:', data);
159
+ widgetPublishStatus.set({
160
+ widgetId: data.widgetId ?? null,
161
+ status: 'success',
162
+ version: data.versionPublished,
163
+ artifactUrl: data.artifactUrl,
164
+ message: data.message,
165
+ error: undefined,
166
+ timestamp: new Date().toISOString()
167
+ });
168
+ });
169
+ sock.on('build:error', (data) => {
170
+ if (showLogs)
171
+ console.log('[WsStore] Build error received:', data);
172
+ widgetPublishStatus.set({
173
+ widgetId: data.widgetId ?? null,
174
+ status: 'failure',
175
+ version: data.version,
176
+ artifactUrl: undefined,
177
+ message: data.message ?? 'Build failed.',
178
+ error: data.error,
179
+ timestamp: new Date().toISOString()
180
+ });
181
+ });
182
+ // =========================================================================
183
+ // Code Generation Status
184
+ // =========================================================================
185
+ sock.on('code_generation_status', (data) => {
186
+ if (showLogs)
187
+ console.log('[WsStore] Code generation status received:', data);
188
+ codeGenerationStatus.set({
189
+ operationId: data.operationId ?? null,
190
+ status: data.status ?? null,
191
+ previousStatus: data.previousStatus ?? null,
192
+ progress: data.progress ?? 0,
193
+ error: data.error ?? null,
194
+ timestamp: data.timestamp ?? new Date().toISOString()
195
+ });
196
+ });
197
+ // =========================================================================
198
+ // Dynamic Worker Preview
199
+ // =========================================================================
200
+ sock.on('vmConsole:aiderOutput', (data) => {
201
+ const output = typeof data?.output === 'string' ? data.output.trim() : '';
202
+ if (!output)
203
+ return;
204
+ if (showLogs)
205
+ console.log('[WsStore] Agent harness output:', output.slice(0, 120));
206
+ agentHarnessOutput.set({
207
+ output,
208
+ timestamp: new Date().toISOString()
209
+ });
210
+ });
211
+ sock.on('dynamic_worker_preview_ready', (data) => {
212
+ if (showLogs)
213
+ console.log('[WsStore] Dynamic Worker preview ready!', {
214
+ widgetId: data.widgetId,
215
+ previewUrl: data.previewUrl?.substring(0, 60) + '...',
216
+ buildTimeMs: data.buildTimeMs
217
+ });
218
+ dynamicWorkerPreviewStatus.set({
219
+ widgetId: data.widgetId,
220
+ previewUrl: data.previewUrl,
221
+ buildTimeMs: data.buildTimeMs,
222
+ timestamp: new Date().toISOString()
223
+ });
224
+ });
225
+ }
226
+ // =============================================================================
227
+ // Public Functions
228
+ // =============================================================================
229
+ /**
230
+ * Connect to WebSocket and join user room for receiving events.
231
+ */
232
+ export async function connectWebSocket(userId) {
233
+ const sock = await getSocket();
234
+ if (!sock) {
235
+ if (showLogs)
236
+ console.error('[WsStore] Socket not available');
237
+ return false;
238
+ }
239
+ if (userId)
240
+ activeUserId = userId;
241
+ if (!sock.connected) {
242
+ sock.connect();
243
+ }
244
+ return new Promise((resolve) => {
245
+ const timeout = setTimeout(() => {
246
+ if (showLogs)
247
+ console.error('[WsStore] Connection timeout');
248
+ resolve(false);
249
+ }, 5000);
250
+ const tryJoin = () => {
251
+ if (sock.connected) {
252
+ clearTimeout(timeout);
253
+ if (userId) {
254
+ sock.emit('joinRoom', { room: `user-${userId}` });
255
+ if (showLogs)
256
+ console.log('[WsStore] Joined user room:', `user-${userId}`);
257
+ }
258
+ connectionState.set({
259
+ connected: true,
260
+ joinedRooms: userId ? [`user-${userId}`] : [],
261
+ error: null
262
+ });
263
+ resolve(true);
264
+ }
265
+ else {
266
+ sock.once('connect', tryJoin);
267
+ }
268
+ };
269
+ tryJoin();
270
+ });
271
+ }
272
+ /**
273
+ * Disconnect from WebSocket.
274
+ */
275
+ export async function disconnectWebSocket() {
276
+ const sock = await getSocket();
277
+ if (!sock)
278
+ return;
279
+ const state = get(connectionState);
280
+ if (state.joinedRooms.length > 0) {
281
+ state.joinedRooms.forEach(room => {
282
+ sock.emit('leave', room);
283
+ });
284
+ }
285
+ connectionState.update(s => ({
286
+ ...s,
287
+ joinedRooms: []
288
+ }));
289
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Sync creator session from site auth (localStorage.session.accessToken).
3
+ * Used when CreatorApp is embedded in Frontend/site on the same origin.
4
+ *
5
+ * Dexie L1 owner is applied only when enableLocalCache was turned on via
6
+ * setEnableLocalCache (CreatorApp prop). Site's authStore owns cache in the
7
+ * site bundle; creator has a separate in-memory owner and must opt in.
8
+ */
9
+ export declare function syncSessionFromSiteAuth(): boolean;
@@ -0,0 +1,53 @@
1
+ import { decodeJWT } from './pageHelpers';
2
+ import { setSession } from './stores/userSession';
3
+ import { syncLocalCacheOwner } from './localCacheGate.js';
4
+ /**
5
+ * Sync creator session from site auth (localStorage.session.accessToken).
6
+ * Used when CreatorApp is embedded in Frontend/site on the same origin.
7
+ *
8
+ * Dexie L1 owner is applied only when enableLocalCache was turned on via
9
+ * setEnableLocalCache (CreatorApp prop). Site's authStore owns cache in the
10
+ * site bundle; creator has a separate in-memory owner and must opt in.
11
+ */
12
+ export function syncSessionFromSiteAuth() {
13
+ if (typeof window === 'undefined')
14
+ return false;
15
+ try {
16
+ const sessionStr = localStorage.getItem('session');
17
+ if (!sessionStr) {
18
+ console.warn('[CreatorApp] No site session found in localStorage');
19
+ syncLocalCacheOwner(null);
20
+ return false;
21
+ }
22
+ const session = JSON.parse(sessionStr);
23
+ const token = session?.accessToken || session?.access_token;
24
+ if (!token) {
25
+ console.warn('[CreatorApp] Site session has no access token');
26
+ syncLocalCacheOwner(null);
27
+ return false;
28
+ }
29
+ const decoded = decodeJWT(token);
30
+ const user = decoded
31
+ ? {
32
+ id: decoded.sub || decoded.user_id || decoded.id || 'site-user',
33
+ email: decoded.email || decoded.user_metadata?.email || session?.user?.email,
34
+ name: decoded.user_metadata?.name ||
35
+ decoded.user_metadata?.full_name ||
36
+ decoded.name ||
37
+ session?.user?.name ||
38
+ 'User',
39
+ role: decoded.role || 'user',
40
+ avatar: decoded.user_metadata?.avatar_url || decoded.user_metadata?.picture
41
+ }
42
+ : session?.user || { id: 'site-user', email: 'user@widgetic.com', name: 'User' };
43
+ // setSession → syncLocalCacheOwner when enableLocalCache is on
44
+ setSession(user, token);
45
+ console.log('[CreatorApp] Session synced from site auth');
46
+ return true;
47
+ }
48
+ catch (error) {
49
+ console.error('[CreatorApp] Failed to sync session from site:', error);
50
+ syncLocalCacheOwner(null);
51
+ return false;
52
+ }
53
+ }
@@ -0,0 +1,17 @@
1
+ export interface WidgetDraft {
2
+ promptText: string;
3
+ chatDraft: string;
4
+ images: string[];
5
+ }
6
+ export declare function saveWidgetDraft(widgetId: string, draft: Partial<WidgetDraft>): Promise<void>;
7
+ export declare function readWidgetDraft(widgetId: string): Promise<Partial<WidgetDraft> | null>;
8
+ export declare function deleteWidgetDraft(widgetId: string): Promise<void>;
9
+ /** Bulk-read all drafts for the owner (keyed by widgetId). */
10
+ export declare function readAllWidgetDrafts(): Promise<Record<string, WidgetDraft>>;
11
+ /** Copy one widget's draft to another (duplicate-widget support). */
12
+ export declare function copyWidgetDraft(sourceWidgetId: string, targetWidgetId: string): Promise<void>;
13
+ export declare function saveCanvasState(canvasId: string | null, json: string): void;
14
+ export declare function readCanvasState(canvasId: string | null): Promise<string | null>;
15
+ export declare function saveActiveGeneration(widgetId: string, operationId: string): void;
16
+ export declare function readActiveGeneration(widgetId: string): Promise<string | null>;
17
+ export declare function clearActiveGeneration(widgetId: string): Promise<void>;
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Durable draft + selection storage for the widget creator.
3
+ *
4
+ * Replaces the per-widget localStorage family (prompt text, prompt images,
5
+ * chat drafts, canvas-state fallback JSON, active generation id) with the
6
+ * shared L1 store. Keys are owner-scoped inside @widgetic/cache-layer.
7
+ * Cross-tab generation/publishing flags intentionally remain in
8
+ * localStorage — they must be visible to other tabs, not just this one.
9
+ */
10
+ import { deleteEntity, getCacheOwner, readAllEntitiesForKind, readEntity, writeEntity } from '@widgetic/cache-layer';
11
+ const DRAFT_KIND = 'creatorDrafts';
12
+ const CANVAS_KIND = 'creatorCanvasState';
13
+ const GENERATION_KIND = 'creatorActiveGeneration';
14
+ function ownerIdOrNull() {
15
+ return getCacheOwner();
16
+ }
17
+ export async function saveWidgetDraft(widgetId, draft) {
18
+ const ownerId = ownerIdOrNull();
19
+ if (!ownerId)
20
+ return;
21
+ const existing = (await readEntity(ownerId, DRAFT_KIND, widgetId)) ?? {
22
+ promptText: '',
23
+ chatDraft: '',
24
+ images: []
25
+ };
26
+ await writeEntity(ownerId, DRAFT_KIND, widgetId, { ...existing, ...draft });
27
+ }
28
+ export async function readWidgetDraft(widgetId) {
29
+ const ownerId = ownerIdOrNull();
30
+ if (!ownerId)
31
+ return null;
32
+ return readEntity(ownerId, DRAFT_KIND, widgetId);
33
+ }
34
+ export async function deleteWidgetDraft(widgetId) {
35
+ const ownerId = ownerIdOrNull();
36
+ if (!ownerId)
37
+ return;
38
+ await deleteEntity(ownerId, DRAFT_KIND, widgetId);
39
+ }
40
+ /** Bulk-read all drafts for the owner (keyed by widgetId). */
41
+ export async function readAllWidgetDrafts() {
42
+ const ownerId = ownerIdOrNull();
43
+ if (!ownerId)
44
+ return {};
45
+ return readAllEntitiesForKind(ownerId, DRAFT_KIND);
46
+ }
47
+ /** Copy one widget's draft to another (duplicate-widget support). */
48
+ export async function copyWidgetDraft(sourceWidgetId, targetWidgetId) {
49
+ const source = await readWidgetDraft(sourceWidgetId);
50
+ if (!source)
51
+ return;
52
+ await saveWidgetDraft(targetWidgetId, source);
53
+ }
54
+ // ─── Canvas state fallback ───────────────────────────────────────
55
+ export function saveCanvasState(canvasId, json) {
56
+ const ownerId = ownerIdOrNull();
57
+ if (!ownerId)
58
+ return;
59
+ void writeEntity(ownerId, CANVAS_KIND, canvasId ?? 'default', json).catch((error) => {
60
+ console.warn('[creatorDraftStorage] Failed to persist canvas state:', error);
61
+ });
62
+ }
63
+ export async function readCanvasState(canvasId) {
64
+ const ownerId = ownerIdOrNull();
65
+ if (!ownerId)
66
+ return null;
67
+ return readEntity(ownerId, CANVAS_KIND, canvasId ?? 'default');
68
+ }
69
+ // ─── Active generation id ────────────────────────────────────────
70
+ export function saveActiveGeneration(widgetId, operationId) {
71
+ const ownerId = ownerIdOrNull();
72
+ if (!ownerId)
73
+ return;
74
+ void writeEntity(ownerId, GENERATION_KIND, widgetId, operationId);
75
+ }
76
+ export async function readActiveGeneration(widgetId) {
77
+ const ownerId = ownerIdOrNull();
78
+ if (!ownerId)
79
+ return null;
80
+ return readEntity(ownerId, GENERATION_KIND, widgetId);
81
+ }
82
+ export async function clearActiveGeneration(widgetId) {
83
+ const ownerId = ownerIdOrNull();
84
+ if (!ownerId)
85
+ return;
86
+ await deleteEntity(ownerId, GENERATION_KIND, widgetId);
87
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Embed code generation utilities for the Embed step.
3
+ *
4
+ * Two formats are supported:
5
+ * - `iframe`: classic `<iframe>` pointing at the published widget HTML on the CDN.
6
+ * - `web-component`: customer-facing `<widgetic>` host tag. The embed SDK
7
+ * scans for this tag and hydrates it. (Autonomous custom elements must
8
+ * contain a hyphen, so the SDK does not `define("widgetic")` — it finds
9
+ * `<widgetic>` in the DOM and renders into it.)
10
+ *
11
+ * The SDK script is served from `cdn.widgetic.com/sdks/browser/embed-sdk.js`
12
+ * (R2 custom domain on the `widgets` bucket — see AGENTS.md embed architecture).
13
+ */
14
+ export type EmbedFormat = 'iframe' | 'web-component';
15
+ export declare const EMBED_FORMATS: EmbedFormat[];
16
+ export declare const EMBED_FORMAT_LABELS: Record<EmbedFormat, string>;
17
+ export interface EmbedCodeParams {
18
+ /** Direct widget HTML URL on the CDN (or API proxy in dev). */
19
+ embedSrc: string;
20
+ /** Composition id, if a composition is selected. */
21
+ compositionId?: string | null;
22
+ /** Embed width in pixels. */
23
+ width: number;
24
+ /** Embed height in pixels. */
25
+ height: number;
26
+ /** CDN base URL for the embed SDK script. Defaults to https://cdn.widgetic.com */
27
+ sdkBaseUrl?: string;
28
+ }
29
+ /**
30
+ * Build the iframe embed snippet. Backward compatible with the previous
31
+ * hardcoded block in `CreatorApp.svelte`.
32
+ */
33
+ export declare function generateIframeEmbedCode({ embedSrc, width, height }: EmbedCodeParams): string;
34
+ /**
35
+ * Build the Web Component embed snippet using `<widgetic>`.
36
+ * Requires a composition id — the custom element loader fetches the
37
+ * composition + widget module from the CDN via the embed-sdk batch API.
38
+ *
39
+ * If no composition is selected we fall back to the iframe format
40
+ * (caller should check `compositionId` before calling this).
41
+ */
42
+ export declare function generateWebComponentEmbedCode({ compositionId, width, height, sdkBaseUrl }: EmbedCodeParams): string;
43
+ /**
44
+ * Pick the right embed code for the requested format, with fallback to
45
+ * iframe when the Web Component format is requested but no composition
46
+ * is selected (custom element requires `composition-id`).
47
+ */
48
+ export declare function generateEmbedCode(format: EmbedFormat, params: EmbedCodeParams): {
49
+ code: string;
50
+ effectiveFormat: EmbedFormat;
51
+ };
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Embed code generation utilities for the Embed step.
3
+ *
4
+ * Two formats are supported:
5
+ * - `iframe`: classic `<iframe>` pointing at the published widget HTML on the CDN.
6
+ * - `web-component`: customer-facing `<widgetic>` host tag. The embed SDK
7
+ * scans for this tag and hydrates it. (Autonomous custom elements must
8
+ * contain a hyphen, so the SDK does not `define("widgetic")` — it finds
9
+ * `<widgetic>` in the DOM and renders into it.)
10
+ *
11
+ * The SDK script is served from `cdn.widgetic.com/sdks/browser/embed-sdk.js`
12
+ * (R2 custom domain on the `widgets` bucket — see AGENTS.md embed architecture).
13
+ */
14
+ export const EMBED_FORMATS = ['iframe', 'web-component'];
15
+ export const EMBED_FORMAT_LABELS = {
16
+ iframe: 'iframe',
17
+ 'web-component': 'Web Component'
18
+ };
19
+ /**
20
+ * Build the iframe embed snippet. Backward compatible with the previous
21
+ * hardcoded block in `CreatorApp.svelte`.
22
+ */
23
+ export function generateIframeEmbedCode({ embedSrc, width, height }) {
24
+ return `<iframe src="${embedSrc}" width="${width}" height="${height}" frameborder="0" allowfullscreen></iframe>`;
25
+ }
26
+ /**
27
+ * Build the Web Component embed snippet using `<widgetic>`.
28
+ * Requires a composition id — the custom element loader fetches the
29
+ * composition + widget module from the CDN via the embed-sdk batch API.
30
+ *
31
+ * If no composition is selected we fall back to the iframe format
32
+ * (caller should check `compositionId` before calling this).
33
+ */
34
+ export function generateWebComponentEmbedCode({ compositionId, width, height, sdkBaseUrl = 'https://cdn.widgetic.com' }) {
35
+ if (!compositionId) {
36
+ // Defensive: caller should have fallen back to iframe already.
37
+ return '';
38
+ }
39
+ return `<script src="${sdkBaseUrl}/sdks/browser/embed-sdk.js" async></script>
40
+ <widgetic
41
+ composition-id="${compositionId}"
42
+ width="${width}"
43
+ height="${height}"
44
+ render-mode="custom-element">
45
+ </widgetic>`;
46
+ }
47
+ /**
48
+ * Pick the right embed code for the requested format, with fallback to
49
+ * iframe when the Web Component format is requested but no composition
50
+ * is selected (custom element requires `composition-id`).
51
+ */
52
+ export function generateEmbedCode(format, params) {
53
+ if (format === 'web-component') {
54
+ if (!params.compositionId) {
55
+ return {
56
+ code: generateIframeEmbedCode(params),
57
+ effectiveFormat: 'iframe'
58
+ };
59
+ }
60
+ return {
61
+ code: generateWebComponentEmbedCode(params),
62
+ effectiveFormat: 'web-component'
63
+ };
64
+ }
65
+ return {
66
+ code: generateIframeEmbedCode(params),
67
+ effectiveFormat: 'iframe'
68
+ };
69
+ }
@@ -0,0 +1,4 @@
1
+ export declare function generateAudioFromText(description: string, duration?: any): Promise<any>;
2
+ export declare function generateImageFromText(str: string, imgWidth: number, imgHeight: number, genMetaObj: any): Promise<any>;
3
+ export declare function generateSuperprompt(str: string): Promise<any>;
4
+ export declare function wakeUpImageGenModel(): Promise<any>;
@@ -0,0 +1,94 @@
1
+ // local endoints methods(proxy)
2
+ // genenerate audio from text using Baseten model
3
+ export async function generateAudioFromText(description, duration = 5) {
4
+ // return { data: "https://replicate.delivery/pbxt/EKK8MxXO69LfeEhhWsy7FA2ku3KTvxrYFO2WxvLochuk1tUSA/output.wav" };
5
+ // basten model id
6
+ const model_id = "7qrj60r3"; // audio-gen model deployment id from the service we use to host models
7
+ // call the model
8
+ const result = await callModel({ prompts: [description], duration: Number(duration), model_host: 'baseten', model_id });
9
+ console.log('Audio Gen Model response data:', result);
10
+ // if no error return the data
11
+ if (!result.error && result.status !== 'error' && result.data) {
12
+ let res = result.data.length > 0 ? result.data[0] : result.data;
13
+ // add the audio data type
14
+ res = 'data:audio/mpeg;base64,' + res;
15
+ // return the audio data object
16
+ return { data: res };
17
+ }
18
+ // if error return the error
19
+ return result;
20
+ }
21
+ // generate images from text calling an AI Model
22
+ const img_gen_model_id = "1vn88"; // image-gen model deployment id from the service we use to host models
23
+ export async function generateImageFromText(str, imgWidth, imgHeight, genMetaObj) {
24
+ // create the model input
25
+ let input = {
26
+ prompt: str,
27
+ // image size
28
+ width: imgWidth, height: imgHeight,
29
+ // other params
30
+ ...genMetaObj,
31
+ // model id
32
+ model_id: img_gen_model_id
33
+ };
34
+ console.log('Model call input:', input);
35
+ // call the model
36
+ let response = await callModel(input);
37
+ console.log('Image Gen Model response:', response);
38
+ // check if no result
39
+ if (!response)
40
+ response = { error: 'No data generated!' };
41
+ // if no error add image header and return the data
42
+ if (!response.error && response.data) {
43
+ // TODO: check if it's an array of images and use first: response.data[0]
44
+ // console.log("Model data response:", response.data.length);
45
+ // let res = response.data.length > 0 ? response.data[0] : response.data;
46
+ // add the image data type
47
+ // res = 'data:image/png;base64,' + res;
48
+ let res = 'data:image/png;base64,' + response.data;
49
+ // return the image data object
50
+ return { data: res };
51
+ }
52
+ // if error return the error
53
+ return response;
54
+ }
55
+ let super_prompt_model_id = "oc3j2"; // superprompt-gen model deployment id from the service we use to host models
56
+ export async function generateSuperprompt(str) {
57
+ // call the model
58
+ let input = { prompt: str, lcm: true, model_host: 'groq', model_id: super_prompt_model_id };
59
+ // console.log('Model call input:', input);
60
+ const result = await callModel(input);
61
+ // console.log('Model response data:', result);
62
+ // if no error modify and return the data
63
+ if (!result.error && result.data) {
64
+ // TODO: check if it's an array of results then use first: results.data[0]
65
+ // console.log("Model data result:", result.data.length);
66
+ // let res = result.data.length > 0 ? result.data[0] : result.data;
67
+ // read the response data
68
+ let res = result.data;
69
+ // return the image data object
70
+ return { data: res };
71
+ }
72
+ // if error return the error
73
+ return result;
74
+ }
75
+ export async function wakeUpImageGenModel() {
76
+ // call the model
77
+ const result = await callModel({ model_id: img_gen_model_id, method: 'wake' });
78
+ // if no error return the data
79
+ return result;
80
+ }
81
+ async function callModel(input) {
82
+ // read model host service name
83
+ let model_host = input.model_host || 'beam';
84
+ // make a request to local endpoint that calls the model on server side
85
+ const response = await fetch(`/api/call-${model_host}-model`, {
86
+ method: 'POST',
87
+ headers: { 'Content-Type': 'application/json' },
88
+ body: JSON.stringify(input),
89
+ });
90
+ // read the data from the response
91
+ const data = await response.json();
92
+ // return response data
93
+ return data;
94
+ }