@sentry/junior 0.97.1 → 0.99.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.
Files changed (59) hide show
  1. package/dist/{agent-hooks-XSUIVRQS.js → agent-hooks-OSW6C3CJ.js} +2 -2
  2. package/dist/api/conversations/detail.d.ts +1 -1
  3. package/dist/api/conversations/detail.query.d.ts +1 -1
  4. package/dist/api/conversations/list.d.ts +7 -2
  5. package/dist/api/conversations/list.query.d.ts +9 -3
  6. package/dist/api/conversations/projection.d.ts +0 -1
  7. package/dist/api/conversations/schema.d.ts +31 -8
  8. package/dist/api/people/schema.d.ts +0 -11
  9. package/dist/api/people/shared.d.ts +2 -4
  10. package/dist/api/schema.d.ts +4 -1
  11. package/dist/api/schema.js +5 -3
  12. package/dist/api-reference.d.ts +2 -2
  13. package/dist/api.js +28 -13
  14. package/dist/app.js +50 -37
  15. package/dist/chat/conversations/search.d.ts +24 -0
  16. package/dist/chat/conversations/sql/search.d.ts +4 -0
  17. package/dist/chat/db.d.ts +3 -0
  18. package/dist/chat/runtime/report-progress.d.ts +3 -0
  19. package/dist/chat/runtime/slack-resume.d.ts +2 -0
  20. package/dist/chat/services/context-compaction.d.ts +1 -0
  21. package/dist/chat/slack/assistant-thread/status-scheduler.d.ts +4 -3
  22. package/dist/chat/slack/outbound.d.ts +6 -0
  23. package/dist/chat/slack/tools/conversation-search.d.ts +71 -0
  24. package/dist/chat/state/turn-session.d.ts +2 -0
  25. package/dist/chat/tool-support/zod-tool.d.ts +1 -1
  26. package/dist/chunk-6DTVCPLO.js +146 -0
  27. package/dist/{chunk-VFH4ZKZT.js → chunk-CRQVIHDI.js} +1 -3
  28. package/dist/{chunk-6U26PYI5.js → chunk-CV22LUIV.js} +7 -17
  29. package/dist/{chunk-GUAP3H7O.js → chunk-DHHU2WSG.js} +2 -2
  30. package/dist/{chunk-T533JLM3.js → chunk-ER45IV77.js} +8 -6
  31. package/dist/{chunk-LUAE4MGW.js → chunk-EUZ44ROE.js} +21 -4
  32. package/dist/{chunk-5HLDPVYS.js → chunk-FTTFV6DC.js} +1 -1
  33. package/dist/{chunk-3F4OPKGF.js → chunk-IO65E4ZD.js} +2 -2
  34. package/dist/{chunk-ON6YKIQ7.js → chunk-KFUSLFLL.js} +21 -15
  35. package/dist/{chunk-FBHZJFHI.js → chunk-NJEDJFK4.js} +1 -1
  36. package/dist/{chunk-35BNLDOJ.js → chunk-OGHXZ4KQ.js} +134 -57
  37. package/dist/{chunk-WJOSZOON.js → chunk-OL6XQ23W.js} +11 -150
  38. package/dist/{chunk-XIRPQQVE.js → chunk-PYK7R5A7.js} +312 -175
  39. package/dist/{chunk-UAMKJPDF.js → chunk-T55RBE4Z.js} +4 -0
  40. package/dist/{chunk-WGXMTFNU.js → chunk-WJ7STXT6.js} +5 -3
  41. package/dist/{chunk-AUUCAFDE.js → chunk-ZZUBLPXD.js} +134 -11
  42. package/dist/cli/chat.js +11 -10
  43. package/dist/cli/plugins.js +2 -2
  44. package/dist/cli/upgrade.js +9 -7
  45. package/dist/{db-BWXYIKFQ.js → db-GFSCDAHS.js} +3 -1
  46. package/dist/detail-Q4IVDNGS.js +67 -0
  47. package/dist/{legacy-import-3NQJVGQL.js → legacy-import-6WWXMALY.js} +2 -2
  48. package/dist/{list-UXJI5Q5X.js → list-A3F5JDYV.js} +7 -5
  49. package/dist/{list-A3WFRIYX.js → list-M5BRWW3D.js} +5 -6
  50. package/dist/{plugin-conversations-DDNGC35A.js → plugin-conversations-PDCQWU3O.js} +3 -3
  51. package/dist/{profile-4RYDXWTF.js → profile-UEIRSVT3.js} +5 -5
  52. package/dist/{runner-JALSYH2P.js → runner-267ZRLZD.js} +8 -7
  53. package/dist/{stats-XKXH3PTY.js → stats-L62E4O4U.js} +7 -17
  54. package/dist/{subagent-TZ55XY37.js → subagent-UN3MP6LV.js} +6 -6
  55. package/migrations/0002_conversation_message_search.sql +1 -0
  56. package/migrations/meta/0002_snapshot.json +987 -0
  57. package/migrations/meta/_journal.json +7 -0
  58. package/package.json +6 -6
  59. package/dist/detail-GA6NXWQJ.js +0 -43
