diffdoc 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/embed.js +12 -24
- package/dist/commands/init.js +2 -0
- package/dist/commands/status.js +17 -24
- package/dist/commands/summarize.js +11 -8
- package/dist/commands/validate.js +113 -0
- package/dist/config.js +7 -1
- package/dist/index.js +16 -0
- package/dist/schemas.js +74 -0
- package/dist/scripts/generate-schemas.js +30 -0
- package/dist/types/artifacts.js +12 -3
- package/package.json +6 -3
- package/schemas/v2/diffdocrc.schema.json +107 -0
- package/schemas/v2/manifest.schema.json +34 -0
- package/schemas/v2/summary-asset.schema.json +103 -0
package/dist/commands/embed.js
CHANGED
|
@@ -22,34 +22,22 @@ function getSummaryPath(summaryDir, hash) {
|
|
|
22
22
|
return node_path_1.default.resolve(summaryDir, `${hash}.json`);
|
|
23
23
|
}
|
|
24
24
|
async function readManifest(manifestPath) {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
const raw = JSON.parse(await promises_1.default.readFile(manifestPath, "utf8"));
|
|
26
|
+
const result = artifacts_1.RepoManifestSchema.safeParse(raw);
|
|
27
|
+
if (!result.success) {
|
|
28
|
+
const issues = result.error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
29
|
+
throw new Error(`Invalid manifest in ${manifestPath}:\n${issues}`);
|
|
28
30
|
}
|
|
29
|
-
return
|
|
30
|
-
schemaVersion: artifacts_1.MANIFEST_SCHEMA_VERSION,
|
|
31
|
-
lastSyncedCommit: typeof parsed.lastSyncedCommit === "string" ? parsed.lastSyncedCommit : "",
|
|
32
|
-
files: parsed.files && typeof parsed.files === "object" ? parsed.files : {}
|
|
33
|
-
};
|
|
31
|
+
return result.data;
|
|
34
32
|
}
|
|
35
33
|
async function readSummaryAsset(summaryPath) {
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
const raw = JSON.parse(await promises_1.default.readFile(summaryPath, "utf8"));
|
|
35
|
+
const result = artifacts_1.SummaryAssetSchema.safeParse(raw);
|
|
36
|
+
if (!result.success) {
|
|
37
|
+
const issues = result.error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
38
|
+
throw new Error(`Invalid summary asset in ${summaryPath}:\n${issues}`);
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
throw new Error(`Invalid summary hash in ${summaryPath}.`);
|
|
42
|
-
}
|
|
43
|
-
if (typeof parsed.summary !== "string") {
|
|
44
|
-
throw new Error(`Invalid summary text in ${summaryPath}.`);
|
|
45
|
-
}
|
|
46
|
-
return {
|
|
47
|
-
schemaVersion: parsed.schemaVersion,
|
|
48
|
-
content_hash: parsed.content_hash,
|
|
49
|
-
metadata: parsed.metadata && typeof parsed.metadata === "object" ? parsed.metadata : undefined,
|
|
50
|
-
summary: parsed.summary,
|
|
51
|
-
raw_code_snapshot: typeof parsed.raw_code_snapshot === "string" ? parsed.raw_code_snapshot : undefined
|
|
52
|
-
};
|
|
40
|
+
return result.data;
|
|
53
41
|
}
|
|
54
42
|
function buildDocument(summaryAsset) {
|
|
55
43
|
return summaryAsset.summary;
|
package/dist/commands/init.js
CHANGED
|
@@ -8,7 +8,9 @@ const promises_1 = __importDefault(require("node:fs/promises"));
|
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
9
|
const promises_2 = require("node:readline/promises");
|
|
10
10
|
const node_process_1 = require("node:process");
|
|
11
|
+
const schemas_1 = require("../schemas");
|
|
11
12
|
const DEFAULT_CONFIG = {
|
|
13
|
+
$schema: `${schemas_1.SCHEMA_BASE_URL}/diffdocrc.schema.json`,
|
|
12
14
|
baseDir: "./.diffdoc",
|
|
13
15
|
aiProvider: "local",
|
|
14
16
|
localLlmEndpoint: "http://localhost:11434/v1",
|
package/dist/commands/status.js
CHANGED
|
@@ -26,18 +26,12 @@ async function readManifest(manifestPath) {
|
|
|
26
26
|
}
|
|
27
27
|
throw error;
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
const result = artifacts_1.RepoManifestSchema.safeParse(parsed);
|
|
30
|
+
if (!result.success) {
|
|
31
|
+
const issues = result.error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
32
|
+
throw new Error(`Invalid manifest in ${manifestPath}:\n${issues}`);
|
|
31
33
|
}
|
|
32
|
-
|
|
33
|
-
if (manifest.schemaVersion !== artifacts_1.MANIFEST_SCHEMA_VERSION) {
|
|
34
|
-
throw new Error(`Unsupported manifest schema in ${manifestPath}. Expected schemaVersion ${artifacts_1.MANIFEST_SCHEMA_VERSION}.`);
|
|
35
|
-
}
|
|
36
|
-
return {
|
|
37
|
-
schemaVersion: artifacts_1.MANIFEST_SCHEMA_VERSION,
|
|
38
|
-
lastSyncedCommit: typeof manifest.lastSyncedCommit === "string" ? manifest.lastSyncedCommit : "",
|
|
39
|
-
files: manifest.files && typeof manifest.files === "object" ? manifest.files : {}
|
|
40
|
-
};
|
|
34
|
+
return result.data;
|
|
41
35
|
}
|
|
42
36
|
async function getSummaryStats(manifestPath, manifest) {
|
|
43
37
|
const summaryDir = getSummaryDir(manifestPath);
|
|
@@ -71,19 +65,18 @@ async function getSummaryStats(manifestPath, manifest) {
|
|
|
71
65
|
continue;
|
|
72
66
|
}
|
|
73
67
|
try {
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
metadata.
|
|
85
|
-
metadata.
|
|
86
|
-
metadata.summary_format !== llm_1.SUMMARY_FORMAT) {
|
|
68
|
+
const raw = JSON.parse(await promises_1.default.readFile(node_path_1.default.resolve(summaryDir, `${hash}.json`), "utf8"));
|
|
69
|
+
const result = artifacts_1.SummaryAssetSchema.safeParse(raw);
|
|
70
|
+
if (!result.success) {
|
|
71
|
+
staleCount += 1;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const asset = result.data;
|
|
75
|
+
if (asset.content_hash !== hash ||
|
|
76
|
+
!asset.metadata ||
|
|
77
|
+
asset.metadata.content_hash !== hash ||
|
|
78
|
+
asset.metadata.prompt_version !== llm_1.SUMMARY_PROMPT_VERSION ||
|
|
79
|
+
asset.metadata.summary_format !== llm_1.SUMMARY_FORMAT) {
|
|
87
80
|
staleCount += 1;
|
|
88
81
|
}
|
|
89
82
|
}
|
|
@@ -8,10 +8,13 @@ const promises_1 = __importDefault(require("node:fs/promises"));
|
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
9
|
const ignore_1 = __importDefault(require("ignore"));
|
|
10
10
|
const artifacts_1 = require("../types/artifacts");
|
|
11
|
+
const schemas_1 = require("../schemas");
|
|
11
12
|
const git_1 = require("../utils/git");
|
|
12
13
|
const hashing_1 = require("../utils/hashing");
|
|
13
14
|
const llm_1 = require("../utils/llm");
|
|
14
15
|
const paths_1 = require("../utils/paths");
|
|
16
|
+
const MANIFEST_SCHEMA_URL = `${schemas_1.SCHEMA_BASE_URL}/manifest.schema.json`;
|
|
17
|
+
const SUMMARY_ASSET_SCHEMA_URL = `${schemas_1.SCHEMA_BASE_URL}/summary-asset.schema.json`;
|
|
15
18
|
function normalizeRelativePath(filePath) {
|
|
16
19
|
return filePath.split(node_path_1.default.sep).join("/");
|
|
17
20
|
}
|
|
@@ -158,20 +161,19 @@ async function isSummaryAssetFresh(summaryPath, expected) {
|
|
|
158
161
|
}
|
|
159
162
|
async function readManifest(manifestPath) {
|
|
160
163
|
try {
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
+
const raw = JSON.parse(await promises_1.default.readFile(manifestPath, "utf8"));
|
|
165
|
+
const result = artifacts_1.RepoManifestSchema.safeParse(raw);
|
|
166
|
+
if (!result.success) {
|
|
167
|
+
const issues = result.error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
168
|
+
throw new Error(`Invalid manifest in ${manifestPath}:\n${issues}`);
|
|
164
169
|
}
|
|
165
|
-
return
|
|
166
|
-
schemaVersion: artifacts_1.MANIFEST_SCHEMA_VERSION,
|
|
167
|
-
lastSyncedCommit: typeof parsed.lastSyncedCommit === "string" ? parsed.lastSyncedCommit : "",
|
|
168
|
-
files: parsed.files && typeof parsed.files === "object" ? parsed.files : {}
|
|
169
|
-
};
|
|
170
|
+
return result.data;
|
|
170
171
|
}
|
|
171
172
|
catch (error) {
|
|
172
173
|
const nodeError = error;
|
|
173
174
|
if (nodeError.code === "ENOENT") {
|
|
174
175
|
return {
|
|
176
|
+
$schema: MANIFEST_SCHEMA_URL,
|
|
175
177
|
schemaVersion: artifacts_1.MANIFEST_SCHEMA_VERSION,
|
|
176
178
|
lastSyncedCommit: "",
|
|
177
179
|
files: {}
|
|
@@ -270,6 +272,7 @@ async function removeManifestPath(filePath, manifest, manifestPath, summaryDir,
|
|
|
270
272
|
async function ensureSummaryAsset(summaryDir, hash, metadata, summaryText, rawCodeSnapshot, includeCodeSnapshot) {
|
|
271
273
|
const summaryPath = getSummaryPath(summaryDir, hash);
|
|
272
274
|
const summary = {
|
|
275
|
+
$schema: SUMMARY_ASSET_SCHEMA_URL,
|
|
273
276
|
schemaVersion: artifacts_1.SUMMARY_ASSET_SCHEMA_VERSION,
|
|
274
277
|
content_hash: hash,
|
|
275
278
|
metadata,
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runValidate = runValidate;
|
|
7
|
+
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const artifacts_1 = require("../types/artifacts");
|
|
10
|
+
const paths_1 = require("../utils/paths");
|
|
11
|
+
function getSummaryDir(manifestPath) {
|
|
12
|
+
return node_path_1.default.resolve(node_path_1.default.dirname(manifestPath), "summaries");
|
|
13
|
+
}
|
|
14
|
+
async function runValidate(options, config) {
|
|
15
|
+
const manifestPath = (0, paths_1.resolveDiffdocArtifactPath)(options.manifest, config.baseDir);
|
|
16
|
+
const issues = [];
|
|
17
|
+
let manifestValid = false;
|
|
18
|
+
let summaryAssetsChecked = 0;
|
|
19
|
+
let summaryAssetsValid = 0;
|
|
20
|
+
// Validate manifest
|
|
21
|
+
let manifestData;
|
|
22
|
+
try {
|
|
23
|
+
manifestData = JSON.parse(await promises_1.default.readFile(manifestPath, "utf8"));
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
const nodeError = error;
|
|
27
|
+
if (nodeError.code === "ENOENT") {
|
|
28
|
+
issues.push({ file: manifestPath, path: "", message: "Manifest file not found." });
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
issues.push({ file: manifestPath, path: "", message: `Failed to parse JSON: ${error.message}` });
|
|
32
|
+
}
|
|
33
|
+
manifestData = undefined;
|
|
34
|
+
}
|
|
35
|
+
if (manifestData !== undefined) {
|
|
36
|
+
const result = artifacts_1.RepoManifestSchema.safeParse(manifestData);
|
|
37
|
+
if (result.success) {
|
|
38
|
+
manifestValid = true;
|
|
39
|
+
// Validate each referenced summary asset
|
|
40
|
+
const summaryDir = getSummaryDir(manifestPath);
|
|
41
|
+
const hashes = new Set(Object.values(result.data.files));
|
|
42
|
+
for (const hash of hashes) {
|
|
43
|
+
summaryAssetsChecked += 1;
|
|
44
|
+
const summaryPath = node_path_1.default.resolve(summaryDir, `${hash}.json`);
|
|
45
|
+
let summaryRaw;
|
|
46
|
+
try {
|
|
47
|
+
summaryRaw = JSON.parse(await promises_1.default.readFile(summaryPath, "utf8"));
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
const nodeError = error;
|
|
51
|
+
if (nodeError.code === "ENOENT") {
|
|
52
|
+
issues.push({ file: summaryPath, path: "", message: "Summary asset file not found." });
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
issues.push({ file: summaryPath, path: "", message: `Failed to parse JSON: ${error.message}` });
|
|
56
|
+
}
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
const assetResult = artifacts_1.SummaryAssetSchema.safeParse(summaryRaw);
|
|
60
|
+
if (assetResult.success) {
|
|
61
|
+
// Cross-check content_hash matches filename
|
|
62
|
+
if (assetResult.data.content_hash !== hash) {
|
|
63
|
+
issues.push({ file: summaryPath, path: "content_hash", message: `Expected "${hash}" but got "${assetResult.data.content_hash}".` });
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
summaryAssetsValid += 1;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
for (const issue of assetResult.error.issues) {
|
|
71
|
+
issues.push({ file: summaryPath, path: issue.path.join("."), message: issue.message });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
for (const issue of result.error.issues) {
|
|
78
|
+
issues.push({ file: manifestPath, path: issue.path.join("."), message: issue.message });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const report = {
|
|
83
|
+
valid: manifestValid && issues.length === 0,
|
|
84
|
+
manifestPath,
|
|
85
|
+
manifestValid,
|
|
86
|
+
summaryAssetsChecked,
|
|
87
|
+
summaryAssetsValid,
|
|
88
|
+
issues
|
|
89
|
+
};
|
|
90
|
+
if (options.json) {
|
|
91
|
+
console.log(JSON.stringify(report, null, 2));
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
console.log(`Manifest: ${manifestPath}`);
|
|
95
|
+
console.log(`Manifest valid: ${manifestValid ? "yes" : "NO"}`);
|
|
96
|
+
console.log(`Summary assets checked: ${summaryAssetsChecked}`);
|
|
97
|
+
console.log(`Summary assets valid: ${summaryAssetsValid}`);
|
|
98
|
+
console.log("---");
|
|
99
|
+
if (issues.length === 0) {
|
|
100
|
+
console.log("All artifacts pass schema validation.");
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
console.log(`Issues (${issues.length}):`);
|
|
104
|
+
for (const issue of issues) {
|
|
105
|
+
const location = issue.path ? `${issue.file} -> ${issue.path}` : issue.file;
|
|
106
|
+
console.log(` - ${location}: ${issue.message}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (!report.valid) {
|
|
111
|
+
process.exitCode = 1;
|
|
112
|
+
}
|
|
113
|
+
}
|
package/dist/config.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.buildRuntimeConfig = buildRuntimeConfig;
|
|
7
7
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const schemas_1 = require("./schemas");
|
|
9
10
|
function readOption(value, envName, fallback = "") {
|
|
10
11
|
return value || process.env[envName] || fallback;
|
|
11
12
|
}
|
|
@@ -56,7 +57,12 @@ function loadRcFile(configPath) {
|
|
|
56
57
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
57
58
|
throw new Error(`Config file must contain a JSON object: ${resolvedPath}`);
|
|
58
59
|
}
|
|
59
|
-
|
|
60
|
+
const result = schemas_1.DiffdocConfigSchema.safeParse(parsed);
|
|
61
|
+
if (!result.success) {
|
|
62
|
+
const issues = result.error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
63
|
+
throw new Error(`Invalid config file ${resolvedPath}:\n${issues}`);
|
|
64
|
+
}
|
|
65
|
+
return result.data;
|
|
60
66
|
}
|
|
61
67
|
function mergeConfigOptions(options) {
|
|
62
68
|
const rcOptions = loadRcFile(options.config);
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ const init_1 = require("./commands/init");
|
|
|
8
8
|
const query_1 = require("./commands/query");
|
|
9
9
|
const status_1 = require("./commands/status");
|
|
10
10
|
const summarize_1 = require("./commands/summarize");
|
|
11
|
+
const validate_1 = require("./commands/validate");
|
|
11
12
|
const program = new commander_1.Command();
|
|
12
13
|
function collectOption(value, previous) {
|
|
13
14
|
previous.push(value);
|
|
@@ -157,6 +158,21 @@ addBaseOptions(program
|
|
|
157
158
|
process.exit(1);
|
|
158
159
|
}
|
|
159
160
|
});
|
|
161
|
+
addBaseOptions(program
|
|
162
|
+
.command("validate"))
|
|
163
|
+
.description("Validate manifest and summary assets against JSON schemas")
|
|
164
|
+
.option("--manifest <path>", "manifest input path under --base-dir", "manifest.json")
|
|
165
|
+
.option("--json", "print validation report as JSON for CI", false)
|
|
166
|
+
.action(async (options) => {
|
|
167
|
+
try {
|
|
168
|
+
const config = (0, config_1.buildRuntimeConfig)(options, { embeddings: false, chat: false });
|
|
169
|
+
await (0, validate_1.runValidate)({ manifest: options.manifest, json: options.json }, config);
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
console.error(error instanceof Error ? error.message : error);
|
|
173
|
+
process.exit(1);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
160
176
|
program.parseAsync(process.argv).catch((error) => {
|
|
161
177
|
console.error(error instanceof Error ? error.message : error);
|
|
162
178
|
process.exit(1);
|
package/dist/schemas.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SummaryAssetSchema = exports.SummaryMetadataSchema = exports.RepoManifestSchema = exports.DiffdocConfigSchema = exports.SCHEMA_BASE_URL = exports.SCHEMA_DIR_VERSION = exports.SUMMARY_ASSET_SCHEMA_VERSION = exports.MANIFEST_SCHEMA_VERSION = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// Schema version constants
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
exports.MANIFEST_SCHEMA_VERSION = 2;
|
|
9
|
+
exports.SUMMARY_ASSET_SCHEMA_VERSION = 2;
|
|
10
|
+
exports.SCHEMA_DIR_VERSION = 2;
|
|
11
|
+
exports.SCHEMA_BASE_URL = `https://raw.githubusercontent.com/sullyTheDev/diffdoc/main/schemas/v${exports.SCHEMA_DIR_VERSION}`;
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Configuration schema (.diffdocrc)
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
exports.DiffdocConfigSchema = zod_1.z.object({
|
|
16
|
+
$schema: zod_1.z.string().optional(),
|
|
17
|
+
baseDir: zod_1.z.string().optional(),
|
|
18
|
+
aiProvider: zod_1.z.enum(["local", "cloud"]).optional(),
|
|
19
|
+
localLlmEndpoint: zod_1.z.string().optional(),
|
|
20
|
+
localEmbedEndpoint: zod_1.z.string().optional(),
|
|
21
|
+
localChatModel: zod_1.z.string().optional(),
|
|
22
|
+
localEmbedModel: zod_1.z.string().optional(),
|
|
23
|
+
cloudLlmEndpoint: zod_1.z.string().optional(),
|
|
24
|
+
cloudChatModel: zod_1.z.string().optional(),
|
|
25
|
+
cloudEmbedModel: zod_1.z.string().optional(),
|
|
26
|
+
embedBatchSize: zod_1.z.union([zod_1.z.number().int().positive(), zod_1.z.string()]).optional(),
|
|
27
|
+
summarizeConcurrency: zod_1.z.union([zod_1.z.number().int().positive(), zod_1.z.string()]).optional(),
|
|
28
|
+
openaiApiKey: zod_1.z.string().optional(),
|
|
29
|
+
includeGlobs: zod_1.z.union([zod_1.z.array(zod_1.z.string()), zod_1.z.string()]).optional(),
|
|
30
|
+
excludeGlobs: zod_1.z.union([zod_1.z.array(zod_1.z.string()), zod_1.z.string()]).optional(),
|
|
31
|
+
ignoreFile: zod_1.z.string().optional(),
|
|
32
|
+
summaryPrompt: zod_1.z.string().optional(),
|
|
33
|
+
summaryPromptFile: zod_1.z.string().optional()
|
|
34
|
+
}).strict();
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// Repository manifest schema
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
exports.RepoManifestSchema = zod_1.z.object({
|
|
39
|
+
$schema: zod_1.z.string().optional(),
|
|
40
|
+
schemaVersion: zod_1.z.literal(exports.MANIFEST_SCHEMA_VERSION),
|
|
41
|
+
lastSyncedCommit: zod_1.z.string(),
|
|
42
|
+
files: zod_1.z.record(zod_1.z.string(), zod_1.z.string())
|
|
43
|
+
});
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
// Summary metadata schema (nested within summary assets)
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
exports.SummaryMetadataSchema = zod_1.z.object({
|
|
48
|
+
file_path: zod_1.z.string(),
|
|
49
|
+
file_name: zod_1.z.string(),
|
|
50
|
+
extension: zod_1.z.string(),
|
|
51
|
+
line_count: zod_1.z.number().int().nonnegative(),
|
|
52
|
+
byte_size: zod_1.z.number().int().nonnegative(),
|
|
53
|
+
content_hash: zod_1.z.string(),
|
|
54
|
+
generated_at: zod_1.z.string(),
|
|
55
|
+
generator: zod_1.z.object({
|
|
56
|
+
provider: zod_1.z.string(),
|
|
57
|
+
model: zod_1.z.string()
|
|
58
|
+
}),
|
|
59
|
+
prompt_version: zod_1.z.number().int(),
|
|
60
|
+
summary_format: zod_1.z.string(),
|
|
61
|
+
custom_prompt_hash: zod_1.z.string().optional(),
|
|
62
|
+
custom_prompt_source: zod_1.z.string().optional()
|
|
63
|
+
});
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
// Summary asset schema (individual hash-named JSON files)
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
exports.SummaryAssetSchema = zod_1.z.object({
|
|
68
|
+
$schema: zod_1.z.string().optional(),
|
|
69
|
+
schemaVersion: zod_1.z.literal(exports.SUMMARY_ASSET_SCHEMA_VERSION),
|
|
70
|
+
content_hash: zod_1.z.string(),
|
|
71
|
+
metadata: exports.SummaryMetadataSchema.optional(),
|
|
72
|
+
summary: zod_1.z.string(),
|
|
73
|
+
raw_code_snapshot: zod_1.z.string().optional()
|
|
74
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const zod_to_json_schema_1 = require("zod-to-json-schema");
|
|
9
|
+
const schemas_1 = require("../schemas");
|
|
10
|
+
const schemas = [
|
|
11
|
+
{ name: "diffdocrc.schema.json", zodSchema: schemas_1.DiffdocConfigSchema },
|
|
12
|
+
{ name: "manifest.schema.json", zodSchema: schemas_1.RepoManifestSchema },
|
|
13
|
+
{ name: "summary-asset.schema.json", zodSchema: schemas_1.SummaryAssetSchema }
|
|
14
|
+
];
|
|
15
|
+
const outDir = node_path_1.default.resolve(__dirname, `../../schemas/v${schemas_1.SCHEMA_DIR_VERSION}`);
|
|
16
|
+
node_fs_1.default.mkdirSync(outDir, { recursive: true });
|
|
17
|
+
for (const entry of schemas) {
|
|
18
|
+
const jsonSchema = (0, zod_to_json_schema_1.zodToJsonSchema)(entry.zodSchema, {
|
|
19
|
+
name: entry.name.replace(".schema.json", ""),
|
|
20
|
+
$refStrategy: "none"
|
|
21
|
+
});
|
|
22
|
+
const schemaWithId = {
|
|
23
|
+
...jsonSchema,
|
|
24
|
+
$id: `${schemas_1.SCHEMA_BASE_URL}/${entry.name}`
|
|
25
|
+
};
|
|
26
|
+
const outPath = node_path_1.default.resolve(outDir, entry.name);
|
|
27
|
+
node_fs_1.default.writeFileSync(outPath, `${JSON.stringify(schemaWithId, null, 2)}\n`);
|
|
28
|
+
console.log(`Generated: ${outPath}`);
|
|
29
|
+
}
|
|
30
|
+
console.log("Schema generation complete.");
|
package/dist/types/artifacts.js
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
// Re-export all schema definitions and types from the canonical source.
|
|
3
|
+
// This file exists for backwards-compatible import paths.
|
|
2
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SUMMARY_ASSET_SCHEMA_VERSION = exports.MANIFEST_SCHEMA_VERSION = void 0;
|
|
4
|
-
|
|
5
|
-
exports.
|
|
5
|
+
exports.DiffdocConfigSchema = exports.SummaryAssetSchema = exports.SummaryMetadataSchema = exports.RepoManifestSchema = exports.SCHEMA_BASE_URL = exports.SCHEMA_DIR_VERSION = exports.SUMMARY_ASSET_SCHEMA_VERSION = exports.MANIFEST_SCHEMA_VERSION = void 0;
|
|
6
|
+
var schemas_1 = require("../schemas");
|
|
7
|
+
Object.defineProperty(exports, "MANIFEST_SCHEMA_VERSION", { enumerable: true, get: function () { return schemas_1.MANIFEST_SCHEMA_VERSION; } });
|
|
8
|
+
Object.defineProperty(exports, "SUMMARY_ASSET_SCHEMA_VERSION", { enumerable: true, get: function () { return schemas_1.SUMMARY_ASSET_SCHEMA_VERSION; } });
|
|
9
|
+
Object.defineProperty(exports, "SCHEMA_DIR_VERSION", { enumerable: true, get: function () { return schemas_1.SCHEMA_DIR_VERSION; } });
|
|
10
|
+
Object.defineProperty(exports, "SCHEMA_BASE_URL", { enumerable: true, get: function () { return schemas_1.SCHEMA_BASE_URL; } });
|
|
11
|
+
Object.defineProperty(exports, "RepoManifestSchema", { enumerable: true, get: function () { return schemas_1.RepoManifestSchema; } });
|
|
12
|
+
Object.defineProperty(exports, "SummaryMetadataSchema", { enumerable: true, get: function () { return schemas_1.SummaryMetadataSchema; } });
|
|
13
|
+
Object.defineProperty(exports, "SummaryAssetSchema", { enumerable: true, get: function () { return schemas_1.SummaryAssetSchema; } });
|
|
14
|
+
Object.defineProperty(exports, "DiffdocConfigSchema", { enumerable: true, get: function () { return schemas_1.DiffdocConfigSchema; } });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "diffdoc",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "Translate repository code shifts into plain-English business context",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Christopher Sullivan",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
22
|
"dist",
|
|
23
|
+
"schemas",
|
|
23
24
|
"README.md",
|
|
24
25
|
"LICENSE",
|
|
25
26
|
".diffdocrc.example"
|
|
@@ -28,7 +29,8 @@
|
|
|
28
29
|
"node": ">=22"
|
|
29
30
|
},
|
|
30
31
|
"scripts": {
|
|
31
|
-
"build": "tsc",
|
|
32
|
+
"build": "tsc && node dist/scripts/generate-schemas.js",
|
|
33
|
+
"generate:schemas": "node dist/scripts/generate-schemas.js",
|
|
32
34
|
"clean": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
33
35
|
"start": "tsc && node ./dist/index.js",
|
|
34
36
|
"prepare": "npm run build"
|
|
@@ -44,6 +46,7 @@
|
|
|
44
46
|
},
|
|
45
47
|
"devDependencies": {
|
|
46
48
|
"@types/node": "^20.19.41",
|
|
47
|
-
"typescript": "^5.3.3"
|
|
49
|
+
"typescript": "^5.3.3",
|
|
50
|
+
"zod-to-json-schema": "^3.25.2"
|
|
48
51
|
}
|
|
49
52
|
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$ref": "#/definitions/diffdocrc",
|
|
3
|
+
"definitions": {
|
|
4
|
+
"diffdocrc": {
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"$schema": {
|
|
8
|
+
"type": "string"
|
|
9
|
+
},
|
|
10
|
+
"baseDir": {
|
|
11
|
+
"type": "string"
|
|
12
|
+
},
|
|
13
|
+
"aiProvider": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"enum": [
|
|
16
|
+
"local",
|
|
17
|
+
"cloud"
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"localLlmEndpoint": {
|
|
21
|
+
"type": "string"
|
|
22
|
+
},
|
|
23
|
+
"localEmbedEndpoint": {
|
|
24
|
+
"type": "string"
|
|
25
|
+
},
|
|
26
|
+
"localChatModel": {
|
|
27
|
+
"type": "string"
|
|
28
|
+
},
|
|
29
|
+
"localEmbedModel": {
|
|
30
|
+
"type": "string"
|
|
31
|
+
},
|
|
32
|
+
"cloudLlmEndpoint": {
|
|
33
|
+
"type": "string"
|
|
34
|
+
},
|
|
35
|
+
"cloudChatModel": {
|
|
36
|
+
"type": "string"
|
|
37
|
+
},
|
|
38
|
+
"cloudEmbedModel": {
|
|
39
|
+
"type": "string"
|
|
40
|
+
},
|
|
41
|
+
"embedBatchSize": {
|
|
42
|
+
"anyOf": [
|
|
43
|
+
{
|
|
44
|
+
"type": "integer",
|
|
45
|
+
"exclusiveMinimum": 0
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"type": "string"
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
"summarizeConcurrency": {
|
|
53
|
+
"anyOf": [
|
|
54
|
+
{
|
|
55
|
+
"type": "integer",
|
|
56
|
+
"exclusiveMinimum": 0
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"type": "string"
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
"openaiApiKey": {
|
|
64
|
+
"type": "string"
|
|
65
|
+
},
|
|
66
|
+
"includeGlobs": {
|
|
67
|
+
"anyOf": [
|
|
68
|
+
{
|
|
69
|
+
"type": "array",
|
|
70
|
+
"items": {
|
|
71
|
+
"type": "string"
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"type": "string"
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
"excludeGlobs": {
|
|
80
|
+
"anyOf": [
|
|
81
|
+
{
|
|
82
|
+
"type": "array",
|
|
83
|
+
"items": {
|
|
84
|
+
"type": "string"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"type": "string"
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
},
|
|
92
|
+
"ignoreFile": {
|
|
93
|
+
"type": "string"
|
|
94
|
+
},
|
|
95
|
+
"summaryPrompt": {
|
|
96
|
+
"type": "string"
|
|
97
|
+
},
|
|
98
|
+
"summaryPromptFile": {
|
|
99
|
+
"type": "string"
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
"additionalProperties": false
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
106
|
+
"$id": "https://raw.githubusercontent.com/sullyTheDev/diffdoc/main/schemas/v2/diffdocrc.schema.json"
|
|
107
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$ref": "#/definitions/manifest",
|
|
3
|
+
"definitions": {
|
|
4
|
+
"manifest": {
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"$schema": {
|
|
8
|
+
"type": "string"
|
|
9
|
+
},
|
|
10
|
+
"schemaVersion": {
|
|
11
|
+
"type": "number",
|
|
12
|
+
"const": 2
|
|
13
|
+
},
|
|
14
|
+
"lastSyncedCommit": {
|
|
15
|
+
"type": "string"
|
|
16
|
+
},
|
|
17
|
+
"files": {
|
|
18
|
+
"type": "object",
|
|
19
|
+
"additionalProperties": {
|
|
20
|
+
"type": "string"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"required": [
|
|
25
|
+
"schemaVersion",
|
|
26
|
+
"lastSyncedCommit",
|
|
27
|
+
"files"
|
|
28
|
+
],
|
|
29
|
+
"additionalProperties": false
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
33
|
+
"$id": "https://raw.githubusercontent.com/sullyTheDev/diffdoc/main/schemas/v2/manifest.schema.json"
|
|
34
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$ref": "#/definitions/summary-asset",
|
|
3
|
+
"definitions": {
|
|
4
|
+
"summary-asset": {
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"$schema": {
|
|
8
|
+
"type": "string"
|
|
9
|
+
},
|
|
10
|
+
"schemaVersion": {
|
|
11
|
+
"type": "number",
|
|
12
|
+
"const": 2
|
|
13
|
+
},
|
|
14
|
+
"content_hash": {
|
|
15
|
+
"type": "string"
|
|
16
|
+
},
|
|
17
|
+
"metadata": {
|
|
18
|
+
"type": "object",
|
|
19
|
+
"properties": {
|
|
20
|
+
"file_path": {
|
|
21
|
+
"type": "string"
|
|
22
|
+
},
|
|
23
|
+
"file_name": {
|
|
24
|
+
"type": "string"
|
|
25
|
+
},
|
|
26
|
+
"extension": {
|
|
27
|
+
"type": "string"
|
|
28
|
+
},
|
|
29
|
+
"line_count": {
|
|
30
|
+
"type": "integer",
|
|
31
|
+
"minimum": 0
|
|
32
|
+
},
|
|
33
|
+
"byte_size": {
|
|
34
|
+
"type": "integer",
|
|
35
|
+
"minimum": 0
|
|
36
|
+
},
|
|
37
|
+
"content_hash": {
|
|
38
|
+
"type": "string"
|
|
39
|
+
},
|
|
40
|
+
"generated_at": {
|
|
41
|
+
"type": "string"
|
|
42
|
+
},
|
|
43
|
+
"generator": {
|
|
44
|
+
"type": "object",
|
|
45
|
+
"properties": {
|
|
46
|
+
"provider": {
|
|
47
|
+
"type": "string"
|
|
48
|
+
},
|
|
49
|
+
"model": {
|
|
50
|
+
"type": "string"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"required": [
|
|
54
|
+
"provider",
|
|
55
|
+
"model"
|
|
56
|
+
],
|
|
57
|
+
"additionalProperties": false
|
|
58
|
+
},
|
|
59
|
+
"prompt_version": {
|
|
60
|
+
"type": "integer"
|
|
61
|
+
},
|
|
62
|
+
"summary_format": {
|
|
63
|
+
"type": "string"
|
|
64
|
+
},
|
|
65
|
+
"custom_prompt_hash": {
|
|
66
|
+
"type": "string"
|
|
67
|
+
},
|
|
68
|
+
"custom_prompt_source": {
|
|
69
|
+
"type": "string"
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"required": [
|
|
73
|
+
"file_path",
|
|
74
|
+
"file_name",
|
|
75
|
+
"extension",
|
|
76
|
+
"line_count",
|
|
77
|
+
"byte_size",
|
|
78
|
+
"content_hash",
|
|
79
|
+
"generated_at",
|
|
80
|
+
"generator",
|
|
81
|
+
"prompt_version",
|
|
82
|
+
"summary_format"
|
|
83
|
+
],
|
|
84
|
+
"additionalProperties": false
|
|
85
|
+
},
|
|
86
|
+
"summary": {
|
|
87
|
+
"type": "string"
|
|
88
|
+
},
|
|
89
|
+
"raw_code_snapshot": {
|
|
90
|
+
"type": "string"
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"required": [
|
|
94
|
+
"schemaVersion",
|
|
95
|
+
"content_hash",
|
|
96
|
+
"summary"
|
|
97
|
+
],
|
|
98
|
+
"additionalProperties": false
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
102
|
+
"$id": "https://raw.githubusercontent.com/sullyTheDev/diffdoc/main/schemas/v2/summary-asset.schema.json"
|
|
103
|
+
}
|