diffdoc 0.6.0 → 0.6.1
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 +3 -0
- package/dist/commands/status.js +17 -24
- package/dist/commands/summarize.js +12 -8
- package/dist/commands/validate.js +113 -0
- package/dist/config.js +7 -1
- package/dist/index.js +16 -0
- package/dist/schemas.js +71 -0
- package/dist/scripts/generate-schemas.js +32 -0
- package/dist/types/artifacts.js +10 -3
- package/package.json +6 -3
- package/schemas/diffdocrc.schema.json +104 -0
- package/schemas/manifest.schema.json +34 -0
- package/schemas/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,10 @@ 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 SCHEMA_BASE_URL = "https://raw.githubusercontent.com/sullyTheDev/diffdoc";
|
|
12
|
+
const PKG_VERSION = require("../../package.json").version;
|
|
11
13
|
const DEFAULT_CONFIG = {
|
|
14
|
+
$schema: `${SCHEMA_BASE_URL}/v${PKG_VERSION}/schemas/diffdocrc.schema.json`,
|
|
12
15
|
baseDir: "./.diffdoc",
|
|
13
16
|
aiProvider: "local",
|
|
14
17
|
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
|
}
|
|
@@ -12,6 +12,10 @@ const git_1 = require("../utils/git");
|
|
|
12
12
|
const hashing_1 = require("../utils/hashing");
|
|
13
13
|
const llm_1 = require("../utils/llm");
|
|
14
14
|
const paths_1 = require("../utils/paths");
|
|
15
|
+
const SCHEMA_BASE_URL = "https://raw.githubusercontent.com/sullyTheDev/diffdoc";
|
|
16
|
+
const PKG_VERSION = require("../../package.json").version;
|
|
17
|
+
const MANIFEST_SCHEMA_URL = `${SCHEMA_BASE_URL}/v${PKG_VERSION}/schemas/manifest.schema.json`;
|
|
18
|
+
const SUMMARY_ASSET_SCHEMA_URL = `${SCHEMA_BASE_URL}/v${PKG_VERSION}/schemas/summary-asset.schema.json`;
|
|
15
19
|
function normalizeRelativePath(filePath) {
|
|
16
20
|
return filePath.split(node_path_1.default.sep).join("/");
|
|
17
21
|
}
|
|
@@ -158,20 +162,19 @@ async function isSummaryAssetFresh(summaryPath, expected) {
|
|
|
158
162
|
}
|
|
159
163
|
async function readManifest(manifestPath) {
|
|
160
164
|
try {
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
165
|
+
const raw = JSON.parse(await promises_1.default.readFile(manifestPath, "utf8"));
|
|
166
|
+
const result = artifacts_1.RepoManifestSchema.safeParse(raw);
|
|
167
|
+
if (!result.success) {
|
|
168
|
+
const issues = result.error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
169
|
+
throw new Error(`Invalid manifest in ${manifestPath}:\n${issues}`);
|
|
164
170
|
}
|
|
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
|
-
};
|
|
171
|
+
return result.data;
|
|
170
172
|
}
|
|
171
173
|
catch (error) {
|
|
172
174
|
const nodeError = error;
|
|
173
175
|
if (nodeError.code === "ENOENT") {
|
|
174
176
|
return {
|
|
177
|
+
$schema: MANIFEST_SCHEMA_URL,
|
|
175
178
|
schemaVersion: artifacts_1.MANIFEST_SCHEMA_VERSION,
|
|
176
179
|
lastSyncedCommit: "",
|
|
177
180
|
files: {}
|
|
@@ -270,6 +273,7 @@ async function removeManifestPath(filePath, manifest, manifestPath, summaryDir,
|
|
|
270
273
|
async function ensureSummaryAsset(summaryDir, hash, metadata, summaryText, rawCodeSnapshot, includeCodeSnapshot) {
|
|
271
274
|
const summaryPath = getSummaryPath(summaryDir, hash);
|
|
272
275
|
const summary = {
|
|
276
|
+
$schema: SUMMARY_ASSET_SCHEMA_URL,
|
|
273
277
|
schemaVersion: artifacts_1.SUMMARY_ASSET_SCHEMA_VERSION,
|
|
274
278
|
content_hash: hash,
|
|
275
279
|
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,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SummaryAssetSchema = exports.SummaryMetadataSchema = exports.RepoManifestSchema = exports.DiffdocConfigSchema = 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
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Configuration schema (.diffdocrc)
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
exports.DiffdocConfigSchema = zod_1.z.object({
|
|
14
|
+
baseDir: zod_1.z.string().optional(),
|
|
15
|
+
aiProvider: zod_1.z.enum(["local", "cloud"]).optional(),
|
|
16
|
+
localLlmEndpoint: zod_1.z.string().optional(),
|
|
17
|
+
localEmbedEndpoint: zod_1.z.string().optional(),
|
|
18
|
+
localChatModel: zod_1.z.string().optional(),
|
|
19
|
+
localEmbedModel: zod_1.z.string().optional(),
|
|
20
|
+
cloudLlmEndpoint: zod_1.z.string().optional(),
|
|
21
|
+
cloudChatModel: zod_1.z.string().optional(),
|
|
22
|
+
cloudEmbedModel: zod_1.z.string().optional(),
|
|
23
|
+
embedBatchSize: zod_1.z.union([zod_1.z.number().int().positive(), zod_1.z.string()]).optional(),
|
|
24
|
+
summarizeConcurrency: zod_1.z.union([zod_1.z.number().int().positive(), zod_1.z.string()]).optional(),
|
|
25
|
+
openaiApiKey: zod_1.z.string().optional(),
|
|
26
|
+
includeGlobs: zod_1.z.union([zod_1.z.array(zod_1.z.string()), zod_1.z.string()]).optional(),
|
|
27
|
+
excludeGlobs: zod_1.z.union([zod_1.z.array(zod_1.z.string()), zod_1.z.string()]).optional(),
|
|
28
|
+
ignoreFile: zod_1.z.string().optional(),
|
|
29
|
+
summaryPrompt: zod_1.z.string().optional(),
|
|
30
|
+
summaryPromptFile: zod_1.z.string().optional()
|
|
31
|
+
}).strict();
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Repository manifest schema
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
exports.RepoManifestSchema = zod_1.z.object({
|
|
36
|
+
$schema: zod_1.z.string().optional(),
|
|
37
|
+
schemaVersion: zod_1.z.literal(exports.MANIFEST_SCHEMA_VERSION),
|
|
38
|
+
lastSyncedCommit: zod_1.z.string(),
|
|
39
|
+
files: zod_1.z.record(zod_1.z.string(), zod_1.z.string())
|
|
40
|
+
});
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// Summary metadata schema (nested within summary assets)
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
exports.SummaryMetadataSchema = zod_1.z.object({
|
|
45
|
+
file_path: zod_1.z.string(),
|
|
46
|
+
file_name: zod_1.z.string(),
|
|
47
|
+
extension: zod_1.z.string(),
|
|
48
|
+
line_count: zod_1.z.number().int().nonnegative(),
|
|
49
|
+
byte_size: zod_1.z.number().int().nonnegative(),
|
|
50
|
+
content_hash: zod_1.z.string(),
|
|
51
|
+
generated_at: zod_1.z.string(),
|
|
52
|
+
generator: zod_1.z.object({
|
|
53
|
+
provider: zod_1.z.string(),
|
|
54
|
+
model: zod_1.z.string()
|
|
55
|
+
}),
|
|
56
|
+
prompt_version: zod_1.z.number().int(),
|
|
57
|
+
summary_format: zod_1.z.string(),
|
|
58
|
+
custom_prompt_hash: zod_1.z.string().optional(),
|
|
59
|
+
custom_prompt_source: zod_1.z.string().optional()
|
|
60
|
+
});
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// Summary asset schema (individual hash-named JSON files)
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
exports.SummaryAssetSchema = zod_1.z.object({
|
|
65
|
+
$schema: zod_1.z.string().optional(),
|
|
66
|
+
schemaVersion: zod_1.z.literal(exports.SUMMARY_ASSET_SCHEMA_VERSION),
|
|
67
|
+
content_hash: zod_1.z.string(),
|
|
68
|
+
metadata: exports.SummaryMetadataSchema.optional(),
|
|
69
|
+
summary: zod_1.z.string(),
|
|
70
|
+
raw_code_snapshot: zod_1.z.string().optional()
|
|
71
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
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 SCHEMA_BASE_URL = "https://raw.githubusercontent.com/sullyTheDev/diffdoc";
|
|
11
|
+
const VERSION = JSON.parse(node_fs_1.default.readFileSync(node_path_1.default.resolve(__dirname, "../../package.json"), "utf8")).version;
|
|
12
|
+
const schemas = [
|
|
13
|
+
{ name: "diffdocrc.schema.json", zodSchema: schemas_1.DiffdocConfigSchema },
|
|
14
|
+
{ name: "manifest.schema.json", zodSchema: schemas_1.RepoManifestSchema },
|
|
15
|
+
{ name: "summary-asset.schema.json", zodSchema: schemas_1.SummaryAssetSchema }
|
|
16
|
+
];
|
|
17
|
+
const outDir = node_path_1.default.resolve(__dirname, "../../schemas");
|
|
18
|
+
node_fs_1.default.mkdirSync(outDir, { recursive: true });
|
|
19
|
+
for (const entry of schemas) {
|
|
20
|
+
const jsonSchema = (0, zod_to_json_schema_1.zodToJsonSchema)(entry.zodSchema, {
|
|
21
|
+
name: entry.name.replace(".schema.json", ""),
|
|
22
|
+
$refStrategy: "none"
|
|
23
|
+
});
|
|
24
|
+
const schemaWithId = {
|
|
25
|
+
...jsonSchema,
|
|
26
|
+
$id: `${SCHEMA_BASE_URL}/v${VERSION}/schemas/${entry.name}`
|
|
27
|
+
};
|
|
28
|
+
const outPath = node_path_1.default.resolve(outDir, entry.name);
|
|
29
|
+
node_fs_1.default.writeFileSync(outPath, `${JSON.stringify(schemaWithId, null, 2)}\n`);
|
|
30
|
+
console.log(`Generated: ${outPath}`);
|
|
31
|
+
}
|
|
32
|
+
console.log("Schema generation complete.");
|
package/dist/types/artifacts.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
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.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, "RepoManifestSchema", { enumerable: true, get: function () { return schemas_1.RepoManifestSchema; } });
|
|
10
|
+
Object.defineProperty(exports, "SummaryMetadataSchema", { enumerable: true, get: function () { return schemas_1.SummaryMetadataSchema; } });
|
|
11
|
+
Object.defineProperty(exports, "SummaryAssetSchema", { enumerable: true, get: function () { return schemas_1.SummaryAssetSchema; } });
|
|
12
|
+
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.1",
|
|
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,104 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$ref": "#/definitions/diffdocrc",
|
|
3
|
+
"definitions": {
|
|
4
|
+
"diffdocrc": {
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"baseDir": {
|
|
8
|
+
"type": "string"
|
|
9
|
+
},
|
|
10
|
+
"aiProvider": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"enum": [
|
|
13
|
+
"local",
|
|
14
|
+
"cloud"
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"localLlmEndpoint": {
|
|
18
|
+
"type": "string"
|
|
19
|
+
},
|
|
20
|
+
"localEmbedEndpoint": {
|
|
21
|
+
"type": "string"
|
|
22
|
+
},
|
|
23
|
+
"localChatModel": {
|
|
24
|
+
"type": "string"
|
|
25
|
+
},
|
|
26
|
+
"localEmbedModel": {
|
|
27
|
+
"type": "string"
|
|
28
|
+
},
|
|
29
|
+
"cloudLlmEndpoint": {
|
|
30
|
+
"type": "string"
|
|
31
|
+
},
|
|
32
|
+
"cloudChatModel": {
|
|
33
|
+
"type": "string"
|
|
34
|
+
},
|
|
35
|
+
"cloudEmbedModel": {
|
|
36
|
+
"type": "string"
|
|
37
|
+
},
|
|
38
|
+
"embedBatchSize": {
|
|
39
|
+
"anyOf": [
|
|
40
|
+
{
|
|
41
|
+
"type": "integer",
|
|
42
|
+
"exclusiveMinimum": 0
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"type": "string"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
},
|
|
49
|
+
"summarizeConcurrency": {
|
|
50
|
+
"anyOf": [
|
|
51
|
+
{
|
|
52
|
+
"type": "integer",
|
|
53
|
+
"exclusiveMinimum": 0
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"type": "string"
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
},
|
|
60
|
+
"openaiApiKey": {
|
|
61
|
+
"type": "string"
|
|
62
|
+
},
|
|
63
|
+
"includeGlobs": {
|
|
64
|
+
"anyOf": [
|
|
65
|
+
{
|
|
66
|
+
"type": "array",
|
|
67
|
+
"items": {
|
|
68
|
+
"type": "string"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"type": "string"
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
},
|
|
76
|
+
"excludeGlobs": {
|
|
77
|
+
"anyOf": [
|
|
78
|
+
{
|
|
79
|
+
"type": "array",
|
|
80
|
+
"items": {
|
|
81
|
+
"type": "string"
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"type": "string"
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
"ignoreFile": {
|
|
90
|
+
"type": "string"
|
|
91
|
+
},
|
|
92
|
+
"summaryPrompt": {
|
|
93
|
+
"type": "string"
|
|
94
|
+
},
|
|
95
|
+
"summaryPromptFile": {
|
|
96
|
+
"type": "string"
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
"additionalProperties": false
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
103
|
+
"$id": "https://raw.githubusercontent.com/sullyTheDev/diffdoc/v0.6.1/schemas/diffdocrc.schema.json"
|
|
104
|
+
}
|
|
@@ -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/v0.6.1/schemas/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/v0.6.1/schemas/summary-asset.schema.json"
|
|
103
|
+
}
|