sqlew 1.0.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/ARCHITECTURE.md +636 -0
- package/CHANGELOG.md +107 -0
- package/LICENSE +21 -0
- package/README.md +359 -0
- package/assets/schema.sql +320 -0
- package/assets/sqlew-logo.png +0 -0
- package/dist/constants.d.ts +146 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +230 -0
- package/dist/constants.js.map +1 -0
- package/dist/database.d.ts +94 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +214 -0
- package/dist/database.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +771 -0
- package/dist/index.js.map +1 -0
- package/dist/schema.d.ts +50 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +161 -0
- package/dist/schema.js.map +1 -0
- package/dist/tools/constraints.d.ts +29 -0
- package/dist/tools/constraints.d.ts.map +1 -0
- package/dist/tools/constraints.js +192 -0
- package/dist/tools/constraints.js.map +1 -0
- package/dist/tools/context.d.ts +56 -0
- package/dist/tools/context.d.ts.map +1 -0
- package/dist/tools/context.js +442 -0
- package/dist/tools/context.js.map +1 -0
- package/dist/tools/files.d.ts +30 -0
- package/dist/tools/files.d.ts.map +1 -0
- package/dist/tools/files.js +201 -0
- package/dist/tools/files.js.map +1 -0
- package/dist/tools/messaging.d.ts +50 -0
- package/dist/tools/messaging.d.ts.map +1 -0
- package/dist/tools/messaging.js +151 -0
- package/dist/tools/messaging.js.map +1 -0
- package/dist/tools/utils.d.ts +29 -0
- package/dist/tools/utils.d.ts.map +1 -0
- package/dist/tools/utils.js +131 -0
- package/dist/tools/utils.js.map +1 -0
- package/dist/types.d.ts +388 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +50 -0
- package/dist/types.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File tracking tools for MCP Shared Context Server
|
|
3
|
+
* Provides file change tracking with layer integration and lock detection
|
|
4
|
+
*/
|
|
5
|
+
import { getDatabase, getOrCreateFile, getOrCreateAgent, getLayerId } from '../database.js';
|
|
6
|
+
import { STRING_TO_CHANGE_TYPE, CHANGE_TYPE_TO_STRING, STANDARD_LAYERS, DEFAULT_QUERY_LIMIT } from '../constants.js';
|
|
7
|
+
/**
|
|
8
|
+
* Record a file change with optional layer assignment and description.
|
|
9
|
+
* Auto-registers the file and agent if they don't exist.
|
|
10
|
+
*
|
|
11
|
+
* @param params - File change parameters
|
|
12
|
+
* @returns Success response with change ID and timestamp
|
|
13
|
+
*/
|
|
14
|
+
export function recordFileChange(params) {
|
|
15
|
+
const db = getDatabase();
|
|
16
|
+
try {
|
|
17
|
+
// Validate change_type
|
|
18
|
+
const changeTypeInt = STRING_TO_CHANGE_TYPE[params.change_type];
|
|
19
|
+
if (changeTypeInt === undefined) {
|
|
20
|
+
throw new Error(`Invalid change_type: ${params.change_type}. Must be one of: created, modified, deleted`);
|
|
21
|
+
}
|
|
22
|
+
// Validate layer if provided
|
|
23
|
+
let layerId = null;
|
|
24
|
+
if (params.layer) {
|
|
25
|
+
if (!STANDARD_LAYERS.includes(params.layer)) {
|
|
26
|
+
throw new Error(`Invalid layer: ${params.layer}. Must be one of: ${STANDARD_LAYERS.join(', ')}`);
|
|
27
|
+
}
|
|
28
|
+
layerId = getLayerId(db, params.layer);
|
|
29
|
+
if (layerId === null) {
|
|
30
|
+
throw new Error(`Layer not found: ${params.layer}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// Auto-register file and agent
|
|
34
|
+
const fileId = getOrCreateFile(db, params.file_path);
|
|
35
|
+
const agentId = getOrCreateAgent(db, params.agent_name);
|
|
36
|
+
// Insert file change record
|
|
37
|
+
const stmt = db.prepare(`
|
|
38
|
+
INSERT INTO file_changes (file_id, agent_id, layer_id, change_type, description)
|
|
39
|
+
VALUES (?, ?, ?, ?, ?)
|
|
40
|
+
`);
|
|
41
|
+
const result = stmt.run(fileId, agentId, layerId, changeTypeInt, params.description || null);
|
|
42
|
+
// Get timestamp
|
|
43
|
+
const tsResult = db.prepare('SELECT ts FROM file_changes WHERE id = ?')
|
|
44
|
+
.get(result.lastInsertRowid);
|
|
45
|
+
return {
|
|
46
|
+
success: true,
|
|
47
|
+
change_id: result.lastInsertRowid,
|
|
48
|
+
timestamp: tsResult ? new Date(tsResult.ts * 1000).toISOString() : new Date().toISOString(),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
53
|
+
throw new Error(`Failed to record file change: ${message}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get file changes with advanced filtering.
|
|
58
|
+
* Uses token-efficient view when no specific filters are applied.
|
|
59
|
+
*
|
|
60
|
+
* @param params - Filter parameters
|
|
61
|
+
* @returns Array of file changes with metadata
|
|
62
|
+
*/
|
|
63
|
+
export function getFileChanges(params) {
|
|
64
|
+
const db = getDatabase();
|
|
65
|
+
try {
|
|
66
|
+
const limit = params.limit || DEFAULT_QUERY_LIMIT;
|
|
67
|
+
const conditions = [];
|
|
68
|
+
const values = [];
|
|
69
|
+
// Build WHERE clause based on filters
|
|
70
|
+
if (params.file_path) {
|
|
71
|
+
conditions.push('f.path = ?');
|
|
72
|
+
values.push(params.file_path);
|
|
73
|
+
}
|
|
74
|
+
if (params.agent_name) {
|
|
75
|
+
conditions.push('a.name = ?');
|
|
76
|
+
values.push(params.agent_name);
|
|
77
|
+
}
|
|
78
|
+
if (params.layer) {
|
|
79
|
+
// Validate layer
|
|
80
|
+
if (!STANDARD_LAYERS.includes(params.layer)) {
|
|
81
|
+
throw new Error(`Invalid layer: ${params.layer}. Must be one of: ${STANDARD_LAYERS.join(', ')}`);
|
|
82
|
+
}
|
|
83
|
+
conditions.push('l.name = ?');
|
|
84
|
+
values.push(params.layer);
|
|
85
|
+
}
|
|
86
|
+
if (params.change_type) {
|
|
87
|
+
const changeTypeInt = STRING_TO_CHANGE_TYPE[params.change_type];
|
|
88
|
+
if (changeTypeInt === undefined) {
|
|
89
|
+
throw new Error(`Invalid change_type: ${params.change_type}`);
|
|
90
|
+
}
|
|
91
|
+
conditions.push('fc.change_type = ?');
|
|
92
|
+
values.push(changeTypeInt);
|
|
93
|
+
}
|
|
94
|
+
if (params.since) {
|
|
95
|
+
// Convert ISO 8601 to Unix epoch
|
|
96
|
+
const sinceEpoch = Math.floor(new Date(params.since).getTime() / 1000);
|
|
97
|
+
conditions.push('fc.ts >= ?');
|
|
98
|
+
values.push(sinceEpoch);
|
|
99
|
+
}
|
|
100
|
+
// Use view if no specific filters (token efficient)
|
|
101
|
+
if (conditions.length === 0) {
|
|
102
|
+
const stmt = db.prepare(`
|
|
103
|
+
SELECT * FROM recent_file_changes
|
|
104
|
+
LIMIT ?
|
|
105
|
+
`);
|
|
106
|
+
const rows = stmt.all(limit);
|
|
107
|
+
return {
|
|
108
|
+
changes: rows,
|
|
109
|
+
count: rows.length,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
// Otherwise, build custom query
|
|
113
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
114
|
+
const stmt = db.prepare(`
|
|
115
|
+
SELECT
|
|
116
|
+
f.path,
|
|
117
|
+
a.name as changed_by,
|
|
118
|
+
l.name as layer,
|
|
119
|
+
CASE fc.change_type
|
|
120
|
+
WHEN 1 THEN 'created'
|
|
121
|
+
WHEN 2 THEN 'modified'
|
|
122
|
+
ELSE 'deleted'
|
|
123
|
+
END as change_type,
|
|
124
|
+
fc.description,
|
|
125
|
+
datetime(fc.ts, 'unixepoch') as changed_at
|
|
126
|
+
FROM file_changes fc
|
|
127
|
+
JOIN files f ON fc.file_id = f.id
|
|
128
|
+
JOIN agents a ON fc.agent_id = a.id
|
|
129
|
+
LEFT JOIN layers l ON fc.layer_id = l.id
|
|
130
|
+
${whereClause}
|
|
131
|
+
ORDER BY fc.ts DESC
|
|
132
|
+
LIMIT ?
|
|
133
|
+
`);
|
|
134
|
+
values.push(limit);
|
|
135
|
+
const rows = stmt.all(...values);
|
|
136
|
+
return {
|
|
137
|
+
changes: rows,
|
|
138
|
+
count: rows.length,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
143
|
+
throw new Error(`Failed to get file changes: ${message}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Check if a file is "locked" (recently modified by another agent).
|
|
148
|
+
* Useful to prevent concurrent edits by multiple agents.
|
|
149
|
+
*
|
|
150
|
+
* @param params - File path and lock duration
|
|
151
|
+
* @returns Lock status with details
|
|
152
|
+
*/
|
|
153
|
+
export function checkFileLock(params) {
|
|
154
|
+
const db = getDatabase();
|
|
155
|
+
try {
|
|
156
|
+
const lockDuration = params.lock_duration || 300; // Default 5 minutes
|
|
157
|
+
const currentTime = Math.floor(Date.now() / 1000);
|
|
158
|
+
const lockThreshold = currentTime - lockDuration;
|
|
159
|
+
// Get the most recent change to this file
|
|
160
|
+
const stmt = db.prepare(`
|
|
161
|
+
SELECT
|
|
162
|
+
a.name as agent,
|
|
163
|
+
fc.change_type,
|
|
164
|
+
fc.ts
|
|
165
|
+
FROM file_changes fc
|
|
166
|
+
JOIN files f ON fc.file_id = f.id
|
|
167
|
+
JOIN agents a ON fc.agent_id = a.id
|
|
168
|
+
WHERE f.path = ?
|
|
169
|
+
ORDER BY fc.ts DESC
|
|
170
|
+
LIMIT 1
|
|
171
|
+
`);
|
|
172
|
+
const result = stmt.get(params.file_path);
|
|
173
|
+
if (!result) {
|
|
174
|
+
// File never changed
|
|
175
|
+
return {
|
|
176
|
+
locked: false,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
// Check if within lock duration
|
|
180
|
+
if (result.ts >= lockThreshold) {
|
|
181
|
+
return {
|
|
182
|
+
locked: true,
|
|
183
|
+
last_agent: result.agent,
|
|
184
|
+
last_change: new Date(result.ts * 1000).toISOString(),
|
|
185
|
+
change_type: CHANGE_TYPE_TO_STRING[result.change_type],
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
// Not locked (too old)
|
|
189
|
+
return {
|
|
190
|
+
locked: false,
|
|
191
|
+
last_agent: result.agent,
|
|
192
|
+
last_change: new Date(result.ts * 1000).toISOString(),
|
|
193
|
+
change_type: CHANGE_TYPE_TO_STRING[result.change_type],
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
198
|
+
throw new Error(`Failed to check file lock: ${message}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/tools/files.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5F,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACpB,MAAM,iBAAiB,CAAC;AAWzB;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAA8B;IAC7D,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;IAEzB,IAAI,CAAC;QACH,uBAAuB;QACvB,MAAM,aAAa,GAAG,qBAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAChE,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,wBAAwB,MAAM,CAAC,WAAW,8CAA8C,CAAC,CAAC;QAC5G,CAAC;QAED,6BAA6B;QAC7B,IAAI,OAAO,GAAkB,IAAI,CAAC;QAClC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAY,CAAC,EAAE,CAAC;gBACnD,MAAM,IAAI,KAAK,CACb,kBAAkB,MAAM,CAAC,KAAK,qBAAqB,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAChF,CAAC;YACJ,CAAC;YACD,OAAO,GAAG,UAAU,CAAC,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;YACvC,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;gBACrB,MAAM,IAAI,KAAK,CAAC,oBAAoB,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;QAED,+BAA+B;QAC/B,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QACrD,MAAM,OAAO,GAAG,gBAAgB,CAAC,EAAE,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QAExD,4BAA4B;QAC5B,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;;KAGvB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CACrB,MAAM,EACN,OAAO,EACP,OAAO,EACP,aAAa,EACb,MAAM,CAAC,WAAW,IAAI,IAAI,CAC3B,CAAC;QAEF,gBAAgB;QAChB,MAAM,QAAQ,GAAG,EAAE,CAAC,OAAO,CAAC,0CAA0C,CAAC;aACpE,GAAG,CAAC,MAAM,CAAC,eAAe,CAA+B,CAAC;QAE7D,OAAO;YACL,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,MAAM,CAAC,eAAyB;YAC3C,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SAC5F,CAAC;IAEJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,IAAI,KAAK,CAAC,iCAAiC,OAAO,EAAE,CAAC,CAAC;IAC9D,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,MAA4B;IACzD,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;IAEzB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,mBAAmB,CAAC;QAClD,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,MAAM,MAAM,GAAU,EAAE,CAAC;QAEzB,sCAAsC;QACtC,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACrB,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAChC,CAAC;QAED,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACtB,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACjC,CAAC;QAED,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,iBAAiB;YACjB,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAY,CAAC,EAAE,CAAC;gBACnD,MAAM,IAAI,KAAK,CACb,kBAAkB,MAAM,CAAC,KAAK,qBAAqB,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAChF,CAAC;YACJ,CAAC;YACD,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;QAED,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YACvB,MAAM,aAAa,GAAG,qBAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAChE,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;gBAChC,MAAM,IAAI,KAAK,CAAC,wBAAwB,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;YAChE,CAAC;YACD,UAAU,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC7B,CAAC;QAED,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,iCAAiC;YACjC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;YACvE,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1B,CAAC;QAED,oDAAoD;QACpD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;;OAGvB,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAuB,CAAC;YAEnD,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE,IAAI,CAAC,MAAM;aACnB,CAAC;QACJ,CAAC;QAED,gCAAgC;QAChC,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAErF,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;QAgBpB,WAAW;;;KAGd,CAAC,CAAC;QAEH,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAuB,CAAC;QAEvD,OAAO;YACL,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,IAAI,CAAC,MAAM;SACnB,CAAC;IAEJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,IAAI,KAAK,CAAC,+BAA+B,OAAO,EAAE,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,MAA2B;IACvD,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;IAEzB,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,MAAM,CAAC,aAAa,IAAI,GAAG,CAAC,CAAC,oBAAoB;QACtE,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAClD,MAAM,aAAa,GAAG,WAAW,GAAG,YAAY,CAAC;QAEjD,0CAA0C;QAC1C,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;;;;;;KAWvB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CACwB,CAAC;QAEjE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,qBAAqB;YACrB,OAAO;gBACL,MAAM,EAAE,KAAK;aACd,CAAC;QACJ,CAAC;QAED,gCAAgC;QAChC,IAAI,MAAM,CAAC,EAAE,IAAI,aAAa,EAAE,CAAC;YAC/B,OAAO;gBACL,MAAM,EAAE,IAAI;gBACZ,UAAU,EAAE,MAAM,CAAC,KAAK;gBACxB,WAAW,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE;gBACrD,WAAW,EAAE,qBAAqB,CAAC,MAAM,CAAC,WAAwB,CAAC;aACpE,CAAC;QACJ,CAAC;QAED,uBAAuB;QACvB,OAAO;YACL,MAAM,EAAE,KAAK;YACb,UAAU,EAAE,MAAM,CAAC,KAAK;YACxB,WAAW,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE;YACrD,WAAW,EAAE,qBAAqB,CAAC,MAAM,CAAC,WAAwB,CAAC;SACpE,CAAC;IAEJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,IAAI,KAAK,CAAC,8BAA8B,OAAO,EAAE,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Messaging Tools for MCP Shared Context Server
|
|
3
|
+
* Agent-to-agent communication with priority and read tracking
|
|
4
|
+
*/
|
|
5
|
+
import type { SendMessageResponse, GetMessagesResponse, MarkReadResponse } from '../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Send a message from one agent to another (or broadcast)
|
|
8
|
+
* Supports priority levels and optional JSON payload
|
|
9
|
+
*
|
|
10
|
+
* @param params - Message parameters
|
|
11
|
+
* @returns Response with message ID and timestamp
|
|
12
|
+
*/
|
|
13
|
+
export declare function sendMessage(params: {
|
|
14
|
+
from_agent: string;
|
|
15
|
+
to_agent: string | null | undefined;
|
|
16
|
+
msg_type: 'decision' | 'warning' | 'request' | 'info';
|
|
17
|
+
message: string;
|
|
18
|
+
priority?: 'low' | 'medium' | 'high' | 'critical';
|
|
19
|
+
payload?: any;
|
|
20
|
+
}): SendMessageResponse & {
|
|
21
|
+
timestamp: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Get messages for an agent with optional filtering
|
|
25
|
+
* Returns messages addressed to agent or broadcast (to_agent_id IS NULL)
|
|
26
|
+
*
|
|
27
|
+
* @param params - Query parameters
|
|
28
|
+
* @returns Array of messages with metadata
|
|
29
|
+
*/
|
|
30
|
+
export declare function getMessages(params: {
|
|
31
|
+
agent_name: string;
|
|
32
|
+
unread_only?: boolean;
|
|
33
|
+
priority_filter?: 'low' | 'medium' | 'high' | 'critical';
|
|
34
|
+
msg_type_filter?: 'decision' | 'warning' | 'request' | 'info';
|
|
35
|
+
limit?: number;
|
|
36
|
+
}): GetMessagesResponse;
|
|
37
|
+
/**
|
|
38
|
+
* Mark messages as read
|
|
39
|
+
* Only marks messages addressed to the specified agent (security check)
|
|
40
|
+
*
|
|
41
|
+
* @param params - Message IDs and agent name
|
|
42
|
+
* @returns Success status and count of marked messages
|
|
43
|
+
*/
|
|
44
|
+
export declare function markRead(params: {
|
|
45
|
+
message_ids: number[];
|
|
46
|
+
agent_name: string;
|
|
47
|
+
}): MarkReadResponse & {
|
|
48
|
+
marked_count: number;
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=messaging.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messaging.d.ts","sourceRoot":"","sources":["../../src/tools/messaging.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,OAAO,KAAK,EAIV,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAErB;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IAClD,OAAO,CAAC,EAAE,GAAG,CAAC;CACf,GAAG,mBAAmB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CA4C9C;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IACzD,eAAe,CAAC,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,mBAAmB,CAkFtB;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE;IAC/B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,gBAAgB,GAAG;IAAE,YAAY,EAAE,MAAM,CAAA;CAAE,CA6B9C"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Messaging Tools for MCP Shared Context Server
|
|
3
|
+
* Agent-to-agent communication with priority and read tracking
|
|
4
|
+
*/
|
|
5
|
+
import { getDatabase, getOrCreateAgent } from '../database.js';
|
|
6
|
+
import { STRING_TO_MESSAGE_TYPE, STRING_TO_PRIORITY, MESSAGE_TYPE_TO_STRING, PRIORITY_TO_STRING, } from '../constants.js';
|
|
7
|
+
/**
|
|
8
|
+
* Send a message from one agent to another (or broadcast)
|
|
9
|
+
* Supports priority levels and optional JSON payload
|
|
10
|
+
*
|
|
11
|
+
* @param params - Message parameters
|
|
12
|
+
* @returns Response with message ID and timestamp
|
|
13
|
+
*/
|
|
14
|
+
export function sendMessage(params) {
|
|
15
|
+
const db = getDatabase();
|
|
16
|
+
// Validate msg_type
|
|
17
|
+
if (!STRING_TO_MESSAGE_TYPE[params.msg_type]) {
|
|
18
|
+
throw new Error(`Invalid msg_type: ${params.msg_type}. Must be one of: decision, warning, request, info`);
|
|
19
|
+
}
|
|
20
|
+
// Validate priority if provided
|
|
21
|
+
const priority = params.priority || 'medium';
|
|
22
|
+
if (!STRING_TO_PRIORITY[priority]) {
|
|
23
|
+
throw new Error(`Invalid priority: ${priority}. Must be one of: low, medium, high, critical`);
|
|
24
|
+
}
|
|
25
|
+
// Auto-register from_agent
|
|
26
|
+
const fromAgentId = getOrCreateAgent(db, params.from_agent);
|
|
27
|
+
// Auto-register to_agent if provided (null = broadcast)
|
|
28
|
+
const toAgentId = params.to_agent ? getOrCreateAgent(db, params.to_agent) : null;
|
|
29
|
+
// Convert enums to integers
|
|
30
|
+
const msgTypeInt = STRING_TO_MESSAGE_TYPE[params.msg_type];
|
|
31
|
+
const priorityInt = STRING_TO_PRIORITY[priority];
|
|
32
|
+
// Serialize payload if provided
|
|
33
|
+
const payloadStr = params.payload ? JSON.stringify(params.payload) : null;
|
|
34
|
+
// Insert message
|
|
35
|
+
const stmt = db.prepare(`
|
|
36
|
+
INSERT INTO agent_messages (from_agent_id, to_agent_id, msg_type, priority, payload, read)
|
|
37
|
+
VALUES (?, ?, ?, ?, ?, 0)
|
|
38
|
+
`);
|
|
39
|
+
const result = stmt.run(fromAgentId, toAgentId, msgTypeInt, priorityInt, payloadStr);
|
|
40
|
+
// Get timestamp
|
|
41
|
+
const tsResult = db.prepare('SELECT ts FROM agent_messages WHERE id = ?').get(result.lastInsertRowid);
|
|
42
|
+
const timestamp = new Date(tsResult.ts * 1000).toISOString();
|
|
43
|
+
return {
|
|
44
|
+
success: true,
|
|
45
|
+
message_id: Number(result.lastInsertRowid),
|
|
46
|
+
timestamp,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get messages for an agent with optional filtering
|
|
51
|
+
* Returns messages addressed to agent or broadcast (to_agent_id IS NULL)
|
|
52
|
+
*
|
|
53
|
+
* @param params - Query parameters
|
|
54
|
+
* @returns Array of messages with metadata
|
|
55
|
+
*/
|
|
56
|
+
export function getMessages(params) {
|
|
57
|
+
const db = getDatabase();
|
|
58
|
+
// Get or create agent to get ID
|
|
59
|
+
const agentId = getOrCreateAgent(db, params.agent_name);
|
|
60
|
+
// Build query dynamically based on filters
|
|
61
|
+
let query = `
|
|
62
|
+
SELECT
|
|
63
|
+
m.id,
|
|
64
|
+
a.name as from_agent,
|
|
65
|
+
m.msg_type,
|
|
66
|
+
m.priority,
|
|
67
|
+
m.payload,
|
|
68
|
+
m.ts,
|
|
69
|
+
m.read
|
|
70
|
+
FROM agent_messages m
|
|
71
|
+
JOIN agents a ON m.from_agent_id = a.id
|
|
72
|
+
WHERE (m.to_agent_id = ? OR m.to_agent_id IS NULL)
|
|
73
|
+
`;
|
|
74
|
+
const queryParams = [agentId];
|
|
75
|
+
// Filter by read status
|
|
76
|
+
if (params.unread_only) {
|
|
77
|
+
query += ' AND m.read = 0';
|
|
78
|
+
}
|
|
79
|
+
// Filter by priority
|
|
80
|
+
if (params.priority_filter) {
|
|
81
|
+
if (!STRING_TO_PRIORITY[params.priority_filter]) {
|
|
82
|
+
throw new Error(`Invalid priority_filter: ${params.priority_filter}`);
|
|
83
|
+
}
|
|
84
|
+
const priorityInt = STRING_TO_PRIORITY[params.priority_filter];
|
|
85
|
+
query += ' AND m.priority = ?';
|
|
86
|
+
queryParams.push(priorityInt);
|
|
87
|
+
}
|
|
88
|
+
// Filter by msg_type
|
|
89
|
+
if (params.msg_type_filter) {
|
|
90
|
+
if (!STRING_TO_MESSAGE_TYPE[params.msg_type_filter]) {
|
|
91
|
+
throw new Error(`Invalid msg_type_filter: ${params.msg_type_filter}`);
|
|
92
|
+
}
|
|
93
|
+
const msgTypeInt = STRING_TO_MESSAGE_TYPE[params.msg_type_filter];
|
|
94
|
+
query += ' AND m.msg_type = ?';
|
|
95
|
+
queryParams.push(msgTypeInt);
|
|
96
|
+
}
|
|
97
|
+
// Order by priority DESC, then timestamp DESC
|
|
98
|
+
query += ' ORDER BY m.priority DESC, m.ts DESC';
|
|
99
|
+
// Limit results
|
|
100
|
+
const limit = params.limit || 50;
|
|
101
|
+
query += ' LIMIT ?';
|
|
102
|
+
queryParams.push(limit);
|
|
103
|
+
const stmt = db.prepare(query);
|
|
104
|
+
const rows = stmt.all(...queryParams);
|
|
105
|
+
// Transform results
|
|
106
|
+
const messages = rows.map(row => ({
|
|
107
|
+
id: row.id,
|
|
108
|
+
from_agent: row.from_agent,
|
|
109
|
+
msg_type: MESSAGE_TYPE_TO_STRING[row.msg_type],
|
|
110
|
+
priority: PRIORITY_TO_STRING[row.priority],
|
|
111
|
+
payload: row.payload ? JSON.parse(row.payload) : null,
|
|
112
|
+
timestamp: new Date(row.ts * 1000).toISOString(),
|
|
113
|
+
read: row.read === 1,
|
|
114
|
+
}));
|
|
115
|
+
return {
|
|
116
|
+
messages,
|
|
117
|
+
count: messages.length,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Mark messages as read
|
|
122
|
+
* Only marks messages addressed to the specified agent (security check)
|
|
123
|
+
*
|
|
124
|
+
* @param params - Message IDs and agent name
|
|
125
|
+
* @returns Success status and count of marked messages
|
|
126
|
+
*/
|
|
127
|
+
export function markRead(params) {
|
|
128
|
+
const db = getDatabase();
|
|
129
|
+
// Validate message_ids array
|
|
130
|
+
if (!params.message_ids || params.message_ids.length === 0) {
|
|
131
|
+
throw new Error('message_ids array cannot be empty');
|
|
132
|
+
}
|
|
133
|
+
// Get agent ID
|
|
134
|
+
const agentId = getOrCreateAgent(db, params.agent_name);
|
|
135
|
+
// Build placeholders for IN clause
|
|
136
|
+
const placeholders = params.message_ids.map(() => '?').join(',');
|
|
137
|
+
// Update only messages addressed to this agent (security check)
|
|
138
|
+
// Also allow broadcast messages (to_agent_id IS NULL)
|
|
139
|
+
const stmt = db.prepare(`
|
|
140
|
+
UPDATE agent_messages
|
|
141
|
+
SET read = 1
|
|
142
|
+
WHERE id IN (${placeholders})
|
|
143
|
+
AND (to_agent_id = ? OR to_agent_id IS NULL)
|
|
144
|
+
`);
|
|
145
|
+
const result = stmt.run(...params.message_ids, agentId);
|
|
146
|
+
return {
|
|
147
|
+
success: true,
|
|
148
|
+
marked_count: result.changes,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=messaging.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messaging.js","sourceRoot":"","sources":["../../src/tools/messaging.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility tools for MCP Shared Context Server
|
|
3
|
+
* Database statistics, layer summaries, and manual cleanup
|
|
4
|
+
*/
|
|
5
|
+
import type { GetLayerSummaryResponse, ClearOldDataParams, ClearOldDataResponse, GetStatsResponse } from '../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Get summary statistics for all architecture layers
|
|
8
|
+
* Uses the layer_summary view for token efficiency
|
|
9
|
+
*
|
|
10
|
+
* @returns Layer summaries for all 5 standard layers
|
|
11
|
+
*/
|
|
12
|
+
export declare function getLayerSummary(): GetLayerSummaryResponse;
|
|
13
|
+
/**
|
|
14
|
+
* Clear old data from the database
|
|
15
|
+
* Deletes messages and file changes older than specified thresholds
|
|
16
|
+
* Preserves decision_history, constraints, and core decisions
|
|
17
|
+
*
|
|
18
|
+
* @param params - Optional parameters for cleanup thresholds
|
|
19
|
+
* @returns Counts of deleted records
|
|
20
|
+
*/
|
|
21
|
+
export declare function clearOldData(params?: ClearOldDataParams): ClearOldDataResponse;
|
|
22
|
+
/**
|
|
23
|
+
* Get comprehensive database statistics
|
|
24
|
+
* Returns counts for all major tables and database health metrics
|
|
25
|
+
*
|
|
26
|
+
* @returns Complete database statistics
|
|
27
|
+
*/
|
|
28
|
+
export declare function getStats(): GetStatsResponse;
|
|
29
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/tools/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EACV,uBAAuB,EACvB,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAGjB,MAAM,aAAa,CAAC;AAErB;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,uBAAuB,CAwBzD;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,oBAAoB,CA8C9E;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,IAAI,gBAAgB,CAuD3C"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility tools for MCP Shared Context Server
|
|
3
|
+
* Database statistics, layer summaries, and manual cleanup
|
|
4
|
+
*/
|
|
5
|
+
import { getDatabase, transaction } from '../database.js';
|
|
6
|
+
/**
|
|
7
|
+
* Get summary statistics for all architecture layers
|
|
8
|
+
* Uses the layer_summary view for token efficiency
|
|
9
|
+
*
|
|
10
|
+
* @returns Layer summaries for all 5 standard layers
|
|
11
|
+
*/
|
|
12
|
+
export function getLayerSummary() {
|
|
13
|
+
const db = getDatabase();
|
|
14
|
+
try {
|
|
15
|
+
// Query the layer_summary view for all layers
|
|
16
|
+
const stmt = db.prepare(`
|
|
17
|
+
SELECT
|
|
18
|
+
layer,
|
|
19
|
+
decisions_count,
|
|
20
|
+
file_changes_count,
|
|
21
|
+
constraints_count
|
|
22
|
+
FROM layer_summary
|
|
23
|
+
ORDER BY layer
|
|
24
|
+
`);
|
|
25
|
+
const summary = stmt.all();
|
|
26
|
+
return {
|
|
27
|
+
summary,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
32
|
+
throw new Error(`Failed to get layer summary: ${message}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Clear old data from the database
|
|
37
|
+
* Deletes messages and file changes older than specified thresholds
|
|
38
|
+
* Preserves decision_history, constraints, and core decisions
|
|
39
|
+
*
|
|
40
|
+
* @param params - Optional parameters for cleanup thresholds
|
|
41
|
+
* @returns Counts of deleted records
|
|
42
|
+
*/
|
|
43
|
+
export function clearOldData(params) {
|
|
44
|
+
const db = getDatabase();
|
|
45
|
+
// Default thresholds
|
|
46
|
+
const messagesHours = params?.messages_older_than_hours ?? 24;
|
|
47
|
+
const fileChangesDays = params?.file_changes_older_than_days ?? 7;
|
|
48
|
+
// Calculate Unix epoch thresholds
|
|
49
|
+
const now = Math.floor(Date.now() / 1000);
|
|
50
|
+
const messagesThreshold = now - (messagesHours * 3600);
|
|
51
|
+
const fileChangesThreshold = now - (fileChangesDays * 86400);
|
|
52
|
+
try {
|
|
53
|
+
return transaction(db, () => {
|
|
54
|
+
// Count messages to be deleted
|
|
55
|
+
const messagesCount = db.prepare('SELECT COUNT(*) as count FROM agent_messages WHERE ts < ?').get(messagesThreshold);
|
|
56
|
+
// Count file changes to be deleted
|
|
57
|
+
const fileChangesCount = db.prepare('SELECT COUNT(*) as count FROM file_changes WHERE ts < ?').get(fileChangesThreshold);
|
|
58
|
+
// Delete old messages
|
|
59
|
+
const deleteMessages = db.prepare('DELETE FROM agent_messages WHERE ts < ?');
|
|
60
|
+
deleteMessages.run(messagesThreshold);
|
|
61
|
+
// Delete old file changes
|
|
62
|
+
const deleteFileChanges = db.prepare('DELETE FROM file_changes WHERE ts < ?');
|
|
63
|
+
deleteFileChanges.run(fileChangesThreshold);
|
|
64
|
+
return {
|
|
65
|
+
success: true,
|
|
66
|
+
messages_deleted: messagesCount.count,
|
|
67
|
+
file_changes_deleted: fileChangesCount.count,
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
73
|
+
throw new Error(`Failed to clear old data: ${message}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get comprehensive database statistics
|
|
78
|
+
* Returns counts for all major tables and database health metrics
|
|
79
|
+
*
|
|
80
|
+
* @returns Complete database statistics
|
|
81
|
+
*/
|
|
82
|
+
export function getStats() {
|
|
83
|
+
const db = getDatabase();
|
|
84
|
+
try {
|
|
85
|
+
// Helper to get count from a table
|
|
86
|
+
const getCount = (table, where) => {
|
|
87
|
+
const query = where
|
|
88
|
+
? `SELECT COUNT(*) as count FROM ${table} WHERE ${where}`
|
|
89
|
+
: `SELECT COUNT(*) as count FROM ${table}`;
|
|
90
|
+
const result = db.prepare(query).get();
|
|
91
|
+
return result.count;
|
|
92
|
+
};
|
|
93
|
+
// Get all statistics
|
|
94
|
+
const agents = getCount('agents');
|
|
95
|
+
const files = getCount('files');
|
|
96
|
+
const context_keys = getCount('context_keys');
|
|
97
|
+
// Decisions (active vs total)
|
|
98
|
+
const active_decisions = getCount('decisions', 'status = 1');
|
|
99
|
+
const total_decisions = getCount('decisions');
|
|
100
|
+
// Messages
|
|
101
|
+
const messages = getCount('agent_messages');
|
|
102
|
+
// File changes
|
|
103
|
+
const file_changes = getCount('file_changes');
|
|
104
|
+
// Constraints (active vs total)
|
|
105
|
+
const active_constraints = getCount('constraints', 'active = 1');
|
|
106
|
+
const total_constraints = getCount('constraints');
|
|
107
|
+
// Metadata
|
|
108
|
+
const tags = getCount('tags');
|
|
109
|
+
const scopes = getCount('scopes');
|
|
110
|
+
const layers = getCount('layers');
|
|
111
|
+
return {
|
|
112
|
+
agents,
|
|
113
|
+
files,
|
|
114
|
+
context_keys,
|
|
115
|
+
active_decisions,
|
|
116
|
+
total_decisions,
|
|
117
|
+
messages,
|
|
118
|
+
file_changes,
|
|
119
|
+
active_constraints,
|
|
120
|
+
total_constraints,
|
|
121
|
+
tags,
|
|
122
|
+
scopes,
|
|
123
|
+
layers,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
128
|
+
throw new Error(`Failed to get database statistics: ${message}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/tools/utils.ts"],"names":[],"mappings":"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"}
|