sqlew 1.1.2 → 2.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.
Files changed (43) hide show
  1. package/CHANGELOG.md +259 -0
  2. package/MIGRATION_v2.md +538 -0
  3. package/README.md +444 -79
  4. package/assets/schema.sql +122 -36
  5. package/dist/cli.d.ts +7 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +312 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/database.d.ts.map +1 -1
  10. package/dist/database.js +18 -0
  11. package/dist/database.js.map +1 -1
  12. package/dist/index.js +373 -707
  13. package/dist/index.js.map +1 -1
  14. package/dist/migrations/add-v2.1.0-features.d.ts +29 -0
  15. package/dist/migrations/add-v2.1.0-features.d.ts.map +1 -0
  16. package/dist/migrations/add-v2.1.0-features.js +198 -0
  17. package/dist/migrations/add-v2.1.0-features.js.map +1 -0
  18. package/dist/schema.d.ts.map +1 -1
  19. package/dist/schema.js +5 -0
  20. package/dist/schema.js.map +1 -1
  21. package/dist/tools/context.d.ts +91 -1
  22. package/dist/tools/context.d.ts.map +1 -1
  23. package/dist/tools/context.js +614 -0
  24. package/dist/tools/context.js.map +1 -1
  25. package/dist/tools/files.d.ts +10 -1
  26. package/dist/tools/files.d.ts.map +1 -1
  27. package/dist/tools/files.js +98 -1
  28. package/dist/tools/files.js.map +1 -1
  29. package/dist/tools/messaging.d.ts +10 -1
  30. package/dist/tools/messaging.d.ts.map +1 -1
  31. package/dist/tools/messaging.js +107 -1
  32. package/dist/tools/messaging.js.map +1 -1
  33. package/dist/tools/utils.d.ts +9 -1
  34. package/dist/tools/utils.d.ts.map +1 -1
  35. package/dist/tools/utils.js +115 -0
  36. package/dist/tools/utils.js.map +1 -1
  37. package/dist/types.d.ts +196 -0
  38. package/dist/types.d.ts.map +1 -1
  39. package/dist/utils/cleanup.d.ts +12 -1
  40. package/dist/utils/cleanup.d.ts.map +1 -1
  41. package/dist/utils/cleanup.js +20 -3
  42. package/dist/utils/cleanup.js.map +1 -1
  43. package/package.json +6 -3
package/assets/schema.sql CHANGED
@@ -1,63 +1,63 @@
1
1
  -- MCP Shared Context Server - Database Schema
2
- -- Version: 1.1.0 (with configurable weekend-aware auto-deletion)
2
+ -- Version: 2.1.0 (with activity log, smart defaults, batch ops, templates, CLI, subscriptions)
3
3
 
4
4
  -- ============================================================================
5
- -- マスターテーブル群(正規化)
5
+ -- Master Tables (Normalization)
6
6
  -- ============================================================================
7
7
 
8
- -- エージェント管理
8
+ -- Agent Management
9
9
  CREATE TABLE IF NOT EXISTS m_agents (
10
10
  id INTEGER PRIMARY KEY AUTOINCREMENT,
11
11
  name TEXT UNIQUE NOT NULL
12
12
  );
13
13
 
14
- -- ファイルパス管理
14
+ -- File Path Management
15
15
  CREATE TABLE IF NOT EXISTS m_files (
16
16
  id INTEGER PRIMARY KEY AUTOINCREMENT,
17
17
  path TEXT UNIQUE NOT NULL
18
18
  );
19
19
 
20
- -- コンテキストキー管理
20
+ -- Context Key Management
21
21
  CREATE TABLE IF NOT EXISTS m_context_keys (
22
22
  id INTEGER PRIMARY KEY AUTOINCREMENT,
23
23
  key TEXT UNIQUE NOT NULL
24
24
  );
25
25
 
26
- -- 制約カテゴリ管理
26
+ -- Constraint Category Management
27
27
  CREATE TABLE IF NOT EXISTS m_constraint_categories (
28
28
  id INTEGER PRIMARY KEY AUTOINCREMENT,
29
29
  name TEXT UNIQUE NOT NULL
30
30
  );
