@firstlovecenter/ai-chat 0.6.0 → 0.7.0

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.
@@ -152,6 +152,11 @@ type ChatMessage = {
152
152
  * `rolePrompt` is the persona the assistant adopts. When non-null, it
153
153
  * takes precedence over the host's static `rolePrompt` configureAiChat
154
154
  * option, so admins can edit live in the settings UI.
155
+ *
156
+ * `gcpProjectId` is an admin-editable override for the GCP project that
157
+ * every Vertex API call targets. When non-null, it takes precedence over
158
+ * the host's static `VertexPort.projectId` so admins can flip projects
159
+ * (staging ↔ prod, multi-tenant) without redeploying.
155
160
  */
156
161
  type AiSettings = {
157
162
  toolProvider: string;
@@ -159,6 +164,7 @@ type AiSettings = {
159
164
  chatInterface: string;
160
165
  maxOutputTokens: number;
161
166
  rolePrompt: string | null;
167
+ gcpProjectId: string | null;
162
168
  updatedAt: Date | null;
163
169
  updatedByUserId: number | null;
164
170
  };
@@ -255,6 +261,8 @@ type AiSettingsPatch = {
255
261
  maxOutputTokens?: number;
256
262
  /** Pass `null` to clear back to the host's static fallback. */
257
263
  rolePrompt?: string | null;
264
+ /** Pass `null` to clear back to the host's static VertexPort.projectId. */
265
+ gcpProjectId?: string | null;
258
266
  };
259
267
  /**
260
268
  * The whole reason this package is ORM-agnostic. Implemented by:
@@ -152,6 +152,11 @@ type ChatMessage = {
152
152
  * `rolePrompt` is the persona the assistant adopts. When non-null, it
153
153
  * takes precedence over the host's static `rolePrompt` configureAiChat
154
154
  * option, so admins can edit live in the settings UI.
155
+ *
156
+ * `gcpProjectId` is an admin-editable override for the GCP project that
157
+ * every Vertex API call targets. When non-null, it takes precedence over
158
+ * the host's static `VertexPort.projectId` so admins can flip projects
159
+ * (staging ↔ prod, multi-tenant) without redeploying.
155
160
  */
156
161
  type AiSettings = {
157
162
  toolProvider: string;
@@ -159,6 +164,7 @@ type AiSettings = {
159
164
  chatInterface: string;
160
165
  maxOutputTokens: number;
161
166
  rolePrompt: string | null;
167
+ gcpProjectId: string | null;
162
168
  updatedAt: Date | null;
163
169
  updatedByUserId: number | null;
164
170
  };
@@ -255,6 +261,8 @@ type AiSettingsPatch = {
255
261
  maxOutputTokens?: number;
256
262
  /** Pass `null` to clear back to the host's static fallback. */
257
263
  rolePrompt?: string | null;
264
+ /** Pass `null` to clear back to the host's static VertexPort.projectId. */
265
+ gcpProjectId?: string | null;
258
266
  };
259
267
  /**
260
268
  * The whole reason this package is ORM-agnostic. Implemented by:
package/dist/ui/index.cjs CHANGED
@@ -489,17 +489,22 @@ function sanitiseBlock(input) {
489
489
  }
490
490
  return { kind: "callout", tone: input.tone, text: input.text };
491
491
  }
492
+ function isBlankString(v) {
493
+ return typeof v !== "string" || !v.trim();
494
+ }
492
495
  function isBlockEmpty(b) {
493
496
  if (b.kind === "paragraph_brief") {
494
- if (b.prose && b.prose.trim()) return false;
495
- return b.key_facts.length === 0 || b.key_facts.every((f) => !f.trim());
497
+ if (typeof b.prose === "string" && b.prose.trim()) return false;
498
+ const facts = Array.isArray(b.key_facts) ? b.key_facts : [];
499
+ return facts.length === 0 || facts.every(isBlankString);
496
500
  }
497
501
  if (b.kind === "list") {
498
- return b.items.length === 0 || b.items.every((i) => !i.trim());
502
+ const items = Array.isArray(b.items) ? b.items : [];
503
+ return items.length === 0 || items.every(isBlankString);
499
504
  }
500
- if (b.kind === "callout") return !b.text.trim();
501
- if (b.kind === "chart") return b.data.length === 0;
502
- if (b.kind === "table") return b.rows.length === 0;
505
+ if (b.kind === "callout") return isBlankString(b.text);
506
+ if (b.kind === "chart") return !Array.isArray(b.data) || b.data.length === 0;
507
+ if (b.kind === "table") return !Array.isArray(b.rows) || b.rows.length === 0;
503
508
  return false;
504
509
  }
505
510
  function AnswerBlocks({ blocks }) {