@lcas58/esmi-api-types 1.0.22 → 1.0.24

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,9 @@
1
1
  import type { AppRouteHandler } from "../../lib/types.js";
2
- import type { DiscoverExternalRoute, DiscoverRoute, GetOneRoute, ListRoute, SaveExternalRoute } from "./events.routes.js";
2
+ import type { ChatRoute, DiscoverExternalRoute, DiscoverRoute, GetOneRoute, ListRoute, SaveExternalRoute } from "./events.routes.js";
3
3
  export declare const list: AppRouteHandler<ListRoute>;
4
4
  export declare const getOne: AppRouteHandler<GetOneRoute>;
5
5
  export declare const discover: AppRouteHandler<DiscoverRoute>;
6
6
  export declare const discoverExternal: AppRouteHandler<DiscoverExternalRoute>;
7
7
  export declare const saveExternal: AppRouteHandler<SaveExternalRoute>;
8
+ export declare const chat: AppRouteHandler<ChatRoute>;
9
+ export declare const chatStream: (c: Parameters<AppRouteHandler<ChatRoute>>[0]) => Promise<Response>;
@@ -1,10 +1,13 @@
1
1
  import { and, eq, gte, ilike, inArray, isNotNull, lte } from "drizzle-orm";
2
+ import { streamSSE } from "hono/streaming";
2
3
  import * as HttpStatusCodes from "stoker/http-status-codes";
3
4
  import * as HttpStatusPhrases from "stoker/http-status-phrases";
4
- import { agentEventsToRaw, runExternalDiscoveryAgent } from "../../agent/runner.js";
5
- import { saveEvents, searchLocalEvents } from "../../agent/tools.js";
5
+ import { agentEventsToRaw, runChatAgent, runExternalDiscoveryAgent, runStreamingChatAgent } from "../../agent/runner.js";
6
+ import { getKnownExternalUrls, saveEvents, searchLocalEvents } from "../../agent/tools.js";
6
7
  import { createDb } from "../../db/index.js";
7
8
  import { event, location } from "../../db/schema/index.js";
9
+ import { buildCacheKey, buildSeenKey, getCachedDiscovery, markUrlsSeen, setCachedDiscovery } from "../../lib/discovery-cache.js";
10
+ import { chatRequestSchema } from "./events.routes.js";
8
11
  export const list = async (c) => {
9
12
  const { db } = createDb(c.env);
10
13
  const query = c.req.valid("query");
@@ -15,10 +18,12 @@ export const list = async (c) => {
15
18
  const state = query.state?.trim();
16
19
  // Time window (default: now → +7 days)
17
20
  const now = new Date();
18
- const from = query.from ? new Date(query.from) : now;
19
- const to = query.to
20
- ? new Date(query.to)
21
- : new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);
21
+ const from = query.from ?? now;
22
+ const to = query.to ?? new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);
23
+ // If `to` was date-only (midnight), extend to end of that day
24
+ if (query.to && to.getUTCHours() === 0 && to.getUTCMinutes() === 0 && to.getUTCSeconds() === 0) {
25
+ to.setUTCHours(23, 59, 59, 999);
26
+ }
22
27
  const whereConditions = [];
23
28
  if (sportId) {
24
29
  whereConditions.push(eq(event.sportId, sportId));
@@ -107,17 +112,59 @@ export const discover = async (c) => {
107
112
  });
108
113
  return c.json(events, HttpStatusCodes.OK);
109
114
  };
