@memnexus-ai/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +13 -0
- package/.eslintrc.js +24 -0
- package/.github/ISSUE_TEMPLATE/phase-1-foundation.md +1078 -0
- package/.github/workflows/publish.yml +277 -0
- package/.github/workflows/test-app-token.yml +54 -0
- package/.npmrc.backup +3 -0
- package/.npmrc.example +6 -0
- package/.prettierignore +4 -0
- package/.prettierrc +8 -0
- package/CHANGELOG.md +138 -0
- package/PLATFORM_TESTING.md +243 -0
- package/README.md +986 -0
- package/RELEASE.md +428 -0
- package/RELEASE_READINESS.md +253 -0
- package/USAGE.md +1373 -0
- package/bin/mx.js +2 -0
- package/dist/commands/apikeys.d.ts +7 -0
- package/dist/commands/apikeys.d.ts.map +1 -0
- package/dist/commands/apikeys.js +133 -0
- package/dist/commands/apikeys.js.map +1 -0
- package/dist/commands/artifacts.d.ts +7 -0
- package/dist/commands/artifacts.d.ts.map +1 -0
- package/dist/commands/artifacts.js +277 -0
- package/dist/commands/artifacts.js.map +1 -0
- package/dist/commands/auth.d.ts +7 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +119 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/communities.d.ts +7 -0
- package/dist/commands/communities.d.ts.map +1 -0
- package/dist/commands/communities.js +137 -0
- package/dist/commands/communities.js.map +1 -0
- package/dist/commands/config.d.ts +7 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +138 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/conversations.d.ts +7 -0
- package/dist/commands/conversations.d.ts.map +1 -0
- package/dist/commands/conversations.js +160 -0
- package/dist/commands/conversations.js.map +1 -0
- package/dist/commands/facts.d.ts +7 -0
- package/dist/commands/facts.d.ts.map +1 -0
- package/dist/commands/facts.js +298 -0
- package/dist/commands/facts.js.map +1 -0
- package/dist/commands/graphrag.d.ts +7 -0
- package/dist/commands/graphrag.d.ts.map +1 -0
- package/dist/commands/graphrag.js +139 -0
- package/dist/commands/graphrag.js.map +1 -0
- package/dist/commands/memories.d.ts +7 -0
- package/dist/commands/memories.d.ts.map +1 -0
- package/dist/commands/memories.js +304 -0
- package/dist/commands/memories.js.map +1 -0
- package/dist/commands/patterns.d.ts +7 -0
- package/dist/commands/patterns.d.ts.map +1 -0
- package/dist/commands/patterns.js +227 -0
- package/dist/commands/patterns.js.map +1 -0
- package/dist/commands/system.d.ts +7 -0
- package/dist/commands/system.d.ts.map +1 -0
- package/dist/commands/system.js +97 -0
- package/dist/commands/system.js.map +1 -0
- package/dist/commands/topics.d.ts +7 -0
- package/dist/commands/topics.d.ts.map +1 -0
- package/dist/commands/topics.js +314 -0
- package/dist/commands/topics.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api-client.d.ts +29 -0
- package/dist/lib/api-client.d.ts.map +1 -0
- package/dist/lib/api-client.js +64 -0
- package/dist/lib/api-client.js.map +1 -0
- package/dist/lib/auth.d.ts +10 -0
- package/dist/lib/auth.d.ts.map +1 -0
- package/dist/lib/auth.js +47 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/config.d.ts +19 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +59 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/errors.d.ts +7 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +133 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/formatters.d.ts +12 -0
- package/dist/lib/formatters.d.ts.map +1 -0
- package/dist/lib/formatters.js +103 -0
- package/dist/lib/formatters.js.map +1 -0
- package/dist/lib/spinner.d.ts +54 -0
- package/dist/lib/spinner.d.ts.map +1 -0
- package/dist/lib/spinner.js +108 -0
- package/dist/lib/spinner.js.map +1 -0
- package/dist/lib/validators.d.ts +92 -0
- package/dist/lib/validators.d.ts.map +1 -0
- package/dist/lib/validators.js +257 -0
- package/dist/lib/validators.js.map +1 -0
- package/dist/types/index.d.ts +13 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/docs/README.md +219 -0
- package/docs/code-generation-strategy.md +560 -0
- package/docs/prd.md +748 -0
- package/docs/sync-strategy.md +533 -0
- package/jest.config.js +30 -0
- package/package.json +67 -0
- package/scripts/install-deps.sh +38 -0
- package/src/commands/apikeys.ts +144 -0
- package/src/commands/artifacts.ts +296 -0
- package/src/commands/auth.ts +122 -0
- package/src/commands/communities.ts +153 -0
- package/src/commands/config.ts +144 -0
- package/src/commands/conversations.ts +176 -0
- package/src/commands/facts.ts +320 -0
- package/src/commands/graphrag.ts +149 -0
- package/src/commands/memories.ts +332 -0
- package/src/commands/patterns.ts +251 -0
- package/src/commands/system.ts +102 -0
- package/src/commands/topics.ts +354 -0
- package/src/index.ts +43 -0
- package/src/lib/api-client.ts +68 -0
- package/src/lib/auth.ts +42 -0
- package/src/lib/config.ts +68 -0
- package/src/lib/errors.ts +143 -0
- package/src/lib/formatters.ts +123 -0
- package/src/lib/spinner.ts +113 -0
- package/src/lib/validators.ts +302 -0
- package/src/types/index.ts +17 -0
- package/tests/__mocks__/chalk.ts +16 -0
- package/tests/__mocks__/cli-table3.ts +37 -0
- package/tests/__mocks__/configstore.ts +38 -0
- package/tests/commands/apikeys.test.ts +179 -0
- package/tests/commands/artifacts.test.ts +194 -0
- package/tests/commands/auth.test.ts +120 -0
- package/tests/commands/communities.test.ts +154 -0
- package/tests/commands/config.test.ts +154 -0
- package/tests/commands/conversations.test.ts +136 -0
- package/tests/commands/facts.test.ts +210 -0
- package/tests/commands/graphrag.test.ts +194 -0
- package/tests/commands/memories.test.ts +215 -0
- package/tests/commands/patterns.test.ts +201 -0
- package/tests/commands/system.test.ts +172 -0
- package/tests/commands/topics.test.ts +274 -0
- package/tests/lib/auth.test.ts +77 -0
- package/tests/lib/config.test.ts +50 -0
- package/tests/lib/errors.test.ts +126 -0
- package/tests/lib/formatters.test.ts +87 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { getApiClient } from '../../src/lib/api-client';
|
|
2
|
+
|
|
3
|
+
// Mock the API client
|
|
4
|
+
jest.mock('../../src/lib/api-client');
|
|
5
|
+
|
|
6
|
+
// Mock chalk
|
|
7
|
+
jest.mock('chalk', () => ({
|
|
8
|
+
default: {
|
|
9
|
+
green: (str: string) => str,
|
|
10
|
+
red: (str: string) => str,
|
|
11
|
+
yellow: (str: string) => str,
|
|
12
|
+
cyan: (str: string) => str,
|
|
13
|
+
gray: (str: string) => str,
|
|
14
|
+
},
|
|
15
|
+
green: (str: string) => str,
|
|
16
|
+
red: (str: string) => str,
|
|
17
|
+
yellow: (str: string) => str,
|
|
18
|
+
cyan: (str: string) => str,
|
|
19
|
+
gray: (str: string) => str,
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
// Mock ora
|
|
23
|
+
jest.mock('ora', () => {
|
|
24
|
+
return jest.fn(() => ({
|
|
25
|
+
start: jest.fn(function() { return this; }),
|
|
26
|
+
succeed: jest.fn(function() { return this; }),
|
|
27
|
+
fail: jest.fn(function() { return this; }),
|
|
28
|
+
}));
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('GraphRAG Commands', () => {
|
|
32
|
+
let mockClient: any;
|
|
33
|
+
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
jest.clearAllMocks();
|
|
36
|
+
|
|
37
|
+
mockClient = {
|
|
38
|
+
graphrag: {
|
|
39
|
+
query: jest.fn(),
|
|
40
|
+
explain: jest.fn(),
|
|
41
|
+
queryCommunities: jest.fn(),
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
(getApiClient as jest.Mock).mockReturnValue(mockClient);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe('graphrag query', () => {
|
|
49
|
+
it('should execute GraphRAG query', async () => {
|
|
50
|
+
const mockResponse = {
|
|
51
|
+
data: [
|
|
52
|
+
{
|
|
53
|
+
id: 'result_1',
|
|
54
|
+
answer: 'This is the answer to your query',
|
|
55
|
+
sources: ['source_1', 'source_2'],
|
|
56
|
+
confidence: 0.92,
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
mockClient.graphrag.query.mockResolvedValue(mockResponse);
|
|
62
|
+
|
|
63
|
+
const result = await mockClient.graphrag.query({
|
|
64
|
+
query: 'What is the meaning of life?',
|
|
65
|
+
mode: 'hybrid',
|
|
66
|
+
maxDepth: 3,
|
|
67
|
+
limit: 20,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
expect(mockClient.graphrag.query).toHaveBeenCalledWith({
|
|
71
|
+
query: 'What is the meaning of life?',
|
|
72
|
+
mode: 'hybrid',
|
|
73
|
+
maxDepth: 3,
|
|
74
|
+
limit: 20,
|
|
75
|
+
});
|
|
76
|
+
expect(result.data).toHaveLength(1);
|
|
77
|
+
expect(result.data[0].confidence).toBe(0.92);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('should support different query modes', async () => {
|
|
81
|
+
const mockResponse = { data: [] };
|
|
82
|
+
|
|
83
|
+
mockClient.graphrag.query.mockResolvedValue(mockResponse);
|
|
84
|
+
|
|
85
|
+
await mockClient.graphrag.query({
|
|
86
|
+
query: 'test',
|
|
87
|
+
mode: 'local',
|
|
88
|
+
maxDepth: 2,
|
|
89
|
+
limit: 10,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
expect(mockClient.graphrag.query).toHaveBeenCalledWith({
|
|
93
|
+
query: 'test',
|
|
94
|
+
mode: 'local',
|
|
95
|
+
maxDepth: 2,
|
|
96
|
+
limit: 10,
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should support context filtering', async () => {
|
|
101
|
+
const mockResponse = { data: [] };
|
|
102
|
+
|
|
103
|
+
mockClient.graphrag.query.mockResolvedValue(mockResponse);
|
|
104
|
+
|
|
105
|
+
await mockClient.graphrag.query({
|
|
106
|
+
query: 'test',
|
|
107
|
+
contextId: 'ctx_123',
|
|
108
|
+
mode: 'hybrid',
|
|
109
|
+
maxDepth: 3,
|
|
110
|
+
limit: 20,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
expect(mockClient.graphrag.query).toHaveBeenCalledWith({
|
|
114
|
+
query: 'test',
|
|
115
|
+
contextId: 'ctx_123',
|
|
116
|
+
mode: 'hybrid',
|
|
117
|
+
maxDepth: 3,
|
|
118
|
+
limit: 20,
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe('graphrag explain', () => {
|
|
124
|
+
it('should explain query result', async () => {
|
|
125
|
+
const mockResult = {
|
|
126
|
+
resultId: 'result_1',
|
|
127
|
+
explanation: 'This result was derived by traversing the knowledge graph...',
|
|
128
|
+
graphPath: ['node_1', 'node_2', 'node_3'],
|
|
129
|
+
reasoning: 'The system found connections between...',
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
mockClient.graphrag.explain.mockResolvedValue(mockResult);
|
|
133
|
+
|
|
134
|
+
const result = await mockClient.graphrag.explain('result_1');
|
|
135
|
+
|
|
136
|
+
expect(mockClient.graphrag.explain).toHaveBeenCalledWith('result_1');
|
|
137
|
+
expect(result.explanation).toBeDefined();
|
|
138
|
+
expect(result.graphPath).toHaveLength(3);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
describe('graphrag query-communities', () => {
|
|
143
|
+
it('should query communities', async () => {
|
|
144
|
+
const mockResponse = {
|
|
145
|
+
data: [
|
|
146
|
+
{
|
|
147
|
+
communityId: 'comm_1',
|
|
148
|
+
communityName: 'Technology Community',
|
|
149
|
+
answer: 'Community-level answer to the query',
|
|
150
|
+
confidence: 0.88,
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
communityId: 'comm_2',
|
|
154
|
+
communityName: 'Science Community',
|
|
155
|
+
answer: 'Another community perspective',
|
|
156
|
+
confidence: 0.85,
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
mockClient.graphrag.queryCommunities.mockResolvedValue(mockResponse);
|
|
162
|
+
|
|
163
|
+
const result = await mockClient.graphrag.queryCommunities({
|
|
164
|
+
query: 'What are the latest trends?',
|
|
165
|
+
limit: 10,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
expect(mockClient.graphrag.queryCommunities).toHaveBeenCalledWith({
|
|
169
|
+
query: 'What are the latest trends?',
|
|
170
|
+
limit: 10,
|
|
171
|
+
});
|
|
172
|
+
expect(result.data).toHaveLength(2);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('should support context filtering in community queries', async () => {
|
|
176
|
+
const mockResponse = { data: [] };
|
|
177
|
+
|
|
178
|
+
mockClient.graphrag.queryCommunities.mockResolvedValue(mockResponse);
|
|
179
|
+
|
|
180
|
+
await mockClient.graphrag.queryCommunities({
|
|
181
|
+
query: 'test',
|
|
182
|
+
contextId: 'ctx_123',
|
|
183
|
+
limit: 10,
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
expect(mockClient.graphrag.queryCommunities).toHaveBeenCalledWith({
|
|
187
|
+
query: 'test',
|
|
188
|
+
contextId: 'ctx_123',
|
|
189
|
+
limit: 10,
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { getApiClient } from '../../src/lib/api-client';
|
|
2
|
+
|
|
3
|
+
// Mock the API client
|
|
4
|
+
jest.mock('../../src/lib/api-client');
|
|
5
|
+
|
|
6
|
+
// Mock chalk
|
|
7
|
+
jest.mock('chalk', () => ({
|
|
8
|
+
default: {
|
|
9
|
+
green: (str: string) => str,
|
|
10
|
+
red: (str: string) => str,
|
|
11
|
+
yellow: (str: string) => str,
|
|
12
|
+
cyan: (str: string) => str,
|
|
13
|
+
gray: (str: string) => str,
|
|
14
|
+
},
|
|
15
|
+
green: (str: string) => str,
|
|
16
|
+
red: (str: string) => str,
|
|
17
|
+
yellow: (str: string) => str,
|
|
18
|
+
cyan: (str: string) => str,
|
|
19
|
+
gray: (str: string) => str,
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
describe('Memories Commands', () => {
|
|
23
|
+
let mockClient: any;
|
|
24
|
+
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
jest.clearAllMocks();
|
|
27
|
+
|
|
28
|
+
mockClient = {
|
|
29
|
+
memories: {
|
|
30
|
+
list: jest.fn(),
|
|
31
|
+
get: jest.fn(),
|
|
32
|
+
create: jest.fn(),
|
|
33
|
+
update: jest.fn(),
|
|
34
|
+
delete: jest.fn(),
|
|
35
|
+
},
|
|
36
|
+
search: {
|
|
37
|
+
query: jest.fn(),
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
(getApiClient as jest.Mock).mockReturnValue(mockClient);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe('memories list', () => {
|
|
45
|
+
it('should list memories with default pagination', async () => {
|
|
46
|
+
const mockResponse = {
|
|
47
|
+
data: [
|
|
48
|
+
{
|
|
49
|
+
id: 'mem_1',
|
|
50
|
+
content: 'Test memory 1',
|
|
51
|
+
memoryType: 'episodic',
|
|
52
|
+
createdAt: '2024-01-01T00:00:00Z',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: 'mem_2',
|
|
56
|
+
content: 'Test memory 2',
|
|
57
|
+
memoryType: 'semantic',
|
|
58
|
+
createdAt: '2024-01-02T00:00:00Z',
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
pagination: {
|
|
62
|
+
limit: 20,
|
|
63
|
+
offset: 0,
|
|
64
|
+
count: 2,
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
mockClient.memories.list.mockResolvedValue(mockResponse);
|
|
69
|
+
|
|
70
|
+
const result = await mockClient.memories.list({ limit: 20, offset: 0 });
|
|
71
|
+
|
|
72
|
+
expect(mockClient.memories.list).toHaveBeenCalledWith({ limit: 20, offset: 0 });
|
|
73
|
+
expect(result.data).toHaveLength(2);
|
|
74
|
+
expect(result.pagination.count).toBe(2);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should handle pagination parameters', async () => {
|
|
78
|
+
const mockResponse = {
|
|
79
|
+
data: [],
|
|
80
|
+
pagination: { limit: 10, offset: 20, count: 0 },
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
mockClient.memories.list.mockResolvedValue(mockResponse);
|
|
84
|
+
|
|
85
|
+
await mockClient.memories.list({ limit: 10, offset: 20 });
|
|
86
|
+
|
|
87
|
+
expect(mockClient.memories.list).toHaveBeenCalledWith({ limit: 10, offset: 20 });
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe('memories get', () => {
|
|
92
|
+
it('should get a specific memory by ID', async () => {
|
|
93
|
+
const mockMemory = {
|
|
94
|
+
id: 'mem_123',
|
|
95
|
+
content: 'Test memory content',
|
|
96
|
+
memoryType: 'episodic',
|
|
97
|
+
createdAt: '2024-01-01T00:00:00Z',
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
mockClient.memories.get.mockResolvedValue(mockMemory);
|
|
101
|
+
|
|
102
|
+
const result = await mockClient.memories.get('mem_123');
|
|
103
|
+
|
|
104
|
+
expect(mockClient.memories.get).toHaveBeenCalledWith('mem_123');
|
|
105
|
+
expect(result.id).toBe('mem_123');
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('should handle 404 errors gracefully', async () => {
|
|
109
|
+
mockClient.memories.get.mockRejectedValue(new Error('Not found'));
|
|
110
|
+
|
|
111
|
+
await expect(mockClient.memories.get('invalid_id')).rejects.toThrow('Not found');
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('memories create', () => {
|
|
116
|
+
it('should create a memory with required fields', async () => {
|
|
117
|
+
const memoryData = {
|
|
118
|
+
content: 'New memory content',
|
|
119
|
+
memoryType: 'episodic',
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const mockCreated = {
|
|
123
|
+
id: 'mem_new',
|
|
124
|
+
...memoryData,
|
|
125
|
+
createdAt: '2024-01-01T00:00:00Z',
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
mockClient.memories.create.mockResolvedValue(mockCreated);
|
|
129
|
+
|
|
130
|
+
const result = await mockClient.memories.create(memoryData);
|
|
131
|
+
|
|
132
|
+
expect(mockClient.memories.create).toHaveBeenCalledWith(memoryData);
|
|
133
|
+
expect(result.id).toBe('mem_new');
|
|
134
|
+
expect(result.content).toBe(memoryData.content);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('should create a memory with optional fields', async () => {
|
|
138
|
+
const memoryData = {
|
|
139
|
+
content: 'New memory',
|
|
140
|
+
memoryType: 'semantic',
|
|
141
|
+
context: 'work',
|
|
142
|
+
topics: ['project-a', 'meeting'],
|
|
143
|
+
importance: 0.8,
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
mockClient.memories.create.mockResolvedValue({ id: 'mem_new', ...memoryData });
|
|
147
|
+
|
|
148
|
+
const result = await mockClient.memories.create(memoryData);
|
|
149
|
+
|
|
150
|
+
expect(result.topics).toEqual(['project-a', 'meeting']);
|
|
151
|
+
expect(result.importance).toBe(0.8);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
describe('memories update', () => {
|
|
156
|
+
it('should update memory fields', async () => {
|
|
157
|
+
const updates = {
|
|
158
|
+
content: 'Updated content',
|
|
159
|
+
importance: 0.9,
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const mockUpdated = {
|
|
163
|
+
id: 'mem_123',
|
|
164
|
+
...updates,
|
|
165
|
+
memoryType: 'episodic',
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
mockClient.memories.update.mockResolvedValue(mockUpdated);
|
|
169
|
+
|
|
170
|
+
const result = await mockClient.memories.update('mem_123', updates);
|
|
171
|
+
|
|
172
|
+
expect(mockClient.memories.update).toHaveBeenCalledWith('mem_123', updates);
|
|
173
|
+
expect(result.content).toBe('Updated content');
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
describe('memories delete', () => {
|
|
178
|
+
it('should delete a memory', async () => {
|
|
179
|
+
mockClient.memories.delete.mockResolvedValue(undefined);
|
|
180
|
+
|
|
181
|
+
await mockClient.memories.delete('mem_123');
|
|
182
|
+
|
|
183
|
+
expect(mockClient.memories.delete).toHaveBeenCalledWith('mem_123');
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
describe('memories search', () => {
|
|
188
|
+
it('should search memories with query', async () => {
|
|
189
|
+
const mockResults = {
|
|
190
|
+
results: [
|
|
191
|
+
{
|
|
192
|
+
memory: { id: 'mem_1', content: 'Matching memory' },
|
|
193
|
+
score: 0.95,
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
mockClient.search.query.mockResolvedValue(mockResults);
|
|
199
|
+
|
|
200
|
+
const result = await mockClient.search.query({
|
|
201
|
+
query: 'test query',
|
|
202
|
+
limit: 10,
|
|
203
|
+
threshold: 0.7,
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
expect(mockClient.search.query).toHaveBeenCalledWith({
|
|
207
|
+
query: 'test query',
|
|
208
|
+
limit: 10,
|
|
209
|
+
threshold: 0.7,
|
|
210
|
+
});
|
|
211
|
+
expect(result.results).toHaveLength(1);
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { getApiClient } from '../../src/lib/api-client';
|
|
2
|
+
|
|
3
|
+
// Mock the API client
|
|
4
|
+
jest.mock('../../src/lib/api-client');
|
|
5
|
+
|
|
6
|
+
// Mock chalk
|
|
7
|
+
jest.mock('chalk', () => ({
|
|
8
|
+
default: {
|
|
9
|
+
green: (str: string) => str,
|
|
10
|
+
red: (str: string) => str,
|
|
11
|
+
yellow: (str: string) => str,
|
|
12
|
+
cyan: (str: string) => str,
|
|
13
|
+
gray: (str: string) => str,
|
|
14
|
+
},
|
|
15
|
+
green: (str: string) => str,
|
|
16
|
+
red: (str: string) => str,
|
|
17
|
+
yellow: (str: string) => str,
|
|
18
|
+
cyan: (str: string) => str,
|
|
19
|
+
gray: (str: string) => str,
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
// Mock ora
|
|
23
|
+
jest.mock('ora', () => {
|
|
24
|
+
return jest.fn(() => ({
|
|
25
|
+
start: jest.fn(function() { return this; }),
|
|
26
|
+
succeed: jest.fn(function() { return this; }),
|
|
27
|
+
fail: jest.fn(function() { return this; }),
|
|
28
|
+
}));
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('Patterns Commands', () => {
|
|
32
|
+
let mockClient: any;
|
|
33
|
+
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
jest.clearAllMocks();
|
|
36
|
+
|
|
37
|
+
mockClient = {
|
|
38
|
+
patterns: {
|
|
39
|
+
list: jest.fn(),
|
|
40
|
+
compile: jest.fn(),
|
|
41
|
+
update: jest.fn(),
|
|
42
|
+
feedback: jest.fn(),
|
|
43
|
+
getBehaviorState: jest.fn(),
|
|
44
|
+
setBehaviorState: jest.fn(),
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
(getApiClient as jest.Mock).mockReturnValue(mockClient);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('patterns list', () => {
|
|
52
|
+
it('should list patterns with default pagination', async () => {
|
|
53
|
+
const mockResponse = {
|
|
54
|
+
data: [
|
|
55
|
+
{
|
|
56
|
+
id: 'pat_1',
|
|
57
|
+
type: 'behavioral',
|
|
58
|
+
description: 'Test pattern 1',
|
|
59
|
+
confidence: 0.85,
|
|
60
|
+
lastUpdated: '2024-01-01T00:00:00Z',
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
pagination: {
|
|
64
|
+
limit: 20,
|
|
65
|
+
offset: 0,
|
|
66
|
+
count: 1,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
mockClient.patterns.list.mockResolvedValue(mockResponse);
|
|
71
|
+
|
|
72
|
+
const result = await mockClient.patterns.list({ limit: 20, offset: 0 });
|
|
73
|
+
|
|
74
|
+
expect(mockClient.patterns.list).toHaveBeenCalledWith({ limit: 20, offset: 0 });
|
|
75
|
+
expect(result.data).toHaveLength(1);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should filter by type', async () => {
|
|
79
|
+
const mockResponse = {
|
|
80
|
+
data: [],
|
|
81
|
+
pagination: { limit: 20, offset: 0, count: 0 },
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
mockClient.patterns.list.mockResolvedValue(mockResponse);
|
|
85
|
+
|
|
86
|
+
await mockClient.patterns.list({ limit: 20, offset: 0, type: 'behavioral' });
|
|
87
|
+
|
|
88
|
+
expect(mockClient.patterns.list).toHaveBeenCalledWith({
|
|
89
|
+
limit: 20,
|
|
90
|
+
offset: 0,
|
|
91
|
+
type: 'behavioral',
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe('patterns compile', () => {
|
|
97
|
+
it('should compile patterns', async () => {
|
|
98
|
+
const mockResult = {
|
|
99
|
+
compiled: 5,
|
|
100
|
+
patterns: [],
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
mockClient.patterns.compile.mockResolvedValue(mockResult);
|
|
104
|
+
|
|
105
|
+
const result = await mockClient.patterns.compile({
|
|
106
|
+
contextId: 'ctx_123',
|
|
107
|
+
force: false,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
expect(mockClient.patterns.compile).toHaveBeenCalledWith({
|
|
111
|
+
contextId: 'ctx_123',
|
|
112
|
+
force: false,
|
|
113
|
+
});
|
|
114
|
+
expect(result.compiled).toBe(5);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
describe('patterns update', () => {
|
|
119
|
+
it('should update pattern', async () => {
|
|
120
|
+
const mockResult = {
|
|
121
|
+
id: 'pat_1',
|
|
122
|
+
description: 'Updated description',
|
|
123
|
+
confidence: 0.9,
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
mockClient.patterns.update.mockResolvedValue(mockResult);
|
|
127
|
+
|
|
128
|
+
const result = await mockClient.patterns.update('pat_1', {
|
|
129
|
+
description: 'Updated description',
|
|
130
|
+
confidence: 0.9,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
expect(mockClient.patterns.update).toHaveBeenCalledWith('pat_1', {
|
|
134
|
+
description: 'Updated description',
|
|
135
|
+
confidence: 0.9,
|
|
136
|
+
});
|
|
137
|
+
expect(result.confidence).toBe(0.9);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe('patterns feedback', () => {
|
|
142
|
+
it('should record feedback', async () => {
|
|
143
|
+
mockClient.patterns.feedback.mockResolvedValue({ success: true });
|
|
144
|
+
|
|
145
|
+
const result = await mockClient.patterns.feedback({
|
|
146
|
+
patternId: 'pat_1',
|
|
147
|
+
feedbackType: 'positive',
|
|
148
|
+
comment: 'Good pattern',
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
expect(mockClient.patterns.feedback).toHaveBeenCalledWith({
|
|
152
|
+
patternId: 'pat_1',
|
|
153
|
+
feedbackType: 'positive',
|
|
154
|
+
comment: 'Good pattern',
|
|
155
|
+
});
|
|
156
|
+
expect(result.success).toBe(true);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
describe('patterns behavior-state', () => {
|
|
161
|
+
it('should get behavioral state', async () => {
|
|
162
|
+
const mockResult = {
|
|
163
|
+
contextId: 'ctx_123',
|
|
164
|
+
activePatterns: ['pat_1', 'pat_2'],
|
|
165
|
+
state: {},
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
mockClient.patterns.getBehaviorState.mockResolvedValue(mockResult);
|
|
169
|
+
|
|
170
|
+
const result = await mockClient.patterns.getBehaviorState({
|
|
171
|
+
contextId: 'ctx_123',
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
expect(mockClient.patterns.getBehaviorState).toHaveBeenCalledWith({
|
|
175
|
+
contextId: 'ctx_123',
|
|
176
|
+
});
|
|
177
|
+
expect(result.activePatterns).toHaveLength(2);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
describe('patterns set-behavior-state', () => {
|
|
182
|
+
it('should set behavioral state', async () => {
|
|
183
|
+
const state = { key: 'value' };
|
|
184
|
+
mockClient.patterns.setBehaviorState.mockResolvedValue({ success: true });
|
|
185
|
+
|
|
186
|
+
const result = await mockClient.patterns.setBehaviorState({
|
|
187
|
+
contextId: 'ctx_123',
|
|
188
|
+
state,
|
|
189
|
+
merge: false,
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
expect(mockClient.patterns.setBehaviorState).toHaveBeenCalledWith({
|
|
193
|
+
contextId: 'ctx_123',
|
|
194
|
+
state,
|
|
195
|
+
merge: false,
|
|
196
|
+
});
|
|
197
|
+
expect(result.success).toBe(true);
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
|