@drawnagency/primitives 0.1.67 → 0.1.68

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 (44) hide show
  1. package/dist/chunk-4YEOTFVU.js +14 -0
  2. package/dist/{chunk-VU3XR362.js → chunk-6UDYJQL6.js} +1 -1
  3. package/dist/{chunk-7IMQVDDJ.js → chunk-EWKCEPMW.js} +1 -1
  4. package/dist/{chunk-XNGG5AGI.js → chunk-KWBM27UR.js} +1 -1
  5. package/dist/{chunk-TEYTLQVH.js → chunk-QKOIEWZ4.js} +33 -1
  6. package/dist/{chunk-4VMAZZXT.js → chunk-TYYCKVAW.js} +4 -4
  7. package/dist/{chunk-KM6HOW4H.js → chunk-VVK6ZRCN.js} +2 -2
  8. package/dist/{chunk-AFK45HX2.js → chunk-WNPMBFD6.js} +1 -1
  9. package/dist/{chunk-WJ7RZ6CC.js → chunk-WXVKX6PY.js} +1 -1
  10. package/dist/components/chat/ChatPanel.d.ts +31 -0
  11. package/dist/components/chat/ChatPanel.d.ts.map +1 -0
  12. package/dist/components/chat/ChatWidget.d.ts +11 -0
  13. package/dist/components/chat/ChatWidget.d.ts.map +1 -0
  14. package/dist/components/primitives/index.js +5 -5
  15. package/dist/components/sections/brand-guide.js +5 -5
  16. package/dist/components/sections/register-schemas.js +7 -7
  17. package/dist/components/sections/register.js +7 -7
  18. package/dist/components/shell/ChatbotConfigModal.d.ts +13 -0
  19. package/dist/components/shell/ChatbotConfigModal.d.ts.map +1 -0
  20. package/dist/components/shell/EditorShell.d.ts +2 -1
  21. package/dist/components/shell/EditorShell.d.ts.map +1 -1
  22. package/dist/index.js +12 -5
  23. package/dist/lib/index.d.ts +1 -0
  24. package/dist/lib/index.d.ts.map +1 -1
  25. package/dist/lib/index.js +6 -3
  26. package/dist/lib/platform-broker.d.ts +7 -0
  27. package/dist/lib/platform-broker.d.ts.map +1 -1
  28. package/dist/lib/platform-broker.js +27 -1
  29. package/dist/media/index.js +3 -3
  30. package/dist/schemas/index.js +6 -2
  31. package/dist/schemas/site-config.d.ts +30 -0
  32. package/dist/schemas/site-config.d.ts.map +1 -1
  33. package/dist/types/database.d.ts +48 -0
  34. package/dist/types/database.d.ts.map +1 -1
  35. package/package.json +1 -1
  36. package/src/components/chat/ChatPanel.tsx +152 -0
  37. package/src/components/chat/ChatWidget.tsx +38 -0
  38. package/src/components/shell/ChatbotConfigModal.tsx +152 -0
  39. package/src/components/shell/EditorShell.tsx +28 -1
  40. package/src/lib/index.ts +1 -0
  41. package/src/lib/platform-broker.ts +36 -0
  42. package/src/schemas/site-config.ts +36 -0
  43. package/src/types/database.ts +48 -0
  44. package/dist/chunk-ZGFAYZWB.js +0 -8
@@ -70,3 +70,39 @@ export async function platformBroker<T = unknown>(
70
70
 
71
71
  throw lastError instanceof Error ? lastError : new Error("Platform broker unreachable");
72
72
  }
73
+
74
+ /**
75
+ * Streaming variant of platformBroker for SSE endpoints (the LLM broker).
76
+ * Same auth headers; retries only pre-stream connection failures — once bytes
77
+ * are flowing there is no safe retry. Non-2xx throws with the status ONLY
78
+ * (never the body: stream endpoints may proxy provider errors).
79
+ */
80
+ export async function platformBrokerStream(
81
+ path: string,
82
+ body: unknown,
83
+ ): Promise<ReadableStream<Uint8Array>> {
84
+ const apiUrl = env("PLATFORM_API_URL");
85
+ const apiKey = env("PLATFORM_API_KEY");
86
+ const siteId = env("PORTAL_SITE_ID");
87
+ const url = `${apiUrl}${path}`;
88
+
89
+ let lastError: unknown;
90
+ for (let attempt = 0; attempt < ATTEMPTS; attempt++) {
91
+ let res: Response;
92
+ try {
93
+ res = await fetch(url, {
94
+ method: "POST",
95
+ headers: { "x-api-key": apiKey, "x-site-id": siteId, "Content-Type": "application/json" },
96
+ body: JSON.stringify(body),
97
+ });
98
+ } catch (err) {
99
+ lastError = err;
100
+ if (attempt === ATTEMPTS - 1) throw err;
101
+ await sleep(RETRY_BASE_MS * 2 ** attempt);
102
+ continue;
103
+ }
104
+ if (!res.ok || !res.body) throw new Error(`Platform broker error (${res.status})`);
105
+ return res.body;
106
+ }
107
+ throw lastError instanceof Error ? lastError : new Error("Platform broker unreachable");
108
+ }
@@ -132,6 +132,38 @@ export function normalizeSiteIndex(raw: unknown): SiteIndex {
132
132
  return IndexSchema.parse(raw);
133
133
  }
134
134
 