115
+ function filterByDateRange(events, from, to) {
116
+ if (!from && !to)
117
+ return events;
118
+ return events.filter((e) => {
119
+ const date = e.startsAt.split("T")[0];
120
+ if (from && date < from.split("T")[0])
121
+ return false;
122
+ if (to && date > to.split("T")[0])
123
+ return false;
124
+ return true;
125
+ });
126
+ }
110
127
  export const discoverExternal = async (c) => {
111
128
  const body = c.req.valid("json");
112
129
  const { db } = createDb(c.env);
113
- const previews = await runExternalDiscoveryAgent(c.env, db, {
130
+ const kv = c.env.DISCOVERY_CACHE;
131
+ const today = new Date().toISOString().split("T")[0];
132
+ const cacheKey = buildCacheKey(body.sportId, body.city, body.state, today);
133
+ const seenKey = buildSeenKey(body.sportId, body.city, body.state);
134
+ // Step 1: If not refresh, try cache first
135
+ if (!body.refresh) {
136
+ const cached = await getCachedDiscovery(kv, cacheKey);
137
+ if (cached !== null && cached.length > 0) {
138
+ const filtered = filterByDateRange(cached, body.from, body.to);
139
+ if (filtered.length > 0) {
140
+ console.log(`[discover] cache HIT for ${cacheKey} (${cached.length} total, ${filtered.length} in range)`);
141
+ return c.json(filtered, HttpStatusCodes.OK);
142
+ }
143
+ console.log(`[discover] cache HIT but 0 events in date range, falling through to agent`);
144
+ }
145
+ else {
146
+ console.log(`[discover] cache MISS for ${cacheKey}`);
147
+ }
148
+ }
149
+ // Step 2: Collect known URLs from DB for exclusion prompt
150
+ const dbUrls = await getKnownExternalUrls(db, body.sportId, body.city, body.state);
151
+ const knownUrls = dbUrls.length > 0 ? dbUrls : undefined;
152
+ // Step 3: Run agent web search
153
+ const results = await runExternalDiscoveryAgent(c.env, db, {
114
154
  sportId: body.sportId,
115
155
  city: body.city,
116
156
  state: body.state,
117
157
  from: body.from,
118
158
  to: body.to,
119
- });
120
- return c.json(previews, HttpStatusCodes.OK);
159
+ }, knownUrls);
160
+ // Step 4: Cache results (only if non-empty)
161
+ if (results.length > 0) {
162
+ await setCachedDiscovery(kv, cacheKey, results);
163
+ await markUrlsSeen(kv, seenKey, results.map((e) => e.url));
164
+ }
165
+ const filtered = filterByDateRange(results, body.from, body.to);
166
+ console.log(`[discover] agent returned ${results.length} events, returning ${filtered.length} in range for ${cacheKey}`);
167
+ return c.json(filtered, HttpStatusCodes.OK);
121
168
  };
122
169
  export const saveExternal = async (c) => {
123
170
  const { events: previews, city, state } = c.req.valid("json");
@@ -154,3 +201,45 @@ export const saveExternal = async (c) => {
154
201
  });
155
202
  return c.json(savedEvents, HttpStatusCodes.OK);
156
203
  };
204
+ export const chat = async (c) => {
205
+ const body = c.req.valid("json");
206
+ const { db } = createDb(c.env);
207
+ const result = await runChatAgent(c.env, db, {
208
+ message: body.message,
209
+ history: body.history,
210
+ city: body.city,
211
+ state: body.state,
212
+ });
213
+ return c.json(result, HttpStatusCodes.OK);
214
+ };
215
+ export const chatStream = async (c) => {
216
+ const rawBody = await c.req.json();
217
+ const parsed = chatRequestSchema.safeParse(rawBody);
218
+ if (!parsed.success) {
219
+ return c.json({ message: "Invalid request body" }, HttpStatusCodes.UNPROCESSABLE_ENTITY);
220
+ }
221
+ const user = c.get("user");
222
+ if (!user) {
223
+ return c.json({ message: "Unauthorized" }, HttpStatusCodes.UNAUTHORIZED);
224
+ }
225
+ const { db } = createDb(c.env);
226
+ const body = parsed.data;
227
+ return streamSSE(c, async (stream) => {
228
+ const writer = async (event) => {
229
+ await stream.writeSSE({ data: JSON.stringify(event) });
230
+ };
231
+ try {
232
+ await runStreamingChatAgent(c.env, db, {
233
+ message: body.message,
234
+ history: body.history,
235
+ city: body.city,
236
+ state: body.state,
237
+ }, writer);
238
+ }
239
+ catch (err) {
240
+ console.error("[chatStream] error:", err);
241
+ await stream.writeSSE({ data: JSON.stringify({ type: "error", message: "Stream failed" }) });
242
+ await stream.writeSSE({ data: JSON.stringify({ type: "done" }) });
243
+ }
244
+ });
245
+ };
@@ -128,6 +128,7 @@ declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../../shar
128
128
  state: string;
129
129
  from?: string | undefined;
130
130
  to?: string | undefined;
131
+ refresh?: boolean | undefined;
131
132
  };
132
133
  };
