@okrlinkhub/agent-factory 0.2.4 → 0.2.6

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 (40) hide show
  1. package/README.md +32 -0
  2. package/dist/client/index.d.ts +145 -3
  3. package/dist/client/index.d.ts.map +1 -1
  4. package/dist/client/index.js +201 -0
  5. package/dist/client/index.js.map +1 -1
  6. package/dist/component/_generated/api.d.ts +2 -0
  7. package/dist/component/_generated/api.d.ts.map +1 -1
  8. package/dist/component/_generated/api.js.map +1 -1
  9. package/dist/component/_generated/component.d.ts +516 -4
  10. package/dist/component/_generated/component.d.ts.map +1 -1
  11. package/dist/component/lib.d.ts +1 -0
  12. package/dist/component/lib.d.ts.map +1 -1
  13. package/dist/component/lib.js +1 -0
  14. package/dist/component/lib.js.map +1 -1
  15. package/dist/component/pushing.d.ts +256 -0
  16. package/dist/component/pushing.d.ts.map +1 -0
  17. package/dist/component/pushing.js +962 -0
  18. package/dist/component/pushing.js.map +1 -0
  19. package/dist/component/queue.d.ts +8 -7
  20. package/dist/component/queue.d.ts.map +1 -1
  21. package/dist/component/queue.js +54 -1
  22. package/dist/component/queue.js.map +1 -1
  23. package/dist/component/scheduler.d.ts +5 -5
  24. package/dist/component/scheduler.js +13 -1
  25. package/dist/component/scheduler.js.map +1 -1
  26. package/dist/component/schema.d.ts +258 -8
  27. package/dist/component/schema.d.ts.map +1 -1
  28. package/dist/component/schema.js +103 -0
  29. package/dist/component/schema.js.map +1 -1
  30. package/package.json +1 -1
  31. package/src/client/index.test.ts +29 -19
  32. package/src/client/index.ts +218 -0
  33. package/src/component/_generated/api.ts +2 -0
  34. package/src/component/_generated/component.ts +520 -4
  35. package/src/component/lib.test.ts +98 -0
  36. package/src/component/lib.ts +17 -0
  37. package/src/component/pushing.ts +1121 -0
  38. package/src/component/queue.ts +65 -1
  39. package/src/component/scheduler.ts +17 -1
  40. package/src/component/schema.ts +137 -0
@@ -288,15 +288,16 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
288
288
  {
289
289
  agentKey: string;
290
290
  bridgeConfig?: {
291
+ appBaseUrlMapJsonSecretRef?: string;
291
292
  appKey?: string;
292
293
  baseUrl?: string;
293
294
  enabled: boolean;
294
- appBaseUrlMapJsonSecretRef?: string;
295
295
  serviceId?: string;
296
296
  serviceKeySecretRef?: string;
297
297
  };
298
298
  clientMd?: string;
299
299
  enabled: boolean;
300
+ providerUserId?: string;
300
301
  secretsRef: Array<string>;
301
302
  skills: Array<string>;
302
303
  soulMd: string;
@@ -365,6 +366,67 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
365
366
  },
366
367
  Name
367
368
  >;