31
31
 
32
- -- レイヤー管理
32
+ -- Layer Management
33
33
  CREATE TABLE IF NOT EXISTS m_layers (
34
34
  id INTEGER PRIMARY KEY AUTOINCREMENT,
35
35
  name TEXT UNIQUE NOT NULL
36
36
  );
37
37
 
38
- -- タグ管理
38
+ -- Tag Management
39
39
  CREATE TABLE IF NOT EXISTS m_tags (
40
40
  id INTEGER PRIMARY KEY AUTOINCREMENT,
41
41
  name TEXT UNIQUE NOT NULL
42
42
  );
43
43
 
44
- -- スコープ管理(モジュール・コンポーネント)
44
+ -- Scope Management (Modules/Components)
45
45
  CREATE TABLE IF NOT EXISTS m_scopes (
46
46
  id INTEGER PRIMARY KEY AUTOINCREMENT,
47
47
  name TEXT UNIQUE NOT NULL
48
48
  );
49
49
 
50
- -- 設定管理(サーバー設定)
50
+ -- Configuration Management (Server Settings)
51
51
  CREATE TABLE IF NOT EXISTS m_config (
52
52
  key TEXT PRIMARY KEY,
53
53
  value TEXT NOT NULL
54
54
  );
55
55
 
56
56
  -- ============================================================================
57
- -- トランザクションテーブル群
57
+ -- Transaction Tables
58
58
  -- ============================================================================
59
59
 