133
134
  output: {
@@ -179,6 +180,7 @@ declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../../shar
179
180
  state: string;
180
181
  from?: string | undefined;
181
182
  to?: string | undefined;
183
+ refresh?: boolean | undefined;
182
184
  };
183
185
  };
184
186
  output: {
@@ -198,6 +200,7 @@ declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../../shar
198
200
  state: string;
199
201
  from?: string | undefined;
200
202
  to?: string | undefined;
203
+ refresh?: boolean | undefined;
201
204
  };
202
205
  };
203
206
  output: {
@@ -213,6 +216,7 @@ declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../../shar
213
216
  state: string;
214
217
  from?: string | undefined;
215
218
  to?: string | undefined;
219
+ refresh?: boolean | undefined;
216
220
  };
217
221
  };
218
222
  output: {
@@ -325,5 +329,57 @@ declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../../shar
325
329
  status: 401;
326
330
  };
327
331
  };
332
+ } & {
333
+ "/events/chat": {
334
+ $post: {
335
+ input: {
336
+ json: {
337
+ message: string;
338
+ city?: string | undefined;
339
+ state?: string | undefined;
340
+ history?: {
341
+ content: string;
342
+ role: "user" | "assistant";
343
+ }[] | undefined;
344
+ };
345
+ };
346
+ output: {
347
+ message: string;
348
+ };
349
+ outputFormat: "text" | "json";
350
+ status: 401;
351
+ } | {
352
+ input: {
353
+ json: {
354
+ message: string;
355
+ city?: string | undefined;
356
+ state?: string | undefined;
357
+ history?: {
358
+ content: string;
359
+ role: "user" | "assistant";
360
+ }[] | undefined;
361
+ };
362
+ };
363
+ output: {
364
+ events: {
365
+ url: string;
366
+ id: string;
367
+ title: string;
368
+ sport: string;
369
+ startsAt: string;
370
+ timezone: string;
371
+ formattedAddress: string;
372
+ latitude: number | null;
373
+ longitude: number | null;
374
+ venueName: string;
375
+ description?: string | undefined;
376
+ endsAt?: string | undefined;
377
+ }[];
378
+ reply: string;
379
+ };
380
+ outputFormat: "text" | "json";
381
+ status: 200;
382
+ };
383
+ };
328
384
  }, "/">;
329
385
  export default router;
@@ -1,4 +1,5 @@
1
1
  import { createRouter } from "../../lib/create-app.js";
2
+ import { isAuth } from "../../middlewares/is-auth.js";
2
3
  import * as handlers from "./events.handlers.js";
3
4
  import * as routes from "./events.routes.js";
4
5
  const router = createRouter()
@@ -6,5 +7,8 @@ const router = createRouter()
6
7
  .openapi(routes.getOne, handlers.getOne)
7
8
  .openapi(routes.discover, handlers.discover)
8
9
  .openapi(routes.discoverExternal, handlers.discoverExternal)
9
- .openapi(routes.saveExternal, handlers.saveExternal);
10
+ .openapi(routes.saveExternal, handlers.saveExternal)
11
+ .openapi(routes.chat, handlers.chat);
12
+ // SSE streaming route (not in OpenAPI spec — SSE responses can't be modeled in JSON schema)
13
+ router.post("/events/chat/stream", isAuth(), handlers.chatStream);
10
14
  export default router;
