@chinjinyu/mcp-knowledge-graph-plus 0.1.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/README.md +700 -0
- package/dist/application/services/FactService.d.ts +16 -0
- package/dist/application/services/FactService.d.ts.map +1 -0
- package/dist/application/services/FactService.js +50 -0
- package/dist/application/services/FactService.js.map +1 -0
- package/dist/application/services/KnowledgeGraphService.d.ts +33 -0
- package/dist/application/services/KnowledgeGraphService.d.ts.map +1 -0
- package/dist/application/services/KnowledgeGraphService.js +271 -0
- package/dist/application/services/KnowledgeGraphService.js.map +1 -0
- package/dist/application/services/LinkService.d.ts +17 -0
- package/dist/application/services/LinkService.d.ts.map +1 -0
- package/dist/application/services/LinkService.js +53 -0
- package/dist/application/services/LinkService.js.map +1 -0
- package/dist/application/services/NodeService.d.ts +31 -0
- package/dist/application/services/NodeService.d.ts.map +1 -0
- package/dist/application/services/NodeService.js +69 -0
- package/dist/application/services/NodeService.js.map +1 -0
- package/dist/core/config/index.d.ts +34 -0
- package/dist/core/config/index.d.ts.map +1 -0
- package/dist/core/config/index.js +60 -0
- package/dist/core/config/index.js.map +1 -0
- package/dist/core/errors/index.d.ts +70 -0
- package/dist/core/errors/index.d.ts.map +1 -0
- package/dist/core/errors/index.js +120 -0
- package/dist/core/errors/index.js.map +1 -0
- package/dist/core/types/index.d.ts +119 -0
- package/dist/core/types/index.d.ts.map +1 -0
- package/dist/core/types/index.js +5 -0
- package/dist/core/types/index.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +117 -0
- package/dist/index.js.map +1 -0
- package/dist/infrastructure/database/DatabaseManager.d.ts +13 -0
- package/dist/infrastructure/database/DatabaseManager.d.ts.map +1 -0
- package/dist/infrastructure/database/DatabaseManager.js +101 -0
- package/dist/infrastructure/database/DatabaseManager.js.map +1 -0
- package/dist/infrastructure/di/Container.d.ts +21 -0
- package/dist/infrastructure/di/Container.d.ts.map +1 -0
- package/dist/infrastructure/di/Container.js +45 -0
- package/dist/infrastructure/di/Container.js.map +1 -0
- package/dist/infrastructure/repositories/BaseRepository.d.ts +23 -0
- package/dist/infrastructure/repositories/BaseRepository.d.ts.map +1 -0
- package/dist/infrastructure/repositories/BaseRepository.js +84 -0
- package/dist/infrastructure/repositories/BaseRepository.js.map +1 -0
- package/dist/infrastructure/repositories/FactRepository.d.ts +28 -0
- package/dist/infrastructure/repositories/FactRepository.d.ts.map +1 -0
- package/dist/infrastructure/repositories/FactRepository.js +101 -0
- package/dist/infrastructure/repositories/FactRepository.js.map +1 -0
- package/dist/infrastructure/repositories/LinkRepository.d.ts +28 -0
- package/dist/infrastructure/repositories/LinkRepository.d.ts.map +1 -0
- package/dist/infrastructure/repositories/LinkRepository.js +107 -0
- package/dist/infrastructure/repositories/LinkRepository.js.map +1 -0
- package/dist/infrastructure/repositories/NodeRepository.d.ts +28 -0
- package/dist/infrastructure/repositories/NodeRepository.d.ts.map +1 -0
- package/dist/infrastructure/repositories/NodeRepository.js +143 -0
- package/dist/infrastructure/repositories/NodeRepository.js.map +1 -0
- package/dist/interfaces/mcp/commands/BaseCommand.d.ts +55 -0
- package/dist/interfaces/mcp/commands/BaseCommand.d.ts.map +1 -0
- package/dist/interfaces/mcp/commands/BaseCommand.js +42 -0
- package/dist/interfaces/mcp/commands/BaseCommand.js.map +1 -0
- package/dist/interfaces/mcp/commands/FactAddCommand.d.ts +42 -0
- package/dist/interfaces/mcp/commands/FactAddCommand.d.ts.map +1 -0
- package/dist/interfaces/mcp/commands/FactAddCommand.js +73 -0
- package/dist/interfaces/mcp/commands/FactAddCommand.js.map +1 -0
- package/dist/interfaces/mcp/commands/FactDelCommand.d.ts +42 -0
- package/dist/interfaces/mcp/commands/FactDelCommand.d.ts.map +1 -0
- package/dist/interfaces/mcp/commands/FactDelCommand.js +68 -0
- package/dist/interfaces/mcp/commands/FactDelCommand.js.map +1 -0
- package/dist/interfaces/mcp/commands/FactEditCommand.d.ts +43 -0
- package/dist/interfaces/mcp/commands/FactEditCommand.d.ts.map +1 -0
- package/dist/interfaces/mcp/commands/FactEditCommand.js +68 -0
- package/dist/interfaces/mcp/commands/FactEditCommand.js.map +1 -0
- package/dist/interfaces/mcp/commands/LinkAddCommand.d.ts +43 -0
- package/dist/interfaces/mcp/commands/LinkAddCommand.d.ts.map +1 -0
- package/dist/interfaces/mcp/commands/LinkAddCommand.js +63 -0
- package/dist/interfaces/mcp/commands/LinkAddCommand.js.map +1 -0
- package/dist/interfaces/mcp/commands/LinkDelCommand.d.ts +43 -0
- package/dist/interfaces/mcp/commands/LinkDelCommand.d.ts.map +1 -0
- package/dist/interfaces/mcp/commands/LinkDelCommand.js +65 -0
- package/dist/interfaces/mcp/commands/LinkDelCommand.js.map +1 -0
- package/dist/interfaces/mcp/commands/LinkEditCommand.d.ts +47 -0
- package/dist/interfaces/mcp/commands/LinkEditCommand.d.ts.map +1 -0
- package/dist/interfaces/mcp/commands/LinkEditCommand.js +75 -0
- package/dist/interfaces/mcp/commands/LinkEditCommand.js.map +1 -0
- package/dist/interfaces/mcp/commands/ListCommand.d.ts +33 -0
- package/dist/interfaces/mcp/commands/ListCommand.d.ts.map +1 -0
- package/dist/interfaces/mcp/commands/ListCommand.js +57 -0
- package/dist/interfaces/mcp/commands/ListCommand.js.map +1 -0
- package/dist/interfaces/mcp/commands/NodeAddCommand.d.ts +46 -0
- package/dist/interfaces/mcp/commands/NodeAddCommand.d.ts.map +1 -0
- package/dist/interfaces/mcp/commands/NodeAddCommand.js +67 -0
- package/dist/interfaces/mcp/commands/NodeAddCommand.js.map +1 -0
- package/dist/interfaces/mcp/commands/NodeDelCommand.d.ts +32 -0
- package/dist/interfaces/mcp/commands/NodeDelCommand.d.ts.map +1 -0
- package/dist/interfaces/mcp/commands/NodeDelCommand.js +63 -0
- package/dist/interfaces/mcp/commands/NodeDelCommand.js.map +1 -0
- package/dist/interfaces/mcp/commands/NodeEditCommand.d.ts +43 -0
- package/dist/interfaces/mcp/commands/NodeEditCommand.d.ts.map +1 -0
- package/dist/interfaces/mcp/commands/NodeEditCommand.js +63 -0
- package/dist/interfaces/mcp/commands/NodeEditCommand.js.map +1 -0
- package/dist/interfaces/mcp/commands/NodeGetCommand.d.ts +40 -0
- package/dist/interfaces/mcp/commands/NodeGetCommand.d.ts.map +1 -0
- package/dist/interfaces/mcp/commands/NodeGetCommand.js +72 -0
- package/dist/interfaces/mcp/commands/NodeGetCommand.js.map +1 -0
- package/dist/interfaces/mcp/commands/SearchCommand.d.ts +53 -0
- package/dist/interfaces/mcp/commands/SearchCommand.d.ts.map +1 -0
- package/dist/interfaces/mcp/commands/SearchCommand.js +91 -0
- package/dist/interfaces/mcp/commands/SearchCommand.js.map +1 -0
- package/package.json +10 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node Repository - handles entity table operations
|
|
3
|
+
*/
|
|
4
|
+
import { NodeAlreadyExistsError, DatabaseError } from '../../core/errors/index.js';
|
|
5
|
+
import { BaseRepository } from './BaseRepository.js';
|
|
6
|
+
export class NodeRepository extends BaseRepository {
|
|
7
|
+
constructor(db) {
|
|
8
|
+
super(db);
|
|
9
|
+
}
|
|
10
|
+
getTableName() {
|
|
11
|
+
return 'entities';
|
|
12
|
+
}
|
|
13
|
+
rowToEntity(row) {
|
|
14
|
+
return {
|
|
15
|
+
id: row.id,
|
|
16
|
+
name: row.name,
|
|
17
|
+
type: row.entity_type,
|
|
18
|
+
createdAt: row.created_at,
|
|
19
|
+
updatedAt: row.updated_at,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
async findById(id) {
|
|
23
|
+
const row = await this.get('SELECT * FROM entities WHERE id = ?', [id]);
|
|
24
|
+
return row ? this.rowToEntity(row) : null;
|
|
25
|
+
}
|
|
26
|
+
async findByName(name) {
|
|
27
|
+
const row = await this.get('SELECT * FROM entities WHERE name = ?', [name]);
|
|
28
|
+
return row ? this.rowToEntity(row) : null;
|
|
29
|
+
}
|
|
30
|
+
async findManyByNames(names) {
|
|
31
|
+
if (names.length === 0)
|
|
32
|
+
return [];
|
|
33
|
+
const placeholders = names.map(() => '?').join(',');
|
|
34
|
+
const rows = await this.all(`SELECT * FROM entities WHERE name IN (${placeholders}) ORDER BY id`, names);
|
|
35
|
+
return rows.map(row => this.rowToEntity(row));
|
|
36
|
+
}
|
|
37
|
+
async findMany(ids) {
|
|
38
|
+
if (ids.length === 0)
|
|
39
|
+
return [];
|
|
40
|
+
const placeholders = ids.map(() => '?').join(',');
|
|
41
|
+
const rows = await this.all(`SELECT * FROM entities WHERE id IN (${placeholders}) ORDER BY id`, ids);
|
|
42
|
+
return rows.map(row => this.rowToEntity(row));
|
|
43
|
+
}
|
|
44
|
+
async findAll() {
|
|
45
|
+
const rows = await this.all('SELECT * FROM entities ORDER BY id');
|
|
46
|
+
return rows.map(row => this.rowToEntity(row));
|
|
47
|
+
}
|
|
48
|
+
async findAllWithPagination(page, pageSize) {
|
|
49
|
+
const offset = (page - 1) * pageSize;
|
|
50
|
+
const countRow = await this.get('SELECT COUNT(*) as count FROM entities');
|
|
51
|
+
const total = countRow?.count ?? 0;
|
|
52
|
+
const rows = await this.all('SELECT * FROM entities ORDER BY id LIMIT ? OFFSET ?', [pageSize, offset]);
|
|
53
|
+
return { nodes: rows.map(row => this.rowToEntity(row)), total };
|
|
54
|
+
}
|
|
55
|
+
async create(input) {
|
|
56
|
+
const now = new Date().toISOString();
|
|
57
|
+
try {
|
|
58
|
+
const result = await this.run('INSERT INTO entities (name, entity_type, created_at, updated_at) VALUES (?, ?, ?, ?)', [input.name, input.type, now, now]);
|
|
59
|
+
const node = await this.findById(result.lastID);
|
|
60
|
+
if (!node)
|
|
61
|
+
throw new DatabaseError('Failed to create node');
|
|
62
|
+
return node;
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
if (this.isUniqueConstraintError(error))
|
|
66
|
+
throw new NodeAlreadyExistsError(input.name);
|
|
67
|
+
throw new DatabaseError('Failed to create node', error);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async createMany(inputs) {
|
|
71
|
+
if (inputs.length === 0)
|
|
72
|
+
return [];
|
|
73
|
+
const nodes = [];
|
|
74
|
+
await this.transaction(async () => {
|
|
75
|
+
for (const input of inputs) {
|
|
76
|
+
try {
|
|
77
|
+
const now = new Date().toISOString();
|
|
78
|
+
const result = await this.run('INSERT OR IGNORE INTO entities (name, entity_type, created_at, updated_at) VALUES (?, ?, ?, ?)', [input.name, input.type, now, now]);
|
|
79
|
+
if (result.changes > 0) {
|
|
80
|
+
const node = await this.findById(result.lastID);
|
|
81
|
+
if (node)
|
|
82
|
+
nodes.push(node);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
if (!this.isUniqueConstraintError(error))
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
return nodes;
|
|
92
|
+
}
|
|
93
|
+
async update(input) {
|
|
94
|
+
const existingNode = await this.findByName(input.nodeName);
|
|
95
|
+
if (!existingNode)
|
|
96
|
+
return null;
|
|
97
|
+
const updates = [];
|
|
98
|
+
const params = [];
|
|
99
|
+
if (input.newName !== undefined) {
|
|
100
|
+
updates.push('name = ?');
|
|
101
|
+
params.push(input.newName);
|
|
102
|
+
}
|
|
103
|
+
if (input.newType !== undefined) {
|
|
104
|
+
updates.push('entity_type = ?');
|
|
105
|
+
params.push(input.newType);
|
|
106
|
+
}
|
|
107
|
+
if (updates.length === 0)
|
|
108
|
+
return existingNode;
|
|
109
|
+
updates.push('updated_at = ?');
|
|
110
|
+
params.push(new Date().toISOString());
|
|
111
|
+
params.push(existingNode.id);
|
|
112
|
+
const sql = `UPDATE entities SET ${updates.join(', ')} WHERE id = ?`;
|
|
113
|
+
try {
|
|
114
|
+
await this.run(sql, params);
|
|
115
|
+
return await this.findById(existingNode.id);
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
if (this.isUniqueConstraintError(error) && input.newName !== undefined) {
|
|
119
|
+
throw new NodeAlreadyExistsError(input.newName);
|
|
120
|
+
}
|
|
121
|
+
throw new DatabaseError('Failed to update node', error);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async delete(id) {
|
|
125
|
+
await this.run('DELETE FROM entities WHERE id = ?', [id]);
|
|
126
|
+
}
|
|
127
|
+
async deleteByNames(names) {
|
|
128
|
+
if (names.length === 0)
|
|
129
|
+
return 0;
|
|
130
|
+
const placeholders = names.map(() => '?').join(',');
|
|
131
|
+
const result = await this.run(`DELETE FROM entities WHERE name IN (${placeholders})`, names);
|
|
132
|
+
return result.changes;
|
|
133
|
+
}
|
|
134
|
+
async count() {
|
|
135
|
+
const row = await this.get('SELECT COUNT(*) as count FROM entities');
|
|
136
|
+
return row?.count ?? 0;
|
|
137
|
+
}
|
|
138
|
+
async existsByName(name) {
|
|
139
|
+
const row = await this.get('SELECT 1 FROM entities WHERE name = ? LIMIT 1', [name]);
|
|
140
|
+
return row !== undefined;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=NodeRepository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NodeRepository.js","sourceRoot":"","sources":["../../../src/infrastructure/repositories/NodeRepository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Command Interface
|
|
3
|
+
*/
|
|
4
|
+
export interface Command<TInput, TOutput> {
|
|
5
|
+
readonly name: string;
|
|
6
|
+
readonly description: string;
|
|
7
|
+
readonly inputSchema: Record<string, unknown>;
|
|
8
|
+
execute(input: TInput): Promise<{
|
|
9
|
+
content: Array<{
|
|
10
|
+
type: 'text';
|
|
11
|
+
text: string;
|
|
12
|
+
}>;
|
|
13
|
+
isError?: boolean;
|
|
14
|
+
}>;
|
|
15
|
+
}
|
|
16
|
+
export declare abstract class BaseCommand<TInput, TOutput> implements Command<TInput, TOutput> {
|
|
17
|
+
abstract readonly name: string;
|
|
18
|
+
abstract readonly description: string;
|
|
19
|
+
abstract readonly inputSchema: Record<string, unknown>;
|
|
20
|
+
abstract execute(input: TInput): Promise<{
|
|
21
|
+
content: Array<{
|
|
22
|
+
type: 'text';
|
|
23
|
+
text: string;
|
|
24
|
+
}>;
|
|
25
|
+
isError?: boolean;
|
|
26
|
+
}>;
|
|
27
|
+
/**
|
|
28
|
+
* Validate that a parameter is an array
|
|
29
|
+
* @param value - The value to validate
|
|
30
|
+
* @param paramName - Parameter name for error message
|
|
31
|
+
* @param options - Optional validation options
|
|
32
|
+
* @param options.description - Description of what the parameter should contain
|
|
33
|
+
* @param options.example - Example of correct usage
|
|
34
|
+
* @throws ValidationError if value is not an array
|
|
35
|
+
*/
|
|
36
|
+
protected validateArray(value: unknown, paramName: string, options?: {
|
|
37
|
+
description?: string;
|
|
38
|
+
example?: string;
|
|
39
|
+
}): void;
|
|
40
|
+
/**
|
|
41
|
+
* Validate that a nested field in each object of an array is itself an array
|
|
42
|
+
* @param items - Array of objects to validate
|
|
43
|
+
* @param objectName - Name of the object array parameter
|
|
44
|
+
* @param fieldName - Name of the nested field to check
|
|
45
|
+
* @param options - Optional validation options
|
|
46
|
+
* @param options.description - Description of what the parameter should contain
|
|
47
|
+
* @param options.example - Example of correct usage
|
|
48
|
+
* @throws ValidationError if any nested field is not an array
|
|
49
|
+
*/
|
|
50
|
+
protected validateNestedArray(items: unknown, objectName: string, fieldName: string, options?: {
|
|
51
|
+
description?: string;
|
|
52
|
+
example?: string;
|
|
53
|
+
}): void;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=BaseCommand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseCommand.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/mcp/commands/BaseCommand.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,OAAO,CAAC,MAAM,EAAE,OAAO;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9C,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACxG;AAOD,8BAAsB,WAAW,CAAC,MAAM,EAAE,OAAO,CAAE,YAAW,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC;IACpF,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvD,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAE/G;;;;;;;;OAQG;IACH,SAAS,CAAC,aAAa,CACrB,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GACnD,IAAI;IAYP;;;;;;;;;OASG;IACH,SAAS,CAAC,mBAAmB,CAC3B,KAAK,EAAE,OAAO,EACd,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GACnD,IAAI;CAiBR"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Command class with common validation utilities
|
|
3
|
+
*/
|
|
4
|
+
import { ValidationError } from '../../../core/errors/index.js';
|
|
5
|
+
export class BaseCommand {
|
|
6
|
+
/**
|
|
7
|
+
* Validate that a parameter is an array
|
|
8
|
+
* @param value - The value to validate
|
|
9
|
+
* @param paramName - Parameter name for error message
|
|
10
|
+
* @param options - Optional validation options
|
|
11
|
+
* @param options.description - Description of what the parameter should contain
|
|
12
|
+
* @param options.example - Example of correct usage
|
|
13
|
+
* @throws ValidationError if value is not an array
|
|
14
|
+
*/
|
|
15
|
+
validateArray(value, paramName, options) {
|
|
16
|
+
if (!Array.isArray(value)) {
|
|
17
|
+
throw ValidationError.forField(paramName, value, `must be an array, but received ${typeof value}`, options?.description, options?.example);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Validate that a nested field in each object of an array is itself an array
|
|
22
|
+
* @param items - Array of objects to validate
|
|
23
|
+
* @param objectName - Name of the object array parameter
|
|
24
|
+
* @param fieldName - Name of the nested field to check
|
|
25
|
+
* @param options - Optional validation options
|
|
26
|
+
* @param options.description - Description of what the parameter should contain
|
|
27
|
+
* @param options.example - Example of correct usage
|
|
28
|
+
* @throws ValidationError if any nested field is not an array
|
|
29
|
+
*/
|
|
30
|
+
validateNestedArray(items, objectName, fieldName, options) {
|
|
31
|
+
if (!Array.isArray(items))
|
|
32
|
+
return;
|
|
33
|
+
for (let i = 0; i < items.length; i++) {
|
|
34
|
+
const item = items[i];
|
|
35
|
+
const fieldValue = item[fieldName];
|
|
36
|
+
if (fieldValue !== undefined && !Array.isArray(fieldValue)) {
|
|
37
|
+
throw ValidationError.forField(`${objectName}[${i}].${fieldName}`, fieldValue, `must be an array, but received ${typeof fieldValue}`, options?.description, options?.example);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=BaseCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseCommand.js","sourceRoot":"","sources":["../../../../src/interfaces/mcp/commands/BaseCommand.ts"],"names":[],"mappings":"AAUA;;GAEG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,MAAM,OAAgB,WAAW;IAM/B;;;;;;;;OAQG;IACO,aAAa,CACrB,KAAc,EACd,SAAiB,EACjB,OAAoD;QAEpD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,eAAe,CAAC,QAAQ,CAC5B,SAAS,EACT,KAAK,EACL,kCAAkC,OAAO,KAAK,EAAE,EAChD,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,OAAO,CACjB,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;;;;;;OASG;IACO,mBAAmB,CAC3B,KAAc,EACd,UAAkB,EAClB,SAAiB,EACjB,OAAoD;QAEpD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,OAAO;QAElC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAA4B,CAAC;YACjD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;YACnC,IAAI,UAAU,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC3D,MAAM,eAAe,CAAC,QAAQ,CAC5B,GAAG,UAAU,IAAI,CAAC,KAAK,SAAS,EAAE,EAClC,UAAU,EACV,kCAAkC,OAAO,UAAU,EAAE,EACrD,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,OAAO,CACjB,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { BaseCommand } from './BaseCommand.js';
|
|
2
|
+
import type { FactService } from '../../../application/services/FactService.js';
|
|
3
|
+
export declare class FactAddCommand extends BaseCommand<any, any> {
|
|
4
|
+
private readonly factService;
|
|
5
|
+
readonly name = "kg_fact_add";
|
|
6
|
+
readonly description = "Add facts to existing nodes. The node must exist; non-existent nodes are silently skipped. Duplicate facts can be added.\n\nExamples:\n1. Add a single fact to a node:\n { \"facts\": [{ \"node\": \"Alice\", \"contents\": [\"Expert in Python\"] }] }\n\n2. Add multiple facts to a node:\n { \"facts\": [{ \"node\": \"TechCorp\", \"contents\": [\"Founded in 2010\", \"500+ employees\", \"Headquarters in Seattle\"] }] }\n\n3. Add facts to multiple nodes:\n { \"facts\": [{ \"node\": \"Alice\", \"contents\": [\"AWS certified\"] }, { \"node\": \"Bob\", \"contents\": [\"MBA degree\"] }] }";
|
|
7
|
+
readonly inputSchema: {
|
|
8
|
+
type: string;
|
|
9
|
+
properties: {
|
|
10
|
+
facts: {
|
|
11
|
+
type: string;
|
|
12
|
+
description: string;
|
|
13
|
+
items: {
|
|
14
|
+
type: string;
|
|
15
|
+
properties: {
|
|
16
|
+
node: {
|
|
17
|
+
type: string;
|
|
18
|
+
description: string;
|
|
19
|
+
};
|
|
20
|
+
contents: {
|
|
21
|
+
type: string;
|
|
22
|
+
items: {
|
|
23
|
+
type: string;
|
|
24
|
+
};
|
|
25
|
+
description: string;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
required: string[];
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
required: string[];
|
|
33
|
+
};
|
|
34
|
+
constructor(factService: FactService);
|
|
35
|
+
execute(input: any): Promise<{
|
|
36
|
+
content: Array<{
|
|
37
|
+
type: 'text';
|
|
38
|
+
text: string;
|
|
39
|
+
}>;
|
|
40
|
+
}>;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=FactAddCommand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FactAddCommand.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/mcp/commands/FactAddCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8CAA8C,CAAC;AAEhF,qBAAa,cAAe,SAAQ,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC;IAgC3C,OAAO,CAAC,QAAQ,CAAC,WAAW;IA/BxC,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,WAAW,mlBAU+F;IACnH,QAAQ,CAAC,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;MAiBlB;gBAE2B,WAAW,EAAE,WAAW;IAI/C,OAAO,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC;CAuCvF"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { BaseCommand } from './BaseCommand.js';
|
|
2
|
+
export class FactAddCommand extends BaseCommand {
|
|
3
|
+
factService;
|
|
4
|
+
name = 'kg_fact_add';
|
|
5
|
+
description = `Add facts to existing nodes. The node must exist; non-existent nodes are silently skipped. Duplicate facts can be added.
|
|
6
|
+
|
|
7
|
+
Examples:
|
|
8
|
+
1. Add a single fact to a node:
|
|
9
|
+
{ "facts": [{ "node": "Alice", "contents": ["Expert in Python"] }] }
|
|
10
|
+
|
|
11
|
+
2. Add multiple facts to a node:
|
|
12
|
+
{ "facts": [{ "node": "TechCorp", "contents": ["Founded in 2010", "500+ employees", "Headquarters in Seattle"] }] }
|
|
13
|
+
|
|
14
|
+
3. Add facts to multiple nodes:
|
|
15
|
+
{ "facts": [{ "node": "Alice", "contents": ["AWS certified"] }, { "node": "Bob", "contents": ["MBA degree"] }] }`;
|
|
16
|
+
inputSchema = {
|
|
17
|
+
type: 'object',
|
|
18
|
+
properties: {
|
|
19
|
+
facts: {
|
|
20
|
+
type: 'array',
|
|
21
|
+
description: 'Array of facts to add. Each item specifies a node name and an array of fact contents.',
|
|
22
|
+
items: {
|
|
23
|
+
type: 'object',
|
|
24
|
+
properties: {
|
|
25
|
+
node: { type: 'string', description: 'Name of the node to add facts to' },
|
|
26
|
+
contents: { type: 'array', items: { type: 'string' }, description: 'Array of fact strings to add' },
|
|
27
|
+
},
|
|
28
|
+
required: ['node', 'contents'],
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
required: ['facts'],
|
|
33
|
+
};
|
|
34
|
+
constructor(factService) {
|
|
35
|
+
super();
|
|
36
|
+
this.factService = factService;
|
|
37
|
+
}
|
|
38
|
+
async execute(input) {
|
|
39
|
+
// Validate array parameters
|
|
40
|
+
this.validateArray(input.facts, 'facts', {
|
|
41
|
+
description: 'Provide an array of facts to add',
|
|
42
|
+
example: '{"facts": [{"node": "Alice", "contents": ["Engineer"]}]}',
|
|
43
|
+
});
|
|
44
|
+
this.validateNestedArray(input.facts, 'facts', 'contents', {
|
|
45
|
+
description: 'The "contents" field must be an array of strings',
|
|
46
|
+
example: '{"facts": [{"node": "Alice", "contents": ["Fact 1", "Fact 2"]}]}',
|
|
47
|
+
});
|
|
48
|
+
// Map 'node' property to 'nodeName' for FactService
|
|
49
|
+
const factsInput = input.facts.map((f) => ({
|
|
50
|
+
nodeName: f.node,
|
|
51
|
+
contents: f.contents,
|
|
52
|
+
}));
|
|
53
|
+
const facts = await this.factService.createFacts(factsInput);
|
|
54
|
+
const entityIds = Array.from(new Set(facts.map(f => f.nodeId)));
|
|
55
|
+
const nodeMap = await this.factService.getNodeNameMap(entityIds);
|
|
56
|
+
const factsByNode = new Map();
|
|
57
|
+
for (const fact of facts) {
|
|
58
|
+
const nodeName = nodeMap.get(fact.nodeId) || '';
|
|
59
|
+
if (!factsByNode.has(nodeName))
|
|
60
|
+
factsByNode.set(nodeName, []);
|
|
61
|
+
factsByNode.get(nodeName).push(fact.content);
|
|
62
|
+
}
|
|
63
|
+
const output = {
|
|
64
|
+
added: facts.length,
|
|
65
|
+
facts: Array.from(factsByNode.entries()).map(([nodeName, facts]) => ({
|
|
66
|
+
node: nodeName,
|
|
67
|
+
contents: facts,
|
|
68
|
+
})),
|
|
69
|
+
};
|
|
70
|
+
return { content: [{ type: 'text', text: JSON.stringify(output) }] };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=FactAddCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FactAddCommand.js","sourceRoot":"","sources":["../../../../src/interfaces/mcp/commands/FactAddCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,MAAM,OAAO,cAAe,SAAQ,WAAqB;IAgC1B;IA/BpB,IAAI,GAAG,aAAa,CAAC;IACrB,WAAW,GAAG;;;;;;;;;;oHAU2F,CAAC;IAC1G,WAAW,GAAG;QACrB,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,OAAO;gBACb,WAAW,EAAE,uFAAuF;gBACpG,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kCAAkC,EAAE;wBACzE,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,8BAA8B,EAAE;qBACpG;oBACD,QAAQ,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC;iBAC/B;aACF;SACF;QACD,QAAQ,EAAE,CAAC,OAAO,CAAC;KACpB,CAAC;IAEF,YAA6B,WAAwB;QACnD,KAAK,EAAE,CAAC;QADmB,gBAAW,GAAX,WAAW,CAAa;IAErD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAAU;QACtB,4BAA4B;QAC5B,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE;YACvC,WAAW,EAAE,kCAAkC;YAC/C,OAAO,EAAE,0DAA0D;SACpE,CAAC,CAAC;QACH,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE;YACzD,WAAW,EAAE,kDAAkD;YAC/D,OAAO,EAAE,kEAAkE;SAC5E,CAAC,CAAC;QAEH,oDAAoD;QACpD,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;YAC9C,QAAQ,EAAE,CAAC,CAAC,IAAI;YAChB,QAAQ,EAAE,CAAC,CAAC,QAAQ;SACrB,CAAC,CAAC,CAAC;QAEJ,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAE7D,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAChE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QAEjE,MAAM,WAAW,GAAG,IAAI,GAAG,EAAoB,CAAC;QAChD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YAChD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAAE,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAC9D,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,MAAM,GAAG;YACb,KAAK,EAAE,KAAK,CAAC,MAAM;YACnB,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;gBACnE,IAAI,EAAE,QAAQ;gBACd,QAAQ,EAAE,KAAK;aAChB,CAAC,CAAC;SACJ,CAAC;QAEF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;IACvE,CAAC;CACF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { BaseCommand } from './BaseCommand.js';
|
|
2
|
+
import type { FactService } from '../../../application/services/FactService.js';
|
|
3
|
+
export declare class FactDelCommand extends BaseCommand<any, any> {
|
|
4
|
+
private readonly factService;
|
|
5
|
+
readonly name = "kg_fact_del";
|
|
6
|
+
readonly description = "Delete specific facts from nodes. You must specify the node name and the exact content of facts to delete. Non-existent facts are silently ignored.\n\nExamples:\n1. Delete a single fact:\n { \"facts\": [{ \"node\": \"Alice\", \"contents\": [\"Old information\"] }] }\n\n2. Delete multiple facts from a node:\n { \"facts\": [{ \"node\": \"TechCorp\", \"contents\": [\"Outdated info 1\", \"Outdated info 2\"] }] }\n\n3. Delete facts from multiple nodes:\n { \"facts\": [{ \"node\": \"Alice\", \"contents\": [\"Deprecated skill\"] }, { \"node\": \"Bob\", \"contents\": [\"Old role\"] }] }";
|
|
7
|
+
readonly inputSchema: {
|
|
8
|
+
type: string;
|
|
9
|
+
properties: {
|
|
10
|
+
facts: {
|
|
11
|
+
type: string;
|
|
12
|
+
description: string;
|
|
13
|
+
items: {
|
|
14
|
+
type: string;
|
|
15
|
+
properties: {
|
|
16
|
+
node: {
|
|
17
|
+
type: string;
|
|
18
|
+
description: string;
|
|
19
|
+
};
|
|
20
|
+
contents: {
|
|
21
|
+
type: string;
|
|
22
|
+
items: {
|
|
23
|
+
type: string;
|
|
24
|
+
};
|
|
25
|
+
description: string;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
required: string[];
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
required: string[];
|
|
33
|
+
};
|
|
34
|
+
constructor(factService: FactService);
|
|
35
|
+
execute(input: any): Promise<{
|
|
36
|
+
content: Array<{
|
|
37
|
+
type: 'text';
|
|
38
|
+
text: string;
|
|
39
|
+
}>;
|
|
40
|
+
}>;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=FactDelCommand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FactDelCommand.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/mcp/commands/FactDelCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8CAA8C,CAAC;AAEhF,qBAAa,cAAe,SAAQ,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC;IAgC3C,OAAO,CAAC,QAAQ,CAAC,WAAW;IA/BxC,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,WAAW,qlBAUgG;IACpH,QAAQ,CAAC,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;MAiBlB;gBAE2B,WAAW,EAAE,WAAW;IAI/C,OAAO,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC;CAgCvF"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { BaseCommand } from './BaseCommand.js';
|
|
2
|
+
export class FactDelCommand extends BaseCommand {
|
|
3
|
+
factService;
|
|
4
|
+
name = 'kg_fact_del';
|
|
5
|
+
description = `Delete specific facts from nodes. You must specify the node name and the exact content of facts to delete. Non-existent facts are silently ignored.
|
|
6
|
+
|
|
7
|
+
Examples:
|
|
8
|
+
1. Delete a single fact:
|
|
9
|
+
{ "facts": [{ "node": "Alice", "contents": ["Old information"] }] }
|
|
10
|
+
|
|
11
|
+
2. Delete multiple facts from a node:
|
|
12
|
+
{ "facts": [{ "node": "TechCorp", "contents": ["Outdated info 1", "Outdated info 2"] }] }
|
|
13
|
+
|
|
14
|
+
3. Delete facts from multiple nodes:
|
|
15
|
+
{ "facts": [{ "node": "Alice", "contents": ["Deprecated skill"] }, { "node": "Bob", "contents": ["Old role"] }] }`;
|
|
16
|
+
inputSchema = {
|
|
17
|
+
type: 'object',
|
|
18
|
+
properties: {
|
|
19
|
+
facts: {
|
|
20
|
+
type: 'array',
|
|
21
|
+
description: 'Array of facts to delete. Each item specifies a node name and the fact contents to delete.',
|
|
22
|
+
items: {
|
|
23
|
+
type: 'object',
|
|
24
|
+
properties: {
|
|
25
|
+
node: { type: 'string', description: 'Name of the node to delete facts from' },
|
|
26
|
+
contents: { type: 'array', items: { type: 'string' }, description: 'Array of fact strings to delete (must match exactly)' },
|
|
27
|
+
},
|
|
28
|
+
required: ['node', 'contents'],
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
required: ['facts'],
|
|
33
|
+
};
|
|
34
|
+
constructor(factService) {
|
|
35
|
+
super();
|
|
36
|
+
this.factService = factService;
|
|
37
|
+
}
|
|
38
|
+
async execute(input) {
|
|
39
|
+
// Validate array parameters
|
|
40
|
+
this.validateArray(input.facts, 'facts', {
|
|
41
|
+
description: 'Provide an array of facts to delete',
|
|
42
|
+
example: '{"facts": [{"node": "Alice", "contents": ["Old fact"]}]}',
|
|
43
|
+
});
|
|
44
|
+
this.validateNestedArray(input.facts, 'facts', 'contents', {
|
|
45
|
+
description: 'The "contents" field must be an array of strings',
|
|
46
|
+
example: '{"facts": [{"node": "Alice", "contents": ["Fact to delete"]}]}',
|
|
47
|
+
});
|
|
48
|
+
let count = 0;
|
|
49
|
+
const deletedFacts = [];
|
|
50
|
+
for (const deletion of input.facts) {
|
|
51
|
+
const deleted = await this.factService.deleteFactsByContent(deletion.node, deletion.contents);
|
|
52
|
+
count += deleted;
|
|
53
|
+
for (const content of deletion.contents) {
|
|
54
|
+
deletedFacts.push({ node: deletion.node, content });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
content: [{
|
|
59
|
+
type: 'text',
|
|
60
|
+
text: JSON.stringify({
|
|
61
|
+
deleted: count,
|
|
62
|
+
facts: deletedFacts,
|
|
63
|
+
}),
|
|
64
|
+
}],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=FactDelCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FactDelCommand.js","sourceRoot":"","sources":["../../../../src/interfaces/mcp/commands/FactDelCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,MAAM,OAAO,cAAe,SAAQ,WAAqB;IAgC1B;IA/BpB,IAAI,GAAG,aAAa,CAAC;IACrB,WAAW,GAAG;;;;;;;;;;qHAU4F,CAAC;IAC3G,WAAW,GAAG;QACrB,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,OAAO;gBACb,WAAW,EAAE,4FAA4F;gBACzG,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uCAAuC,EAAE;wBAC9E,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,sDAAsD,EAAE;qBAC5H;oBACD,QAAQ,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC;iBAC/B;aACF;SACF;QACD,QAAQ,EAAE,CAAC,OAAO,CAAC;KACpB,CAAC;IAEF,YAA6B,WAAwB;QACnD,KAAK,EAAE,CAAC;QADmB,gBAAW,GAAX,WAAW,CAAa;IAErD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAAU;QACtB,4BAA4B;QAC5B,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE;YACvC,WAAW,EAAE,qCAAqC;YAClD,OAAO,EAAE,0DAA0D;SACpE,CAAC,CAAC;QACH,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE;YACzD,WAAW,EAAE,kDAAkD;YAC/D,OAAO,EAAE,gEAAgE;SAC1E,CAAC,CAAC;QAEH,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,MAAM,YAAY,GAAU,EAAE,CAAC;QAE/B,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YACnC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,oBAAoB,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC9F,KAAK,IAAI,OAAO,CAAC;YACjB,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBACxC,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;QAED,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;wBACnB,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE,YAAY;qBACpB,CAAC;iBACH,CAAC;SACH,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { BaseCommand } from './BaseCommand.js';
|
|
2
|
+
import type { FactService } from '../../../application/services/FactService.js';
|
|
3
|
+
export declare class FactEditCommand extends BaseCommand<any, any> {
|
|
4
|
+
private readonly factService;
|
|
5
|
+
readonly name = "kg_fact_edit";
|
|
6
|
+
readonly description = "Edit an existing fact's content. You must specify the node name, the old content to match, and the new content. The match must be exact.\n\nExamples:\n1. Update a fact:\n { \"facts\": [{ \"node\": \"Alice\", \"old\": \"5 years experience\", \"new\": \"6 years experience\" }] }\n\n2. Update multiple facts:\n { \"facts\": [{ \"node\": \"Alice\", \"old\": \"Junior Developer\", \"new\": \"Senior Developer\" }, { \"node\": \"TechCorp\", \"old\": \"500 employees\", \"new\": \"1000 employees\" }] }\n\n3. Correct a typo:\n { \"facts\": [{ \"node\": \"ProjectX\", \"old\": \"Due Q2 2024\", \"new\": \"Completed on time!\" }] }";
|
|
7
|
+
readonly inputSchema: {
|
|
8
|
+
type: string;
|
|
9
|
+
properties: {
|
|
10
|
+
facts: {
|
|
11
|
+
type: string;
|
|
12
|
+
description: string;
|
|
13
|
+
items: {
|
|
14
|
+
type: string;
|
|
15
|
+
properties: {
|
|
16
|
+
node: {
|
|
17
|
+
type: string;
|
|
18
|
+
description: string;
|
|
19
|
+
};
|
|
20
|
+
old: {
|
|
21
|
+
type: string;
|
|
22
|
+
description: string;
|
|
23
|
+
};
|
|
24
|
+
new: {
|
|
25
|
+
type: string;
|
|
26
|
+
description: string;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
required: string[];
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
required: string[];
|
|
34
|
+
};
|
|
35
|
+
constructor(factService: FactService);
|
|
36
|
+
execute(input: any): Promise<{
|
|
37
|
+
content: Array<{
|
|
38
|
+
type: 'text';
|
|
39
|
+
text: string;
|
|
40
|
+
}>;
|
|
41
|
+
}>;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=FactEditCommand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FactEditCommand.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/mcp/commands/FactEditCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8CAA8C,CAAC;AAEhF,qBAAa,eAAgB,SAAQ,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC;IAiC5C,OAAO,CAAC,QAAQ,CAAC,WAAW;IAhCxC,QAAQ,CAAC,IAAI,kBAAkB;IAC/B,QAAQ,CAAC,WAAW,2nBAUuE;IAC3F,QAAQ,CAAC,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;MAkBlB;gBAE2B,WAAW,EAAE,WAAW;IAI/C,OAAO,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC;CAgCvF"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { BaseCommand } from './BaseCommand.js';
|
|
2
|
+
export class FactEditCommand extends BaseCommand {
|
|
3
|
+
factService;
|
|
4
|
+
name = 'kg_fact_edit';
|
|
5
|
+
description = `Edit an existing fact's content. You must specify the node name, the old content to match, and the new content. The match must be exact.
|
|
6
|
+
|
|
7
|
+
Examples:
|
|
8
|
+
1. Update a fact:
|
|
9
|
+
{ "facts": [{ "node": "Alice", "old": "5 years experience", "new": "6 years experience" }] }
|
|
10
|
+
|
|
11
|
+
2. Update multiple facts:
|
|
12
|
+
{ "facts": [{ "node": "Alice", "old": "Junior Developer", "new": "Senior Developer" }, { "node": "TechCorp", "old": "500 employees", "new": "1000 employees" }] }
|
|
13
|
+
|
|
14
|
+
3. Correct a typo:
|
|
15
|
+
{ "facts": [{ "node": "ProjectX", "old": "Due Q2 2024", "new": "Completed on time!" }] }`;
|
|
16
|
+
inputSchema = {
|
|
17
|
+
type: 'object',
|
|
18
|
+
properties: {
|
|
19
|
+
facts: {
|
|
20
|
+
type: 'array',
|
|
21
|
+
description: 'Array of facts to edit. Each item identifies a fact by node and old content, then provides new content.',
|
|
22
|
+
items: {
|
|
23
|
+
type: 'object',
|
|
24
|
+
properties: {
|
|
25
|
+
node: { type: 'string', description: 'Name of the node containing the fact' },
|
|
26
|
+
old: { type: 'string', description: 'Current content to match exactly' },
|
|
27
|
+
new: { type: 'string', description: 'New content to replace with' },
|
|
28
|
+
},
|
|
29
|
+
required: ['node', 'old', 'new'],
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
required: ['facts'],
|
|
34
|
+
};
|
|
35
|
+
constructor(factService) {
|
|
36
|
+
super();
|
|
37
|
+
this.factService = factService;
|
|
38
|
+
}
|
|
39
|
+
async execute(input) {
|
|
40
|
+
// Validate array parameters
|
|
41
|
+
this.validateArray(input.facts, 'facts', {
|
|
42
|
+
description: 'Provide an array of facts to edit',
|
|
43
|
+
example: '{"facts": [{"node": "Alice", "old": "old content", "new": "new content"}]}',
|
|
44
|
+
});
|
|
45
|
+
// Map 'node'/'old'/'new' to 'nodeName'/'oldContent'/'newContent'
|
|
46
|
+
const edits = input.facts.map((fact) => ({
|
|
47
|
+
nodeName: fact.node,
|
|
48
|
+
oldContent: fact.old,
|
|
49
|
+
newContent: fact.new,
|
|
50
|
+
}));
|
|
51
|
+
const facts = await this.factService.updateFactsByContent(edits);
|
|
52
|
+
const entityIds = Array.from(new Set(facts.map(f => f.nodeId)));
|
|
53
|
+
const nodeMap = await this.factService.getNodeNameMap(entityIds);
|
|
54
|
+
return {
|
|
55
|
+
content: [{
|
|
56
|
+
type: 'text',
|
|
57
|
+
text: JSON.stringify({
|
|
58
|
+
updated: facts.length,
|
|
59
|
+
facts: facts.map(f => ({
|
|
60
|
+
node: nodeMap.get(f.nodeId) || '',
|
|
61
|
+
content: f.content,
|
|
62
|
+
})),
|
|
63
|
+
}),
|
|
64
|
+
}],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=FactEditCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FactEditCommand.js","sourceRoot":"","sources":["../../../../src/interfaces/mcp/commands/FactEditCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,MAAM,OAAO,eAAgB,SAAQ,WAAqB;IAiC3B;IAhCpB,IAAI,GAAG,cAAc,CAAC;IACtB,WAAW,GAAG;;;;;;;;;;4FAUmE,CAAC;IAClF,WAAW,GAAG;QACrB,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,OAAO;gBACb,WAAW,EAAE,yGAAyG;gBACtH,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,sCAAsC,EAAE;wBAC7E,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kCAAkC,EAAE;wBACxE,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,6BAA6B,EAAE;qBACpE;oBACD,QAAQ,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC;iBACjC;aACF;SACF;QACD,QAAQ,EAAE,CAAC,OAAO,CAAC;KACpB,CAAC;IAEF,YAA6B,WAAwB;QACnD,KAAK,EAAE,CAAC;QADmB,gBAAW,GAAX,WAAW,CAAa;IAErD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAAU;QACtB,4BAA4B;QAC5B,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE;YACvC,WAAW,EAAE,mCAAmC;YAChD,OAAO,EAAE,4EAA4E;SACtF,CAAC,CAAC;QAEH,iEAAiE;QACjE,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,CAAC;YAC5C,QAAQ,EAAE,IAAI,CAAC,IAAI;YACnB,UAAU,EAAE,IAAI,CAAC,GAAG;YACpB,UAAU,EAAE,IAAI,CAAC,GAAG;SACrB,CAAC,CAAC,CAAC;QAEJ,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAEjE,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAChE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QAEjE,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;wBACnB,OAAO,EAAE,KAAK,CAAC,MAAM;wBACrB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;4BACrB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE;4BACjC,OAAO,EAAE,CAAC,CAAC,OAAO;yBACnB,CAAC,CAAC;qBACJ,CAAC;iBACH,CAAC;SACH,CAAC;IACJ,CAAC;CACF"}
|