@@ -15,11 +15,11 @@ import {
15
15
 
16
16
  // src/chat/conversations/sql/store.ts
17
17
  import { randomUUID as randomUUID2 } from "crypto";
18
- import { and as and2, asc, desc, eq as eq2, isNull, sql as sql4 } from "drizzle-orm";
18
+ import { and as and2, asc, desc, eq as eq2, isNull, sql as sql5 } from "drizzle-orm";
19
19
 
20
20
  // src/chat/identities/sql.ts
21
21
  import { randomUUID } from "crypto";
22
- import { and, eq, sql as sql3 } from "drizzle-orm";
22
+ import { and, eq, sql as sql4 } from "drizzle-orm";
23
23
 
24
24
  // src/db/schema/agent-steps.ts
25
25
  import {
@@ -236,6 +236,7 @@ var juniorAgentSteps = pgTable5(
236
236
  );
237
237
 
238
238
  // src/db/schema/conversation-messages.ts
239
+ import { sql as sql3 } from "drizzle-orm";
239
240
  import { index as index5, jsonb as jsonb5, pgTable as pgTable6, primaryKey as primaryKey2, text as text6 } from "drizzle-orm/pg-core";
240
241
  var juniorConversationMessages = pgTable6(
241
242
  "junior_conversation_messages",
@@ -256,6 +257,10 @@ var juniorConversationMessages = pgTable6(
256
257
  index5("junior_conversation_messages_activity_idx").on(
257
258
  table.conversationId,
258
259
  table.createdAt
260
+ ),
261
+ index5("junior_conversation_messages_search_idx").using(
262
+ "gin",
263
+ sql3`to_tsvector('english', ${table.text})`
259
264
  )
260
265
  ]
261
266
  );
@@ -288,8 +293,8 @@ async function upsertUser(executor, args) {
288
293
  }).onConflictDoUpdate({
289
294
  target: juniorUsers.primaryEmailNormalized,
290
295
  set: {
291
- displayName: sql3`coalesce(${juniorUsers.displayName}, excluded.display_name)`,
292
- updatedAt: sql3`excluded.updated_at`
296
+ displayName: sql4`coalesce(${juniorUsers.displayName}, excluded.display_name)`,
297
+ updatedAt: sql4`excluded.updated_at`
293
298
  }
294
299
  }).returning({ id: juniorUsers.id });
295
300
  const id = rows[0]?.id;
@@ -350,16 +355,16 @@ async function upsertIdentity(executor, identity, nowMs = Date.now()) {
350
355
  juniorIdentities.providerSubjectId
351
356
  ],
352
357
  set: {
353
- kind: sql3`excluded.kind`,
354
- userId: sql3`coalesce(${juniorIdentities.userId}, excluded.user_id)`,
355
- displayName: sql3`coalesce(${juniorIdentities.displayName}, excluded.display_name)`,
356
- handle: sql3`coalesce(${juniorIdentities.handle}, excluded.handle)`,
357
- email: sql3`case when ${juniorIdentities.emailVerified} then coalesce(${juniorIdentities.email}, excluded.email) when excluded.email_verified then excluded.email else coalesce(${juniorIdentities.email}, excluded.email) end`,
358
- emailNormalized: sql3`case when ${juniorIdentities.emailVerified} then coalesce(${juniorIdentities.emailNormalized}, excluded.email_normalized) when excluded.email_verified then excluded.email_normalized else coalesce(${juniorIdentities.emailNormalized}, excluded.email_normalized) end`,
359
- emailVerified: sql3`${juniorIdentities.emailVerified} OR excluded.email_verified`,
360
- avatarUrl: sql3`coalesce(${juniorIdentities.avatarUrl}, excluded.avatar_url)`,
361
- metadata: sql3`coalesce(${juniorIdentities.metadata}, excluded.metadata_json)`,
362
- updatedAt: sql3`excluded.updated_at`
358
+ kind: sql4`excluded.kind`,
359
+ userId: sql4`coalesce(${juniorIdentities.userId}, excluded.user_id)`,
360
+ displayName: sql4`coalesce(${juniorIdentities.displayName}, excluded.display_name)`,
361
+ handle: sql4`coalesce(${juniorIdentities.handle}, excluded.handle)`,
362
+ email: sql4`case when ${juniorIdentities.emailVerified} then coalesce(${juniorIdentities.email}, excluded.email) when excluded.email_verified then excluded.email else coalesce(${juniorIdentities.email}, excluded.email) end`,
363
+ emailNormalized: sql4`case when ${juniorIdentities.emailVerified} then coalesce(${juniorIdentities.emailNormalized}, excluded.email_normalized) when excluded.email_verified then excluded.email_normalized else coalesce(${juniorIdentities.emailNormalized}, excluded.email_normalized) end`,
364
+ emailVerified: sql4`${juniorIdentities.emailVerified} OR excluded.email_verified`,
365
+ avatarUrl: sql4`coalesce(${juniorIdentities.avatarUrl}, excluded.avatar_url)`,
366
+ metadata: sql4`coalesce(${juniorIdentities.metadata}, excluded.metadata_json)`,
367
+ updatedAt: sql4`excluded.updated_at`
363
368
  }
364
369
  }).returning({
365
370
  id: juniorIdentities.id,
@@ -763,7 +768,7 @@ var SqlStore = class {
763
768
  }).onConflictDoUpdate({
764
769
  target: juniorConversations.conversationId,
765
770
  set: {
766
- parentConversationId: sql4`coalesce(${juniorConversations.parentConversationId}, excluded.parent_conversation_id)`
771
+ parentConversationId: sql5`coalesce(${juniorConversations.parentConversationId}, excluded.parent_conversation_id)`
767
772
  }
768
773
  });
769
774
  }