@@ -594,10 +594,12 @@ export declare const discoverRequestSchema: z.ZodObject<{
594
594
  state: z.ZodString;
595
595
  from: z.ZodOptional<z.ZodString>;
596
596
  to: z.ZodOptional<z.ZodString>;
597
+ refresh: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
597
598
  }, "strip", z.ZodTypeAny, {
598
599
  sportId: string;
599
600
  city: string;
600
601
  state: string;
602
+ refresh: boolean;
601
603
  from?: string | undefined;
602
604
  to?: string | undefined;
603
605
  }, {
@@ -606,6 +608,7 @@ export declare const discoverRequestSchema: z.ZodObject<{
606
608
  state: string;
607
609
  from?: string | undefined;
608
610
  to?: string | undefined;
611
+ refresh?: boolean | undefined;
609
612
  }>;
610
613
  export declare const discover: {
611
614
  path: "/events/discover";
@@ -623,10 +626,12 @@ export declare const discover: {
623
626
  state: z.ZodString;
624
627
  from: z.ZodOptional<z.ZodString>;
625
628
  to: z.ZodOptional<z.ZodString>;
629
+ refresh: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
626
630
  }, "strip", z.ZodTypeAny, {
627
631
  sportId: string;
628
632
  city: string;
629
633
  state: string;
634
+ refresh: boolean;
630
635
  from?: string | undefined;
631
636
  to?: string | undefined;
632
637
  }, {
@@ -635,6 +640,7 @@ export declare const discover: {
635
640
  state: string;
636
641
  from?: string | undefined;
637
642
  to?: string | undefined;
643
+ refresh?: boolean | undefined;
638
644
  }>;
639
645
  };
640
646
  };
@@ -935,10 +941,12 @@ export declare const discoverExternal: {
935
941
  state: z.ZodString;
936
942
  from: z.ZodOptional<z.ZodString>;
937
943
  to: z.ZodOptional<z.ZodString>;
944
+ refresh: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
938
945
  }, "strip", z.ZodTypeAny, {
939
946
  sportId: string;
940
947
  city: string;
941
948
  state: string;
949
+ refresh: boolean;
942
950
  from?: string | undefined;
943
951
  to?: string | undefined;
944
952
  }, {
@@ -947,6 +955,7 @@ export declare const discoverExternal: {
947
955
  state: string;
948
956
  from?: string | undefined;
949
957
  to?: string | undefined;
958
+ refresh?: boolean | undefined;
950
959
  }>;
951
960
  };
952
961
  };
@@ -1390,8 +1399,262 @@ export declare const saveExternal: {
1390
1399
  } & {
1391
1400
  getRoutingPath(): "/events/save-external";
1392
1401
  };
