@sentry/junior 0.108.0 → 0.110.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/dist/{agent-hooks-NU5HK3PS.js → agent-hooks-ELT4ODFF.js} +12 -13
  2. package/dist/api/conversations/access.d.ts +9 -0
  3. package/dist/api/conversations/aggregate.d.ts +12 -1
  4. package/dist/api/conversations/archive.d.ts +3 -5
  5. package/dist/api/conversations/detail.d.ts +156 -7
  6. package/dist/api/conversations/events.d.ts +2 -2
  7. package/dist/api/conversations/list.d.ts +57 -6
  8. package/dist/api/conversations/projection.d.ts +6 -7
  9. package/dist/api/conversations/reporting.d.ts +10 -4
  10. package/dist/api/conversations/routes.d.ts +2 -1
  11. package/dist/api/conversations/shared.d.ts +1 -1
  12. package/dist/api/conversations/stats.d.ts +37 -6
  13. package/dist/api/conversations/stats.query.d.ts +1 -1
  14. package/dist/api/conversations/usage.d.ts +9 -0
  15. package/dist/api/http.d.ts +7 -0
  16. package/dist/api/locations/detail.d.ts +102 -6
  17. package/dist/api/locations/list.d.ts +43 -5
  18. package/dist/api/locations/query.d.ts +4 -2
  19. package/dist/api/locations/routes.d.ts +2 -1
  20. package/dist/api/people/list.d.ts +28 -6
  21. package/dist/api/people/list.query.d.ts +1 -1
  22. package/dist/api/people/profile.d.ts +96 -7
  23. package/dist/api/people/profile.query.d.ts +4 -2
  24. package/dist/api/people/routes.d.ts +2 -1
  25. package/dist/api/people/shared.d.ts +1219 -2
  26. package/dist/api/route.d.ts +18 -4
  27. package/dist/api/schema/common.d.ts +6 -0
  28. package/dist/api/{conversations/schema.d.ts → schema/conversation.d.ts} +88 -9
  29. package/dist/api/{locations/schema.d.ts → schema/location.d.ts} +5 -0
  30. package/dist/api/{people/schema.d.ts → schema/person.d.ts} +37 -45
  31. package/dist/api/schema.d.ts +8 -22
  32. package/dist/api/schema.js +10 -2
  33. package/dist/api.d.ts +5 -1
  34. package/dist/api.js +838 -369
  35. package/dist/app.d.ts +1 -0
  36. package/dist/app.js +1564 -486
  37. package/dist/catalog-runtime-4GI22PXK.js +16 -0
  38. package/dist/chat/agent/resume.d.ts +11 -12
  39. package/dist/chat/conversations/history.d.ts +3 -0
  40. package/dist/chat/conversations/sql/privacy.d.ts +3 -15
  41. package/dist/chat/conversations/sql/store.d.ts +0 -7
  42. package/dist/chat/log-context.d.ts +40 -0
  43. package/dist/chat/logging.d.ts +3 -26
  44. package/dist/chat/pi/messages.d.ts +2 -2
  45. package/dist/chat/pi/sql-model-usage.d.ts +4 -1
  46. package/dist/chat/runtime/slack-resume.d.ts +2 -2
  47. package/dist/chat/services/auth-pause.d.ts +4 -0
  48. package/dist/chat/services/context-compaction.d.ts +1 -0
  49. package/dist/chat/services/turn-session-record.d.ts +0 -2
  50. package/dist/chat/slack/reply.d.ts +7 -19
  51. package/dist/chat/state/conversation.d.ts +1 -0
  52. package/dist/chat/task-execution/queue-signing.d.ts +10 -8
  53. package/dist/chat/task-execution/queue.d.ts +9 -7
  54. package/dist/chat/task-execution/slack-work.d.ts +6 -6
  55. package/dist/{chunk-UD6THJ2I.js → chunk-2T7TIEXI.js} +197 -12
  56. package/dist/{chunk-CEA3A3UA.js → chunk-2ZTTXTSZ.js} +24 -1
  57. package/dist/{chunk-XKB7LGIW.js → chunk-3S7YYHBI.js} +3 -139
  58. package/dist/chunk-3TV7OEHL.js +10 -0
  59. package/dist/{chunk-A5CO2EHL.js → chunk-3UBQI73J.js} +11 -15
  60. package/dist/{chunk-7FBGKXPE.js → chunk-42WRQLJ6.js} +10 -33
  61. package/dist/{chunk-TE4QHJH4.js → chunk-4QU44P7Q.js} +135 -595
  62. package/dist/{chunk-RT5BUHR5.js → chunk-6Y5L4BOM.js} +3 -5
  63. package/dist/{chunk-VIXFG2VC.js → chunk-C4MZ3GP5.js} +1 -2
  64. package/dist/{chunk-3RGQLX2F.js → chunk-C5XAFTHY.js} +1011 -29
  65. package/dist/{chunk-PUAMO4PI.js → chunk-FPK7XY3F.js} +139 -99
  66. package/dist/{chunk-H3QYZL7K.js → chunk-GK47NBDE.js} +28 -3
  67. package/dist/{chunk-O24R4DCK.js → chunk-IYKPU7H6.js} +94 -56
  68. package/dist/chunk-JQFJO5WH.js +477 -0
  69. package/dist/{chunk-VH6KWKG2.js → chunk-L5XQPJ7T.js} +3 -3
  70. package/dist/{chunk-2XXEKR44.js → chunk-MIAKQNYX.js} +43 -31
  71. package/dist/{chunk-KPMPQ6AA.js → chunk-RHHRKSPI.js} +249 -223
  72. package/dist/{chunk-YT72TOEK.js → chunk-SBOBTS27.js} +2 -2
  73. package/dist/{chunk-B5I5LMSP.js → chunk-W6RJZG7F.js} +5 -7
  74. package/dist/chunk-W75ZPAGG.js +44 -0
  75. package/dist/{chunk-SS67LUOK.js → chunk-WNOVRQ67.js} +6 -7
  76. package/dist/{chunk-YIPD3L6L.js → chunk-Y3H2DN6F.js} +8 -10
  77. package/dist/{chunk-DY7TRYB5.js → chunk-Y5FK3CNG.js} +1 -1
  78. package/dist/chunk-ZKIOWEFL.js +125 -0
  79. package/dist/cli/chat.js +23 -24
  80. package/dist/cli/check.js +9 -7
  81. package/dist/cli/plugins.js +16 -17
  82. package/dist/cli/snapshot-warmup.js +11 -10
  83. package/dist/cli/upgrade.js +314 -3505
  84. package/dist/db/db.d.ts +1 -1
  85. package/dist/db/schema/conversations.d.ts +17 -0
  86. package/dist/db/schema.d.ts +17 -0
  87. package/dist/{db-AMRBAT5D.js → db-Y6W6CWWW.js} +8 -7
  88. package/dist/instrumentation.js +4 -3
  89. package/dist/nitro.js +4 -4
  90. package/dist/reporting-schema.d.ts +46 -0
  91. package/dist/{runner-TQH5GAJ4.js → runner-BBFV5GLR.js} +17 -21
  92. package/dist/{skills-ITNHBARB.js → skills-AR4AF32L.js} +8 -6
  93. package/dist/{validation-AGQ46ZGV.js → validation-FBIEPTC2.js} +8 -6
  94. package/dist/version.d.ts +2 -0
  95. package/dist/version.js +7 -0
  96. package/migrations/0006_drop_legacy_conversation_messages.sql +1 -0
  97. package/migrations/0007_thick_sugar_man.sql +23 -0
  98. package/migrations/README.md +12 -9
  99. package/migrations/meta/0006_snapshot.json +948 -0
  100. package/migrations/meta/0007_snapshot.json +1013 -0
  101. package/migrations/meta/_journal.json +14 -0
  102. package/package.json +9 -5
  103. package/dist/catalog-runtime-FOFNPR3P.js +0 -14
  104. package/dist/chunk-AHJR2IFF.js +0 -115
  105. package/dist/chunk-B7PUBQQM.js +0 -53
  106. package/dist/chunk-G3E7SCME.js +0 -28
  107. package/dist/chunk-J3B3FPP2.js +0 -1061
  108. package/dist/chunk-OB42YVAE.js +0 -16
  109. package/dist/chunk-TWINAEZQ.js +0 -1283
