@sentry/junior 0.105.0 → 0.107.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-EOFSY2PD.js → agent-hooks-ICPIJAFY.js} +9 -7
- package/dist/api/conversations/detail.d.ts +1 -1
- package/dist/api/conversations/events.d.ts +14 -0
- package/dist/api/conversations/schema.d.ts +196 -463
- package/dist/api/schema.d.ts +2 -7
- package/dist/api/schema.js +10 -8
- package/dist/api.js +377 -810
- package/dist/app.js +2284 -2288
- package/dist/{catalog-runtime-5CVM2DOF.js → catalog-runtime-FOFNPR3P.js} +3 -2
- package/dist/chat/agent/prompt.d.ts +1 -1
- package/dist/chat/agent/request.d.ts +28 -29
- package/dist/chat/agent/resume.d.ts +7 -7
- package/dist/chat/agent/session.d.ts +5 -6
- package/dist/chat/agent/tools.d.ts +3 -3
- package/dist/chat/agent-dispatch/runner.d.ts +2 -0
- package/dist/chat/config.d.ts +3 -2
- package/dist/chat/conversations/history.d.ts +582 -167
- package/dist/chat/conversations/message-projection.d.ts +6 -0
- package/dist/chat/conversations/message-summaries.d.ts +9 -0
- package/dist/chat/conversations/messages.d.ts +13 -27
- package/dist/chat/conversations/projection.d.ts +30 -53
- package/dist/chat/conversations/provenance.d.ts +42 -0
- package/dist/chat/conversations/search.d.ts +2 -2
- package/dist/chat/conversations/sql/conversation-row.d.ts +1 -1
- package/dist/chat/conversations/sql/event-lock.d.ts +3 -0
- package/dist/chat/conversations/sql/history.d.ts +3 -3
- package/dist/chat/conversations/sql/privacy.d.ts +27 -0
- package/dist/chat/conversations/sql/purge.d.ts +2 -10
- package/dist/chat/conversations/sql/store.d.ts +0 -5
- package/dist/chat/conversations/store.d.ts +8 -13
- package/dist/chat/conversations/turn-lifecycle.d.ts +41 -0
- package/dist/chat/db.d.ts +4 -10
- package/dist/chat/model-profile.d.ts +10 -0
- package/dist/chat/oauth-flow.d.ts +0 -5
- package/dist/chat/pi/conversation-events.d.ts +33 -0
- package/dist/chat/pi/sql-model-usage.d.ts +10 -0
- package/dist/chat/plugins/agent-hooks.d.ts +4 -2
- package/dist/chat/resource-events/ingest.d.ts +0 -13
- package/dist/chat/runtime/delivered-turn-state.d.ts +1 -1
- package/dist/chat/runtime/generated-artifacts.d.ts +1 -1
- package/dist/chat/runtime/reply-executor.d.ts +2 -0
- package/dist/chat/runtime/slack-resume.d.ts +23 -28
- package/dist/chat/runtime/slack-runtime.d.ts +2 -0
- package/dist/chat/runtime/turn.d.ts +14 -1
- package/dist/chat/services/context-compaction-marker.d.ts +0 -1
- package/dist/chat/services/context-compaction.d.ts +1 -0
- package/dist/chat/services/conversation-memory.d.ts +9 -0
- package/dist/chat/services/plugin-auth-orchestration.d.ts +1 -4
- package/dist/chat/services/subscribed-decision.d.ts +1 -1
- package/dist/chat/services/turn-failure-response.d.ts +10 -3
- package/dist/chat/services/turn-limit.d.ts +6 -0
- package/dist/chat/services/turn-result.d.ts +7 -12
- package/dist/chat/services/{turn-reasoning-level.d.ts → turn-router.d.ts} +12 -8
- package/dist/chat/services/turn-session-record.d.ts +15 -17
- package/dist/chat/slack/adapter.d.ts +2 -2
- package/dist/chat/slack/errors.d.ts +2 -0
- package/dist/chat/slack/outbound.d.ts +0 -1
- package/dist/chat/slack/reply.d.ts +2 -8
- package/dist/chat/slack/tools/channel-capabilities.d.ts +2 -2
- package/dist/chat/slack/tools/{send-message.d.ts → send-files.d.ts} +27 -19
- package/dist/chat/state/conversation.d.ts +4 -4
- package/dist/chat/state/turn-id.d.ts +2 -0
- package/dist/chat/state/turn-session-keys.d.ts +6 -0
- package/dist/chat/state/turn-session.d.ts +11 -9
- package/dist/chat/task-execution/state.d.ts +6 -1
- package/dist/chat/task-execution/store.d.ts +1 -1
- package/dist/chat/tool-support/pi-tool-adapter.d.ts +1 -1
- package/dist/chat/tool-support/tool-execution-report.d.ts +1 -0
- package/dist/chat/tools/handoff/tool.d.ts +2 -2
- package/dist/chat/tools/sandbox/file-uploads.d.ts +28 -6
- package/dist/chat/tools/types.d.ts +6 -9
- package/dist/chat/tools/web/image-generate.d.ts +4 -6
- package/dist/{chunk-QDKRE3LS.js → chunk-4YF7Z6IA.js} +390 -270
- package/dist/{chunk-4PDVOHXP.js → chunk-AUUOHQAT.js} +2 -2
- package/dist/chunk-B2Z2H66D.js +250 -0
- package/dist/{chunk-QVTVCJR4.js → chunk-CQ7KSO2B.js} +75 -45
- package/dist/{chunk-MJSJAHBW.js → chunk-DY7TRYB5.js} +1 -1
- package/dist/{chunk-NJJFU6CP.js → chunk-EDLNHZH3.js} +883 -898
- package/dist/{chunk-O7ILGCMJ.js → chunk-IGHMVDWI.js} +134 -18
- package/dist/chunk-MU6HHZEN.js +99 -0
- package/dist/{chunk-BCULHGZK.js → chunk-NVOTGWYX.js} +458 -684
- package/dist/{chunk-AEWZ7F65.js → chunk-O24R4DCK.js} +2 -179
- package/dist/{chunk-CCFROYAV.js → chunk-PUAMO4PI.js} +115 -125
- package/dist/{chunk-VDHMFCDY.js → chunk-RMVOAJRL.js} +30 -13
- package/dist/{chunk-7G4J3CR7.js → chunk-SPUAJVVH.js} +6 -4
- package/dist/{chunk-M3UAVLEN.js → chunk-SS67LUOK.js} +43 -290
- package/dist/{chunk-FXFQNHRU.js → chunk-VFUK3X5B.js} +4 -2
- package/dist/{chunk-CCTCIISK.js → chunk-VH6KWKG2.js} +2 -2
- package/dist/chunk-VIXFG2VC.js +182 -0
- package/dist/{chunk-RMZ65YAA.js → chunk-YFQ7CQDE.js} +687 -21
- package/dist/{chunk-77LHNQK4.js → chunk-YIPD3L6L.js} +4 -2
- package/dist/{chunk-U26ZWZCN.js → chunk-YNP2ATQX.js} +6 -4
- package/dist/{chunk-WR7H7VLJ.js → chunk-YT72TOEK.js} +2 -2
- package/dist/cli/chat.js +21 -20
- package/dist/cli/check.js +4 -3
- package/dist/cli/plugins.js +11 -9
- package/dist/cli/snapshot-warmup.js +7 -5
- package/dist/cli/upgrade.js +2046 -105
- package/dist/db/schema/{agent-steps.d.ts → conversation-events.d.ts} +37 -21
- package/dist/db/schema.d.ts +28 -159
- package/dist/{db-PDMC67T3.js → db-DIGO4TGW.js} +6 -8
- package/dist/{runner-6A7MQRUE.js → runner-ACR2HAIC.js} +209 -101
- package/dist/{skills-722AXRV5.js → skills-ITNHBARB.js} +4 -3
- package/dist/{validation-EUI2UFRM.js → validation-AGQ46ZGV.js} +4 -3
- package/migrations/0005_conversation_events.sql +122 -0
- package/migrations/README.md +23 -10
- package/migrations/meta/0005_snapshot.json +948 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +6 -6
- package/dist/api/conversations/activity.d.ts +0 -40
- package/dist/api/conversations/detail-projection.d.ts +0 -11
- package/dist/api/conversations/detail.query.d.ts +0 -3
- package/dist/api/conversations/subagent.d.ts +0 -10
- package/dist/api/conversations/transcript.d.ts +0 -28
- package/dist/chat/conversations/legacy-advisor-session.d.ts +0 -7
- package/dist/chat/conversations/legacy-import.d.ts +0 -38
- package/dist/chat/conversations/sql/legacy-history-import.d.ts +0 -55
- package/dist/chat/conversations/sql/messages.d.ts +0 -4
- package/dist/chat/conversations/visible-compactions.d.ts +0 -11
- package/dist/chat/conversations/visible-messages.d.ts +0 -47
- package/dist/chat/services/reply-delivery-plan.d.ts +0 -5
- package/dist/chat/state/session-log.d.ts +0 -384
- package/dist/chunk-RYDF4GOX.js +0 -1072
- package/dist/chunk-XIMUQ4IU.js +0 -147
- package/dist/db/schema/conversation-messages.d.ts +0 -153
- package/dist/handlers/github-webhook/check-suite.d.ts +0 -3
- package/dist/handlers/github-webhook/issue-comment.d.ts +0 -3
- package/dist/handlers/github-webhook/pull-request-review-comment.d.ts +0 -3
- package/dist/handlers/github-webhook/pull-request-review.d.ts +0 -3
- package/dist/handlers/github-webhook/pull-request.d.ts +0 -3
- package/dist/handlers/github-webhook/resource.d.ts +0 -10
- package/dist/handlers/github-webhook.d.ts +0 -15
- package/dist/legacy-import-G333RHJZ.js +0 -18
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getChatConfig,
|
|
3
|
-
getConnectedStateContext,
|
|
4
|
-
getStateAdapter,
|
|
5
3
|
modelProfileSchema
|
|
6
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SS67LUOK.js";
|
|
7
5
|
import {
|
|
8
6
|
juniorDestinations,
|
|
9
7
|
timestamptz
|
|
10
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-VFUK3X5B.js";
|
|
11
9
|
import {
|
|
12
10
|
parseDestination,
|
|
13
11
|
sameDestination
|
|
14
12
|
} from "./chunk-B7PUBQQM.js";
|
|
15
13
|
import {
|
|
16
|
-
normalizeIdentityEmail
|
|
17
|
-
|
|
18
|
-
} from "./chunk-AEWZ7F65.js";
|
|
14
|
+
normalizeIdentityEmail
|
|
15
|
+
} from "./chunk-O24R4DCK.js";
|
|
19
16
|
|
|
20
17
|
// src/chat/conversations/sql/store.ts
|
|
21
18
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
@@ -25,15 +22,18 @@ import { and as and2, asc, desc, eq as eq2, isNull, sql as sql5 } from "drizzle-
|
|
|
25
22
|
import { randomUUID } from "crypto";
|
|
26
23
|
import { and, eq, sql as sql4 } from "drizzle-orm";
|
|
27
24
|
|
|
28
|
-
// src/db/schema/
|
|
25
|
+
// src/db/schema/conversation-events.ts
|
|
29
26
|
import {
|
|
27
|
+
foreignKey,
|
|
30
28
|
index as index3,
|
|
31
29
|
integer as integer2,
|
|
32
30
|
jsonb as jsonb3,
|
|
33
31
|
pgTable as pgTable4,
|
|
34
32
|
primaryKey,
|
|
35
|
-
text as text4
|
|
33
|
+
text as text4,
|
|
34
|
+
uniqueIndex as uniqueIndex3
|
|
36
35
|
} from "drizzle-orm/pg-core";
|
|
36
|
+
import { sql as sql3 } from "drizzle-orm";
|
|
37
37
|
|
|
38
38
|
// src/db/schema/conversations.ts
|
|
39
39
|
import { sql as sql2 } from "drizzle-orm";
|
|
@@ -183,62 +183,50 @@ var juniorConversations = pgTable3(
|
|
|
183
183
|
]
|
|
184
184
|
);
|
|
185
185
|
|
|
186
|
-
// src/db/schema/
|
|
187
|
-
var
|
|
188
|
-
"
|
|
186
|
+
// src/db/schema/conversation-events.ts
|
|
187
|
+
var juniorConversationEvents = pgTable4(
|
|
188
|
+
"junior_conversation_events",
|
|
189
189
|
{
|
|
190
|
-
conversationId: text4("conversation_id").notNull()
|
|
190
|
+
conversationId: text4("conversation_id").notNull(),
|
|
191
191
|
seq: integer2("seq").notNull(),
|
|
192
|
-
|
|
192
|
+
historyVersion: integer2("history_version").notNull(),
|
|
193
|
+
schemaVersion: integer2("schema_version").default(1).notNull(),
|
|
194
|
+
idempotencyKey: text4("idempotency_key"),
|
|
193
195
|
type: text4("type").notNull(),
|
|
194
|
-
role: text4("role"),
|
|
195
196
|
payload: jsonb3("payload").$type().notNull(),
|
|
196
197
|
createdAt: timestamptz("created_at").notNull()
|
|
197
198
|
},
|
|
198
199
|
(table) => [
|
|
199
|
-
primaryKey({
|
|
200
|
-
|
|
200
|
+
primaryKey({
|
|
201
|
+
name: "junior_conversation_events_conversation_id_seq_pk",
|
|
202
|
+
columns: [table.conversationId, table.seq]
|
|
203
|
+
}),
|
|
204
|
+
foreignKey({
|
|
205
|
+
name: "junior_conversation_events_conversation_id_junior_conversations_conversation_id_fk",
|
|
206
|
+
columns: [table.conversationId],
|
|
207
|
+
foreignColumns: [juniorConversations.conversationId]
|
|
208
|
+
}),
|
|
209
|
+
index3("junior_conversation_events_history_version_idx").on(
|
|
201
210
|
table.conversationId,
|
|
202
|
-
table.
|
|
211
|
+
table.historyVersion,
|
|
203
212
|
table.seq
|
|
204
|
-
)
|
|
205
|
-
]
|
|
206
|
-
);
|
|
207
|
-
|
|
208
|
-
// src/db/schema/conversation-messages.ts
|
|
209
|
-
import { sql as sql3 } from "drizzle-orm";
|
|
210
|
-
import { index as index4, jsonb as jsonb4, pgTable as pgTable5, primaryKey as primaryKey2, text as text5 } from "drizzle-orm/pg-core";
|
|
211
|
-
var juniorConversationMessages = pgTable5(
|
|
212
|
-
"junior_conversation_messages",
|
|
213
|
-
{
|
|
214
|
-
conversationId: text5("conversation_id").notNull().references(() => juniorConversations.conversationId),
|
|
215
|
-
messageId: text5("message_id").notNull(),
|
|
216
|
-
role: text5("role").$type().notNull(),
|
|
217
|
-
authorIdentityId: text5("author_identity_id").references(
|
|
218
|
-
() => juniorIdentities.id
|
|
219
213
|
),
|
|
220
|
-
|
|
221
|
-
meta: jsonb4("meta").$type(),
|
|
222
|
-
repliedAt: timestamptz("replied_at"),
|
|
223
|
-
createdAt: timestamptz("created_at").notNull()
|
|
224
|
-
},
|
|
225
|
-
(table) => [
|
|
226
|
-
primaryKey2({ columns: [table.conversationId, table.messageId] }),
|
|
227
|
-
index4("junior_conversation_messages_activity_idx").on(
|
|
214
|
+
index3("junior_conversation_events_type_idx").on(
|
|
228
215
|
table.conversationId,
|
|
229
|
-
table.
|
|
216
|
+
table.type,
|
|
217
|
+
table.seq
|
|
230
218
|
),
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
219
|
+
index3("junior_conversation_events_message_search_idx").using("gin", sql3`to_tsvector('english', ${table.payload}->>'text')`).where(sql3`${table.type} = 'message'`),
|
|
220
|
+
uniqueIndex3("junior_conversation_events_idempotency_idx").on(
|
|
221
|
+
table.conversationId,
|
|
222
|
+
table.idempotencyKey
|
|
234
223
|
)
|
|
235
224
|
]
|
|
236
225
|
);
|
|
237
226
|
|
|
238
227
|
// src/db/schema.ts
|
|
239
228
|
var juniorSqlSchema = {
|
|
240
|
-
|
|
241
|
-
juniorConversationMessages,
|
|
229
|
+
juniorConversationEvents,
|
|
242
230
|
juniorConversations,
|
|
243
231
|
juniorDestinations,
|
|
244
232
|
juniorIdentities,
|
|
@@ -536,6 +524,11 @@ function conversationFromRow(readRow) {
|
|
|
536
524
|
lastActivityAtMs: requiredMsFromDate(row.lastActivityAt),
|
|
537
525
|
updatedAtMs: requiredMsFromDate(row.updatedAt),
|
|
538
526
|
execution,
|
|
527
|
+
...row.parentConversationId ? {
|
|
528
|
+
lineage: {
|
|
529
|
+
parentConversationId: row.parentConversationId
|
|
530
|
+
}
|
|
531
|
+
} : {},
|
|
539
532
|
...destination ? { destination } : {},
|
|
540
533
|
...actor ? { actor } : {},
|
|
541
534
|
...msFromDate(row.archivedAt) !== void 0 ? { archivedAtMs: msFromDate(row.archivedAt) } : {},
|
|
@@ -715,31 +708,6 @@ var SqlStore = class {
|
|
|
715
708
|
}
|
|
716
709
|
});
|
|
717
710
|
}
|
|
718
|
-
async ensureChildConversation(args) {
|
|
719
|
-
const at = dateFromMs2(args.nowMs ?? now());
|
|
720
|
-
await this.executor.db().insert(juniorConversations).values({
|
|
721
|
-
conversationId: args.parentConversationId,
|
|
722
|
-
schemaVersion: 1,
|
|
723
|
-
createdAt: at,
|
|
724
|
-
lastActivityAt: at,
|
|
725
|
-
updatedAt: at,
|
|
726
|
-
executionStatus: "idle"
|
|
727
|
-
}).onConflictDoNothing({ target: juniorConversations.conversationId });
|
|
728
|
-
await this.executor.db().insert(juniorConversations).values({
|
|
729
|
-
conversationId: args.conversationId,
|
|
730
|
-
schemaVersion: 1,
|
|
731
|
-
parentConversationId: args.parentConversationId,
|
|
732
|
-
createdAt: at,
|
|
733
|
-
lastActivityAt: at,
|
|
734
|
-
updatedAt: at,
|
|
735
|
-
executionStatus: "idle"
|
|
736
|
-
}).onConflictDoUpdate({
|
|
737
|
-
target: juniorConversations.conversationId,
|
|
738
|
-
set: {
|
|
739
|
-
parentConversationId: sql5`coalesce(${juniorConversations.parentConversationId}, excluded.parent_conversation_id)`
|
|
740
|
-
}
|
|
741
|
-
});
|
|
742
|
-
}
|
|
743
711
|
/** Copy one conversation record and retained metrics into SQL during backfill. */
|
|
744
712
|
async backfillConversation(sourceConversation, metrics) {
|
|
745
713
|
const { visibility: _visibility, ...conversation } = sourceConversation;
|
|
@@ -904,7 +872,8 @@ var SqlStore = class {
|
|
|
904
872
|
executionStatus: conversation.execution.status,
|
|
905
873
|
runId: conversation.execution.runId ?? null,
|
|
906
874
|
lastCheckpointAt: conversation.execution.lastCheckpointAtMs === void 0 ? null : dateFromMs2(conversation.execution.lastCheckpointAtMs),
|
|
907
|
-
lastEnqueuedAt: conversation.execution.lastEnqueuedAtMs === void 0 ? null : dateFromMs2(conversation.execution.lastEnqueuedAtMs)
|
|
875
|
+
lastEnqueuedAt: conversation.execution.lastEnqueuedAtMs === void 0 ? null : dateFromMs2(conversation.execution.lastEnqueuedAtMs),
|
|
876
|
+
parentConversationId: conversation.lineage?.parentConversationId ?? null
|
|
908
877
|
}).onConflictDoUpdate({
|
|
909
878
|
target: juniorConversations.conversationId,
|
|
910
879
|
set: {
|
|
@@ -971,99 +940,115 @@ function createSqlStore(executor) {
|
|
|
971
940
|
}
|
|
972
941
|
|
|
973
942
|
// src/chat/conversations/sql/history.ts
|
|
974
|
-
import {
|
|
943
|
+
import {
|
|
944
|
+
and as and3,
|
|
945
|
+
asc as asc2,
|
|
946
|
+
desc as desc2,
|
|
947
|
+
eq as eq3,
|
|
948
|
+
gte,
|
|
949
|
+
inArray,
|
|
950
|
+
isNotNull,
|
|
951
|
+
lte,
|
|
952
|
+
sql as sql7
|
|
953
|
+
} from "drizzle-orm";
|
|
975
954
|
|
|
976
955
|
// src/chat/conversations/history.ts
|
|
977
|
-
import { z as z3 } from "zod";
|
|
978
|
-
|
|
979
|
-
// src/chat/pi/messages.ts
|
|
980
|
-
import { z } from "zod";
|
|
981
|
-
var piMessageSchema = z.object({
|
|
982
|
-
role: z.string()
|
|
983
|
-
}).passthrough().transform((value) => value);
|
|
984
|
-
var piContentMessageSchema = z.object({
|
|
985
|
-
content: z.array(z.unknown()),
|
|
986
|
-
role: z.string().min(1)
|
|
987
|
-
}).passthrough().transform((value) => value);
|
|
988
|
-
|
|
989
|
-
// src/chat/state/session-log.ts
|
|
990
|
-
import { isDeepStrictEqual } from "util";
|
|
991
956
|
import { z as z2 } from "zod";
|
|
957
|
+
|
|
958
|
+
// src/chat/conversations/provenance.ts
|
|
992
959
|
import { actorSchema } from "@sentry/junior-plugin-api";
|
|
993
|
-
|
|
994
|
-
var
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
var schemaVersionSchema = z2.union([z2.literal(1), z2.literal(2)]);
|
|
998
|
-
var piMessageAuthoritySchema = z2.union([
|
|
999
|
-
z2.literal("instruction"),
|
|
1000
|
-
z2.literal("context")
|
|
960
|
+
import { z } from "zod";
|
|
961
|
+
var conversationMessageAuthoritySchema = z.union([
|
|
962
|
+
z.literal("instruction"),
|
|
963
|
+
z.literal("context")
|
|
1001
964
|
]);
|
|
1002
|
-
var
|
|
1003
|
-
authority:
|
|
965
|
+
var conversationMessageProvenanceSchema = z.object({
|
|
966
|
+
authority: conversationMessageAuthoritySchema,
|
|
1004
967
|
actor: actorSchema.optional()
|
|
1005
968
|
}).strict();
|
|
1006
|
-
|
|
1007
|
-
authority: "context"
|
|
1008
|
-
};
|
|
1009
|
-
function instructionProvenance(actor) {
|
|
969
|
+
function instructionProvenanceFor(actor) {
|
|
1010
970
|
return actor ? { authority: "instruction", actor } : { authority: "instruction" };
|
|
1011
971
|
}
|
|
1012
|
-
|
|
1013
|
-
|
|
972
|
+
var contextProvenance = {
|
|
973
|
+
authority: "context"
|
|
974
|
+
};
|
|
975
|
+
function actorIdentityKey(actor) {
|
|
976
|
+
if (actor.platform === "system") {
|
|
977
|
+
return `system ${actor.name}`;
|
|
978
|
+
}
|
|
979
|
+
return actor.platform === "slack" ? `slack\0${actor.teamId}\0${actor.userId}` : `${actor.platform}\0${actor.userId}`;
|
|
1014
980
|
}
|
|
1015
|
-
function
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
981
|
+
function instructionActors(provenance) {
|
|
982
|
+
const seen = /* @__PURE__ */ new Set();
|
|
983
|
+
const actors = [];
|
|
984
|
+
for (const entry of provenance) {
|
|
985
|
+
if (entry.authority !== "instruction" || !entry.actor) {
|
|
986
|
+
continue;
|
|
987
|
+
}
|
|
988
|
+
const identity = actorIdentityKey(entry.actor);
|
|
989
|
+
if (seen.has(identity)) {
|
|
990
|
+
continue;
|
|
991
|
+
}
|
|
992
|
+
seen.add(identity);
|
|
993
|
+
actors.push(entry.actor);
|
|
1025
994
|
}
|
|
1026
|
-
return
|
|
995
|
+
return actors;
|
|
1027
996
|
}
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
messages: z2.array(piMessageSchema),
|
|
1042
|
-
provenance: z2.array(piMessageProvenanceSchema).optional(),
|
|
1043
|
-
// Legacy v1 latest-wins actor; v1 resets carry no per-message provenance.
|
|
1044
|
-
actor: storedSlackActorSchema.optional()
|
|
997
|
+
|
|
998
|
+
// src/chat/conversations/history.ts
|
|
999
|
+
var handoffModelProfileSchema = modelProfileSchema.refine(
|
|
1000
|
+
(profile) => profile !== "standard",
|
|
1001
|
+
"handoff profile must not be standard"
|
|
1002
|
+
);
|
|
1003
|
+
var conversationAgentStepPayloadSchema = z2.object({ role: z2.string() }).passthrough().transform((value) => value);
|
|
1004
|
+
var conversationMessageDataSchema = z2.object({
|
|
1005
|
+
message: conversationAgentStepPayloadSchema,
|
|
1006
|
+
provenance: conversationMessageProvenanceSchema.optional()
|
|
1007
|
+
}).strict();
|
|
1008
|
+
var agentStepEventDataSchema = conversationMessageDataSchema.extend({
|
|
1009
|
+
type: z2.literal("agent_step")
|
|
1045
1010
|
});
|
|
1046
|
-
var
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
actor: storedSlackActorSchema
|
|
1011
|
+
var replacementHistoryMessageSchema = conversationMessageDataSchema.extend({
|
|
1012
|
+
// Preserve the copied message's position when a turn resumes. Synthetic
|
|
1013
|
+
// summary and handoff messages have no source event.
|
|
1014
|
+
sourceEventSeq: z2.number().int().nonnegative().optional()
|
|
1051
1015
|
});
|
|
1052
|
-
var
|
|
1053
|
-
|
|
1016
|
+
var replacementHistorySchema = z2.array(replacementHistoryMessageSchema);
|
|
1017
|
+
var historyReplacementEventDataSchema = z2.discriminatedUnion("type", [
|
|
1018
|
+
z2.object({
|
|
1019
|
+
type: z2.literal("handoff"),
|
|
1020
|
+
modelProfile: handoffModelProfileSchema,
|
|
1021
|
+
modelId: z2.string().min(1),
|
|
1022
|
+
triggeringToolCallId: z2.string().min(1).optional(),
|
|
1023
|
+
replacementHistory: replacementHistorySchema
|
|
1024
|
+
}).strict(),
|
|
1025
|
+
z2.object({
|
|
1026
|
+
type: z2.literal("compaction"),
|
|
1027
|
+
modelProfile: modelProfileSchema,
|
|
1028
|
+
modelId: z2.string().min(1),
|
|
1029
|
+
replacementHistory: replacementHistorySchema
|
|
1030
|
+
}).strict()
|
|
1031
|
+
]);
|
|
1032
|
+
var legacyRollbackEventDataSchema = z2.object({
|
|
1033
|
+
type: z2.literal("rollback"),
|
|
1034
|
+
modelProfile: modelProfileSchema,
|
|
1035
|
+
modelId: z2.string().min(1),
|
|
1036
|
+
replacementHistory: replacementHistorySchema
|
|
1037
|
+
}).strict();
|
|
1038
|
+
var historyReplacementSchema = z2.object({
|
|
1039
|
+
data: historyReplacementEventDataSchema,
|
|
1040
|
+
createdAtMs: z2.number().finite()
|
|
1041
|
+
}).strict();
|
|
1042
|
+
var mcpProviderConnectedEventDataSchema = z2.object({
|
|
1054
1043
|
type: z2.literal("mcp_provider_connected"),
|
|
1055
|
-
sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
|
|
1056
1044
|
provider: z2.string().min(1)
|
|
1057
|
-
});
|
|
1045
|
+
}).strict();
|
|
1058
1046
|
var authorizationKindSchema = z2.union([
|
|
1059
1047
|
z2.literal("plugin"),
|
|
1060
1048
|
z2.literal("mcp")
|
|
1061
1049
|
]);
|
|
1062
|
-
var
|
|
1063
|
-
schemaVersion: schemaVersionSchema,
|
|
1050
|
+
var authorizationRequestedEventDataSchema = z2.object({
|
|
1064
1051
|
type: z2.literal("authorization_requested"),
|
|
1065
|
-
sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
|
|
1066
|
-
createdAtMs: z2.number().int().nonnegative(),
|
|
1067
1052
|
kind: authorizationKindSchema,
|
|
1068
1053
|
provider: z2.string().min(1),
|
|
1069
1054
|
actorId: z2.string().min(1),
|
|
@@ -1072,366 +1057,184 @@ var authorizationRequestedEntrySchema = z2.object({
|
|
|
1072
1057
|
z2.literal("private_link_sent"),
|
|
1073
1058
|
z2.literal("private_link_reused")
|
|
1074
1059
|
])
|
|
1075
|
-
});
|
|
1076
|
-
var
|
|
1077
|
-
schemaVersion: schemaVersionSchema,
|
|
1060
|
+
}).strict();
|
|
1061
|
+
var authorizationCompletedEventDataSchema = z2.object({
|
|
1078
1062
|
type: z2.literal("authorization_completed"),
|
|
1079
|
-
sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
|
|
1080
|
-
createdAtMs: z2.number().int().nonnegative(),
|
|
1081
1063
|
kind: authorizationKindSchema,
|
|
1082
1064
|
provider: z2.string().min(1),
|
|
1083
1065
|
actorId: z2.string().min(1),
|
|
1084
1066
|
authorizationId: z2.string().min(1)
|
|
1085
|
-
});
|
|
1086
|
-
var
|
|
1087
|
-
type: z2.literal("advisor_session"),
|
|
1088
|
-
parentConversationId: z2.string().min(1),
|
|
1089
|
-
key: z2.string().min(1)
|
|
1090
|
-
});
|
|
1091
|
-
var toolExecutionStartedEntrySchema = z2.object({
|
|
1092
|
-
schemaVersion: schemaVersionSchema,
|
|
1067
|
+
}).strict();
|
|
1068
|
+
var toolExecutionStartedEventDataSchema = z2.object({
|
|
1093
1069
|
type: z2.literal("tool_execution_started"),
|
|
1094
|
-
sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
|
|
1095
|
-
createdAtMs: z2.number().int().nonnegative(),
|
|
1096
1070
|
toolCallId: z2.string().min(1),
|
|
1097
|
-
toolName: z2.string().min(1)
|
|
1098
|
-
|
|
1071
|
+
toolName: z2.string().min(1)
|
|
1072
|
+
}).strict();
|
|
1073
|
+
var conversationMessageRoleSchema = z2.union([
|
|
1074
|
+
z2.literal("user"),
|
|
1075
|
+
z2.literal("assistant"),
|
|
1076
|
+
z2.literal("system")
|
|
1077
|
+
]);
|
|
1078
|
+
var messageEventDataSchema = z2.object({
|
|
1079
|
+
type: z2.literal("message"),
|
|
1080
|
+
messageId: z2.string().min(1),
|
|
1081
|
+
role: conversationMessageRoleSchema,
|
|
1082
|
+
text: z2.string(),
|
|
1083
|
+
authorIdentityId: z2.string().min(1).optional(),
|
|
1084
|
+
meta: z2.record(z2.string(), z2.unknown()).optional()
|
|
1085
|
+
}).strict();
|
|
1086
|
+
var messageUpdatedEventDataSchema = messageEventDataSchema.extend({
|
|
1087
|
+
type: z2.literal("message_updated")
|
|
1099
1088
|
});
|
|
1100
|
-
var
|
|
1101
|
-
|
|
1089
|
+
var messageHandledEventDataSchema = z2.object({
|
|
1090
|
+
type: z2.literal("message_handled"),
|
|
1091
|
+
messageId: z2.string().min(1)
|
|
1092
|
+
}).strict();
|
|
1093
|
+
var messagesSummarizedEventDataSchema = z2.object({
|
|
1094
|
+
type: z2.literal("messages_summarized"),
|
|
1095
|
+
historyFromSeq: z2.number().int().nonnegative(),
|
|
1096
|
+
compactions: z2.array(
|
|
1097
|
+
z2.object({
|
|
1098
|
+
coveredMessageCount: z2.number().int().nonnegative(),
|
|
1099
|
+
createdAtMs: z2.number(),
|
|
1100
|
+
id: z2.string().min(1),
|
|
1101
|
+
summary: z2.string()
|
|
1102
|
+
}).strict()
|
|
1103
|
+
)
|
|
1104
|
+
}).strict();
|
|
1105
|
+
var conversationTurnSurfaceSchema = z2.enum([
|
|
1106
|
+
"slack",
|
|
1107
|
+
"api",
|
|
1108
|
+
"scheduler",
|
|
1109
|
+
"internal"
|
|
1110
|
+
]);
|
|
1111
|
+
var conversationTurnFailureCodeSchema = z2.enum([
|
|
1112
|
+
"agent_run_failed",
|
|
1113
|
+
"delivery_failed",
|
|
1114
|
+
"model_execution_failed",
|
|
1115
|
+
"persistence_failed"
|
|
1116
|
+
]);
|
|
1117
|
+
var turnStartedEventDataSchema = z2.object({
|
|
1118
|
+
type: z2.literal("turn_started"),
|
|
1119
|
+
turnId: z2.string().min(1),
|
|
1120
|
+
inputMessageIds: z2.array(z2.string().min(1)).min(1),
|
|
1121
|
+
surface: conversationTurnSurfaceSchema
|
|
1122
|
+
}).strict().refine(
|
|
1123
|
+
(data) => new Set(data.inputMessageIds).size === data.inputMessageIds.length,
|
|
1124
|
+
"turn input message ids must be unique"
|
|
1125
|
+
);
|
|
1126
|
+
var turnCompletedEventDataSchema = z2.object({
|
|
1127
|
+
type: z2.literal("turn_completed"),
|
|
1128
|
+
turnId: z2.string().min(1),
|
|
1129
|
+
outcome: z2.enum(["success", "no_reply"])
|
|
1130
|
+
}).strict();
|
|
1131
|
+
var turnFailedEventDataSchema = z2.object({
|
|
1132
|
+
type: z2.literal("turn_failed"),
|
|
1133
|
+
turnId: z2.string().min(1),
|
|
1134
|
+
failureCode: conversationTurnFailureCodeSchema,
|
|
1135
|
+
eventId: z2.string().regex(/^[a-f0-9]{32}$/i).optional()
|
|
1136
|
+
}).strict();
|
|
1137
|
+
var subagentStartedEventDataSchema = z2.object({
|
|
1102
1138
|
type: z2.literal("subagent_started"),
|
|
1103
|
-
sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
|
|
1104
1139
|
subagentInvocationId: z2.string().min(1),
|
|
1105
1140
|
subagentKind: z2.string().min(1),
|
|
1106
|
-
parentToolCallId: z2.string().min(1).optional(),
|
|
1107
|
-
parentConversationId: z2.string().min(1),
|
|
1108
|
-
parentSessionId: z2.string().min(1).optional(),
|
|
1109
|
-
transcriptRef: transcriptRefSchema,
|
|
1110
|
-
historyMode: z2.literal("shared"),
|
|
1111
1141
|
modelId: z2.string().min(1).optional(),
|
|
1142
|
+
parentToolCallId: z2.string().min(1).optional(),
|
|
1112
1143
|
reasoningLevel: z2.string().min(1).optional(),
|
|
1113
|
-
|
|
1114
|
-
});
|
|
1115
|
-
var
|
|
1116
|
-
schemaVersion: schemaVersionSchema,
|
|
1144
|
+
childConversationId: z2.string().min(1)
|
|
1145
|
+
}).strict();
|
|
1146
|
+
var subagentEndedEventDataSchema = z2.object({
|
|
1117
1147
|
type: z2.literal("subagent_ended"),
|
|
1118
|
-
sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
|
|
1119
1148
|
subagentInvocationId: z2.string().min(1),
|
|
1120
1149
|
outcome: z2.union([
|
|
1121
1150
|
z2.literal("success"),
|
|
1122
1151
|
z2.literal("error"),
|
|
1123
1152
|
z2.literal("aborted")
|
|
1124
1153
|
]),
|
|
1125
|
-
errorCode: z2.string().min(1).optional()
|
|
1126
|
-
transcriptEndMessageIndex: z2.number().int().nonnegative().optional(),
|
|
1127
|
-
transcriptStartMessageIndex: z2.number().int().nonnegative().optional(),
|
|
1128
|
-
createdAtMs: z2.number().int().nonnegative()
|
|
1129
|
-
});
|
|
1130
|
-
var sessionLogEntrySchema = z2.discriminatedUnion("type", [
|
|
1131
|
-
piMessageEntrySchema,
|
|
1132
|
-
projectionResetEntrySchema,
|
|
1133
|
-
actorRecordedEntrySchema,
|
|
1134
|
-
mcpProviderConnectedEntrySchema,
|
|
1135
|
-
authorizationRequestedEntrySchema,
|
|
1136
|
-
authorizationCompletedEntrySchema,
|
|
1137
|
-
toolExecutionStartedEntrySchema,
|
|
1138
|
-
subagentStartedEntrySchema,
|
|
1139
|
-
subagentEndedEntrySchema
|
|
1140
|
-
]);
|
|
1141
|
-
function key(scope) {
|
|
1142
|
-
const prefix = getChatConfig().state.keyPrefix;
|
|
1143
|
-
return [
|
|
1144
|
-
...prefix ? [prefix] : [],
|
|
1145
|
-
AGENT_SESSION_LOG_PREFIX,
|
|
1146
|
-
scope.conversationId
|
|
1147
|
-
].join(":");
|
|
1148
|
-
}
|
|
1149
|
-
function rawKey(scope) {
|
|
1150
|
-
return [AGENT_SESSION_LOG_PREFIX, scope.conversationId].join(":");
|
|
1151
|
-
}
|
|
1152
|
-
function storedRecord(value) {
|
|
1153
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
1154
|
-
}
|
|
1155
|
-
function migrateStoredEntry(value) {
|
|
1156
|
-
const record = storedRecord(value);
|
|
1157
|
-
if (!record) {
|
|
1158
|
-
return value;
|
|
1159
|
-
}
|
|
1160
|
-
const migrated = { ...record };
|
|
1161
|
-
if ("requester" in migrated && !("actor" in migrated)) {
|
|
1162
|
-
migrated.actor = migrated.requester;
|
|
1163
|
-
}
|
|
1164
|
-
delete migrated.requester;
|
|
1165
|
-
if (migrated.type === "requester_recorded") {
|
|
1166
|
-
migrated.type = "actor_recorded";
|
|
1167
|
-
}
|
|
1168
|
-
if ("requesterId" in migrated && !("actorId" in migrated)) {
|
|
1169
|
-
migrated.actorId = migrated.requesterId;
|
|
1170
|
-
}
|
|
1171
|
-
delete migrated.requesterId;
|
|
1172
|
-
return migrated;
|
|
1173
|
-
}
|
|
1174
|
-
function piEntry(message, sessionId, provenance) {
|
|
1175
|
-
return {
|
|
1176
|
-
schemaVersion: AGENT_SESSION_LOG_SCHEMA_VERSION,
|
|
1177
|
-
type: "pi_message",
|
|
1178
|
-
sessionId,
|
|
1179
|
-
message,
|
|
1180
|
-
// Ambient context is the decode default, so only attributed/instruction
|
|
1181
|
-
// provenance needs to be persisted on the entry.
|
|
1182
|
-
...provenance && !isDefaultContextProvenance(provenance) ? { provenance } : {}
|
|
1183
|
-
};
|
|
1184
|
-
}
|
|
1185
|
-
function decode(value) {
|
|
1186
|
-
if (typeof value === "string") {
|
|
1187
|
-
return decode(JSON.parse(value));
|
|
1188
|
-
}
|
|
1189
|
-
const parsed = sessionLogEntrySchema.safeParse(migrateStoredEntry(value));
|
|
1190
|
-
if (parsed.success) {
|
|
1191
|
-
return parsed.data;
|
|
1192
|
-
}
|
|
1193
|
-
return piEntry(piMessageSchema.parse(value), INITIAL_SESSION_ID);
|
|
1194
|
-
}
|
|
1195
|
-
function actorIdentityKey(actor) {
|
|
1196
|
-
if (actor.platform === "system") {
|
|
1197
|
-
return `system ${actor.name}`;
|
|
1198
|
-
}
|
|
1199
|
-
return actor.platform === "slack" ? `slack\0${actor.teamId}\0${actor.userId}` : `${actor.platform}\0${actor.userId}`;
|
|
1200
|
-
}
|
|
1201
|
-
function instructionActors(provenance) {
|
|
1202
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1203
|
-
const actors = [];
|
|
1204
|
-
for (const entry of provenance) {
|
|
1205
|
-
if (entry.authority !== "instruction" || !entry.actor) {
|
|
1206
|
-
continue;
|
|
1207
|
-
}
|
|
1208
|
-
const identity = actorIdentityKey(entry.actor);
|
|
1209
|
-
if (seen.has(identity)) {
|
|
1210
|
-
continue;
|
|
1211
|
-
}
|
|
1212
|
-
seen.add(identity);
|
|
1213
|
-
actors.push(entry.actor);
|
|
1214
|
-
}
|
|
1215
|
-
return actors;
|
|
1216
|
-
}
|
|
1217
|
-
function redisStore(redisStateAdapter) {
|
|
1218
|
-
const client = redisStateAdapter.getClient();
|
|
1219
|
-
return {
|
|
1220
|
-
async append({ entries, scope, ttlMs }) {
|
|
1221
|
-
const listKey = key(scope);
|
|
1222
|
-
if (entries.length > 0) {
|
|
1223
|
-
await client.rPush(
|
|
1224
|
-
listKey,
|
|
1225
|
-
entries.map((entry) => JSON.stringify(entry))
|
|
1226
|
-
);
|
|
1227
|
-
}
|
|
1228
|
-
await client.pExpire(listKey, Math.max(1, ttlMs));
|
|
1229
|
-
},
|
|
1230
|
-
async read(scope) {
|
|
1231
|
-
const values = await client.lRange(key(scope), 0, -1);
|
|
1232
|
-
return values.map(decode);
|
|
1233
|
-
}
|
|
1234
|
-
};
|
|
1235
|
-
}
|
|
1236
|
-
function stateStore() {
|
|
1237
|
-
const stateAdapter = getStateAdapter();
|
|
1238
|
-
return {
|
|
1239
|
-
async append({ entries, scope, ttlMs }) {
|
|
1240
|
-
const listKey = rawKey(scope);
|
|
1241
|
-
const lock = await stateAdapter.acquireLock(
|
|
1242
|
-
`${listKey}:commit`,
|
|
1243
|
-
STATE_STORE_LOCK_TTL_MS
|
|
1244
|
-
);
|
|
1245
|
-
if (!lock) {
|
|
1246
|
-
throw new Error("Could not acquire session log commit lock");
|
|
1247
|
-
}
|
|
1248
|
-
try {
|
|
1249
|
-
const existingValue = await stateAdapter.get(listKey);
|
|
1250
|
-
const existingEntries = Array.isArray(existingValue) ? existingValue.map(decode) : (await stateAdapter.getList(listKey)).map(decode);
|
|
1251
|
-
await stateAdapter.set(
|
|
1252
|
-
listKey,
|
|
1253
|
-
[...existingEntries, ...entries],
|
|
1254
|
-
Math.max(1, ttlMs)
|
|
1255
|
-
);
|
|
1256
|
-
} finally {
|
|
1257
|
-
await stateAdapter.releaseLock(lock);
|
|
1258
|
-
}
|
|
1259
|
-
},
|
|
1260
|
-
async read(scope) {
|
|
1261
|
-
const listKey = rawKey(scope);
|
|
1262
|
-
const value = await stateAdapter.get(listKey);
|
|
1263
|
-
if (Array.isArray(value)) {
|
|
1264
|
-
return value.map(decode);
|
|
1265
|
-
}
|
|
1266
|
-
const values = await stateAdapter.getList(listKey);
|
|
1267
|
-
return values.map(decode);
|
|
1268
|
-
}
|
|
1269
|
-
};
|
|
1270
|
-
}
|
|
1271
|
-
async function defaultStore() {
|
|
1272
|
-
const { redisStateAdapter, stateAdapter } = await getConnectedStateContext();
|
|
1273
|
-
if (redisStateAdapter) {
|
|
1274
|
-
return redisStore(redisStateAdapter);
|
|
1275
|
-
}
|
|
1276
|
-
await stateAdapter.connect();
|
|
1277
|
-
return stateStore();
|
|
1278
|
-
}
|
|
1279
|
-
async function loadEntries(args) {
|
|
1280
|
-
const store = args.store ?? await defaultStore();
|
|
1281
|
-
return (await store.read(args)).map(decode);
|
|
1282
|
-
}
|
|
1283
|
-
async function readSessionLogEntries(args) {
|
|
1284
|
-
return loadEntries(args);
|
|
1285
|
-
}
|
|
1286
|
-
function instructionProvenanceFor(actor) {
|
|
1287
|
-
return instructionProvenance(actor);
|
|
1288
|
-
}
|
|
1289
|
-
var contextProvenance = unattributedContextProvenance;
|
|
1290
|
-
|
|
1291
|
-
// src/chat/conversations/history.ts
|
|
1292
|
-
var handoffModelProfileSchema = modelProfileSchema.refine(
|
|
1293
|
-
(profile) => profile !== "standard",
|
|
1294
|
-
"handoff profile must not be standard"
|
|
1295
|
-
);
|
|
1296
|
-
var piMessageStepEntrySchema = z3.object({
|
|
1297
|
-
type: z3.literal("pi_message"),
|
|
1298
|
-
schemaVersion: z3.number().int().optional(),
|
|
1299
|
-
message: piMessageSchema,
|
|
1300
|
-
provenance: piMessageProvenanceSchema.optional()
|
|
1301
|
-
});
|
|
1302
|
-
var contextEpochStartedEntrySchema = z3.union([
|
|
1303
|
-
z3.object({
|
|
1304
|
-
type: z3.literal("context_epoch_started"),
|
|
1305
|
-
reason: z3.literal("initial"),
|
|
1306
|
-
modelProfile: z3.literal("standard"),
|
|
1307
|
-
modelId: z3.string().min(1)
|
|
1308
|
-
}).strict(),
|
|
1309
|
-
z3.object({
|
|
1310
|
-
type: z3.literal("context_epoch_started"),
|
|
1311
|
-
reason: z3.literal("handoff"),
|
|
1312
|
-
modelProfile: handoffModelProfileSchema,
|
|
1313
|
-
modelId: z3.string().min(1)
|
|
1314
|
-
}).strict(),
|
|
1315
|
-
z3.object({
|
|
1316
|
-
type: z3.literal("context_epoch_started"),
|
|
1317
|
-
reason: z3.union([z3.literal("compaction"), z3.literal("rollback")]),
|
|
1318
|
-
// TODO(v0.97.0): Remove support for deployed compaction/rollback markers
|
|
1319
|
-
// without model bindings after those rows pass the retention horizon.
|
|
1320
|
-
modelProfile: z3.undefined().optional(),
|
|
1321
|
-
modelId: z3.undefined().optional()
|
|
1322
|
-
}).strict(),
|
|
1323
|
-
z3.object({
|
|
1324
|
-
type: z3.literal("context_epoch_started"),
|
|
1325
|
-
reason: z3.union([z3.literal("compaction"), z3.literal("rollback")]),
|
|
1326
|
-
modelProfile: modelProfileSchema,
|
|
1327
|
-
modelId: z3.string().min(1)
|
|
1328
|
-
}).strict()
|
|
1329
|
-
]);
|
|
1330
|
-
var piMessageStepSchema = z3.object({
|
|
1331
|
-
message: piMessageSchema,
|
|
1332
|
-
createdAtMs: z3.number().finite(),
|
|
1333
|
-
provenance: piMessageProvenanceSchema.optional()
|
|
1154
|
+
errorCode: z2.string().min(1).optional()
|
|
1334
1155
|
}).strict();
|
|
1335
|
-
var
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
modelProfile: modelProfileSchema,
|
|
1351
|
-
modelId: z3.string().min(1),
|
|
1352
|
-
messages: z3.array(piMessageStepSchema)
|
|
1353
|
-
}).strict()
|
|
1156
|
+
var appendableConversationEventDataSchema = z2.union([
|
|
1157
|
+
messageEventDataSchema,
|
|
1158
|
+
messageUpdatedEventDataSchema,
|
|
1159
|
+
agentStepEventDataSchema,
|
|
1160
|
+
mcpProviderConnectedEventDataSchema,
|
|
1161
|
+
authorizationRequestedEventDataSchema,
|
|
1162
|
+
authorizationCompletedEventDataSchema,
|
|
1163
|
+
toolExecutionStartedEventDataSchema,
|
|
1164
|
+
messageHandledEventDataSchema,
|
|
1165
|
+
messagesSummarizedEventDataSchema,
|
|
1166
|
+
turnStartedEventDataSchema,
|
|
1167
|
+
turnCompletedEventDataSchema,
|
|
1168
|
+
turnFailedEventDataSchema,
|
|
1169
|
+
subagentStartedEventDataSchema,
|
|
1170
|
+
subagentEndedEventDataSchema
|
|
1354
1171
|
]);
|
|
1355
|
-
var
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
var authorizationKindSchema2 = z3.union([
|
|
1360
|
-
z3.literal("plugin"),
|
|
1361
|
-
z3.literal("mcp")
|
|
1172
|
+
var conversationEventDataSchema = z2.union([
|
|
1173
|
+
appendableConversationEventDataSchema,
|
|
1174
|
+
historyReplacementEventDataSchema,
|
|
1175
|
+
legacyRollbackEventDataSchema
|
|
1362
1176
|
]);
|
|
1363
|
-
var
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
var toolExecutionStartedEntrySchema2 = z3.object({
|
|
1382
|
-
type: z3.literal("tool_execution_started"),
|
|
1383
|
-
toolCallId: z3.string().min(1),
|
|
1384
|
-
toolName: z3.string().min(1),
|
|
1385
|
-
args: z3.unknown().optional()
|
|
1386
|
-
});
|
|
1387
|
-
var visibleContextCompactedEntrySchema = z3.object({
|
|
1388
|
-
type: z3.literal("visible_context_compacted"),
|
|
1389
|
-
compactions: z3.array(
|
|
1390
|
-
z3.object({
|
|
1391
|
-
coveredMessageIds: z3.array(z3.string()),
|
|
1392
|
-
createdAtMs: z3.number(),
|
|
1393
|
-
id: z3.string().min(1),
|
|
1394
|
-
summary: z3.string()
|
|
1395
|
-
})
|
|
1396
|
-
)
|
|
1397
|
-
});
|
|
1398
|
-
var subagentStartedEntrySchema2 = z3.object({
|
|
1399
|
-
type: z3.literal("subagent_started"),
|
|
1400
|
-
subagentInvocationId: z3.string().min(1),
|
|
1401
|
-
subagentKind: z3.string().min(1),
|
|
1402
|
-
modelId: z3.string().min(1).optional(),
|
|
1403
|
-
parentToolCallId: z3.string().min(1).optional(),
|
|
1404
|
-
reasoningLevel: z3.string().min(1).optional(),
|
|
1405
|
-
childConversationId: z3.string().min(1),
|
|
1406
|
-
historyMode: z3.union([z3.literal("isolated"), z3.literal("shared")])
|
|
1407
|
-
}).strict();
|
|
1408
|
-
var subagentEndedEntrySchema2 = z3.object({
|
|
1409
|
-
type: z3.literal("subagent_ended"),
|
|
1410
|
-
subagentInvocationId: z3.string().min(1),
|
|
1411
|
-
outcome: z3.union([
|
|
1412
|
-
z3.literal("success"),
|
|
1413
|
-
z3.literal("error"),
|
|
1414
|
-
z3.literal("aborted")
|
|
1415
|
-
]),
|
|
1416
|
-
errorCode: z3.string().min(1).optional()
|
|
1417
|
-
});
|
|
1418
|
-
var appendableAgentStepEntrySchema = z3.union([
|
|
1419
|
-
piMessageStepEntrySchema,
|
|
1420
|
-
mcpProviderConnectedEntrySchema2,
|
|
1421
|
-
authorizationRequestedEntrySchema2,
|
|
1422
|
-
authorizationCompletedEntrySchema2,
|
|
1423
|
-
toolExecutionStartedEntrySchema2,
|
|
1424
|
-
visibleContextCompactedEntrySchema,
|
|
1425
|
-
subagentStartedEntrySchema2,
|
|
1426
|
-
subagentEndedEntrySchema2
|
|
1177
|
+
var knownConversationEventTypeSchema = z2.enum([
|
|
1178
|
+
"message",
|
|
1179
|
+
"message_updated",
|
|
1180
|
+
"agent_step",
|
|
1181
|
+
"mcp_provider_connected",
|
|
1182
|
+
"authorization_requested",
|
|
1183
|
+
"authorization_completed",
|
|
1184
|
+
"tool_execution_started",
|
|
1185
|
+
"message_handled",
|
|
1186
|
+
"messages_summarized",
|
|
1187
|
+
"turn_started",
|
|
1188
|
+
"turn_completed",
|
|
1189
|
+
"turn_failed",
|
|
1190
|
+
"subagent_started",
|
|
1191
|
+
"subagent_ended",
|
|
1192
|
+
"handoff",
|
|
1193
|
+
"compaction",
|
|
1194
|
+
"rollback"
|
|
1427
1195
|
]);
|
|
1428
|
-
var
|
|
1429
|
-
|
|
1430
|
-
|
|
1196
|
+
var unknownConversationEventDataSchema = z2.object({
|
|
1197
|
+
type: z2.literal("unknown"),
|
|
1198
|
+
originalType: z2.string().min(1),
|
|
1199
|
+
payload: z2.unknown()
|
|
1200
|
+
}).strict();
|
|
1201
|
+
var conversationEventEnvelopeSchema = z2.object({
|
|
1202
|
+
schemaVersion: z2.number().int().nonnegative(),
|
|
1203
|
+
seq: z2.number().int().nonnegative(),
|
|
1204
|
+
historyVersion: z2.number().int().nonnegative(),
|
|
1205
|
+
idempotencyKey: z2.string().min(1).optional(),
|
|
1206
|
+
createdAtMs: z2.number().finite()
|
|
1207
|
+
}).strict();
|
|
1208
|
+
var conversationEventSchema = z2.union([
|
|
1209
|
+
conversationEventEnvelopeSchema.extend({
|
|
1210
|
+
schemaVersion: z2.literal(1),
|
|
1211
|
+
data: conversationEventDataSchema
|
|
1212
|
+
}),
|
|
1213
|
+
conversationEventEnvelopeSchema.extend({
|
|
1214
|
+
data: unknownConversationEventDataSchema
|
|
1215
|
+
})
|
|
1431
1216
|
]);
|
|
1432
|
-
var
|
|
1433
|
-
|
|
1434
|
-
|
|
1217
|
+
var storedConversationEventSchema = conversationEventEnvelopeSchema.extend({
|
|
1218
|
+
type: z2.string().min(1),
|
|
1219
|
+
payload: z2.unknown()
|
|
1220
|
+
});
|
|
1221
|
+
function decodeStoredConversationEvent(value) {
|
|
1222
|
+
const stored = storedConversationEventSchema.parse(value);
|
|
1223
|
+
const { type, payload, ...envelope } = stored;
|
|
1224
|
+
const knownType = knownConversationEventTypeSchema.safeParse(type).success;
|
|
1225
|
+
if (stored.schemaVersion === 1 && knownType) {
|
|
1226
|
+
const data = typeof payload === "object" && payload !== null && !Array.isArray(payload) ? { ...payload, type } : { type };
|
|
1227
|
+
return conversationEventSchema.parse({ ...envelope, data });
|
|
1228
|
+
}
|
|
1229
|
+
return conversationEventSchema.parse({
|
|
1230
|
+
...envelope,
|
|
1231
|
+
data: { type: "unknown", originalType: type, payload }
|
|
1232
|
+
});
|
|
1233
|
+
}
|
|
1234
|
+
var newConversationEventSchema = z2.object({
|
|
1235
|
+
data: appendableConversationEventDataSchema,
|
|
1236
|
+
idempotencyKey: z2.string().min(1).optional(),
|
|
1237
|
+
createdAtMs: z2.number().finite()
|
|
1435
1238
|
}).strict();
|
|
1436
1239
|
|
|
1437
1240
|
// src/chat/conversations/sql/conversation-row.ts
|
|
@@ -1470,66 +1273,92 @@ function sanitizePostgresJson(value) {
|
|
|
1470
1273
|
return value;
|
|
1471
1274
|
}
|
|
1472
1275
|
return Object.fromEntries(
|
|
1473
|
-
Object.entries(value).map(([
|
|
1474
|
-
|
|
1276
|
+
Object.entries(value).map(([key, item]) => [
|
|
1277
|
+
key,
|
|
1475
1278
|
sanitizePostgresJson(item)
|
|
1476
1279
|
])
|
|
1477
1280
|
);
|
|
1478
1281
|
}
|
|
1479
1282
|
|
|
1480
|
-
// src/chat/conversations/sql/
|
|
1481
|
-
function
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
return typeof role === "string" ? role : null;
|
|
1283
|
+
// src/chat/conversations/sql/event-lock.ts
|
|
1284
|
+
async function withConversationEventLock(executor, conversationId, callback) {
|
|
1285
|
+
return executor.withLock(
|
|
1286
|
+
`junior_conversation:event:${conversationId}`,
|
|
1287
|
+
callback
|
|
1288
|
+
);
|
|
1487
1289
|
}
|
|
1488
|
-
|
|
1489
|
-
|
|
1290
|
+
|
|
1291
|
+
// src/chat/conversations/sql/history.ts
|
|
1292
|
+
var messageHistoryEventTypes = [
|
|
1293
|
+
"message",
|
|
1294
|
+
"message_updated",
|
|
1295
|
+
"message_handled"
|
|
1296
|
+
];
|
|
1297
|
+
function insertFromEvent(conversationId, seq, historyVersion, event) {
|
|
1298
|
+
const { type, ...payload } = conversationEventDataSchema.parse(event.data);
|
|
1490
1299
|
return {
|
|
1491
1300
|
conversationId,
|
|
1492
1301
|
seq,
|
|
1493
|
-
|
|
1302
|
+
historyVersion,
|
|
1303
|
+
schemaVersion: 1,
|
|
1304
|
+
idempotencyKey: event.idempotencyKey ?? null,
|
|
1494
1305
|
type,
|
|
1495
|
-
role: messageRole(step.entry),
|
|
1496
1306
|
payload: sanitizePostgresJson(payload),
|
|
1497
|
-
createdAt: new Date(
|
|
1307
|
+
createdAt: new Date(event.createdAtMs)
|
|
1498
1308
|
};
|
|
1499
1309
|
}
|
|
1500
|
-
function
|
|
1501
|
-
|
|
1502
|
-
|
|
1310
|
+
function eventFromRow(row) {
|
|
1311
|
+
return decodeStoredConversationEvent({
|
|
1312
|
+
schemaVersion: row.schemaVersion,
|
|
1503
1313
|
seq: row.seq,
|
|
1504
|
-
|
|
1314
|
+
historyVersion: row.historyVersion,
|
|
1315
|
+
...row.idempotencyKey ? { idempotencyKey: row.idempotencyKey } : {},
|
|
1505
1316
|
createdAtMs: row.createdAt.getTime(),
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
}
|
|
1509
|
-
function piMessageStep(step) {
|
|
1510
|
-
return {
|
|
1511
|
-
entry: {
|
|
1512
|
-
type: "pi_message",
|
|
1513
|
-
message: step.message,
|
|
1514
|
-
...step.provenance ? { provenance: step.provenance } : {}
|
|
1515
|
-
},
|
|
1516
|
-
createdAtMs: step.createdAtMs
|
|
1517
|
-
};
|
|
1317
|
+
type: row.type,
|
|
1318
|
+
payload: row.payload
|
|
1319
|
+
});
|
|
1518
1320
|
}
|
|
1519
|
-
var
|
|
1321
|
+
var SqlConversationEventStore = class {
|
|
1520
1322
|
constructor(executor) {
|
|
1521
1323
|
this.executor = executor;
|
|
1522
1324
|
}
|
|
1523
1325
|
executor;
|
|
1524
|
-
async append(conversationId,
|
|
1525
|
-
const parsed =
|
|
1326
|
+
async append(conversationId, events) {
|
|
1327
|
+
const parsed = events.map(
|
|
1328
|
+
(event) => newConversationEventSchema.parse(event)
|
|
1329
|
+
);
|
|
1526
1330
|
if (parsed.length === 0) {
|
|
1527
1331
|
return;
|
|
1528
1332
|
}
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1333
|
+
await withConversationEventLock(this.executor, conversationId, async () => {
|
|
1334
|
+
const existingKeys = parsed.map((event) => event.idempotencyKey).filter((key) => key !== void 0);
|
|
1335
|
+
const persistedKeys = existingKeys.length === 0 ? /* @__PURE__ */ new Set() : new Set(
|
|
1336
|
+
(await this.executor.db().select({ key: juniorConversationEvents.idempotencyKey }).from(juniorConversationEvents).where(
|
|
1337
|
+
and3(
|
|
1338
|
+
eq3(
|
|
1339
|
+
juniorConversationEvents.conversationId,
|
|
1340
|
+
conversationId
|
|
1341
|
+
),
|
|
1342
|
+
inArray(
|
|
1343
|
+
juniorConversationEvents.idempotencyKey,
|
|
1344
|
+
existingKeys
|
|
1345
|
+
)
|
|
1346
|
+
)
|
|
1347
|
+
)).flatMap((row) => row.key ? [row.key] : [])
|
|
1348
|
+
);
|
|
1349
|
+
const acceptedKeys = new Set(persistedKeys);
|
|
1350
|
+
const pending = parsed.filter((event) => {
|
|
1351
|
+
if (event.idempotencyKey === void 0) return true;
|
|
1352
|
+
if (acceptedKeys.has(event.idempotencyKey)) return false;
|
|
1353
|
+
acceptedKeys.add(event.idempotencyKey);
|
|
1354
|
+
return true;
|
|
1355
|
+
});
|
|
1356
|
+
if (pending.length === 0) {
|
|
1357
|
+
return;
|
|
1358
|
+
}
|
|
1359
|
+
const newestCreatedAtMs = Math.max(
|
|
1360
|
+
...pending.map((event) => event.createdAtMs)
|
|
1361
|
+
);
|
|
1533
1362
|
await ensureConversationRow(
|
|
1534
1363
|
this.executor,
|
|
1535
1364
|
conversationId,
|
|
@@ -1542,17 +1371,17 @@ var SqlAgentStepStore = class {
|
|
|
1542
1371
|
)
|
|
1543
1372
|
);
|
|
1544
1373
|
const cursor = await this.readCursor(conversationId);
|
|
1545
|
-
const
|
|
1374
|
+
const historyVersion = cursor.maxHistoryVersion ?? 0;
|
|
1546
1375
|
let seq = cursor.nextSeq;
|
|
1547
|
-
const rows =
|
|
1548
|
-
(
|
|
1376
|
+
const rows = pending.map(
|
|
1377
|
+
(event) => insertFromEvent(conversationId, seq++, historyVersion, event)
|
|
1549
1378
|
);
|
|
1550
|
-
await this.executor.db().insert(
|
|
1379
|
+
await this.executor.db().insert(juniorConversationEvents).values(rows);
|
|
1551
1380
|
});
|
|
1552
1381
|
}
|
|
1553
|
-
async
|
|
1554
|
-
const parsed =
|
|
1555
|
-
await this.executor
|
|
1382
|
+
async replaceHistory(conversationId, replacement) {
|
|
1383
|
+
const parsed = historyReplacementSchema.parse(replacement);
|
|
1384
|
+
await withConversationEventLock(this.executor, conversationId, async () => {
|
|
1556
1385
|
await ensureConversationRow(this.executor, conversationId, Date.now());
|
|
1557
1386
|
await this.executor.db().update(juniorConversations).set({ archivedAt: null }).where(
|
|
1558
1387
|
and3(
|
|
@@ -1561,140 +1390,89 @@ var SqlAgentStepStore = class {
|
|
|
1561
1390
|
)
|
|
1562
1391
|
);
|
|
1563
1392
|
const cursor = await this.readCursor(conversationId);
|
|
1564
|
-
const
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
(step) => insertFromStep(conversationId, seq++, contextEpoch, step)
|
|
1393
|
+
const historyVersion = (cursor.maxHistoryVersion ?? 0) + 1;
|
|
1394
|
+
await this.executor.db().insert(juniorConversationEvents).values(
|
|
1395
|
+
insertFromEvent(
|
|
1396
|
+
conversationId,
|
|
1397
|
+
cursor.nextSeq,
|
|
1398
|
+
historyVersion,
|
|
1399
|
+
parsed
|
|
1400
|
+
)
|
|
1573
1401
|
);
|
|
1574
|
-
await this.executor.db().insert(juniorAgentSteps).values(rows);
|
|
1575
1402
|
});
|
|
1576
1403
|
}
|
|
1577
|
-
async
|
|
1404
|
+
async loadCurrentHistory(conversationId) {
|
|
1578
1405
|
const cursor = await this.readCursor(conversationId);
|
|
1579
|
-
if (cursor.
|
|
1406
|
+
if (cursor.maxHistoryVersion === null) {
|
|
1580
1407
|
return [];
|
|
1581
1408
|
}
|
|
1582
|
-
const rows = await this.executor.db().select().from(
|
|
1409
|
+
const rows = await this.executor.db().select().from(juniorConversationEvents).where(
|
|
1410
|
+
and3(
|
|
1411
|
+
eq3(juniorConversationEvents.conversationId, conversationId),
|
|
1412
|
+
eq3(juniorConversationEvents.historyVersion, cursor.maxHistoryVersion)
|
|
1413
|
+
)
|
|
1414
|
+
).orderBy(asc2(juniorConversationEvents.seq));
|
|
1415
|
+
return rows.map(eventFromRow);
|
|
1416
|
+
}
|
|
1417
|
+
async loadHistoryContaining(conversationId, seq, throughSeq) {
|
|
1418
|
+
const [boundary] = await this.executor.db().select({ historyVersion: juniorConversationEvents.historyVersion }).from(juniorConversationEvents).where(
|
|
1419
|
+
and3(
|
|
1420
|
+
eq3(juniorConversationEvents.conversationId, conversationId),
|
|
1421
|
+
eq3(juniorConversationEvents.seq, seq)
|
|
1422
|
+
)
|
|
1423
|
+
).limit(1);
|
|
1424
|
+
if (!boundary) return void 0;
|
|
1425
|
+
const rows = await this.executor.db().select().from(juniorConversationEvents).where(
|
|
1426
|
+
and3(
|
|
1427
|
+
eq3(juniorConversationEvents.conversationId, conversationId),
|
|
1428
|
+
eq3(juniorConversationEvents.historyVersion, boundary.historyVersion),
|
|
1429
|
+
throughSeq === void 0 ? void 0 : lte(juniorConversationEvents.seq, throughSeq)
|
|
1430
|
+
)
|
|
1431
|
+
).orderBy(asc2(juniorConversationEvents.seq));
|
|
1432
|
+
return rows.map(eventFromRow);
|
|
1433
|
+
}
|
|
1434
|
+
async loadMessageHistory(conversationId) {
|
|
1435
|
+
const [compactionRow] = await this.executor.db().select().from(juniorConversationEvents).where(
|
|
1436
|
+
and3(
|
|
1437
|
+
eq3(juniorConversationEvents.conversationId, conversationId),
|
|
1438
|
+
eq3(juniorConversationEvents.type, "messages_summarized")
|
|
1439
|
+
)
|
|
1440
|
+
).orderBy(desc2(juniorConversationEvents.seq)).limit(1);
|
|
1441
|
+
const compaction = compactionRow ? eventFromRow(compactionRow) : void 0;
|
|
1442
|
+
const historyFromSeq = compaction?.data.type === "messages_summarized" ? compaction.data.historyFromSeq : 0;
|
|
1443
|
+
const rows = await this.executor.db().select().from(juniorConversationEvents).where(
|
|
1583
1444
|
and3(
|
|
1584
|
-
eq3(
|
|
1585
|
-
|
|
1445
|
+
eq3(juniorConversationEvents.conversationId, conversationId),
|
|
1446
|
+
inArray(juniorConversationEvents.type, messageHistoryEventTypes),
|
|
1447
|
+
gte(juniorConversationEvents.seq, historyFromSeq)
|
|
1586
1448
|
)
|
|
1587
|
-
).orderBy(asc2(
|
|
1588
|
-
return rows.map(
|
|
1449
|
+
).orderBy(asc2(juniorConversationEvents.seq));
|
|
1450
|
+
return { events: rows.map(eventFromRow), compaction };
|
|
1589
1451
|
}
|
|
1590
1452
|
async loadHistory(conversationId) {
|
|
1591
|
-
const rows = await this.executor.db().select().from(
|
|
1592
|
-
return rows.map(
|
|
1453
|
+
const rows = await this.executor.db().select().from(juniorConversationEvents).where(eq3(juniorConversationEvents.conversationId, conversationId)).orderBy(asc2(juniorConversationEvents.seq));
|
|
1454
|
+
return rows.map(eventFromRow);
|
|
1593
1455
|
}
|
|
1594
|
-
/** Read the next
|
|
1456
|
+
/** Read the next sequence and active model-history version. */
|
|
1595
1457
|
async readCursor(conversationId) {
|
|
1596
1458
|
const rows = await this.executor.db().select({
|
|
1597
|
-
maxSeq: sql7`max(${
|
|
1598
|
-
|
|
1599
|
-
}).from(
|
|
1459
|
+
maxSeq: sql7`max(${juniorConversationEvents.seq})`,
|
|
1460
|
+
maxHistoryVersion: sql7`max(${juniorConversationEvents.historyVersion})`
|
|
1461
|
+
}).from(juniorConversationEvents).where(eq3(juniorConversationEvents.conversationId, conversationId));
|
|
1600
1462
|
const maxSeq = rows[0]?.maxSeq;
|
|
1601
|
-
const
|
|
1463
|
+
const maxHistoryVersion = rows[0]?.maxHistoryVersion;
|
|
1602
1464
|
return {
|
|
1603
|
-
|
|
1465
|
+
maxHistoryVersion: maxHistoryVersion === null || maxHistoryVersion === void 0 ? null : Number(maxHistoryVersion),
|
|
1604
1466
|
nextSeq: maxSeq === null || maxSeq === void 0 ? 0 : Number(maxSeq) + 1
|
|
1605
1467
|
};
|
|
1606
1468
|
}
|
|
1607
1469
|
};
|
|
1608
|
-
function
|
|
1609
|
-
return new
|
|
1610
|
-
}
|
|
1611
|
-
|
|
1612
|
-
// src/chat/conversations/sql/messages.ts
|
|
1613
|
-
import { and as and4, asc as asc3, eq as eq4, isNotNull as isNotNull2, isNull as isNull2, sql as sql8 } from "drizzle-orm";
|
|
1614
|
-
function messageFromRow(row) {
|
|
1615
|
-
return {
|
|
1616
|
-
conversationId: row.conversationId,
|
|
1617
|
-
messageId: row.messageId,
|
|
1618
|
-
role: row.role,
|
|
1619
|
-
text: row.text,
|
|
1620
|
-
createdAtMs: row.createdAt.getTime(),
|
|
1621
|
-
...row.authorIdentityId ? { authorIdentityId: row.authorIdentityId } : {},
|
|
1622
|
-
...row.meta ? { meta: row.meta } : {},
|
|
1623
|
-
...row.repliedAt ? { repliedAtMs: row.repliedAt.getTime() } : {}
|
|
1624
|
-
};
|
|
1625
|
-
}
|
|
1626
|
-
var SqlConversationMessageStore = class {
|
|
1627
|
-
constructor(executor) {
|
|
1628
|
-
this.executor = executor;
|
|
1629
|
-
}
|
|
1630
|
-
executor;
|
|
1631
|
-
async record(conversationId, messages) {
|
|
1632
|
-
if (messages.length === 0) {
|
|
1633
|
-
return;
|
|
1634
|
-
}
|
|
1635
|
-
const newestCreatedAtMs = Math.max(
|
|
1636
|
-
...messages.map((message) => message.createdAtMs)
|
|
1637
|
-
);
|
|
1638
|
-
await this.executor.transaction(async () => {
|
|
1639
|
-
await ensureConversationRow(
|
|
1640
|
-
this.executor,
|
|
1641
|
-
conversationId,
|
|
1642
|
-
newestCreatedAtMs
|
|
1643
|
-
);
|
|
1644
|
-
await this.executor.db().update(juniorConversations).set({ archivedAt: null }).where(
|
|
1645
|
-
and4(
|
|
1646
|
-
eq4(juniorConversations.conversationId, conversationId),
|
|
1647
|
-
isNotNull2(juniorConversations.archivedAt)
|
|
1648
|
-
)
|
|
1649
|
-
);
|
|
1650
|
-
await this.executor.db().insert(juniorConversationMessages).values(
|
|
1651
|
-
messages.map((message) => ({
|
|
1652
|
-
conversationId,
|
|
1653
|
-
messageId: message.messageId,
|
|
1654
|
-
role: message.role,
|
|
1655
|
-
authorIdentityId: message.authorIdentityId ?? null,
|
|
1656
|
-
text: message.text,
|
|
1657
|
-
meta: message.meta ?? null,
|
|
1658
|
-
repliedAt: null,
|
|
1659
|
-
createdAt: new Date(message.createdAtMs)
|
|
1660
|
-
}))
|
|
1661
|
-
).onConflictDoUpdate({
|
|
1662
|
-
target: [
|
|
1663
|
-
juniorConversationMessages.conversationId,
|
|
1664
|
-
juniorConversationMessages.messageId
|
|
1665
|
-
],
|
|
1666
|
-
set: {
|
|
1667
|
-
meta: sql8`nullif(coalesce(${juniorConversationMessages.meta}, '{}'::jsonb) || coalesce(excluded.meta, '{}'::jsonb), '{}'::jsonb)`
|
|
1668
|
-
}
|
|
1669
|
-
});
|
|
1670
|
-
});
|
|
1671
|
-
}
|
|
1672
|
-
async markReplied(conversationId, messageId, repliedAtMs) {
|
|
1673
|
-
await this.executor.db().update(juniorConversationMessages).set({
|
|
1674
|
-
repliedAt: sql8`coalesce(${juniorConversationMessages.repliedAt}, ${new Date(repliedAtMs)})`
|
|
1675
|
-
}).where(
|
|
1676
|
-
and4(
|
|
1677
|
-
eq4(juniorConversationMessages.conversationId, conversationId),
|
|
1678
|
-
eq4(juniorConversationMessages.messageId, messageId),
|
|
1679
|
-
isNull2(juniorConversationMessages.repliedAt)
|
|
1680
|
-
)
|
|
1681
|
-
);
|
|
1682
|
-
}
|
|
1683
|
-
async list(conversationId, opts = {}) {
|
|
1684
|
-
const query = this.executor.db().select().from(juniorConversationMessages).where(eq4(juniorConversationMessages.conversationId, conversationId)).orderBy(
|
|
1685
|
-
asc3(juniorConversationMessages.createdAt),
|
|
1686
|
-
asc3(juniorConversationMessages.messageId)
|
|
1687
|
-
);
|
|
1688
|
-
const rows = opts.limit === void 0 ? await query : await query.limit(Math.max(0, opts.limit));
|
|
1689
|
-
return rows.map(messageFromRow);
|
|
1690
|
-
}
|
|
1691
|
-
};
|
|
1692
|
-
function createSqlConversationMessageStore(executor) {
|
|
1693
|
-
return new SqlConversationMessageStore(executor);
|
|
1470
|
+
function createSqlConversationEventStore(executor) {
|
|
1471
|
+
return new SqlConversationEventStore(executor);
|
|
1694
1472
|
}
|
|
1695
1473
|
|
|
1696
1474
|
// src/chat/conversations/sql/search.ts
|
|
1697
|
-
import { and as
|
|
1475
|
+
import { and as and4, desc as desc3, eq as eq4, isNull as isNull2, ne, sql as sql8 } from "drizzle-orm";
|
|
1698
1476
|
var SqlConversationSearchStore = class {
|
|
1699
1477
|
constructor(executor) {
|
|
1700
1478
|
this.executor = executor;
|
|
@@ -1702,48 +1480,51 @@ var SqlConversationSearchStore = class {
|
|
|
1702
1480
|
executor;
|
|
1703
1481
|
async search(args) {
|
|
1704
1482
|
const db = this.executor.db();
|
|
1705
|
-
const tsquery =
|
|
1706
|
-
const
|
|
1707
|
-
const
|
|
1708
|
-
const
|
|
1483
|
+
const tsquery = sql8`websearch_to_tsquery('english', ${args.query})`;
|
|
1484
|
+
const text5 = sql8`${juniorConversationEvents.payload}->>'text'`;
|
|
1485
|
+
const rank = sql8`ts_rank_cd(to_tsvector('english', ${text5}), ${tsquery})`;
|
|
1486
|
+
const excerpt = sql8`ts_headline('english', ${text5}, ${tsquery}, 'MaxFragments=2, MinWords=8, MaxWords=40, FragmentDelimiter=" … ", StartSel=**, StopSel=**')`;
|
|
1487
|
+
const role = sql8`${juniorConversationEvents.payload}->>'role'`;
|
|
1488
|
+
const messageId = sql8`${juniorConversationEvents.payload}->>'messageId'`;
|
|
1709
1489
|
const bestPerConversation = db.selectDistinctOn([juniorConversations.conversationId], {
|
|
1710
1490
|
conversationId: juniorConversations.conversationId,
|
|
1711
1491
|
excerpt: excerpt.as("excerpt"),
|
|
1712
1492
|
lastActivityAt: juniorConversations.lastActivityAt,
|
|
1713
|
-
messageCreatedAt:
|
|
1714
|
-
messageId:
|
|
1493
|
+
messageCreatedAt: juniorConversationEvents.createdAt,
|
|
1494
|
+
messageId: messageId.as("message_id"),
|
|
1715
1495
|
providerDestinationId: juniorDestinations.providerDestinationId,
|
|
1716
1496
|
rank: rank.as("rank"),
|
|
1717
1497
|
role: role.as("role")
|
|
1718
|
-
}).from(
|
|
1498
|
+
}).from(juniorConversationEvents).innerJoin(
|
|
1719
1499
|
juniorConversations,
|
|
1720
|
-
|
|
1500
|
+
eq4(
|
|
1721
1501
|
juniorConversations.conversationId,
|
|
1722
|
-
|
|
1502
|
+
juniorConversationEvents.conversationId
|
|
1723
1503
|
)
|
|
1724
1504
|
).innerJoin(
|
|
1725
1505
|
juniorDestinations,
|
|
1726
|
-
|
|
1506
|
+
eq4(juniorDestinations.id, juniorConversations.destinationId)
|
|
1727
1507
|
).where(
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1508
|
+
and4(
|
|
1509
|
+
eq4(juniorConversations.source, "slack"),
|
|
1510
|
+
isNull2(juniorConversations.parentConversationId),
|
|
1511
|
+
isNull2(juniorConversations.transcriptPurgedAt),
|
|
1732
1512
|
ne(juniorConversations.conversationId, args.currentConversationId),
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1513
|
+
eq4(juniorDestinations.provider, args.scope.provider),
|
|
1514
|
+
eq4(juniorDestinations.providerTenantId, args.scope.providerTenantId),
|
|
1515
|
+
eq4(juniorDestinations.visibility, "public"),
|
|
1516
|
+
eq4(juniorConversationEvents.type, "message"),
|
|
1517
|
+
sql8`${role} in ('user', 'assistant')`,
|
|
1518
|
+
sql8`to_tsvector('english', ${text5}) @@ ${tsquery}`
|
|
1738
1519
|
)
|
|
1739
1520
|
).orderBy(
|
|
1740
1521
|
juniorConversations.conversationId,
|
|
1741
|
-
|
|
1742
|
-
|
|
1522
|
+
desc3(rank),
|
|
1523
|
+
desc3(juniorConversationEvents.createdAt)
|
|
1743
1524
|
).as("best_conversation_matches");
|
|
1744
1525
|
const rows = await db.select().from(bestPerConversation).orderBy(
|
|
1745
|
-
|
|
1746
|
-
|
|
1526
|
+
desc3(bestPerConversation.rank),
|
|
1527
|
+
desc3(bestPerConversation.lastActivityAt)
|
|
1747
1528
|
).limit(args.limit);
|
|
1748
1529
|
return rows.map((row) => ({
|
|
1749
1530
|
conversationId: row.conversationId,
|
|
@@ -2014,24 +1795,23 @@ function createDb(args) {
|
|
|
2014
1795
|
});
|
|
2015
1796
|
}
|
|
2016
1797
|
function getSqlExecutor() {
|
|
2017
|
-
const { sql:
|
|
2018
|
-
if (current?.databaseUrl !==
|
|
1798
|
+
const { sql: sql9 } = getChatConfig();
|
|
1799
|
+
if (current?.databaseUrl !== sql9.databaseUrl || current.driver !== sql9.driver) {
|
|
2019
1800
|
if (current) {
|
|
2020
1801
|
const previous = current;
|
|
2021
1802
|
current = void 0;
|
|
2022
1803
|
void previous.db.close().catch(() => void 0);
|
|
2023
1804
|
}
|
|
2024
1805
|
const db = createDb({
|
|
2025
|
-
databaseUrl:
|
|
2026
|
-
driver:
|
|
1806
|
+
databaseUrl: sql9.databaseUrl,
|
|
1807
|
+
driver: sql9.driver
|
|
2027
1808
|
});
|
|
2028
1809
|
current = {
|
|
2029
|
-
databaseUrl:
|
|
2030
|
-
driver:
|
|
1810
|
+
databaseUrl: sql9.databaseUrl,
|
|
1811
|
+
driver: sql9.driver,
|
|
2031
1812
|
db,
|
|
2032
1813
|
store: createSqlStore(db),
|
|
2033
|
-
|
|
2034
|
-
messageStore: createSqlConversationMessageStore(db),
|
|
1814
|
+
eventStore: createSqlConversationEventStore(db),
|
|
2035
1815
|
searchStore: createSqlConversationSearchStore(db)
|
|
2036
1816
|
};
|
|
2037
1817
|
}
|
|
@@ -2044,13 +1824,9 @@ function getConversationStore() {
|
|
|
2044
1824
|
getSqlExecutor();
|
|
2045
1825
|
return current.store;
|
|
2046
1826
|
}
|
|
2047
|
-
function
|
|
1827
|
+
function getConversationEventStore() {
|
|
2048
1828
|
getSqlExecutor();
|
|
2049
|
-
return current.
|
|
2050
|
-
}
|
|
2051
|
-
function getConversationMessageStore() {
|
|
2052
|
-
getSqlExecutor();
|
|
2053
|
-
return current.messageStore;
|
|
1829
|
+
return current.eventStore;
|
|
2054
1830
|
}
|
|
2055
1831
|
function getConversationSearchStore() {
|
|
2056
1832
|
getSqlExecutor();
|
|
@@ -2066,25 +1842,23 @@ export {
|
|
|
2066
1842
|
juniorUsers,
|
|
2067
1843
|
juniorIdentities,
|
|
2068
1844
|
juniorConversations,
|
|
2069
|
-
|
|
2070
|
-
juniorConversationMessages,
|
|
1845
|
+
juniorConversationEvents,
|
|
2071
1846
|
createSqlStore,
|
|
2072
|
-
|
|
2073
|
-
legacyActorProvenance,
|
|
2074
|
-
instructionActors,
|
|
2075
|
-
readSessionLogEntries,
|
|
1847
|
+
conversationMessageProvenanceSchema,
|
|
2076
1848
|
instructionProvenanceFor,
|
|
2077
1849
|
contextProvenance,
|
|
2078
|
-
|
|
1850
|
+
instructionActors,
|
|
1851
|
+
conversationEventDataSchema,
|
|
1852
|
+
decodeStoredConversationEvent,
|
|
1853
|
+
newConversationEventSchema,
|
|
2079
1854
|
sanitizePostgresJson,
|
|
2080
|
-
|
|
2081
|
-
|
|
1855
|
+
withConversationEventLock,
|
|
1856
|
+
createSqlConversationEventStore,
|
|
2082
1857
|
createJuniorSqlExecutor,
|
|
2083
1858
|
getSqlExecutor,
|
|
2084
1859
|
getDb,
|
|
2085
1860
|
getConversationStore,
|
|
2086
|
-
|
|
2087
|
-
getConversationMessageStore,
|
|
1861
|
+
getConversationEventStore,
|
|
2088
1862
|
getConversationSearchStore,
|
|
2089
1863
|
closeDb
|
|
2090
1864
|
};
|