@@ -890,9 +895,9 @@ var SqlStore = class {
890
895
  /** Upsert the conversation row while preserving previously discovered nullable metadata fields. */
891
896
  async upsertConversation(args) {
892
897
  const { conversation } = args;
893
- const incomingExecutionVersion = sql4`coalesce(excluded.execution_updated_at, excluded.updated_at)`;
894
- const currentExecutionVersion = sql4`coalesce(${juniorConversations.executionUpdatedAt}, ${juniorConversations.updatedAt})`;
895
- const incomingExecutionIsFresh = sql4`${incomingExecutionVersion} >= ${currentExecutionVersion}`;
898
+ const incomingExecutionVersion = sql5`coalesce(excluded.execution_updated_at, excluded.updated_at)`;
899
+ const currentExecutionVersion = sql5`coalesce(${juniorConversations.executionUpdatedAt}, ${juniorConversations.updatedAt})`;
900
+ const incomingExecutionIsFresh = sql5`${incomingExecutionVersion} >= ${currentExecutionVersion}`;
896
901
  const destinationId = await this.upsertDestination(
897
902
  destinationUpsertFromDestination({
898
903
  channelName: conversation.channelName,
@@ -934,24 +939,24 @@ var SqlStore = class {
934
939
  }).onConflictDoUpdate({
935
940
  target: juniorConversations.conversationId,
936
941
  set: {
937
- source: sql4`coalesce(excluded.source, ${juniorConversations.source})`,
938
- originType: sql4`coalesce(excluded.origin_type, ${juniorConversations.originType})`,
939
- originId: sql4`coalesce(excluded.origin_id, ${juniorConversations.originId})`,
940
- originRunId: sql4`coalesce(excluded.origin_run_id, ${juniorConversations.originRunId})`,
941
- destinationId: sql4`coalesce(excluded.destination_id, ${juniorConversations.destinationId})`,
942
- actorIdentityId: sql4`coalesce(excluded.actor_identity_id, ${juniorConversations.actorIdentityId})`,
943
- creatorIdentityId: sql4`coalesce(excluded.creator_identity_id, ${juniorConversations.creatorIdentityId})`,
944
- credentialSubjectIdentityId: sql4`coalesce(excluded.credential_subject_identity_id, ${juniorConversations.credentialSubjectIdentityId})`,
945
- channelName: sql4`coalesce(excluded.channel_name, ${juniorConversations.channelName})`,
946
- title: sql4`coalesce(excluded.title, ${juniorConversations.title})`,
947
- createdAt: sql4`least(${juniorConversations.createdAt}, excluded.created_at)`,
948
- lastActivityAt: sql4`greatest(${juniorConversations.lastActivityAt}, excluded.last_activity_at)`,
949
- updatedAt: sql4`greatest(${juniorConversations.updatedAt}, excluded.updated_at)`,
950
- executionUpdatedAt: sql4`case when ${incomingExecutionIsFresh} then excluded.execution_updated_at else ${juniorConversations.executionUpdatedAt} end`,
951
- executionStatus: sql4`case when ${incomingExecutionIsFresh} then excluded.execution_status else ${juniorConversations.executionStatus} end`,
952
- runId: sql4`case when ${incomingExecutionIsFresh} then excluded.run_id else ${juniorConversations.runId} end`,
953
- lastCheckpointAt: sql4`case when ${incomingExecutionIsFresh} then coalesce(excluded.last_checkpoint_at, ${juniorConversations.lastCheckpointAt}) else ${juniorConversations.lastCheckpointAt} end`,
954
- lastEnqueuedAt: sql4`case when ${incomingExecutionIsFresh} then coalesce(excluded.last_enqueued_at, ${juniorConversations.lastEnqueuedAt}) else ${juniorConversations.lastEnqueuedAt} end`
942
+ source: sql5`coalesce(excluded.source, ${juniorConversations.source})`,
943
+ originType: sql5`coalesce(excluded.origin_type, ${juniorConversations.originType})`,
944
+ originId: sql5`coalesce(excluded.origin_id, ${juniorConversations.originId})`,
945
+ originRunId: sql5`coalesce(excluded.origin_run_id, ${juniorConversations.originRunId})`,
946
+ destinationId: sql5`coalesce(excluded.destination_id, ${juniorConversations.destinationId})`,
947
+ actorIdentityId: sql5`coalesce(excluded.actor_identity_id, ${juniorConversations.actorIdentityId})`,
948
+ creatorIdentityId: sql5`coalesce(excluded.creator_identity_id, ${juniorConversations.creatorIdentityId})`,
949
+ credentialSubjectIdentityId: sql5`coalesce(excluded.credential_subject_identity_id, ${juniorConversations.credentialSubjectIdentityId})`,
950
+ channelName: sql5`coalesce(excluded.channel_name, ${juniorConversations.channelName})`,
951
+ title: sql5`coalesce(excluded.title, ${juniorConversations.title})`,
952
+ createdAt: sql5`least(${juniorConversations.createdAt}, excluded.created_at)`,
953
+ lastActivityAt: sql5`greatest(${juniorConversations.lastActivityAt}, excluded.last_activity_at)`,
954
+ updatedAt: sql5`greatest(${juniorConversations.updatedAt}, excluded.updated_at)`,
955
+ executionUpdatedAt: sql5`case when ${incomingExecutionIsFresh} then excluded.execution_updated_at else ${juniorConversations.executionUpdatedAt} end`,
956
+ executionStatus: sql5`case when ${incomingExecutionIsFresh} then excluded.execution_status else ${juniorConversations.executionStatus} end`,
957
+ runId: sql5`case when ${incomingExecutionIsFresh} then excluded.run_id else ${juniorConversations.runId} end`,
958
+ lastCheckpointAt: sql5`case when ${incomingExecutionIsFresh} then coalesce(excluded.last_checkpoint_at, ${juniorConversations.lastCheckpointAt}) else ${juniorConversations.lastCheckpointAt} end`,
959
+ lastEnqueuedAt: sql5`case when ${incomingExecutionIsFresh} then coalesce(excluded.last_enqueued_at, ${juniorConversations.lastEnqueuedAt}) else ${juniorConversations.lastEnqueuedAt} end`
955
960
  }
956
961
  });
957
962
  }
@@ -959,7 +964,7 @@ var SqlStore = class {
959
964
  if (!destination) {
960
965
  return void 0;
961
966
  }
962
- const visibilityUpdate = destination.refreshVisibility ? sql4`excluded.visibility` : juniorDestinations.visibility;
967
+ const visibilityUpdate = destination.refreshVisibility ? sql5`excluded.visibility` : juniorDestinations.visibility;
963
968
  const rows = await this.executor.db().insert(juniorDestinations).values({
964
969
  id: randomUUID2(),
965
970
  provider: destination.provider,
@@ -979,14 +984,14 @@ var SqlStore = class {
979
984
  juniorDestinations.providerDestinationId
980
985
  ],
981
986
  set: {
982
- kind: sql4`excluded.kind`,
983
- displayName: sql4`coalesce(excluded.display_name, ${juniorDestinations.displayName})`,
987
+ kind: sql5`excluded.kind`,
988
+ displayName: sql5`coalesce(excluded.display_name, ${juniorDestinations.displayName})`,
984
989
  // Signal-less writes insert as private but must not clobber an
985
990
  // existing public/private value. Live source signals refresh this
986
991
  // field so converted channels converge on the next message.
987
992
  visibility: visibilityUpdate,
988
- metadata: sql4`coalesce(excluded.metadata_json, ${juniorDestinations.metadata})`,
989
- updatedAt: sql4`excluded.updated_at`
993
+ metadata: sql5`coalesce(excluded.metadata_json, ${juniorDestinations.metadata})`,
994
+ updatedAt: sql5`excluded.updated_at`
990
995
  }
991
996
  }).returning({ id: juniorDestinations.id });
992
997
  return rows[0]?.id;
@@ -997,7 +1002,7 @@ function createSqlStore(executor) {
997
1002
  }
998
1003
 
999
1004
  // src/chat/conversations/sql/history.ts
1000
- import { and as and3, asc as asc2, eq as eq3, sql as sql6 } from "drizzle-orm";
1005
+ import { and as and3, asc as asc2, eq as eq3, sql as sql7 } from "drizzle-orm";
1001
1006
 
1002
1007
  // src/chat/conversations/history.ts
1003
1008
  import { z as z3 } from "zod";
@@ -1461,7 +1466,7 @@ var newAgentStepSchema = z3.object({
1461
1466
  }).strict();
1462
1467
 
1463
1468
  // src/chat/conversations/sql/conversation-row.ts
1464
- import { sql as sql5 } from "drizzle-orm";
1469
+ import { sql as sql6 } from "drizzle-orm";
1465
1470
  async function ensureConversationRow(executor, conversationId, atMs) {
1466
1471
  const at = new Date(atMs);
1467
1472
  await executor.db().insert(juniorConversations).values({
@@ -1473,8 +1478,8 @@ async function ensureConversationRow(executor, conversationId, atMs) {
1473
1478
  }).onConflictDoUpdate({
1474
1479
  target: juniorConversations.conversationId,
1475
1480
  set: {
1476
- lastActivityAt: sql5`greatest(${juniorConversations.lastActivityAt}, excluded.last_activity_at)`,
1477
- updatedAt: sql5`greatest(${juniorConversations.updatedAt}, excluded.updated_at)`,
1481
+ lastActivityAt: sql6`greatest(${juniorConversations.lastActivityAt}, excluded.last_activity_at)`,
1482
+ updatedAt: sql6`greatest(${juniorConversations.updatedAt}, excluded.updated_at)`,
1478
1483
  transcriptPurgedAt: null
1479
1484
  }
1480
1485
  });
@@ -1585,8 +1590,8 @@ var SqlAgentStepStore = class {
1585
1590
  /** Read the next `seq` and current highest epoch for one conversation. */
1586
1591
  async readCursor(conversationId) {
1587
1592
  const rows = await this.executor.db().select({
1588
- maxSeq: sql6`max(${juniorAgentSteps.seq})`,
1589
- maxEpoch: sql6`max(${juniorAgentSteps.contextEpoch})`
1593
+ maxSeq: sql7`max(${juniorAgentSteps.seq})`,
1594
+ maxEpoch: sql7`max(${juniorAgentSteps.contextEpoch})`
1590
1595
  }).from(juniorAgentSteps).where(eq3(juniorAgentSteps.conversationId, conversationId));
1591
1596
  const maxSeq = rows[0]?.maxSeq;
1592
1597
  const maxEpoch = rows[0]?.maxEpoch;
@@ -1601,7 +1606,7 @@ function createSqlAgentStepStore(executor) {
1601
1606
  }
1602
1607
 
1603
1608
  // src/chat/conversations/sql/messages.ts
1604
- import { and as and4, asc as asc3, eq as eq4, isNull as isNull2, sql as sql7 } from "drizzle-orm";
1609
+ import { and as and4, asc as asc3, eq as eq4, isNull as isNull2, sql as sql8 } from "drizzle-orm";
1605
1610
  function messageFromRow(row) {
1606
1611
  return {
1607
1612
  conversationId: row.conversationId,
@@ -1649,14 +1654,14 @@ var SqlConversationMessageStore = class {
1649
1654
  juniorConversationMessages.messageId
1650
1655
  ],
1651
1656
  set: {
1652
- meta: sql7`nullif(coalesce(${juniorConversationMessages.meta}, '{}'::jsonb) || coalesce(excluded.meta, '{}'::jsonb), '{}'::jsonb)`
1657
+ meta: sql8`nullif(coalesce(${juniorConversationMessages.meta}, '{}'::jsonb) || coalesce(excluded.meta, '{}'::jsonb), '{}'::jsonb)`
1653
1658
  }
1654
1659
  });
1655
1660
  });
1656
1661
  }
1657
1662
  async markReplied(conversationId, messageId, repliedAtMs) {
1658
1663
  await this.executor.db().update(juniorConversationMessages).set({
1659
- repliedAt: sql7`coalesce(${juniorConversationMessages.repliedAt}, ${new Date(repliedAtMs)})`
1664
+ repliedAt: sql8`coalesce(${juniorConversationMessages.repliedAt}, ${new Date(repliedAtMs)})`
1660
1665
  }).where(
1661
1666
  and4(
1662
1667
  eq4(juniorConversationMessages.conversationId, conversationId),
@@ -1678,6 +1683,72 @@ function createSqlConversationMessageStore(executor) {
1678
1683
  return new SqlConversationMessageStore(executor);
1679
1684
  }
1680
1685
 
1686
+ // src/chat/conversations/sql/search.ts
1687
+ import { and as and5, desc as desc2, eq as eq5, inArray, isNull as isNull3, ne, sql as sql9 } from "drizzle-orm";
1688
+ var SqlConversationSearchStore = class {
1689
+ constructor(executor) {
1690
+ this.executor = executor;
1691
+ }
1692
+ executor;
1693
+ async search(args) {
1694
+ const db = this.executor.db();
1695
+ const tsquery = sql9`websearch_to_tsquery('english', ${args.query})`;
1696
+ const rank = sql9`ts_rank_cd(to_tsvector('english', ${juniorConversationMessages.text}), ${tsquery})`;
1697
+ const excerpt = sql9`ts_headline('english', ${juniorConversationMessages.text}, ${tsquery}, 'MaxFragments=2, MinWords=8, MaxWords=40, FragmentDelimiter=" … ", StartSel=**, StopSel=**')`;
1698
+ const role = sql9`${juniorConversationMessages.role}`;
1699
+ const bestPerConversation = db.selectDistinctOn([juniorConversations.conversationId], {
1700
+ conversationId: juniorConversations.conversationId,
1701
+ excerpt: excerpt.as("excerpt"),
1702
+ lastActivityAt: juniorConversations.lastActivityAt,
1703
+ messageCreatedAt: juniorConversationMessages.createdAt,
1704
+ messageId: juniorConversationMessages.messageId,
1705
+ providerDestinationId: juniorDestinations.providerDestinationId,
1706
+ rank: rank.as("rank"),
1707
+ role: role.as("role")
1708
+ }).from(juniorConversationMessages).innerJoin(
1709
+ juniorConversations,
1710
+ eq5(
1711
+ juniorConversations.conversationId,
1712
+ juniorConversationMessages.conversationId
1713
+ )
1714
+ ).innerJoin(
1715
+ juniorDestinations,
1716
+ eq5(juniorDestinations.id, juniorConversations.destinationId)
1717
+ ).where(
1718
+ and5(
1719
+ eq5(juniorConversations.source, "slack"),
1720
+ isNull3(juniorConversations.parentConversationId),
1721
+ isNull3(juniorConversations.transcriptPurgedAt),
1722
+ ne(juniorConversations.conversationId, args.currentConversationId),
1723
+ eq5(juniorDestinations.provider, args.scope.provider),
1724
+ eq5(juniorDestinations.providerTenantId, args.scope.providerTenantId),
1725
+ eq5(juniorDestinations.visibility, "public"),
1726
+ inArray(juniorConversationMessages.role, ["user", "assistant"]),
1727
+ sql9`to_tsvector('english', ${juniorConversationMessages.text}) @@ ${tsquery}`
1728
+ )
1729
+ ).orderBy(
1730
+ juniorConversations.conversationId,
1731
+ desc2(rank),
1732
+ desc2(juniorConversationMessages.createdAt)
1733
+ ).as("best_conversation_matches");
1734
+ const rows = await db.select().from(bestPerConversation).orderBy(
1735
+ desc2(bestPerConversation.rank),
1736
+ desc2(bestPerConversation.lastActivityAt)
1737
+ ).limit(args.limit);
1738
+ return rows.map((row) => ({
1739
+ conversationId: row.conversationId,
1740
+ excerpt: row.excerpt,
1741
+ messageCreatedAtMs: row.messageCreatedAt.getTime(),
1742
+ messageId: row.messageId,
1743
+ providerDestinationId: row.providerDestinationId,
1744
+ role: row.role
1745
+ }));
1746
+ }
1747
+ };
1748
+ function createSqlConversationSearchStore(executor) {
1749
+ return new SqlConversationSearchStore(executor);
1750
+ }
1751
+
1681
1752
  // src/db/neon.ts
1682
1753
  import { AsyncLocalStorage } from "async_hooks";
1683
1754
  import {
@@ -1933,24 +2004,25 @@ function createDb(args) {
1933
2004
  });
1934
2005
  }
1935
2006
  function getSqlExecutor() {
1936
- const { sql: sql8 } = getChatConfig();
1937
- if (current?.databaseUrl !== sql8.databaseUrl || current.driver !== sql8.driver) {
2007
+ const { sql: sql10 } = getChatConfig();
2008
+ if (current?.databaseUrl !== sql10.databaseUrl || current.driver !== sql10.driver) {
1938
2009
  if (current) {
1939
2010
  const previous = current;
1940
2011
  current = void 0;
1941
2012
  void previous.db.close().catch(() => void 0);
1942
2013
  }
1943
2014
  const db = createDb({
1944
- databaseUrl: sql8.databaseUrl,
1945
- driver: sql8.driver
2015
+ databaseUrl: sql10.databaseUrl,
2016
+ driver: sql10.driver
1946
2017
  });
1947
2018
  current = {
1948
- databaseUrl: sql8.databaseUrl,
1949
- driver: sql8.driver,
2019
+ databaseUrl: sql10.databaseUrl,
2020
+ driver: sql10.driver,
1950
2021
  db,
1951
2022
  store: createSqlStore(db),
1952
2023
  stepStore: createSqlAgentStepStore(db),
1953
- messageStore: createSqlConversationMessageStore(db)
2024
+ messageStore: createSqlConversationMessageStore(db),
2025
+ searchStore: createSqlConversationSearchStore(db)
1954
2026
  };
1955
2027
  }
1956
2028
  return current.db;
@@ -1970,6 +2042,10 @@ function getConversationMessageStore() {
1970
2042
  getSqlExecutor();
1971
2043
  return current.messageStore;
1972
2044
  }
2045
+ function getConversationSearchStore() {
2046
+ getSqlExecutor();
2047
+ return current.searchStore;
2048
+ }
1973
2049
  async function closeDb() {
1974
2050
  const previous = current;
1975
2051
  current = void 0;
@@ -1999,5 +2075,6 @@ export {
1999
2075
  getConversationStore,
2000
2076
  getAgentStepStore,
2001
2077
  getConversationMessageStore,
2078
+ getConversationSearchStore,
2002
2079
  closeDb
2003
2080
  };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  commitMessages,
3
3
  loadTurnProjection
4
- } from "./chunk-GUAP3H7O.js";
4
+ } from "./chunk-DHHU2WSG.js";
5
5
  import {
6
6
  usageSchema
7
7
  } from "./chunk-PDO5BLNM.js";
@@ -9,150 +9,13 @@ import {
9
9
  getConversationStore,
10
10
  instructionActors,
11
11
  instructionProvenanceFor
12
- } from "./chunk-35BNLDOJ.js";
12
+ } from "./chunk-OGHXZ4KQ.js";
13
13
  import {
14
14
  getStateAdapter
15
15
  } from "./chunk-EEZCY5WX.js";
16
16
  import {
17
17
  toStoredSlackActor
18
18
  } from "./chunk-I35CTGPO.js";
19
- import {
20
- isRecord,
21
- toOptionalNumber,
22
- toOptionalString
23
- } from "./chunk-OB42YVAE.js";
24
-
25
- // src/chat/state/conversation.ts
26
- function defaultConversationState() {
27
- const nowMs = Date.now();
28
- return {
29
- schemaVersion: 1,
30
- messages: [],
31
- compactions: [],
32
- backfill: {},
33
- processing: {},
34
- stats: {
35
- estimatedContextTokens: 0,
36
- totalMessageCount: 0,
37
- compactedMessageCount: 0,
38
- updatedAtMs: nowMs
39
- },
40
- vision: {
41
- byFileId: {}
42
- }
43
- };
44
- }
45
- function coercePendingAuthState(value) {
46
- if (!isRecord(value)) {
47
- return void 0;
48
- }
49
- const kind = value.kind;
50
- const provider = toOptionalString(value.provider);
51
- const actorId = toOptionalString(value.actorId);
52
- const scope = toOptionalString(value.scope);
53
- const sessionId = toOptionalString(value.sessionId);
54
- const linkSentAtMs = toOptionalNumber(value.linkSentAtMs);
55
- if (kind !== "mcp" && kind !== "plugin" || !provider || !actorId || !sessionId || typeof linkSentAtMs !== "number") {
56
- return void 0;
57
- }
58
- return {
59
- kind,
60
- provider,
61
- actorId,
62
- ...scope ? { scope } : {},
63
- sessionId,
64
- linkSentAtMs
65
- };
66
- }
67
- function coerceThreadConversationState(value) {
68
- if (!isRecord(value)) {
69
- return defaultConversationState();
70
- }
71
- const root = value;
72
- const rawConversation = isRecord(root.conversation) ? root.conversation : {};
73
- const base = defaultConversationState();
74
- const messages = [];
75
- const rawCompactions = Array.isArray(rawConversation.compactions) ? rawConversation.compactions : [];
76
- const compactions = [];
77
- for (const item of rawCompactions) {
78
- if (!isRecord(item)) continue;
79
- const id = toOptionalString(item.id);
80
- const summary = toOptionalString(item.summary);
81
- const createdAtMs = toOptionalNumber(item.createdAtMs);
82
- if (!id || !summary || !createdAtMs) continue;
83
- const coveredMessageIds = Array.isArray(item.coveredMessageIds) ? item.coveredMessageIds.filter(
84
- (entry) => typeof entry === "string" && entry.length > 0
85
- ) : [];
86
- compactions.push({
87
- id,
88
- summary,
89
- createdAtMs,
90
- coveredMessageIds
91
- });
92
- }
93
- const rawBackfill = isRecord(rawConversation.backfill) ? rawConversation.backfill : {};
94
- const backfill = {
95
- completedAtMs: toOptionalNumber(rawBackfill.completedAtMs),
96
- source: rawBackfill.source === "recent_messages" || rawBackfill.source === "thread_fetch" ? rawBackfill.source : void 0
97
- };
98
- const rawProcessing = isRecord(rawConversation.processing) ? rawConversation.processing : {};
99
- const processing = {
100
- activeTurnId: toOptionalString(rawProcessing.activeTurnId),
101
- lastCompletedAtMs: toOptionalNumber(rawProcessing.lastCompletedAtMs),
102
- pendingAuth: coercePendingAuthState(rawProcessing.pendingAuth)
103
- };
104
- const rawStats = isRecord(rawConversation.stats) ? rawConversation.stats : {};
105
- const stats = {
106
- estimatedContextTokens: toOptionalNumber(rawStats.estimatedContextTokens) ?? base.stats.estimatedContextTokens,
107
- totalMessageCount: toOptionalNumber(rawStats.totalMessageCount) ?? messages.length,
108
- compactedMessageCount: toOptionalNumber(rawStats.compactedMessageCount) ?? 0,
109
- updatedAtMs: toOptionalNumber(rawStats.updatedAtMs) ?? base.stats.updatedAtMs
110
- };
111
- const rawVision = isRecord(rawConversation.vision) ? rawConversation.vision : {};
112
- const rawVisionByFileId = isRecord(rawVision.byFileId) ? rawVision.byFileId : {};
113
- const byFileId = {};
114
- for (const [fileId, value2] of Object.entries(rawVisionByFileId)) {
115
- if (typeof fileId !== "string" || fileId.trim().length === 0) continue;
116
- if (!isRecord(value2)) continue;
117
- const summary = toOptionalString(value2.summary);
118
- const analyzedAtMs = toOptionalNumber(value2.analyzedAtMs);
119
- if (!summary || !analyzedAtMs) continue;
120
- byFileId[fileId] = {
121
- summary,
122
- analyzedAtMs
123
- };
124
- }
125
- return {
126
- schemaVersion: 1,
127
- messages,
128
- compactions,
129
- backfill,
130
- processing,
131
- stats,
132
- vision: {
133
- backfillCompletedAtMs: toOptionalNumber(rawVision.backfillCompletedAtMs),
134
- byFileId
135
- }
136
- };
137
- }
138
- function buildConversationStatePatch(conversation) {
139
- const {
140
- compactions: _compactions,
141
- messages: _messages,
142
- ...scratch
143
- } = conversation;
144
- return {
145
- conversation: {
146
- ...scratch,
147
- schemaVersion: 1,
148
- stats: {
149
- ...conversation.stats,
150
- totalMessageCount: conversation.messages.length,
151
- updatedAtMs: Date.now()
152
- }
153
- }
154
- };
155
- }
156
19
 
157
20
  // src/chat/usage.ts
158
21
  var agentTurnUsageSchema = usageSchema;
@@ -649,10 +512,7 @@ async function readAgentTurnSessionSummariesFromIndex(key, stateAdapter) {
649
512
  }
650
513
  async function listAgentTurnSessionSummariesForConversation(conversationId) {
651
514
  const stateAdapter = getStateAdapter();
652
- const summaries = await readAgentTurnSessionSummariesFromIndex(
653
- agentTurnSessionConversationIndexKey(conversationId),
654
- stateAdapter
655
- );
515
+ const summaries = await listBoundedAgentTurnSessionSummariesForConversation(conversationId);
656
516
  if (summaries.length > 0) {
657
517
  return summaries;
658
518
  }
@@ -661,6 +521,12 @@ async function listAgentTurnSessionSummariesForConversation(conversationId) {
661
521
  stateAdapter
662
522
  )).filter((summary) => summary.conversationId === conversationId);
663
523
  }
524
+ async function listBoundedAgentTurnSessionSummariesForConversation(conversationId) {
525
+ return readAgentTurnSessionSummariesFromIndex(
526
+ agentTurnSessionConversationIndexKey(conversationId),
527
+ getStateAdapter()
528
+ );
529
+ }
664
530
  async function listAgentTurnSessionSummariesForConversations(stateAdapter, conversationIds) {
665
531
  const ids = [...new Set(conversationIds)];
666
532
  const globalSummaries = await readAgentTurnSessionSummariesFromIndex(
@@ -730,9 +596,6 @@ async function failAgentTurnSessionRecord(args) {
730
596
  });
731
597
  }
732
598
 
733
- // src/chat/state/ttl.ts
734
- var JUNIOR_THREAD_STATE_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
735
-
736
599
  export {
737
600
  hasAgentTurnUsage,
738
601
  addAgentTurnUsage,
@@ -740,10 +603,8 @@ export {
740
603
  upsertAgentTurnSessionRecord,
741
604
  recordAgentTurnSessionSummary,
742
605
  listAgentTurnSessionSummariesForConversation,
606
+ listBoundedAgentTurnSessionSummariesForConversation,
743
607
  listAgentTurnSessionSummariesForConversations,
744
608
  abandonAgentTurnSessionRecord,
745
- failAgentTurnSessionRecord,
746
- JUNIOR_THREAD_STATE_TTL_MS,
747
- coerceThreadConversationState,
748
- buildConversationStatePatch
609
+ failAgentTurnSessionRecord
749
610
  };