@okrlinkhub/agent-factory 2.0.0 → 2.0.1

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.
@@ -40,6 +40,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
40
40
  agentKey: string;
41
41
  boundAt: number;
42
42
  consumerUserId: string;
43
+ conversationId: string;
43
44
  metadata: null | Record<string, string>;
44
45
  revokedAt: null | number;
45
46
  source: "manual" | "telegram_pairing" | "api";
@@ -247,6 +248,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
247
248
  agentKey: string;
248
249
  boundAt: number;
249
250
  consumerUserId: string;
251
+ conversationId: string;
250
252
  metadata: null | Record<string, string>;
251
253
  revokedAt: null | number;
252
254
  source: "manual" | "telegram_pairing" | "api";
@@ -372,7 +374,11 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
372
374
  "query",
373
375
  "internal",
374
376
  { telegramChatId?: string; telegramUserId?: string },
375
- { agentKey: null | string; consumerUserId: null | string },
377
+ {
378
+ agentKey: null | string;
379
+ consumerUserId: null | string;
380
+ conversationId: null | string;
381
+ },
376
382
  Name
377
383
  >;
378
384
  resolveAgentForUser: FunctionReference<
@@ -430,6 +436,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
430
436
  agentKey: string;
431
437
  boundAt: number;
432
438
  consumerUserId: string;
439
+ conversationId: string;
433
440
  metadata: null | Record<string, string>;
434
441
  revokedAt: null | number;
435
442
  source: "manual" | "telegram_pairing" | "api";
@@ -475,6 +482,16 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
475
482
  leaseId: string;
476
483
  messageId: string;
