sync-agents-settings 0.3.0 → 0.4.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 (57) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +121 -22
  3. package/commands/report-schema.md +25 -0
  4. package/commands/sync-diff.md +5 -1
  5. package/commands/sync-doctor.md +43 -0
  6. package/commands/sync-instructions.md +6 -2
  7. package/commands/sync-reconcile.md +41 -0
  8. package/commands/sync-validate.md +42 -0
  9. package/commands/sync.md +6 -2
  10. package/dist/backup.d.ts +1 -1
  11. package/dist/backup.js +4 -1
  12. package/dist/backup.js.map +1 -1
  13. package/dist/cli.js +541 -54
  14. package/dist/cli.js.map +1 -1
  15. package/dist/diff.d.ts +6 -0
  16. package/dist/diff.js +7 -0
  17. package/dist/diff.js.map +1 -0
  18. package/dist/doctor.d.ts +23 -0
  19. package/dist/doctor.js +140 -0
  20. package/dist/doctor.js.map +1 -0
  21. package/dist/fix.d.ts +19 -0
  22. package/dist/fix.js +71 -0
  23. package/dist/fix.js.map +1 -0
  24. package/dist/instructions.d.ts +8 -1
  25. package/dist/instructions.js +370 -11
  26. package/dist/instructions.js.map +1 -1
  27. package/dist/oauth.d.ts +2 -0
  28. package/dist/oauth.js +7 -0
  29. package/dist/oauth.js.map +1 -0
  30. package/dist/paths.d.ts +4 -0
  31. package/dist/paths.js +5 -0
  32. package/dist/paths.js.map +1 -1
  33. package/dist/reconcile.d.ts +27 -0
  34. package/dist/reconcile.js +122 -0
  35. package/dist/reconcile.js.map +1 -0
  36. package/dist/report-parser.d.ts +81 -0
  37. package/dist/report-parser.js +129 -0
  38. package/dist/report-parser.js.map +1 -0
  39. package/dist/report-schema-renderer.d.ts +2 -0
  40. package/dist/report-schema-renderer.js +129 -0
  41. package/dist/report-schema-renderer.js.map +1 -0
  42. package/dist/report-schema-sync.d.ts +9 -0
  43. package/dist/report-schema-sync.js +28 -0
  44. package/dist/report-schema-sync.js.map +1 -0
  45. package/dist/report.d.ts +47 -0
  46. package/dist/report.js +55 -0
  47. package/dist/report.js.map +1 -0
  48. package/dist/types.d.ts +1 -1
  49. package/dist/validation.d.ts +18 -0
  50. package/dist/validation.js +62 -0
  51. package/dist/validation.js.map +1 -0
  52. package/dist/writers/codex.js +12 -2
  53. package/dist/writers/codex.js.map +1 -1
  54. package/dist/writers/kimi.d.ts +7 -0
  55. package/dist/writers/kimi.js +25 -0
  56. package/dist/writers/kimi.js.map +1 -0
  57. package/package.json +3 -2