@@ -0,0 +1,477 @@
1
+ import {
2
+ juniorDestinations,
3
+ timestamptz
4
+ } from "./chunk-VFUK3X5B.js";
5
+
6
+ // src/db/neon.ts
7
+ import { AsyncLocalStorage } from "async_hooks";
8
+ import {
9
+ Pool
10
+ } from "@neondatabase/serverless";
11
+ import { drizzle } from "drizzle-orm/neon-serverless";
12
+ import { migrate } from "drizzle-orm/neon-serverless/migrator";
13
+
14
+ // src/db/schema/conversation-events.ts
15
+ import {
16
+ foreignKey,
17
+ index as index3,
18
+ integer as integer2,
19
+ jsonb as jsonb3,
20
+ pgTable as pgTable4,
21
+ primaryKey,
22
+ text as text4,
23
+ uniqueIndex as uniqueIndex3
24
+ } from "drizzle-orm/pg-core";
25
+ import { sql as sql3 } from "drizzle-orm";
26
+
27
+ // src/db/schema/conversations.ts
28
+ import { sql as sql2 } from "drizzle-orm";
29
+ import {
30
+ index as index2,
31
+ integer,
32
+ jsonb as jsonb2,
33
+ pgTable as pgTable3,
34
+ text as text3
35
+ } from "drizzle-orm/pg-core";
36
+
37
+ // src/db/schema/identities.ts
38
+ import { sql } from "drizzle-orm";
39
+ import {
40
+ boolean,
41
+ index,
42
+ jsonb,
43
+ pgTable as pgTable2,
44
+ text as text2,
45
+ uniqueIndex as uniqueIndex2
46
+ } from "drizzle-orm/pg-core";
47
+
48
+ // src/db/schema/users.ts
49
+ import { text, pgTable, uniqueIndex } from "drizzle-orm/pg-core";
50
+ var juniorUsers = pgTable(
51
+ "junior_users",
52
+ {
53
+ id: text("id").primaryKey(),
54
+ primaryEmail: text("primary_email").notNull(),
55
+ primaryEmailNormalized: text("primary_email_normalized").notNull(),
56
+ displayName: text("display_name"),
57
+ createdAt: timestamptz("created_at").notNull(),
58
+ updatedAt: timestamptz("updated_at").notNull()
59
+ },
60
+ (table) => [
61
+ uniqueIndex("junior_users_primary_email_normalized_uidx").on(
62
+ table.primaryEmailNormalized
63
+ )
64
+ ]
65
+ );
66
+
67
+ // src/db/schema/identities.ts
68
+ var juniorIdentities = pgTable2(
69
+ "junior_identities",
70
+ {
71
+ id: text2("id").primaryKey(),
72
+ kind: text2("kind").$type().notNull(),
73
+ provider: text2("provider").notNull(),
74
+ providerTenantId: text2("provider_tenant_id").notNull().default(""),
75
+ providerSubjectId: text2("provider_subject_id").notNull(),
76
+ displayName: text2("display_name"),
77
+ handle: text2("handle"),
78
+ email: text2("email"),
79
+ avatarUrl: text2("avatar_url"),
80
+ metadata: jsonb("metadata_json"),
81
+ createdAt: timestamptz("created_at").notNull(),
82
+ updatedAt: timestamptz("updated_at").notNull(),
83
+ userId: text2("user_id").references(() => juniorUsers.id),
84
+ emailNormalized: text2("email_normalized"),
85
+ emailVerified: boolean("email_verified").notNull().default(false)
86
+ },
87
+ (table) => [
88
+ uniqueIndex2("junior_identities_provider_subject_uidx").on(
89
+ table.provider,
90
+ table.providerTenantId,
91
+ table.providerSubjectId
92
+ ),
93
+ index("junior_identities_user_idx").on(table.userId),
94
+ index("junior_identities_verified_email_idx").on(table.emailNormalized).where(
95
+ sql`${table.emailVerified} = true AND ${table.emailNormalized} IS NOT NULL`
96
+ ),
97
+ index("junior_identities_kind_provider_idx").on(table.kind, table.provider)
98
+ ]
99
+ );
100
+
101
+ // src/db/schema/conversations.ts
102
+ var juniorConversations = pgTable3(
103
+ "junior_conversations",
104
+ {
105
+ conversationId: text3("conversation_id").primaryKey(),
106
+ schemaVersion: integer("schema_version").notNull().default(1),
107
+ source: text3("source").$type(),
108
+ originType: text3("origin_type"),
109
+ originId: text3("origin_id"),
110
+ originRunId: text3("origin_run_id"),
111
+ destinationId: text3("destination_id").references(
112
+ () => juniorDestinations.id
113
+ ),
114
+ destination: jsonb2("destination_json").$type(),
115
+ actorIdentityId: text3("actor_identity_id").references(
116
+ () => juniorIdentities.id
117
+ ),
118
+ creatorIdentityId: text3("creator_identity_id").references(
119
+ () => juniorIdentities.id
120
+ ),
121
+ credentialSubjectIdentityId: text3(
122
+ "credential_subject_identity_id"
123
+ ).references(() => juniorIdentities.id),
124
+ actor: jsonb2("actor_json").$type(),
125
+ channelName: text3("channel_name"),
126
+ title: text3("title"),
127
+ createdAt: timestamptz("created_at").notNull(),
128
+ lastActivityAt: timestamptz("last_activity_at").notNull(),
129
+ updatedAt: timestamptz("updated_at").notNull(),
130
+ executionUpdatedAt: timestamptz("execution_updated_at"),
131
+ executionStatus: text3("execution_status").$type().notNull(),
132
+ runId: text3("run_id"),
133
+ lastCheckpointAt: timestamptz("last_checkpoint_at"),
134
+ lastEnqueuedAt: timestamptz("last_enqueued_at"),
135
+ // Subagent runs are child conversations; top-level listings filter
136
+ // parent_conversation_id IS NULL. Historical advisor children use this too.
137
+ parentConversationId: text3("parent_conversation_id").references(
138
+ () => juniorConversations.conversationId
139
+ ),
140
+ // Roots reference themselves; descendants reference the root whose actor
141
+ // and destination own their privacy boundary.
142
+ rootConversationId: text3("root_conversation_id").references(
143
+ () => juniorConversations.conversationId
144
+ ),
145
+ transcriptPurgedAt: timestamptz("transcript_purged_at"),
146
+ durationMs: integer("duration_ms").notNull().default(0),
147
+ usage: jsonb2("usage_json").$type(),
148
+ executionDurationMs: integer("execution_duration_ms").notNull().default(0),
149
+ executionUsage: jsonb2("execution_usage_json").$type(),
150
+ metricRunId: text3("metric_run_id"),
151
+ archivedAt: timestamptz("archived_at")
152
+ },
153
+ (table) => [
154
+ index2("junior_conversations_last_activity_idx").on(
155
+ table.lastActivityAt.desc(),
156
+ table.conversationId
157
+ ),
158
+ index2("junior_conversations_active_idx").using(
159
+ "btree",
160
+ sql2`coalesce(${table.executionUpdatedAt}, ${table.updatedAt})`,
161
+ table.conversationId
162
+ ).where(sql2`${table.executionStatus} <> 'idle'`),
163
+ index2("junior_conversations_destination_activity_idx").on(
164
+ table.destinationId,
165
+ table.lastActivityAt.desc()
166
+ ),
167
+ index2("junior_conversations_actor_activity_idx").on(
168
+ table.actorIdentityId,
169
+ table.lastActivityAt.desc()
170
+ ),
171
+ index2("junior_conversations_origin_idx").on(
172
+ table.originType,
173
+ table.originId,
174
+ table.lastActivityAt.desc()
175
+ ),
176
+ index2("junior_conversations_parent_idx").on(table.parentConversationId),
177
+ index2("junior_conversations_root_idx").on(table.rootConversationId)
178
+ ]
179
+ );
180
+
181
+ // src/db/schema/conversation-events.ts
182
+ var juniorConversationEvents = pgTable4(
183
+ "junior_conversation_events",
184
+ {
185
+ conversationId: text4("conversation_id").notNull(),
186
+ seq: integer2("seq").notNull(),
187
+ historyVersion: integer2("history_version").notNull(),
188
+ schemaVersion: integer2("schema_version").default(1).notNull(),
189
+ idempotencyKey: text4("idempotency_key"),
190
+ type: text4("type").notNull(),
191
+ payload: jsonb3("payload").$type().notNull(),
192
+ createdAt: timestamptz("created_at").notNull()
193
+ },
194
+ (table) => [
195
+ primaryKey({
196
+ name: "junior_conversation_events_conversation_id_seq_pk",
197
+ columns: [table.conversationId, table.seq]
198
+ }),
199
+ foreignKey({
200
+ name: "junior_conversation_events_conversation_id_junior_conversations_conversation_id_fk",
201
+ columns: [table.conversationId],
202
+ foreignColumns: [juniorConversations.conversationId]
203
+ }),
204
+ index3("junior_conversation_events_history_version_idx").on(
205
+ table.conversationId,
206
+ table.historyVersion,
207
+ table.seq
208
+ ),
209
+ index3("junior_conversation_events_type_idx").on(
210
+ table.conversationId,
211
+ table.type,
212
+ table.seq
213
+ ),
214
+ index3("junior_conversation_events_message_search_idx").using("gin", sql3`to_tsvector('english', ${table.payload}->>'text')`).where(sql3`${table.type} = 'message'`),
215
+ uniqueIndex3("junior_conversation_events_idempotency_idx").on(
216
+ table.conversationId,
217
+ table.idempotencyKey
218
+ )
219
+ ]
220
+ );
221
+
222
+ // src/db/schema.ts
223
+ var juniorSqlSchema = {
224
+ juniorConversationEvents,
225
+ juniorConversations,
226
+ juniorDestinations,
227
+ juniorIdentities,
228
+ juniorUsers
229
+ };
230
+
231
+ // src/db/neon.ts
232
+ var NeonExecutor = class {
233
+ constructor(pool) {
234
+ this.pool = pool;
235
+ }
236
+ pool;
237
+ transactionClient = new AsyncLocalStorage();
238
+ savepointId = 0;
239
+ db() {
240
+ return drizzle(this.queryClient(), {
241
+ schema: juniorSqlSchema
242
+ });
243
+ }
244
+ async execute(statement, params = []) {
245
+ await this.queryClient().query(statement, [...params]);
246
+ }
247
+ async query(statement, params = []) {
248
+ const result = await this.queryClient().query(statement, [
249
+ ...params
250
+ ]);
251
+ return result.rows;
252
+ }
253
+ async migrate(config) {
254
+ await migrate(
255
+ drizzle(this.queryClient(), { schema: juniorSqlSchema }),
256
+ config
257
+ );
258
+ }
259
+ async transaction(callback) {
260
+ const existingClient = this.transactionClient.getStore();
261
+ if (existingClient) {
262
+ const savepoint = `junior_savepoint_${++this.savepointId}`;
263
+ await existingClient.query(`SAVEPOINT ${savepoint}`);
264
+ try {
265
+ const result = await callback();
266
+ await existingClient.query(`RELEASE SAVEPOINT ${savepoint}`);
267
+ return result;
268
+ } catch (error) {
269
+ await existingClient.query(`ROLLBACK TO SAVEPOINT ${savepoint}`);
270
+ await existingClient.query(`RELEASE SAVEPOINT ${savepoint}`);
271
+ throw error;
272
+ }
273
+ }
274
+ const client = await this.pool.connect();
275
+ try {
276
+ await client.query("BEGIN");
277
+ const result = await this.transactionClient.run(client, callback);
278
+ await client.query("COMMIT");
279
+ return result;
280
+ } catch (error) {
281
+ await client.query("ROLLBACK");
282
+ throw error;
283
+ } finally {
284
+ client.release();
285
+ }
286
+ }
287
+ async withLock(lockName, callback) {
288
+ if (!lockName) {
289
+ throw new Error("SQL lock name is required");
290
+ }
291
+ const existingClient = this.transactionClient.getStore();
292
+ if (existingClient) {
293
+ await existingClient.query("SELECT pg_advisory_xact_lock(hashtext($1))", [
294
+ lockName
295
+ ]);
296
+ return await callback();
297
+ }
298
+ const client = await this.pool.connect();
299
+ try {
300
+ await client.query("BEGIN");
301
+ return await this.transactionClient.run(client, async () => {
302
+ try {
303
+ await client.query("SELECT pg_advisory_xact_lock(hashtext($1))", [
304
+ lockName
305
+ ]);
306
+ const result = await callback();
307
+ await client.query("COMMIT");
308
+ return result;
309
+ } catch (error) {
310
+ await client.query("ROLLBACK");
311
+ throw error;
312
+ }
313
+ });
314
+ } finally {
315
+ client.release();
316
+ }
317
+ }
318
+ async withMigrationLock(migrationTable, callback) {
319
+ const client = await this.pool.connect();
320
+ const lockName = `junior:migrate:${migrationTable}`;
321
+ try {
322
+ await client.query("SELECT pg_advisory_lock(hashtext($1))", [lockName]);
323
+ return await callback();
324
+ } finally {
325
+ client.release(true);
326
+ }
327
+ }
328
+ async close() {
329
+ await this.pool.end();
330
+ }
331
+ queryClient() {
332
+ return this.transactionClient.getStore() ?? this.pool;
333
+ }
334
+ };
335
+ function createNeonJuniorSqlExecutor(args) {
336
+ return new NeonExecutor(
337
+ new Pool({
338
+ connectionString: args.connectionString,
339
+ max: 3
340
+ })
341
+ );
342
+ }
343
+
344
+ // src/db/postgres.ts
345
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
346
+ import pg from "pg";
347
+ import { drizzle as drizzle2 } from "drizzle-orm/node-postgres";
348
+ import { migrate as migrate2 } from "drizzle-orm/node-postgres/migrator";
349
+ var { Pool: Pool2 } = pg;
350
+ var PostgresExecutor = class {
351
+ constructor(pool) {
352
+ this.pool = pool;
353
+ }
354
+ pool;
355
+ transactionClient = new AsyncLocalStorage2();
356
+ savepointId = 0;
357
+ db() {
358
+ return drizzle2(this.queryClient(), {
359
+ schema: juniorSqlSchema
360
+ });
361
+ }
362
+ async execute(statement, params = []) {
363
+ await this.queryClient().query(statement, [...params]);
364
+ }
365
+ async query(statement, params = []) {
366
+ const result = await this.queryClient().query(statement, [
367
+ ...params
368
+ ]);
369
+ return result.rows;
370
+ }
371
+ async migrate(config) {
372
+ await migrate2(
373
+ drizzle2(this.queryClient(), { schema: juniorSqlSchema }),
374
+ config
375
+ );
376
+ }
377
+ async transaction(callback) {
378
+ const existingClient = this.transactionClient.getStore();
379
+ if (existingClient) {
380
+ const savepoint = `junior_savepoint_${++this.savepointId}`;
381
+ await existingClient.query(`SAVEPOINT ${savepoint}`);
382
+ try {
383
+ const result = await callback();
384
+ await existingClient.query(`RELEASE SAVEPOINT ${savepoint}`);
385
+ return result;
386
+ } catch (error) {
387
+ await existingClient.query(`ROLLBACK TO SAVEPOINT ${savepoint}`);
388
+ await existingClient.query(`RELEASE SAVEPOINT ${savepoint}`);
389
+ throw error;
390
+ }
391
+ }
392
+ const client = await this.pool.connect();
393
+ try {
394
+ await client.query("BEGIN");
395
+ const result = await this.transactionClient.run(client, callback);
396
+ await client.query("COMMIT");
397
+ return result;
398
+ } catch (error) {
399
+ await client.query("ROLLBACK");
400
+ throw error;
401
+ } finally {
402
+ client.release();
403
+ }
404
+ }
405
+ async withLock(lockName, callback) {
406
+ if (!lockName) {
407
+ throw new Error("SQL lock name is required");
408
+ }
409
+ const existingClient = this.transactionClient.getStore();
410
+ if (existingClient) {
411
+ await existingClient.query("SELECT pg_advisory_xact_lock(hashtext($1))", [
412
+ lockName
413
+ ]);
414
+ return await callback();
415
+ }
416
+ const client = await this.pool.connect();
417
+ try {
418
+ await client.query("BEGIN");
419
+ return await this.transactionClient.run(client, async () => {
420
+ try {
421
+ await client.query("SELECT pg_advisory_xact_lock(hashtext($1))", [
422
+ lockName
423
+ ]);
424
+ const result = await callback();
425
+ await client.query("COMMIT");
426
+ return result;
427
+ } catch (error) {
428
+ await client.query("ROLLBACK");
429
+ throw error;
430
+ }
431
+ });
432
+ } finally {
433
+ client.release();
434
+ }
435
+ }
436
+ async withMigrationLock(migrationTable, callback) {
437
+ const client = await this.pool.connect();
438
+ const lockName = `junior:migrate:${migrationTable}`;
439
+ try {
440
+ await client.query("SELECT pg_advisory_lock(hashtext($1))", [lockName]);
441
+ return await callback();
442
+ } finally {
443
+ client.release(true);
444
+ }
445
+ }
446
+ async close() {
447
+ await this.pool.end();
448
+ }
449
+ queryClient() {
450
+ return this.transactionClient.getStore() ?? this.pool;
451
+ }
452
+ };
453
+ function createPostgresJuniorSqlExecutor(args) {
454
+ return new PostgresExecutor(
455
+ new Pool2({
456
+ application_name: args.applicationName,
457
+ connectionString: args.connectionString,
458
+ max: 3
459
+ })
460
+ );
461
+ }
462
+
463
+ // src/db/executor.ts
464
+ function createJuniorSqlExecutor(args) {
465
+ if (args.driver === "postgres") {
466
+ return createPostgresJuniorSqlExecutor(args);
467
+ }
468
+ return createNeonJuniorSqlExecutor(args);
469
+ }
470
+
471
+ export {
472
+ juniorUsers,
473
+ juniorIdentities,
474
+ juniorConversations,
475
+ juniorConversationEvents,
476
+ createJuniorSqlExecutor
477
+ };
@@ -3,16 +3,16 @@ import {
3
3
  } from "./chunk-4ZNGQH7C.js";
