@firstlovecenter/ai-chat 0.2.3 → 0.5.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,7 +1,8 @@
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-DNwFvL-C.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-DNwFvL-C.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-CDKxdzQc.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-CDKxdzQc.cjs';
3
3
  import { GoogleAuth } from 'google-auth-library';
4
4
  export { GoogleAuth } from 'google-auth-library';
5
+ import 'zod';
5
6
 
6
7
  /**
7
8
  * Provider-agnostic tool-calling abstraction.
@@ -302,6 +303,34 @@ declare function createAgentCustomRoutes<S>(ctx: AgentCustomRouteCtx<S>): {
302
303
  POST: (req: Request) => Promise<Response>;
303
304
  };
304
305
 
306
+ /**
307
+ * Streaming-route hooks for the Vercel AI SDK chat.
308
+ *
309
+ * Identical to `AgentCustomHooks` — the lifecycle (pre-auth → auth →
310
+ * post-auth → resolve session → onSessionStart → stream → onSessionEnd)
311
+ * is the same. We re-alias rather than introducing a new type so consumers
312
+ * can plug a single hook bag into both routes.
313
+ */
314
+ type AgentVercelHooks$1<S> = AgentCustomHooks$1<S>;
315
+ type AgentVercelRouteCtx<S> = {
316
+ persistence: PersistencePort;
317
+ auth: AuthPort<S>;
318
+ scope: ScopePort<S>;
319
+ tools: ToolsPort;
320
+ vertex: VertexPort;
321
+ logger?: LoggerPort;
322
+ /**
323
+ * Optional lifecycle hooks. See `AgentCustomHooks` for the available
324
+ * extension points (shutdown gating, rate limiting, per-request
325
+ * resource setup/teardown).
326
+ */
327
+ hooks?: AgentVercelHooks$1<S>;
328
+ };
329
+ declare function createAgentVercelRoutes<S>(ctx: AgentVercelRouteCtx<S>): {
330
+ /** Next.js-compatible POST handler. */
331
+ POST: (req: Request) => Promise<Response>;
332
+ };
333
+
305
334
  /**
306
335
  * `chat-sessions` route factory — host-agnostic CRUD for chat sessions.
307
336
  *
@@ -501,6 +530,7 @@ type AiChatRuntime<S = unknown> = {
501
530
  }) => Promise<AgentResult>;
502
531
  routes: {
503
532
  agentCustom: ReturnType<typeof createAgentCustomRoutes<S>>;
533
+ agentVercel: ReturnType<typeof createAgentVercelRoutes<S>>;
504
534
  chatSessions: ReturnType<typeof createChatSessionsRoutes<S>>;
505
535
  adminSettings: ReturnType<typeof createAdminSettingsRoutes<S>>;
506
536
  };
@@ -513,5 +543,12 @@ declare function configureAiChat<S = unknown>(opts: ConfigureAiChatOpts<S>): AiC
513
543
 
514
544
  type RouteHooks<S> = RouteHooks$1<S>;
515
545
  type AgentCustomHooks<S> = AgentCustomHooks$1<S>;
546
+ /**
547
+ * Alias of `AgentCustomHooks` — the Vercel AI SDK chat reuses the same
548
+ * lifecycle (pre-auth → auth → post-auth → resolve session → onSessionStart
549
+ * → stream → onSessionEnd). Re-exported for callers that prefer the more
550
+ * specific name.
551
+ */
552
+ type AgentVercelHooks<S> = AgentVercelHooks$1<S>;
516
553
 