369
+ createPushJobCustom: FunctionReference<
370
+ "mutation",
371
+ "internal",
372
+ {
373
+ companyId: string;
374
+ consumerUserId: string;
375
+ enabled?: boolean;
376
+ nowMs?: number;
377
+ periodicity: "manual" | "daily" | "weekly" | "monthly";
378
+ schedule:
379
+ | { kind: "manual" }
380
+ | { kind: "daily"; time: string }
381
+ | { kind: "weekly"; time: string; weekday: number }
382
+ | { dayOfMonth: number | "last"; kind: "monthly"; time: string };
383
+ text: string;
384
+ timezone: string;
385
+ title: string;
386
+ },
387
+ string,
388
+ Name
389
+ >;
390
+ createPushJobFromTemplate: FunctionReference<
391
+ "mutation",
392
+ "internal",
393
+ {
394
+ companyId: string;
395
+ consumerUserId: string;
396
+ enabled?: boolean;
397
+ nowMs?: number;
398
+ schedule?:
399
+ | { kind: "manual" }
400
+ | { kind: "daily"; time: string }
401
+ | { kind: "weekly"; time: string; weekday: number }
402
+ | { dayOfMonth: number | "last"; kind: "monthly"; time: string };
403
+ templateId: string;
404
+ timezone: string;
405
+ },
406
+ string,
407
+ Name
408
+ >;
409
+ createPushTemplate: FunctionReference<
410
+ "mutation",
411
+ "internal",
412
+ {
413
+ actorUserId: string;
414
+ companyId: string;
415
+ enabled?: boolean;
416
+ nowMs?: number;
417
+ periodicity: "manual" | "daily" | "weekly" | "monthly";
418
+ suggestedTimes: Array<
419
+ | { kind: "daily"; time: string }
420
+ | { kind: "weekly"; time: string; weekday: number }
421
+ | { dayOfMonth: number | "last"; kind: "monthly"; time: string }
422
+ >;
423
+ templateKey: string;
424
+ text: string;
425
+ title: string;
426
+ },
427
+ string,
428
+ Name
429
+ >;
368
430
  deleteFlyVolume: FunctionReference<
369
431
  "action",
370
432
  "internal",
@@ -372,6 +434,40 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
372
434
  { message: string; ok: boolean; status: number },
373
435
  Name
374
436
  >;
437
+ deletePushJob: FunctionReference<
438
+ "mutation",
439
+ "internal",
440
+ { jobId: string },
441
+ boolean,
442
+ Name
443
+ >;
444
+ deletePushTemplate: FunctionReference<
445
+ "mutation",
446
+ "internal",
447
+ { templateId: string },
448
+ boolean,
449
+ Name
450
+ >;
451
+ dispatchDuePushJobs: FunctionReference<
452
+ "mutation",
453
+ "internal",
454
+ {
455
+ limit?: number;
456
+ nowMs?: number;
457
+ providerConfig?: {
458
+ appName: string;
459
+ image: string;
460
+ kind: "fly" | "runpod" | "ecs";
461
+ organizationSlug: string;
462
+ region: string;
463
+ volumeName: string;
464
+ volumePath: string;
465
+ volumeSizeGb: number;
466
+ };
467
+ },
468
+ { enqueued: number; failed: number; scanned: number; skipped: number },
469
+ Name
470
+ >;
375
471
  enqueue: FunctionReference<
376
472
  "mutation",
377
473
  "internal",