@@ -0,0 +1,122 @@
1
+ import { createBackup, getFilesToBackup } from "./backup.js";
2
+ import { runDoctor } from "./doctor.js";
3
+ import { readClaudeMcpServers } from "./reader.js";
4
+ import { validateServersForTargets, } from "./validation.js";
5
+ import { isOAuthOnlyServer } from "./oauth.js";
6
+ import { writeToGemini } from "./writers/gemini.js";
7
+ import { writeToCodex, resolveCodexConfigPath } from "./writers/codex.js";
8
+ import { writeToOpenCode } from "./writers/opencode.js";
9
+ import { writeToKiro } from "./writers/kiro.js";
10
+ import { writeToCursor } from "./writers/cursor.js";
11
+ import { writeToKimi, resolveKimiMcpConfigPath } from "./writers/kimi.js";
12
+ export function reconcileTargets(targets, options = {}) {
13
+ let servers = readClaudeMcpServers();
14
+ if (options.skipOAuth) {
15
+ servers = servers.filter((server) => !isOAuthOnlyServer(server));
16
+ }
17
+ const validation = validateServersForTargets(servers, targets, { skipOAuth: options.skipOAuth });
18
+ if (validation.errorCount > 0) {
19
+ return {
20
+ status: "validation_failed",
21
+ validation,
22
+ syncResults: [],
23
+ };
24
+ }
25
+ const doctor = runDoctor(targets, {
26
+ skipOAuth: options.skipOAuth,
27
+ codexHome: options.codexHome,
28
+ kimiHome: options.kimiHome,
29
+ });
30
+ if (doctor.hasErrors) {
31
+ return {
32
+ status: "doctor_failed",
33
+ validation,
34
+ doctor,
35
+ syncResults: [],
36
+ };
37
+ }
38
+ if (!doctor.hasDrift) {
39
+ return {
40
+ status: "noop",
41
+ validation,
42
+ doctor,
43
+ syncResults: [],
44
+ };
45
+ }
46
+ const mapByName = new Map(servers.map((server) => [server.name, server]));
47
+ const targetsToSync = [];
48
+ const plan = new Map();
49
+ const syncResults = [];
50
+ for (const result of doctor.results) {
51
+ if (result.status !== "drift" || result.missing.length === 0)
52
+ continue;
53
+ targetsToSync.push(result.target);
54
+ const neededServers = result.missing
55
+ .map((name) => mapByName.get(name))
56
+ .filter((server) => Boolean(server));
57
+ plan.set(result.target, neededServers);
58
+ }
59
+ let backupDir;
60
+ if (!options.dryRun && !options.skipBackup && targetsToSync.length > 0) {
61
+ const codexConfigPath = resolveCodexConfigPath(options.codexHome);
62
+ const kimiConfigPath = resolveKimiMcpConfigPath(options.kimiHome);
63
+ backupDir = createBackup(getFilesToBackup(targetsToSync, codexConfigPath, kimiConfigPath));
64
+ }
65
+ for (const result of doctor.results) {
66
+ if (result.status !== "drift" || result.missing.length === 0)
67
+ continue;
68
+ const neededServers = plan.get(result.target) ?? [];
69
+ const writeResult = writeTarget(result.target, neededServers, Boolean(options.dryRun), options.codexHome, options.kimiHome);
70
+ syncResults.push({
71
+ target: result.target,
72
+ missing: result.missing,
73
+ added: writeResult.added,
74
+ skipped: writeResult.skipped,
75
+ });
76
+ }
77
+ return {
78
+ status: "reconciled",
79
+ validation,
80
+ doctor,
81
+ syncResults,
82
+ backupDir,
83
+ };
84
+ }
85
+ function writeTarget(target, servers, dryRun, codexHome, kimiHome) {
86
+ if (target === "gemini") {
87
+ return writeToGemini(servers, dryRun);
88
+ }
89
+ if (target === "codex") {
90
+ const { added, skipped } = writeToCodex(servers, dryRun, codexHome);
91
+ return { added, skipped };
92
+ }
93
+ if (target === "opencode") {
94
+ return writeToOpenCode(servers, dryRun);
95
+ }
96
+ if (target === "kiro") {
97
+ return writeToKiro(servers, dryRun);
98
+ }
99
+ if (target === "kimi") {
100
+ const { added, skipped } = writeToKimi(servers, dryRun, kimiHome);
101
+ return { added, skipped };
102
+ }
103
+ return writeToCursor(servers, dryRun);
104
+ }
105
+ export function groupValidationByTarget(issues, targets) {
106
+ const grouped = {
107
+ gemini: [],
108
+ codex: [],
109
+ opencode: [],
110
+ kiro: [],
111
+ kimi: [],
112
+ cursor: [],
113
+ };
114
+ for (const target of targets) {
115
+ grouped[target] ??= [];
116
+ }
117
+ for (const issue of issues) {
118
+ grouped[issue.target].push(issue);
119
+ }
120
+ return grouped;
121
+ }
122
+ //# sourceMappingURL=reconcile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../src/reconcile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ export declare const SUPPORTED_REPORT_SCHEMA_VERSION = 1;
2
+ type ParsedReport = {
3
+ schemaVersion: number;
4
+ command?: string;
5
+ [key: string]: unknown;
6
+ };
7
+ export type KnownReportCommand = "sync" | "diff" | "doctor" | "validate" | "reconcile" | "sync-instructions";
8
+ export declare const KNOWN_REPORT_COMMANDS: KnownReportCommand[];
9
+ type RequiredFieldType = "array" | "number" | "boolean" | "string";
10
+ interface RequiredFieldSpec {
11
+ field: string;
12
+ type: RequiredFieldType;
13
+ }
14
+ export interface ValidateReportV1 {
15
+ schemaVersion: 1;
16
+ command: "validate";
17
+ issues: unknown[];
18
+ errorCount: number;
19
+ warningCount: number;
20
+ [key: string]: unknown;
21
+ }
22
+ export interface DoctorReportV1 {
23
+ schemaVersion: 1;
24
+ command: "doctor";
25
+ hasDrift: boolean;
26
+ hasErrors: boolean;
27
+ [key: string]: unknown;
28
+ }
29
+ export interface SyncReportV1 {
30
+ schemaVersion: 1;
31
+ command: "sync";
32
+ targets: unknown[];
33
+ [key: string]: unknown;
34
+ }
35
+ export interface DiffReportV1 {
36
+ schemaVersion: 1;
37
+ command: "diff";
38
+ targets: unknown[];
39
+ sourceNames: string[];
40
+ [key: string]: unknown;
41
+ }
42
+ export interface ReconcileReportV1 {
43
+ schemaVersion: 1;
44
+ command: "reconcile";
45
+ status: string;
46
+ syncResults: unknown[];
47
+ [key: string]: unknown;
48
+ }
49
+ export interface SyncInstructionsReportV1 {
50
+ schemaVersion: 1;
51
+ command: "sync-instructions";
52
+ unsupportedGlobalTargets: string[];
53
+ [key: string]: unknown;
54
+ }
55
+ export type KnownJsonReport = ValidateReportV1 | DoctorReportV1 | SyncReportV1 | DiffReportV1 | ReconcileReportV1 | SyncInstructionsReportV1;
56
+ type ParseErrorCode = "INVALID_JSON" | "MISSING_SCHEMA_VERSION" | "UNSUPPORTED_SCHEMA_VERSION" | "INVALID_COMMAND_PAYLOAD" | "UNKNOWN_COMMAND";
57
+ export type ParseJsonReportResult = {
58
+ ok: true;
59
+ data: ParsedReport;
60
+ } | {
61
+ ok: false;
62
+ error: {
63
+ code: ParseErrorCode;
64
+ message: string;
65
+ };
66
+ };
67
+ export type ParseKnownJsonReportResult = {
68
+ ok: true;
69
+ data: KnownJsonReport;
70
+ } | {
71
+ ok: false;
72
+ error: {
73
+ code: ParseErrorCode;
74
+ message: string;
75
+ };
76
+ };
77
+ export declare function parseJsonReport(raw: string): ParseJsonReportResult;
78
+ export declare function parseKnownJsonReport(raw: string): ParseKnownJsonReportResult;
79
+ export declare const COMMAND_REQUIRED_FIELDS: Record<KnownReportCommand, RequiredFieldSpec[]>;
80
+ export declare const COMMAND_PAYLOAD_VALIDATORS: Record<KnownReportCommand, (report: ParsedReport) => boolean>;
81
+ export {};
@@ -0,0 +1,129 @@
1
+ export const SUPPORTED_REPORT_SCHEMA_VERSION = 1;
2
+ export const KNOWN_REPORT_COMMANDS = [
3
+ "sync",
4
+ "diff",
5
+ "doctor",
6
+ "validate",
7
+ "reconcile",
8
+ "sync-instructions",
9
+ ];
10
+ export function parseJsonReport(raw) {
11
+ let parsed;
12
+ try {
13
+ parsed = JSON.parse(raw);
14
+ }
15
+ catch {
16
+ return {
17
+ ok: false,
18
+ error: {
19
+ code: "INVALID_JSON",
20
+ message: "Input is not valid JSON.",
21
+ },
22
+ };
23
+ }
24
+ if (!parsed || typeof parsed !== "object") {
25
+ return {
26
+ ok: false,
27
+ error: {
28
+ code: "MISSING_SCHEMA_VERSION",
29
+ message: "Report must be a JSON object with schemaVersion.",
30
+ },
31
+ };
32
+ }
33
+ const schemaVersion = parsed.schemaVersion;
34
+ if (typeof schemaVersion !== "number") {
35
+ return {
36
+ ok: false,
37
+ error: {
38
+ code: "MISSING_SCHEMA_VERSION",
39
+ message: "schemaVersion is required.",
40
+ },
41
+ };
42
+ }
43
+ if (schemaVersion !== SUPPORTED_REPORT_SCHEMA_VERSION) {
44
+ return {
45
+ ok: false,
46
+ error: {
47
+ code: "UNSUPPORTED_SCHEMA_VERSION",
48
+ message: `Unsupported schemaVersion ${schemaVersion}. Expected ${SUPPORTED_REPORT_SCHEMA_VERSION}.`,
49
+ },
50
+ };
51
+ }
52
+ const report = parsed;
53
+ if (!isValidCommandPayload(report)) {
54
+ return {
55
+ ok: false,
56
+ error: {
57
+ code: "INVALID_COMMAND_PAYLOAD",
58
+ message: "Report payload does not match required fields for its command.",
59
+ },
60
+ };
61
+ }
62
+ return { ok: true, data: report };
63
+ }
64
+ export function parseKnownJsonReport(raw) {
65
+ const parsed = parseJsonReport(raw);
66
+ if (!parsed.ok) {
67
+ return parsed;
68
+ }
69
+ if (!isKnownReportCommand(parsed.data.command)) {
70
+ return {
71
+ ok: false,
72
+ error: {
73
+ code: "UNKNOWN_COMMAND",
74
+ message: `Unsupported command in report: ${String(parsed.data.command)}`,
75
+ },
76
+ };
77
+ }
78
+ return { ok: true, data: parsed.data };
79
+ }
80
+ function isValidCommandPayload(report) {
81
+ if (typeof report.command !== "string") {
82
+ return true;
83
+ }
84
+ if (isKnownReportCommand(report.command)) {
85
+ return COMMAND_PAYLOAD_VALIDATORS[report.command](report);
86
+ }
87
+ // Unknown command: keep parser forward-compatible as long as schemaVersion matches.
88
+ return true;
89
+ }
90
+ function isKnownReportCommand(value) {
91
+ return typeof value === "string" && KNOWN_REPORT_COMMANDS.includes(value);
92
+ }
93
+ export const COMMAND_REQUIRED_FIELDS = {
94
+ sync: [{ field: "targets", type: "array" }],
95
+ diff: [
96
+ { field: "targets", type: "array" },
97
+ { field: "sourceNames", type: "array" },
98
+ ],
99
+ doctor: [
100
+ { field: "hasDrift", type: "boolean" },
101
+ { field: "hasErrors", type: "boolean" },
102
+ ],
103
+ validate: [
104
+ { field: "errorCount", type: "number" },
105
+ { field: "warningCount", type: "number" },
106
+ ],
107
+ reconcile: [
108
+ { field: "status", type: "string" },
109
+ { field: "syncResults", type: "array" },
110
+ ],
111
+ "sync-instructions": [{ field: "unsupportedGlobalTargets", type: "array" }],
112
+ };
113
+ export const COMMAND_PAYLOAD_VALIDATORS = {
114
+ sync: (report) => hasRequiredFields(report, COMMAND_REQUIRED_FIELDS.sync),
115
+ diff: (report) => hasRequiredFields(report, COMMAND_REQUIRED_FIELDS.diff),
116
+ doctor: (report) => hasRequiredFields(report, COMMAND_REQUIRED_FIELDS.doctor),
117
+ validate: (report) => hasRequiredFields(report, COMMAND_REQUIRED_FIELDS.validate),
118
+ reconcile: (report) => hasRequiredFields(report, COMMAND_REQUIRED_FIELDS.reconcile),
119
+ "sync-instructions": (report) => hasRequiredFields(report, COMMAND_REQUIRED_FIELDS["sync-instructions"]),
120
+ };
121
+ function hasRequiredFields(report, specs) {
122
+ return specs.every((spec) => matchesFieldType(report[spec.field], spec.type));
123
+ }
124
+ function matchesFieldType(value, type) {
125
+ if (type === "array")
126
+ return Array.isArray(value);
127
+ return typeof value === type;
128
+ }
129
+ //# sourceMappingURL=report-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-parser.js","sourceRoot":"","sources":["../src/report-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function renderReportRequiredFieldsMarkdown(): string;
2
+ export declare function generateReportSchemaDocument(): string;
@@ -0,0 +1,129 @@
1
+ import { KNOWN_REPORT_COMMANDS, COMMAND_REQUIRED_FIELDS } from "./report-parser.js";
2
+ export function renderReportRequiredFieldsMarkdown() {
3
+ const lines = [];
4
+ lines.push("## Required Fields (Generated)");
5
+ lines.push("");
6
+ lines.push("Generated from `src/report-parser.ts` `COMMAND_REQUIRED_FIELDS`.");
7
+ lines.push("");
8
+ for (const command of KNOWN_REPORT_COMMANDS) {
9
+ lines.push(`### \`${command}\``);
10
+ const specs = COMMAND_REQUIRED_FIELDS[command];
11
+ for (const spec of specs) {
12
+ lines.push(`- \`${spec.field}\` (${spec.type})`);
13
+ }
14
+ lines.push("");
15
+ }
16
+ return lines.join("\n").trim() + "\n";
17
+ }
18
+ export function generateReportSchemaDocument() {
19
+ const sections = [
20
+ "# Report Schema",
21
+ "",
22
+ "This document defines the machine-readable JSON payloads returned by commands with `--report json`.",
23
+ "",
24
+ "## Common Contract",
25
+ "",
26
+ "- Every report payload includes `schemaVersion`.",
27
+ "- Current value: `schemaVersion: 1`.",
28
+ "- Consumers should reject unknown major schema versions.",
29
+ "- Use `src/report-parser.ts` (`parseJsonReport`) as the canonical parser helper for downstream integrations.",
30
+ "- For strict typed consumption, use `parseKnownJsonReport` + `KnownJsonReport` (discriminated union by `command`).",
31
+ "- Parser error codes:",
32
+ " - `INVALID_JSON`",
33
+ " - `MISSING_SCHEMA_VERSION`",
34
+ " - `UNSUPPORTED_SCHEMA_VERSION`",
35
+ " - `INVALID_COMMAND_PAYLOAD` (schema version is valid but required fields for the `command` payload are missing or wrong type)",
36
+ " - `UNKNOWN_COMMAND`",
37
+ "- Command payload checks are implemented via a single validator map (`COMMAND_PAYLOAD_VALIDATORS`) in `src/report-parser.ts`.",
38
+ "",
39
+ "## Commands",
40
+ "",
41
+ "### `sync --report json`",
42
+ "",
43
+ "Top-level fields:",
44
+ "- `schemaVersion: number`",
45
+ '- `command: "sync"`',
46
+ "- `sourceCount: number`",
47
+ "- `dryRun: boolean`",
48
+ "- `skipOAuth: boolean`",
49
+ "- `targets: Array<{ target, added, skipped, configPath? }>`",
50
+ "",
51
+ "### `diff --report json`",
52
+ "",
53
+ "Top-level fields:",
54
+ "- `schemaVersion: number`",
55
+ '- `command: "diff"`',
56
+ "- `sourceCount: number`",
57
+ "- `sourceNames: string[]`",
58
+ "- `targets: Array<{ target, shared, onlyInSource, onlyInTarget, note? }>`",
59
+ "",
60
+ "### `doctor --report json`",
61
+ "",
62
+ "Top-level fields:",
63
+ "- `schemaVersion: number`",
64
+ '- `command: "doctor"`',
65
+ "- `resultCount: number`",
66
+ "- `sourceCount: number`",
67
+ "- `sourceNames: string[]`",
68
+ "- `hasDrift: boolean`",
69
+ "- `hasErrors: boolean`",
70
+ "- `results: Array<{ target, status, missing, extra, note? }>`",
71
+ "",
72
+ "Exit codes:",
73
+ "- `0`: no drift",
74
+ "- `1`: drift found",
75
+ "- `2`: target parse error",
76
+ "",
77
+ "### `validate --report json`",
78
+ "",
79
+ "Top-level fields:",
80
+ "- `schemaVersion: number`",
81
+ '- `command: "validate"`',
82
+ "- `issues: Array<{ target, server, severity, code, message }>`",
83
+ "- `errorCount: number`",
84
+ "- `warningCount: number`",
85
+ "",
86
+ "Exit codes:",
87
+ "- `0`: no validation errors (warnings allowed)",
88
+ "- `2`: validation errors found",
89
+ "",
90
+ "### `reconcile --report json`",
91
+ "",
92
+ "Top-level fields:",
93
+ "- `schemaVersion: number`",
94
+ '- `command: "reconcile"`',
95
+ '- `status: "validation_failed" | "doctor_failed" | "noop" | "reconciled"`',
96
+ "- `validation: { issues, errorCount, warningCount }`",
97
+ "- `doctor?: { ...doctor payload subset }`",
98
+ "- `syncResults: Array<{ target, missing, added, skipped }>`",
99
+ "- `backupDir?: string`",
100
+ "",
101
+ "### `sync-instructions --report json`",
102
+ "",
103
+ "Top-level fields:",
104
+ "- `schemaVersion: number`",
105
+ '- `command: "sync-instructions"`',
106
+ "- `unsupportedGlobalTargets: string[]`",
107
+ "- `global?: { synced, skipped, appended }`",
108
+ "- `local?: { synced, skipped, appended }`",
109
+ "",
110
+ "Notes:",
111
+ "- To keep JSON output clean in non-dry-run mode, use `--on-conflict` and `--no-backup`.",
112
+ "- In JSON mode, the CLI uses a non-interactive conflict strategy.",
113
+ "",
114
+ "## Minimal Examples",
115
+ "",
116
+ "```json",
117
+ '{ "schemaVersion": 1, "command": "validate", "issues": [], "errorCount": 0, "warningCount": 0 }',
118
+ "```",
119
+ "",
120
+ "```json",
121
+ '{ "schemaVersion": 1, "command": "doctor", "resultCount": 1, "hasDrift": false, "hasErrors": false, "results": [] }',
122
+ "```",
123
+ "",
124
+ renderReportRequiredFieldsMarkdown().trim(),
125
+ "",
126
+ ];
127
+ return sections.join("\n").trim() + "\n";
128
+ }
129
+ //# sourceMappingURL=report-schema-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-schema-renderer.js","sourceRoot":"","sources":["../src/report-schema-renderer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ type CheckReason = "ok" | "missing" | "diff";
2
+ export interface ReportSchemaCheckResult {
3
+ upToDate: boolean;
4
+ reason: CheckReason;
5
+ generated: string;
6
+ current?: string;
7
+ }
8
+ export declare function checkReportSchemaUpToDate(targetPath: string): ReportSchemaCheckResult;
9
+ export {};
@@ -0,0 +1,28 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { generateReportSchemaDocument } from "./report-schema-renderer.js";
3
+ export function checkReportSchemaUpToDate(targetPath) {
4
+ const generated = generateReportSchemaDocument();
5
+ if (!existsSync(targetPath)) {
6
+ return {
7
+ upToDate: false,
8
+ reason: "missing",
9
+ generated,
10
+ };
11
+ }
12
+ const current = readFileSync(targetPath, "utf-8");
13
+ if (current !== generated) {
14
+ return {
15
+ upToDate: false,
16
+ reason: "diff",
17
+ generated,
18
+ current,
19
+ };
20
+ }
21
+ return {
22
+ upToDate: true,
23
+ reason: "ok",
24
+ generated,
25
+ current,
26
+ };
27
+ }
28
+ //# sourceMappingURL=report-schema-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-schema-sync.js","sourceRoot":"","sources":["../src/report-schema-sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AAW3E,MAAM,UAAU,yBAAyB,CAAC,UAAkB;IAC1D,MAAM,SAAS,GAAG,4BAA4B,EAAE,CAAC;IAEjD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO;YACL,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,SAAS;YACjB,SAAS;SACV,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAClD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO;YACL,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,MAAM;YACd,SAAS;YACT,OAAO;SACR,CAAC;IACJ,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,IAAI;QACd,MAAM,EAAE,IAAI;QACZ,SAAS;QACT,OAAO;KACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,47 @@
1
+ import type { DoctorReport } from "./doctor.js";
2
+ import type { ReconcileResult } from "./reconcile.js";
3
+ import type { ValidationReport } from "./validation.js";
4
+ import type { SyncTarget } from "./types.js";
5
+ import type { SyncInstructionsResult } from "./instructions.js";
6
+ interface SyncTargetReport {
7
+ target: SyncTarget;
8
+ added: string[];
9
+ skipped: string[];
10
+ configPath?: string;
11
+ }
12
+ interface SyncReportPayload {
13
+ schemaVersion: number;
14
+ command: "sync";
15
+ sourceCount: number;
16
+ dryRun: boolean;
17
+ skipOAuth: boolean;
18
+ targets: SyncTargetReport[];
19
+ }
20
+ interface SyncInstructionsReportPayload {
21
+ schemaVersion: number;
22
+ command: "sync-instructions";
23
+ unsupportedGlobalTargets: string[];
24
+ global?: SyncInstructionsResult;
25
+ local?: SyncInstructionsResult;
26
+ }
27
+ interface DiffTargetReport {
28
+ target: string;
29
+ shared: string[];
30
+ onlyInSource: string[];
31
+ onlyInTarget: string[];
32
+ note?: string;
33
+ }
34
+ interface DiffReportPayload {
35
+ schemaVersion: number;
36
+ command: "diff";
37
+ sourceCount: number;
38
+ sourceNames: string[];
39
+ targets: DiffTargetReport[];
40
+ }
41
+ export declare function formatReconcileReport(result: ReconcileResult): string;
42
+ export declare function formatDoctorReport(report: DoctorReport): string;
43
+ export declare function formatValidationReport(report: ValidationReport): string;
44
+ export declare function formatSyncReport(report: Omit<SyncReportPayload, "command" | "schemaVersion">): string;
45
+ export declare function formatSyncInstructionsReport(report: Omit<SyncInstructionsReportPayload, "command" | "schemaVersion">): string;
46
+ export declare function formatDiffReport(report: Omit<DiffReportPayload, "command" | "schemaVersion">): string;
47
+ export {};
package/dist/report.js ADDED
@@ -0,0 +1,55 @@
1
+ const REPORT_SCHEMA_VERSION = 1;
2
+ export function formatReconcileReport(result) {
3
+ const payload = {
4
+ schemaVersion: REPORT_SCHEMA_VERSION,
5
+ command: "reconcile",
6
+ status: result.status,
7
+ validation: result.validation,
8
+ doctor: result.doctor,
9
+ syncResults: result.syncResults,
10
+ backupDir: result.backupDir,
11
+ };
12
+ return JSON.stringify(payload, null, 2);
13
+ }
14
+ export function formatDoctorReport(report) {
15
+ const payload = {
16
+ schemaVersion: REPORT_SCHEMA_VERSION,
17
+ command: "doctor",
18
+ resultCount: report.results.length,
19
+ ...report,
20
+ };
21
+ return JSON.stringify(payload, null, 2);
22
+ }
23
+ export function formatValidationReport(report) {
24
+ const payload = {
25
+ schemaVersion: REPORT_SCHEMA_VERSION,
26
+ command: "validate",
27
+ ...report,
28
+ };
29
+ return JSON.stringify(payload, null, 2);
30
+ }
31
+ export function formatSyncReport(report) {
32
+ const payload = {
33
+ schemaVersion: REPORT_SCHEMA_VERSION,
34
+ command: "sync",
35
+ ...report,
36
+ };
37
+ return JSON.stringify(payload, null, 2);
38
+ }
39
+ export function formatSyncInstructionsReport(report) {
40
+ const payload = {
41
+ schemaVersion: REPORT_SCHEMA_VERSION,
42
+ command: "sync-instructions",
43
+ ...report,
44
+ };
45
+ return JSON.stringify(payload, null, 2);
46
+ }
47
+ export function formatDiffReport(report) {
48
+ const payload = {
49
+ schemaVersion: REPORT_SCHEMA_VERSION,
50
+ command: "diff",
51
+ ...report,
52
+ };
53
+ return JSON.stringify(payload, null, 2);
54
+ }
55
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAMA,MAAM,qBAAqB,GAAG,CAAC,CAAC;AA+DhC,MAAM,UAAU,qBAAqB,CAAC,MAAuB;IAC3D,MAAM,OAAO,GAA2B;QACtC,aAAa,EAAE,qBAAqB;QACpC,OAAO,EAAE,WAAW;QACpB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAoB;IACrD,MAAM,OAAO,GAAwB;QACnC,aAAa,EAAE,qBAAqB;QACpC,OAAO,EAAE,QAAQ;QACjB,WAAW,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM;QAClC,GAAG,MAAM;KACV,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,MAAwB;IAC7D,MAAM,OAAO,GAA4B;QACvC,aAAa,EAAE,qBAAqB;QACpC,OAAO,EAAE,UAAU;QACnB,GAAG,MAAM;KACV,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,MAA4D;IAE5D,MAAM,OAAO,GAAsB;QACjC,aAAa,EAAE,qBAAqB;QACpC,OAAO,EAAE,MAAM;QACf,GAAG,MAAM;KACV,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,MAAwE;IAExE,MAAM,OAAO,GAAkC;QAC7C,aAAa,EAAE,qBAAqB;QACpC,OAAO,EAAE,mBAAmB;QAC5B,GAAG,MAAM;KACV,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,MAA4D;IAE5D,MAAM,OAAO,GAAsB;QACjC,aAAa,EAAE,qBAAqB;QACpC,OAAO,EAAE,MAAM;QACf,GAAG,MAAM;KACV,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC1C,CAAC"}
package/dist/types.d.ts CHANGED
@@ -70,4 +70,4 @@ export interface UnifiedMcpServer {
70
70
  headers?: Record<string, string>;
71
71
  oauth?: Record<string, unknown>;
72
72
  }
73
- export type SyncTarget = "gemini" | "codex" | "opencode" | "kiro" | "cursor";
73
+ export type SyncTarget = "gemini" | "codex" | "opencode" | "kiro" | "cursor" | "kimi";
@@ -0,0 +1,18 @@
1
+ import type { SyncTarget, UnifiedMcpServer } from "./types.js";
2
+ export type ValidationSeverity = "error" | "warning";
3
+ export interface ValidationIssue {
4
+ target: SyncTarget;
5
+ server: string;
6
+ severity: ValidationSeverity;
7
+ code: "INVALID_STDIO_COMMAND_REQUIRED" | "INVALID_REMOTE_URL_REQUIRED" | "CODEX_UNSUPPORTED_HEADERS" | "OAUTH_MANUAL_SETUP_REQUIRED";
8
+ message: string;
9
+ }
10
+ export interface ValidationReport {
11
+ issues: ValidationIssue[];
12
+ errorCount: number;
13
+ warningCount: number;
14
+ }
15
+ export interface ValidationOptions {
16
+ skipOAuth?: boolean;
17
+ }
18
+ export declare function validateServersForTargets(servers: UnifiedMcpServer[], targets: SyncTarget[], options?: ValidationOptions): ValidationReport;