proofscan 0.5.6 → 0.5.8

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.
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,MAAM,GAAG,OAAO,CAiFxE"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoBpC,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,MAAM,GAAG,OAAO,CAkbxE"}
@@ -2,7 +2,12 @@
2
2
  * Config commands
3
3
  */
4
4
  import { Command } from 'commander';
5
+ import { createInterface } from 'readline';
6
+ import { readFile } from 'fs/promises';
5
7
  import { ConfigManager } from '../config/index.js';
8
+ import { readClipboard } from '../utils/clipboard.js';
9
+ import { parseConnectorJson, toConnector, findDuplicates, findInternalDuplicates, } from '../config/add.js';
10
+ import { SnapshotManager, formatSnapshotLine, formatConfigDiff, } from '../config/snapshot.js';
6
11
  import { output, outputSuccess, outputError, maskSecretsInObject, getOutputOptions } from '../utils/output.js';
7
12
  export function createConfigCommand(getConfigPath) {
8
13
  const cmd = new Command('config')
@@ -38,17 +43,40 @@ export function createConfigCommand(getConfigPath) {
38
43
  });
39
44
  cmd
40
45
  .command('show')
41
- .description('Show current config (secrets masked)')
42
- .action(async () => {
46
+ .description('Show current config or a snapshot (secrets masked)')
47
+ .argument('[number]', 'Snapshot number to show (from ls)')
48
+ .action(async (num) => {
43
49
  try {
44
50
  const manager = new ConfigManager(getConfigPath());
45
- const config = await manager.load();
46
- const masked = maskSecretsInObject(config);
47
- if (getOutputOptions().json) {
48
- output(masked);
51
+ if (num) {
52
+ // Show snapshot
53
+ const snapshots = new SnapshotManager(manager.getConfigDir());
54
+ const snapshot = await snapshots.getByNumber(parseInt(num, 10));
55
+ if (!snapshot) {
56
+ outputError(`Snapshot #${num} not found`);
57
+ process.exit(1);
58
+ }
59
+ const masked = maskSecretsInObject(snapshot.config);
60
+ if (getOutputOptions().json) {
61
+ output({ snapshot: snapshot.meta, config: masked });
62
+ }
63
+ else {
64
+ console.log(`Snapshot #${num}: ${snapshot.meta.note || '(no note)'}`);
65
+ console.log(`Created: ${snapshot.meta.created_at}`);
66
+ console.log();
67
+ console.log(JSON.stringify(masked, null, 2));
68
+ }
49
69
  }
50
70
  else {
51
- console.log(JSON.stringify(masked, null, 2));
71
+ // Show current config
72
+ const config = await manager.load();
73
+ const masked = maskSecretsInObject(config);
74
+ if (getOutputOptions().json) {
75
+ output(masked);
76
+ }
77
+ else {
78
+ console.log(JSON.stringify(masked, null, 2));
79
+ }
52
80
  }
53
81
  }
54
82
  catch (error) {
@@ -76,6 +104,371 @@ export function createConfigCommand(getConfigPath) {
76
104
  process.exit(1);
77
105
  }
78
106
  });
107
+ // ============================================================
108
+ // config add - add connectors from JSON
109
+ // ============================================================
110
+ cmd
111
+ .command('add')
112
+ .description('Add connectors from MCP server JSON (Claude Desktop, mcp.so, or array)')
113
+ .addHelpText('after', `
114
+ Supported JSON formats:
115
+ Claude Desktop: { "mcpServers": { "<id>": { "command": "...", ... } } }
116
+ Single object: { "id": "...", "command": "...", "args": [...], "env": {...} }
117
+ Array: [ { "id": "...", "command": "...", ... }, ... ]
118
+
119
+ Examples:
120
+ pfscan config add --clip # Read from clipboard
121
+ pfscan config add --clip --dry-run # Preview clipboard content
122
+ pfscan config add --file mcp.json # Read from file
123
+ pfscan config add # Paste JSON interactively
124
+ cat mcp.json | pfscan config add # Pipe from stdin
125
+ `)
126
+ .option('--clip', 'Read JSON from system clipboard')
127
+ .option('--file <path>', 'Read JSON from file')
128
+ .option('--overwrite', 'Overwrite existing connector IDs')
129
+ .option('--dry-run', 'Parse and show what would be added, without writing')
130
+ .action(async (options) => {
131
+ try {
132
+ const manager = new ConfigManager(getConfigPath());
133
+ // Read input: --clip > --file > stdin/interactive
134
+ let jsonInput;
135
+ if (options.clip) {
136
+ try {
137
+ jsonInput = readClipboard();
138
+ if (!jsonInput || jsonInput.trim().length === 0) {
139
+ outputError('Clipboard is empty\nHint: Use --file <path> or pipe JSON via stdin.');
140
+ process.exit(1);
141
+ }
142
+ }
143
+ catch (error) {
144
+ outputError('Failed to read clipboard', error instanceof Error ? error : undefined);
145
+ process.exit(1);
146
+ }
147
+ }
148
+ else if (options.file) {
149
+ try {
150
+ jsonInput = await readFile(options.file, 'utf-8');
151
+ }
152
+ catch (error) {
153
+ outputError(`Failed to read file: ${options.file}`, error instanceof Error ? error : undefined);
154
+ process.exit(1);
155
+ }
156
+ }
157
+ else {
158
+ jsonInput = await readStdinJson();
159
+ }
160
+ // Parse JSON
161
+ const parseResult = parseConnectorJson(jsonInput);
162
+ if (!parseResult.success || parseResult.connectors.length === 0) {
163
+ if (parseResult.errors.length > 0) {
164
+ outputError('Failed to parse JSON', new Error(parseResult.errors.join('\n')));
165
+ }
166
+ else {
167
+ outputError('No connectors found in JSON');
168
+ }
169
+ process.exit(1);
170
+ }
171
+ // Check for internal duplicates
172
+ const internalDups = findInternalDuplicates(parseResult.connectors);
173
+ if (internalDups.length > 0) {
174
+ outputError(`Duplicate IDs in input: ${internalDups.join(', ')}`);
175
+ process.exit(1);
176
+ }
177
+ // Load existing config
178
+ const config = await manager.loadOrDefault();
179
+ // Check for duplicates with existing connectors
180
+ const duplicates = findDuplicates(parseResult.connectors, config.connectors);
181
+ // Handle duplicates
182
+ if (duplicates.length > 0 && !options.overwrite && !options.dryRun) {
183
+ outputError(`Connector IDs already exist: ${duplicates.join(', ')}\n` +
184
+ 'Use --overwrite to update them, or --dry-run to preview.');
185
+ process.exit(1);
186
+ }
187
+ // Prepare result
188
+ const result = {
189
+ added: [],
190
+ updated: [],
191
+ skipped: [],
192
+ duplicates,
193
+ };
194
+ // Process connectors
195
+ const existingIds = new Set(config.connectors.map(c => c.id));
196
+ for (const parsed of parseResult.connectors) {
197
+ if (existingIds.has(parsed.id)) {
198
+ if (options.overwrite) {
199
+ // Update existing
200
+ const index = config.connectors.findIndex(c => c.id === parsed.id);
201
+ config.connectors[index] = toConnector(parsed);
202
+ result.updated.push(parsed.id);
203
+ }
204
+ else {
205
+ result.skipped.push(parsed.id);
206
+ }
207
+ }
208
+ else {
209
+ // Add new
210
+ config.connectors.push(toConnector(parsed));
211
+ result.added.push(parsed.id);
212
+ }
213
+ }
214
+ // Output summary
215
+ const summary = formatAddSummary(parseResult.connectors, result, options.dryRun);
216
+ if (getOutputOptions().json) {
217
+ output({
218
+ dry_run: options.dryRun || false,
219
+ parsed_count: parseResult.connectors.length,
220
+ added: result.added,
221
+ updated: result.updated,
222
+ skipped: result.skipped,
223
+ });
224
+ }
225
+ else {
226
+ console.log(summary);
227
+ }
228
+ // Save if not dry-run
229
+ if (!options.dryRun && (result.added.length > 0 || result.updated.length > 0)) {
230
+ await manager.save(config);
231
+ outputSuccess('Config updated');
232
+ }
233
+ else if (options.dryRun) {
234
+ console.log('\n(dry-run: no changes written)');
235
+ }
236
+ }
237
+ catch (error) {
238
+ outputError('Failed to add connectors', error instanceof Error ? error : undefined);
239
+ process.exit(1);
240
+ }
241
+ });
242
+ // ============================================================
243
+ // config save - save snapshot
244
+ // ============================================================
245
+ cmd
246
+ .command('save')
247
+ .description('Save a snapshot of the current config')
248
+ .option('--note <text>', 'Add a note to the snapshot')
249
+ .action(async (options) => {
250
+ try {
251
+ const manager = new ConfigManager(getConfigPath());
252
+ const config = await manager.load();
253
+ const snapshots = new SnapshotManager(manager.getConfigDir());
254
+ const meta = await snapshots.save(config, options.note);
255
+ if (getOutputOptions().json) {
256
+ output(meta);
257
+ }
258
+ else {
259
+ outputSuccess(`Snapshot saved: ${meta.id}`);
260
+ if (meta.note) {
261
+ console.log(` Note: "${meta.note}"`);
262
+ }
263
+ console.log(` Connectors: ${meta.connector_count}`);
264
+ }
265
+ }
266
+ catch (error) {
267
+ outputError('Failed to save snapshot', error instanceof Error ? error : undefined);
268
+ process.exit(1);
269
+ }
270
+ });
271
+ // ============================================================
272
+ // config ls - list snapshots
273
+ // ============================================================
274
+ cmd
275
+ .command('ls')
276
+ .description('List saved config snapshots')
277
+ .action(async () => {
278
+ try {
279
+ const manager = new ConfigManager(getConfigPath());
280
+ const snapshots = new SnapshotManager(manager.getConfigDir());
281
+ const list = await snapshots.list();
282
+ if (list.length === 0) {
283
+ console.log('No snapshots saved.');
284
+ console.log('Use `pfscan config save` to create one.');
285
+ return;
286
+ }
287
+ // Find which snapshot matches current config
288
+ let currentMatch = null;
289
+ try {
290
+ const config = await manager.load();
291
+ currentMatch = await snapshots.findMatchingSnapshot(config);
292
+ }
293
+ catch {
294
+ // Config might not exist
295
+ }
296
+ if (getOutputOptions().json) {
297
+ output({
298
+ snapshots: list,
299
+ current_match: currentMatch,
300
+ });
301
+ }
302
+ else {
303
+ console.log('Snapshots (newest first):');
304
+ console.log();
305
+ for (let i = 0; i < list.length; i++) {
306
+ const isCurrent = currentMatch === i + 1;
307
+ console.log(formatSnapshotLine(i + 1, list[i], isCurrent));
308
+ }
309
+ }
310
+ }
311
+ catch (error) {
312
+ outputError('Failed to list snapshots', error instanceof Error ? error : undefined);
313
+ process.exit(1);
314
+ }
315
+ });
316
+ // ============================================================
317
+ // config load - load snapshot
318
+ // ============================================================
319
+ cmd
320
+ .command('load')
321
+ .description('Load a saved snapshot (dry-run by default)')
322
+ .argument('<number>', 'Snapshot number to load (from ls)')
323
+ .option('--force', 'Actually replace current config')
324
+ .action(async (num, options) => {
325
+ try {
326
+ const manager = new ConfigManager(getConfigPath());
327
+ const snapshots = new SnapshotManager(manager.getConfigDir());
328
+ const snapshotNum = parseInt(num, 10);
329
+ const snapshot = await snapshots.getByNumber(snapshotNum);
330
+ if (!snapshot) {
331
+ outputError(`Snapshot #${num} not found`);
332
+ process.exit(1);
333
+ }
334
+ // Load current config for diff
335
+ let currentConfig;
336
+ try {
337
+ currentConfig = await manager.load();
338
+ }
339
+ catch {
340
+ currentConfig = { version: 1, connectors: [] };
341
+ }
342
+ const diff = snapshots.diffConfigs(currentConfig, snapshot.config);
343
+ if (getOutputOptions().json) {
344
+ output({
345
+ dry_run: !options.force,
346
+ snapshot: snapshot.meta,
347
+ diff,
348
+ });
349
+ }
350
+ else {
351
+ console.log(`Snapshot #${num}: ${snapshot.meta.note || '(no note)'}`);
352
+ console.log(`Created: ${snapshot.meta.created_at}`);
353
+ console.log();
354
+ console.log('Changes:');
355
+ console.log(formatConfigDiff(diff));
356
+ }
357
+ if (options.force) {
358
+ await manager.save(snapshot.config);
359
+ outputSuccess('Config replaced with snapshot');
360
+ }
361
+ else {
362
+ console.log();
363
+ console.log('(dry-run: use --force to apply)');
364
+ }
365
+ }
366
+ catch (error) {
367
+ outputError('Failed to load snapshot', error instanceof Error ? error : undefined);
368
+ process.exit(1);
369
+ }
370
+ });
371
+ // ============================================================
372
+ // config delete - delete snapshot
373
+ // ============================================================
374
+ cmd
375
+ .command('delete')
376
+ .description('Delete a saved snapshot (dry-run by default)')
377
+ .argument('<number>', 'Snapshot number to delete (from ls)')
378
+ .option('--force', 'Actually delete the snapshot')
379
+ .action(async (num, options) => {
380
+ try {
381
+ const manager = new ConfigManager(getConfigPath());
382
+ const snapshots = new SnapshotManager(manager.getConfigDir());
383
+ const snapshotNum = parseInt(num, 10);
384
+ const snapshot = await snapshots.getByNumber(snapshotNum);
385
+ if (!snapshot) {
386
+ outputError(`Snapshot #${num} not found`);
387
+ process.exit(1);
388
+ }
389
+ if (getOutputOptions().json) {
390
+ output({
391
+ dry_run: !options.force,
392
+ snapshot: snapshot.meta,
393
+ });
394
+ }
395
+ else {
396
+ console.log(`Snapshot #${num}: ${snapshot.meta.note || '(no note)'}`);
397
+ console.log(`Created: ${snapshot.meta.created_at}`);
398
+ console.log(`Connectors: ${snapshot.meta.connector_count}`);
399
+ }
400
+ if (options.force) {
401
+ await snapshots.delete(snapshotNum);
402
+ outputSuccess('Snapshot deleted');
403
+ }
404
+ else {
405
+ console.log();
406
+ console.log('(dry-run: use --force to delete)');
407
+ }
408
+ }
409
+ catch (error) {
410
+ outputError('Failed to delete snapshot', error instanceof Error ? error : undefined);
411
+ process.exit(1);
412
+ }
413
+ });
79
414
  return cmd;
80
415
  }
416
+ // ============================================================
417
+ // Helper functions
418
+ // ============================================================
419
+ /**
420
+ * Read JSON from stdin interactively
421
+ */
422
+ async function readStdinJson() {
423
+ // Check if stdin is a TTY (interactive)
424
+ if (process.stdin.isTTY) {
425
+ console.log('Paste MCP server configuration (JSON), then press Ctrl+D:');
426
+ }
427
+ return new Promise((resolve, reject) => {
428
+ const chunks = [];
429
+ const rl = createInterface({
430
+ input: process.stdin,
431
+ terminal: false,
432
+ });
433
+ rl.on('line', (line) => {
434
+ chunks.push(line);
435
+ });
436
+ rl.on('close', () => {
437
+ const content = chunks.join('\n').trim();
438
+ if (content.length === 0) {
439
+ reject(new Error('No input received'));
440
+ }
441
+ else {
442
+ resolve(content);
443
+ }
444
+ });
445
+ rl.on('error', reject);
446
+ });
447
+ }
448
+ /**
449
+ * Format summary for add operation
450
+ */
451
+ function formatAddSummary(parsed, result, dryRun) {
452
+ const lines = [];
453
+ const action = dryRun ? 'Would' : 'Will';
454
+ lines.push(`Parsed ${parsed.length} connector(s)`);
455
+ lines.push('');
456
+ // Show connector list with masked env
457
+ for (const p of parsed) {
458
+ const envInfo = p.env ? ` (${Object.keys(p.env).length} env vars)` : '';
459
+ const argsInfo = p.args ? ` [${p.args.length} args]` : '';
460
+ lines.push(` ${p.id}: ${p.command}${argsInfo}${envInfo}`);
461
+ }
462
+ lines.push('');
463
+ if (result.added.length > 0) {
464
+ lines.push(`${action} add: ${result.added.join(', ')}`);
465
+ }
466
+ if (result.updated.length > 0) {
467
+ lines.push(`${action} update: ${result.updated.join(', ')}`);
468
+ }
469
+ if (result.skipped.length > 0) {
470
+ lines.push(`Skipped (already exists): ${result.skipped.join(', ')}`);
471
+ }
472
+ return lines.join('\n');
473
+ }
81
474
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Config add - parse and normalize MCP server JSON from various sources
3
+ *
4
+ * Supports:
5
+ * - Claude Desktop format: { "mcpServers": { "<id>": { "command": "...", ... } } }
6
+ * - Single object: { "id": "...", "command": "...", ... }
7
+ * - Array: [ { "id": "...", "command": "...", ... }, ... ]
8
+ */
9
+ import type { Connector } from '../types/index.js';
10
+ /** Parsed connector from JSON input */
11
+ export interface ParsedConnector {
12
+ id: string;
13
+ command: string;
14
+ args?: string[];
15
+ env?: Record<string, string>;
16
+ }
17
+ /** Result of parsing JSON input */
18
+ export interface ParseResult {
19
+ success: boolean;
20
+ connectors: ParsedConnector[];
21
+ errors: string[];
22
+ }
23
+ /** Result of add operation */
24
+ export interface AddResult {
25
+ added: string[];
26
+ updated: string[];
27
+ skipped: string[];
28
+ duplicates: string[];
29
+ }
30
+ /**
31
+ * Parse and normalize JSON input to connector list
32
+ */
33
+ export declare function parseConnectorJson(jsonString: string): ParseResult;
34
+ /**
35
+ * Convert ParsedConnector to Connector type
36
+ */
37
+ export declare function toConnector(parsed: ParsedConnector): Connector;
38
+ /**
39
+ * Check for duplicates between parsed connectors and existing ones
40
+ */
41
+ export declare function findDuplicates(parsed: ParsedConnector[], existing: Connector[]): string[];
42
+ /**
43
+ * Check for duplicates within parsed connectors
44
+ */
45
+ export declare function findInternalDuplicates(parsed: ParsedConnector[]): string[];
46
+ //# sourceMappingURL=add.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/config/add.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAkB,MAAM,mBAAmB,CAAC;AAMnE,uCAAuC;AACvC,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,mCAAmC;AACnC,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,8BAA8B;AAC9B,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAwHD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW,CAsClE;AAMD;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,CAmB9D;AAMD;;GAEG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,eAAe,EAAE,EACzB,QAAQ,EAAE,SAAS,EAAE,GACpB,MAAM,EAAE,CAGV;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,EAAE,CAe1E"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Config add - parse and normalize MCP server JSON from various sources
3
+ *
4
+ * Supports:
5
+ * - Claude Desktop format: { "mcpServers": { "<id>": { "command": "...", ... } } }
6
+ * - Single object: { "id": "...", "command": "...", ... }
7
+ * - Array: [ { "id": "...", "command": "...", ... }, ... ]
8
+ */
9
+ // ============================================================
10
+ // JSON Parsing
11
+ // ============================================================
12
+ /**
13
+ * Check if value is a non-empty string
14
+ */
15
+ function isNonEmptyString(value) {
16
+ return typeof value === 'string' && value.trim().length > 0;
17
+ }
18
+ /**
19
+ * Check if value is a string array
20
+ */
21
+ function isStringArray(value) {
22
+ return Array.isArray(value) && value.every(v => typeof v === 'string');
23
+ }
24
+ /**
25
+ * Check if value is a string-to-string object
26
+ */
27
+ function isStringRecord(value) {
28
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
29
+ return false;
30
+ }
31
+ return Object.entries(value).every(([k, v]) => typeof k === 'string' && typeof v === 'string');
32
+ }
33
+ /**
34
+ * Validate and extract connector from a single object
35
+ */
36
+ function validateConnectorObject(obj, id) {
37
+ if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
38
+ return { connector: null, error: 'Expected an object' };
39
+ }
40
+ const record = obj;
41
+ // Get id from object or provided parameter
42
+ const connectorId = id ?? record.id;
43
+ if (!isNonEmptyString(connectorId)) {
44
+ return { connector: null, error: 'Missing or invalid "id" field' };
45
+ }
46
+ // Validate command
47
+ if (!isNonEmptyString(record.command)) {
48
+ return { connector: null, error: `Connector "${connectorId}": missing or invalid "command"` };
49
+ }
50
+ // Validate args if present
51
+ if (record.args !== undefined && !isStringArray(record.args)) {
52
+ return { connector: null, error: `Connector "${connectorId}": "args" must be an array of strings` };
53
+ }
54
+ // Validate env if present
55
+ if (record.env !== undefined && !isStringRecord(record.env)) {
56
+ return { connector: null, error: `Connector "${connectorId}": "env" must be an object with string values` };
57
+ }
58
+ return {
59
+ connector: {
60
+ id: connectorId,
61
+ command: record.command,
62
+ args: record.args,
63
+ env: record.env,
64
+ },
65
+ error: null,
66
+ };
67
+ }
68
+ /**
69
+ * Parse Claude Desktop format: { "mcpServers": { "<id>": { ... } } }
70
+ */
71
+ function parseClaudeDesktopFormat(obj) {
72
+ const mcpServers = obj.mcpServers;
73
+ if (typeof mcpServers !== 'object' || mcpServers === null || Array.isArray(mcpServers)) {
74
+ return { success: false, connectors: [], errors: ['Invalid mcpServers format'] };
75
+ }
76
+ const connectors = [];
77
+ const errors = [];
78
+ for (const [id, serverConfig] of Object.entries(mcpServers)) {
79
+ const result = validateConnectorObject(serverConfig, id);
80
+ if (result.connector) {
81
+ connectors.push(result.connector);
82
+ }
83
+ else if (result.error) {
84
+ errors.push(result.error);
85
+ }
86
+ }
87
+ return { success: errors.length === 0, connectors, errors };
88
+ }
89
+ /**
90
+ * Parse array format: [ { "id": "...", ... }, ... ]
91
+ */
92
+ function parseArrayFormat(arr) {
93
+ const connectors = [];
94
+ const errors = [];
95
+ for (let i = 0; i < arr.length; i++) {
96
+ const result = validateConnectorObject(arr[i]);
97
+ if (result.connector) {
98
+ connectors.push(result.connector);
99
+ }
100
+ else if (result.error) {
101
+ errors.push(`[${i}]: ${result.error}`);
102
+ }
103
+ }
104
+ return { success: errors.length === 0, connectors, errors };
105
+ }
106
+ /**
107
+ * Parse and normalize JSON input to connector list
108
+ */
109
+ export function parseConnectorJson(jsonString) {
110
+ // Try to parse JSON
111
+ let parsed;
112
+ try {
113
+ parsed = JSON.parse(jsonString);
114
+ }
115
+ catch (e) {
116
+ const message = e instanceof Error ? e.message : 'Unknown error';
117
+ return { success: false, connectors: [], errors: [`Invalid JSON: ${message}`] };
118
+ }
119
+ // Case A: Claude Desktop format with mcpServers
120
+ if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
121
+ const obj = parsed;
122
+ if ('mcpServers' in obj) {
123
+ return parseClaudeDesktopFormat(obj);
124
+ }
125
+ // Case B: Single object with id and command
126
+ if ('command' in obj) {
127
+ const result = validateConnectorObject(obj);
128
+ if (result.connector) {
129
+ return { success: true, connectors: [result.connector], errors: [] };
130
+ }
131
+ return { success: false, connectors: [], errors: [result.error || 'Invalid connector'] };
132
+ }
133
+ return { success: false, connectors: [], errors: ['Unrecognized JSON format'] };
134
+ }
135
+ // Case C: Array format
136
+ if (Array.isArray(parsed)) {
137
+ if (parsed.length === 0) {
138
+ return { success: false, connectors: [], errors: ['Empty array'] };
139
+ }
140
+ return parseArrayFormat(parsed);
141
+ }
142
+ return { success: false, connectors: [], errors: ['Expected object or array'] };
143
+ }
144
+ // ============================================================
145
+ // Connector Conversion
146
+ // ============================================================
147
+ /**
148
+ * Convert ParsedConnector to Connector type
149
+ */
150
+ export function toConnector(parsed) {
151
+ const transport = {
152
+ type: 'stdio',
153
+ command: parsed.command,
154
+ };
155
+ if (parsed.args && parsed.args.length > 0) {
156
+ transport.args = parsed.args;
157
+ }
158
+ if (parsed.env && Object.keys(parsed.env).length > 0) {
159
+ transport.env = parsed.env;
160
+ }
161
+ return {
162
+ id: parsed.id,
163
+ enabled: true,
164
+ transport,
165
+ };
166
+ }
167
+ // ============================================================
168
+ // Duplicate Detection
169
+ // ============================================================
170
+ /**
171
+ * Check for duplicates between parsed connectors and existing ones
172
+ */
173
+ export function findDuplicates(parsed, existing) {
174
+ const existingIds = new Set(existing.map(c => c.id));
175
+ return parsed.filter(p => existingIds.has(p.id)).map(p => p.id);
176
+ }
177
+ /**
178
+ * Check for duplicates within parsed connectors
179
+ */
180
+ export function findInternalDuplicates(parsed) {
181
+ const seen = new Set();
182
+ const duplicates = [];
183
+ for (const p of parsed) {
184
+ if (seen.has(p.id)) {
185
+ if (!duplicates.includes(p.id)) {
186
+ duplicates.push(p.id);
187
+ }
188
+ }
189
+ else {
190
+ seen.add(p.id);
191
+ }
192
+ }
193
+ return duplicates;
194
+ }
195
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/config/add.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA+BH,+DAA+D;AAC/D,eAAe;AACf,+DAA+D;AAE/D;;GAEG;AACH,SAAS,gBAAgB,CAAC,KAAc;IACtC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;AAC9D,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;AACzE,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,CAChC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ,CAC3D,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB,CAC9B,GAAY,EACZ,EAAW;IAEX,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAClE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC;IAC1D,CAAC;IAED,MAAM,MAAM,GAAG,GAA8B,CAAC;IAE9C,2CAA2C;IAC3C,MAAM,WAAW,GAAG,EAAE,IAAI,MAAM,CAAC,EAAE,CAAC;IACpC,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,EAAE,CAAC;QACnC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAAC;IACrE,CAAC;IAED,mBAAmB;IACnB,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,WAAW,iCAAiC,EAAE,CAAC;IAChG,CAAC;IAED,2BAA2B;IAC3B,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7D,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,WAAW,uCAAuC,EAAE,CAAC;IACtG,CAAC;IAED,0BAA0B;IAC1B,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5D,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,WAAW,+CAA+C,EAAE,CAAC;IAC9G,CAAC;IAED,OAAO;QACL,SAAS,EAAE;YACT,EAAE,EAAE,WAAW;YACf,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,IAAI,EAAE,MAAM,CAAC,IAA4B;YACzC,GAAG,EAAE,MAAM,CAAC,GAAyC;SACtD;QACD,KAAK,EAAE,IAAI;KACZ,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,wBAAwB,CAAC,GAA4B;IAC5D,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC;IAClC,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACvF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,2BAA2B,CAAC,EAAE,CAAC;IACnF,CAAC;IAED,MAAM,UAAU,GAAsB,EAAE,CAAC;IACzC,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,KAAK,MAAM,CAAC,EAAE,EAAE,YAAY,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5D,MAAM,MAAM,GAAG,uBAAuB,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QACzD,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACrB,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACpC,CAAC;aAAM,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;AAC9D,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,GAAc;IACtC,MAAM,UAAU,GAAsB,EAAE,CAAC;IACzC,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/C,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACrB,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACpC,CAAC;aAAM,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;AAC9D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAAkB;IACnD,oBAAoB;IACpB,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,OAAO,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QACjE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,iBAAiB,OAAO,EAAE,CAAC,EAAE,CAAC;IAClF,CAAC;IAED,gDAAgD;IAChD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5E,MAAM,GAAG,GAAG,MAAiC,CAAC;QAC9C,IAAI,YAAY,IAAI,GAAG,EAAE,CAAC;YACxB,OAAO,wBAAwB,CAAC,GAAG,CAAC,CAAC;QACvC,CAAC;QAED,4CAA4C;QAC5C,IAAI,SAAS,IAAI,GAAG,EAAE,CAAC;YACrB,MAAM,MAAM,GAAG,uBAAuB,CAAC,GAAG,CAAC,CAAC;YAC5C,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;gBACrB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;YACvE,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,KAAK,IAAI,mBAAmB,CAAC,EAAE,CAAC;QAC3F,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,0BAA0B,CAAC,EAAE,CAAC;IAClF,CAAC;IAED,uBAAuB;IACvB,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC;QACrE,CAAC;QACD,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,0BAA0B,CAAC,EAAE,CAAC;AAClF,CAAC;AAED,+DAA+D;AAC/D,uBAAuB;AACvB,+DAA+D;AAE/D;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,MAAuB;IACjD,MAAM,SAAS,GAAmB;QAChC,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC;IAEF,IAAI,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1C,SAAS,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IAC/B,CAAC;IAED,IAAI,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrD,SAAS,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;IAC7B,CAAC;IAED,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,OAAO,EAAE,IAAI;QACb,SAAS;KACV,CAAC;AACJ,CAAC;AAED,+DAA+D;AAC/D,sBAAsB;AACtB,+DAA+D;AAE/D;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAyB,EACzB,QAAqB;IAErB,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACrD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAClE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAyB;IAC9D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,UAAU,GAAa,EAAE,CAAC;IAEhC,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YACnB,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC/B,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -1,4 +1,6 @@
1
1
  export * from './schema.js';