4
4
  import {
5
5
  getSlackBotToken
6
- } from "./chunk-SS67LUOK.js";
6
+ } from "./chunk-WNOVRQ67.js";
7
7
  import {
8
8
  logWarn,
9
9
  setSpanAttributes,
10
10
  setSpanStatus,
11
11
  withSpan
12
- } from "./chunk-O24R4DCK.js";
12
+ } from "./chunk-IYKPU7H6.js";
13
13
  import {
14
14
  parseSlackChannelReferenceId
15
- } from "./chunk-7FBGKXPE.js";
15
+ } from "./chunk-42WRQLJ6.js";
16
16
 
17
17
  // src/chat/slack/client.ts
18
18
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
@@ -1,16 +1,39 @@
1
1
  import {
2
2
  createVercelQueueClient
3
3
  } from "./chunk-KNFROR7R.js";
4
- import {
5
- destinationKey,
6
- parseDestination
7
- } from "./chunk-B7PUBQQM.js";
8
4
 
9
5
  // src/chat/task-execution/queue-signing.ts
10
6
  import { createHmac, timingSafeEqual } from "crypto";
11
- var CONVERSATION_WORK_QUEUE_SIGNATURE_CONTEXT = "junior.conversation_work_queue.v1";
12
- var CONVERSATION_WORK_QUEUE_SIGNATURE_VERSION = "v1";
7
+ import { z as z2 } from "zod";
8
+
9
+ // src/chat/task-execution/queue.ts
10
+ import { z } from "zod";
11
+ var conversationQueueMessageSchema = z.object({
12
+ conversationId: z.string().trim().min(1)
13
+ }).strict();
14
+ var ConversationQueueMessageRejectedError = class extends Error {
15
+ conversationId;
16
+ reason;
17
+ constructor(reason, message, options = {}) {
18
+ super(message);
19
+ this.name = "ConversationQueueMessageRejectedError";
20
+ this.reason = reason;
21
+ this.conversationId = options.conversationId;
22
+ }
23
+ };
24
+ function isConversationQueueMessageRejectedError(error) {
25
+ return error instanceof ConversationQueueMessageRejectedError;
26
+ }
27
+
28
+ // src/chat/task-execution/queue-signing.ts
29
+ var CONVERSATION_WORK_QUEUE_SIGNATURE_CONTEXT = "junior.conversation_work_queue.v2";
30
+ var CONVERSATION_WORK_QUEUE_SIGNATURE_VERSION = "v2";
13
31
  var CONVERSATION_WORK_QUEUE_SIGNATURE_MAX_SKEW_MS = 60 * 60 * 1e3;
