@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.
@@ -1,5 +1,5 @@
1
- import { S as SystemBlock, T as ToolSchema, a as ToolContext, b as ToolDefinition, P as PresentPayload, c as PersistencePort, A as AuthPort, d as ScopePort, e as ToolsPort, V as VertexPort, L as LoggerPort } from '../types-CQntnyDJ.cjs';
2
- export { f as AiSettings, g as AiSettingsPatch, h as AppendMessageInput, i as AuthFail, j as AuthOk, k as AuthResult, B as Block, C as ChartSpec, l as ChatMessage, m as ChatMessageRole, n as ChatSession, o as CreateSessionInput, p as ListSessionsOpts, q as TERMINAL_TOOL_NAME, r as ToolResult, s as err, t as ok } from '../types-CQntnyDJ.cjs';
1
+ import { S as SystemBlock, T as ToolSchema, a as ToolContext, b as ToolDefinition, P as PresentPayload, c as PersistencePort, A as AuthPort, d as ScopePort, e as ToolsPort, V as VertexPort, L as LoggerPort } from '../types-BnwUkqKb.cjs';
2
+ export { f as AiSettings, g as AiSettingsPatch, h as AppendMessageInput, i as AuthFail, j as AuthOk, k as AuthResult, B as Block, C as ChartSpec, l as ChatMessage, m as ChatMessageRole, n as ChatSession, o as CreateSessionInput, p as ListSessionsOpts, q as TERMINAL_TOOL_NAME, r as ToolResult, s as err, t as ok } from '../types-BnwUkqKb.cjs';
3
3
  import { GoogleAuth } from 'google-auth-library';
4
4
  export { GoogleAuth } from 'google-auth-library';
5
5
  import 'zod';