1402
+ export declare const chatRequestSchema: z.ZodObject<{
1403
+ message: z.ZodString;
1404
+ history: z.ZodOptional<z.ZodArray<z.ZodObject<{
1405
+ role: z.ZodEnum<["user", "assistant"]>;
1406
+ content: z.ZodString;
1407
+ }, "strip", z.ZodTypeAny, {
1408
+ content: string;
1409
+ role: "user" | "assistant";
1410
+ }, {
1411
+ content: string;
1412
+ role: "user" | "assistant";
1413
+ }>, "many">>;
1414
+ city: z.ZodOptional<z.ZodString>;
1415
+ state: z.ZodOptional<z.ZodString>;
1416
+ }, "strip", z.ZodTypeAny, {
1417
+ message: string;
1418
+ city?: string | undefined;
1419
+ state?: string | undefined;
1420
+ history?: {
1421
+ content: string;
1422
+ role: "user" | "assistant";
1423
+ }[] | undefined;
1424
+ }, {
1425
+ message: string;
1426
+ city?: string | undefined;
1427
+ state?: string | undefined;
1428
+ history?: {
1429
+ content: string;
1430
+ role: "user" | "assistant";
1431
+ }[] | undefined;
1432
+ }>;
1433
+ export declare const chatResponseSchema: z.ZodObject<{
1434
+ reply: z.ZodString;
1435
+ events: z.ZodArray<z.ZodObject<{
1436
+ id: z.ZodString;
1437
+ title: z.ZodString;
1438
+ sport: z.ZodString;
1439
+ startsAt: z.ZodString;
1440
+ timezone: z.ZodString;
1441
+ url: z.ZodString;
1442
+ venueName: z.ZodString;
1443
+ formattedAddress: z.ZodString;
1444
+ latitude: z.ZodNullable<z.ZodNumber>;
1445
+ longitude: z.ZodNullable<z.ZodNumber>;
1446
+ description: z.ZodOptional<z.ZodString>;
1447
+ endsAt: z.ZodOptional<z.ZodString>;
1448
+ }, "strip", z.ZodTypeAny, {
1449
+ url: string;
1450
+ id: string;
1451
+ title: string;
1452
+ sport: string;
1453
+ startsAt: string;
1454
+ timezone: string;
1455
+ formattedAddress: string;
1456
+ latitude: number | null;
1457
+ longitude: number | null;
1458
+ venueName: string;
1459
+ description?: string | undefined;
1460
+ endsAt?: string | undefined;
1461
+ }, {
1462
+ url: string;
1463
+ id: string;
1464
+ title: string;
1465
+ sport: string;
1466
+ startsAt: string;
1467
+ timezone: string;
1468
+ formattedAddress: string;
1469
+ latitude: number | null;
1470
+ longitude: number | null;
1471
+ venueName: string;
1472
+ description?: string | undefined;
1473
+ endsAt?: string | undefined;
1474
+ }>, "many">;
1475
+ }, "strip", z.ZodTypeAny, {
1476
+ events: {
1477
+ url: string;
1478
+ id: string;
1479
+ title: string;
1480
+ sport: string;
1481
+ startsAt: string;
1482
+ timezone: string;
1483
+ formattedAddress: string;
1484
+ latitude: number | null;
1485
+ longitude: number | null;
1486
+ venueName: string;
1487
+ description?: string | undefined;
1488
+ endsAt?: string | undefined;
1489
+ }[];
1490
+ reply: string;
1491
+ }, {
1492
+ events: {
1493
+ url: string;
1494
+ id: string;
1495
+ title: string;
1496
+ sport: string;
1497
+ startsAt: string;
1498
+ timezone: string;
1499
+ formattedAddress: string;
1500
+ latitude: number | null;
1501
+ longitude: number | null;
1502
+ venueName: string;
1503
+ description?: string | undefined;
1504
+ endsAt?: string | undefined;
1505
+ }[];
1506
+ reply: string;
1507
+ }>;
1508
+ export declare const chat: {
1509
+ path: "/events/chat";
1510
+ method: "post";
1511
+ tags: string[];
1512
+ middleware: [import("hono").MiddlewareHandler];
1513
+ request: {
1514
+ body: {
1515
+ required: boolean;
1516
+ content: {
1517
+ "application/json": {
1518
+ schema: z.ZodObject<{
1519
+ message: z.ZodString;
1520
+ history: z.ZodOptional<z.ZodArray<z.ZodObject<{
1521
+ role: z.ZodEnum<["user", "assistant"]>;
1522
+ content: z.ZodString;
1523
+ }, "strip", z.ZodTypeAny, {
1524
+ content: string;
1525
+ role: "user" | "assistant";
1526
+ }, {
1527
+ content: string;
1528
+ role: "user" | "assistant";
1529
+ }>, "many">>;
1530
+ city: z.ZodOptional<z.ZodString>;
1531
+ state: z.ZodOptional<z.ZodString>;
1532
+ }, "strip", z.ZodTypeAny, {
1533
+ message: string;
1534
+ city?: string | undefined;
1535
+ state?: string | undefined;
1536
+ history?: {
1537
+ content: string;
1538
+ role: "user" | "assistant";
1539
+ }[] | undefined;
1540
+ }, {
1541
+ message: string;
1542
+ city?: string | undefined;
1543
+ state?: string | undefined;
1544
+ history?: {
1545
+ content: string;
1546
+ role: "user" | "assistant";
1547
+ }[] | undefined;
1548
+ }>;
1549
+ };
1550
+ };
1551
+ description: string;
1552
+ };
1553
+ };
1554
+ responses: {
1555
+ 200: {
1556
+ content: {
1557
+ "application/json": {
1558
+ schema: z.ZodObject<{
1559
+ reply: z.ZodString;
1560
+ events: z.ZodArray<z.ZodObject<{
1561
+ id: z.ZodString;
1562
+ title: z.ZodString;
1563
+ sport: z.ZodString;
1564
+ startsAt: z.ZodString;
1565
+ timezone: z.ZodString;
1566
+ url: z.ZodString;
1567
+ venueName: z.ZodString;
1568
+ formattedAddress: z.ZodString;
1569
+ latitude: z.ZodNullable<z.ZodNumber>;
1570
+ longitude: z.ZodNullable<z.ZodNumber>;
1571
+ description: z.ZodOptional<z.ZodString>;
1572
+ endsAt: z.ZodOptional<z.ZodString>;
1573
+ }, "strip", z.ZodTypeAny, {
1574
+ url: string;
1575
+ id: string;
1576
+ title: string;
1577
+ sport: string;
1578
+ startsAt: string;
1579
+ timezone: string;
1580
+ formattedAddress: string;
1581
+ latitude: number | null;
1582
+ longitude: number | null;
1583
+ venueName: string;
1584
+ description?: string | undefined;
1585
+ endsAt?: string | undefined;
1586
+ }, {
1587
+ url: string;
1588
+ id: string;
1589
+ title: string;
1590
+ sport: string;
1591
+ startsAt: string;
1592
+ timezone: string;
1593
+ formattedAddress: string;
1594
+ latitude: number | null;
1595
+ longitude: number | null;
1596
+ venueName: string;
1597
+ description?: string | undefined;
1598
+ endsAt?: string | undefined;
1599
+ }>, "many">;
1600
+ }, "strip", z.ZodTypeAny, {
1601
+ events: {
1602
+ url: string;
1603
+ id: string;
1604
+ title: string;
1605
+ sport: string;
1606
+ startsAt: string;
1607
+ timezone: string;
1608
+ formattedAddress: string;
1609
+ latitude: number | null;
1610
+ longitude: number | null;
1611
+ venueName: string;
1612
+ description?: string | undefined;
1613
+ endsAt?: string | undefined;
1614
+ }[];
1615
+ reply: string;
1616
+ }, {
1617
+ events: {
1618
+ url: string;
1619
+ id: string;
1620
+ title: string;
1621
+ sport: string;
1622
+ startsAt: string;
1623
+ timezone: string;
1624
+ formattedAddress: string;
1625
+ latitude: number | null;
1626
+ longitude: number | null;
1627
+ venueName: string;
1628
+ description?: string | undefined;
1629
+ endsAt?: string | undefined;
1630
+ }[];
1631
+ reply: string;
1632
+ }>;
1633
+ };
1634
+ };
1635
+ description: string;
1636
+ };
1637
+ 401: {
1638
+ content: {
1639
+ "application/json": {
1640
+ schema: z.ZodObject<{
1641
+ message: z.ZodString;
1642
+ }, "strip", z.ZodTypeAny, {
1643
+ message: string;
1644
+ }, {
1645
+ message: string;
1646
+ }>;
1647
+ };
1648
+ };
1649
+ description: string;
1650
+ };
1651
+ };
1652
+ } & {
1653
+ getRoutingPath(): "/events/chat";
1654
+ };
1393
1655
  export type ListRoute = typeof list;