32
+ var signedConversationQueueMessageSchema = conversationQueueMessageSchema.extend({
33
+ signature: z2.string().trim().min(1),
34
+ signatureVersion: z2.literal(CONVERSATION_WORK_QUEUE_SIGNATURE_VERSION),
35
+ signedAtMs: z2.number().finite()
36
+ }).strict();
14
37
  function getConversationWorkQueueSecret() {
15
38
  return process.env.JUNIOR_SECRET?.trim() || void 0;
16
39
  }
@@ -18,12 +41,11 @@ function buildSignedPayload(message, signedAtMs) {
18
41
  return [
19
42
  CONVERSATION_WORK_QUEUE_SIGNATURE_CONTEXT,
20
43
  signedAtMs,
21
- message.conversationId,
22
- destinationKey(message.destination)
44
+ message.conversationId
23
45
  ].join(":");
24
46
  }
25
- function signPayload(message, signedAtMs, secret) {
26
- return createHmac("sha256", secret).update(buildSignedPayload(message, signedAtMs)).digest("hex");
47
+ function signPayload(payload, secret) {
48
+ return createHmac("sha256", secret).update(payload).digest("hex");
27
49
  }
28
50
  function timingSafeMatch(expected, actual) {
29
51
  const expectedBuffer = Buffer.from(expected);
@@ -34,21 +56,8 @@ function timingSafeMatch(expected, actual) {
34
56
  return timingSafeEqual(expectedBuffer, actualBuffer);
35
57
  }
36
58
  function parseSignedConversationQueueMessage(value) {
37
- if (!value || typeof value !== "object") {
38
- return void 0;
39
- }
40
- const record = value;
41
- const destination = parseDestination(record.destination);
42
- if (typeof record.conversationId !== "string" || !record.conversationId.trim() || !destination || record.signatureVersion !== CONVERSATION_WORK_QUEUE_SIGNATURE_VERSION || typeof record.signedAtMs !== "number" || !Number.isFinite(record.signedAtMs) || typeof record.signature !== "string" || !record.signature.trim()) {
43
- return void 0;
44
- }
45
- return {
46
- conversationId: record.conversationId,
47
- destination,
48
- signature: record.signature,
49
- signatureVersion: CONVERSATION_WORK_QUEUE_SIGNATURE_VERSION,
50
- signedAtMs: record.signedAtMs
51
- };
59
+ const parsed = signedConversationQueueMessageSchema.safeParse(value);
60
+ return parsed.success ? parsed.data : void 0;
52
61
  }
53
62
  function signConversationQueueMessage(message, nowMs = Date.now()) {
54
63
  const secret = getConversationWorkQueueSecret();
@@ -61,7 +70,7 @@ function signConversationQueueMessage(message, nowMs = Date.now()) {
61
70
  ...message,
62
71
  signedAtMs: nowMs,
63
72
  signatureVersion: CONVERSATION_WORK_QUEUE_SIGNATURE_VERSION,
64
- signature: signPayload(message, nowMs, secret)
73
+ signature: signPayload(buildSignedPayload(message, nowMs), secret)
65
74
  };
66
75
  }
67
76
  function verifyConversationQueueMessage(value, nowMs = Date.now()) {
@@ -79,16 +88,16 @@ function verifyConversationQueueMessage(value, nowMs = Date.now()) {
79
88
  if (Math.abs(nowMs - message.signedAtMs) > CONVERSATION_WORK_QUEUE_SIGNATURE_MAX_SKEW_MS) {
80
89
  return { status: "rejected", reason: "expired" };
81
90
  }
82
- const expected = signPayload(message, message.signedAtMs, secret);
91
+ const expected = signPayload(
92
+ buildSignedPayload(message, message.signedAtMs),
93
+ secret
94
+ );
83
95
  if (!timingSafeMatch(expected, message.signature)) {
84
96
  return { status: "rejected", reason: "signature_mismatch" };
85
97
  }
86
98
  return {
87
99
  status: "verified",
88
- message: {
89
- conversationId: message.conversationId,
90
- destination: message.destination
91
- }
100
+ message: { conversationId: message.conversationId }
92
101
  };
93
102
  }
94
103
 
@@ -130,6 +139,9 @@ function getVercelConversationWorkQueue() {
130
139
  }
131
140
 
132
141
  export {
142
+ conversationQueueMessageSchema,
143
+ ConversationQueueMessageRejectedError,
144
+ isConversationQueueMessageRejectedError,
133
145
  verifyConversationQueueMessage,
134
146
  resolveConversationWorkQueueTopic,
135
147
  getVercelConversationWorkQueue