135
+ // Task ids share the audience-name slug rules (lowercase alnum/dash/underscore).
136
+ const ChatbotTaskIdSchema = z.string().min(1).max(32).regex(/^[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?$/,
137
+ "Task id must be lowercase letters, numbers, dashes, or underscores");
138
+
139
+ export const ChatbotTaskSchema = z.object({
140
+ id: ChatbotTaskIdSchema,
141
+ label: z.string().min(1).max(60),
142
+ prompt: z.string().max(4_000),
143
+ // Audience names allowed to see this task; [] = all — same semantics as SectionMeta.access.
144
+ access: z.array(z.string()).default([]),
145
+ });
146
+ export type ChatbotTask = z.infer<typeof ChatbotTaskSchema>;
147
+
148
+ export const ChatbotConfigSchema = z
149
+ .object({
150
+ enabled: z.boolean().default(false),
151
+ systemPrompt: z.string().max(8_000).default(""),
152
+ // Audience names the widget is shown to; [] = all audiences.
153
+ audiences: z.array(z.string()).default([]),
154
+ tasks: z.array(ChatbotTaskSchema).max(20).default([]),
155
+ })
156
+ .superRefine((cfg, ctx) => {
157
+ const seen = new Set<string>();
158
+ for (const t of cfg.tasks) {
159
+ if (seen.has(t.id)) {
160
+ ctx.addIssue({ code: z.ZodIssueCode.custom, message: `Duplicate task id "${t.id}"` });
161
+ }
162
+ seen.add(t.id);
163
+ }
164
+ });
165
+ export type ChatbotConfig = z.infer<typeof ChatbotConfigSchema>;
166
+
135
167
  export const SiteConfigSchema = z.object({
136
168
  siteName: z.string().default("Brand Portal"),
137
169
  primaryColor: HexColorSchema.default("#009ca6"),
@@ -153,6 +185,10 @@ export const SiteConfigSchema = z.object({
153
185
  .nullable()
154
186
  .default(null),
155
187
  media: MediaConfigSchema.default(MediaConfigSchema.parse({})),
188
+ // Brand chatbot config (editor-owned; the platform kill switch lives in the
189
+ // sites table, not here). Every field defaults so pre-existing
190
+ // site-config.json files keep parsing.
191
+ chatbot: ChatbotConfigSchema.default({ enabled: false, systemPrompt: "", audiences: [], tasks: [] }),
156
192
  });
157
193
 
158
194
  export type SiteConfig = z.infer<typeof SiteConfigSchema>;
@@ -150,6 +150,41 @@ export type Database = {
150
150
  },
151
151
  ]
152
152
  }
153
+ chat_usage: {
154
+ Row: {
155
+ day: string
156
+ input_tokens: number
157
+ output_tokens: number
158
+ requests: number
159
+ site_id: string
160
+ updated_at: string
161
+ }
162
+ Insert: {
163
+ day: string
164
+ input_tokens?: number
165
+ output_tokens?: number
166
+ requests?: number
167
+ site_id: string
168
+ updated_at?: string
169
+ }
170
+ Update: {
171
+ day?: string
172
+ input_tokens?: number
173
+ output_tokens?: number
174
+ requests?: number
175
+ site_id?: string
176
+ updated_at?: string
177
+ }
178
+ Relationships: [
179
+ {
180
+ foreignKeyName: "chat_usage_site_id_fkey"
181
+ columns: ["site_id"]
182
+ isOneToOne: false
183
+ referencedRelation: "sites"
184
+ referencedColumns: ["id"]
185
+ },
186
+ ]
187
+ }
153
188
  deploy_status: {
154
189
  Row: {
155
190
  commit_sha: string | null
@@ -535,6 +570,7 @@ export type Database = {
535
570
  }
536
571
  sites: {
537
572
  Row: {
573
+ chatbot_enabled: boolean
538
574
  created_at: string | null
539
575
  custom_domain: string | null
540
576
  failed_step: string | null
@@ -550,6 +586,7 @@ export type Database = {
550
586
  subdomain: string | null
551
587
  }
552
588
  Insert: {
589
+ chatbot_enabled?: boolean
553
590
  created_at?: string | null
554
591
  custom_domain?: string | null
555
592
  failed_step?: string | null
@@ -565,6 +602,7 @@ export type Database = {
565
602
  subdomain?: string | null
566
603
  }
567
604
  Update: {
605
+ chatbot_enabled?: boolean
568
606
  created_at?: string | null
569
607
  custom_domain?: string | null
570
608
  failed_step?: string | null
@@ -642,6 +680,16 @@ export type Database = {
642
680
  [_ in never]: never
643
681
  }
644
682
  Functions: {
683
+ chat_usage_hit: {
684
+ Args: {
685
+ p_day: string
686
+ p_input_tokens: number
687
+ p_output_tokens: number
688
+ p_requests: number
689
+ p_site_id: string
690
+ }
691
+ Returns: undefined
692
+ }
645
693
  get_user_id_by_email: { Args: { lookup_email: string }; Returns: string }
646
694
  is_site_member: { Args: { p_site_id: string }; Returns: boolean }
647
695
  is_site_owner: { Args: { p_site_id: string }; Returns: boolean }
@@ -1,8 +0,0 @@
1
- // src/lib/pages.ts
2
- function slugifyPageSlug(input) {
3
- return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
4
- }
5
-
6
- export {
7
- slugifyPageSlug
8
- };