diffdoc 0.2.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.
package/dist/index.js CHANGED
@@ -4,10 +4,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const commander_1 = require("commander");
5
5
  const config_1 = require("./config");
6
6
  const embed_1 = require("./commands/embed");
7
+ const init_1 = require("./commands/init");
7
8
  const query_1 = require("./commands/query");
9
+ const status_1 = require("./commands/status");
8
10
  const summarize_1 = require("./commands/summarize");
9
- const llm_1 = require("./utils/llm");
10
11
  const program = new commander_1.Command();
12
+ function collectOption(value, previous) {
13
+ previous.push(value);
14
+ return previous;
15
+ }
11
16
  function addBaseOptions(command) {
12
17
  return command
13
18
  .option("--config <path>", "path to .diffdocrc JSON config file")
@@ -37,16 +42,17 @@ program
37
42
  .name("diffdoc")
38
43
  .description("Translate repository code shifts into plain-English business context")
39
44
  .version("0.1.0");
40
- addChatOptions(addBaseOptions(program
41
- .command("summarize")))
42
- .description("Summarize repository code into a portable JSON manifest")
43
- .option("--path <path>", "repository or code path to scan", ".")
44
- .option("--out <path>", "manifest output path under --base-dir", "manifest.json")
45
- .option("--mode <mode>", "summarization mode: all or delta", "all")
45
+ program
46
+ .command("init")
47
+ .description("Initialize DiffDoc configuration for this repository")
48
+ .option("--yes", "use defaults without prompting", false)
49
+ .option("--provider <provider>", "AI provider: local or cloud")
50
+ .option("--config <path>", "path to .diffdocrc JSON config file")
51
+ .option("--base-dir <path>", "DiffDoc artifact directory")
52
+ .option("--force", "overwrite existing config file", false)
46
53
  .action(async (options) => {
47
54
  try {
48
- const config = (0, config_1.buildRuntimeConfig)(options, { chat: true });
49
- await (0, summarize_1.runSummarize)({ path: options.path, out: options.out, mode: options.mode }, config);
55
+ await (0, init_1.runInit)(options);
50
56
  }
51
57
  catch (error) {
52
58
  console.error(error instanceof Error ? error.message : error);
@@ -54,14 +60,29 @@ addChatOptions(addBaseOptions(program
54
60
  }
55
61
  });
56
62
  addChatOptions(addBaseOptions(program
57
- .command("prompt")))
58
- .description("Send a plain prompt to the configured LLM")
59
- .argument("<message...>", "prompt text to send")
60
- .action(async (messageParts, options) => {
63
+ .command("summarize")))
64
+ .description("Summarize repository code into a portable JSON manifest")
65
+ .option("--path <path>", "repository or code path to scan", ".")
66
+ .option("--out <path>", "manifest output path under --base-dir", "manifest.json")
67
+ .option("--mode <mode>", "summarization mode: all or delta", "all")
68
+ .option("--include-code-snapshot", "store raw code in summary assets", false)
69
+ .option("--json", "print summarize report as JSON for CI", false)
70
+ .option("--include-glob <pattern>", "include glob pattern (repeatable)", collectOption, [])
71
+ .option("--exclude-glob <pattern>", "exclude glob pattern (repeatable)", collectOption, [])
72
+ .option("--ignore-file <path>", "path to ignore pattern file relative to --path")
73
+ .action(async (options) => {
61
74
  try {
62
75
  const config = (0, config_1.buildRuntimeConfig)(options, { chat: true });
63
- const response = await (0, llm_1.promptLlm)(messageParts.join(" "), config.chat);
64
- console.log(response);
76
+ await (0, summarize_1.runSummarize)({
77
+ path: options.path,
78
+ out: options.out,
79
+ mode: options.mode,
80
+ includeCodeSnapshot: options.includeCodeSnapshot,
81
+ json: options.json,
82
+ includeGlobs: options.includeGlob,
83
+ excludeGlobs: options.excludeGlob,
84
+ ignoreFile: options.ignoreFile
85
+ }, config);
65
86
  }
66
87
  catch (error) {
67
88
  console.error(error instanceof Error ? error.message : error);
@@ -104,10 +125,26 @@ addCloudEndpointAndKeyOptions(addEmbeddingOptions(addBaseOptions(program
104
125
  .command("embed"))))
105
126
  .description("Embed manifest summaries into a local Vectra index")
106
127
  .option("--manifest <path>", "manifest input path under --base-dir", "manifest.json")
128
+ .option("--rebuild", "rebuild local index from scratch", false)
107
129
  .action(async (options) => {
108
130
  try {
109
131
  const config = (0, config_1.buildRuntimeConfig)(options, { embeddings: true });
110
- await (0, embed_1.runEmbed)({ manifest: options.manifest }, config);
132
+ await (0, embed_1.runEmbed)({ manifest: options.manifest, rebuild: options.rebuild }, config);
133
+ }
134
+ catch (error) {
135
+ console.error(error instanceof Error ? error.message : error);
136
+ process.exit(1);
137
+ }
138
+ });
139
+ addBaseOptions(program
140
+ .command("status"))
141
+ .description("Show manifest and index sync status")
142
+ .option("--manifest <path>", "manifest input path under --base-dir", "manifest.json")
143
+ .option("--json", "print status as JSON for CI", false)
144
+ .action(async (options) => {
145
+ try {
146
+ const config = (0, config_1.buildRuntimeConfig)(options, { embeddings: false, chat: false });
147
+ await (0, status_1.runStatus)({ manifest: options.manifest, json: options.json }, config);
111
148
  }
112
149
  catch (error) {
113
150
  console.error(error instanceof Error ? error.message : error);
@@ -39,7 +39,7 @@ function buildAnswerPrompt(question, results) {
39
39
  `File: ${result.filePath}`,
40
40
  `Score: ${result.score}`,
41
41
  `Summary:\n${result.summaryText}`,
42
- `Code Snapshot:\n${result.rawCodeSnapshot}`
42
+ `Code Snapshot:\n${result.rawCodeSnapshot || "(not stored)"}`
43
43
  ].join("\n");
44
44
  }).join("\n\n---\n\n");
45
45
  return `Answer the user's question using only the retrieved DiffDoc results below. If the results do not contain enough information, say what is missing. Prefer a direct answer first, then cite the relevant file paths. Keep the explanation appropriate to the question: summarize when asked for a summary, explain implementation details when asked how something works, and avoid unsupported claims.\n\nUser question:\n${question}\n\nRetrieved results:\n${context}`;
@@ -67,7 +67,7 @@ async function answerFromIndex(question, topK, config) {
67
67
  results: []
68
68
  };
69
69
  }
70
- const answer = await (0, llm_1.promptLlm)(buildAnswerPrompt(question, results), config.chat);
70
+ const answer = await (0, llm_1.generateAnswer)(buildAnswerPrompt(question, results), config.chat);
71
71
  return {
72
72
  answer,
73
73
  sources: results.map((result) => ({ filePath: result.filePath, score: result.score })),
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SUMMARY_ASSET_SCHEMA_VERSION = exports.MANIFEST_SCHEMA_VERSION = void 0;
4
+ exports.MANIFEST_SCHEMA_VERSION = 2;
5
+ exports.SUMMARY_ASSET_SCHEMA_VERSION = 1;
package/dist/utils/git.js CHANGED
@@ -7,16 +7,12 @@ exports.getGitDeltas = getGitDeltas;
7
7
  exports.getCurrentCommit = getCurrentCommit;
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  const simple_git_1 = __importDefault(require("simple-git"));
10
- const TARGET_EXTENSIONS = new Set([".ts", ".js", ".cs", ".py"]);
11
10
  function normalizePath(filePath) {
12
11
  return filePath.split(node_path_1.default.sep).join("/");
13
12
  }
14
- function isTargetCodeFile(filePath) {
15
- return TARGET_EXTENSIONS.has(node_path_1.default.extname(filePath));
16
- }
17
13
  function addUnique(target, filePath) {
18
14
  const normalized = normalizePath(filePath.trim());
19
- if (normalized && isTargetCodeFile(normalized)) {
15
+ if (normalized) {
20
16
  target.add(normalized);
21
17
  }
22
18
  }
package/dist/utils/llm.js CHANGED
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.generateFunctionalSummary = generateFunctionalSummary;
7
- exports.promptLlm = promptLlm;
7
+ exports.generateAnswer = generateAnswer;
8
8
  exports.generateEmbeddings = generateEmbeddings;
9
9
  const openai_1 = __importDefault(require("openai"));
10
10
  function createClient(config) {
@@ -31,7 +31,7 @@ async function generateFunctionalSummary(fileName, codeContent, config) {
31
31
  });
32
32
  return response.choices[0]?.message?.content?.trim() || "No business behavior summary was returned.";
33
33
  }
34
- async function promptLlm(prompt, config) {
34
+ async function generateAnswer(prompt, config) {
35
35
  const { client, model } = createClient(config);
36
36
  const response = await client.chat.completions.create({
37
37
  model,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "diffdoc",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Translate repository code shifts into plain-English business context",
5
5
  "license": "MIT",
6
6
  "author": "Christopher Sullivan",
@@ -15,8 +15,8 @@
15
15
  "type": "commonjs",
16
16
  "main": "dist/index.js",
17
17
  "bin": {
18
- "diffdoc": "./dist/index.js",
19
- "diffdoc-mcp": "./dist/mcp.js"
18
+ "diffdoc": "dist/index.js",
19
+ "diffdoc-mcp": "dist/mcp.js"
20
20
  },
21
21
  "files": [
22
22
  "dist",