477
484
  payload: {
485
+ attachments?: Array<{
486
+ expiresAt: number;
487
+ fileName?: string;
488
+ kind: "photo" | "video" | "audio" | "voice" | "document";
489
+ mimeType?: string;
490
+ sizeBytes?: number;
491
+ status: "ready" | "expired";
492
+ storageId: string;
493
+ telegramFileId: string;
494
+ }>;
478
495
  externalMessageId?: string;
479
496
  messageText: string;
480
497
  metadata?: Record<string, string>;
@@ -765,6 +782,16 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
765
782
  maxAttempts?: number;
766
783
  nowMs?: number;
767
784
  payload: {
785
+ attachments?: Array<{
786
+ expiresAt: number;
787
+ fileName?: string;
788
+ kind: "photo" | "video" | "audio" | "voice" | "document";
789
+ mimeType?: string;
790
+ sizeBytes?: number;
791
+ status: "ready" | "expired";
792
+ storageId: string;
793
+ telegramFileId: string;
794
+ }>;
768
795
  externalMessageId?: string;
769
796
  messageText: string;
770
797
  metadata?: Record<string, string>;
@@ -886,6 +913,16 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
886
913
  lastError: null | string;
887
914
  maxAttempts: number;
888
915
  payload: {
916
+ attachments?: Array<{
917
+ expiresAt: number;
918
+ fileName?: string;
919
+ kind: "photo" | "video" | "audio" | "voice" | "document";
920
+ mimeType?: string;
921
+ sizeBytes?: number;
922
+ status: "ready" | "expired";
923
+ storageId: string;
924
+ telegramFileId: string;
925
+ }>;
889
926
  externalMessageId?: string;
890
927
  messageText: string;
891
928
  metadata?: Record<string, string>;
@@ -929,6 +966,16 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
929
966
  };
930
967
  messageId: string;
931
968
  payload: {
969
+ attachments?: Array<{
970
+ expiresAt: number;
971
+ fileName?: string;
972
+ kind: "photo" | "video" | "audio" | "voice" | "document";
973
+ mimeType?: string;
974
+ sizeBytes?: number;
975
+ status: "ready" | "expired";
976
+ storageId: string;
977
+ telegramFileId: string;
978
+ }>;
932
979
  externalMessageId?: string;
933
980
  messageText: string;
934
981
  metadata?: Record<string, string>;
@@ -945,7 +992,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
945
992
  "internal",
946
993
  { agentKey: string; consumerUserId: string; nowMs?: number },
947
994
  null | {
948
- conversationId: null | string;
995
+ conversationId: string;
949
996
  createdAt: number;
950
997
  downloadUrl: null | string;
951
998
  sha256: null | string;
@@ -1040,6 +1087,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
1040
1087
  agentKey: string;
1041
1088
  boundAt: number;
1042
1089
  consumerUserId: string;
1090
+ conversationId: string;
1043
1091
  metadata: null | Record<string, string>;
1044
1092
  revokedAt: null | number;
1045
1093
  source: "manual" | "telegram_pairing" | "api";
@@ -1323,6 +1371,16 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
1323
1371
  lastError: null | string;
1324
1372
  maxAttempts: number;
1325
1373
  payload: {
1374
+ attachments?: Array<{
1375
+ expiresAt: number;
1376
+ fileName?: string;
1377
+ kind: "photo" | "video" | "audio" | "voice" | "document";
1378
+ mimeType?: string;
1379
+ sizeBytes?: number;
1380
+ status: "ready" | "expired";
1381
+ storageId: string;
1382
+ telegramFileId: string;
1383
+ }>;
1326
1384
  externalMessageId?: string;
1327
1385
  messageText: string;
1328
1386
  metadata?: Record<string, string>;
@@ -1356,6 +1414,16 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
1356
1414
  lastError: null | string;
1357
1415
  maxAttempts: number;
1358
1416
  payload: {
1417
+ attachments?: Array<{
1418
+ expiresAt: number;
1419
+ fileName?: string;
1420
+ kind: "photo" | "video" | "audio" | "voice" | "document";
1421
+ mimeType?: string;
1422
+ sizeBytes?: number;
1423
+ status: "ready" | "expired";
1424
+ storageId: string;
1425
+ telegramFileId: string;
1426
+ }>;
1359
1427
  externalMessageId?: string;
1360
1428
  messageText: string;
1361
1429
  metadata?: Record<string, string>;
@@ -1374,7 +1442,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
1374
1442
  "internal",
1375
1443
  { conversationId: string; limit?: number; nowMs?: number },
1376
1444
  Array<{
1377
- conversationId: null | string;
1445
+ conversationId: string;
1378
1446
  createdAt: number;
1379
1447
  downloadUrl: null | string;
1380
1448
  sha256: null | string;
@@ -1394,7 +1462,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
1394
1462
  nowMs?: number;
1395
1463
  },
1396
1464
  Array<{
1397
- conversationId: null | string;
1465
+ conversationId: string;
1398
1466
  createdAt: number;
1399
1467
  downloadUrl: null | string;
1400
1468
  sha256: null | string;
@@ -1429,7 +1497,10 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
1429
1497
  "query",
1430
1498
  "internal",
1431
1499
  {},
1432
- null | { systemPrompt?: string },
1500
+ null | {
1501
+ systemPrompt?: string;
1502
+ telegramAttachmentRetentionMs?: number;
1503
+ },
1433
1504
  Name
1434
1505
  >;
1435
1506
  providerRuntimeConfig: FunctionReference<
@@ -1495,7 +1566,11 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
1495
1566
  "query",
1496
1567
  "internal",
1497
1568
  { telegramChatId?: string; telegramUserId?: string },
1498
- { agentKey: null | string; consumerUserId: null | string },
1569
+ {
1570
+ agentKey: null | string;
1571
+ consumerUserId: null | string;
1572
+ conversationId: null | string;
1573
+ },
1499
1574
  Name
1500
1575
  >;
1501
1576
  resolveAgentForUser: FunctionReference<
@@ -1577,7 +1652,13 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
1577
1652
  setMessageRuntimeConfig: FunctionReference<
1578
1653
  "mutation",
1579
1654
  "internal",
1580
- { messageConfig: { systemPrompt?: string }; nowMs?: number },
1655
+ {
1656
+ messageConfig: {
1657
+ systemPrompt?: string;
1658
+ telegramAttachmentRetentionMs?: number;
1659
+ };
1660
+ nowMs?: number;
1661
+ },
1581
1662
  null,
1582
1663
  Name
1583
1664
  >;
@@ -2201,6 +2282,16 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
2201
2282
  leaseId: string;
2202
2283
  messageId: string;
2203
2284
  payload: {
2285
+ attachments?: Array<{
2286
+ expiresAt: number;
2287
+ fileName?: string;
2288
+ kind: "photo" | "video" | "audio" | "voice" | "document";
2289
+ mimeType?: string;
2290
+ sizeBytes?: number;
2291
+ status: "ready" | "expired";
2292
+ storageId: string;
2293
+ telegramFileId: string;
2294
+ }>;
2204
2295
  externalMessageId?: string;
2205
2296
  messageText: string;
2206
2297
  metadata?: Record<string, string>;
@@ -2280,6 +2371,16 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
2280
2371
  maxAttempts?: number;
2281
2372
  nowMs?: number;
2282
2373
  payload: {
2374
+ attachments?: Array<{
2375
+ expiresAt: number;
2376
+ fileName?: string;
2377
+ kind: "photo" | "video" | "audio" | "voice" | "document";
2378
+ mimeType?: string;
2379
+ sizeBytes?: number;
2380
+ status: "ready" | "expired";
2381
+ storageId: string;
2382
+ telegramFileId: string;
2383
+ }>;
2283
2384
  externalMessageId?: string;
2284
2385
  messageText: string;
2285
2386
  metadata?: Record<string, string>;
@@ -2387,6 +2488,16 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
2387
2488
  lastError: null | string;
2388
2489
  maxAttempts: number;
2389
2490
  payload: {
2491
+ attachments?: Array<{
2492
+ expiresAt: number;
2493
+ fileName?: string;
2494
+ kind: "photo" | "video" | "audio" | "voice" | "document";
2495
+ mimeType?: string;
2496
+ sizeBytes?: number;
2497
+ status: "ready" | "expired";
2498
+ storageId: string;
2499
+ telegramFileId: string;
2500
+ }>;
2390
2501
  externalMessageId?: string;
2391
2502
  messageText: string;
2392
2503
  metadata?: Record<string, string>;
@@ -2430,6 +2541,16 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
2430
2541
  };
2431
2542
  messageId: string;
2432
2543
  payload: {
2544
+ attachments?: Array<{
2545
+ expiresAt: number;
2546
+ fileName?: string;
2547
+ kind: "photo" | "video" | "audio" | "voice" | "document";
2548
+ mimeType?: string;
2549
+ sizeBytes?: number;
2550
+ status: "ready" | "expired";
2551
+ storageId: string;
2552
+ telegramFileId: string;
2553
+ }>;
2433
2554
  externalMessageId?: string;
2434
2555
  messageText: string;
2435
2556
  metadata?: Record<string, string>;
@@ -2446,7 +2567,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
2446
2567
  "internal",
2447
2568
  {
2448
2569
  agentKey: string;
2449
- conversationId?: string;
2570
+ conversationId: string;
2450
2571
  nowMs?: number;
2451
2572
  workspaceId: string;
2452
2573
  },
@@ -2464,7 +2585,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
2464
2585
  "internal",
2465
2586
  { agentKey: string; consumerUserId: string; nowMs?: number },
2466
2587
  null | {
2467
- conversationId: null | string;
2588
+ conversationId: string;
2468
2589
  createdAt: number;
2469
2590
  downloadUrl: null | string;
2470
2591
  sha256: null | string;
@@ -2643,6 +2764,16 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
2643
2764
  lastError: null | string;
2644
2765
  maxAttempts: number;
2645
2766
  payload: {
2767
+ attachments?: Array<{
2768
+ expiresAt: number;
2769
+ fileName?: string;
2770
+ kind: "photo" | "video" | "audio" | "voice" | "document";
2771
+ mimeType?: string;
2772
+ sizeBytes?: number;
2773
+ status: "ready" | "expired";
2774
+ storageId: string;
2775
+ telegramFileId: string;
2776
+ }>;
2646
2777
  externalMessageId?: string;
2647
2778
  messageText: string;
2648
2779
  metadata?: Record<string, string>;
@@ -2676,6 +2807,16 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
2676
2807
  lastError: null | string;
2677
2808
  maxAttempts: number;
2678
2809
  payload: {
2810
+ attachments?: Array<{
2811
+ expiresAt: number;
2812
+ fileName?: string;
2813
+ kind: "photo" | "video" | "audio" | "voice" | "document";
2814
+ mimeType?: string;
2815
+ sizeBytes?: number;
2816
+ status: "ready" | "expired";
2817
+ storageId: string;
2818
+ telegramFileId: string;
2819
+ }>;
2679
2820
  externalMessageId?: string;
2680
2821
  messageText: string;
2681
2822
  metadata?: Record<string, string>;
@@ -2694,7 +2835,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
2694
2835
  "internal",
2695
2836
  { conversationId: string; limit?: number; nowMs?: number },
2696
2837
  Array<{
2697
- conversationId: null | string;
2838
+ conversationId: string;
2698
2839
  createdAt: number;
2699
2840
  downloadUrl: null | string;
2700
2841
  sha256: null | string;
@@ -2714,7 +2855,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
2714
2855
  nowMs?: number;
2715
2856
  },
2716
2857
  Array<{
2717
- conversationId: null | string;
2858
+ conversationId: string;
2718
2859
  createdAt: number;
2719
2860
  downloadUrl: null | string;
2720
2861
  sha256: null | string;
@@ -2728,7 +2869,10 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
2728
2869
  "query",
2729
2870
  "internal",
2730
2871
  {},
2731
- null | { systemPrompt?: string },
2872
+ null | {
2873
+ systemPrompt?: string;
2874
+ telegramAttachmentRetentionMs?: number;
2875
+ },
2732
2876
  Name
2733
2877
  >;
2734
2878
  prepareDataSnapshotUpload: FunctionReference<
@@ -2736,7 +2880,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
2736
2880
  "internal",
2737
2881
  {
2738
2882
  agentKey: string;
2739
- conversationId?: string;
2883
+ conversationId: string;
2740
2884
  nowMs?: number;
2741
2885
  reason: "drain" | "signal" | "manual";
2742
2886
  workerId: string;
@@ -2806,7 +2950,13 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
2806
2950
  setMessageRuntimeConfig: FunctionReference<
2807
2951
  "mutation",
2808
2952
  "internal",
2809
- { messageConfig: { systemPrompt?: string }; nowMs?: number },
2953
+ {
2954
+ messageConfig: {
2955
+ systemPrompt?: string;
2956
+ telegramAttachmentRetentionMs?: number;
2957
+ };
2958
+ nowMs?: number;
2959
+ },
2810
2960
  null,
2811
2961
  Name
2812
2962
  >;
@@ -201,6 +201,138 @@ describe("component lib", () => {
201
201
  expect(claim?.payload.messageText).toBe("hello");
202
202
  });
203
203
 
204
+ test("message runtime config should store telegram attachment retention", async () => {
205
+ const t = initConvexTest();
206
+ await t.mutation(api.lib.setMessageRuntimeConfig, {
207
+ messageConfig: {
208
+ telegramAttachmentRetentionMs: 60_000,
209
+ },
210
+ });
211
+
212
+ const storedMessageConfig = await t.query(api.lib.messageRuntimeConfig, {});
213
+ expect(storedMessageConfig).toEqual({
214
+ telegramAttachmentRetentionMs: 60_000,
215
+ });
216
+ });
217
+
218
+ test("enqueue should persist telegram attachments for claimed jobs", async () => {
219
+ const t = initConvexTest();
220
+ const nowMs = Date.UTC(2026, 0, 1, 9, 0, 0);
221
+ vi.setSystemTime(nowMs);
222
+ await t.mutation(api.queue.upsertAgentProfile, {
223
+ agentKey: "attachment-agent",
224
+ version: "1.0.0",
225
+ secretsRef: [],
226
+ enabled: true,
227
+ });
228
+ const storageId = await t.run(async (ctx) => {
229
+ return await ctx.storage.store(new Blob(["photo-binary"], { type: "image/jpeg" }));
230
+ });
231
+
232
+ const messageId = await t.mutation(api.lib.enqueue, {
233
+ conversationId: "telegram:chat:attachment",
234
+ agentKey: "attachment-agent",
235
+ payload: {
236
+ provider: "telegram",
237
+ providerUserId: "u-attachment-1",
238
+ messageText: "[telegram media] photo message",
239
+ attachments: [
240
+ {
241
+ kind: "photo",
242
+ status: "ready",
243
+ storageId,
244
+ telegramFileId: "telegram-photo-1",
245
+ mimeType: "image/jpeg",
246
+ sizeBytes: 12,
247
+ expiresAt: nowMs + 60_000,
248
+ },
249
+ ],
250
+ },
251
+ nowMs,
252
+ });
253
+
254
+ const claim = await t.mutation(api.lib.claim, {
255
+ workerId: "worker-attachment-1",
256
+ nowMs,
257
+ });
258
+ expect(claim?.messageId).toBe(messageId);
259
+ expect(claim?.payload.attachments).toHaveLength(1);
260
+ expect(claim?.payload.attachments?.[0]?.telegramFileId).toBe("telegram-photo-1");
261
+
262
+ const bundle = await t.query(api.lib.getHydrationBundle, {
263
+ messageId,
264
+ workspaceId: "default",
265
+ });
266
+ expect(bundle?.payload.attachments).toHaveLength(1);
267
+ expect(bundle?.payload.attachments?.[0]?.storageId).toBe(storageId);
268
+
269
+ const attachmentRows = await t.run(async (ctx) => {
270
+ return await ctx.db
271
+ .query("messageAttachments")
272
+ .withIndex("by_messageId", (q) => q.eq("messageId", messageId))
273
+ .collect();
274
+ });
275
+ expect(attachmentRows).toHaveLength(1);
276
+ expect(attachmentRows[0]?.status).toBe("ready");
277
+ });
278
+
279
+ test("expireOldTelegramAttachments should expire stored attachments and queued payloads", async () => {
280
+ const t = initConvexTest();
281
+ const nowMs = Date.UTC(2026, 0, 1, 10, 0, 0);
282
+ vi.setSystemTime(nowMs);
283
+ await t.mutation(api.queue.upsertAgentProfile, {
284
+ agentKey: "attachment-expiry-agent",
285
+ version: "1.0.0",
286
+ secretsRef: [],
287
+ enabled: true,
288
+ });
289
+ const storageId = await t.run(async (ctx) => {
290
+ return await ctx.storage.store(new Blob(["document-binary"], { type: "application/pdf" }));
291
+ });
292
+
293
+ const messageId = await t.mutation(api.queue.enqueueMessage, {
294
+ conversationId: "telegram:chat:attachment-expiry",
295
+ agentKey: "attachment-expiry-agent",
296
+ payload: {
297
+ provider: "telegram",
298
+ providerUserId: "u-attachment-expiry-1",
299
+ messageText: "[telegram media] document message",
300
+ attachments: [
301
+ {
302
+ kind: "document",
303
+ status: "ready",
304
+ storageId,
305
+ telegramFileId: "telegram-document-1",
306
+ fileName: "brief.pdf",
307
+ mimeType: "application/pdf",
308
+ sizeBytes: 15,
309
+ expiresAt: nowMs + 10,
310
+ },
311
+ ],
312
+ },
313
+ nowMs,
314
+ });
315
+
316
+ const expired = await t.mutation((internal.queue as any).expireOldTelegramAttachments, {
317
+ nowMs: nowMs + 11,
318
+ limit: 10,
319
+ });
320
+ expect(expired).toBe(1);
321
+
322
+ const attachmentRows = await t.run(async (ctx) => {
323
+ return await ctx.db
324
+ .query("messageAttachments")
325
+ .withIndex("by_messageId", (q) => q.eq("messageId", messageId))
326
+ .collect();
327
+ });
328
+ expect(attachmentRows[0]?.status).toBe("expired");
329
+
330
+ const messageRow = await t.run(async (ctx) => {
331
+ return await ctx.db.get(messageId);
332
+ });
333
+ expect(messageRow?.payload.attachments?.[0]?.status).toBe("expired");
334
+ });
335
+
204
336
  test("enqueue should fail when providerUserId is blank in payload", async () => {
205
337
  const t = initConvexTest();
206
338
  await t.mutation(api.queue.upsertAgentProfile, {