1394
1656
  export type GetOneRoute = typeof getOne;
1395
1657
  export type DiscoverRoute = typeof discover;
1396
1658
  export type DiscoverExternalRoute = typeof discoverExternal;
1397
1659
  export type SaveExternalRoute = typeof saveExternal;
1660
+ export type ChatRoute = typeof chat;
@@ -35,6 +35,7 @@ export const discoverRequestSchema = z.object({
35
35
  state: z.string().min(1),
36
36
  from: z.string().optional(),
37
37
  to: z.string().optional(),
38
+ refresh: z.boolean().optional().default(false),
38
39
  });
39
40
  export const discover = createRoute({
40
41
  path: "/events/discover",
@@ -79,3 +80,30 @@ export const saveExternal = createRoute({
79
80
  [HttpStatusCodes.UNAUTHORIZED]: jsonContent(unauthorizedSchema, "Unauthorized"),
80
81
  },
81
82
  });
83
+ const chatMessageSchema = z.object({
84
+ role: z.enum(["user", "assistant"]),
85
+ content: z.string(),
86
+ });
87
+ export const chatRequestSchema = z.object({
88
+ message: z.string().min(1),
89
+ history: z.array(chatMessageSchema).optional(),
90
+ city: z.string().optional(),
91
+ state: z.string().optional(),
92
+ });
93
+ export const chatResponseSchema = z.object({
94
+ reply: z.string(),
95
+ events: z.array(externalEventPreviewSchema),
96
+ });
97
+ export const chat = createRoute({
98
+ path: "/events/chat",
99
+ method: "post",
100
+ tags: ["Events"],
101
+ middleware: [isAuth()],
102
+ request: {
103
+ body: jsonContentRequired(chatRequestSchema, "Chat message"),
104
+ },
105
+ responses: {
106
+ [HttpStatusCodes.OK]: jsonContent(chatResponseSchema, "Chat response with friendly text and events"),
107
+ [HttpStatusCodes.UNAUTHORIZED]: jsonContent(unauthorizedSchema, "Unauthorized"),
108
+ },
109
+ });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lcas58/esmi-api-types",
3
3
  "type": "module",
4
- "version": "1.0.22",
4
+ "version": "1.0.24",
5
5
  "license": "MIT",
6
6
  "exports": {
7
7
  ".": {