@futdevpro/nts-dynamo 1.15.2 → 1.15.3
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/.cursor/rules/__assistant_guide.mdc +30 -0
- package/.cursor/rules/__main.mdc +62 -0
- package/.cursor/rules/_ag_backend-structure.mdc +86 -0
- package/.cursor/rules/_ag_backend.mdc +16 -0
- package/.cursor/rules/_ag_debug.mdc +8 -0
- package/.cursor/rules/_ag_documentation_writing_rules.mdc +372 -0
- package/.cursor/rules/_ag_file-refactoring.mdc +113 -0
- package/.cursor/rules/_ag_fixes_rules.mdc +6 -0
- package/.cursor/rules/_ag_frontend-structure.mdc +87 -0
- package/.cursor/rules/_ag_frontend.mdc +40 -0
- package/.cursor/rules/_ag_import-rules.mdc +45 -0
- package/.cursor/rules/_ag_naming.mdc +116 -0
- package/.cursor/rules/_ag_running_commands.mdc +5 -0
- package/.cursor/rules/_ag_server-controller.mdc +6 -0
- package/.cursor/rules/_ag_should-be.mdc +7 -0
- package/.cursor/rules/_ag_swearing.mdc +47 -0
- package/.cursor/rules/ai_development_guide.md +61 -0
- package/.cursor/rules/ai_directives.md +114 -0
- package/.cursor/rules/cursor-rules.md +160 -0
- package/.cursor/rules/default-command.mdc +229 -0
- package/.cursor/rules/error_code_pattern.md +40 -0
- package/.cursor/rules/saved rule mcp server use.md +16 -0
- package/build/_modules/custom-data/custom-data.controller.d.ts.map +1 -1
- package/build/_modules/custom-data/custom-data.controller.js +1 -2
- package/build/_modules/custom-data/custom-data.controller.js.map +1 -1
- package/build/_services/core/api.service.d.ts.map +1 -1
- package/build/_services/core/api.service.js +1 -0
- package/build/_services/core/api.service.js.map +1 -1
- package/package.json +5 -4
- package/scripts/run-coverage-tests.js +5 -1
- package/spec/support/helpers/spec-reporter-loader.js +359 -0
- package/spec/support/helpers/ts-node-helper.js +84 -0
- package/spec/support/jasmine.coverage.json +2 -1
- package/spec/support/jasmine.json +3 -3
- package/src/_collections/archive.util.spec.ts +36 -0
- package/src/_collections/get-environment-settings.util.spec.ts +210 -0
- package/src/_collections/star.controller.spec.ts +224 -0
- package/src/_models/control-models/api-call-params.control-model.spec.ts +62 -3
- package/src/_models/control-models/app-ext-system-controls.control-model.spec.ts +52 -0
- package/src/_models/control-models/app-params.control-model.spec.ts +158 -2
- package/src/_models/control-models/endpoint-params.control-model.spec.ts +578 -0
- package/src/_modules/ai/_modules/document-ai/_collections/dai-chunking.util.spec.ts +242 -0
- package/src/_modules/ai/_modules/document-ai/_collections/dai-document.util.spec.ts +209 -0
- package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-document.data-service.spec.ts +342 -0
- package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-vector-data.service.spec.ts +550 -0
- package/src/_modules/ai/_modules/open-ai/_services/oai-embedding.control-service.spec.ts +240 -0
- package/src/_modules/ai/_modules/open-ai/_services/oai-llm-chat.service-base.spec.ts +462 -0
- package/src/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.spec.ts +437 -0
- package/src/_modules/ai/_services/ai-embedding.service-base.spec.ts +98 -0
- package/src/_modules/ai/_services/ai-llm-chat.service-base.spec.ts +229 -0
- package/src/_modules/ai/_services/ai-llm.service-base.spec.ts +250 -0
- package/src/_modules/ai/_services/ai-provider.service-base.spec.ts +79 -0
- package/src/_modules/assistant/_collections/ass.util.spec.ts +176 -0
- package/src/_modules/assistant/_services/ass-io.control-service.spec.ts +140 -0
- package/src/_modules/assistant/_services/ass-main.control-service.spec.ts +192 -0
- package/src/_modules/bot/_modules/discord-bot/_services/dib-messaging-provider.control-service.spec.ts +431 -0
- package/src/_modules/bot/_modules/dynamo-bot/_collections/dyb-operations.util.spec.ts +160 -0
- package/src/_modules/bot/_modules/dynamo-bot/_services/dyb-messaging-provider.control-service.spec.ts +374 -0
- package/src/_modules/bot/_modules/slack-bot/_services/slb-messaging-provider.control-service.spec.ts +344 -0
- package/src/_modules/bot/_modules/teams-bot/_services/teb-messaging-provider.control-service.spec.ts +345 -0
- package/src/_modules/bot/_services/bot-commands.control-service.spec.ts +116 -0
- package/src/_modules/bot/_services/bot-io.control-service.spec.ts +285 -0
- package/src/_modules/bot/_services/bot-main.control-service.spec.ts +208 -0
- package/src/_modules/bot/_services/bot-messaging-provider.service-base.spec.ts +349 -0
- package/src/_modules/bot/_services/bot-routines.control-service.spec.ts +111 -0
- package/src/_modules/custom-data/custom-data.controller.spec.ts +49 -0
- package/src/_modules/custom-data/custom-data.controller.ts +1 -3
- package/src/_modules/custom-data/custom-data.data-service.spec.ts +54 -0
- package/src/_modules/custom-data/get-custom-data-routing-module.util.spec.ts +28 -0
- package/src/_modules/defaults/_services/default-auth.service.spec.ts +269 -0
- package/src/_modules/defaults/_services/default-socket-events.service.spec.ts +42 -0
- package/src/_modules/defaults/_services/default-user.data-service.spec.ts +187 -0
- package/src/_modules/discord-assistant/_collections/dias.util.spec.ts +366 -0
- package/src/_modules/discord-assistant/_services/dias-io.control-service.spec.ts +108 -0
- package/src/_modules/discord-assistant/_services/dias-main.control-service.spec.ts +22 -0
- package/src/_modules/discord-assistant/_services/dias.service-base.spec.ts +195 -0
- package/src/_modules/discord-assistant-voiced/_services/dias-discord-bot.control-service.spec.ts +34 -0
- package/src/_modules/discord-bot/_collections/dibo-operations.util.spec.ts +214 -0
- package/src/_modules/discord-bot/_services/dibo-commands.control-service.spec.ts +154 -0
- package/src/_modules/discord-bot/_services/dibo-io.control-service.spec.ts +264 -0
- package/src/_modules/discord-bot/_services/dibo-main.control-service.spec.ts +408 -0
- package/src/_modules/discord-bot/_services/dibo-routines.control-service.spec.ts +105 -0
- package/src/_modules/local-vector-search/_services/lvs-doc-chunk-data.service.spec.ts +418 -0
- package/src/_modules/local-vector-search/_services/lvs-local-vector-search.data-service.spec.ts +345 -0
- package/src/_modules/messaging/_collections/msg.util.spec.ts +226 -0
- package/src/_modules/messaging/_services/msg-events.service.spec.ts +219 -0
- package/src/_modules/messaging/_services/msg-main.control-service.spec.ts +147 -0
- package/src/_modules/messaging/_services/msg.controller.spec.ts +201 -0
- package/src/_modules/mock/data-model.mock.spec.ts +27 -24
- package/src/_modules/oauth2/_routes/oauth2.controller.spec.ts +107 -0
- package/src/_modules/oauth2/_services/oauth2.auth-service.spec.ts +254 -0
- package/src/_modules/oauth2/_services/oauth2.control-service.spec.ts +585 -0
- package/src/_modules/server/errors/errors.control-service.spec.ts +230 -0
- package/src/_modules/server/errors/errors.controller.spec.ts +165 -0
- package/src/_modules/server/errors/errors.data-service.spec.ts +355 -0
- package/src/_modules/server/server-status/server-status-snapshot.control-service.spec.ts +70 -0
- package/src/_modules/server/server-status/server-status-snapshot.data-service.spec.ts +77 -0
- package/src/_modules/server/server-status/server-status.control-service.spec.ts +516 -0
- package/src/_modules/server/server-status/server-status.controller.spec.ts +156 -0
- package/src/_modules/socket/_models/socket-client-service-params.control-model.spec.ts +6 -3
- package/src/_modules/socket/_models/socket-presence.control-model.spec.ts +164 -0
- package/src/_modules/socket/_services/socket-client.service.spec.ts +15 -0
- package/src/_modules/test/get-test-routing-module.util.spec.ts +28 -0
- package/src/_modules/test/test.controller.spec.ts +72 -0
- package/src/_modules/usage/usage.controller.spec.ts +81 -0
- package/src/_modules/usage/usage.data-service.spec.ts +332 -0
- package/src/_services/base/api.service-base.spec.ts +125 -0
- package/src/_services/base/archive-data.service.spec.ts +196 -0
- package/src/_services/base/data.service.spec.ts +493 -0
- package/src/_services/base/db.service.spec.ts +59 -18
- package/src/_services/base/singleton.service-base.spec.ts +28 -0
- package/src/_services/base/singleton.service.spec.ts +114 -0
- package/src/_services/core/api.service.ts +1 -0
- package/src/_services/core/auth.service.spec.ts +159 -0
- package/src/_services/core/email.service.spec.ts +14 -22
- package/src/_services/core/global.service.spec.ts +275 -0
- package/src/_services/core/service-collection.service.spec.ts +46 -0
- package/src/_services/route/routing-module.service.spec.ts +8 -6
- package/src/_services/shared.static-service.spec.ts +89 -0
- package/src/_modules/socket/app-extended.server.spec.ts +0 -227
- package/src/_services/server/app.server.spec.ts +0 -138
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
|
|
2
|
+
import { DyFM_AI_Message, DyFM_AI_MessageRole } from '@futdevpro/fsm-dynamo/ai';
|
|
3
|
+
import { DyNTS_Ass_Util } from './ass.util';
|
|
4
|
+
import { DyNTS_Bot_MessageWrapper } from '../../bot/_models/bot-message-wrapper.interface';
|
|
5
|
+
import { DyNTS_Ass_global_settings } from './ass-global-settings.const';
|
|
6
|
+
|
|
7
|
+
describe('| DyNTS_Ass_Util', () => {
|
|
8
|
+
describe('| convertBotMessagesToAIConversation', () => {
|
|
9
|
+
it('| should convert bot messages to AI conversation format', () => {
|
|
10
|
+
const messages: DyNTS_Bot_MessageWrapper<any>[] = [
|
|
11
|
+
{
|
|
12
|
+
id: 'msg-1',
|
|
13
|
+
content: 'User message',
|
|
14
|
+
authorId: 'user-123',
|
|
15
|
+
authorName: 'user',
|
|
16
|
+
isBot: false,
|
|
17
|
+
} as any,
|
|
18
|
+
{
|
|
19
|
+
id: 'msg-2',
|
|
20
|
+
content: 'Bot response',
|
|
21
|
+
authorId: 'bot-123',
|
|
22
|
+
authorName: 'bot',
|
|
23
|
+
isBot: true,
|
|
24
|
+
} as any,
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
const result = DyNTS_Ass_Util.convertBotMessagesToAIConversation({
|
|
28
|
+
messages: messages,
|
|
29
|
+
botClientId: 'bot-123',
|
|
30
|
+
botDisplayName: 'Bot',
|
|
31
|
+
issuer: 'issuer-123',
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
expect(result.length).toBe(2);
|
|
35
|
+
expect(result[0].role).toBe(DyFM_AI_MessageRole.user);
|
|
36
|
+
expect(result[0].content).toBe('User message');
|
|
37
|
+
expect(result[1].role).toBe(DyFM_AI_MessageRole.assistant);
|
|
38
|
+
expect(result[1].content).toBe('Bot response');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('| should identify bot messages by isBot flag', () => {
|
|
42
|
+
const messages: DyNTS_Bot_MessageWrapper<any>[] = [
|
|
43
|
+
{
|
|
44
|
+
id: 'msg-1',
|
|
45
|
+
content: 'Message',
|
|
46
|
+
authorId: 'bot-123',
|
|
47
|
+
isBot: true,
|
|
48
|
+
} as any,
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const result = DyNTS_Ass_Util.convertBotMessagesToAIConversation({
|
|
52
|
+
messages: messages,
|
|
53
|
+
botClientId: 'bot-123',
|
|
54
|
+
botDisplayName: 'Bot',
|
|
55
|
+
issuer: 'issuer-123',
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
expect(result[0].role).toBe(DyFM_AI_MessageRole.assistant);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('| should identify bot messages by authorId match', () => {
|
|
62
|
+
const messages: DyNTS_Bot_MessageWrapper<any>[] = [
|
|
63
|
+
{
|
|
64
|
+
id: 'msg-1',
|
|
65
|
+
content: 'Message',
|
|
66
|
+
authorId: 'bot-123',
|
|
67
|
+
isBot: false,
|
|
68
|
+
} as any,
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
const result = DyNTS_Ass_Util.convertBotMessagesToAIConversation({
|
|
72
|
+
messages: messages,
|
|
73
|
+
botClientId: 'bot-123',
|
|
74
|
+
botDisplayName: 'Bot',
|
|
75
|
+
issuer: 'issuer-123',
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
expect(result[0].role).toBe(DyFM_AI_MessageRole.assistant);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('| should identify bot messages by authorName match', () => {
|
|
82
|
+
const messages: DyNTS_Bot_MessageWrapper<any>[] = [
|
|
83
|
+
{
|
|
84
|
+
id: 'msg-1',
|
|
85
|
+
content: 'Message',
|
|
86
|
+
authorId: 'other-123',
|
|
87
|
+
authorName: 'Bot',
|
|
88
|
+
isBot: false,
|
|
89
|
+
} as any,
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
const result = DyNTS_Ass_Util.convertBotMessagesToAIConversation({
|
|
93
|
+
messages: messages,
|
|
94
|
+
botClientId: 'bot-123',
|
|
95
|
+
botDisplayName: 'Bot',
|
|
96
|
+
issuer: 'issuer-123',
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
expect(result[0].role).toBe(DyFM_AI_MessageRole.assistant);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('| should identify bot messages by authorDisplayName match', () => {
|
|
103
|
+
const messages: DyNTS_Bot_MessageWrapper<any>[] = [
|
|
104
|
+
{
|
|
105
|
+
id: 'msg-1',
|
|
106
|
+
content: 'Message',
|
|
107
|
+
authorId: 'other-123',
|
|
108
|
+
authorDisplayName: 'Bot',
|
|
109
|
+
isBot: false,
|
|
110
|
+
} as any,
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
const result = DyNTS_Ass_Util.convertBotMessagesToAIConversation({
|
|
114
|
+
messages: messages,
|
|
115
|
+
botClientId: 'bot-123',
|
|
116
|
+
botDisplayName: 'Bot',
|
|
117
|
+
issuer: 'issuer-123',
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
expect(result[0].role).toBe(DyFM_AI_MessageRole.assistant);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('| should convert bot messages with user translation flags to user role', () => {
|
|
124
|
+
const userTranslationFlag = DyNTS_Ass_global_settings.userTranslationFlags[0];
|
|
125
|
+
const messages: DyNTS_Bot_MessageWrapper<any>[] = [
|
|
126
|
+
{
|
|
127
|
+
id: 'msg-1',
|
|
128
|
+
content: `Message with ${userTranslationFlag} flag`,
|
|
129
|
+
authorId: 'bot-123',
|
|
130
|
+
isBot: true,
|
|
131
|
+
} as any,
|
|
132
|
+
];
|
|
133
|
+
|
|
134
|
+
const result = DyNTS_Ass_Util.convertBotMessagesToAIConversation({
|
|
135
|
+
messages: messages,
|
|
136
|
+
botClientId: 'bot-123',
|
|
137
|
+
botDisplayName: 'Bot',
|
|
138
|
+
issuer: 'issuer-123',
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
expect(result[0].role).toBe(DyFM_AI_MessageRole.user);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('| should handle empty messages array', () => {
|
|
145
|
+
const result = DyNTS_Ass_Util.convertBotMessagesToAIConversation({
|
|
146
|
+
messages: [],
|
|
147
|
+
botClientId: 'bot-123',
|
|
148
|
+
botDisplayName: 'Bot',
|
|
149
|
+
issuer: 'issuer-123',
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
expect(result).toEqual([]);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('| should convert user messages to user role', () => {
|
|
156
|
+
const messages: DyNTS_Bot_MessageWrapper<any>[] = [
|
|
157
|
+
{
|
|
158
|
+
id: 'msg-1',
|
|
159
|
+
content: 'User message',
|
|
160
|
+
authorId: 'user-123',
|
|
161
|
+
isBot: false,
|
|
162
|
+
} as any,
|
|
163
|
+
];
|
|
164
|
+
|
|
165
|
+
const result = DyNTS_Ass_Util.convertBotMessagesToAIConversation({
|
|
166
|
+
messages: messages,
|
|
167
|
+
botClientId: 'bot-123',
|
|
168
|
+
botDisplayName: 'Bot',
|
|
169
|
+
issuer: 'issuer-123',
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
expect(result[0].role).toBe(DyFM_AI_MessageRole.user);
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
|
|
2
|
+
import { DyNTS_Ass_IO_ControlService } from './ass-io.control-service';
|
|
3
|
+
import { DyNTS_Ass_Main_ControlService } from './ass-main.control-service';
|
|
4
|
+
import { DyNTS_Bot_IO_ControlService } from '../../bot/_services/bot-io.control-service';
|
|
5
|
+
import { DyNTS_Bot_MessageWrapper } from '../../bot/_models/bot-message-wrapper.interface';
|
|
6
|
+
import { DyNTS_AI_LLMChat_ServiceBase } from '../../ai/_services/ai-llm-chat.service-base';
|
|
7
|
+
import { DyFM_Error } from '@futdevpro/fsm-dynamo';
|
|
8
|
+
import { DyNTS_global_settings } from '../../../_collections/global-settings.const';
|
|
9
|
+
import { DyNTS_Ass_Util } from '../_collections/ass.util';
|
|
10
|
+
|
|
11
|
+
class TestAssIOService extends DyNTS_Ass_IO_ControlService {
|
|
12
|
+
protected declare mainBot_CS: any;
|
|
13
|
+
protected getMainBotControlService(): any {
|
|
14
|
+
return {
|
|
15
|
+
gatherMessagesForMessage: jasmine.createSpy('gatherMessagesForMessage').and.returnValue(
|
|
16
|
+
Promise.resolve([])
|
|
17
|
+
),
|
|
18
|
+
defaultSystemPrompt: 'Test prompt',
|
|
19
|
+
aiProvider: {
|
|
20
|
+
requestSimpleMessageInConversation: jasmine.createSpy('requestSimpleMessageInConversation').and.returnValue(
|
|
21
|
+
Promise.resolve('AI response')
|
|
22
|
+
),
|
|
23
|
+
} as any,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
protected getCommandsControlService(): any {
|
|
28
|
+
return {} as any;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static getInstance(): TestAssIOService {
|
|
32
|
+
return TestAssIOService.getSingletonInstance();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
describe('| DyNTS_Ass_IO_ControlService', () => {
|
|
37
|
+
let service: TestAssIOService;
|
|
38
|
+
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
service = TestAssIOService.getInstance();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('| should be a singleton instance', () => {
|
|
44
|
+
const instance1 = TestAssIOService.getInstance();
|
|
45
|
+
const instance2 = TestAssIOService.getInstance();
|
|
46
|
+
|
|
47
|
+
expect(instance1).toBe(instance2);
|
|
48
|
+
expect(instance1).toBeInstanceOf(TestAssIOService);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('| should get AI provider from main bot service', () => {
|
|
52
|
+
(service as any).mainBot_CS = (service as any).getMainBotControlService();
|
|
53
|
+
|
|
54
|
+
expect(service.aiProvider).toBeDefined();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe('| handleMessage', () => {
|
|
58
|
+
it('| should handle message with AI and reply', async () => {
|
|
59
|
+
const mockMessage = {
|
|
60
|
+
provider: {
|
|
61
|
+
botId: 'bot-123',
|
|
62
|
+
botDisplayName: 'Bot',
|
|
63
|
+
replyToMessage: jasmine.createSpy('replyToMessage').and.returnValue(
|
|
64
|
+
Promise.resolve({ content: 'AI response' } as any)
|
|
65
|
+
),
|
|
66
|
+
},
|
|
67
|
+
content: 'User message',
|
|
68
|
+
} as any as DyNTS_Bot_MessageWrapper<any>;
|
|
69
|
+
|
|
70
|
+
(service as any).mainBot_CS = (service as any).getMainBotControlService();
|
|
71
|
+
spyOn(DyNTS_Ass_Util, 'convertBotMessagesToAIConversation').and.returnValue([
|
|
72
|
+
{ role: 'user' as any, content: 'User message' },
|
|
73
|
+
]);
|
|
74
|
+
|
|
75
|
+
const result = await service.handleMessage(mockMessage, 'issuer-123');
|
|
76
|
+
|
|
77
|
+
expect((service as any).mainBot_CS.gatherMessagesForMessage).toHaveBeenCalledWith(mockMessage);
|
|
78
|
+
expect((service as any).mainBot_CS.aiProvider.requestSimpleMessageInConversation).toHaveBeenCalled();
|
|
79
|
+
expect(mockMessage.provider.replyToMessage).toHaveBeenCalledWith(mockMessage, 'AI response');
|
|
80
|
+
expect(result).toBeDefined();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('| should send error reply when error occurs and debugLevel >= 1', async () => {
|
|
84
|
+
const mockMessage = {
|
|
85
|
+
provider: {
|
|
86
|
+
botId: 'bot-123',
|
|
87
|
+
botDisplayName: 'Bot',
|
|
88
|
+
replyToMessage: jasmine.createSpy('replyToMessage').and.returnValue(
|
|
89
|
+
Promise.resolve({} as any)
|
|
90
|
+
),
|
|
91
|
+
},
|
|
92
|
+
content: 'User message',
|
|
93
|
+
} as any as DyNTS_Bot_MessageWrapper<any>;
|
|
94
|
+
|
|
95
|
+
(service as any).mainBot_CS = (service as any).getMainBotControlService();
|
|
96
|
+
(service as any).mainBot_CS.gatherMessagesForMessage = jasmine.createSpy('gatherMessagesForMessage').and.returnValue(
|
|
97
|
+
Promise.reject(new Error('Test error'))
|
|
98
|
+
);
|
|
99
|
+
service.dontSendErrorReply = false;
|
|
100
|
+
// Set bot_settings directly instead of using spyOn
|
|
101
|
+
const originalBotSettings = DyNTS_global_settings.bot_settings;
|
|
102
|
+
(DyNTS_global_settings as any).bot_settings = { debugLevel: 1 };
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
await expectAsync(
|
|
106
|
+
service.handleMessage(mockMessage, 'issuer-123')
|
|
107
|
+
).toBeRejected();
|
|
108
|
+
|
|
109
|
+
expect(mockMessage.provider.replyToMessage).toHaveBeenCalled();
|
|
110
|
+
} finally {
|
|
111
|
+
// Restore original bot_settings
|
|
112
|
+
(DyNTS_global_settings as any).bot_settings = originalBotSettings;
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('| should not send error reply when dontSendErrorReply is true', async () => {
|
|
117
|
+
const mockMessage = {
|
|
118
|
+
provider: {
|
|
119
|
+
botId: 'bot-123',
|
|
120
|
+
botDisplayName: 'Bot',
|
|
121
|
+
replyToMessage: jasmine.createSpy('replyToMessage'),
|
|
122
|
+
},
|
|
123
|
+
content: 'User message',
|
|
124
|
+
} as any as DyNTS_Bot_MessageWrapper<any>;
|
|
125
|
+
|
|
126
|
+
(service as any).mainBot_CS = (service as any).getMainBotControlService();
|
|
127
|
+
(service as any).mainBot_CS.gatherMessagesForMessage = jasmine.createSpy('gatherMessagesForMessage').and.returnValue(
|
|
128
|
+
Promise.reject(new Error('Test error'))
|
|
129
|
+
);
|
|
130
|
+
service.dontSendErrorReply = true;
|
|
131
|
+
|
|
132
|
+
await expectAsync(
|
|
133
|
+
service.handleMessage(mockMessage, 'issuer-123')
|
|
134
|
+
).toBeRejected();
|
|
135
|
+
|
|
136
|
+
expect(mockMessage.provider.replyToMessage).not.toHaveBeenCalled();
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
|
|
2
|
+
import { DyNTS_Ass_Main_ControlService } from './ass-main.control-service';
|
|
3
|
+
import { DyNTS_Bot_Main_ControlService } from '../../bot/_services/bot-main.control-service';
|
|
4
|
+
import { DyNTS_AI_LLMChat_ServiceBase } from '../../ai/_services/ai-llm-chat.service-base';
|
|
5
|
+
import { DyNTS_Bot_MessageWrapper } from '../../bot/_models/bot-message-wrapper.interface';
|
|
6
|
+
import { DyNTS_Bot_ChannelWrapper } from '../../bot/_models/bot-channel-wrapper.interface';
|
|
7
|
+
import { DyFM_AI_Message } from '@futdevpro/fsm-dynamo/ai';
|
|
8
|
+
import { DyFM_Msg_Provider_Type } from '@futdevpro/fsm-dynamo/messaging';
|
|
9
|
+
import { DyNTS_Ass_Util } from '../_collections/ass.util';
|
|
10
|
+
import { DyNTS_Ass_global_settings } from '../_collections/ass-global-settings.const';
|
|
11
|
+
|
|
12
|
+
class TestAssMainService extends DyNTS_Ass_Main_ControlService<DyFM_Msg_Provider_Type> {
|
|
13
|
+
protected getAIProvider(): DyNTS_AI_LLMChat_ServiceBase {
|
|
14
|
+
return {
|
|
15
|
+
defaultSettings: {
|
|
16
|
+
systemPrompt: 'Test prompt',
|
|
17
|
+
useModel: 'test-model',
|
|
18
|
+
},
|
|
19
|
+
} as any;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
protected getBotIOControlService(): any {
|
|
23
|
+
return {} as any;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
protected getRoutinesControlService(): any {
|
|
27
|
+
return {} as any;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
protected getCommandsControlService(): any {
|
|
31
|
+
return {} as any;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
protected defaultProviderType: DyFM_Msg_Provider_Type = DyFM_Msg_Provider_Type.discord;
|
|
35
|
+
protected availableProviders: any[] = [];
|
|
36
|
+
|
|
37
|
+
static getInstance(): TestAssMainService {
|
|
38
|
+
return TestAssMainService.getSingletonInstance();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
describe('| DyNTS_Ass_Main_ControlService', () => {
|
|
43
|
+
let service: TestAssMainService;
|
|
44
|
+
|
|
45
|
+
beforeEach(() => {
|
|
46
|
+
service = TestAssMainService.getInstance();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('| should be a singleton instance', () => {
|
|
50
|
+
const instance1 = TestAssMainService.getInstance();
|
|
51
|
+
const instance2 = TestAssMainService.getInstance();
|
|
52
|
+
|
|
53
|
+
expect(instance1).toBe(instance2);
|
|
54
|
+
expect(instance1).toBeInstanceOf(TestAssMainService);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('| should have default system prompt', () => {
|
|
58
|
+
expect(service.defaultSystemPrompt).toBe(DyNTS_Ass_global_settings.defaultSystemPrompt);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('| should initialize AI provider in constructor', () => {
|
|
62
|
+
expect(service.aiProvider).toBeDefined();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe('| gatherMessagesForMessage', () => {
|
|
66
|
+
it('| should gather and filter messages', async () => {
|
|
67
|
+
const mockMessage = {
|
|
68
|
+
provider: {
|
|
69
|
+
fetchMessagesForMessage: jasmine.createSpy('fetchMessagesForMessage').and.returnValue(
|
|
70
|
+
Promise.resolve([
|
|
71
|
+
{ content: 'Message 1', timestamp: 1000 },
|
|
72
|
+
{ content: '[NOISE] Message 2', timestamp: 2000 },
|
|
73
|
+
{ content: 'Message 3', timestamp: 3000 },
|
|
74
|
+
] as any[])
|
|
75
|
+
),
|
|
76
|
+
},
|
|
77
|
+
} as any as DyNTS_Bot_MessageWrapper<any>;
|
|
78
|
+
|
|
79
|
+
const result = await service.gatherMessagesForMessage(mockMessage);
|
|
80
|
+
|
|
81
|
+
expect(result.length).toBe(2);
|
|
82
|
+
expect(result[0].content).toBe('Message 1');
|
|
83
|
+
expect(result[1].content).toBe('Message 3');
|
|
84
|
+
expect(mockMessage.provider.fetchMessagesForMessage).toHaveBeenCalledWith(mockMessage, 100);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('| should use custom limit', async () => {
|
|
88
|
+
const mockMessage = {
|
|
89
|
+
provider: {
|
|
90
|
+
fetchMessagesForMessage: jasmine.createSpy('fetchMessagesForMessage').and.returnValue(
|
|
91
|
+
Promise.resolve([])
|
|
92
|
+
),
|
|
93
|
+
},
|
|
94
|
+
} as any as DyNTS_Bot_MessageWrapper<any>;
|
|
95
|
+
|
|
96
|
+
await service.gatherMessagesForMessage(mockMessage, 50);
|
|
97
|
+
|
|
98
|
+
expect(mockMessage.provider.fetchMessagesForMessage).toHaveBeenCalledWith(mockMessage, 50);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('| should sort messages by timestamp', async () => {
|
|
102
|
+
const mockMessage = {
|
|
103
|
+
provider: {
|
|
104
|
+
fetchMessagesForMessage: jasmine.createSpy('fetchMessagesForMessage').and.returnValue(
|
|
105
|
+
Promise.resolve([
|
|
106
|
+
{ content: 'Message 3', timestamp: 3000 },
|
|
107
|
+
{ content: 'Message 1', timestamp: 1000 },
|
|
108
|
+
{ content: 'Message 2', timestamp: 2000 },
|
|
109
|
+
] as any[])
|
|
110
|
+
),
|
|
111
|
+
},
|
|
112
|
+
} as any as DyNTS_Bot_MessageWrapper<any>;
|
|
113
|
+
|
|
114
|
+
const result = await service.gatherMessagesForMessage(mockMessage);
|
|
115
|
+
|
|
116
|
+
expect(result[0].timestamp).toBe(1000);
|
|
117
|
+
expect(result[1].timestamp).toBe(2000);
|
|
118
|
+
expect(result[2].timestamp).toBe(3000);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
describe('| gatherMessagesInChannel', () => {
|
|
123
|
+
it('| should gather messages from channel', async () => {
|
|
124
|
+
const mockChannel = {
|
|
125
|
+
provider: {
|
|
126
|
+
fetchMessages: jasmine.createSpy('fetchMessages').and.returnValue(
|
|
127
|
+
Promise.resolve([
|
|
128
|
+
{ content: 'Message 1' },
|
|
129
|
+
{ content: 'Message 2' },
|
|
130
|
+
] as any[])
|
|
131
|
+
),
|
|
132
|
+
},
|
|
133
|
+
} as any as DyNTS_Bot_ChannelWrapper;
|
|
134
|
+
|
|
135
|
+
const result = await service.gatherMessagesInChannel(mockChannel, 'issuer-123');
|
|
136
|
+
|
|
137
|
+
expect(result.length).toBe(2);
|
|
138
|
+
expect(mockChannel.provider.fetchMessages).toHaveBeenCalledWith(mockChannel, 100);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
describe('| gatherMessagesAsAIConversation', () => {
|
|
143
|
+
it('| should convert messages to AI conversation format', async () => {
|
|
144
|
+
const mockMessage = {
|
|
145
|
+
provider: {
|
|
146
|
+
botId: 'bot-123',
|
|
147
|
+
botDisplayName: 'Bot',
|
|
148
|
+
fetchMessagesForMessage: jasmine.createSpy('fetchMessagesForMessage').and.returnValue(
|
|
149
|
+
Promise.resolve([
|
|
150
|
+
{ content: 'User message', authorId: 'user-123', isBot: false },
|
|
151
|
+
{ content: 'Bot message', authorId: 'bot-123', isBot: true },
|
|
152
|
+
] as any[])
|
|
153
|
+
),
|
|
154
|
+
},
|
|
155
|
+
} as any as DyNTS_Bot_MessageWrapper<any>;
|
|
156
|
+
spyOn(DyNTS_Ass_Util, 'convertBotMessagesToAIConversation').and.returnValue([
|
|
157
|
+
{ role: 'user' as any, content: 'User message' },
|
|
158
|
+
{ role: 'assistant' as any, content: 'Bot message' },
|
|
159
|
+
]);
|
|
160
|
+
|
|
161
|
+
const result = await service.gatherMessagesAsAIConversation(mockMessage, 'issuer-123');
|
|
162
|
+
|
|
163
|
+
expect(result.length).toBe(2);
|
|
164
|
+
expect(DyNTS_Ass_Util.convertBotMessagesToAIConversation).toHaveBeenCalled();
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
describe('| gatherMessagesAsAIConversationInChannel', () => {
|
|
169
|
+
it('| should convert channel messages to AI conversation format', async () => {
|
|
170
|
+
const mockChannel = {
|
|
171
|
+
provider: {
|
|
172
|
+
botId: 'bot-123',
|
|
173
|
+
botDisplayName: 'Bot',
|
|
174
|
+
fetchMessages: jasmine.createSpy('fetchMessages').and.returnValue(
|
|
175
|
+
Promise.resolve([
|
|
176
|
+
{ content: 'User message', authorId: 'user-123', isBot: false },
|
|
177
|
+
] as any[])
|
|
178
|
+
),
|
|
179
|
+
},
|
|
180
|
+
} as any as DyNTS_Bot_ChannelWrapper;
|
|
181
|
+
spyOn(DyNTS_Ass_Util, 'convertBotMessagesToAIConversation').and.returnValue([
|
|
182
|
+
{ role: 'user' as any, content: 'User message' },
|
|
183
|
+
]);
|
|
184
|
+
|
|
185
|
+
const result = await service.gatherMessagesAsAIConversationInChannel(mockChannel, 'issuer-123');
|
|
186
|
+
|
|
187
|
+
expect(result.length).toBe(1);
|
|
188
|
+
expect(DyNTS_Ass_Util.convertBotMessagesToAIConversation).toHaveBeenCalled();
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
|