@sentry/junior 0.153.0 → 0.155.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.
- package/dist/{agent-hooks-7BWOB7SN.js → agent-hooks-AWVTLAV2.js} +11 -12
- package/dist/api/conversations/list.d.ts +5 -3
- package/dist/api/conversations/membership.d.ts +16 -0
- package/dist/api/locations/detail.d.ts +1 -0
- package/dist/api/schema/conversation.d.ts +3 -0
- package/dist/api/schema/location.d.ts +1 -0
- package/dist/api/schema/person.d.ts +1 -0
- package/dist/api/schema.js +1 -1
- package/dist/api.js +318 -187
- package/dist/app.js +39 -39
- package/dist/catalog-runtime-V6YD6KH5.js +16 -0
- package/dist/chat/conversations/sql/event-actor.d.ts +14 -0
- package/dist/chat/conversations/sql/event-lock.d.ts +1 -1
- package/dist/chat/conversations/sql/participants.d.ts +17 -0
- package/dist/chat/plugins/unfinished-work.d.ts +2 -0
- package/dist/chat/runtime/agent-runner.d.ts +2 -0
- package/dist/chat/runtime/slack-resume.d.ts +1 -1
- package/dist/chat/state/conversation.d.ts +1 -0
- package/dist/{chunk-O2YXWWPM.js → chunk-2AHVM3HK.js} +92 -9
- package/dist/{chunk-VXWTGOLW.js → chunk-2WLJDM23.js} +1 -1
- package/dist/{chunk-4TWLKHOM.js → chunk-37G5HJ2X.js} +4 -4
- package/dist/{chunk-ISEROVYZ.js → chunk-4K5N6HTX.js} +5 -5
- package/dist/{chunk-ET54Q4TD.js → chunk-773XC7P4.js} +116 -82
- package/dist/{chunk-HUO3UTAQ.js → chunk-7MA4HV4W.js} +1 -1
- package/dist/{chunk-HMU2QP5M.js → chunk-7NYEB2TM.js} +1 -1
- package/dist/{chunk-URFV5RWN.js → chunk-AENPRXCG.js} +23 -56
- package/dist/{chunk-TIV3PX5H.js → chunk-APHDJYN7.js} +2 -2
- package/dist/{chunk-RUIXF3YQ.js → chunk-BDUENQD3.js} +1 -1
- package/dist/{chunk-5TXDKTET.js → chunk-CPQBTTI6.js} +7 -7
- package/dist/{chunk-A5SROS6H.js → chunk-ELOTIL5F.js} +5 -5
- package/dist/{chunk-JJAMURMR.js → chunk-EORR34UB.js} +1 -1
- package/dist/{chunk-5QBK3QHJ.js → chunk-J2SYI36O.js} +6 -8
- package/dist/{chunk-K4LK6KYO.js → chunk-J7MWZFFP.js} +4 -4
- package/dist/{chunk-COC65LIW.js → chunk-JFZBGFNX.js} +3 -1
- package/dist/{chunk-YECBSG77.js → chunk-JIC33O5L.js} +2 -2
- package/dist/{chunk-XAYXN4EG.js → chunk-JJX77MB7.js} +366 -138
- package/dist/{chunk-FLEY546A.js → chunk-KBT2I5ER.js} +7 -7
- package/dist/{chunk-37LMRT7G.js → chunk-KTVHAHUV.js} +1 -1
- package/dist/{chunk-PMJAY6JS.js → chunk-LQT3SWFA.js} +5 -5
- package/dist/{chunk-HYEAR6HL.js → chunk-MLBH7J7J.js} +1 -1
- package/dist/{chunk-5DMPHA4V.js → chunk-NKFRRZIT.js} +27 -37
- package/dist/{chunk-HOK7MEWG.js → chunk-NWSKFYOH.js} +1 -1
- package/dist/{chunk-JY2HJYJT.js → chunk-RN3AWYEP.js} +2 -2
- package/dist/{chunk-RKW5QGGN.js → chunk-RQ62VKM7.js} +1 -1
- package/dist/{chunk-XQPKMLRI.js → chunk-SDRJ2LE3.js} +1 -1
- package/dist/{chunk-JAJVUQV7.js → chunk-TKJ7277U.js} +3 -3
- package/dist/{chunk-EPOA52SD.js → chunk-TVXAN43I.js} +1 -1
- package/dist/{chunk-2NS3ACHB.js → chunk-UWTXAYBP.js} +11 -11
- package/dist/{chunk-2J4VCHRX.js → chunk-V57LZDHN.js} +8 -10
- package/dist/{chunk-HZF5P5UN.js → chunk-V7YE4WCP.js} +58 -7
- package/dist/{chunk-PGJBNO3I.js → chunk-XFZLQANQ.js} +2 -2
- package/dist/{chunk-5XBRH3N7.js → chunk-Y6MVGU7L.js} +12 -11
- package/dist/{chunk-WTKAALLV.js → chunk-Y7ZUBP2K.js} +6 -6
- package/dist/{chunk-UG5UCHHJ.js → chunk-ZLSFOSDK.js} +2 -1
- package/dist/cli/chat.js +36 -36
- package/dist/cli/check.js +8 -9
- package/dist/cli/init.js +41 -7
- package/dist/cli/plugins.js +15 -16
- package/dist/cli/snapshot-create.js +11 -12
- package/dist/cli/upgrade.js +9 -10
- package/dist/db/schema/conversation-events.d.ts +20 -0
- package/dist/db/schema/conversation-participants.d.ts +63 -0
- package/dist/db/schema.d.ts +77 -1
- package/dist/{db-QNQM5YRR.js → db-WT7P56AH.js} +8 -8
- package/dist/instrumentation.js +4 -4
- package/dist/nitro.js +2 -2
- package/dist/{oauth-callback-server-ERQPIR27.js → oauth-callback-server-R2PK2MCA.js} +26 -26
- package/dist/{runner-BX46SQIE.js → runner-O7YYUIHT.js} +15 -16
- package/dist/{sandbox-egress-signals-EKPAVWQL.js → sandbox-egress-signals-U3ZX7C5W.js} +3 -4
- package/dist/{skills-JL44EIRX.js → skills-S6HLQRH7.js} +8 -9
- package/dist/spawn-B4SBFFA2.js +37 -0
- package/dist/{validation-UU2AIJIY.js → validation-46WD2OAR.js} +8 -9
- package/dist/version.js +1 -1
- package/dist/{work-SS7RU5CH.js → work-YT5QUBS3.js} +20 -21
- package/dist/worker-4C5BEDWN.js +24 -0
- package/migrations/0026_conversation_event_actor_and_participants.sql +140 -0
- package/migrations/meta/0026_snapshot.json +2424 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +8 -6
- package/dist/catalog-runtime-CGUDNL3D.js +0 -17
- package/dist/chunk-F3B2YJ76.js +0 -57
- package/dist/spawn-W6FO32T4.js +0 -38
- package/dist/worker-5P2E7LVI.js +0 -25
|
@@ -2,29 +2,31 @@ import {
|
|
|
2
2
|
createJuniorSqlExecutor,
|
|
3
3
|
juniorConversationBindings,
|
|
4
4
|
juniorConversationEvents,
|
|
5
|
+
juniorConversationParticipants,
|
|
5
6
|
juniorConversations,
|
|
6
7
|
juniorIdentities,
|
|
7
8
|
juniorUsers
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-773XC7P4.js";
|
|
9
10
|
import {
|
|
10
11
|
TURN_REASONING_LEVELS,
|
|
11
12
|
getChatConfig,
|
|
12
13
|
modelProfileSchema
|
|
13
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-XFZLQANQ.js";
|
|
14
15
|
import {
|
|
15
16
|
juniorDestinations
|
|
16
17
|
} from "./chunk-VFUK3X5B.js";
|
|
17
18
|
import {
|
|
19
|
+
parseActorUserId,
|
|
18
20
|
parseSlackChannelReferenceId,
|
|
19
21
|
parseSlackTeamId
|
|
20
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-V7YE4WCP.js";
|
|
21
23
|
import {
|
|
22
24
|
normalizeIdentityEmail
|
|
23
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-7NYEB2TM.js";
|
|
24
26
|
|
|
25
27
|
// src/chat/conversations/sql/store.ts
|
|
26
28
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
27
|
-
import { and as
|
|
29
|
+
import { and as and4, asc, desc, eq as eq4, isNull, sql as sql3 } from "drizzle-orm";
|
|
28
30
|
|
|
29
31
|
// src/chat/destination.ts
|
|
30
32
|
import {
|
|
@@ -206,6 +208,42 @@ async function deleteProviderIdentityForSlackUser(executor, slackTeamId, slackUs
|
|
|
206
208
|
);
|
|
207
209
|
}
|
|
208
210
|
|
|
211
|
+
// src/chat/conversations/sql/participants.ts
|
|
212
|
+
import { and as and2, eq as eq2, inArray, sql as sql2 } from "drizzle-orm";
|
|
213
|
+
async function resolveRootConversationId(executor, conversationId) {
|
|
214
|
+
const [row] = await executor.db().select({
|
|
215
|
+
rootConversationId: juniorConversations.rootConversationId
|
|
216
|
+
}).from(juniorConversations).where(eq2(juniorConversations.conversationId, conversationId)).limit(1);
|
|
217
|
+
return row?.rootConversationId ?? conversationId;
|
|
218
|
+
}
|
|
219
|
+
async function recordConversationParticipant(executor, args) {
|
|
220
|
+
const [identity] = await executor.db().select({
|
|
221
|
+
kind: juniorIdentities.kind,
|
|
222
|
+
userId: juniorIdentities.userId
|
|
223
|
+
}).from(juniorIdentities).where(eq2(juniorIdentities.id, args.actorIdentityId)).limit(1);
|
|
224
|
+
if (!identity?.userId || identity.kind !== "user") {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const rootConversationId = await resolveRootConversationId(
|
|
228
|
+
executor,
|
|
229
|
+
args.conversationId
|
|
230
|
+
);
|
|
231
|
+
const at = new Date(args.atMs);
|
|
232
|
+
await executor.db().insert(juniorConversationParticipants).values({
|
|
233
|
+
userId: identity.userId,
|
|
234
|
+
rootConversationId,
|
|
235
|
+
lastMessageAt: at
|
|
236
|
+
}).onConflictDoUpdate({
|
|
237
|
+
target: [
|
|
238
|
+
juniorConversationParticipants.userId,
|
|
239
|
+
juniorConversationParticipants.rootConversationId
|
|
240
|
+
],
|
|
241
|
+
set: {
|
|
242
|
+
lastMessageAt: sql2`greatest(${juniorConversationParticipants.lastMessageAt}, excluded.last_message_at)`
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
209
247
|
// src/chat/source.ts
|
|
210
248
|
import { sourceSchema } from "@sentry/junior-plugin-api";
|
|
211
249
|
function normalizeSessionSource(value) {
|
|
@@ -241,17 +279,17 @@ function parseSessionSource(value) {
|
|
|
241
279
|
}
|
|
242
280
|
|
|
243
281
|
// src/chat/conversations/sql/bindings.ts
|
|
244
|
-
import { and as
|
|
282
|
+
import { and as and3, eq as eq3 } from "drizzle-orm";
|
|
245
283
|
async function getConversationIdByProviderConversation(executor, args) {
|
|
246
284
|
const rows = await executor.db().select({ conversationId: juniorConversationBindings.conversationId }).from(juniorConversationBindings).where(
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
285
|
+
and3(
|
|
286
|
+
eq3(juniorConversationBindings.provider, args.provider),
|
|
287
|
+
eq3(juniorConversationBindings.providerTenantId, args.providerTenantId),
|
|
288
|
+
eq3(
|
|
251
289
|
juniorConversationBindings.providerDestinationId,
|
|
252
290
|
args.providerDestinationId
|
|
253
291
|
),
|
|
254
|
-
|
|
292
|
+
eq3(
|
|
255
293
|
juniorConversationBindings.providerConversationId,
|
|
256
294
|
args.providerConversationId
|
|
257
295
|
)
|
|
@@ -768,7 +806,7 @@ var SqlStore = class {
|
|
|
768
806
|
metricRunId: args.execution.runId ?? null,
|
|
769
807
|
executionDurationMs: args.metrics.durationMs,
|
|
770
808
|
executionUsage: args.metrics.usage ?? (sameRun ? row?.executionUsage ?? null : null)
|
|
771
|
-
}).where(
|
|
809
|
+
}).where(eq4(juniorConversations.conversationId, args.conversationId));
|
|
772
810
|
}
|
|
773
811
|
});
|
|
774
812
|
}
|
|
@@ -780,11 +818,11 @@ var SqlStore = class {
|
|
|
780
818
|
actorUserDisplayName: juniorUsers.displayName
|
|
781
819
|
}).from(juniorConversations).leftJoin(
|
|
782
820
|
juniorDestinations,
|
|
783
|
-
|
|
821
|
+
eq4(juniorDestinations.id, juniorConversations.destinationId)
|
|
784
822
|
).leftJoin(
|
|
785
823
|
juniorIdentities,
|
|
786
|
-
|
|
787
|
-
).leftJoin(juniorUsers,
|
|
824
|
+
eq4(juniorIdentities.id, juniorConversations.actorIdentityId)
|
|
825
|
+
).leftJoin(juniorUsers, eq4(juniorUsers.id, juniorIdentities.userId)).where(isNull(juniorConversations.parentConversationId)).orderBy(
|
|
788
826
|
desc(juniorConversations.lastActivityAt),
|
|
789
827
|
asc(juniorConversations.conversationId)
|
|
790
828
|
).limit(Math.max(0, args.limit ?? 1e4)).offset(Math.max(0, args.offset ?? 0));
|
|
@@ -798,13 +836,13 @@ var SqlStore = class {
|
|
|
798
836
|
const rows = await this.executor.db().select({
|
|
799
837
|
visibility: juniorDestinations.visibility
|
|
800
838
|
}).from(juniorDestinations).where(
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
839
|
+
and4(
|
|
840
|
+
eq4(juniorDestinations.provider, args.provider),
|
|
841
|
+
eq4(
|
|
804
842
|
juniorDestinations.providerTenantId,
|
|
805
843
|
tenantId2(args.providerTenantId)
|
|
806
844
|
),
|
|
807
|
-
|
|
845
|
+
eq4(
|
|
808
846
|
juniorDestinations.providerDestinationId,
|
|
809
847
|
args.providerDestinationId
|
|
810
848
|
)
|
|
@@ -835,19 +873,19 @@ var SqlStore = class {
|
|
|
835
873
|
actorUserDisplayName: juniorUsers.displayName
|
|
836
874
|
}).from(juniorConversations).leftJoin(
|
|
837
875
|
juniorDestinations,
|
|
838
|
-
|
|
876
|
+
eq4(juniorDestinations.id, juniorConversations.destinationId)
|
|
839
877
|
).leftJoin(
|
|
840
878
|
juniorIdentities,
|
|
841
|
-
|
|
842
|
-
).leftJoin(juniorUsers,
|
|
879
|
+
eq4(juniorIdentities.id, juniorConversations.actorIdentityId)
|
|
880
|
+
).leftJoin(juniorUsers, eq4(juniorUsers.id, juniorIdentities.userId)).where(eq4(juniorConversations.conversationId, conversationId));
|
|
843
881
|
return rows[0];
|
|
844
882
|
}
|
|
845
883
|
/** Upsert the conversation row while preserving previously discovered nullable metadata fields. */
|
|
846
884
|
async upsertConversation(args) {
|
|
847
885
|
const { conversation } = args;
|
|
848
|
-
const incomingExecutionVersion =
|
|
849
|
-
const currentExecutionVersion =
|
|
850
|
-
const incomingExecutionIsFresh =
|
|
886
|
+
const incomingExecutionVersion = sql3`coalesce(excluded.execution_updated_at, excluded.updated_at)`;
|
|
887
|
+
const currentExecutionVersion = sql3`coalesce(${juniorConversations.executionUpdatedAt}, ${juniorConversations.updatedAt})`;
|
|
888
|
+
const incomingExecutionIsFresh = sql3`${incomingExecutionVersion} >= ${currentExecutionVersion}`;
|
|
851
889
|
const destinationId = await this.upsertDestination(
|
|
852
890
|
destinationUpsertFromDestination({
|
|
853
891
|
channelName: conversation.channelName,
|
|
@@ -863,7 +901,7 @@ var SqlStore = class {
|
|
|
863
901
|
actorIdentityObservation,
|
|
864
902
|
conversation.updatedAtMs
|
|
865
903
|
) : void 0;
|
|
866
|
-
const rootConversationId = conversation.lineage ?
|
|
904
|
+
const rootConversationId = conversation.lineage ? sql3`(
|
|
867
905
|
select parent.root_conversation_id
|
|
868
906
|
from junior_conversations parent
|
|
869
907
|
where parent.conversation_id = ${conversation.lineage.parentConversationId}
|
|
@@ -898,39 +936,49 @@ var SqlStore = class {
|
|
|
898
936
|
target: juniorConversations.conversationId,
|
|
899
937
|
set: {
|
|
900
938
|
// Origin source is set-once so dashboard continues cannot rewrite a Slack root.
|
|
901
|
-
source:
|
|
902
|
-
sessionSource:
|
|
903
|
-
originType:
|
|
904
|
-
originId:
|
|
905
|
-
originRunId:
|
|
906
|
-
destinationId:
|
|
907
|
-
actorIdentityId:
|
|
908
|
-
creatorIdentityId:
|
|
909
|
-
credentialSubjectIdentityId:
|
|
910
|
-
channelName:
|
|
911
|
-
title:
|
|
912
|
-
createdAt:
|
|
913
|
-
lastActivityAt:
|
|
914
|
-
updatedAt:
|
|
915
|
-
executionUpdatedAt:
|
|
916
|
-
executionStatus:
|
|
917
|
-
runId:
|
|
918
|
-
lastCheckpointAt:
|
|
919
|
-
lastEnqueuedAt:
|
|
920
|
-
rootConversationId:
|
|
939
|
+
source: sql3`coalesce(${juniorConversations.source}, excluded.source)`,
|
|
940
|
+
sessionSource: sql3`coalesce(${juniorConversations.sessionSource}, excluded.source_json)`,
|
|
941
|
+
originType: sql3`coalesce(excluded.origin_type, ${juniorConversations.originType})`,
|
|
942
|
+
originId: sql3`coalesce(excluded.origin_id, ${juniorConversations.originId})`,
|
|
943
|
+
originRunId: sql3`coalesce(excluded.origin_run_id, ${juniorConversations.originRunId})`,
|
|
944
|
+
destinationId: sql3`coalesce(excluded.destination_id, ${juniorConversations.destinationId})`,
|
|
945
|
+
actorIdentityId: sql3`coalesce(excluded.actor_identity_id, ${juniorConversations.actorIdentityId})`,
|
|
946
|
+
creatorIdentityId: sql3`coalesce(excluded.creator_identity_id, ${juniorConversations.creatorIdentityId})`,
|
|
947
|
+
credentialSubjectIdentityId: sql3`coalesce(excluded.credential_subject_identity_id, ${juniorConversations.credentialSubjectIdentityId})`,
|
|
948
|
+
channelName: sql3`coalesce(excluded.channel_name, ${juniorConversations.channelName})`,
|
|
949
|
+
title: sql3`coalesce(excluded.title, ${juniorConversations.title})`,
|
|
950
|
+
createdAt: sql3`least(${juniorConversations.createdAt}, excluded.created_at)`,
|
|
951
|
+
lastActivityAt: sql3`greatest(${juniorConversations.lastActivityAt}, excluded.last_activity_at)`,
|
|
952
|
+
updatedAt: sql3`greatest(${juniorConversations.updatedAt}, excluded.updated_at)`,
|
|
953
|
+
executionUpdatedAt: sql3`case when ${incomingExecutionIsFresh} then excluded.execution_updated_at else ${juniorConversations.executionUpdatedAt} end`,
|
|
954
|
+
executionStatus: sql3`case when ${incomingExecutionIsFresh} then excluded.execution_status else ${juniorConversations.executionStatus} end`,
|
|
955
|
+
runId: sql3`case when ${incomingExecutionIsFresh} then excluded.run_id else ${juniorConversations.runId} end`,
|
|
956
|
+
lastCheckpointAt: sql3`case when ${incomingExecutionIsFresh} then coalesce(excluded.last_checkpoint_at, ${juniorConversations.lastCheckpointAt}) else ${juniorConversations.lastCheckpointAt} end`,
|
|
957
|
+
lastEnqueuedAt: sql3`case when ${incomingExecutionIsFresh} then coalesce(excluded.last_enqueued_at, ${juniorConversations.lastEnqueuedAt}) else ${juniorConversations.lastEnqueuedAt} end`,
|
|
958
|
+
rootConversationId: sql3`coalesce(${juniorConversations.rootConversationId}, excluded.root_conversation_id)`
|
|
921
959
|
}
|
|
922
960
|
}).returning({
|
|
961
|
+
actorIdentityId: juniorConversations.actorIdentityId,
|
|
962
|
+
parentConversationId: juniorConversations.parentConversationId,
|
|
923
963
|
rootConversationId: juniorConversations.rootConversationId
|
|
924
964
|
});
|
|
925
|
-
|
|
965
|
+
const row = rows[0];
|
|
966
|
+
if (!row?.rootConversationId) {
|
|
926
967
|
throw new Error("Conversation parent is missing its persisted root");
|
|
927
968
|
}
|
|
969
|
+
if (row.actorIdentityId && row.parentConversationId === null) {
|
|
970
|
+
await recordConversationParticipant(this.executor, {
|
|
971
|
+
actorIdentityId: row.actorIdentityId,
|
|
972
|
+
conversationId: conversation.conversationId,
|
|
973
|
+
atMs: conversation.lastActivityAtMs
|
|
974
|
+
});
|
|
975
|
+
}
|
|
928
976
|
}
|
|
929
977
|
async upsertDestination(destination, nowMs) {
|
|
930
978
|
if (!destination) {
|
|
931
979
|
return void 0;
|
|
932
980
|
}
|
|
933
|
-
const visibilityUpdate = destination.refreshVisibility ?
|
|
981
|
+
const visibilityUpdate = destination.refreshVisibility ? sql3`excluded.visibility` : juniorDestinations.visibility;
|
|
934
982
|
const rows = await this.executor.db().insert(juniorDestinations).values({
|
|
935
983
|
id: randomUUID2(),
|
|
936
984
|
provider: destination.provider,
|
|
@@ -950,14 +998,14 @@ var SqlStore = class {
|
|
|
950
998
|
juniorDestinations.providerDestinationId
|
|
951
999
|
],
|
|
952
1000
|
set: {
|
|
953
|
-
kind:
|
|
954
|
-
displayName:
|
|
1001
|
+
kind: sql3`excluded.kind`,
|
|
1002
|
+
displayName: sql3`coalesce(excluded.display_name, ${juniorDestinations.displayName})`,
|
|
955
1003
|
// Signal-less writes remain unknown and must not clobber an existing
|
|
956
1004
|
// public/private value. Live source signals refresh this field so
|
|
957
1005
|
// converted channels converge on the next message.
|
|
958
1006
|
visibility: visibilityUpdate,
|
|
959
|
-
metadata:
|
|
960
|
-
updatedAt:
|
|
1007
|
+
metadata: sql3`coalesce(excluded.metadata_json, ${juniorDestinations.metadata})`,
|
|
1008
|
+
updatedAt: sql3`excluded.updated_at`
|
|
961
1009
|
}
|
|
962
1010
|
}).returning({ id: juniorDestinations.id });
|
|
963
1011
|
return rows[0]?.id;
|
|
@@ -969,17 +1017,17 @@ function createSqlStore(executor) {
|
|
|
969
1017
|
|
|
970
1018
|
// src/chat/conversations/sql/history.ts
|
|
971
1019
|
import {
|
|
972
|
-
and as
|
|
1020
|
+
and as and6,
|
|
973
1021
|
asc as asc2,
|
|
974
1022
|
desc as desc2,
|
|
975
|
-
eq as
|
|
1023
|
+
eq as eq6,
|
|
976
1024
|
gt,
|
|
977
1025
|
gte,
|
|
978
|
-
inArray,
|
|
1026
|
+
inArray as inArray2,
|
|
979
1027
|
isNotNull,
|
|
980
1028
|
lt,
|
|
981
1029
|
lte,
|
|
982
|
-
sql as
|
|
1030
|
+
sql as sql6
|
|
983
1031
|
} from "drizzle-orm";
|
|
984
1032
|
|
|
985
1033
|
// src/chat/conversations/history.ts
|
|
@@ -1344,7 +1392,7 @@ var newConversationEventSchema = z3.object({
|
|
|
1344
1392
|
}).strict();
|
|
1345
1393
|
|
|
1346
1394
|
// src/chat/conversations/sql/conversation-row.ts
|
|
1347
|
-
import { sql as
|
|
1395
|
+
import { sql as sql4 } from "drizzle-orm";
|
|
1348
1396
|
async function ensureConversationRow(executor, conversationId, atMs, options = {}) {
|
|
1349
1397
|
const at = new Date(atMs);
|
|
1350
1398
|
const insert = executor.db().insert(juniorConversations).values({
|
|
@@ -1363,13 +1411,169 @@ async function ensureConversationRow(executor, conversationId, atMs, options = {
|
|
|
1363
1411
|
await insert.onConflictDoUpdate({
|
|
1364
1412
|
target: juniorConversations.conversationId,
|
|
1365
1413
|
set: {
|
|
1366
|
-
lastActivityAt:
|
|
1367
|
-
updatedAt:
|
|
1414
|
+
lastActivityAt: sql4`greatest(${juniorConversations.lastActivityAt}, excluded.last_activity_at)`,
|
|
1415
|
+
updatedAt: sql4`greatest(${juniorConversations.updatedAt}, excluded.updated_at)`,
|
|
1368
1416
|
transcriptPurgedAt: null
|
|
1369
1417
|
}
|
|
1370
1418
|
});
|
|
1371
1419
|
}
|
|
1372
1420
|
|
|
1421
|
+
// src/chat/conversations/sql/event-actor.ts
|
|
1422
|
+
import { and as and5, eq as eq5, or, sql as sql5 } from "drizzle-orm";
|
|
1423
|
+
var SLACK_USER_ID_PATTERN = /^[UW][A-Z0-9]{5,}$/;
|
|
1424
|
+
function isRecord(value) {
|
|
1425
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1426
|
+
}
|
|
1427
|
+
function readAuthor(meta) {
|
|
1428
|
+
if (!isRecord(meta) || !isRecord(meta.author)) {
|
|
1429
|
+
return {};
|
|
1430
|
+
}
|
|
1431
|
+
const author = meta.author;
|
|
1432
|
+
return {
|
|
1433
|
+
...typeof author.email === "string" ? { email: author.email } : {},
|
|
1434
|
+
...typeof author.fullName === "string" ? { fullName: author.fullName } : {},
|
|
1435
|
+
...typeof author.isBot === "boolean" ? { isBot: author.isBot } : {},
|
|
1436
|
+
...typeof author.userId === "string" ? { userId: author.userId } : {},
|
|
1437
|
+
...typeof author.userName === "string" ? { userName: author.userName } : {}
|
|
1438
|
+
};
|
|
1439
|
+
}
|
|
1440
|
+
async function loadConversationSlackTenantId(executor, conversationId) {
|
|
1441
|
+
const [row] = await executor.db().select({
|
|
1442
|
+
providerTenantId: juniorDestinations.providerTenantId,
|
|
1443
|
+
sessionSource: juniorConversations.sessionSource
|
|
1444
|
+
}).from(juniorConversations).leftJoin(
|
|
1445
|
+
juniorDestinations,
|
|
1446
|
+
eq5(juniorDestinations.id, juniorConversations.destinationId)
|
|
1447
|
+
).where(eq5(juniorConversations.conversationId, conversationId)).limit(1);
|
|
1448
|
+
const destinationTenant = row?.providerTenantId?.trim();
|
|
1449
|
+
if (destinationTenant) {
|
|
1450
|
+
return destinationTenant;
|
|
1451
|
+
}
|
|
1452
|
+
const sessionSource = row?.sessionSource;
|
|
1453
|
+
if (isRecord(sessionSource) && sessionSource.platform === "slack" && typeof sessionSource.teamId === "string" && sessionSource.teamId.trim()) {
|
|
1454
|
+
return sessionSource.teamId.trim();
|
|
1455
|
+
}
|
|
1456
|
+
return void 0;
|
|
1457
|
+
}
|
|
1458
|
+
async function findIdentityIdByProviderSubject(executor, args) {
|
|
1459
|
+
const rows = await executor.db().select({ id: juniorIdentities.id }).from(juniorIdentities).where(
|
|
1460
|
+
and5(
|
|
1461
|
+
eq5(juniorIdentities.provider, args.provider),
|
|
1462
|
+
eq5(juniorIdentities.providerSubjectId, args.providerSubjectId),
|
|
1463
|
+
args.providerTenantId === void 0 ? void 0 : eq5(juniorIdentities.providerTenantId, args.providerTenantId)
|
|
1464
|
+
)
|
|
1465
|
+
).limit(1);
|
|
1466
|
+
return rows[0]?.id;
|
|
1467
|
+
}
|
|
1468
|
+
async function findJuniorIdentityIdByEmail(executor, email) {
|
|
1469
|
+
const normalized = email.trim().toLowerCase();
|
|
1470
|
+
if (!normalized) return void 0;
|
|
1471
|
+
const rows = await executor.db().select({ id: juniorIdentities.id }).from(juniorIdentities).where(
|
|
1472
|
+
and5(
|
|
1473
|
+
eq5(juniorIdentities.provider, "junior"),
|
|
1474
|
+
eq5(juniorIdentities.kind, "user"),
|
|
1475
|
+
or(
|
|
1476
|
+
eq5(juniorIdentities.providerSubjectId, normalized),
|
|
1477
|
+
and5(
|
|
1478
|
+
eq5(juniorIdentities.emailNormalized, normalized),
|
|
1479
|
+
eq5(juniorIdentities.emailVerified, true)
|
|
1480
|
+
)
|
|
1481
|
+
)
|
|
1482
|
+
)
|
|
1483
|
+
).limit(1);
|
|
1484
|
+
return rows[0]?.id;
|
|
1485
|
+
}
|
|
1486
|
+
async function findJuniorIdentityIdByDashboardAuthorId(executor, dashboardAuthorId) {
|
|
1487
|
+
if (!dashboardAuthorId.startsWith("dashboard:")) {
|
|
1488
|
+
return void 0;
|
|
1489
|
+
}
|
|
1490
|
+
const rows = await executor.db().select({ id: juniorIdentities.id }).from(juniorIdentities).where(
|
|
1491
|
+
and5(
|
|
1492
|
+
eq5(juniorIdentities.provider, "junior"),
|
|
1493
|
+
eq5(juniorIdentities.kind, "user"),
|
|
1494
|
+
eq5(juniorIdentities.emailVerified, true),
|
|
1495
|
+
sql5`${juniorIdentities.emailNormalized} is not null`,
|
|
1496
|
+
// Match webActorFromEmail(): dashboard:${sha256(email).slice(0,24)}
|
|
1497
|
+
sql5`concat(
|
|
1498
|
+
'dashboard:',
|
|
1499
|
+
left(encode(digest(${juniorIdentities.emailNormalized}, 'sha256'), 'hex'), 24)
|
|
1500
|
+
) = ${dashboardAuthorId}`
|
|
1501
|
+
)
|
|
1502
|
+
).limit(1);
|
|
1503
|
+
return rows[0]?.id;
|
|
1504
|
+
}
|
|
1505
|
+
async function resolveEventActorIdentityId(executor, args) {
|
|
1506
|
+
const data = args.data;
|
|
1507
|
+
if (data.type !== "message" && data.type !== "message_updated") {
|
|
1508
|
+
return void 0;
|
|
1509
|
+
}
|
|
1510
|
+
if (typeof data.authorIdentityId === "string" && data.authorIdentityId) {
|
|
1511
|
+
return data.authorIdentityId;
|
|
1512
|
+
}
|
|
1513
|
+
if (data.role !== "user") {
|
|
1514
|
+
return void 0;
|
|
1515
|
+
}
|
|
1516
|
+
const author = readAuthor(data.meta);
|
|
1517
|
+
if (author.isBot === true) {
|
|
1518
|
+
return void 0;
|
|
1519
|
+
}
|
|
1520
|
+
const userId = parseActorUserId(author.userId);
|
|
1521
|
+
if (!userId) {
|
|
1522
|
+
return void 0;
|
|
1523
|
+
}
|
|
1524
|
+
if (SLACK_USER_ID_PATTERN.test(userId)) {
|
|
1525
|
+
const tenantId3 = await loadConversationSlackTenantId(
|
|
1526
|
+
executor,
|
|
1527
|
+
args.conversationId
|
|
1528
|
+
);
|
|
1529
|
+
const observation = {
|
|
1530
|
+
kind: "user",
|
|
1531
|
+
provider: "slack",
|
|
1532
|
+
providerSubjectId: userId,
|
|
1533
|
+
...tenantId3 ? { providerTenantId: tenantId3 } : {},
|
|
1534
|
+
...author.fullName ? { displayName: author.fullName } : {},
|
|
1535
|
+
...author.userName ? { handle: author.userName } : {},
|
|
1536
|
+
...author.email ? { email: author.email, emailVerified: true } : {}
|
|
1537
|
+
};
|
|
1538
|
+
if (tenantId3) {
|
|
1539
|
+
const stored = await upsertIdentity(executor, observation, args.nowMs);
|
|
1540
|
+
return stored.id;
|
|
1541
|
+
}
|
|
1542
|
+
return await findIdentityIdByProviderSubject(executor, {
|
|
1543
|
+
provider: "slack",
|
|
1544
|
+
providerSubjectId: userId
|
|
1545
|
+
}) ?? void 0;
|
|
1546
|
+
}
|
|
1547
|
+
const email = typeof author.email === "string" && author.email.includes("@") ? author.email.trim().toLowerCase() : userId.includes("@") ? userId.trim().toLowerCase() : void 0;
|
|
1548
|
+
if (email) {
|
|
1549
|
+
const stored = await upsertIdentity(
|
|
1550
|
+
executor,
|
|
1551
|
+
{
|
|
1552
|
+
kind: "user",
|
|
1553
|
+
provider: "junior",
|
|
1554
|
+
providerSubjectId: email,
|
|
1555
|
+
email,
|
|
1556
|
+
emailVerified: true,
|
|
1557
|
+
...author.fullName ? { displayName: author.fullName } : {},
|
|
1558
|
+
metadata: { platform: "web" }
|
|
1559
|
+
},
|
|
1560
|
+
args.nowMs
|
|
1561
|
+
);
|
|
1562
|
+
return stored.id;
|
|
1563
|
+
}
|
|
1564
|
+
if (userId.startsWith("dashboard:")) {
|
|
1565
|
+
return findJuniorIdentityIdByDashboardAuthorId(executor, userId);
|
|
1566
|
+
}
|
|
1567
|
+
return findJuniorIdentityIdByEmail(executor, userId);
|
|
1568
|
+
}
|
|
1569
|
+
function stripPayloadAuthorIdentityId(data) {
|
|
1570
|
+
if (data.type !== "message" && data.type !== "message_updated" || data.authorIdentityId === void 0) {
|
|
1571
|
+
return data;
|
|
1572
|
+
}
|
|
1573
|
+
const { authorIdentityId: _authorIdentityId, ...rest } = data;
|
|
1574
|
+
return rest;
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1373
1577
|
// src/db/postgres-json.ts
|
|
1374
1578
|
function sanitizePostgresJson(value) {
|
|
1375
1579
|
if (typeof value === "string") {
|
|
@@ -1395,10 +1599,7 @@ function sanitizePostgresJson(value) {
|
|
|
1395
1599
|
|
|
1396
1600
|
// src/chat/conversations/sql/event-lock.ts
|
|
1397
1601
|
async function withConversationEventLock(executor, conversationId, callback) {
|
|
1398
|
-
return executor.withLock(
|
|
1399
|
-
`junior_conversation:event:${conversationId}`,
|
|
1400
|
-
callback
|
|
1401
|
-
);
|
|
1602
|
+
return executor.withLock(`junior_conversation:${conversationId}`, callback);
|
|
1402
1603
|
}
|
|
1403
1604
|
|
|
1404
1605
|
// src/chat/conversations/sql/history.ts
|
|
@@ -1407,8 +1608,9 @@ var messageHistoryEventTypes = [
|
|
|
1407
1608
|
"message_updated",
|
|
1408
1609
|
"message_handled"
|
|
1409
1610
|
];
|
|
1410
|
-
function insertFromEvent(conversationId, seq, historyVersion, event) {
|
|
1411
|
-
const
|
|
1611
|
+
function insertFromEvent(conversationId, seq, historyVersion, event, actorIdentityId) {
|
|
1612
|
+
const stripped = stripPayloadAuthorIdentityId(event.data);
|
|
1613
|
+
const { type, ...payload } = conversationEventDataSchema.parse(stripped);
|
|
1412
1614
|
return {
|
|
1413
1615
|
conversationId,
|
|
1414
1616
|
seq,
|
|
@@ -1417,10 +1619,12 @@ function insertFromEvent(conversationId, seq, historyVersion, event) {
|
|
|
1417
1619
|
idempotencyKey: event.idempotencyKey ?? null,
|
|
1418
1620
|
type,
|
|
1419
1621
|
payload: sanitizePostgresJson(payload),
|
|
1622
|
+
actorIdentityId: actorIdentityId ?? null,
|
|
1420
1623
|
createdAt: new Date(event.createdAtMs)
|
|
1421
1624
|
};
|
|
1422
1625
|
}
|
|
1423
1626
|
function eventFromRow(row) {
|
|
1627
|
+
const payload = row.actorIdentityId && typeof row.payload === "object" && row.payload !== null && !Array.isArray(row.payload) && (row.type === "message" || row.type === "message_updated") && !("authorIdentityId" in row.payload) ? { ...row.payload, authorIdentityId: row.actorIdentityId } : row.payload;
|
|
1424
1628
|
return decodeStoredConversationEvent({
|
|
1425
1629
|
schemaVersion: row.schemaVersion,
|
|
1426
1630
|
seq: row.seq,
|
|
@@ -1428,7 +1632,7 @@ function eventFromRow(row) {
|
|
|
1428
1632
|
...row.idempotencyKey ? { idempotencyKey: row.idempotencyKey } : {},
|
|
1429
1633
|
createdAtMs: row.createdAt.getTime(),
|
|
1430
1634
|
type: row.type,
|
|
1431
|
-
payload
|
|
1635
|
+
payload
|
|
1432
1636
|
});
|
|
1433
1637
|
}
|
|
1434
1638
|
function messagesSummarizedEventFromRow(row) {
|
|
@@ -1456,12 +1660,12 @@ var SqlConversationEventStore = class {
|
|
|
1456
1660
|
const existingKeys = parsed.map((event) => event.idempotencyKey).filter((key) => key !== void 0);
|
|
1457
1661
|
const persistedKeys = existingKeys.length === 0 ? /* @__PURE__ */ new Set() : new Set(
|
|
1458
1662
|
(await this.executor.db().select({ key: juniorConversationEvents.idempotencyKey }).from(juniorConversationEvents).where(
|
|
1459
|
-
|
|
1460
|
-
|
|
1663
|
+
and6(
|
|
1664
|
+
eq6(
|
|
1461
1665
|
juniorConversationEvents.conversationId,
|
|
1462
1666
|
conversationId
|
|
1463
1667
|
),
|
|
1464
|
-
|
|
1668
|
+
inArray2(
|
|
1465
1669
|
juniorConversationEvents.idempotencyKey,
|
|
1466
1670
|
existingKeys
|
|
1467
1671
|
)
|
|
@@ -1489,8 +1693,8 @@ var SqlConversationEventStore = class {
|
|
|
1489
1693
|
);
|
|
1490
1694
|
if (options.activity !== "preserve") {
|
|
1491
1695
|
await this.executor.db().update(juniorConversations).set({ archivedAt: null }).where(
|
|
1492
|
-
|
|
1493
|
-
|
|
1696
|
+
and6(
|
|
1697
|
+
eq6(juniorConversations.conversationId, conversationId),
|
|
1494
1698
|
isNotNull(juniorConversations.archivedAt)
|
|
1495
1699
|
)
|
|
1496
1700
|
);
|
|
@@ -1498,9 +1702,33 @@ var SqlConversationEventStore = class {
|
|
|
1498
1702
|
const cursor = await this.readCursor(conversationId);
|
|
1499
1703
|
const historyVersion = cursor.maxHistoryVersion ?? 0;
|
|
1500
1704
|
let seq = cursor.nextSeq;
|
|
1501
|
-
const rows =
|
|
1502
|
-
|
|
1503
|
-
|
|
1705
|
+
const rows = [];
|
|
1706
|
+
for (const event of pending) {
|
|
1707
|
+
const actorIdentityId = await resolveEventActorIdentityId(
|
|
1708
|
+
this.executor,
|
|
1709
|
+
{
|
|
1710
|
+
conversationId,
|
|
1711
|
+
data: event.data,
|
|
1712
|
+
nowMs: event.createdAtMs
|
|
1713
|
+
}
|
|
1714
|
+
);
|
|
1715
|
+
rows.push(
|
|
1716
|
+
insertFromEvent(
|
|
1717
|
+
conversationId,
|
|
1718
|
+
seq++,
|
|
1719
|
+
historyVersion,
|
|
1720
|
+
event,
|
|
1721
|
+
actorIdentityId
|
|
1722
|
+
)
|
|
1723
|
+
);
|
|
1724
|
+
if (actorIdentityId) {
|
|
1725
|
+
await recordConversationParticipant(this.executor, {
|
|
1726
|
+
actorIdentityId,
|
|
1727
|
+
conversationId,
|
|
1728
|
+
atMs: event.createdAtMs
|
|
1729
|
+
});
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1504
1732
|
await this.executor.db().insert(juniorConversationEvents).values(rows);
|
|
1505
1733
|
});
|
|
1506
1734
|
}
|
|
@@ -1509,8 +1737,8 @@ var SqlConversationEventStore = class {
|
|
|
1509
1737
|
await withConversationEventLock(this.executor, conversationId, async () => {
|
|
1510
1738
|
await ensureConversationRow(this.executor, conversationId, Date.now());
|
|
1511
1739
|
await this.executor.db().update(juniorConversations).set({ archivedAt: null }).where(
|
|
1512
|
-
|
|
1513
|
-
|
|
1740
|
+
and6(
|
|
1741
|
+
eq6(juniorConversations.conversationId, conversationId),
|
|
1514
1742
|
isNotNull(juniorConversations.archivedAt)
|
|
1515
1743
|
)
|
|
1516
1744
|
);
|
|
@@ -1532,34 +1760,34 @@ var SqlConversationEventStore = class {
|
|
|
1532
1760
|
return [];
|
|
1533
1761
|
}
|
|
1534
1762
|
const rows = await this.executor.db().select().from(juniorConversationEvents).where(
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1763
|
+
and6(
|
|
1764
|
+
eq6(juniorConversationEvents.conversationId, conversationId),
|
|
1765
|
+
eq6(juniorConversationEvents.historyVersion, cursor.maxHistoryVersion)
|
|
1538
1766
|
)
|
|
1539
1767
|
).orderBy(asc2(juniorConversationEvents.seq));
|
|
1540
1768
|
return rows.map(eventFromRow);
|
|
1541
1769
|
}
|
|
1542
1770
|
async loadByIdempotencyKey(conversationId, idempotencyKey) {
|
|
1543
1771
|
const [row] = await this.executor.db().select().from(juniorConversationEvents).where(
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1772
|
+
and6(
|
|
1773
|
+
eq6(juniorConversationEvents.conversationId, conversationId),
|
|
1774
|
+
eq6(juniorConversationEvents.idempotencyKey, idempotencyKey)
|
|
1547
1775
|
)
|
|
1548
1776
|
).limit(1);
|
|
1549
1777
|
return row ? eventFromRow(row) : void 0;
|
|
1550
1778
|
}
|
|
1551
1779
|
async loadHistoryContaining(conversationId, seq, throughSeq) {
|
|
1552
1780
|
const [boundary] = await this.executor.db().select({ historyVersion: juniorConversationEvents.historyVersion }).from(juniorConversationEvents).where(
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1781
|
+
and6(
|
|
1782
|
+
eq6(juniorConversationEvents.conversationId, conversationId),
|
|
1783
|
+
eq6(juniorConversationEvents.seq, seq)
|
|
1556
1784
|
)
|
|
1557
1785
|
).limit(1);
|
|
1558
1786
|
if (!boundary) return void 0;
|
|
1559
1787
|
const rows = await this.executor.db().select().from(juniorConversationEvents).where(
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1788
|
+
and6(
|
|
1789
|
+
eq6(juniorConversationEvents.conversationId, conversationId),
|
|
1790
|
+
eq6(juniorConversationEvents.historyVersion, boundary.historyVersion),
|
|
1563
1791
|
throughSeq === void 0 ? void 0 : lte(juniorConversationEvents.seq, throughSeq)
|
|
1564
1792
|
)
|
|
1565
1793
|
).orderBy(asc2(juniorConversationEvents.seq));
|
|
@@ -1567,45 +1795,45 @@ var SqlConversationEventStore = class {
|
|
|
1567
1795
|
}
|
|
1568
1796
|
async loadLatestStructuredEvent(conversationId, namespace, name) {
|
|
1569
1797
|
const [row] = await this.executor.db().select().from(juniorConversationEvents).where(
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1798
|
+
and6(
|
|
1799
|
+
eq6(juniorConversationEvents.conversationId, conversationId),
|
|
1800
|
+
eq6(juniorConversationEvents.type, "structured_event"),
|
|
1801
|
+
sql6`${juniorConversationEvents.payload}->>'namespace' = ${namespace}`,
|
|
1802
|
+
sql6`${juniorConversationEvents.payload}->>'name' = ${name}`
|
|
1575
1803
|
)
|
|
1576
1804
|
).orderBy(desc2(juniorConversationEvents.seq)).limit(1);
|
|
1577
1805
|
return row ? eventFromRow(row) : void 0;
|
|
1578
1806
|
}
|
|
1579
1807
|
async loadLatestInstruction(conversationId) {
|
|
1580
1808
|
const [row] = await this.executor.db().select().from(juniorConversationEvents).where(
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1809
|
+
and6(
|
|
1810
|
+
eq6(juniorConversationEvents.conversationId, conversationId),
|
|
1811
|
+
eq6(juniorConversationEvents.type, "user_message"),
|
|
1812
|
+
sql6`${juniorConversationEvents.payload}->'provenance'->>'authority' = 'instruction'`
|
|
1585
1813
|
)
|
|
1586
1814
|
).orderBy(desc2(juniorConversationEvents.seq)).limit(1);
|
|
1587
1815
|
return row ? eventFromRow(row) : void 0;
|
|
1588
1816
|
}
|
|
1589
1817
|
async loadMessageHistory(conversationId) {
|
|
1590
1818
|
const [compactionRow] = await this.executor.db().select().from(juniorConversationEvents).where(
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1819
|
+
and6(
|
|
1820
|
+
eq6(juniorConversationEvents.conversationId, conversationId),
|
|
1821
|
+
eq6(juniorConversationEvents.type, "messages_summarized")
|
|
1594
1822
|
)
|
|
1595
1823
|
).orderBy(desc2(juniorConversationEvents.seq)).limit(1);
|
|
1596
1824
|
const compaction = compactionRow ? messagesSummarizedEventFromRow(compactionRow) : void 0;
|
|
1597
1825
|
const historyFromSeq = compaction?.data.historyFromSeq ?? 0;
|
|
1598
1826
|
const rows = await this.executor.db().select().from(juniorConversationEvents).where(
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1827
|
+
and6(
|
|
1828
|
+
eq6(juniorConversationEvents.conversationId, conversationId),
|
|
1829
|
+
inArray2(juniorConversationEvents.type, messageHistoryEventTypes),
|
|
1602
1830
|
gte(juniorConversationEvents.seq, historyFromSeq)
|
|
1603
1831
|
)
|
|
1604
1832
|
).orderBy(asc2(juniorConversationEvents.seq));
|
|
1605
1833
|
return { events: rows.map(eventFromRow), compaction, historyFromSeq };
|
|
1606
1834
|
}
|
|
1607
1835
|
async loadHistory(conversationId) {
|
|
1608
|
-
const rows = await this.executor.db().select().from(juniorConversationEvents).where(
|
|
1836
|
+
const rows = await this.executor.db().select().from(juniorConversationEvents).where(eq6(juniorConversationEvents.conversationId, conversationId)).orderBy(asc2(juniorConversationEvents.seq));
|
|
1609
1837
|
return rows.map(eventFromRow);
|
|
1610
1838
|
}
|
|
1611
1839
|
async query(conversationId, query) {
|
|
@@ -1615,9 +1843,9 @@ var SqlConversationEventStore = class {
|
|
|
1615
1843
|
if (query.afterSeq !== void 0 && query.beforeSeq !== void 0 && query.afterSeq >= query.beforeSeq) {
|
|
1616
1844
|
return { events: [], hasOlder: false, hasNewer: false };
|
|
1617
1845
|
}
|
|
1618
|
-
const typeFilter = query.types && query.types.length > 0 ?
|
|
1619
|
-
const bounds =
|
|
1620
|
-
|
|
1846
|
+
const typeFilter = query.types && query.types.length > 0 ? inArray2(juniorConversationEvents.type, [...query.types]) : void 0;
|
|
1847
|
+
const bounds = and6(
|
|
1848
|
+
eq6(juniorConversationEvents.conversationId, conversationId),
|
|
1621
1849
|
query.afterSeq === void 0 ? void 0 : gt(juniorConversationEvents.seq, query.afterSeq),
|
|
1622
1850
|
query.beforeSeq === void 0 ? void 0 : lt(juniorConversationEvents.seq, query.beforeSeq),
|
|
1623
1851
|
typeFilter
|
|
@@ -1654,8 +1882,8 @@ var SqlConversationEventStore = class {
|
|
|
1654
1882
|
return false;
|
|
1655
1883
|
}
|
|
1656
1884
|
const [row] = await this.executor.db().select({ seq: juniorConversationEvents.seq }).from(juniorConversationEvents).where(
|
|
1657
|
-
|
|
1658
|
-
|
|
1885
|
+
and6(
|
|
1886
|
+
eq6(juniorConversationEvents.conversationId, args.conversationId),
|
|
1659
1887
|
args.afterSeq === void 0 ? void 0 : gt(juniorConversationEvents.seq, args.afterSeq),
|
|
1660
1888
|
args.beforeSeq === void 0 ? void 0 : lt(juniorConversationEvents.seq, args.beforeSeq),
|
|
1661
1889
|
args.typeFilter
|
|
@@ -1666,9 +1894,9 @@ var SqlConversationEventStore = class {
|
|
|
1666
1894
|
/** Read the next sequence and active model-history version. */
|
|
1667
1895
|
async readCursor(conversationId) {
|
|
1668
1896
|
const rows = await this.executor.db().select({
|
|
1669
|
-
maxSeq:
|
|
1670
|
-
maxHistoryVersion:
|
|
1671
|
-
}).from(juniorConversationEvents).where(
|
|
1897
|
+
maxSeq: sql6`max(${juniorConversationEvents.seq})`,
|
|
1898
|
+
maxHistoryVersion: sql6`max(${juniorConversationEvents.historyVersion})`
|
|
1899
|
+
}).from(juniorConversationEvents).where(eq6(juniorConversationEvents.conversationId, conversationId));
|
|
1672
1900
|
const maxSeq = rows[0]?.maxSeq;
|
|
1673
1901
|
const maxHistoryVersion = rows[0]?.maxHistoryVersion;
|
|
1674
1902
|
return {
|
|
@@ -1682,7 +1910,7 @@ function createSqlConversationEventStore(executor) {
|
|
|
1682
1910
|
}
|
|
1683
1911
|
|
|
1684
1912
|
// src/chat/conversations/sql/message-search.ts
|
|
1685
|
-
import { and as
|
|
1913
|
+
import { and as and7, desc as desc3, eq as eq7, isNull as isNull2, ne, sql as sql7 } from "drizzle-orm";
|
|
1686
1914
|
var EXCERPT_WITHOUT_QUERY_CHARS = 240;
|
|
1687
1915
|
var SqlConversationMessageSearchStore = class {
|
|
1688
1916
|
constructor(executor) {
|
|
@@ -1692,29 +1920,29 @@ var SqlConversationMessageSearchStore = class {
|
|
|
1692
1920
|
async search(args) {
|
|
1693
1921
|
const db = this.executor.db();
|
|
1694
1922
|
const query = args.filters.query?.trim() || void 0;
|
|
1695
|
-
const text =
|
|
1696
|
-
const role =
|
|
1697
|
-
const messageId =
|
|
1698
|
-
const tsquery = query ?
|
|
1699
|
-
const rank = tsquery ?
|
|
1700
|
-
const excerpt = tsquery ?
|
|
1923
|
+
const text = sql7`${juniorConversationEvents.payload}->>'text'`;
|
|
1924
|
+
const role = sql7`${juniorConversationEvents.payload}->>'role'`;
|
|
1925
|
+
const messageId = sql7`${juniorConversationEvents.payload}->>'messageId'`;
|
|
1926
|
+
const tsquery = query ? sql7`websearch_to_tsquery('english', ${query})` : void 0;
|
|
1927
|
+
const rank = tsquery ? sql7`ts_rank_cd(to_tsvector('english', ${text}), ${tsquery})` : sql7`1`;
|
|
1928
|
+
const excerpt = tsquery ? sql7`ts_headline('english', ${text}, ${tsquery}, 'MaxFragments=2, MinWords=8, MaxWords=40, FragmentDelimiter=" … ", StartSel=**, StopSel=**')` : sql7`left(${text}, ${EXCERPT_WITHOUT_QUERY_CHARS})`;
|
|
1701
1929
|
const conditions = [
|
|
1702
|
-
|
|
1930
|
+
eq7(juniorConversations.source, "slack"),
|
|
1703
1931
|
isNull2(juniorConversations.parentConversationId),
|
|
1704
1932
|
isNull2(juniorConversations.transcriptPurgedAt),
|
|
1705
1933
|
ne(juniorConversations.conversationId, args.currentConversationId),
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1934
|
+
eq7(juniorDestinations.provider, args.scope.provider),
|
|
1935
|
+
eq7(juniorDestinations.providerTenantId, args.scope.providerTenantId),
|
|
1936
|
+
eq7(juniorDestinations.visibility, "public"),
|
|
1937
|
+
eq7(juniorConversationEvents.type, "message"),
|
|
1938
|
+
sql7`${role} in ('user', 'assistant')`
|
|
1711
1939
|
];
|
|
1712
1940
|
if (tsquery) {
|
|
1713
|
-
conditions.push(
|
|
1941
|
+
conditions.push(sql7`to_tsvector('english', ${text}) @@ ${tsquery}`);
|
|
1714
1942
|
}
|
|
1715
1943
|
if (args.filters.channelId) {
|
|
1716
1944
|
conditions.push(
|
|
1717
|
-
|
|
1945
|
+
eq7(juniorDestinations.providerDestinationId, args.filters.channelId)
|
|
1718
1946
|
);
|
|
1719
1947
|
}
|
|
1720
1948
|
const bestPerConversation = db.selectDistinctOn([juniorConversations.conversationId], {
|
|
@@ -1729,14 +1957,14 @@ var SqlConversationMessageSearchStore = class {
|
|
|
1729
1957
|
role: role.as("role")
|
|
1730
1958
|
}).from(juniorConversationEvents).innerJoin(
|
|
1731
1959
|
juniorConversations,
|
|
1732
|
-
|
|
1960
|
+
eq7(
|
|
1733
1961
|
juniorConversations.conversationId,
|
|
1734
1962
|
juniorConversationEvents.conversationId
|
|
1735
1963
|
)
|
|
1736
1964
|
).innerJoin(
|
|
1737
1965
|
juniorDestinations,
|
|
1738
|
-
|
|
1739
|
-
).where(
|
|
1966
|
+
eq7(juniorDestinations.id, juniorConversations.destinationId)
|
|
1967
|
+
).where(and7(...conditions)).orderBy(
|
|
1740
1968
|
juniorConversations.conversationId,
|
|
1741
1969
|
desc3(rank),
|
|
1742
1970
|
desc3(juniorConversationEvents.createdAt)
|
|
@@ -1771,22 +1999,22 @@ function createDb(args) {
|
|
|
1771
1999
|
});
|
|
1772
2000
|
}
|
|
1773
2001
|
function getSqlExecutor() {
|
|
1774
|
-
const { sql:
|
|
1775
|
-
if (current?.databaseUrl !==
|
|
2002
|
+
const { sql: sql8 } = getChatConfig();
|
|
2003
|
+
if (current?.databaseUrl !== sql8.databaseUrl || current.driver !== sql8.driver || current.statementTimeoutMs !== sql8.statementTimeoutMs) {
|
|
1776
2004
|
if (current) {
|
|
1777
2005
|
const previous = current;
|
|
1778
2006
|
current = void 0;
|
|
1779
2007
|
void previous.db.close().catch(() => void 0);
|
|
1780
2008
|
}
|
|
1781
2009
|
const db = createDb({
|
|
1782
|
-
databaseUrl:
|
|
1783
|
-
driver:
|
|
1784
|
-
statementTimeoutMs:
|
|
2010
|
+
databaseUrl: sql8.databaseUrl,
|
|
2011
|
+
driver: sql8.driver,
|
|
2012
|
+
statementTimeoutMs: sql8.statementTimeoutMs
|
|
1785
2013
|
});
|
|
1786
2014
|
current = {
|
|
1787
|
-
databaseUrl:
|
|
1788
|
-
driver:
|
|
1789
|
-
statementTimeoutMs:
|
|
2015
|
+
databaseUrl: sql8.databaseUrl,
|
|
2016
|
+
driver: sql8.driver,
|
|
2017
|
+
statementTimeoutMs: sql8.statementTimeoutMs,
|
|
1790
2018
|
db,
|
|
1791
2019
|
store: createSqlStore(db),
|
|
1792
2020
|
eventStore: createSqlConversationEventStore(db),
|