@memberjunction/server 5.44.0 → 5.45.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.
- package/dist/agentSessions/ReturningVisitorRecap.d.ts +39 -0
- package/dist/agentSessions/ReturningVisitorRecap.d.ts.map +1 -0
- package/dist/agentSessions/ReturningVisitorRecap.js +198 -0
- package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -0
- package/dist/agentSessions/SessionJanitor.d.ts +13 -0
- package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
- package/dist/agentSessions/SessionJanitor.js +65 -7
- package/dist/agentSessions/SessionJanitor.js.map +1 -1
- package/dist/agentSessions/SessionManager.d.ts.map +1 -1
- package/dist/agentSessions/SessionManager.js +37 -0
- package/dist/agentSessions/SessionManager.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.d.ts +10 -0
- package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkRouter.js +16 -0
- package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.d.ts +7 -0
- package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
- package/dist/auth/magicLink/MagicLinkService.js +13 -3
- package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
- package/dist/auth/magicLink/index.d.ts +1 -1
- package/dist/auth/magicLink/index.d.ts.map +1 -1
- package/dist/auth/magicLink/index.js +1 -1
- package/dist/auth/magicLink/index.js.map +1 -1
- package/dist/auth/magicLink/magicLinkCore.d.ts +38 -1
- package/dist/auth/magicLink/magicLinkCore.d.ts.map +1 -1
- package/dist/auth/magicLink/magicLinkCore.js +42 -19
- package/dist/auth/magicLink/magicLinkCore.js.map +1 -1
- package/dist/auth/magicLink/types.d.ts +26 -0
- package/dist/auth/magicLink/types.d.ts.map +1 -1
- package/dist/config.d.ts +1883 -144
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +160 -36
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +45 -2
- package/dist/context.js.map +1 -1
- package/dist/generated/generated.d.ts +522 -0
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +2860 -0
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +13 -0
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +22 -0
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +4 -0
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +101 -3
- package/dist/index.js.map +1 -1
- package/dist/integration/CustomColumnPromoter.d.ts.map +1 -1
- package/dist/integration/CustomColumnPromoter.js +6 -0
- package/dist/integration/CustomColumnPromoter.js.map +1 -1
- package/dist/realtimeWidget/WidgetRouter.d.ts +26 -0
- package/dist/realtimeWidget/WidgetRouter.d.ts.map +1 -0
- package/dist/realtimeWidget/WidgetRouter.js +182 -0
- package/dist/realtimeWidget/WidgetRouter.js.map +1 -0
- package/dist/realtimeWidget/WidgetSessionService.d.ts +265 -0
- package/dist/realtimeWidget/WidgetSessionService.d.ts.map +1 -0
- package/dist/realtimeWidget/WidgetSessionService.js +477 -0
- package/dist/realtimeWidget/WidgetSessionService.js.map +1 -0
- package/dist/realtimeWidget/host-identity.d.ts +40 -0
- package/dist/realtimeWidget/host-identity.d.ts.map +1 -0
- package/dist/realtimeWidget/host-identity.js +58 -0
- package/dist/realtimeWidget/host-identity.js.map +1 -0
- package/dist/realtimeWidget/index.d.ts +10 -0
- package/dist/realtimeWidget/index.d.ts.map +1 -0
- package/dist/realtimeWidget/index.js +9 -0
- package/dist/realtimeWidget/index.js.map +1 -0
- package/dist/realtimeWidget/visitorIdentity.d.ts +76 -0
- package/dist/realtimeWidget/visitorIdentity.d.ts.map +1 -0
- package/dist/realtimeWidget/visitorIdentity.js +202 -0
- package/dist/realtimeWidget/visitorIdentity.js.map +1 -0
- package/dist/realtimeWidget/widgetCore.d.ts +106 -0
- package/dist/realtimeWidget/widgetCore.d.ts.map +1 -0
- package/dist/realtimeWidget/widgetCore.js +173 -0
- package/dist/realtimeWidget/widgetCore.js.map +1 -0
- package/dist/realtimeWidget/widgetGuestElevation.d.ts +51 -0
- package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -0
- package/dist/realtimeWidget/widgetGuestElevation.js +79 -0
- package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -0
- package/dist/resolvers/ComponentRegistryResolver.d.ts +7 -0
- package/dist/resolvers/ComponentRegistryResolver.d.ts.map +1 -1
- package/dist/resolvers/ComponentRegistryResolver.js +31 -8
- package/dist/resolvers/ComponentRegistryResolver.js.map +1 -1
- package/dist/resolvers/EntityPermissionResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityPermissionResolver.js +1 -2
- package/dist/resolvers/EntityPermissionResolver.js.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.d.ts +9 -6
- package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
- package/dist/resolvers/QuerySystemUserResolver.js +15 -13
- package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts +10 -0
- package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
- package/dist/resolvers/RealtimeClientSessionResolver.js +47 -3
- package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
- package/dist/resolvers/RingCentralTelephonyResolver.d.ts +27 -0
- package/dist/resolvers/RingCentralTelephonyResolver.d.ts.map +1 -0
- package/dist/resolvers/RingCentralTelephonyResolver.js +87 -0
- package/dist/resolvers/RingCentralTelephonyResolver.js.map +1 -0
- package/dist/resolvers/RunAIAgentResolver.d.ts +9 -0
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +20 -4
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/SearchKnowledgeResolver.d.ts.map +1 -1
- package/dist/resolvers/SearchKnowledgeResolver.js +2 -0
- package/dist/resolvers/SearchKnowledgeResolver.js.map +1 -1
- package/dist/resolvers/TeamsMeetingsResolver.d.ts +28 -0
- package/dist/resolvers/TeamsMeetingsResolver.d.ts.map +1 -0
- package/dist/resolvers/TeamsMeetingsResolver.js +91 -0
- package/dist/resolvers/TeamsMeetingsResolver.js.map +1 -0
- package/dist/resolvers/TelephonyResolver.d.ts +26 -0
- package/dist/resolvers/TelephonyResolver.d.ts.map +1 -0
- package/dist/resolvers/TelephonyResolver.js +86 -0
- package/dist/resolvers/TelephonyResolver.js.map +1 -0
- package/dist/resolvers/TestQuerySQLResolver.d.ts +1 -1
- package/dist/resolvers/TestQuerySQLResolver.d.ts.map +1 -1
- package/dist/resolvers/TestQuerySQLResolver.js +2 -3
- package/dist/resolvers/TestQuerySQLResolver.js.map +1 -1
- package/dist/resolvers/VonageTelephonyResolver.d.ts +26 -0
- package/dist/resolvers/VonageTelephonyResolver.d.ts.map +1 -0
- package/dist/resolvers/VonageTelephonyResolver.js +86 -0
- package/dist/resolvers/VonageTelephonyResolver.js.map +1 -0
- package/dist/rest/MediaStreamHandler.js +4 -1
- package/dist/rest/MediaStreamHandler.js.map +1 -1
- package/dist/telephony/RingCentralTelephonyService.d.ts +115 -0
- package/dist/telephony/RingCentralTelephonyService.d.ts.map +1 -0
- package/dist/telephony/RingCentralTelephonyService.js +262 -0
- package/dist/telephony/RingCentralTelephonyService.js.map +1 -0
- package/dist/telephony/TeamsMeetingsRouter.d.ts +40 -0
- package/dist/telephony/TeamsMeetingsRouter.d.ts.map +1 -0
- package/dist/telephony/TeamsMeetingsRouter.js +96 -0
- package/dist/telephony/TeamsMeetingsRouter.js.map +1 -0
- package/dist/telephony/TeamsMeetingsService.d.ts +113 -0
- package/dist/telephony/TeamsMeetingsService.d.ts.map +1 -0
- package/dist/telephony/TeamsMeetingsService.js +196 -0
- package/dist/telephony/TeamsMeetingsService.js.map +1 -0
- package/dist/telephony/TwilioTelephonyRouter.d.ts +36 -0
- package/dist/telephony/TwilioTelephonyRouter.d.ts.map +1 -0
- package/dist/telephony/TwilioTelephonyRouter.js +143 -0
- package/dist/telephony/TwilioTelephonyRouter.js.map +1 -0
- package/dist/telephony/TwilioTelephonyService.d.ts +95 -0
- package/dist/telephony/TwilioTelephonyService.d.ts.map +1 -0
- package/dist/telephony/TwilioTelephonyService.js +193 -0
- package/dist/telephony/TwilioTelephonyService.js.map +1 -0
- package/dist/telephony/VonageTelephonyRouter.d.ts +41 -0
- package/dist/telephony/VonageTelephonyRouter.d.ts.map +1 -0
- package/dist/telephony/VonageTelephonyRouter.js +201 -0
- package/dist/telephony/VonageTelephonyRouter.js.map +1 -0
- package/dist/telephony/VonageTelephonyService.d.ts +90 -0
- package/dist/telephony/VonageTelephonyService.d.ts.map +1 -0
- package/dist/telephony/VonageTelephonyService.js +191 -0
- package/dist/telephony/VonageTelephonyService.js.map +1 -0
- package/dist/telephony/calendar-scheduler.d.ts +67 -0
- package/dist/telephony/calendar-scheduler.d.ts.map +1 -0
- package/dist/telephony/calendar-scheduler.js +133 -0
- package/dist/telephony/calendar-scheduler.js.map +1 -0
- package/dist/telephony/index.d.ts +29 -0
- package/dist/telephony/index.d.ts.map +1 -0
- package/dist/telephony/index.js +38 -0
- package/dist/telephony/index.js.map +1 -0
- package/dist/telephony/media-upgrade-router.d.ts +33 -0
- package/dist/telephony/media-upgrade-router.d.ts.map +1 -0
- package/dist/telephony/media-upgrade-router.js +56 -0
- package/dist/telephony/media-upgrade-router.js.map +1 -0
- package/dist/telephony/ringcentral-runtime.d.ts +14 -0
- package/dist/telephony/ringcentral-runtime.d.ts.map +1 -0
- package/dist/telephony/ringcentral-runtime.js +18 -0
- package/dist/telephony/ringcentral-runtime.js.map +1 -0
- package/dist/telephony/teams-meetings-runtime.d.ts +16 -0
- package/dist/telephony/teams-meetings-runtime.d.ts.map +1 -0
- package/dist/telephony/teams-meetings-runtime.js +20 -0
- package/dist/telephony/teams-meetings-runtime.js.map +1 -0
- package/dist/telephony/teamsAcsMediaRegistry.d.ts +69 -0
- package/dist/telephony/teamsAcsMediaRegistry.d.ts.map +1 -0
- package/dist/telephony/teamsAcsMediaRegistry.js +118 -0
- package/dist/telephony/teamsAcsMediaRegistry.js.map +1 -0
- package/dist/telephony/telephony-runtime.d.ts +14 -0
- package/dist/telephony/telephony-runtime.d.ts.map +1 -0
- package/dist/telephony/telephony-runtime.js +18 -0
- package/dist/telephony/telephony-runtime.js.map +1 -0
- package/dist/telephony/twilioMediaRegistry.d.ts +60 -0
- package/dist/telephony/twilioMediaRegistry.d.ts.map +1 -0
- package/dist/telephony/twilioMediaRegistry.js +106 -0
- package/dist/telephony/twilioMediaRegistry.js.map +1 -0
- package/dist/telephony/vonage-runtime.d.ts +14 -0
- package/dist/telephony/vonage-runtime.d.ts.map +1 -0
- package/dist/telephony/vonage-runtime.js +18 -0
- package/dist/telephony/vonage-runtime.js.map +1 -0
- package/dist/telephony/vonageMediaRegistry.d.ts +78 -0
- package/dist/telephony/vonageMediaRegistry.d.ts.map +1 -0
- package/dist/telephony/vonageMediaRegistry.js +158 -0
- package/dist/telephony/vonageMediaRegistry.js.map +1 -0
- package/package.json +88 -83
- package/src/__tests__/RunAIAgentResolver.streaming.test.ts +128 -0
- package/src/__tests__/magicLink.test.ts +53 -3
- package/src/__tests__/search-knowledge-tags.test.ts +9 -9
- package/src/__tests__/teams-meetings-service.test.ts +65 -0
- package/src/__tests__/teamsAcsMediaRegistry.test.ts +82 -0
- package/src/__tests__/twilio-telephony-service.test.ts +23 -0
- package/src/__tests__/twilioMediaRegistry.test.ts +103 -0
- package/src/__tests__/vonageMediaRegistry.test.ts +180 -0
- package/src/__tests__/widget.test.ts +204 -0
- package/src/__tests__/widgetGuestElevation.test.ts +57 -0
- package/src/__tests__/widgetHostIdentity.test.ts +117 -0
- package/src/agentSessions/ReturningVisitorRecap.ts +242 -0
- package/src/agentSessions/SessionJanitor.ts +66 -6
- package/src/agentSessions/SessionManager.ts +38 -0
- package/src/auth/magicLink/MagicLinkRouter.ts +17 -0
- package/src/auth/magicLink/MagicLinkService.ts +13 -3
- package/src/auth/magicLink/index.ts +1 -0
- package/src/auth/magicLink/magicLinkCore.ts +48 -20
- package/src/auth/magicLink/types.ts +26 -0
- package/src/config.ts +172 -38
- package/src/context.ts +50 -3
- package/src/generated/generated.ts +1991 -1
- package/src/generic/ResolverBase.ts +28 -0
- package/src/generic/RunViewResolver.ts +4 -0
- package/src/index.ts +109 -3
- package/src/integration/CustomColumnPromoter.ts +6 -0
- package/src/realtimeWidget/WidgetRouter.ts +204 -0
- package/src/realtimeWidget/WidgetSessionService.ts +714 -0
- package/src/realtimeWidget/host-identity.ts +84 -0
- package/src/realtimeWidget/index.ts +15 -0
- package/src/realtimeWidget/visitorIdentity.ts +258 -0
- package/src/realtimeWidget/widgetCore.ts +231 -0
- package/src/realtimeWidget/widgetGuestElevation.ts +115 -0
- package/src/resolvers/ComponentRegistryResolver.ts +36 -10
- package/src/resolvers/EntityPermissionResolver.ts +1 -2
- package/src/resolvers/QuerySystemUserResolver.ts +14 -10
- package/src/resolvers/RealtimeClientSessionResolver.ts +59 -2
- package/src/resolvers/RingCentralTelephonyResolver.ts +64 -0
- package/src/resolvers/RunAIAgentResolver.ts +32 -8
- package/src/resolvers/SearchKnowledgeResolver.ts +2 -0
- package/src/resolvers/TeamsMeetingsResolver.ts +68 -0
- package/src/resolvers/TelephonyResolver.ts +63 -0
- package/src/resolvers/TestQuerySQLResolver.ts +2 -3
- package/src/resolvers/VonageTelephonyResolver.ts +63 -0
- package/src/rest/MediaStreamHandler.ts +4 -1
- package/src/telephony/RingCentralTelephonyService.ts +342 -0
- package/src/telephony/TeamsMeetingsRouter.ts +124 -0
- package/src/telephony/TeamsMeetingsService.ts +268 -0
- package/src/telephony/TwilioTelephonyRouter.ts +184 -0
- package/src/telephony/TwilioTelephonyService.ts +261 -0
- package/src/telephony/VonageTelephonyRouter.ts +239 -0
- package/src/telephony/VonageTelephonyService.ts +259 -0
- package/src/telephony/calendar-scheduler.ts +176 -0
- package/src/telephony/index.ts +43 -0
- package/src/telephony/media-upgrade-router.ts +62 -0
- package/src/telephony/ringcentral-runtime.ts +22 -0
- package/src/telephony/teams-meetings-runtime.ts +24 -0
- package/src/telephony/teamsAcsMediaRegistry.ts +152 -0
- package/src/telephony/telephony-runtime.ts +22 -0
- package/src/telephony/twilioMediaRegistry.ts +137 -0
- package/src/telephony/vonage-runtime.ts +22 -0
- package/src/telephony/vonageMediaRegistry.ts +200 -0
- package/dist/agents/skip-agent.d.ts +0 -111
- package/dist/agents/skip-agent.d.ts.map +0 -1
- package/dist/agents/skip-agent.js +0 -1487
- package/dist/agents/skip-agent.js.map +0 -1
- package/dist/agents/skip-sdk.d.ts +0 -261
- package/dist/agents/skip-sdk.d.ts.map +0 -1
- package/dist/agents/skip-sdk.js +0 -909
- package/dist/agents/skip-sdk.js.map +0 -1
- package/src/agents/skip-agent.ts +0 -1594
- package/src/agents/skip-sdk.ts +0 -1210
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/server",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.45.1",
|
|
4
4
|
"description": "MemberJunction: This project provides API access via GraphQL to the common data store.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -27,88 +27,93 @@
|
|
|
27
27
|
"@as-integrations/express5": "^1.0.0",
|
|
28
28
|
"@graphql-tools/schema": "latest",
|
|
29
29
|
"@graphql-tools/utils": "^11.0.0",
|
|
30
|
-
"@memberjunction/actions": "5.
|
|
31
|
-
"@memberjunction/actions-apollo": "5.
|
|
32
|
-
"@memberjunction/actions-base": "5.
|
|
33
|
-
"@memberjunction/actions-bizapps-accounting": "5.
|
|
34
|
-
"@memberjunction/actions-bizapps-crm": "5.
|
|
35
|
-
"@memberjunction/actions-bizapps-formbuilders": "5.
|
|
36
|
-
"@memberjunction/actions-bizapps-lms": "5.
|
|
37
|
-
"@memberjunction/actions-bizapps-social": "5.
|
|
38
|
-
"@memberjunction/ai": "5.
|
|
39
|
-
"@memberjunction/ai-agent-manager": "5.
|
|
40
|
-
"@memberjunction/ai-agent-manager-actions": "5.
|
|
41
|
-
"@memberjunction/ai-agents": "5.
|
|
42
|
-
"@memberjunction/ai-bridge-
|
|
43
|
-
"@memberjunction/ai-
|
|
44
|
-
"@memberjunction/ai-
|
|
45
|
-
"@memberjunction/ai-
|
|
46
|
-
"@memberjunction/ai-
|
|
47
|
-
"@memberjunction/ai-
|
|
48
|
-
"@memberjunction/ai-
|
|
49
|
-
"@memberjunction/ai-
|
|
50
|
-
"@memberjunction/ai-
|
|
51
|
-
"@memberjunction/
|
|
52
|
-
"@memberjunction/
|
|
53
|
-
"@memberjunction/
|
|
54
|
-
"@memberjunction/
|
|
55
|
-
"@memberjunction/
|
|
56
|
-
"@memberjunction/
|
|
57
|
-
"@memberjunction/
|
|
58
|
-
"@memberjunction/
|
|
59
|
-
"@memberjunction/
|
|
60
|
-
"@memberjunction/
|
|
61
|
-
"@memberjunction/
|
|
62
|
-
"@memberjunction/
|
|
63
|
-
"@memberjunction/
|
|
64
|
-
"@memberjunction/
|
|
65
|
-
"@memberjunction/
|
|
66
|
-
"@memberjunction/
|
|
67
|
-
"@memberjunction/
|
|
68
|
-
"@memberjunction/
|
|
69
|
-
"@memberjunction/
|
|
70
|
-
"@memberjunction/
|
|
71
|
-
"@memberjunction/
|
|
72
|
-
"@memberjunction/
|
|
73
|
-
"@memberjunction/
|
|
74
|
-
"@memberjunction/
|
|
75
|
-
"@memberjunction/
|
|
76
|
-
"@memberjunction/
|
|
77
|
-
"@memberjunction/
|
|
78
|
-
"@memberjunction/
|
|
79
|
-
"@memberjunction/
|
|
80
|
-
"@memberjunction/
|
|
81
|
-
"@memberjunction/
|
|
82
|
-
"@memberjunction/
|
|
83
|
-
"@memberjunction/
|
|
84
|
-
"@memberjunction/
|
|
85
|
-
"@memberjunction/
|
|
86
|
-
"@memberjunction/
|
|
87
|
-
"@memberjunction/
|
|
88
|
-
"@memberjunction/
|
|
89
|
-
"@memberjunction/
|
|
90
|
-
"@memberjunction/
|
|
91
|
-
"@memberjunction/
|
|
92
|
-
"@memberjunction/
|
|
93
|
-
"@memberjunction/
|
|
94
|
-
"@memberjunction/
|
|
95
|
-
"@memberjunction/
|
|
96
|
-
"@memberjunction/
|
|
97
|
-
"@memberjunction/
|
|
98
|
-
"@memberjunction/
|
|
99
|
-
"@memberjunction/
|
|
100
|
-
"@memberjunction/
|
|
101
|
-
"@memberjunction/
|
|
102
|
-
"@memberjunction/
|
|
103
|
-
"@memberjunction/
|
|
104
|
-
"@memberjunction/
|
|
105
|
-
"@memberjunction/
|
|
106
|
-
"@memberjunction/
|
|
107
|
-
"@memberjunction/
|
|
108
|
-
"@memberjunction/
|
|
109
|
-
"@memberjunction/
|
|
110
|
-
"@memberjunction/
|
|
111
|
-
"@memberjunction/
|
|
30
|
+
"@memberjunction/actions": "5.45.1",
|
|
31
|
+
"@memberjunction/actions-apollo": "5.45.1",
|
|
32
|
+
"@memberjunction/actions-base": "5.45.1",
|
|
33
|
+
"@memberjunction/actions-bizapps-accounting": "5.45.1",
|
|
34
|
+
"@memberjunction/actions-bizapps-crm": "5.45.1",
|
|
35
|
+
"@memberjunction/actions-bizapps-formbuilders": "5.45.1",
|
|
36
|
+
"@memberjunction/actions-bizapps-lms": "5.45.1",
|
|
37
|
+
"@memberjunction/actions-bizapps-social": "5.45.1",
|
|
38
|
+
"@memberjunction/ai": "5.45.1",
|
|
39
|
+
"@memberjunction/ai-agent-manager": "5.45.1",
|
|
40
|
+
"@memberjunction/ai-agent-manager-actions": "5.45.1",
|
|
41
|
+
"@memberjunction/ai-agents": "5.45.1",
|
|
42
|
+
"@memberjunction/ai-bridge-base": "5.45.1",
|
|
43
|
+
"@memberjunction/ai-bridge-ringcentral": "5.45.1",
|
|
44
|
+
"@memberjunction/ai-bridge-server": "5.45.1",
|
|
45
|
+
"@memberjunction/ai-bridge-teams": "5.45.1",
|
|
46
|
+
"@memberjunction/ai-bridge-twilio": "5.45.1",
|
|
47
|
+
"@memberjunction/ai-bridge-vonage": "5.45.1",
|
|
48
|
+
"@memberjunction/ai-core-plus": "5.45.1",
|
|
49
|
+
"@memberjunction/ai-engine-base": "5.45.1",
|
|
50
|
+
"@memberjunction/ai-mcp-client": "5.45.1",
|
|
51
|
+
"@memberjunction/ai-prompts": "5.45.1",
|
|
52
|
+
"@memberjunction/ai-provider-bundle": "5.45.1",
|
|
53
|
+
"@memberjunction/ai-vector-sync": "5.45.1",
|
|
54
|
+
"@memberjunction/ai-vectordb": "5.45.1",
|
|
55
|
+
"@memberjunction/ai-vectors-pinecone": "5.45.1",
|
|
56
|
+
"@memberjunction/aiengine": "5.45.1",
|
|
57
|
+
"@memberjunction/api-keys": "5.45.1",
|
|
58
|
+
"@memberjunction/auth-providers": "5.45.1",
|
|
59
|
+
"@memberjunction/clustering-engine": "5.45.1",
|
|
60
|
+
"@memberjunction/codegen-lib": "5.45.1",
|
|
61
|
+
"@memberjunction/communication-engine": "5.45.1",
|
|
62
|
+
"@memberjunction/communication-ms-graph": "5.45.1",
|
|
63
|
+
"@memberjunction/notifications": "5.45.1",
|
|
64
|
+
"@memberjunction/communication-sendgrid": "5.45.1",
|
|
65
|
+
"@memberjunction/communication-types": "5.45.1",
|
|
66
|
+
"@memberjunction/component-registry-client-sdk": "5.45.1",
|
|
67
|
+
"@memberjunction/computer-use": "5.45.1",
|
|
68
|
+
"@memberjunction/computer-use-engine": "5.45.1",
|
|
69
|
+
"@memberjunction/config": "5.45.1",
|
|
70
|
+
"@memberjunction/core": "5.45.1",
|
|
71
|
+
"@memberjunction/core-actions": "5.45.1",
|
|
72
|
+
"@memberjunction/core-entities": "5.45.1",
|
|
73
|
+
"@memberjunction/core-entities-server": "5.45.1",
|
|
74
|
+
"@memberjunction/credentials": "5.45.1",
|
|
75
|
+
"@memberjunction/data-context": "5.45.1",
|
|
76
|
+
"@memberjunction/data-context-server": "5.45.1",
|
|
77
|
+
"@memberjunction/doc-utils": "5.45.1",
|
|
78
|
+
"@memberjunction/encryption": "5.45.1",
|
|
79
|
+
"@memberjunction/entity-communications-base": "5.45.1",
|
|
80
|
+
"@memberjunction/entity-communications-server": "5.45.1",
|
|
81
|
+
"@memberjunction/esignature": "5.45.1",
|
|
82
|
+
"@memberjunction/external-change-detection": "5.45.1",
|
|
83
|
+
"@memberjunction/generic-database-provider": "5.45.1",
|
|
84
|
+
"@memberjunction/global": "5.45.1",
|
|
85
|
+
"@memberjunction/graphql-dataprovider": "5.45.1",
|
|
86
|
+
"@memberjunction/integration-engine": "5.45.1",
|
|
87
|
+
"@memberjunction/integration-progress-artifacts": "5.45.1",
|
|
88
|
+
"@memberjunction/integration-schema-builder": "5.45.1",
|
|
89
|
+
"@memberjunction/interactive-component-types": "5.45.1",
|
|
90
|
+
"@memberjunction/lists": "5.45.1",
|
|
91
|
+
"@memberjunction/lists-base": "5.45.1",
|
|
92
|
+
"@memberjunction/livekit-room-server": "5.45.1",
|
|
93
|
+
"@memberjunction/postgresql-dataprovider": "5.45.1",
|
|
94
|
+
"@memberjunction/queue": "5.45.1",
|
|
95
|
+
"@memberjunction/record-comparison": "5.45.1",
|
|
96
|
+
"@memberjunction/redis-provider": "5.45.1",
|
|
97
|
+
"@memberjunction/remote-browser-base": "5.45.1",
|
|
98
|
+
"@memberjunction/remote-browser-cdp": "5.45.1",
|
|
99
|
+
"@memberjunction/remote-browser-selfhost": "5.45.1",
|
|
100
|
+
"@memberjunction/remote-browser-server": "5.45.1",
|
|
101
|
+
"@memberjunction/scheduling-actions": "5.45.1",
|
|
102
|
+
"@memberjunction/scheduling-base-types": "5.45.1",
|
|
103
|
+
"@memberjunction/scheduling-engine": "5.45.1",
|
|
104
|
+
"@memberjunction/scheduling-engine-base": "5.45.1",
|
|
105
|
+
"@memberjunction/schema-engine": "5.45.1",
|
|
106
|
+
"@memberjunction/search-engine": "5.45.1",
|
|
107
|
+
"@memberjunction/server-extensions-core": "5.45.1",
|
|
108
|
+
"@memberjunction/sql-dialect": "5.45.1",
|
|
109
|
+
"@memberjunction/sqlserver-dataprovider": "5.45.1",
|
|
110
|
+
"@memberjunction/storage": "5.45.1",
|
|
111
|
+
"@memberjunction/tag-engine": "5.45.1",
|
|
112
|
+
"@memberjunction/tag-engine-base": "5.45.1",
|
|
113
|
+
"@memberjunction/templates": "5.45.1",
|
|
114
|
+
"@memberjunction/testing-engine": "5.45.1",
|
|
115
|
+
"@memberjunction/testing-engine-base": "5.45.1",
|
|
116
|
+
"@memberjunction/version-history": "5.45.1",
|
|
112
117
|
"@octokit/auth-app": "^7.1.5",
|
|
113
118
|
"@octokit/rest": "^21.1.1",
|
|
114
119
|
"@types/compression": "^1.8.1",
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Wire-shape tests for RunAIAgentResolver's streaming callback.
|
|
3
|
+
*
|
|
4
|
+
* The conversation client (ConversationsRuntime's ConversationStreaming) parses the
|
|
5
|
+
* exact JSON this resolver publishes to the PushStatusUpdates topic — in particular
|
|
6
|
+
* `data.type === 'streaming'` and `data.streaming.{content,isPartial,kind}`. These
|
|
7
|
+
* tests pin the published shape so the server and client can't silently drift
|
|
8
|
+
* (the client's own parsing of this same shape is pinned in
|
|
9
|
+
* packages/ConversationsRuntime/src/__tests__/ConversationStreaming.test.ts).
|
|
10
|
+
*/
|
|
11
|
+
import 'reflect-metadata'; // must precede any type-graphql decorator evaluation
|
|
12
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
13
|
+
import type { PubSubEngine } from 'type-graphql';
|
|
14
|
+
|
|
15
|
+
// type-graphql's real decorators need emitDecoratorMetadata to infer field types
|
|
16
|
+
// (`@Field() success: boolean`), which vitest's esbuild transform does not emit.
|
|
17
|
+
// The GraphQL schema is irrelevant here — no-op every decorator so the resolver
|
|
18
|
+
// module can be imported and its streaming callback exercised directly.
|
|
19
|
+
vi.mock('type-graphql', () => {
|
|
20
|
+
const decoratorFactory = (..._args: unknown[]) => (..._decorated: unknown[]) => undefined;
|
|
21
|
+
const exportNames = [
|
|
22
|
+
'Resolver', 'Query', 'Mutation', 'Subscription', 'Arg', 'Args', 'ArgsType', 'Ctx', 'Root',
|
|
23
|
+
'Info', 'Field', 'FieldResolver', 'ObjectType', 'InputType', 'InterfaceType', 'Authorized',
|
|
24
|
+
'UseMiddleware', 'Extensions', 'Directive', 'ID', 'Int', 'Float', 'GraphQLISODateTime',
|
|
25
|
+
'GraphQLTimestamp', 'registerEnumType', 'createMethodDecorator', 'createParamDecorator',
|
|
26
|
+
'buildSchema', 'buildSchemaSync', 'PubSub',
|
|
27
|
+
];
|
|
28
|
+
return Object.fromEntries(exportNames.map((name) => [name, decoratorFactory]));
|
|
29
|
+
});
|
|
30
|
+
import type { AgentExecutionStreamingCallback } from '@memberjunction/ai-core-plus';
|
|
31
|
+
|
|
32
|
+
import { RunAIAgentResolver } from '../resolvers/RunAIAgentResolver.js';
|
|
33
|
+
import type { UserPayload } from '../types.js';
|
|
34
|
+
|
|
35
|
+
/** Access the private factory without widening the class's public API. */
|
|
36
|
+
interface StreamingCallbackFactory {
|
|
37
|
+
createStreamingCallback(
|
|
38
|
+
pubSub: PubSubEngine,
|
|
39
|
+
sessionId: string,
|
|
40
|
+
userPayload: UserPayload,
|
|
41
|
+
agentRunRef: { current: unknown }
|
|
42
|
+
): AgentExecutionStreamingCallback;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function buildHarness() {
|
|
46
|
+
const publish = vi.fn().mockResolvedValue(undefined);
|
|
47
|
+
const pubSub = { publish } as unknown as PubSubEngine;
|
|
48
|
+
const userPayload = { sessionId: 'session-1' } as UserPayload;
|
|
49
|
+
const agentRunRef = {
|
|
50
|
+
current: {
|
|
51
|
+
ID: 'run-1',
|
|
52
|
+
GetAll: () => ({ ID: 'run-1', ConversationDetailID: 'detail-1', Agent: 'Betty' }),
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
const resolver = new RunAIAgentResolver() as unknown as StreamingCallbackFactory;
|
|
56
|
+
const callback = resolver.createStreamingCallback(pubSub, 'session-1', userPayload, agentRunRef);
|
|
57
|
+
return { publish, callback };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Parse the published envelope back out of the pubSub.publish mock. */
|
|
61
|
+
function publishedData(publish: ReturnType<typeof vi.fn>): Record<string, unknown> {
|
|
62
|
+
expect(publish).toHaveBeenCalledOnce();
|
|
63
|
+
const envelope = publish.mock.calls[0][1] as { message: string };
|
|
64
|
+
const parsed = JSON.parse(envelope.message) as Record<string, unknown>;
|
|
65
|
+
expect(parsed.type).toBe('StreamingContent');
|
|
66
|
+
expect(parsed.resolver).toBe('RunAIAgentResolver');
|
|
67
|
+
return parsed.data as Record<string, unknown>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
describe('RunAIAgentResolver.createStreamingCallback', () => {
|
|
71
|
+
it('publishes the streaming wire shape the conversation client parses', () => {
|
|
72
|
+
const { publish, callback } = buildHarness();
|
|
73
|
+
|
|
74
|
+
callback({ content: 'Hel', isComplete: false, stepType: 'prompt', modelName: 'gpt-x', kind: 'final-response' });
|
|
75
|
+
|
|
76
|
+
const data = publishedData(publish);
|
|
77
|
+
expect(data.type).toBe('streaming');
|
|
78
|
+
expect(data.agentRunId).toBe('run-1');
|
|
79
|
+
expect((data.agentRun as Record<string, unknown>).ConversationDetailID).toBe('detail-1');
|
|
80
|
+
expect(data.streaming).toMatchObject({
|
|
81
|
+
content: 'Hel',
|
|
82
|
+
isPartial: true,
|
|
83
|
+
stepName: 'prompt',
|
|
84
|
+
kind: 'final-response',
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('maps isComplete=true to isPartial=false on the final chunk', () => {
|
|
89
|
+
const { publish, callback } = buildHarness();
|
|
90
|
+
|
|
91
|
+
callback({ content: '', isComplete: true, kind: 'final-response' });
|
|
92
|
+
|
|
93
|
+
const data = publishedData(publish);
|
|
94
|
+
expect((data.streaming as Record<string, unknown>).isPartial).toBe(false);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('passes an absent kind through untouched — unmarked raw streams must stay unrendered', () => {
|
|
98
|
+
// Guard rail: if the resolver ever defaults unmarked chunks to a renderable
|
|
99
|
+
// kind (e.g. `chunk.kind ?? 'final-response'` left in from local testing),
|
|
100
|
+
// every Loop agent's raw JSON envelope would render into chat bubbles.
|
|
101
|
+
// This test fails the moment such a fallback exists.
|
|
102
|
+
const { publish, callback } = buildHarness();
|
|
103
|
+
|
|
104
|
+
callback({ content: '{"taskComplete":', isComplete: false, stepType: 'prompt' });
|
|
105
|
+
|
|
106
|
+
const data = publishedData(publish);
|
|
107
|
+
expect((data.streaming as Record<string, unknown>).kind).toBeUndefined();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('does not publish when no agent run is available yet', () => {
|
|
111
|
+
const publish = vi.fn();
|
|
112
|
+
const pubSub = { publish } as unknown as PubSubEngine;
|
|
113
|
+
const resolver = new RunAIAgentResolver() as unknown as StreamingCallbackFactory;
|
|
114
|
+
const callback = resolver.createStreamingCallback(
|
|
115
|
+
pubSub,
|
|
116
|
+
'session-1',
|
|
117
|
+
{ sessionId: 'session-1' } as UserPayload,
|
|
118
|
+
{ current: null }
|
|
119
|
+
);
|
|
120
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => undefined);
|
|
121
|
+
try {
|
|
122
|
+
callback({ content: 'early', isComplete: false });
|
|
123
|
+
expect(publish).not.toHaveBeenCalled();
|
|
124
|
+
} finally {
|
|
125
|
+
consoleSpy.mockRestore();
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
2
|
import jwt from 'jsonwebtoken';
|
|
3
|
-
import { createPublicKey } from 'node:crypto';
|
|
3
|
+
import { createPublicKey, type JsonWebKey } from 'node:crypto';
|
|
4
4
|
import {
|
|
5
5
|
generateRawToken,
|
|
6
6
|
hashToken,
|
|
@@ -228,6 +228,56 @@ describe('magic-link core', () => {
|
|
|
228
228
|
});
|
|
229
229
|
});
|
|
230
230
|
|
|
231
|
+
describe('buildConsumeInviteSQL (postgresql dialect)', () => {
|
|
232
|
+
// PG uses `schema.table` (unquoted — PostgreSQLDataProvider.ExecuteSQL auto-quotes
|
|
233
|
+
// the PascalCase identifiers). SS uses the bracket-quoted `[schema].[table]` form.
|
|
234
|
+
const pgTable = '__mj.MagicLinkInvite';
|
|
235
|
+
const pgSql = buildConsumeInviteSQL(pgTable, 'postgresql');
|
|
236
|
+
|
|
237
|
+
it('targets the supplied unquoted schema.table', () => {
|
|
238
|
+
expect(pgSql).toContain(`UPDATE ${pgTable} `);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it('uses UPDATE … RETURNING as the atomic single-use gate (no OUTPUT/DECLARE table var)', () => {
|
|
242
|
+
expect(pgSql).toContain('RETURNING ID;');
|
|
243
|
+
expect(pgSql).not.toContain('OUTPUT');
|
|
244
|
+
expect(pgSql).not.toContain('DECLARE');
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it('binds the invite ID as PG positional param $1, not T-SQL @p0 (injection-safe)', () => {
|
|
248
|
+
expect(pgSql).toContain('ID = $1');
|
|
249
|
+
expect(pgSql).not.toContain('@p0');
|
|
250
|
+
expect(pgSql).not.toMatch(/@/); // no T-SQL @-anything survives on PG
|
|
251
|
+
expect(pgSql).not.toMatch(/ID = '/);
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('uses PG timestamp expressions, not T-SQL SYSUTCDATETIME()', () => {
|
|
255
|
+
expect(pgSql).not.toContain('SYSUTCDATETIME');
|
|
256
|
+
expect(pgSql).toContain("(now() AT TIME ZONE 'utc')");
|
|
257
|
+
expect(pgSql).toContain("ConsumedAt = COALESCE(ConsumedAt, (now() AT TIME ZONE 'utc'))");
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
it('guards atomically on Active + not-exhausted + not-expired (same predicate as SS)', () => {
|
|
261
|
+
const where = pgSql.slice(pgSql.indexOf('WHERE'));
|
|
262
|
+
expect(where).toContain("Status = 'Active'");
|
|
263
|
+
expect(where).toContain('UseCount < MaxUses');
|
|
264
|
+
expect(where).toContain("ExpiresAt > (now() AT TIME ZONE 'utc')");
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('increments UseCount and flips Status on the last use (same semantics as SS)', () => {
|
|
268
|
+
expect(pgSql).toContain('UseCount = UseCount + 1');
|
|
269
|
+
expect(pgSql).toContain("Status = CASE WHEN UseCount + 1 >= MaxUses THEN 'Consumed' ELSE Status END");
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('rejects a non-whitelisted PG table identifier (defense-in-depth against injection)', () => {
|
|
273
|
+
// Bracket-quoted (SS) form is not a valid PG identifier here.
|
|
274
|
+
expect(() => buildConsumeInviteSQL('[__mj].[MagicLinkInvite]', 'postgresql')).toThrow();
|
|
275
|
+
expect(() => buildConsumeInviteSQL('__mj.MagicLinkInvite; DROP TABLE x;--', 'postgresql')).toThrow();
|
|
276
|
+
expect(() => buildConsumeInviteSQL('__mj.Magic Link', 'postgresql')).toThrow();
|
|
277
|
+
expect(() => buildConsumeInviteSQL(pgTable, 'postgresql')).not.toThrow();
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
|
|
231
281
|
describe('canIssueInvites', () => {
|
|
232
282
|
it('always allows Owners, regardless of issuer-role config (case/space-insensitive)', () => {
|
|
233
283
|
expect(canIssueInvites('Owner', [], [])).toBe(true);
|
|
@@ -351,7 +401,7 @@ describe('MagicLinkKeyManager', () => {
|
|
|
351
401
|
expect(header.kid).toBe(jwk.kid);
|
|
352
402
|
|
|
353
403
|
// Full verification against the public key reconstructed from the JWK.
|
|
354
|
-
const publicKey = createPublicKey({ key: jwk as
|
|
404
|
+
const publicKey = createPublicKey({ key: jwk as unknown as JsonWebKey, format: 'jwk' });
|
|
355
405
|
const decoded = jwt.verify(token, publicKey, {
|
|
356
406
|
algorithms: ['RS256'],
|
|
357
407
|
issuer: 'http://localhost:4051',
|
|
@@ -375,7 +425,7 @@ describe('MagicLinkKeyManager', () => {
|
|
|
375
425
|
ttlSeconds: 3600,
|
|
376
426
|
});
|
|
377
427
|
const token = km.Sign(claims);
|
|
378
|
-
const publicKey = createPublicKey({ key: km.GetJWKS().keys[0] as
|
|
428
|
+
const publicKey = createPublicKey({ key: km.GetJWKS().keys[0] as unknown as JsonWebKey, format: 'jwk' });
|
|
379
429
|
|
|
380
430
|
// Flip a character in the payload segment.
|
|
381
431
|
const parts = token.split('.');
|
|
@@ -127,7 +127,7 @@ describe('SearchKnowledgeResolver', () => {
|
|
|
127
127
|
const resolver = createResolver();
|
|
128
128
|
mockSearch.mockResolvedValueOnce(createMockSearchResult());
|
|
129
129
|
|
|
130
|
-
const result = await resolver.SearchKnowledge('test query', 20, undefined, undefined, fakeContext as never);
|
|
130
|
+
const result = await resolver.SearchKnowledge('test query', 20, undefined, undefined, undefined, undefined, undefined, fakeContext as never);
|
|
131
131
|
|
|
132
132
|
expect(mockSearch).toHaveBeenCalledOnce();
|
|
133
133
|
expect(result.Success).toBe(true);
|
|
@@ -139,7 +139,7 @@ describe('SearchKnowledgeResolver', () => {
|
|
|
139
139
|
const resolver = createResolver();
|
|
140
140
|
mockSearch.mockResolvedValueOnce(createMockSearchResult());
|
|
141
141
|
|
|
142
|
-
await resolver.SearchKnowledge('cheese', 50, undefined, undefined, fakeContext as never);
|
|
142
|
+
await resolver.SearchKnowledge('cheese', 50, undefined, undefined, undefined, undefined, undefined, fakeContext as never);
|
|
143
143
|
|
|
144
144
|
const searchParams = mockSearch.mock.calls[0][0];
|
|
145
145
|
expect(searchParams.Query).toBe('cheese');
|
|
@@ -151,7 +151,7 @@ describe('SearchKnowledgeResolver', () => {
|
|
|
151
151
|
mockSearch.mockResolvedValueOnce(createMockSearchResult());
|
|
152
152
|
|
|
153
153
|
const filters = { EntityNames: ['Contacts'], SourceTypes: undefined, Tags: ['VIP'] };
|
|
154
|
-
await resolver.SearchKnowledge('test', 20, filters as never, undefined, fakeContext as never);
|
|
154
|
+
await resolver.SearchKnowledge('test', 20, filters as never, undefined, undefined, undefined, undefined, fakeContext as never);
|
|
155
155
|
|
|
156
156
|
const searchParams = mockSearch.mock.calls[0][0];
|
|
157
157
|
expect(searchParams.Filters).toEqual({
|
|
@@ -165,7 +165,7 @@ describe('SearchKnowledgeResolver', () => {
|
|
|
165
165
|
const resolver = createResolver();
|
|
166
166
|
mockSearch.mockResolvedValueOnce(createMockSearchResult());
|
|
167
167
|
|
|
168
|
-
await resolver.SearchKnowledge('test', 20, undefined, 0.5, fakeContext as never);
|
|
168
|
+
await resolver.SearchKnowledge('test', 20, undefined, 0.5, undefined, undefined, undefined, fakeContext as never);
|
|
169
169
|
|
|
170
170
|
const searchParams = mockSearch.mock.calls[0][0];
|
|
171
171
|
expect(searchParams.MinScore).toBe(0.5);
|
|
@@ -175,7 +175,7 @@ describe('SearchKnowledgeResolver', () => {
|
|
|
175
175
|
const resolver = createResolver();
|
|
176
176
|
mockSearch.mockResolvedValueOnce(createMockSearchResult());
|
|
177
177
|
|
|
178
|
-
const result = await resolver.SearchKnowledge('test', 20, undefined, undefined, fakeContext as never);
|
|
178
|
+
const result = await resolver.SearchKnowledge('test', 20, undefined, undefined, undefined, undefined, undefined, fakeContext as never);
|
|
179
179
|
|
|
180
180
|
const item = result.Results[0];
|
|
181
181
|
expect(item.ID).toBe('result-1');
|
|
@@ -193,7 +193,7 @@ describe('SearchKnowledgeResolver', () => {
|
|
|
193
193
|
SourceCounts: { Vector: 5, FullText: 3, Entity: 10, Storage: 0 }
|
|
194
194
|
}));
|
|
195
195
|
|
|
196
|
-
const result = await resolver.SearchKnowledge('test', 20, undefined, undefined, fakeContext as never);
|
|
196
|
+
const result = await resolver.SearchKnowledge('test', 20, undefined, undefined, undefined, undefined, undefined, fakeContext as never);
|
|
197
197
|
|
|
198
198
|
expect(result.SourceCounts.Vector).toBe(5);
|
|
199
199
|
expect(result.SourceCounts.FullText).toBe(3);
|
|
@@ -204,7 +204,7 @@ describe('SearchKnowledgeResolver', () => {
|
|
|
204
204
|
const resolver = createResolver();
|
|
205
205
|
mockSearch.mockResolvedValueOnce(createMockSearchResult({ Success: false, ErrorMessage: 'Query cannot be empty' }));
|
|
206
206
|
|
|
207
|
-
const result = await resolver.SearchKnowledge(' ', 20, undefined, undefined, fakeContext as never);
|
|
207
|
+
const result = await resolver.SearchKnowledge(' ', 20, undefined, undefined, undefined, undefined, undefined, fakeContext as never);
|
|
208
208
|
|
|
209
209
|
expect(mockSearch).toHaveBeenCalled();
|
|
210
210
|
expect(result.Success).toBe(false);
|
|
@@ -214,7 +214,7 @@ describe('SearchKnowledgeResolver', () => {
|
|
|
214
214
|
const resolver = new SearchKnowledgeResolver();
|
|
215
215
|
(resolver as Record<string, unknown>)['GetUserFromPayload'] = vi.fn().mockReturnValue(null);
|
|
216
216
|
|
|
217
|
-
const result = await resolver.SearchKnowledge('test', 20, undefined, undefined, fakeContext as never);
|
|
217
|
+
const result = await resolver.SearchKnowledge('test', 20, undefined, undefined, undefined, undefined, undefined, fakeContext as never);
|
|
218
218
|
|
|
219
219
|
expect(result.Success).toBe(false);
|
|
220
220
|
expect(result.ErrorMessage).toContain('current user');
|
|
@@ -224,7 +224,7 @@ describe('SearchKnowledgeResolver', () => {
|
|
|
224
224
|
const resolver = createResolver();
|
|
225
225
|
mockSearch.mockRejectedValueOnce(new Error('Connection failed'));
|
|
226
226
|
|
|
227
|
-
const result = await resolver.SearchKnowledge('test', 20, undefined, undefined, fakeContext as never);
|
|
227
|
+
const result = await resolver.SearchKnowledge('test', 20, undefined, undefined, undefined, undefined, undefined, fakeContext as never);
|
|
228
228
|
|
|
229
229
|
expect(result.Success).toBe(false);
|
|
230
230
|
expect(result.ErrorMessage).toContain('Connection failed');
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { TeamsMeetingsService } from '../telephony/TeamsMeetingsService.js';
|
|
3
|
+
import { TeamsAcsMediaRegistry } from '../telephony/teamsAcsMediaRegistry.js';
|
|
4
|
+
import { RealTeamsBindings } from '@memberjunction/ai-bridge-teams';
|
|
5
|
+
import type { BaseRealtimeBridge } from '@memberjunction/ai-bridge-base';
|
|
6
|
+
import type { TeamsMeetingsConfig } from '../config.js';
|
|
7
|
+
|
|
8
|
+
const CONFIG: TeamsMeetingsConfig = {
|
|
9
|
+
enabled: true,
|
|
10
|
+
tenantId: 'tenant-1',
|
|
11
|
+
botAccessToken: 'tok',
|
|
12
|
+
notificationClientState: 'secret',
|
|
13
|
+
acsSampleRate: 16000,
|
|
14
|
+
modelSampleRate: 16000,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
describe('TeamsMeetingsService.buildBindSdk', () => {
|
|
18
|
+
it('binds a RealTeamsBindings factory onto the Teams driver (the live Graph + ACS wiring seam)', () => {
|
|
19
|
+
const service = new TeamsMeetingsService(CONFIG, new TeamsAcsMediaRegistry());
|
|
20
|
+
const setSdkFactory = vi.fn();
|
|
21
|
+
const fakeDriver = { SetSdkFactory: setSdkFactory } as unknown as BaseRealtimeBridge;
|
|
22
|
+
// A minimal fake Graph client (only used as a constructor arg here).
|
|
23
|
+
const graphClient = { CreateCall: vi.fn() } as unknown as Parameters<typeof service.buildBindSdk>[0];
|
|
24
|
+
|
|
25
|
+
service.buildBindSdk(graphClient)(fakeDriver);
|
|
26
|
+
|
|
27
|
+
expect(setSdkFactory).toHaveBeenCalledTimes(1);
|
|
28
|
+
const factory = setSdkFactory.mock.calls[0][0] as () => unknown;
|
|
29
|
+
expect(typeof factory).toBe('function');
|
|
30
|
+
// The factory yields a real (bound) RealTeamsBindings — proving the offline seam meets live plumbing.
|
|
31
|
+
expect(factory()).toBeInstanceOf(RealTeamsBindings);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
describe('TeamsMeetingsService.JoinMeetingByUrl', () => {
|
|
36
|
+
it('returns accepted=false (never throws) when the agent identity is missing', async () => {
|
|
37
|
+
const provider = {
|
|
38
|
+
GetEntityObject: vi.fn().mockResolvedValue({ Load: vi.fn().mockResolvedValue(false), IsActive: false }),
|
|
39
|
+
};
|
|
40
|
+
const service = new TeamsMeetingsService(CONFIG, new TeamsAcsMediaRegistry());
|
|
41
|
+
const result = await service.JoinMeetingByUrl(
|
|
42
|
+
'identity-1',
|
|
43
|
+
'https://teams.microsoft.com/l/meetup-join/x',
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- minimal UserInfo stub for a pure-branch test
|
|
45
|
+
{ ID: 'u1' } as never,
|
|
46
|
+
provider as never,
|
|
47
|
+
);
|
|
48
|
+
expect(result.accepted).toBe(false);
|
|
49
|
+
expect(result.reason).toMatch(/not found or inactive/i);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe('TeamsMeetingsService notification drive helpers', () => {
|
|
54
|
+
it('tears down the call + registry on call-ended (no throw when no client registered)', () => {
|
|
55
|
+
const registry = new TeamsAcsMediaRegistry();
|
|
56
|
+
registry.RegisterCall('call-1');
|
|
57
|
+
expect(registry.HasCall('call-1')).toBe(true);
|
|
58
|
+
const service = new TeamsMeetingsService(CONFIG, registry);
|
|
59
|
+
|
|
60
|
+
service.DriveCallEnded('call-1');
|
|
61
|
+
expect(registry.HasCall('call-1')).toBe(false);
|
|
62
|
+
// An unknown roster drive is a silent no-op.
|
|
63
|
+
expect(() => service.DriveParticipantsUpdated('unknown', [{ id: 'p1' }])).not.toThrow();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { TeamsAcsMediaRegistry, type IAcsMediaTransport } from '../telephony/teamsAcsMediaRegistry.js';
|
|
3
|
+
import type { AcsInboundAudioFrame } from '@memberjunction/ai-bridge-teams';
|
|
4
|
+
|
|
5
|
+
class FakeTransport implements IAcsMediaTransport {
|
|
6
|
+
public readonly Sent: ArrayBuffer[] = [];
|
|
7
|
+
public Closed = false;
|
|
8
|
+
public sendAudioFrame(pcm: ArrayBuffer): void {
|
|
9
|
+
this.Sent.push(pcm);
|
|
10
|
+
}
|
|
11
|
+
public close(): void {
|
|
12
|
+
this.Closed = true;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const frame = (bytes: number): ArrayBuffer => new ArrayBuffer(bytes);
|
|
17
|
+
|
|
18
|
+
describe('TeamsAcsMediaRegistry', () => {
|
|
19
|
+
it('exposes the configured ACS sample rate', () => {
|
|
20
|
+
expect(new TeamsAcsMediaRegistry().SampleRate).toBe(16000);
|
|
21
|
+
expect(new TeamsAcsMediaRegistry(8000).SampleRate).toBe(8000);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('buffers outbound PCM before the transport attaches, then flushes on attach', () => {
|
|
25
|
+
const registry = new TeamsAcsMediaRegistry();
|
|
26
|
+
const a = frame(4);
|
|
27
|
+
const b = frame(8);
|
|
28
|
+
registry.Send('call-1', a);
|
|
29
|
+
registry.Send('call-1', b);
|
|
30
|
+
|
|
31
|
+
const transport = new FakeTransport();
|
|
32
|
+
registry.AttachTransport('call-1', transport);
|
|
33
|
+
|
|
34
|
+
expect(transport.Sent).toEqual([a, b]);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('sends immediately once the transport is attached', () => {
|
|
38
|
+
const registry = new TeamsAcsMediaRegistry();
|
|
39
|
+
const transport = new FakeTransport();
|
|
40
|
+
registry.AttachTransport('call-1', transport);
|
|
41
|
+
const a = frame(4);
|
|
42
|
+
registry.Send('call-1', a);
|
|
43
|
+
expect(transport.Sent).toEqual([a]);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('dispatches inbound frames to all registered handlers for the call', () => {
|
|
47
|
+
const registry = new TeamsAcsMediaRegistry();
|
|
48
|
+
const seen: AcsInboundAudioFrame[] = [];
|
|
49
|
+
registry.OnFrame('call-1', (f) => seen.push(f));
|
|
50
|
+
registry.OnFrame('call-1', (f) => seen.push(f));
|
|
51
|
+
const f: AcsInboundAudioFrame = { Pcm: frame(2), ParticipantId: 'p1' };
|
|
52
|
+
registry.DispatchInbound('call-1', f);
|
|
53
|
+
expect(seen).toEqual([f, f]);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('dispatches hand-raise signals to registered hand-raise handlers', () => {
|
|
57
|
+
const registry = new TeamsAcsMediaRegistry();
|
|
58
|
+
let raised: boolean | undefined;
|
|
59
|
+
registry.OnHandRaise('call-1', (_p, r) => (raised = r));
|
|
60
|
+
registry.DispatchHandRaise('call-1', 'p1', true);
|
|
61
|
+
expect(raised).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('ignores inbound dispatch + hand-raise for unknown calls (no throw)', () => {
|
|
65
|
+
const registry = new TeamsAcsMediaRegistry();
|
|
66
|
+
expect(() => registry.DispatchInbound('nope', { Pcm: frame(2), ParticipantId: 'p1' })).not.toThrow();
|
|
67
|
+
expect(() => registry.DispatchHandRaise('nope', 'p1', true)).not.toThrow();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('closes the transport and forgets the call on EndCall', () => {
|
|
71
|
+
const registry = new TeamsAcsMediaRegistry();
|
|
72
|
+
const transport = new FakeTransport();
|
|
73
|
+
registry.AttachTransport('call-1', transport);
|
|
74
|
+
expect(registry.HasCall('call-1')).toBe(true);
|
|
75
|
+
|
|
76
|
+
registry.EndCall('call-1');
|
|
77
|
+
expect(transport.Closed).toBe(true);
|
|
78
|
+
expect(registry.HasCall('call-1')).toBe(false);
|
|
79
|
+
// EndCall on an unknown call is a silent no-op.
|
|
80
|
+
expect(() => registry.EndCall('unknown')).not.toThrow();
|
|
81
|
+
});
|
|
82
|
+
});
|