@mcarvin/smart-diff 1.0.0 → 1.0.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/README.md +5 -4
- package/dist/index.cjs +6 -6
- package/dist/index.mjs +6 -6
- package/package.json +3 -3
- package/dist/typings/ai/aiSummary.d.ts +0 -18
- package/dist/typings/ai/openAIConfig.d.ts +0 -21
- package/dist/typings/git/gitDiff.d.ts +0 -33
- package/dist/typings/index.d.ts +0 -24
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# smart-diff
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/smart-diff)
|
|
3
|
+
[](https://www.npmjs.com/package/@mcarvin/smart-diff)
|
|
4
4
|
[](https://raw.githubusercontent.com/mcarvin8/smart-diff/main/LICENSE.md)
|
|
5
|
-
[](https://npmjs.org/package/smart-diff)
|
|
5
|
+
[](https://npmjs.org/package/@mcarvin/smart-diff)
|
|
6
6
|
|
|
7
7
|
TypeScript library that turns a **git revision range** into a **Markdown summary** using an OpenAI-compatible Chat Completions API. It uses [`simple-git`](https://github.com/steveukx/git-js) to read the repo, respects **path includes/excludes** and **commit message include/exclude regexes**, and sends commits, paths, structured diff stats, and unified diff text to the model.
|
|
8
8
|
|
|
@@ -11,11 +11,12 @@ There is **no local fallback**: you must either configure an LLM gateway via env
|
|
|
11
11
|
## Requirements
|
|
12
12
|
|
|
13
13
|
- **Node.js** 20+
|
|
14
|
+
- Git Bash
|
|
14
15
|
|
|
15
16
|
## Installation
|
|
16
17
|
|
|
17
18
|
```bash
|
|
18
|
-
npm install smart-diff
|
|
19
|
+
npm install @mcarvin/smart-diff
|
|
19
20
|
```
|
|
20
21
|
|
|
21
22
|
Build the package from source with `npm run build` (Rollup outputs CommonJS and ESM under `dist/`).
|
|
@@ -39,7 +40,7 @@ The client is created with the official [`openai`](https://www.npmjs.com/package
|
|
|
39
40
|
### `summarizeGitDiff`
|
|
40
41
|
|
|
41
42
|
```ts
|
|
42
|
-
import { summarizeGitDiff } from 'smart-diff';
|
|
43
|
+
import { summarizeGitDiff } from '@mcarvin/smart-diff';
|
|
43
44
|
|
|
44
45
|
const markdown = await summarizeGitDiff({
|
|
45
46
|
from: 'origin/main',
|
package/dist/index.cjs
CHANGED
|
@@ -154,12 +154,12 @@ function truncateUnifiedDiffForLlm(diffText, maxChars) {
|
|
|
154
154
|
const marker = `\n\n--- TRUNCATED: unified diff was ${diffText.length} characters; only the first ${maxChars} were sent. Narrow the ref range, adjust commit/path filters, or raise maxDiffChars / LLM_MAX_DIFF_CHARS only if your model context allows. ---\n`;
|
|
155
155
|
return diffText.slice(0, maxChars) + marker;
|
|
156
156
|
}
|
|
157
|
-
const DEFAULT_GIT_DIFF_SYSTEM_PROMPT = `You are a senior software engineer helping developers understand code and configuration changes from the git context they supplied.
|
|
158
|
-
You receive: commit subject lines (when available), changed file paths, and unified git patch(es)—either one range diff or concatenated per-commit patches, depending on how the diff was produced. Patches may be truncated mid-section with an explicit marker—do not infer changes beyond visible lines.
|
|
159
|
-
Explain what changed in terms of behavior, APIs, data, configuration, security, and operational risk. Tie claims to the patch when possible.
|
|
160
|
-
Produce a concise, developer-focused summary in Markdown.
|
|
161
|
-
Use sections that fit the change (for example: Highlights, Breaking or risky changes, API / contract changes, Data & schema, Configuration & infra, Security & auth, Tests & quality). Omit empty sections.
|
|
162
|
-
Group related changes; do not list every individual file. When multiple commits appear in the context, briefly separate notable themes by commit when helpful.
|
|
157
|
+
const DEFAULT_GIT_DIFF_SYSTEM_PROMPT = `You are a senior software engineer helping developers understand code and configuration changes from the git context they supplied.
|
|
158
|
+
You receive: commit subject lines (when available), changed file paths, and unified git patch(es)—either one range diff or concatenated per-commit patches, depending on how the diff was produced. Patches may be truncated mid-section with an explicit marker—do not infer changes beyond visible lines.
|
|
159
|
+
Explain what changed in terms of behavior, APIs, data, configuration, security, and operational risk. Tie claims to the patch when possible.
|
|
160
|
+
Produce a concise, developer-focused summary in Markdown.
|
|
161
|
+
Use sections that fit the change (for example: Highlights, Breaking or risky changes, API / contract changes, Data & schema, Configuration & infra, Security & auth, Tests & quality). Omit empty sections.
|
|
162
|
+
Group related changes; do not list every individual file. When multiple commits appear in the context, briefly separate notable themes by commit when helpful.
|
|
163
163
|
If the user message includes a Team line, use that exact team name in the summary title (for example: "## <Team> – Change summary" or similar).`;
|
|
164
164
|
const LLM_GATEWAY_REQUIRED_MESSAGE = 'No LLM gateway configured. Set OPENAI_API_KEY or LLM_API_KEY, and/or LLM_BASE_URL or OPENAI_BASE_URL, ' +
|
|
165
165
|
'and/or JSON in OPENAI_DEFAULT_HEADERS or LLM_DEFAULT_HEADERS. ' +
|
package/dist/index.mjs
CHANGED
|
@@ -152,12 +152,12 @@ function truncateUnifiedDiffForLlm(diffText, maxChars) {
|
|
|
152
152
|
const marker = `\n\n--- TRUNCATED: unified diff was ${diffText.length} characters; only the first ${maxChars} were sent. Narrow the ref range, adjust commit/path filters, or raise maxDiffChars / LLM_MAX_DIFF_CHARS only if your model context allows. ---\n`;
|
|
153
153
|
return diffText.slice(0, maxChars) + marker;
|
|
154
154
|
}
|
|
155
|
-
const DEFAULT_GIT_DIFF_SYSTEM_PROMPT = `You are a senior software engineer helping developers understand code and configuration changes from the git context they supplied.
|
|
156
|
-
You receive: commit subject lines (when available), changed file paths, and unified git patch(es)—either one range diff or concatenated per-commit patches, depending on how the diff was produced. Patches may be truncated mid-section with an explicit marker—do not infer changes beyond visible lines.
|
|
157
|
-
Explain what changed in terms of behavior, APIs, data, configuration, security, and operational risk. Tie claims to the patch when possible.
|
|
158
|
-
Produce a concise, developer-focused summary in Markdown.
|
|
159
|
-
Use sections that fit the change (for example: Highlights, Breaking or risky changes, API / contract changes, Data & schema, Configuration & infra, Security & auth, Tests & quality). Omit empty sections.
|
|
160
|
-
Group related changes; do not list every individual file. When multiple commits appear in the context, briefly separate notable themes by commit when helpful.
|
|
155
|
+
const DEFAULT_GIT_DIFF_SYSTEM_PROMPT = `You are a senior software engineer helping developers understand code and configuration changes from the git context they supplied.
|
|
156
|
+
You receive: commit subject lines (when available), changed file paths, and unified git patch(es)—either one range diff or concatenated per-commit patches, depending on how the diff was produced. Patches may be truncated mid-section with an explicit marker—do not infer changes beyond visible lines.
|
|
157
|
+
Explain what changed in terms of behavior, APIs, data, configuration, security, and operational risk. Tie claims to the patch when possible.
|
|
158
|
+
Produce a concise, developer-focused summary in Markdown.
|
|
159
|
+
Use sections that fit the change (for example: Highlights, Breaking or risky changes, API / contract changes, Data & schema, Configuration & infra, Security & auth, Tests & quality). Omit empty sections.
|
|
160
|
+
Group related changes; do not list every individual file. When multiple commits appear in the context, briefly separate notable themes by commit when helpful.
|
|
161
161
|
If the user message includes a Team line, use that exact team name in the summary title (for example: "## <Team> – Change summary" or similar).`;
|
|
162
162
|
const LLM_GATEWAY_REQUIRED_MESSAGE = 'No LLM gateway configured. Set OPENAI_API_KEY or LLM_API_KEY, and/or LLM_BASE_URL or OPENAI_BASE_URL, ' +
|
|
163
163
|
'and/or JSON in OPENAI_DEFAULT_HEADERS or LLM_DEFAULT_HEADERS. ' +
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcarvin/smart-diff",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Summarizes a git diff using OpenAI models.",
|
|
5
5
|
"author": "Matt Carvin",
|
|
6
6
|
"license": "MIT",
|
|
@@ -59,10 +59,10 @@
|
|
|
59
59
|
},
|
|
60
60
|
"repository": {
|
|
61
61
|
"type": "git",
|
|
62
|
-
"url": "git+https://github.com/mcarvin8/
|
|
62
|
+
"url": "git+https://github.com/mcarvin8/smart-diff.git"
|
|
63
63
|
},
|
|
64
64
|
"bugs": {
|
|
65
|
-
"url": "https://github.com/mcarvin8/
|
|
65
|
+
"url": "https://github.com/mcarvin8/smart-diff/issues"
|
|
66
66
|
},
|
|
67
67
|
"keywords": [
|
|
68
68
|
"openai",
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { CommitInfo, DiffSummary } from '../git/gitDiff.js';
|
|
2
|
-
import { type OpenAiLikeClient } from './openAIConfig.js';
|
|
3
|
-
export declare function resolveLlmMaxDiffChars(cliOverride?: number): number;
|
|
4
|
-
export declare function truncateUnifiedDiffForLlm(diffText: string, maxChars: number): string;
|
|
5
|
-
export declare const DEFAULT_GIT_DIFF_SYSTEM_PROMPT = "You are a senior software engineer helping developers understand code and configuration changes from the git context they supplied.\nYou receive: commit subject lines (when available), changed file paths, and unified git patch(es)\u2014either one range diff or concatenated per-commit patches, depending on how the diff was produced. Patches may be truncated mid-section with an explicit marker\u2014do not infer changes beyond visible lines.\nExplain what changed in terms of behavior, APIs, data, configuration, security, and operational risk. Tie claims to the patch when possible.\nProduce a concise, developer-focused summary in Markdown.\nUse sections that fit the change (for example: Highlights, Breaking or risky changes, API / contract changes, Data & schema, Configuration & infra, Security & auth, Tests & quality). Omit empty sections.\nGroup related changes; do not list every individual file. When multiple commits appear in the context, briefly separate notable themes by commit when helpful.\nIf the user message includes a Team line, use that exact team name in the summary title (for example: \"## <Team> \u2013 Change summary\" or similar).";
|
|
6
|
-
export type SummarizeFlags = {
|
|
7
|
-
from: string;
|
|
8
|
-
to?: string;
|
|
9
|
-
model?: string;
|
|
10
|
-
team?: string;
|
|
11
|
-
maxDiffChars?: number;
|
|
12
|
-
systemPrompt?: string;
|
|
13
|
-
commitMessageIncludeRegexes?: string[];
|
|
14
|
-
commitMessageExcludeRegexes?: string[];
|
|
15
|
-
};
|
|
16
|
-
type OpenAiClientProvider = () => Promise<OpenAiLikeClient>;
|
|
17
|
-
export declare function generateSummary(diffText: string, fileNames: string[], commits: CommitInfo[], flags: SummarizeFlags, openAiClientProvider?: OpenAiClientProvider, diffSummary?: DiffSummary): Promise<string>;
|
|
18
|
-
export {};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export declare function resolveLlmBaseUrl(): string | undefined;
|
|
2
|
-
export declare function parseLlmDefaultHeadersFromEnv(): Record<string, string> | undefined;
|
|
3
|
-
export declare function splitPromotableAuthorizationFromHeaders(headers: Record<string, string>): {
|
|
4
|
-
defaultHeaders: Record<string, string>;
|
|
5
|
-
apiKeyFromAuthHeader?: string;
|
|
6
|
-
};
|
|
7
|
-
export declare function shouldUseLlmGateway(): boolean;
|
|
8
|
-
export type OpenAiLikeClient = {
|
|
9
|
-
chat: {
|
|
10
|
-
completions: {
|
|
11
|
-
create(...options: unknown[]): Promise<unknown>;
|
|
12
|
-
};
|
|
13
|
-
};
|
|
14
|
-
};
|
|
15
|
-
export type OpenAiLikeClientInit = {
|
|
16
|
-
apiKey: string;
|
|
17
|
-
baseURL?: string;
|
|
18
|
-
defaultHeaders?: Record<string, string>;
|
|
19
|
-
};
|
|
20
|
-
export declare function resolveOpenAiLikeClientInit(): OpenAiLikeClientInit;
|
|
21
|
-
export declare function createOpenAiLikeClient(): Promise<OpenAiLikeClient>;
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type { SimpleGit } from 'simple-git';
|
|
2
|
-
export type CommitInfo = {
|
|
3
|
-
hash: string;
|
|
4
|
-
message: string;
|
|
5
|
-
};
|
|
6
|
-
export type DiffStatus = 'added' | 'deleted' | 'modified' | 'renamed' | 'copied' | 'type-changed' | 'unknown';
|
|
7
|
-
export type DiffFileSummary = {
|
|
8
|
-
path: string;
|
|
9
|
-
status: DiffStatus;
|
|
10
|
-
additions: number;
|
|
11
|
-
deletions: number;
|
|
12
|
-
oldPath?: string;
|
|
13
|
-
newPath?: string;
|
|
14
|
-
};
|
|
15
|
-
export type DiffSummary = {
|
|
16
|
-
files: DiffFileSummary[];
|
|
17
|
-
totalFiles: number;
|
|
18
|
-
totalAdditions: number;
|
|
19
|
-
totalDeletions: number;
|
|
20
|
-
};
|
|
21
|
-
export type DiffPathFilter = {
|
|
22
|
-
includeFolders?: string[];
|
|
23
|
-
excludeFolders?: string[];
|
|
24
|
-
};
|
|
25
|
-
export declare function createGitClient(cwd?: string): SimpleGit;
|
|
26
|
-
export declare function getCommits(git: SimpleGit, from: string, to: string): Promise<CommitInfo[]>;
|
|
27
|
-
export declare function filterCommitsByMessageRegexes(commits: CommitInfo[], includePatterns?: string[], excludePatterns?: string[]): CommitInfo[];
|
|
28
|
-
export declare function getRepoRoot(git: SimpleGit): Promise<string>;
|
|
29
|
-
export declare function buildDiffPathspecs(repoRoot: string, pathFilter?: DiffPathFilter): string[];
|
|
30
|
-
export declare function getDiff(git: SimpleGit, from: string, to: string, commits: CommitInfo[], filterByCommits: boolean, pathFilter?: DiffPathFilter, repoRootOverride?: string): Promise<string>;
|
|
31
|
-
export declare function getDiffSummary(git: SimpleGit, from: string, to: string, commits: CommitInfo[], filterByCommits: boolean, pathFilter?: DiffPathFilter, repoRootOverride?: string): Promise<DiffSummary>;
|
|
32
|
-
export declare function getChangedFiles(git: SimpleGit, from: string, to: string, commits: CommitInfo[], filterByCommits: boolean, pathFilter?: DiffPathFilter, repoRootOverride?: string): Promise<string[]>;
|
|
33
|
-
export declare function parseDiffSummary(diffOutput: string): DiffSummary;
|
package/dist/typings/index.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { SimpleGit } from 'simple-git';
|
|
2
|
-
import type { OpenAiLikeClient } from './ai/openAIConfig.js';
|
|
3
|
-
export type GitDiffAiSummaryOptions = {
|
|
4
|
-
from: string;
|
|
5
|
-
to?: string;
|
|
6
|
-
cwd?: string;
|
|
7
|
-
git?: SimpleGit;
|
|
8
|
-
includeFolders?: string[];
|
|
9
|
-
excludeFolders?: string[];
|
|
10
|
-
commitMessageIncludeRegexes?: string[];
|
|
11
|
-
commitMessageExcludeRegexes?: string[];
|
|
12
|
-
systemPrompt?: string;
|
|
13
|
-
teamName?: string;
|
|
14
|
-
model?: string;
|
|
15
|
-
maxDiffChars?: number;
|
|
16
|
-
openAiClientProvider?: () => Promise<OpenAiLikeClient>;
|
|
17
|
-
};
|
|
18
|
-
export declare function summarizeGitDiff(options: GitDiffAiSummaryOptions): Promise<string>;
|
|
19
|
-
export type { CommitInfo, DiffFileSummary, DiffPathFilter, DiffSummary } from './git/gitDiff.js';
|
|
20
|
-
export { buildDiffPathspecs, createGitClient, filterCommitsByMessageRegexes, getChangedFiles, getCommits, getDiff, getDiffSummary, getRepoRoot, } from './git/gitDiff.js';
|
|
21
|
-
export type { SummarizeFlags } from './ai/aiSummary.js';
|
|
22
|
-
export { DEFAULT_GIT_DIFF_SYSTEM_PROMPT, generateSummary, resolveLlmMaxDiffChars, truncateUnifiedDiffForLlm } from './ai/aiSummary.js';
|
|
23
|
-
export type { OpenAiLikeClient, OpenAiLikeClientInit } from './ai/openAIConfig.js';
|
|
24
|
-
export { createOpenAiLikeClient, parseLlmDefaultHeadersFromEnv, resolveLlmBaseUrl, resolveOpenAiLikeClientInit, shouldUseLlmGateway, splitPromotableAuthorizationFromHeaders, } from './ai/openAIConfig.js';
|