517
- export { type AgentCustomHooks, type AgentInput, type AgentResult, type AiChatRuntime, AuthPort, BUILTIN_CHAT_INTERFACE_IDS, type ChatInterfaceRegistryEntry, type ConfigureAiChatOpts, DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_MAX_TOOL_TURNS, LoggerPort, PersistencePort, PresentPayload, type ProviderInitOpts, type RouteHooks, ScopePort, SystemBlock, ToolContext, ToolDefinition, type ToolProviderDef, ToolSchema, ToolsPort, type TranscriptEntry, VertexPort, configureAiChat, getToolProvider, runAgent, toolProviders };
554
+ export { type AgentCustomHooks, type AgentInput, type AgentResult, type AgentVercelHooks, type AiChatRuntime, AuthPort, BUILTIN_CHAT_INTERFACE_IDS, type ChatInterfaceRegistryEntry, type ConfigureAiChatOpts, DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_MAX_TOOL_TURNS, LoggerPort, PersistencePort, PresentPayload, type ProviderInitOpts, type RouteHooks, ScopePort, SystemBlock, ToolContext, ToolDefinition, type ToolProviderDef, ToolSchema, ToolsPort, type TranscriptEntry, VertexPort, configureAiChat, getToolProvider, runAgent, toolProviders };
@@ -1,7 +1,8 @@
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-DNwFvL-C.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-DNwFvL-C.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-CDKxdzQc.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-CDKxdzQc.js';
3
3
  import { GoogleAuth } from 'google-auth-library';
4
4
  export { GoogleAuth } from 'google-auth-library';
5
+ import 'zod';
5
6
 
6
7
  /**
7
8
  * Provider-agnostic tool-calling abstraction.
@@ -302,6 +303,34 @@ declare function createAgentCustomRoutes<S>(ctx: AgentCustomRouteCtx<S>): {
302
303
  POST: (req: Request) => Promise<Response>;
303
304
  };
304
305
 
306
+ /**
307
+ * Streaming-route hooks for the Vercel AI SDK chat.
308
+ *
309
+ * Identical to `AgentCustomHooks` — the lifecycle (pre-auth → auth →
310
+ * post-auth → resolve session → onSessionStart → stream → onSessionEnd)
311
+ * is the same. We re-alias rather than introducing a new type so consumers
312
+ * can plug a single hook bag into both routes.
313
+ */
314
+ type AgentVercelHooks$1<S> = AgentCustomHooks$1<S>;
315
+ type AgentVercelRouteCtx<S> = {
316
+ persistence: PersistencePort;
317
+ auth: AuthPort<S>;
318
+ scope: ScopePort<S>;
319
+ tools: ToolsPort;
320
+ vertex: VertexPort;
321
+ logger?: LoggerPort;
322
+ /**
323
+ * Optional lifecycle hooks. See `AgentCustomHooks` for the available
324
+ * extension points (shutdown gating, rate limiting, per-request
325
+ * resource setup/teardown).
326
+ */
327
+ hooks?: AgentVercelHooks$1<S>;
328
+ };
329
+ declare function createAgentVercelRoutes<S>(ctx: AgentVercelRouteCtx<S>): {
330
+ /** Next.js-compatible POST handler. */
331
+ POST: (req: Request) => Promise<Response>;
332
+ };
333
+
305
334
  /**
306
335
  * `chat-sessions` route factory — host-agnostic CRUD for chat sessions.
307
336
  *
@@ -501,6 +530,7 @@ type AiChatRuntime<S = unknown> = {
501
530
  }) => Promise<AgentResult>;
502
531
  routes: {
503
532
  agentCustom: ReturnType<typeof createAgentCustomRoutes<S>>;
533
+ agentVercel: ReturnType<typeof createAgentVercelRoutes<S>>;
504
534
  chatSessions: ReturnType<typeof createChatSessionsRoutes<S>>;
505
535
  adminSettings: ReturnType<typeof createAdminSettingsRoutes<S>>;
506
536
  };
@@ -513,5 +543,12 @@ declare function configureAiChat<S = unknown>(opts: ConfigureAiChatOpts<S>): AiC
513
543
 
514
544
  type RouteHooks<S> = RouteHooks$1<S>;
515
545
  type AgentCustomHooks<S> = AgentCustomHooks$1<S>;
546
+ /**
547
+ * Alias of `AgentCustomHooks` — the Vercel AI SDK chat reuses the same
548
+ * lifecycle (pre-auth → auth → post-auth → resolve session → onSessionStart
549
+ * → stream → onSessionEnd). Re-exported for callers that prefer the more
550
+ * specific name.
551
+ */
552
+ type AgentVercelHooks<S> = AgentVercelHooks$1<S>;
516
553
 