60
- -- 決定事項(文字列値)
60
+ -- Decisions (String Values)
61
61
  CREATE TABLE IF NOT EXISTS t_decisions (
62
62
  key_id INTEGER PRIMARY KEY REFERENCES m_context_keys(id),
63
63
  value TEXT NOT NULL,
@@ -68,7 +68,7 @@ CREATE TABLE IF NOT EXISTS t_decisions (
68
68
  ts INTEGER DEFAULT (unixepoch())
69
69
  );
70
70
 
71
- -- 決定事項(数値)
71
+ -- Decisions (Numeric Values)
72
72
  CREATE TABLE IF NOT EXISTS t_decisions_numeric (
73
73
  key_id INTEGER PRIMARY KEY REFERENCES m_context_keys(id),
74
74
  value REAL NOT NULL,
@@ -79,7 +79,7 @@ CREATE TABLE IF NOT EXISTS t_decisions_numeric (
79
79
  ts INTEGER DEFAULT (unixepoch())
80
80
  );
81
81
 
82
- -- 決定事項のバージョン履歴
82
+ -- Decision Version History
83
83
  CREATE TABLE IF NOT EXISTS t_decision_history (
84
84
  id INTEGER PRIMARY KEY AUTOINCREMENT,
85
85
  key_id INTEGER REFERENCES m_context_keys(id),
@@ -89,33 +89,33 @@ CREATE TABLE IF NOT EXISTS t_decision_history (
89
89
  ts INTEGER NOT NULL
90
90
  );
91
91
 
92
- -- 決定事項へのタグ付け(多対多)
92
+ -- Decision Tagging (Many-to-Many)
93
93
  CREATE TABLE IF NOT EXISTS t_decision_tags (
94
94
  decision_key_id INTEGER REFERENCES m_context_keys(id),
95
95
  tag_id INTEGER REFERENCES m_tags(id),
96
96
  PRIMARY KEY (decision_key_id, tag_id)
97
97
  );
98
98
 
99
- -- 決定事項のスコープ(多対多)
99
+ -- Decision Scopes (Many-to-Many)
100
100
  CREATE TABLE IF NOT EXISTS t_decision_scopes (
101
101
  decision_key_id INTEGER REFERENCES m_context_keys(id),
102
102
  scope_id INTEGER REFERENCES m_scopes(id),
103
103
  PRIMARY KEY (decision_key_id, scope_id)
104
104
  );
105
105
 
106
- -- エージェント間メッセージ
106
+ -- Inter-Agent Messages
107
107
  CREATE TABLE IF NOT EXISTS t_agent_messages (
108
108
  id INTEGER PRIMARY KEY AUTOINCREMENT,
109
109
  from_agent_id INTEGER NOT NULL REFERENCES m_agents(id),
110
110
  to_agent_id INTEGER REFERENCES m_agents(id), -- NULL = broadcast
111
111
  msg_type INTEGER NOT NULL, -- 1=decision, 2=warning, 3=request, 4=info
112
112
  priority INTEGER DEFAULT 2, -- 1=low, 2=medium, 3=high, 4=critical
113
- payload TEXT, -- JSON文字列(必要な場合のみ)
113
+ payload TEXT, -- JSON string (only when needed)
114
114
  ts INTEGER DEFAULT (unixepoch()),
115
115
  read INTEGER DEFAULT 0
116
116
  );
117
117
 
118
- -- ファイル変更履歴
118
+ -- File Change History
119
119
  CREATE TABLE IF NOT EXISTS t_file_changes (
120
120
  id INTEGER PRIMARY KEY AUTOINCREMENT,
121
121
  file_id INTEGER NOT NULL REFERENCES m_files(id),
@@ -126,7 +126,7 @@ CREATE TABLE IF NOT EXISTS t_file_changes (
126
126
  ts INTEGER DEFAULT (unixepoch())
127
127
  );
128
128
 
129
- -- 制約・要件
129
+ -- Constraints/Requirements
130
130
  CREATE TABLE IF NOT EXISTS t_constraints (
131
131
  id INTEGER PRIMARY KEY AUTOINCREMENT,
132
132
  category_id INTEGER NOT NULL REFERENCES m_constraint_categories(id),
@@ -138,15 +138,36 @@ CREATE TABLE IF NOT EXISTS t_constraints (
138
138
  ts INTEGER DEFAULT (unixepoch())
139
139
  );
140
140
 
141
- -- 制約へのタグ付け(多対多)
141
+ -- Constraint Tagging (Many-to-Many)
142
142
  CREATE TABLE IF NOT EXISTS t_constraint_tags (
143
143
  constraint_id INTEGER REFERENCES t_constraints(id),
144
144
  tag_id INTEGER REFERENCES m_tags(id),
145
145
  PRIMARY KEY (constraint_id, tag_id)
146
146
  );
147
147
 
148
+ -- Activity Log (v2.1.0 - FR-001)
149
+ CREATE TABLE IF NOT EXISTS t_activity_log (
150
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
151
+ ts INTEGER DEFAULT (unixepoch()),
152
+ agent_id INTEGER NOT NULL REFERENCES m_agents(id),
153
+ action_type TEXT NOT NULL, -- 'decision_set', 'decision_update', 'message_send', 'file_record'
154
+ target TEXT NOT NULL, -- key name, message id, file path, etc.
155
+ layer_id INTEGER REFERENCES m_layers(id),
156
+ details TEXT -- JSON string with additional details
157
+ );
158
+
159
+ -- Decision Templates (v2.1.0 - FR-006)
160
+ CREATE TABLE IF NOT EXISTS t_decision_templates (
161
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
162
+ name TEXT UNIQUE NOT NULL,
163
+ defaults TEXT NOT NULL, -- JSON: {layer, status, tags, priority}
164
+ required_fields TEXT, -- JSON array: ["cve_id", "severity"]
165
+ created_by INTEGER REFERENCES m_agents(id),
166
+ ts INTEGER DEFAULT (unixepoch())
167
+ );
168
+
148
169
  -- ============================================================================
149
- -- インデックス
170
+ -- Indexes
150
171
  -- ============================================================================
151
172
 
152
173
  CREATE INDEX IF NOT EXISTS idx_decisions_ts ON t_decisions(ts DESC);
@@ -162,12 +183,15 @@ CREATE INDEX IF NOT EXISTS idx_constraints_active ON t_constraints(active, categ
162
183
  CREATE INDEX IF NOT EXISTS idx_constraints_priority ON t_constraints(priority DESC);
163
184
  CREATE INDEX IF NOT EXISTS idx_decision_tags_tag ON t_decision_tags(tag_id);
164
185
  CREATE INDEX IF NOT EXISTS idx_decision_scopes_scope ON t_decision_scopes(scope_id);
186
+ CREATE INDEX IF NOT EXISTS idx_activity_log_ts ON t_activity_log(ts DESC);
187
+ CREATE INDEX IF NOT EXISTS idx_activity_log_agent ON t_activity_log(agent_id);
188
+ CREATE INDEX IF NOT EXISTS idx_activity_log_action ON t_activity_log(action_type);
165
189
 
166
190
  -- ============================================================================
167
- -- ビュー(トークン効率化)
191
+ -- Views (Token Efficiency)
168
192
  -- ============================================================================
169
193
 
170
- -- タグ付き決定事項(最も効率的なビュー)
194
+ -- Tagged Decisions (Most Efficient View)
171
195
  CREATE VIEW IF NOT EXISTS v_tagged_decisions AS
172
196
  SELECT
173
197
  k.key,
@@ -188,7 +212,7 @@ JOIN m_context_keys k ON d.key_id = k.id
188
212
  LEFT JOIN m_layers l ON d.layer_id = l.id
189
213
  LEFT JOIN m_agents a ON d.agent_id = a.id;
190
214
 
191
- -- アクティブなコンテキスト(直近1時間、アクティブのみ)
215
+ -- Active Context (Last Hour, Active Only)
192
216
  CREATE VIEW IF NOT EXISTS v_active_context AS
193
217
  SELECT
194
218
  k.key,
@@ -204,7 +228,7 @@ LEFT JOIN m_agents a ON d.agent_id = a.id
204
228
  WHERE d.status = 1 AND d.ts > unixepoch() - 3600
205
229
  ORDER BY d.ts DESC;
206
230
 
207
- -- レイヤー別サマリー
231
+ -- Layer Summary
208
232
  CREATE VIEW IF NOT EXISTS v_layer_summary AS
209
233
  SELECT
210
234
  l.name as layer,
@@ -217,7 +241,7 @@ LEFT JOIN t_file_changes fc ON l.id = fc.layer_id AND fc.ts > unixepoch() - 3600
217
241
  LEFT JOIN t_constraints c ON l.id = c.layer_id AND c.active = 1
218
242
  GROUP BY l.id;
219
243
 
220
- -- 優先度別未読メッセージ
244
+ -- Unread Messages by Priority
221
245
  CREATE VIEW IF NOT EXISTS v_unread_messages_by_priority AS
222
246
  SELECT
223
247
  a.name as agent,
@@ -229,7 +253,7 @@ WHERE m.read = 0
229
253
  GROUP BY m.to_agent_id, m.priority
230
254
  ORDER BY m.priority DESC;
231
255
 
232
- -- 最近のファイル変更(レイヤー付き)
256
+ -- Recent File Changes (With Layer)
233
257
  CREATE VIEW IF NOT EXISTS v_recent_file_changes AS
234
258
  SELECT
235
259
  f.path,
@@ -245,7 +269,7 @@ LEFT JOIN m_layers l ON fc.layer_id = l.id
245
269
  WHERE fc.ts > unixepoch() - 3600
246
270
  ORDER BY fc.ts DESC;
247
271
 
248
- -- タグ付き制約
272
+ -- Tagged Constraints
249
273
  CREATE VIEW IF NOT EXISTS v_tagged_constraints AS
250
274
  SELECT
251
275
  c.id,
@@ -266,10 +290,10 @@ WHERE c.active = 1
266
290
  ORDER BY c.priority DESC, cc.name, c.ts DESC;
267
291
 
268
292
  -- ============================================================================
269
- -- トリガー(自動処理)
293
+ -- Triggers (Automatic Processing)
270
294
  -- ============================================================================
271
295
 
272
- -- バージョン履歴の自動記録
296
+ -- Automatic Version History Recording
273
297
  CREATE TRIGGER IF NOT EXISTS trg_record_decision_history
274
298
  AFTER UPDATE ON t_decisions
275
299
  WHEN OLD.value != NEW.value OR OLD.version != NEW.version
@@ -278,11 +302,65 @@ BEGIN
278
302
  VALUES (OLD.key_id, OLD.version, OLD.value, OLD.agent_id, OLD.ts);
279
303
  END;
280
304
 
305
+ -- Activity Log Recording Triggers (v2.1.0 - FR-001)
306
+ -- Decision Addition Log
307
+ CREATE TRIGGER IF NOT EXISTS trg_log_decision_set
308
+ AFTER INSERT ON t_decisions
309
+ BEGIN
310
+ INSERT INTO t_activity_log (agent_id, action_type, target, layer_id, details)
311
+ SELECT
312
+ COALESCE(NEW.agent_id, (SELECT id FROM m_agents WHERE name = 'system' LIMIT 1)),
313
+ 'decision_set',
314
+ (SELECT key FROM m_context_keys WHERE id = NEW.key_id),
315
+ NEW.layer_id,
316
+ json_object('value', NEW.value, 'version', NEW.version, 'status', NEW.status);
317
+ END;
318
+
319
+ -- Decision Update Log
320
+ CREATE TRIGGER IF NOT EXISTS trg_log_decision_update
321
+ AFTER UPDATE ON t_decisions
322
+ WHEN OLD.value != NEW.value OR OLD.version != NEW.version OR OLD.status != NEW.status
323
+ BEGIN
324
+ INSERT INTO t_activity_log (agent_id, action_type, target, layer_id, details)
325
+ SELECT
326
+ COALESCE(NEW.agent_id, (SELECT id FROM m_agents WHERE name = 'system' LIMIT 1)),
327
+ 'decision_update',
328
+ (SELECT key FROM m_context_keys WHERE id = NEW.key_id),
329
+ NEW.layer_id,
330
+ json_object('old_value', OLD.value, 'new_value', NEW.value, 'old_version', OLD.version, 'new_version', NEW.version, 'old_status', OLD.status, 'new_status', NEW.status);
331
+ END;
332
+
333
+ -- Message Send Log
334
+ CREATE TRIGGER IF NOT EXISTS trg_log_message_send
335
+ AFTER INSERT ON t_agent_messages
336
+ BEGIN
337
+ INSERT INTO t_activity_log (agent_id, action_type, target, layer_id, details)
338
+ SELECT
339
+ NEW.from_agent_id,
340
+ 'message_send',
341
+ 'msg_id:' || NEW.id,
342
+ NULL,
343
+ json_object('to_agent_id', NEW.to_agent_id, 'msg_type', NEW.msg_type, 'priority', NEW.priority);
344
+ END;
345
+
346
+ -- File Change Log
347
+ CREATE TRIGGER IF NOT EXISTS trg_log_file_record
348
+ AFTER INSERT ON t_file_changes
349
+ BEGIN
350
+ INSERT INTO t_activity_log (agent_id, action_type, target, layer_id, details)
351
+ SELECT
352
+ NEW.agent_id,
353
+ 'file_record',
354
+ (SELECT path FROM m_files WHERE id = NEW.file_id),
355
+ NEW.layer_id,
356
+ json_object('change_type', NEW.change_type, 'description', NEW.description);
357
+ END;
358
+
281
359
  -- ============================================================================
282
- -- 初期データ
360
+ -- Initial Data
283
361
  -- ============================================================================
284
362
 
285
- -- 標準レイヤー
363
+ -- Standard Layers
286
364
  INSERT OR IGNORE INTO m_layers (name) VALUES
287
365
  ('presentation'),
288
366
  ('business'),
@@ -290,13 +368,13 @@ INSERT OR IGNORE INTO m_layers (name) VALUES
290
368
  ('infrastructure'),
291
369
  ('cross-cutting');
292
370
 
293
- -- 標準カテゴリ
371
+ -- Standard Categories
294
372
  INSERT OR IGNORE INTO m_constraint_categories (name) VALUES
295
373
  ('performance'),
296
374
  ('architecture'),
297
375
  ('security');
298
376
 
299
- -- よくあるタグ
377
+ -- Common Tags
300
378
  INSERT OR IGNORE INTO m_tags (name) VALUES
301
379
  ('authentication'),
302
380
  ('authorization'),
@@ -309,8 +387,16 @@ INSERT OR IGNORE INTO m_tags (name) VALUES
309
387
  ('validation'),
310
388
  ('error-handling');
311
389
 
312
- -- デフォルト設定(自動削除の設定)
390
+ -- Default Settings (Auto-deletion Configuration)
313
391
  INSERT OR IGNORE INTO m_config (key, value) VALUES
314
392
  ('autodelete_ignore_weekend', '0'),
315
393
  ('autodelete_message_hours', '24'),
316
394
  ('autodelete_file_history_days', '7');
395
+
396
+ -- Built-in Templates (Built-in Decision Templates - FR-006)
397
+ INSERT OR IGNORE INTO t_decision_templates (name, defaults, required_fields, created_by, ts) VALUES
398
+ ('breaking_change', '{"layer":"business","status":"active","tags":["breaking"]}', NULL, NULL, unixepoch()),
399
+ ('security_vulnerability', '{"layer":"infrastructure","status":"active","tags":["security","vulnerability"]}', '["cve_id","severity"]', NULL, unixepoch()),
400
+ ('performance_optimization', '{"layer":"business","status":"active","tags":["performance","optimization"]}', NULL, NULL, unixepoch()),
401
+ ('deprecation', '{"layer":"business","status":"active","tags":["deprecation"]}', NULL, NULL, unixepoch()),
402
+ ('architecture_decision', '{"layer":"infrastructure","status":"active","tags":["architecture","adr"]}', NULL, NULL, unixepoch());
package/dist/cli.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI for sqlew - Standalone query commands for mcp-sqlew
4
+ * Provides quick terminal access to decisions, messages, files, and activity logs
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;GAGG"}
package/dist/cli.js ADDED
@@ -0,0 +1,312 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI for sqlew - Standalone query commands for mcp-sqlew
4
+ * Provides quick terminal access to decisions, messages, files, and activity logs
5
+ */
6
+ import { initializeDatabase } from './database.js';
7
+ import { searchAdvanced } from './tools/context.js';
8
+ import { getMessages } from './tools/messaging.js';
9
+ import { getFileChanges } from './tools/files.js';
10
+ import { getActivityLog } from './tools/utils.js';
11
+ // ============================================================================
12
+ // Helper Functions
13
+ // ============================================================================
14
+ /**
15
+ * Parse command-line arguments into structured object
16
+ */
17
+ function parseArgs(args) {
18
+ const parsed = {};
19
+ for (let i = 0; i < args.length; i++) {
20
+ const arg = args[i];
21
+ if (arg.startsWith('--')) {
22
+ const key = arg.slice(2);
23
+ const value = args[i + 1];
24
+ if (key === 'unread') {
25
+ parsed.unread = true;
26
+ }
27
+ else if (key === 'help') {
28
+ parsed.help = true;
29
+ }
30
+ else if (value && !value.startsWith('--')) {
31
+ // Handle different key types
32
+ if (key === 'limit') {
33
+ parsed[key] = parseInt(value, 10);
34
+ }
35
+ else if (key === 'db-path') {
36
+ parsed['db-path'] = value;
37
+ }
38
+ else {
39
+ parsed[key] = value;
40
+ }
41
+ i++; // Skip the value in next iteration
42
+ }
43
+ }
44
+ else if (!parsed.command) {
45
+ parsed.command = arg;
46
+ }
47
+ else if (!parsed.subcommand) {
48
+ parsed.subcommand = arg;
49
+ }
50
+ }
51
+ return parsed;
52
+ }
53
+ /**
54
+ * Format output as JSON
55
+ */
56
+ function formatJSON(data) {
57
+ console.log(JSON.stringify(data, null, 2));
58
+ }
59
+ /**
60
+ * Format output as ASCII table
61
+ */
62
+ function formatTable(data, headers) {
63
+ if (data.length === 0) {
64
+ console.log('No results found.');
65
+ return;
66
+ }
67
+ // Calculate column widths
68
+ const widths = headers.map(h => h.length);
69
+ data.forEach(row => {
70
+ headers.forEach((header, i) => {
71
+ const value = String(row[header] || '');
72
+ widths[i] = Math.max(widths[i], Math.min(value.length, 50));
73
+ });
74
+ });
75
+ // Print header
76
+ const headerRow = headers.map((h, i) => h.padEnd(widths[i])).join(' | ');
77
+ console.log(headerRow);
78
+ console.log(headers.map((_, i) => '-'.repeat(widths[i])).join('-+-'));
79
+ // Print rows
80
+ data.forEach(row => {
81
+ const rowStr = headers.map((header, i) => {
82
+ let value = String(row[header] || '');
83
+ if (value.length > 50) {
84
+ value = value.slice(0, 47) + '...';
85
+ }
86
+ return value.padEnd(widths[i]);
87
+ }).join(' | ');
88
+ console.log(rowStr);
89
+ });
90
+ console.log(`\nTotal: ${data.length} result(s)`);
91
+ }
92
+ /**
93
+ * Show help message
94
+ */
95
+ function showHelp() {
96
+ console.log(`
97
+ sqlew CLI - Query tool for mcp-sqlew v2.1.0
98
+
99
+ USAGE:
100
+ sqlew query <subcommand> [options]
101
+
102
+ SUBCOMMANDS:
103
+ decisions Query decisions with filtering
104
+ messages Query agent messages
105
+ files Query file changes
106
+ activity Query activity log
107
+
108
+ OPTIONS:
109
+ --layer <layer> Filter by layer (presentation, business, data, infrastructure, cross-cutting)
110
+ --tags <tags> Filter by tags (comma-separated)
111
+ --since <time> Time filter (e.g., "5m", "1h", "2d", or ISO timestamp)
112
+ --unread Show only unread messages (messages only)
113
+ --priority <priority> Filter by priority (low, medium, high, critical)
114
+ --agent <agent> Filter by agent name
115
+ --actions <actions> Filter by action types (comma-separated, activity only)
116
+ --limit <number> Limit number of results
117
+ --output <format> Output format: json or table (default: json)
118
+ --db-path <path> Database file path (default: .sqlew/sqlew.db)
119
+ --help Show this help message
120
+
121
+ EXAMPLES:
122
+ # Query active decisions with breaking changes
123
+ sqlew query decisions --layer=business --tags=breaking --output=table
124
+
125
+ # Query unread high-priority messages
126
+ sqlew query messages --unread --priority=high --output=json
127
+
128
+ # Query recent file changes in last hour
129
+ sqlew query files --since=1h --output=table
130
+
131
+ # Query recent activity from all agents
132
+ sqlew query activity --since=5m --agent=* --output=json
133
+
134
+ # Query activity with specific actions
135
+ sqlew query activity --actions=decision_set,message_send --limit=20
136
+ `);
137
+ }
138
+ // ============================================================================
139
+ // Query Commands
140
+ // ============================================================================
141
+ /**
142
+ * Query decisions command
143
+ */
144
+ function queryDecisions(args) {
145
+ const outputFormat = args.output || 'json';
146
+ // Build query params
147
+ const params = {};
148
+ if (args.layer) {
149
+ params.layers = [args.layer];
150
+ }
151
+ if (args.tags) {
152
+ params.tags_any = args.tags.split(',').map(t => t.trim());
153
+ }
154
+ if (args.since) {
155
+ params.updated_after = args.since;
156
+ }
157
+ if (args.limit) {
158
+ params.limit = args.limit;
159
+ }
160
+ // Execute query
161
+ const result = searchAdvanced(params);
162
+ // Output results
163
+ if (outputFormat === 'json') {
164
+ formatJSON(result);
165
+ }
166
+ else {
167
+ formatTable(result.decisions, ['key', 'value', 'version', 'status', 'layer', 'tags', 'updated']);
168
+ }
169
+ }
170
+ /**
171
+ * Query messages command
172
+ */
173
+ function queryMessages(args) {
174
+ const outputFormat = args.output || 'json';
175
+ // Agent name is required for messages
176
+ const agentName = args.agent || 'cli';
177
+ // Build query params
178
+ const params = {
179
+ agent_name: agentName,
180
+ };
181
+ if (args.unread) {
182
+ params.unread_only = true;
183
+ }
184
+ if (args.priority) {
185
+ params.priority_filter = args.priority;
186
+ }
187
+ if (args.limit) {
188
+ params.limit = args.limit;
189
+ }
190
+ // Execute query
191
+ const result = getMessages(params);
192
+ // Output results
193
+ if (outputFormat === 'json') {
194
+ formatJSON(result);
195
+ }
196
+ else {
197
+ formatTable(result.messages, ['id', 'from_agent', 'msg_type', 'priority', 'timestamp', 'read']);
198
+ }
199
+ }
200
+ /**
201
+ * Query files command
202
+ */
203
+ function queryFiles(args) {
204
+ const outputFormat = args.output || 'json';
205
+ // Build query params
206
+ const params = {};
207
+ if (args.since) {
208
+ params.since = args.since;
209
+ }
210
+ if (args.layer) {
211
+ params.layer = args.layer;
212
+ }
213
+ if (args.agent) {
214
+ params.agent_name = args.agent;
215
+ }
216
+ if (args.limit) {
217
+ params.limit = args.limit;
218
+ }
219
+ // Execute query
220
+ const result = getFileChanges(params);
221
+ // Output results
222
+ if (outputFormat === 'json') {
223
+ formatJSON(result);
224
+ }
225
+ else {
226
+ formatTable(result.changes, ['path', 'changed_by', 'change_type', 'layer', 'changed_at']);
227
+ }
228
+ }
229
+ /**
230
+ * Query activity command
231
+ */
232
+ function queryActivity(args) {
233
+ const outputFormat = args.output || 'json';
234
+ // Build query params
235
+ const params = {};
236
+ if (args.since) {
237
+ params.since = args.since;
238
+ }
239
+ if (args.agent) {
240
+ // Support wildcard for all agents
241
+ if (args.agent === '*') {
242
+ params.agent_names = ['*'];
243
+ }
244
+ else {
245
+ params.agent_names = args.agent.split(',').map(a => a.trim());
246
+ }
247
+ }
248
+ if (args.actions) {
249
+ params.actions = args.actions.split(',').map(a => a.trim());
250
+ }
251
+ if (args.limit) {
252
+ params.limit = args.limit;
253
+ }
254
+ // Execute query
255
+ const result = getActivityLog(params);
256
+ // Output results
257
+ if (outputFormat === 'json') {
258
+ formatJSON(result);
259
+ }
260
+ else {
261
+ formatTable(result.activities, ['id', 'timestamp', 'agent', 'action', 'target', 'layer']);
262
+ }
263
+ }
264
+ // ============================================================================
265
+ // Main Entry Point
266
+ // ============================================================================
267
+ function main() {
268
+ const args = parseArgs(process.argv.slice(2));
269
+ // Show help if requested or no command
270
+ if (args.help || !args.command) {
271
+ showHelp();
272
+ process.exit(0);
273
+ }
274
+ try {
275
+ // Initialize database
276
+ const dbPath = args['db-path'];
277
+ initializeDatabase(dbPath);
278
+ // Route to appropriate command
279
+ if (args.command === 'query') {
280
+ switch (args.subcommand) {
281
+ case 'decisions':
282
+ queryDecisions(args);
283
+ break;
284
+ case 'messages':
285
+ queryMessages(args);
286
+ break;
287
+ case 'files':
288
+ queryFiles(args);
289
+ break;
290
+ case 'activity':
291
+ queryActivity(args);
292
+ break;
293
+ default:
294
+ console.error(`Unknown subcommand: ${args.subcommand}`);
295
+ console.error('Run "sqlew --help" for usage information.');
296
+ process.exit(1);
297
+ }
298
+ }
299
+ else {
300
+ console.error(`Unknown command: ${args.command}`);
301
+ console.error('Run "sqlew --help" for usage information.');
302
+ process.exit(1);
303
+ }
304
+ }
305
+ catch (error) {
306
+ console.error('Error:', error instanceof Error ? error.message : String(error));
307
+ process.exit(1);
308
+ }
309
+ }
310
+ // Run main function
311
+ main();
312
+ //# sourceMappingURL=cli.js.map