@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,320 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import {
|
|
5
|
+
listFacts,
|
|
6
|
+
getFactById,
|
|
7
|
+
createFact,
|
|
8
|
+
updateFact,
|
|
9
|
+
deleteFact,
|
|
10
|
+
searchFacts,
|
|
11
|
+
} from '@memnexus-ai/mx-typescript-sdk';
|
|
12
|
+
import { getApiOptions } from '../lib/api-client';
|
|
13
|
+
import { handleError } from '../lib/errors';
|
|
14
|
+
import { printOutput } from '../lib/formatters';
|
|
15
|
+
import { OutputFormat } from '../types';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Register semantic facts management commands
|
|
19
|
+
* @param program - Commander program instance
|
|
20
|
+
*/
|
|
21
|
+
export function registerFactsCommands(program: Command): void {
|
|
22
|
+
const facts = program.command('facts').description('Manage semantic facts');
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* mx facts list [options]
|
|
26
|
+
* List facts with pagination
|
|
27
|
+
*/
|
|
28
|
+
facts
|
|
29
|
+
.command('list')
|
|
30
|
+
.description('List facts')
|
|
31
|
+
.option('--page <number>', 'Page number', '0')
|
|
32
|
+
.option('--limit <number>', 'Results per page', '20')
|
|
33
|
+
.option('--format <format>', 'Output format (json|table|yaml)')
|
|
34
|
+
.action(async (options) => {
|
|
35
|
+
try {
|
|
36
|
+
const page = parseInt(options.page, 10);
|
|
37
|
+
const limit = parseInt(options.limit, 10);
|
|
38
|
+
const offset = page * limit;
|
|
39
|
+
|
|
40
|
+
const result = await listFacts({
|
|
41
|
+
...getApiOptions(),
|
|
42
|
+
query: { limit, offset },
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Format for table display
|
|
46
|
+
if (options.format === 'table' || !options.format) {
|
|
47
|
+
const tableData = (result.data?.data || []).map((f: any) => ({
|
|
48
|
+
id: f.id,
|
|
49
|
+
subject: f.subject?.substring(0, 20) + (f.subject?.length > 20 ? '...' : ''),
|
|
50
|
+
predicate: f.predicate,
|
|
51
|
+
object: f.object?.substring(0, 20) + (f.object?.length > 20 ? '...' : ''),
|
|
52
|
+
confidence: f.confidence?.toFixed(2) || 'N/A',
|
|
53
|
+
}));
|
|
54
|
+
|
|
55
|
+
printOutput(tableData, options.format as OutputFormat, {
|
|
56
|
+
columns: ['id', 'subject', 'predicate', 'object', 'confidence'],
|
|
57
|
+
maxColumnWidth: 25,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
console.log(
|
|
61
|
+
chalk.gray(
|
|
62
|
+
`\nShowing ${offset + 1}-${offset + (result.data?.data?.length || 0)} of ${
|
|
63
|
+
result.data?.count || 0
|
|
64
|
+
} (Page ${page + 1})`
|
|
65
|
+
)
|
|
66
|
+
);
|
|
67
|
+
} else {
|
|
68
|
+
printOutput(result.data, options.format as OutputFormat);
|
|
69
|
+
}
|
|
70
|
+
} catch (error) {
|
|
71
|
+
handleError(error);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* mx facts get <id>
|
|
77
|
+
* Get a specific fact by ID
|
|
78
|
+
*/
|
|
79
|
+
facts
|
|
80
|
+
.command('get <id>')
|
|
81
|
+
.description('Get a specific fact')
|
|
82
|
+
.option('--format <format>', 'Output format (json|table|yaml)')
|
|
83
|
+
.action(async (id: string, options) => {
|
|
84
|
+
try {
|
|
85
|
+
const result = await getFactById({
|
|
86
|
+
...getApiOptions(),
|
|
87
|
+
path: { id },
|
|
88
|
+
});
|
|
89
|
+
printOutput(result.data?.data, options.format as OutputFormat);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
handleError(error);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* mx facts create [options]
|
|
97
|
+
* Create a new fact
|
|
98
|
+
*/
|
|
99
|
+
facts
|
|
100
|
+
.command('create')
|
|
101
|
+
.description('Create a new fact')
|
|
102
|
+
.option('--subject <text>', 'Fact subject (entity name)')
|
|
103
|
+
.option('--predicate <text>', 'Relationship type')
|
|
104
|
+
.option('--object <text>', 'Fact object (related entity)')
|
|
105
|
+
.option('--confidence <number>', 'Confidence score (0-1)', '1.0')
|
|
106
|
+
.option('--memory-id <id>', 'Associated memory ID')
|
|
107
|
+
.option('--interactive', 'Interactive mode')
|
|
108
|
+
.option('--format <format>', 'Output format (json|table|yaml)')
|
|
109
|
+
.action(async (options) => {
|
|
110
|
+
try {
|
|
111
|
+
let factData: any = {};
|
|
112
|
+
|
|
113
|
+
if (options.interactive || !options.subject || !options.predicate || !options.object) {
|
|
114
|
+
// Interactive mode
|
|
115
|
+
const answers = await inquirer.prompt([
|
|
116
|
+
{
|
|
117
|
+
type: 'input',
|
|
118
|
+
name: 'subject',
|
|
119
|
+
message: 'Subject (entity name):',
|
|
120
|
+
default: options.subject,
|
|
121
|
+
validate: (input: string) => input.trim().length > 0 || 'Subject is required',
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
type: 'input',
|
|
125
|
+
name: 'predicate',
|
|
126
|
+
message: 'Predicate (relationship):',
|
|
127
|
+
default: options.predicate,
|
|
128
|
+
validate: (input: string) => input.trim().length > 0 || 'Predicate is required',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
type: 'input',
|
|
132
|
+
name: 'object',
|
|
133
|
+
message: 'Object (related entity):',
|
|
134
|
+
default: options.object,
|
|
135
|
+
validate: (input: string) => input.trim().length > 0 || 'Object is required',
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
type: 'number',
|
|
139
|
+
name: 'confidence',
|
|
140
|
+
message: 'Confidence (0-1):',
|
|
141
|
+
default: parseFloat(options.confidence) || 1.0,
|
|
142
|
+
validate: (input: number) => {
|
|
143
|
+
if (input < 0 || input > 1) return 'Confidence must be between 0 and 1';
|
|
144
|
+
return true;
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
type: 'input',
|
|
149
|
+
name: 'memoryId',
|
|
150
|
+
message: 'Memory ID (optional):',
|
|
151
|
+
default: options.memoryId,
|
|
152
|
+
},
|
|
153
|
+
]);
|
|
154
|
+
|
|
155
|
+
factData = {
|
|
156
|
+
subject: answers.subject,
|
|
157
|
+
predicate: answers.predicate,
|
|
158
|
+
object: answers.object,
|
|
159
|
+
confidence: answers.confidence,
|
|
160
|
+
memoryId: answers.memoryId || undefined,
|
|
161
|
+
};
|
|
162
|
+
} else {
|
|
163
|
+
// Direct mode
|
|
164
|
+
factData = {
|
|
165
|
+
subject: options.subject,
|
|
166
|
+
predicate: options.predicate,
|
|
167
|
+
object: options.object,
|
|
168
|
+
confidence: parseFloat(options.confidence),
|
|
169
|
+
memoryId: options.memoryId,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const result = await createFact({
|
|
174
|
+
...getApiOptions(),
|
|
175
|
+
body: factData,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const fact = result.data?.data;
|
|
179
|
+
console.log(chalk.green(`✓ Fact created with ID: ${fact?.id}`));
|
|
180
|
+
printOutput(fact, options.format as OutputFormat);
|
|
181
|
+
} catch (error) {
|
|
182
|
+
handleError(error);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* mx facts update <id> [options]
|
|
188
|
+
* Update an existing fact
|
|
189
|
+
*/
|
|
190
|
+
facts
|
|
191
|
+
.command('update <id>')
|
|
192
|
+
.description('Update an existing fact')
|
|
193
|
+
.option('--subject <text>', 'Updated subject')
|
|
194
|
+
.option('--predicate <text>', 'Updated predicate')
|
|
195
|
+
.option('--object <text>', 'Updated object')
|
|
196
|
+
.option('--confidence <number>', 'Updated confidence (0-1)')
|
|
197
|
+
.option('--format <format>', 'Output format (json|table|yaml)')
|
|
198
|
+
.action(async (id: string, options) => {
|
|
199
|
+
try {
|
|
200
|
+
const updates: any = {};
|
|
201
|
+
|
|
202
|
+
if (options.subject) updates.subject = options.subject;
|
|
203
|
+
if (options.predicate) updates.predicate = options.predicate;
|
|
204
|
+
if (options.object) updates.object = options.object;
|
|
205
|
+
if (options.confidence) {
|
|
206
|
+
const conf = parseFloat(options.confidence);
|
|
207
|
+
if (conf < 0 || conf > 1) {
|
|
208
|
+
console.log(chalk.red('Error: Confidence must be between 0 and 1'));
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
updates.confidence = conf;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (Object.keys(updates).length === 0) {
|
|
215
|
+
console.log(chalk.yellow('No updates provided. Use --help to see available options.'));
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const result = await updateFact({
|
|
220
|
+
...getApiOptions(),
|
|
221
|
+
path: { id },
|
|
222
|
+
body: updates,
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
const fact = result.data?.data;
|
|
226
|
+
console.log(chalk.green(`✓ Fact ${id} updated successfully`));
|
|
227
|
+
printOutput(fact, options.format as OutputFormat);
|
|
228
|
+
} catch (error) {
|
|
229
|
+
handleError(error);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* mx facts delete <id>
|
|
235
|
+
* Delete a fact
|
|
236
|
+
*/
|
|
237
|
+
facts
|
|
238
|
+
.command('delete <id>')
|
|
239
|
+
.description('Delete a fact')
|
|
240
|
+
.option('--force', 'Skip confirmation prompt')
|
|
241
|
+
.action(async (id: string, options) => {
|
|
242
|
+
try {
|
|
243
|
+
if (!options.force) {
|
|
244
|
+
const answers = await inquirer.prompt([
|
|
245
|
+
{
|
|
246
|
+
type: 'confirm',
|
|
247
|
+
name: 'confirm',
|
|
248
|
+
message: `Are you sure you want to delete fact ${id}?`,
|
|
249
|
+
default: false,
|
|
250
|
+
},
|
|
251
|
+
]);
|
|
252
|
+
|
|
253
|
+
if (!answers.confirm) {
|
|
254
|
+
console.log(chalk.yellow('Delete cancelled'));
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
await deleteFact({
|
|
260
|
+
...getApiOptions(),
|
|
261
|
+
path: { id },
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
console.log(chalk.green(`✓ Fact ${id} deleted successfully`));
|
|
265
|
+
} catch (error) {
|
|
266
|
+
handleError(error);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* mx facts search [options]
|
|
272
|
+
* Search facts
|
|
273
|
+
*/
|
|
274
|
+
facts
|
|
275
|
+
.command('search')
|
|
276
|
+
.description('Search facts')
|
|
277
|
+
.option('--query <text>', 'Search query')
|
|
278
|
+
.option('--limit <number>', 'Maximum results', '20')
|
|
279
|
+
.option('--format <format>', 'Output format (json|table|yaml)')
|
|
280
|
+
.action(async (options) => {
|
|
281
|
+
try {
|
|
282
|
+
if (!options.query) {
|
|
283
|
+
console.log(chalk.red('Error: --query is required'));
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const result = await searchFacts({
|
|
288
|
+
...getApiOptions(),
|
|
289
|
+
body: {
|
|
290
|
+
query: options.query,
|
|
291
|
+
limit: parseInt(options.limit, 10),
|
|
292
|
+
},
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
const searchData = result.data;
|
|
296
|
+
|
|
297
|
+
// Format for table display
|
|
298
|
+
if (options.format === 'table' || !options.format) {
|
|
299
|
+
const tableData = (searchData?.data || []).map((f: any) => ({
|
|
300
|
+
id: f.id || 'N/A',
|
|
301
|
+
subject: f.subject?.substring(0, 20) + (f.subject?.length > 20 ? '...' : ''),
|
|
302
|
+
predicate: f.predicate,
|
|
303
|
+
object: f.object?.substring(0, 20) + (f.object?.length > 20 ? '...' : ''),
|
|
304
|
+
confidence: f.confidence?.toFixed(2) || 'N/A',
|
|
305
|
+
}));
|
|
306
|
+
|
|
307
|
+
printOutput(tableData, options.format as OutputFormat, {
|
|
308
|
+
columns: ['id', 'subject', 'predicate', 'object', 'confidence'],
|
|
309
|
+
maxColumnWidth: 25,
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
console.log(chalk.gray(`\nFound ${searchData?.count || 0} results`));
|
|
313
|
+
} else {
|
|
314
|
+
printOutput(searchData, options.format as OutputFormat);
|
|
315
|
+
}
|
|
316
|
+
} catch (error) {
|
|
317
|
+
handleError(error);
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
import {
|
|
5
|
+
executeGraphRagQuery,
|
|
6
|
+
explainGraphRagQuery,
|
|
7
|
+
queryCommunities,
|
|
8
|
+
} from '@memnexus-ai/mx-typescript-sdk';
|
|
9
|
+
import { getApiOptions } from '../lib/api-client';
|
|
10
|
+
import { handleError } from '../lib/errors';
|
|
11
|
+
import { printOutput } from '../lib/formatters';
|
|
12
|
+
import { OutputFormat } from '../types';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Register GraphRAG query commands
|
|
16
|
+
* @param program - Commander program instance
|
|
17
|
+
*/
|
|
18
|
+
export function registerGraphragCommands(program: Command): void {
|
|
19
|
+
const graphrag = program.command('graphrag').description('Execute GraphRAG queries');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* mx graphrag query [options]
|
|
23
|
+
* Execute a GraphRAG query
|
|
24
|
+
*/
|
|
25
|
+
graphrag
|
|
26
|
+
.command('query')
|
|
27
|
+
.description('Execute GraphRAG query')
|
|
28
|
+
.option('--query <text>', 'Query text (required)')
|
|
29
|
+
.option('--context-id <id>', 'Context ID')
|
|
30
|
+
.option('--mode <mode>', 'Query mode (local|global|hybrid)', 'hybrid')
|
|
31
|
+
.option('--max-depth <number>', 'Graph traversal depth', '3')
|
|
32
|
+
.option('--limit <number>', 'Max results', '20')
|
|
33
|
+
.option('--format <format>', 'Output format (json|table|yaml)')
|
|
34
|
+
.action(async (options) => {
|
|
35
|
+
try {
|
|
36
|
+
if (!options.query) {
|
|
37
|
+
console.log(chalk.red('Error: --query is required'));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const spinner = ora('Executing GraphRAG query...').start();
|
|
42
|
+
|
|
43
|
+
const result = await executeGraphRagQuery({
|
|
44
|
+
...getApiOptions(),
|
|
45
|
+
body: {
|
|
46
|
+
query: options.query,
|
|
47
|
+
maxDepth: parseInt(options.maxDepth, 10),
|
|
48
|
+
limit: parseInt(options.limit, 10),
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
spinner.succeed('Query executed successfully');
|
|
53
|
+
|
|
54
|
+
const responseData = result.data as any;
|
|
55
|
+
if (options.format === 'table' || !options.format) {
|
|
56
|
+
const tableData = (responseData?.data || []).map((r: any) => ({
|
|
57
|
+
id: r.id,
|
|
58
|
+
answer: r.answer?.substring(0, 50) + (r.answer?.length > 50 ? '...' : ''),
|
|
59
|
+
sources: r.sources?.length || 0,
|
|
60
|
+
confidence: r.confidence || 0,
|
|
61
|
+
}));
|
|
62
|
+
|
|
63
|
+
printOutput(tableData, options.format as OutputFormat, {
|
|
64
|
+
columns: ['id', 'answer', 'sources', 'confidence'],
|
|
65
|
+
maxColumnWidth: 25,
|
|
66
|
+
});
|
|
67
|
+
} else {
|
|
68
|
+
printOutput(responseData, options.format as OutputFormat);
|
|
69
|
+
}
|
|
70
|
+
} catch (error) {
|
|
71
|
+
handleError(error);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* mx graphrag explain <result-id>
|
|
77
|
+
* Explain a query result
|
|
78
|
+
*/
|
|
79
|
+
graphrag
|
|
80
|
+
.command('explain <result-id>')
|
|
81
|
+
.description('Explain query result')
|
|
82
|
+
.option('--format <format>', 'Output format (json|table|yaml)')
|
|
83
|
+
.action(async (resultId: string, options) => {
|
|
84
|
+
try {
|
|
85
|
+
const spinner = ora('Generating explanation...').start();
|
|
86
|
+
|
|
87
|
+
const result = await explainGraphRagQuery({
|
|
88
|
+
...getApiOptions(),
|
|
89
|
+
query: { queryId: resultId },
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
spinner.succeed('Explanation generated');
|
|
93
|
+
printOutput(result.data, options.format as OutputFormat);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
handleError(error);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* mx graphrag query-communities [options]
|
|
101
|
+
* Query at community level
|
|
102
|
+
*/
|
|
103
|
+
graphrag
|
|
104
|
+
.command('query-communities')
|
|
105
|
+
.description('Query communities')
|
|
106
|
+
.option('--query <text>', 'Query text (required)')
|
|
107
|
+
.option('--context-id <id>', 'Context ID')
|
|
108
|
+
.option('--limit <number>', 'Max communities', '10')
|
|
109
|
+
.option('--format <format>', 'Output format (json|table|yaml)')
|
|
110
|
+
.action(async (options) => {
|
|
111
|
+
try {
|
|
112
|
+
if (!options.query) {
|
|
113
|
+
console.log(chalk.red('Error: --query is required'));
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const spinner = ora('Querying communities...').start();
|
|
118
|
+
|
|
119
|
+
const result = await queryCommunities({
|
|
120
|
+
...getApiOptions(),
|
|
121
|
+
body: {
|
|
122
|
+
query: options.query,
|
|
123
|
+
limit: parseInt(options.limit, 10),
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
spinner.succeed('Community query completed');
|
|
128
|
+
|
|
129
|
+
const responseData = result.data as any;
|
|
130
|
+
if (options.format === 'table' || !options.format) {
|
|
131
|
+
const tableData = (responseData?.data || []).map((c: any) => ({
|
|
132
|
+
communityId: c.communityId,
|
|
133
|
+
communityName: c.communityName || 'N/A',
|
|
134
|
+
answer: c.answer?.substring(0, 40) + (c.answer?.length > 40 ? '...' : ''),
|
|
135
|
+
confidence: c.confidence || 0,
|
|
136
|
+
}));
|
|
137
|
+
|
|
138
|
+
printOutput(tableData, options.format as OutputFormat, {
|
|
139
|
+
columns: ['communityId', 'communityName', 'answer', 'confidence'],
|
|
140
|
+
maxColumnWidth: 20,
|
|
141
|
+
});
|
|
142
|
+
} else {
|
|
143
|
+
printOutput(responseData, options.format as OutputFormat);
|
|
144
|
+
}
|
|
145
|
+
} catch (error) {
|
|
146
|
+
handleError(error);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|