@@ -445,9 +541,9 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
445
541
  null | {
446
542
  agentKey: string;
447
543
  bridgeRuntimeConfig: null | {
544
+ appBaseUrlMapJson: null | string;
448
545
  appKey: null | string;
449
546
  baseUrl: null | string;
450
- appBaseUrlMapJson: null | string;
451
547
  serviceId: null | string;
452
548
  serviceKey: null | string;
453
549
  serviceKeySecretRef: null | string;
@@ -542,6 +638,72 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
542
638
  { secretId: string; secretRef: string; version: number },
543
639
  Name
544
640
  >;
641
+ listPushDispatchesByJob: FunctionReference<
642
+ "query",
643
+ "internal",
644
+ { jobId: string; limit?: number },
645
+ Array<{
646
+ _id: string;
647
+ createdAt: number;
648
+ error: null | string;
649
+ runKey: string;
650
+ scheduledFor: number;
651
+ status: "enqueued" | "skipped" | "failed";
652
+ }>,
653
+ Name
654
+ >;
655
+ listPushJobsForUser: FunctionReference<
656
+ "query",
657
+ "internal",
658
+ { consumerUserId: string; includeDisabled?: boolean },
659
+ Array<{
660
+ _id: string;
661
+ agentKey: null | string;
662
+ companyId: string;
663
+ consumerUserId: string;
664
+ createdAt: number;
665
+ enabled: boolean;
666
+ lastRunAt: null | number;
667
+ lastRunKey: null | string;
668
+ nextRunAt: null | number;
669
+ periodicity: "manual" | "daily" | "weekly" | "monthly";
670
+ schedule:
671
+ | { kind: "manual" }
672
+ | { kind: "daily"; time: string }
673
+ | { kind: "weekly"; time: string; weekday: number }
674
+ | { dayOfMonth: number | "last"; kind: "monthly"; time: string };
675
+ sourceTemplateId: null | string;
676
+ text: string;
677
+ timezone: string;
678
+ title: string;
679
+ updatedAt: number;
680
+ }>,
681
+ Name
682
+ >;
683
+ listPushTemplatesByCompany: FunctionReference<
684
+ "query",
685
+ "internal",
686
+ { companyId: string; includeDisabled?: boolean },
687
+ Array<{
688
+ _id: string;
689
+ companyId: string;
690
+ createdAt: number;
691
+ createdBy: string;
692
+ enabled: boolean;
693
+ periodicity: "manual" | "daily" | "weekly" | "monthly";
694
+ suggestedTimes: Array<
695
+ | { kind: "daily"; time: string }
696
+ | { kind: "weekly"; time: string; weekday: number }
697
+ | { dayOfMonth: number | "last"; kind: "monthly"; time: string }
698
+ >;
699
+ templateKey: string;
700
+ text: string;
701
+ title: string;
702
+ updatedAt: number;
703
+ updatedBy: string;
704
+ }>,
705
+ Name
706
+ >;
545
707
  queueStats: FunctionReference<
546
708
  "query",
547
709
  "internal",
@@ -617,6 +779,101 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
617
779
  }>,
618
780
  Name
619
781
  >;
782
+ sendBroadcastToAllActiveAgents: FunctionReference<
783
+ "mutation",
784
+ "internal",
785
+ {
786
+ companyId: string;
787
+ nowMs?: number;
788
+ providerConfig?: {
789
+ appName: string;
790
+ image: string;
791
+ kind: "fly" | "runpod" | "ecs";
792
+ organizationSlug: string;
793
+ region: string;
794
+ volumeName: string;
795
+ volumePath: string;
796
+ volumeSizeGb: number;
797
+ };
798
+ requestedBy: string;
799
+ text: string;
800
+ title: string;
801
+ },
802
+ {
803
+ broadcastId: string;
804
+ enqueued: number;
805
+ failed: number;
806
+ totalTargets: number;
807
+ },
808
+ Name
809
+ >;
810
+ setPushJobEnabled: FunctionReference<
811
+ "mutation",
812
+ "internal",
813
+ { enabled: boolean; jobId: string; nowMs?: number },
814
+ boolean,
815
+ Name
816
+ >;
817
+ triggerPushJobNow: FunctionReference<
818
+ "mutation",
819
+ "internal",
820
+ {
821
+ jobId: string;
822
+ nowMs?: number;
823
+ providerConfig?: {
824
+ appName: string;
825
+ image: string;
826
+ kind: "fly" | "runpod" | "ecs";
827
+ organizationSlug: string;
828
+ region: string;
829
+ volumeName: string;
830
+ volumePath: string;
831
+ volumeSizeGb: number;
832
+ };
833
+ },
834
+ { enqueuedMessageId: string; runKey: string },
835
+ Name
836
+ >;
837
+ updatePushJob: FunctionReference<
838
+ "mutation",
839
+ "internal",
840
+ {
841
+ enabled?: boolean;
842
+ jobId: string;
843
+ nowMs?: number;
844
+ periodicity?: "manual" | "daily" | "weekly" | "monthly";
845
+ schedule?:
846
+ | { kind: "manual" }
847
+ | { kind: "daily"; time: string }
848
+ | { kind: "weekly"; time: string; weekday: number }
849
+ | { dayOfMonth: number | "last"; kind: "monthly"; time: string };
850
+ text?: string;
851
+ timezone?: string;
852
+ title?: string;
853
+ },
854
+ boolean,
855
+ Name
856
+ >;
857
+ updatePushTemplate: FunctionReference<
858
+ "mutation",
859
+ "internal",
860
+ {
861
+ actorUserId: string;
862
+ enabled?: boolean;
863
+ nowMs?: number;
864
+ periodicity?: "manual" | "daily" | "weekly" | "monthly";
865
+ suggestedTimes?: Array<
866
+ | { kind: "daily"; time: string }
867
+ | { kind: "weekly"; time: string; weekday: number }
868
+ | { dayOfMonth: number | "last"; kind: "monthly"; time: string }
869
+ >;
870
+ templateId: string;
871
+ text?: string;
872
+ title?: string;
873
+ },
874
+ boolean,
875
+ Name
876
+ >;
620
877
  workerStats: FunctionReference<
621
878
  "query",
622
879
  "internal",
@@ -647,6 +904,264 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
647
904
  >;
648
905
  };