517
- export { type AgentCustomHooks, type AgentInput, type AgentResult, type AiChatRuntime, AuthPort, BUILTIN_CHAT_INTERFACE_IDS, type ChatInterfaceRegistryEntry, type ConfigureAiChatOpts, DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_MAX_TOOL_TURNS, LoggerPort, PersistencePort, PresentPayload, type ProviderInitOpts, type RouteHooks, ScopePort, SystemBlock, ToolContext, ToolDefinition, type ToolProviderDef, ToolSchema, ToolsPort, type TranscriptEntry, VertexPort, configureAiChat, getToolProvider, runAgent, toolProviders };
554
+ export { type AgentCustomHooks, type AgentInput, type AgentResult, type AgentVercelHooks, type AiChatRuntime, AuthPort, BUILTIN_CHAT_INTERFACE_IDS, type ChatInterfaceRegistryEntry, type ConfigureAiChatOpts, DEFAULT_MAX_OUTPUT_TOKENS, DEFAULT_MAX_TOOL_TURNS, LoggerPort, PersistencePort, PresentPayload, type ProviderInitOpts, type RouteHooks, ScopePort, SystemBlock, ToolContext, ToolDefinition, type ToolProviderDef, ToolSchema, ToolsPort, type TranscriptEntry, VertexPort, configureAiChat, getToolProvider, runAgent, toolProviders };
@@ -1,5 +1,8 @@
1
1
  import { AnthropicVertex } from '@anthropic-ai/vertex-sdk';
2
2
  import { randomUUID } from 'crypto';
3
+ import { StreamData, streamText, tool } from 'ai';
4
+ import { createVertex } from '@ai-sdk/google-vertex';
5
+ import { createVertexAnthropic } from '@ai-sdk/google-vertex/anthropic';
3
6
  export { GoogleAuth } from 'google-auth-library';
4
7
 
5
8
  // src/server/tools/types.ts