@@ -398,7 +398,7 @@ declare function createChatSessionsRoutes<S>(ctx: ChatSessionsRouteCtx<S>): {
398
398
  /**
399
399
  * `/api/admin/ai-settings` route factory — global AI configuration (super_admin only).
400
400
  *
401
- * Five patchable fields on the singleton settings row:
401
+ * Six patchable fields on the singleton settings row:
402
402
  * - `tool_provider` — vendor that drives the agent tool loop. Validated
403
403
  * against the registered `toolProviders` registry passed in via ctx.
404
404
  * - `gcp_location` — the Vertex region every provider call hits. Stays
@@ -417,6 +417,10 @@ declare function createChatSessionsRoutes<S>(ctx: ChatSessionsRouteCtx<S>): {
417
417
  * `configureAiChat({ rolePrompt })` fallback; we canonicalise an empty/
418
418
  * whitespace-only string to `null` on write so the "no override" state has
419
419
  * a single representation in storage.
420
+ * - `gcp_project_id` — admin-editable GCP project override. Empty string and
421
+ * the explicit JSON `null` both clear the override back to the host's
422
+ * static `VertexPort.projectId`. Validated against GCP's project-id
423
+ * format (`[a-z][-a-z0-9]{4,28}[a-z0-9]`) when non-null.
420
424
  *
421
425
  * Wire format is snake_case to preserve byte-for-byte parity with the
422
426
  * host route the package replaces — existing host UIs keep working
@@ -1,5 +1,5 @@
1
- import { S as SystemBlock, T as ToolSchema, a as ToolContext, b as ToolDefinition, P as PresentPayload, c as PersistencePort, A as AuthPort, d as ScopePort, e as ToolsPort, V as VertexPort, L as LoggerPort } from '../types-CQntnyDJ.js';
2
- export { f as AiSettings, g as AiSettingsPatch, h as AppendMessageInput, i as AuthFail, j as AuthOk, k as AuthResult, B as Block, C as ChartSpec, l as ChatMessage, m as ChatMessageRole, n as ChatSession, o as CreateSessionInput, p as ListSessionsOpts, q as TERMINAL_TOOL_NAME, r as ToolResult, s as err, t as ok } from '../types-CQntnyDJ.js';
1
+ import { S as SystemBlock, T as ToolSchema, a as ToolContext, b as ToolDefinition, P as PresentPayload, c as PersistencePort, A as AuthPort, d as ScopePort, e as ToolsPort, V as VertexPort, L as LoggerPort } from '../types-BnwUkqKb.js';
2
+ export { f as AiSettings, g as AiSettingsPatch, h as AppendMessageInput, i as AuthFail, j as AuthOk, k as AuthResult, B as Block, C as ChartSpec, l as ChatMessage, m as ChatMessageRole, n as ChatSession, o as CreateSessionInput, p as ListSessionsOpts, q as TERMINAL_TOOL_NAME, r as ToolResult, s as err, t as ok } from '../types-BnwUkqKb.js';
3
3
  import { GoogleAuth } from 'google-auth-library';
4
4
  export { GoogleAuth } from 'google-auth-library';
5
5
  import 'zod';
@@ -398,7 +398,7 @@ declare function createChatSessionsRoutes<S>(ctx: ChatSessionsRouteCtx<S>): {
398
398
  /**
399
399
  * `/api/admin/ai-settings` route factory — global AI configuration (super_admin only).
400
400
  *
401
- * Five patchable fields on the singleton settings row:
401
+ * Six patchable fields on the singleton settings row:
402
402
  * - `tool_provider` — vendor that drives the agent tool loop. Validated
403
403
  * against the registered `toolProviders` registry passed in via ctx.
404
404
  * - `gcp_location` — the Vertex region every provider call hits. Stays
@@ -417,6 +417,10 @@ declare function createChatSessionsRoutes<S>(ctx: ChatSessionsRouteCtx<S>): {
417
417
  * `configureAiChat({ rolePrompt })` fallback; we canonicalise an empty/
418
418
  * whitespace-only string to `null` on write so the "no override" state has
419
419
  * a single representation in storage.
420
+ * - `gcp_project_id` — admin-editable GCP project override. Empty string and
421
+ * the explicit JSON `null` both clear the override back to the host's
422
+ * static `VertexPort.projectId`. Validated against GCP's project-id
423
+ * format (`[a-z][-a-z0-9]{4,28}[a-z0-9]`) when non-null.
420
424
  *
421
425
  * Wire format is snake_case to preserve byte-for-byte parity with the
422
426
  * host route the package replaces — existing host UIs keep working
@@ -912,6 +912,7 @@ function createAgentCustomRoutes(ctx) {
912
912
  const rawChatSessionId = body?.chatSessionId;
913
913
  const incomingChatSessionId = typeof rawChatSessionId === "number" && Number.isInteger(rawChatSessionId) ? rawChatSessionId : null;
914
914
  const aiSettings = await persistence.getAiSettings();
915
+ const effectiveProjectId = aiSettings.gcpProjectId ?? vertex.projectId;
915
916
  let chatSessionId;
916
917
  if (incomingChatSessionId !== null) {
917
918
  const owned = await persistence.getSession(incomingChatSessionId, userId);
@@ -955,7 +956,7 @@ function createAgentCustomRoutes(ctx) {
955
956
  }
956
957
  const provider = def.createProvider({
957
958
  auth: vertex.auth,
958
- projectId: vertex.projectId,
959
+ projectId: effectiveProjectId,
959
960
  defaultLocation: vertex.defaultLocation,
960
961
  modelIds: vertex.modelIds,
961
962
  location: aiSettings.gcpLocation
@@ -1033,7 +1034,7 @@ data: ${JSON.stringify(data)}
1033
1034
  }
1034
1035
  for await (const token of narratorFn({
1035
1036
  auth: vertex.auth,
1036
- projectId: vertex.projectId,
1037
+ projectId: effectiveProjectId,
1037
1038
  location: aiSettings.gcpLocation,
1038
1039
  modelId: narratorModelId,
1039
1040
  maxTokens: aiSettings.maxOutputTokens,
@@ -1237,6 +1238,7 @@ function createAgentVercelRoutes(ctx) {
1237
1238
  const rawModel = body?.model;
1238
1239
  const requestedModel = typeof rawModel === "string" && VALID_MODELS.has(rawModel) ? rawModel : null;
1239
1240
  const aiSettings = await persistence.getAiSettings();
1241
+ const effectiveProjectId = aiSettings.gcpProjectId ?? vertex.projectId;
1240
1242
  let chatSessionId;
1241
1243
  if (incomingChatSessionId !== null) {
1242
1244
  const owned = await persistence.getSession(
@@ -1308,11 +1310,11 @@ function createAgentVercelRoutes(ctx) {
1308
1310
  });
1309
1311
  const system = systemBlocks.map((b) => b.text).join("\n\n");
1310
1312
  const model = provider === "claude" ? createVertexAnthropic({
1311
- project: vertex.projectId,
1313
+ project: effectiveProjectId,
1312
1314
  location: vertex.defaultLocation,
1313
1315
  googleAuthOptions: {}
1314
1316
  })(vertex.modelIds.claude) : createVertex({
1315
- project: vertex.projectId,
1317
+ project: effectiveProjectId,
1316
1318
  location: aiSettings.gcpLocation,
1317
1319
  googleAuthOptions: {}
1318
1320
  })(vertex.modelIds.gemini);
@@ -1613,6 +1615,7 @@ function createChatSessionsRoutes(ctx) {
1613
1615
  var VALID_LOCATIONS = ["us-east5", "global"];
1614
1616
  var MIN_MAX_OUTPUT_TOKENS = 256;
1615
1617
  var MAX_MAX_OUTPUT_TOKENS = 64e3;
1618
+ var GCP_PROJECT_ID_REGEX = /^[a-z][-a-z0-9]{4,28}[a-z0-9]$/;
1616
1619
  function isStringRecord(v) {
1617
1620
  return typeof v === "object" && v !== null && !Array.isArray(v);
1618
1621
  }
@@ -1629,6 +1632,7 @@ function toWire(settings) {
1629
1632
  chat_interface: settings.chatInterface,
1630
1633
  max_output_tokens: settings.maxOutputTokens,
1631
1634
  role_prompt: settings.rolePrompt,
1635
+ gcp_project_id: settings.gcpProjectId,
1632
1636
  updated_at: settings.updatedAt ? settings.updatedAt.toISOString() : null,
1633
1637
  updated_by_user_id: settings.updatedByUserId
1634
1638
  };
@@ -1726,11 +1730,28 @@ function createAdminSettingsRoutes(ctx) {
1726
1730
  return jsonResponse({ error: "invalid_role_prompt" }, 400);
1727
1731
  }
1728
1732
  }
1729
- if (patch.toolProvider === void 0 && patch.gcpLocation === void 0 && patch.chatInterface === void 0 && patch.maxOutputTokens === void 0 && !("rolePrompt" in patch)) {
1733
+ if ("gcp_project_id" in body) {
1734
+ const v = body.gcp_project_id;
1735
+ if (v === null) {
1736
+ patch.gcpProjectId = null;
1737
+ } else if (typeof v === "string") {
1738
+ const trimmed = v.trim();
1739
+ if (trimmed === "") {
1740
+ patch.gcpProjectId = null;
1741
+ } else if (trimmed.length > 64 || !GCP_PROJECT_ID_REGEX.test(trimmed)) {
1742
+ return jsonResponse({ error: "invalid_gcp_project_id" }, 400);
1743
+ } else {
1744
+ patch.gcpProjectId = trimmed;
1745
+ }
1746
+ } else {
1747
+ return jsonResponse({ error: "invalid_gcp_project_id" }, 400);
1748
+ }
1749
+ }
1750
+ if (patch.toolProvider === void 0 && patch.gcpLocation === void 0 && patch.chatInterface === void 0 && patch.maxOutputTokens === void 0 && !("rolePrompt" in patch) && !("gcpProjectId" in patch)) {
1730
1751
  return jsonResponse(
1731
1752
  {
1732
1753
  error: "empty_patch",
1733
- message: "Body must set at least one of tool_provider, gcp_location, chat_interface, max_output_tokens, role_prompt."
1754
+ message: "Body must set at least one of tool_provider, gcp_location, chat_interface, max_output_tokens, role_prompt, gcp_project_id."
1734
1755
  },
1735
1756
  400
1736
1757
  );
@@ -1791,9 +1812,10 @@ function configureAiChat(opts) {
1791
1812
  `Unknown tool provider '${providerId ?? settings.toolProvider}'. Registered: ${toolProviders2.map((p) => p.id).join(", ")}.`
1792
1813
  );
1793
1814
  }
1815
+ const effectiveProjectId = settings.gcpProjectId ?? opts.vertex.projectId;
1794
1816
  const provider = def.createProvider({
1795
1817
  auth: opts.vertex.auth,
1796
- projectId: opts.vertex.projectId,
1818
+ projectId: effectiveProjectId,
1797
1819
  defaultLocation: opts.vertex.defaultLocation,
1798
1820
  modelIds: opts.vertex.modelIds,
1799
1821
  location: location ?? settings.gcpLocation