2
2
  export * from './manager.js';
3
3
  export * from './import.js';
4
+ export * from './add.js';
5
+ export * from './snapshot.js';
4
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC"}
@@ -1,4 +1,6 @@
1
1
  export * from './schema.js';
2
2
  export * from './manager.js';
3
3
  export * from './import.js';
4
+ export * from './add.js';
5
+ export * from './snapshot.js';
4
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Config snapshot management
3
+ *
4
+ * Stores snapshots of config in state/config-snapshots/
5
+ * Maintains an index file with metadata for each snapshot.
6
+ */
7
+ import type { Config } from '../types/index.js';
8
+ /** Snapshot metadata */
9
+ export interface SnapshotMeta {
10
+ id: string;
11
+ created_at: string;
12
+ note: string | null;
13
+ file_name: string;
14
+ connector_count: number;
15
+ hash: string;
16
+ }
17
+ /** Snapshot index */
18
+ export interface SnapshotIndex {
19
+ version: 1;
20
+ snapshots: SnapshotMeta[];
21
+ }
22
+ /** Snapshot with full config */
23
+ export interface Snapshot {
24
+ meta: SnapshotMeta;
25
+ config: Config;
26
+ }
27
+ /** Diff between two configs */
28
+ export interface ConfigDiff {
29
+ added: string[];
30
+ removed: string[];
31
+ changed: string[];
32
+ unchanged: string[];
33
+ }
34
+ export declare class SnapshotManager {
35
+ private snapshotDir;
36
+ private indexPath;
37
+ constructor(configDir: string);
38
+ /**
39
+ * Ensure snapshot directory exists
40
+ */
41
+ private ensureDir;
42
+ /**
43
+ * Load snapshot index
44
+ */
45
+ loadIndex(): Promise<SnapshotIndex>;
46
+ /**
47
+ * Save snapshot index
48
+ */
49
+ private saveIndex;
50
+ /**
51
+ * Compute hash of config for comparison
52
+ */
53
+ computeHash(config: Config): string;
54
+ /**
55
+ * Generate snapshot ID from timestamp
56
+ */
57
+ private generateId;
58
+ /**
59
+ * Save a snapshot of current config
60
+ */
61
+ save(config: Config, note?: string): Promise<SnapshotMeta>;
62
+ /**
63
+ * List all snapshots (newest first)
64
+ */
65
+ list(): Promise<SnapshotMeta[]>;
66
+ /**
67
+ * Get snapshot by display number (1-indexed, newest first)
68
+ */
69
+ getByNumber(num: number): Promise<Snapshot | null>;
70
+ /**
71
+ * Delete snapshot by display number
72
+ */
73
+ delete(num: number): Promise<SnapshotMeta | null>;
74
+ /**
75
+ * Find snapshot matching current config by hash
76
+ */
77
+ findMatchingSnapshot(config: Config): Promise<number | null>;
78
+ /**
79
+ * Compare two configs and return diff
80
+ */
81
+ diffConfigs(current: Config, target: Config): ConfigDiff;
82
+ }
83
+ /**
84
+ * Format snapshot for display
85
+ */
86
+ export declare function formatSnapshotLine(num: number, meta: SnapshotMeta, isCurrent?: boolean): string;
87
+ /**
88
+ * Format config diff for display
89
+ */
90
+ export declare function formatConfigDiff(diff: ConfigDiff): string;
91
+ //# sourceMappingURL=snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../src/config/snapshot.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAOhD,wBAAwB;AACxB,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBAAqB;AACrB,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,CAAC,CAAC;IACX,SAAS,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,gCAAgC;AAChC,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,+BAA+B;AAC/B,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAMD,qBAAa,eAAe;IAC1B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,EAAE,MAAM;IAK7B;;OAEG;YACW,SAAS;IAIvB;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,aAAa,CAAC;IAazC;;OAEG;YACW,SAAS;IAKvB;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAKnC;;OAEG;IACH,OAAO,CAAC,UAAU;IAIlB;;OAEG;IACG,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IA6BhE;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAKrC;;OAEG;IACG,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAsBxD;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAqBvD;;OAEG;IACG,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAalE;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU;CAiCzD;AAMD;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,YAAY,EAClB,SAAS,GAAE,OAAe,GACzB,MAAM,CAeR;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAqBzD"}
@@ -0,0 +1,226 @@
1
+ /**
2
+ * Config snapshot management
3
+ *
4
+ * Stores snapshots of config in state/config-snapshots/
5
+ * Maintains an index file with metadata for each snapshot.
6
+ */
7
+ import { createHash } from 'crypto';
8
+ import { join } from 'path';
9
+ import { mkdir, unlink } from 'fs/promises';
10
+ import { atomicWriteFile, readFileSafe, fileExists } from '../utils/fs.js';
11
+ // ============================================================
12
+ // Snapshot Manager
13
+ // ============================================================
14
+ export class SnapshotManager {
15
+ snapshotDir;
16
+ indexPath;
17
+ constructor(configDir) {
18
+ this.snapshotDir = join(configDir, 'config-snapshots');
19
+ this.indexPath = join(this.snapshotDir, 'index.json');
20
+ }
21
+ /**
22
+ * Ensure snapshot directory exists
23
+ */
24
+ async ensureDir() {
25
+ await mkdir(this.snapshotDir, { recursive: true });
26
+ }
27
+ /**
28
+ * Load snapshot index
29
+ */
30
+ async loadIndex() {
31
+ const content = await readFileSafe(this.indexPath);
32
+ if (!content) {
33
+ return { version: 1, snapshots: [] };
34
+ }
35
+ try {
36
+ return JSON.parse(content);
37
+ }
38
+ catch {
39
+ return { version: 1, snapshots: [] };
40
+ }
41
+ }
42
+ /**
43
+ * Save snapshot index
44
+ */
45
+ async saveIndex(index) {
46
+ await this.ensureDir();
47
+ await atomicWriteFile(this.indexPath, JSON.stringify(index, null, 2) + '\n');
48
+ }
49
+ /**
50
+ * Compute hash of config for comparison
51
+ */
52
+ computeHash(config) {
53
+ const canonical = JSON.stringify(config);
54
+ return createHash('sha256').update(canonical).digest('hex').slice(0, 16);
55
+ }
56
+ /**
57
+ * Generate snapshot ID from timestamp
58
+ */
59
+ generateId() {
60
+ return new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
61
+ }
62
+ /**
63
+ * Save a snapshot of current config
64
+ */
65
+ async save(config, note) {
66
+ await this.ensureDir();
67
+ const id = this.generateId();
68
+ const hash = this.computeHash(config);
69
+ const noteSuffix = note ? `_${note.replace(/[^a-zA-Z0-9-]/g, '_').slice(0, 30)}` : '';
70
+ const fileName = `${id}${noteSuffix}.json`;
71
+ const filePath = join(this.snapshotDir, fileName);
72
+ // Save snapshot file
73
+ await atomicWriteFile(filePath, JSON.stringify(config, null, 2) + '\n');
74
+ // Update index
75
+ const index = await this.loadIndex();
76
+ const meta = {
77
+ id,
78
+ created_at: new Date().toISOString(),
79
+ note: note || null,
80
+ file_name: fileName,
81
+ connector_count: config.connectors.length,
82
+ hash,
83
+ };
84
+ index.snapshots.unshift(meta); // newest first
85
+ await this.saveIndex(index);
86
+ return meta;
87
+ }
88
+ /**
89
+ * List all snapshots (newest first)
90
+ */
91
+ async list() {
92
+ const index = await this.loadIndex();
93
+ return index.snapshots;
94
+ }
95
+ /**
96
+ * Get snapshot by display number (1-indexed, newest first)
97
+ */
98
+ async getByNumber(num) {
99
+ const index = await this.loadIndex();
100
+ if (num < 1 || num > index.snapshots.length) {
101
+ return null;
102
+ }
103
+ const meta = index.snapshots[num - 1];
104
+ const filePath = join(this.snapshotDir, meta.file_name);
105
+ const content = await readFileSafe(filePath);
106
+ if (!content) {
107
+ return null;
108
+ }
109
+ try {
110
+ const config = JSON.parse(content);
111
+ return { meta, config };
112
+ }
113
+ catch {
114
+ return null;
115
+ }
116
+ }
117
+ /**
118
+ * Delete snapshot by display number
119
+ */
120
+ async delete(num) {
121
+ const index = await this.loadIndex();
122
+ if (num < 1 || num > index.snapshots.length) {
123
+ return null;
124
+ }
125
+ const meta = index.snapshots[num - 1];
126
+ const filePath = join(this.snapshotDir, meta.file_name);
127
+ // Remove file if exists
128
+ if (await fileExists(filePath)) {
129
+ await unlink(filePath);
130
+ }
131
+ // Remove from index
132
+ index.snapshots.splice(num - 1, 1);
133
+ await this.saveIndex(index);
134
+ return meta;
135
+ }
136
+ /**
137
+ * Find snapshot matching current config by hash
138
+ */
139
+ async findMatchingSnapshot(config) {
140
+ const hash = this.computeHash(config);
141
+ const index = await this.loadIndex();
142
+ for (let i = 0; i < index.snapshots.length; i++) {
143
+ if (index.snapshots[i].hash === hash) {
144
+ return i + 1; // 1-indexed
145
+ }
146
+ }
147
+ return null;
148
+ }
149
+ /**
150
+ * Compare two configs and return diff
151
+ */
152
+ diffConfigs(current, target) {
153
+ const currentIds = new Set(current.connectors.map(c => c.id));
154
+ const targetIds = new Set(target.connectors.map(c => c.id));
155
+ const added = [];
156
+ const removed = [];
157
+ const changed = [];
158
+ const unchanged = [];
159
+ // Find removed (in current but not in target)
160
+ for (const id of currentIds) {
161
+ if (!targetIds.has(id)) {
162
+ removed.push(id);
163
+ }
164
+ }
165
+ // Find added and changed
166
+ for (const targetConn of target.connectors) {
167
+ if (!currentIds.has(targetConn.id)) {
168
+ added.push(targetConn.id);
169
+ }
170
+ else {
171
+ // Check if changed
172
+ const currentConn = current.connectors.find(c => c.id === targetConn.id);
173
+ if (JSON.stringify(currentConn) !== JSON.stringify(targetConn)) {
174
+ changed.push(targetConn.id);
175
+ }
176
+ else {
177
+ unchanged.push(targetConn.id);
178
+ }
179
+ }
180
+ }
181
+ return { added, removed, changed, unchanged };
182
+ }
183
+ }
184
+ // ============================================================
185
+ // Formatting helpers
186
+ // ============================================================
187
+ /**
188
+ * Format snapshot for display
189
+ */
190
+ export function formatSnapshotLine(num, meta, isCurrent = false) {
191
+ const date = new Date(meta.created_at);
192
+ const dateStr = date.toLocaleString('ja-JP', {
193
+ year: 'numeric',
194
+ month: '2-digit',
195
+ day: '2-digit',
196
+ hour: '2-digit',
197
+ minute: '2-digit',
198
+ });
199
+ const note = meta.note ? ` "${meta.note}"` : '';
200
+ const current = isCurrent ? ' [current]' : '';
201
+ const connectors = `${meta.connector_count} connectors`;
202
+ return ` ${num}. ${dateStr} - ${connectors}${note}${current}`;
203
+ }
204
+ /**
205
+ * Format config diff for display
206
+ */
207
+ export function formatConfigDiff(diff) {
208
+ const lines = [];
209
+ if (diff.added.length > 0) {
210
+ lines.push(` + Added: ${diff.added.join(', ')}`);
211
+ }
212
+ if (diff.removed.length > 0) {
213
+ lines.push(` - Removed: ${diff.removed.join(', ')}`);
214
+ }
215
+ if (diff.changed.length > 0) {
216
+ lines.push(` ~ Changed: ${diff.changed.join(', ')}`);
217
+ }
218
+ if (diff.unchanged.length > 0) {
219
+ lines.push(` = Unchanged: ${diff.unchanged.join(', ')}`);
220
+ }
221
+ if (lines.length === 0) {
222
+ lines.push(' No changes');
223
+ }
224
+ return lines.join('\n');
225
+ }
226
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/config/snapshot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Cross-platform clipboard reading utility
3
+ */
4
+ /**
5
+ * Read text content from system clipboard
6
+ *
7
+ * OS support:
8
+ * - Windows: PowerShell Get-Clipboard
9
+ * - macOS: pbpaste
10
+ * - Linux: wl-paste (Wayland), fallback to xclip (X11)
11
+ */
12
+ export declare function readClipboard(): string;
13
+ /**
14
+ * Check if clipboard tools are available
15
+ */
16
+ export declare function isClipboardAvailable(): boolean;
17
+ //# sourceMappingURL=clipboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../../src/utils/clipboard.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH;;;;;;;GAOG;AACH,wBAAgB,aAAa,IAAI,MAAM,CA+CtC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CA4B9C"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Cross-platform clipboard reading utility
3
+ */
4
+ import { execSync } from 'child_process';
5
+ import { platform } from 'os';
6
+ /**
7
+ * Read text content from system clipboard
8
+ *
9
+ * OS support:
10
+ * - Windows: PowerShell Get-Clipboard
11
+ * - macOS: pbpaste
12
+ * - Linux: wl-paste (Wayland), fallback to xclip (X11)
13
+ */
14
+ export function readClipboard() {
15
+ const os = platform();
16
+ try {
17
+ let command;
18
+ switch (os) {
19
+ case 'win32':
20
+ // Windows: PowerShell Get-Clipboard
21
+ command = 'powershell.exe -NoProfile -Command "Get-Clipboard -Raw"';
22
+ break;
23
+ case 'darwin':
24
+ // macOS: pbpaste
25
+ command = 'pbpaste';
26
+ break;
27
+ case 'linux':
28
+ // Linux: try wl-paste (Wayland) first, fallback to xclip (X11)
29
+ try {
30
+ return execSync('wl-paste --no-newline 2>/dev/null', {
31
+ encoding: 'utf-8',
32
+ stdio: ['pipe', 'pipe', 'pipe'],
33
+ });
34
+ }
35
+ catch {
36
+ // Fallback to xclip
37
+ command = 'xclip -selection clipboard -o';
38
+ }
39
+ break;
40
+ default:
41
+ throw new Error(`Unsupported platform: ${os}`);
42
+ }
43
+ const content = execSync(command, {
44
+ encoding: 'utf-8',
45
+ stdio: ['pipe', 'pipe', 'pipe'],
46
+ });
47
+ return content;
48
+ }
49
+ catch (error) {
50
+ const message = error instanceof Error ? error.message : 'Unknown error';
51
+ throw new Error(`Failed to read clipboard: ${message}\n` +
52
+ 'Hint: Use --file <path> or pipe JSON via stdin instead.');
53
+ }
54
+ }
55
+ /**
56
+ * Check if clipboard tools are available
57
+ */
58
+ export function isClipboardAvailable() {
59
+ const os = platform();
60
+ try {
61
+ switch (os) {
62
+ case 'win32':
63
+ execSync('powershell.exe -NoProfile -Command "exit 0"', { stdio: 'pipe' });
64
+ return true;
65
+ case 'darwin':
66
+ execSync('which pbpaste', { stdio: 'pipe' });
67
+ return true;
68
+ case 'linux':
69
+ try {
70
+ execSync('which wl-paste', { stdio: 'pipe' });
71
+ return true;
72
+ }
73
+ catch {
74
+ execSync('which xclip', { stdio: 'pipe' });
75
+ return true;
76
+ }
77
+ default:
78
+ return false;
79
+ }
80
+ }
81
+ catch {
82
+ return false;
83
+ }
84
+ }
85
+ //# sourceMappingURL=clipboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../src/utils/clipboard.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAE9B;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;IAEtB,IAAI,CAAC;QACH,IAAI,OAAe,CAAC;QAEpB,QAAQ,EAAE,EAAE,CAAC;YACX,KAAK,OAAO;gBACV,oCAAoC;gBACpC,OAAO,GAAG,yDAAyD,CAAC;gBACpE,MAAM;YAER,KAAK,QAAQ;gBACX,iBAAiB;gBACjB,OAAO,GAAG,SAAS,CAAC;gBACpB,MAAM;YAER,KAAK,OAAO;gBACV,+DAA+D;gBAC/D,IAAI,CAAC;oBACH,OAAO,QAAQ,CAAC,mCAAmC,EAAE;wBACnD,QAAQ,EAAE,OAAO;wBACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;qBAChC,CAAC,CAAC;gBACL,CAAC;gBAAC,MAAM,CAAC;oBACP,oBAAoB;oBACpB,OAAO,GAAG,+BAA+B,CAAC;gBAC5C,CAAC;gBACD,MAAM;YAER;gBACE,MAAM,IAAI,KAAK,CAAC,yBAAyB,EAAE,EAAE,CAAC,CAAC;QACnD,CAAC;QAED,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE;YAChC,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QACzE,MAAM,IAAI,KAAK,CACb,6BAA6B,OAAO,IAAI;YACxC,yDAAyD,CAC1D,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB;IAClC,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;IAEtB,IAAI,CAAC;QACH,QAAQ,EAAE,EAAE,CAAC;YACX,KAAK,OAAO;gBACV,QAAQ,CAAC,6CAA6C,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;gBAC3E,OAAO,IAAI,CAAC;YAEd,KAAK,QAAQ;gBACX,QAAQ,CAAC,eAAe,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;gBAC7C,OAAO,IAAI,CAAC;YAEd,KAAK,OAAO;gBACV,IAAI,CAAC;oBACH,QAAQ,CAAC,gBAAgB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;oBAC9C,OAAO,IAAI,CAAC;gBACd,CAAC;gBAAC,MAAM,CAAC;oBACP,QAAQ,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;oBAC3C,OAAO,IAAI,CAAC;gBACd,CAAC;YAEH;gBACE,OAAO,KAAK,CAAC;QACjB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "proofscan",
3
- "version": "0.5.6",
3
+ "version": "0.5.8",
4
4
  "description": "MCP Server scanner - eliminate black boxes by capturing JSON-RPC from connection to tools/list",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",