@@ -70,8 +73,8 @@ async function runAgent(input) {
70
73
  const toolResults = [];
71
74
  for (const tc of response.toolCalls) {
72
75
  transcript.push({ kind: "tool_use", name: tc.name, input: tc.input });
73
- const tool = input.tools[tc.name];
74
- if (!tool) {
76
+ const tool2 = input.tools[tc.name];
77
+ if (!tool2) {
75
78
  const errResult = {
76
79
  ok: false,
77
80
  error: { code: "UNKNOWN_TOOL", message: `Unknown tool: ${tc.name}` }
@@ -85,7 +88,7 @@ async function runAgent(input) {
85
88
  });
86
89
  continue;
87
90
  }
88
- const result = await tool.execute(tc.input, {
91
+ const result = await tool2.execute(tc.input, {
89
92
  ...input.ctx,
90
93
  toolCallCount
91
94
  });
@@ -1135,6 +1138,297 @@ data: {}
1135
1138
  }
1136
1139
  };
1137
1140
  }
1141
+ function buildVercelTools(tools, ctx, data, onPresent) {
1142
+ const result = {};
1143
+ let toolCallCount = 0;
1144
+ for (const [name, def] of Object.entries(tools)) {
1145
+ if (!def.zodSchema) {
1146
+ throw new Error(
1147
+ `Tool '${name}' has no zodSchema; required for the Vercel AI SDK chat. Add a Zod schema to the tool definition (or remove it from the registry if the host only uses the custom SSE chat).`
1148
+ );
1149
+ }
1150
+ if (name === TERMINAL_TOOL_NAME) {
1151
+ result[name] = tool({
1152
+ description: def.schema.description,
1153
+ // The Zod schema doubles as the runtime parameter validator the SDK
1154
+ // hands the model. We accept whatever Zod shape the host registered;
1155
+ // the SDK uses it to validate the tool-call arguments before dispatch.
1156
+ parameters: def.zodSchema,
1157
+ execute: async (input) => {
1158
+ if (toolCallCount < 2) {
1159
+ return {
1160
+ error: {
1161
+ code: "SELF_VERIFY_REQUIRED",
1162
+ message: "Per FR-8.3 you must run at least one CROSS-CHECK tool call (a different metric, a different period, or a run_sql sanity-check) before present. Make that extra call now, then call present again."
1163
+ }
1164
+ };
1165
+ }
1166
+ const payload = input;
1167
+ for (let i = 0; i < payload.blocks.length; i++) {
1168
+ data.append({
1169
+ type: "block",
1170
+ value: { index: i, ...payload.blocks[i] }
1171
+ });
1172
+ }
1173
+ onPresent(payload);
1174
+ return { ok: true };
1175
+ }
1176
+ });
1177
+ continue;
1178
+ }
1179
+ result[name] = tool({
1180
+ description: def.schema.description,
1181
+ parameters: def.zodSchema,
1182
+ execute: async (input) => {
1183
+ const res = await def.execute(input, { ...ctx, toolCallCount });
1184
+ toolCallCount += 1;
1185
+ if (res.ok) return res.data;
1186
+ return { error: res.error };
1187
+ }
1188
+ });
1189
+ }
1190
+ return result;
1191
+ }
1192
+
1193
+ // src/server/routes/agent-vercel.ts
1194
+ var VALID_MODELS = /* @__PURE__ */ new Set(["claude", "gemini"]);
1195
+ function jsonError2(status, code, message) {
1196
+ return new Response(JSON.stringify({ error: { code, message } }), {
1197
+ status,
1198
+ headers: { "Content-Type": "application/json" }
1199
+ });
1200
+ }
1201
+ function defaultGenerateSessionId2() {
1202
+ return randomUUID().replace(/-/g, "").slice(0, 16);
1203
+ }
1204
+ function createAgentVercelRoutes(ctx) {
1205
+ const { persistence, auth, scope, tools, vertex, logger, hooks } = ctx;
1206
+ return {
1207
+ /** Next.js-compatible POST handler. */
1208
+ POST: async (req) => {
1209
+ if (hooks?.onRequest) {
1210
+ const short = await hooks.onRequest(req);
1211
+ if (short) return short;
1212
+ }
1213
+ const authResult = await auth.requireAuth(req);
1214
+ if (!authResult.ok) return authResult.response;
1215
+ const { scope: callerScope, userId } = authResult;
1216
+ if (hooks?.onAuthenticated) {
1217
+ const short = await hooks.onAuthenticated({
1218
+ req,
1219
+ scope: callerScope,
1220
+ userId
1221
+ });
1222
+ if (short) return short;
1223
+ }
1224
+ const body = await req.json().catch(() => null);
1225
+ const question = typeof body?.question === "string" ? body.question.trim() : "";
1226
+ if (!question) {
1227
+ return jsonError2(
1228
+ 400,
1229
+ "VALIDATION_FAILED",
1230
+ "question must be a non-empty string."
1231
+ );
1232
+ }
1233
+ const rawChatSessionId = body?.chatSessionId;
1234
+ const incomingChatSessionId = typeof rawChatSessionId === "number" && Number.isInteger(rawChatSessionId) ? rawChatSessionId : null;
1235
+ const rawModel = body?.model;
1236
+ const requestedModel = typeof rawModel === "string" && VALID_MODELS.has(rawModel) ? rawModel : null;
1237
+ const aiSettings = await persistence.getAiSettings();
1238
+ let chatSessionId;
1239
+ if (incomingChatSessionId !== null) {
1240
+ const owned = await persistence.getSession(
1241
+ incomingChatSessionId,
1242
+ userId
1243
+ );
1244
+ if (!owned) {
1245
+ return jsonError2(404, "NOT_FOUND", "Chat session not found.");
1246
+ }
1247
+ chatSessionId = owned.id;
1248
+ } else {
1249
+ const created = await persistence.createSession({
1250
+ userId,
1251
+ title: question.slice(0, 200)
1252
+ });
1253
+ chatSessionId = created.id;
1254
+ }
1255
+ await persistence.appendMessage({
1256
+ sessionId: chatSessionId,
1257
+ role: "user",
1258
+ question
1259
+ });
1260
+ const sessionId = hooks?.generateSessionId ? await hooks.generateSessionId({
1261
+ scope: callerScope,
1262
+ userId,
1263
+ chatSessionId: incomingChatSessionId
1264
+ }) : defaultGenerateSessionId2();
1265
+ const scopeSummary = await scope.buildScopeSummary(callerScope);
1266
+ const scopeLabel = await scope.resolveScopeLabel(callerScope);
1267
+ const toolContext = {
1268
+ scope: callerScope,
1269
+ sessionId,
1270
+ scopeSummary,
1271
+ toolCallCount: 0
1272
+ };
1273
+ const systemBlocks = await tools.buildSystemBlocks(toolContext);
1274
+ const provider = requestedModel ?? aiSettings.toolProvider;
1275
+ if (!VALID_MODELS.has(provider)) {
1276
+ return jsonError2(
1277
+ 400,
1278
+ "INVALID_PROVIDER",
1279
+ `Vercel chat only supports 'claude' or 'gemini'; got '${provider}'.`
1280
+ );
1281
+ }
1282
+ const data = new StreamData();
1283
+ let presentPayload = null;
1284
+ let persistedError = null;
1285
+ let sessionStarted = false;
1286
+ try {
1287
+ if (hooks?.onSessionStart) {
1288
+ await hooks.onSessionStart({
1289
+ scope: callerScope,
1290
+ sessionId,
1291
+ userId
1292
+ });
1293
+ }
1294
+ sessionStarted = true;
1295
+ const vercelTools = buildVercelTools(
1296
+ tools.tools,
1297
+ toolContext,
1298
+ data,
1299
+ (p) => {
1300
+ presentPayload = p;
1301
+ }
1302
+ );
1303
+ data.append({
1304
+ type: "meta",
1305
+ value: { chatSessionId, scopeLabel }
1306
+ });
1307
+ const system = systemBlocks.map((b) => b.text).join("\n\n");
1308
+ const model = provider === "claude" ? createVertexAnthropic({
1309
+ project: vertex.projectId,
1310
+ location: vertex.defaultLocation,
1311
+ googleAuthOptions: {}
1312
+ })(vertex.modelIds.claude) : createVertex({
1313
+ project: vertex.projectId,
1314
+ location: aiSettings.gcpLocation,
1315
+ googleAuthOptions: {}
1316
+ })(vertex.modelIds.gemini);
1317
+ const result = streamText({
1318
+ model,
1319
+ system,
1320
+ messages: [{ role: "user", content: question }],
1321
+ tools: vercelTools,
1322
+ maxSteps: 12,
1323
+ maxTokens: 4096,
1324
+ onFinish: async ({ text }) => {
1325
+ try {
1326
+ let blocks = presentPayload?.blocks ?? [];
1327
+ const prose = {};
1328
+ const trimmed = (text ?? "").trim();
1329
+ if (presentPayload === null && trimmed) {
1330
+ const topic = question.length > 80 ? question.slice(0, 77) + "..." : question;
1331
+ const synthetic = {
1332
+ kind: "paragraph_brief",
1333
+ topic,
1334
+ key_facts: [trimmed]
1335
+ };
1336
+ blocks = [synthetic];
1337
+ prose[0] = trimmed;
1338
+ data.append({
1339
+ type: "block",
1340
+ value: { index: 0, ...synthetic }
1341
+ });
1342
+ } else if (text) {
1343
+ const firstPbIdx = blocks.findIndex(
1344
+ (b) => b.kind === "paragraph_brief"
1345
+ );
1346
+ if (firstPbIdx >= 0) prose[firstPbIdx] = text;
1347
+ }
1348
+ await persistence.appendMessage({
1349
+ sessionId: chatSessionId,
1350
+ role: "assistant",
1351
+ blocks: blocks.length ? blocks : null,
1352
+ prose: Object.keys(prose).length ? prose : null,
1353
+ errorJson: persistedError
1354
+ });
1355
+ } catch (err2) {
1356
+ logger?.warn?.(
1357
+ {
1358
+ chatSessionId,
1359
+ sessionId,
1360
+ err: err2.message
1361
+ },
1362
+ "[agent-vercel] failed to persist assistant turn"
1363
+ );
1364
+ } finally {
1365
+ try {
1366
+ await data.close();
1367
+ } catch {
1368
+ }
1369
+ }
1370
+ }
1371
+ });
1372
+ return result.toDataStreamResponse({ data });
1373
+ } catch (e) {
1374
+ const message = e.message ?? "Internal error";
1375
+ persistedError = { code: "INTERNAL", message };
1376
+ logger?.error?.(
1377
+ { chatSessionId, sessionId, err: message },
1378
+ "[agent-vercel] route errored"
1379
+ );
1380
+ try {
1381
+ data.append({
1382
+ type: "error",
1383
+ value: { code: "INTERNAL", message }
1384
+ });
1385
+ } catch {
1386
+ }
1387
+ try {
1388
+ await data.close();
1389
+ } catch {
1390
+ }
1391
+ try {
1392
+ await persistence.appendMessage({
1393
+ sessionId: chatSessionId,
1394
+ role: "assistant",
1395
+ blocks: null,
1396
+ prose: null,
1397
+ errorJson: persistedError
1398
+ });
1399
+ } catch (err2) {
1400
+ logger?.warn?.(
1401
+ { chatSessionId, sessionId, err: err2.message },
1402
+ "[agent-vercel] failed to persist error turn"
1403
+ );
1404
+ }
1405
+ return jsonError2(500, "INTERNAL", message);
1406
+ } finally {
1407
+ if (hooks?.onSessionEnd) {
1408
+ const cause = req.signal.aborted ? "abort" : persistedError ? "error" : "complete";
1409
+ try {
1410
+ await hooks.onSessionEnd({
1411
+ scope: callerScope,
1412
+ sessionId,
1413
+ userId,
1414
+ cause
1415
+ });
1416
+ } catch (err2) {
1417
+ logger?.warn?.(
1418
+ {
1419
+ chatSessionId,
1420
+ sessionId,
1421
+ sessionStarted,
1422
+ err: err2.message
1423
+ },
1424
+ "[agent-vercel] onSessionEnd hook failed"
1425
+ );
1426
+ }
1427
+ }
1428
+ }
1429
+ }
1430
+ };
1431
+ }
1138
1432
 
1139
1433
  // src/server/routes/chat-sessions.ts
1140
1434
  var DEFAULT_TITLE = "New chat";
@@ -1495,6 +1789,15 @@ function configureAiChat(opts) {
1495
1789
  resolveNarratorId: opts.resolveNarratorId,
1496
1790
  hooks: opts.hooks
1497
1791
  });
1792
+ const agentVercel = createAgentVercelRoutes({
1793
+ persistence: opts.persistence,
1794
+ auth: opts.auth,
1795
+ scope: opts.scope,
1796
+ tools,
1797
+ vertex: opts.vertex,
1798
+ logger: opts.logger,
1799
+ hooks: opts.hooks
1800
+ });
1498
1801
  const chatSessions = createChatSessionsRoutes({
1499
1802
  persistence: opts.persistence,
1500
1803
  auth: opts.auth,
@@ -1511,7 +1814,7 @@ function configureAiChat(opts) {
1511
1814
  });
1512
1815
  return {
1513
1816
  runAgent: runAgentBound,
1514
- routes: { agentCustom, chatSessions, adminSettings },
1817
+ routes: { agentCustom, agentVercel, chatSessions, adminSettings },
1515
1818
  registries: { toolProviders: toolProviders2, chatInterfaces }
1516
1819
  };
1517
1820
  }