649
906
  };
907
+ pushing: {
908
+ createPushJobCustom: FunctionReference<
909
+ "mutation",
910
+ "internal",
911
+ {
912
+ companyId: string;
913
+ consumerUserId: string;
914
+ enabled?: boolean;
915
+ nowMs?: number;
916
+ periodicity: "manual" | "daily" | "weekly" | "monthly";
917
+ schedule:
918
+ | { kind: "manual" }
919
+ | { kind: "daily"; time: string }
920
+ | { kind: "weekly"; time: string; weekday: number }
921
+ | { dayOfMonth: number | "last"; kind: "monthly"; time: string };
922
+ text: string;
923
+ timezone: string;
924
+ title: string;
925
+ },
926
+ string,
927
+ Name
928
+ >;
929
+ createPushJobFromTemplate: FunctionReference<
930
+ "mutation",
931
+ "internal",
932
+ {
933
+ companyId: string;
934
+ consumerUserId: string;
935
+ enabled?: boolean;
936
+ nowMs?: number;
937
+ schedule?:
938
+ | { kind: "manual" }
939
+ | { kind: "daily"; time: string }
940
+ | { kind: "weekly"; time: string; weekday: number }
941
+ | { dayOfMonth: number | "last"; kind: "monthly"; time: string };
942
+ templateId: string;
943
+ timezone: string;
944
+ },
945
+ string,
946
+ Name
947
+ >;
948
+ createPushTemplate: FunctionReference<
949
+ "mutation",
950
+ "internal",
951
+ {
952
+ actorUserId: string;
953
+ companyId: string;
954
+ enabled?: boolean;
955
+ nowMs?: number;
956
+ periodicity: "manual" | "daily" | "weekly" | "monthly";
957
+ suggestedTimes: Array<
958
+ | { kind: "daily"; time: string }
959
+ | { kind: "weekly"; time: string; weekday: number }
960
+ | { dayOfMonth: number | "last"; kind: "monthly"; time: string }
961
+ >;
962
+ templateKey: string;
963
+ text: string;
964
+ title: string;
965
+ },
966
+ string,
967
+ Name
968
+ >;
969
+ deletePushJob: FunctionReference<
970
+ "mutation",
971
+ "internal",
972
+ { jobId: string },
973
+ boolean,
974
+ Name
975
+ >;
976
+ deletePushTemplate: FunctionReference<
977
+ "mutation",
978
+ "internal",
979
+ { templateId: string },
980
+ boolean,
981
+ Name
982
+ >;
983
+ dispatchDuePushJobs: FunctionReference<
984
+ "mutation",
985
+ "internal",
986
+ {
987
+ limit?: number;
988
+ nowMs?: number;
989
+ providerConfig?: {
990
+ appName: string;
991
+ image: string;
992
+ kind: "fly" | "runpod" | "ecs";
993
+ organizationSlug: string;
994
+ region: string;
995
+ volumeName: string;
996
+ volumePath: string;
997
+ volumeSizeGb: number;
998
+ };
999
+ },
1000
+ { enqueued: number; failed: number; scanned: number; skipped: number },
1001
+ Name
1002
+ >;
1003
+ listPushDispatchesByJob: FunctionReference<
1004
+ "query",
1005
+ "internal",
1006
+ { jobId: string; limit?: number },
1007
+ Array<{
1008
+ _id: string;
1009
+ createdAt: number;
1010
+ error: null | string;
1011
+ runKey: string;
1012
+ scheduledFor: number;
1013
+ status: "enqueued" | "skipped" | "failed";
1014
+ }>,
1015
+ Name
1016
+ >;
1017
+ listPushJobsForUser: FunctionReference<
1018
+ "query",
1019
+ "internal",
1020
+ { consumerUserId: string; includeDisabled?: boolean },
1021
+ Array<{
1022
+ _id: string;
1023
+ agentKey: null | string;
1024
+ companyId: string;
1025
+ consumerUserId: string;
1026
+ createdAt: number;
1027
+ enabled: boolean;
1028
+ lastRunAt: null | number;
1029
+ lastRunKey: null | string;
1030
+ nextRunAt: null | number;
1031
+ periodicity: "manual" | "daily" | "weekly" | "monthly";
1032
+ schedule:
1033
+ | { kind: "manual" }
1034
+ | { kind: "daily"; time: string }
1035
+ | { kind: "weekly"; time: string; weekday: number }
1036
+ | { dayOfMonth: number | "last"; kind: "monthly"; time: string };
1037
+ sourceTemplateId: null | string;
1038
+ text: string;
1039
+ timezone: string;
1040
+ title: string;
1041
+ updatedAt: number;
1042
+ }>,
1043
+ Name
1044
+ >;
1045
+ listPushTemplatesByCompany: FunctionReference<
1046
+ "query",
1047
+ "internal",
1048
+ { companyId: string; includeDisabled?: boolean },
1049
+ Array<{
1050
+ _id: string;
1051
+ companyId: string;
1052
+ createdAt: number;
1053
+ createdBy: string;
1054
+ enabled: boolean;
1055
+ periodicity: "manual" | "daily" | "weekly" | "monthly";
1056
+ suggestedTimes: Array<
1057
+ | { kind: "daily"; time: string }
1058
+ | { kind: "weekly"; time: string; weekday: number }
1059
+ | { dayOfMonth: number | "last"; kind: "monthly"; time: string }
1060
+ >;
1061
+ templateKey: string;
1062
+ text: string;
1063
+ title: string;
1064
+ updatedAt: number;
1065
+ updatedBy: string;
1066
+ }>,
1067
+ Name
1068
+ >;
1069
+ sendBroadcastToAllActiveAgents: FunctionReference<
1070
+ "mutation",
1071
+ "internal",
1072
+ {
1073
+ companyId: string;
1074
+ nowMs?: number;
1075
+ providerConfig?: {
1076
+ appName: string;
1077
+ image: string;
1078
+ kind: "fly" | "runpod" | "ecs";
1079
+ organizationSlug: string;
1080
+ region: string;
1081
+ volumeName: string;
1082
+ volumePath: string;
1083
+ volumeSizeGb: number;
1084
+ };
1085
+ requestedBy: string;
1086
+ text: string;
1087
+ title: string;
1088
+ },
1089
+ {
1090
+ broadcastId: string;
1091
+ enqueued: number;
1092
+ failed: number;
1093
+ totalTargets: number;
1094
+ },
1095
+ Name
1096
+ >;
1097
+ setPushJobEnabled: FunctionReference<
1098
+ "mutation",
1099
+ "internal",
1100
+ { enabled: boolean; jobId: string; nowMs?: number },
1101
+ boolean,
1102
+ Name
1103
+ >;
1104
+ triggerPushJobNow: FunctionReference<
1105
+ "mutation",
1106
+ "internal",
1107
+ {
1108
+ jobId: string;
1109
+ nowMs?: number;
1110
+ providerConfig?: {
1111
+ appName: string;
1112
+ image: string;
1113
+ kind: "fly" | "runpod" | "ecs";
1114
+ organizationSlug: string;
1115
+ region: string;
1116
+ volumeName: string;
1117
+ volumePath: string;
1118
+ volumeSizeGb: number;
1119
+ };
1120
+ },
1121
+ { enqueuedMessageId: string; runKey: string },
1122
+ Name
1123
+ >;
1124
+ updatePushJob: FunctionReference<
1125
+ "mutation",
1126
+ "internal",
1127
+ {
1128
+ enabled?: boolean;
1129
+ jobId: string;
1130
+ nowMs?: number;
1131
+ periodicity?: "manual" | "daily" | "weekly" | "monthly";
1132
+ schedule?:
1133
+ | { kind: "manual" }
1134
+ | { kind: "daily"; time: string }
1135
+ | { kind: "weekly"; time: string; weekday: number }
1136
+ | { dayOfMonth: number | "last"; kind: "monthly"; time: string };
1137
+ text?: string;
1138
+ timezone?: string;
1139
+ title?: string;
1140
+ },
1141
+ boolean,
1142
+ Name
1143
+ >;
1144
+ updatePushTemplate: FunctionReference<
1145
+ "mutation",
1146
+ "internal",
1147
+ {
1148
+ actorUserId: string;
1149
+ enabled?: boolean;
1150
+ nowMs?: number;
1151
+ periodicity?: "manual" | "daily" | "weekly" | "monthly";
1152
+ suggestedTimes?: Array<
1153
+ | { kind: "daily"; time: string }
1154
+ | { kind: "weekly"; time: string; weekday: number }
1155
+ | { dayOfMonth: number | "last"; kind: "monthly"; time: string }
1156
+ >;
1157
+ templateId: string;
1158
+ text?: string;
1159
+ title?: string;
1160
+ },
1161
+ boolean,
1162
+ Name
1163
+ >;
1164
+ };
650
1165
  queue: {
651
1166
  appendConversationMessages: FunctionReference<
652
1167
  "mutation",
@@ -808,9 +1323,9 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
808
1323
  null | {
809
1324
  agentKey: string;
810
1325
  bridgeRuntimeConfig: null | {
1326
+ appBaseUrlMapJson: null | string;
811
1327
  appKey: null | string;
812
1328
  baseUrl: null | string;
813
- appBaseUrlMapJson: null | string;
814
1329
  serviceId: null | string;
815
1330
  serviceKey: null | string;
816
1331
  serviceKeySecretRef: null | string;
@@ -987,15 +1502,16 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
987
1502
  {
988
1503
  agentKey: string;
989
1504
  bridgeConfig?: {
1505
+ appBaseUrlMapJsonSecretRef?: string;
990
1506
  appKey?: string;
991
1507
  baseUrl?: string;
992
1508
  enabled: boolean;
993
- appBaseUrlMapJsonSecretRef?: string;
994
1509
  serviceId?: string;
995
1510
  serviceKeySecretRef?: string;
996
1511
  };
997
1512
  clientMd?: string;
998
1513
  enabled: boolean;
1514
+ providerUserId?: string;
999
1515
  secretsRef: Array<string>;
1000
1516
  skills: Array<string>;
1001
1517
  soulMd: string;
@@ -456,4 +456,102 @@ describe("component lib", () => {
456
456
  expect(reconcile.spawned).toBe(0);
457
457
  expect(reconcile.terminated).toBe(0);
458
458
  });
459
+
460
+ test("push jobs should dispatch scheduled messages and log runs", async () => {
461
+ const t = initConvexTest();
462
+ await t.mutation(api.queue.upsertAgentProfile, {
463
+ agentKey: "push-agent",
464
+ version: "1.0.0",
465
+ soulMd: "# Soul",
466
+ clientMd: "# Client",
467
+ skills: [],
468
+ secretsRef: [],
469
+ enabled: true,
470
+ });
471
+ await t.mutation(api.lib.bindUserAgent, {
472
+ consumerUserId: "user-push-1",
473
+ agentKey: "push-agent",
474
+ source: "manual",
475
+ metadata: { companyId: "co-1" },
476
+ });
477
+
478
+ const baseMs = Date.UTC(2026, 0, 1, 7, 59, 0);
479
+ const jobId = await t.mutation((api.lib as any).createPushJobCustom, {
480
+ companyId: "co-1",
481
+ consumerUserId: "user-push-1",
482
+ title: "Daily check",
483
+ text: "Ping automatico",
484
+ periodicity: "daily",
485
+ timezone: "UTC",
486
+ schedule: {
487
+ kind: "daily",
488
+ time: "08:00",
489
+ },
490
+ nowMs: baseMs,
491
+ });
492
+
493
+ const dispatch = await t.mutation((api.lib as any).dispatchDuePushJobs, {
494
+ nowMs: baseMs + 6 * 60_000,
495
+ limit: 50,
496
+ });
497
+ expect(dispatch.enqueued).toBe(1);
498
+ expect(dispatch.failed).toBe(0);
499
+
500
+ const queueStats = await t.query(api.lib.queueStats, {});
501
+ expect(queueStats.queuedReady).toBe(1);
502
+
503
+ const jobDispatches = await t.query((api.lib as any).listPushDispatchesByJob, {
504
+ jobId,
505
+ limit: 10,
506
+ });
507
+ expect(jobDispatches.length).toBe(1);
508
+ expect(jobDispatches[0].status).toBe("enqueued");
509
+ });
510
+
511
+ test("admin broadcast should enqueue to all active company agents", async () => {
512
+ const t = initConvexTest();
513
+ await t.mutation(api.queue.upsertAgentProfile, {
514
+ agentKey: "broadcast-agent-a",
515
+ version: "1.0.0",
516
+ soulMd: "# Soul",
517
+ clientMd: "# Client",
518
+ skills: [],
519
+ secretsRef: [],
520
+ enabled: true,
521
+ });
522
+ await t.mutation(api.queue.upsertAgentProfile, {
523
+ agentKey: "broadcast-agent-b",
524
+ version: "1.0.0",
525
+ soulMd: "# Soul",
526
+ clientMd: "# Client",
527
+ skills: [],
528
+ secretsRef: [],
529
+ enabled: true,
530
+ });
531
+ await t.mutation(api.lib.bindUserAgent, {
532
+ consumerUserId: "company-user-a",
533
+ agentKey: "broadcast-agent-a",
534
+ source: "manual",
535
+ metadata: { companyId: "company-broadcast" },
536
+ });
537
+ await t.mutation(api.lib.bindUserAgent, {
538
+ consumerUserId: "company-user-b",
539
+ agentKey: "broadcast-agent-b",
540
+ source: "manual",
541
+ metadata: { companyId: "company-broadcast" },
542
+ });
543
+
544
+ const result = await t.mutation((api.lib as any).sendBroadcastToAllActiveAgents, {
545
+ companyId: "company-broadcast",
546
+ title: "Aggiornamento policy",
547
+ text: "Sincronizza le nuove istruzioni",
548
+ requestedBy: "admin-1",
549
+ });
550
+ expect(result.totalTargets).toBe(2);
551
+ expect(result.enqueued).toBe(2);
552
+ expect(result.failed).toBe(0);
553
+
554
+ const queueStats = await t.query(api.lib.queueStats, {});
555
+ expect(queueStats.queuedReady).toBe(2);
556
+ });
459
557
  });