sf-git-ai-meta-insights 2.0.1 → 2.1.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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.1.0](https://github.com/mcarvin8/sf-git-ai-meta-insights/compare/v2.0.1...v2.1.0) (2026-04-19)
4
+
5
+
6
+ ### Features
7
+
8
+ * **smart-diff:** bump @mcarvin/smart-diff from 1.0.3 to 1.1.0 ([#14](https://github.com/mcarvin8/sf-git-ai-meta-insights/issues/14)) ([d56e96e](https://github.com/mcarvin8/sf-git-ai-meta-insights/commit/d56e96eae3020cbe6ccd88cb33dac3799756ff80))
9
+
3
10
  ## [2.0.1](https://github.com/mcarvin8/sf-git-ai-meta-insights/compare/v2.0.0...v2.0.1) (2026-04-14)
4
11
 
5
12
 
package/README.md CHANGED
@@ -1,12 +1,17 @@
1
1
  # sf-git-ai-meta-insights
2
2
 
3
- [![NPM](https://img.shields.io/npm/v/sf-git-ai-meta-insights.svg?label=sf-git-ai-meta-insights)](https://www.npmjs.com/package/sf-git-ai-meta-insights) [![Downloads/week](https://img.shields.io/npm/dw/sf-git-ai-meta-insights.svg)](https://npmjs.org/package/sf-git-ai-meta-insights) [![License](https://img.shields.io/badge/License-MIT-yellow.svg)](https://raw.githubusercontent.com/salesforcecli/sf-git-ai-meta-insights/main/LICENSE.md)
3
+ [![NPM](https://img.shields.io/npm/v/sf-git-ai-meta-insights.svg?label=sf-git-ai-meta-insights)](https://www.npmjs.com/package/sf-git-ai-meta-insights)
4
+ [![Downloads/week](https://img.shields.io/npm/dw/sf-git-ai-meta-insights.svg)](https://npmjs.org/package/sf-git-ai-meta-insights)
5
+ [![License](https://img.shields.io/badge/License-MIT-yellow.svg)](https://raw.githubusercontent.com/salesforcecli/sf-git-ai-meta-insights/main/LICENSE.md)
6
+ [![codecov](https://codecov.io/gh/mcarvin8/sf-git-ai-meta-insights/graph/badge.svg?token=N5FKE0JPHN)](https://codecov.io/gh/mcarvin8/sf-git-ai-meta-insights)
4
7
 
5
- `sf-git-ai-meta-insights` is an `sf` plugin that generates AI-assisted summaries of Salesforce metadata changes from a git diff.
8
+ `sf-git-ai-meta-insights` is an `sf` plugin that generates AI summaries of Salesforce metadata changes from a git diff.
6
9
 
7
10
  ## Overview
8
11
 
9
- This plugin summarizes metadata changes between two Git refs, optionally filters commits by message, and writes a Markdown file using an **OpenAI-compatible** LLM. A configured gateway (API key and/or base URL and/or default headers—see below) is **required**; there is no offline or local-only summary.
12
+ This plugin summarizes metadata changes between two Git refs, optionally filters commits by message, and writes a Markdown file using an **OpenAI-compatible** LLM. A configured gateway (API key and/or base URL and/or default headers) is **required**.
13
+
14
+ ![Markdown Summary Example](https://raw.githubusercontent.com/mcarvin8/sf-git-ai-meta-insights/main/.github/images/summary-example.png)
10
15
 
11
16
  ## Installation
12
17
 
@@ -22,15 +27,18 @@ Summarize metadata changes between two Git refs and write the generated summary
22
27
 
23
28
  #### Flags
24
29
 
25
- - `--from` `-f` (**required**) Start reference for the git diff range. You must pass an explicit ref (for example `HEAD~1`, a tag, or a commit hash); there is no default.
26
- - `--to` `-t` End reference for the git diff range. Defaults to `HEAD`.
27
- - `--commit-message-include` `-m` Include commits whose messages match any of these regex patterns (repeatable, OR).
28
- - `--commit-message-exclude` `-e` Exclude commits whose messages match any of these regex patterns (repeatable, OR).
29
- - `--include-package-directory` `-i` Extra repo-relative package paths merged with `sfdx-project.json` package directories (repeatable).
30
- - `--exclude-package-directory` `-x` Exclude package paths: removes matching entries from the configured package list and adds git `:(exclude)` pathspecs for the diff (repeatable).
31
- - `--team` Optional team or squad label for the summary (also supported via `METADATA_AUDIT_TEAM` or `SF_GIT_AI_TEAM`).
32
- - `--output` `-p` Output file path for the generated summary. Defaults to `metadata-summary.md`.
33
- - `--model` OpenAI model used for the summary. Defaults to `gpt-4o-mini`.
30
+ | Flag | Short | Required | Default | Description |
31
+ | ----------------------------- | ----- | -------- | --------------------- | ----------------------------------------------------------------------------------------------- |
32
+ | `--from` | `-f` | Yes | | Start reference for the git diff range (e.g. `HEAD~1`, a tag, or a commit hash). |
33
+ | `--to` | `-t` | No | `HEAD` | End reference for the git diff range. |
34
+ | `--commit-message-include` | `-m` | No | | Include commits whose messages match any of these regex patterns (repeatable, OR). |
35
+ | `--commit-message-exclude` | `-e` | No | | Exclude commits whose messages match any of these regex patterns (repeatable, OR). |
36
+ | `--include-package-directory` | `-i` | No | | Extra repo-relative package paths merged with `sfdx-project.json` directories (repeatable). |
37
+ | `--exclude-package-directory` | `-x` | No | | Exclude package paths from the configured list and add git `:(exclude)` pathspecs (repeatable). |
38
+ | `--team` | | No | | Team or squad label for the summary (also via `METADATA_AUDIT_TEAM` or `SF_GIT_AI_TEAM`). |
39
+ | `--output` | `-p` | No | `metadata-summary.md` | Output file path for the generated summary. |
40
+ | `--model` | | No | `gpt-4o-mini` | OpenAI model used for the summary. |
41
+ | `--max-diff-chars` | | No | | Max characters of unified diff text sent to the model (5,000–5,000,000). |
34
42
 
35
43
  #### Examples
36
44
 
@@ -40,6 +48,13 @@ Summarize changes since the previous commit:
40
48
  sf sgai metadata summarize --from HEAD~1 --to HEAD
41
49
  ```
42
50
 
51
+ Summarize changes from the past week on main branch:
52
+
53
+ ```bash
54
+ FROM=$(git log origin/main -1 --before="1 week ago" --pretty=format:%H)
55
+ sf sgai metadata summarize --from "$FROM" --to "origin/main"
56
+ ```
57
+
43
58
  Summarize a custom range and save to `changes.md`:
44
59
 
45
60
  ```bash
@@ -52,7 +67,7 @@ Summarize only commits whose messages match a regex:
52
67
  sf sgai metadata summarize --from main --to HEAD --commit-message-include "(feature|fix)"
53
68
  ```
54
69
 
55
- Use a custom OpenAI model:
70
+ Set a specific OpenAI model:
56
71
 
57
72
  ```bash
58
73
  sf sgai metadata summarize --from HEAD~1 --to HEAD --model gpt-4o-mini
@@ -62,30 +77,26 @@ sf sgai metadata summarize --from HEAD~1 --to HEAD --model gpt-4o-mini
62
77
 
63
78
  - `sf` CLI installed
64
79
  - Node.js 20 or later
65
- - **LLM gateway configuration** (see below)—at least one of `OPENAI_API_KEY` / `LLM_API_KEY`, `LLM_BASE_URL` / `OPENAI_BASE_URL`, or JSON in `OPENAI_DEFAULT_HEADERS` / `LLM_DEFAULT_HEADERS` so the OpenAI-compatible client can call your provider
80
+ - **OpenAI configuration**—see below
66
81
  - A Salesforce DX project repository with a `sfdx-project.json` file present in the repo root (unless you pass only `--include-package-directory` paths)
67
82
  - [Git Bash](https://git-scm.com/install/)
68
83
 
69
84
  This plugin reads `packageDirectories` from `sfdx-project.json` (when present) to scope the git diff, merges optional CLI include/exclude paths, then sends context to the model.
70
85
 
71
- The plugin uses the official Node [`openai`](https://www.npmjs.com/package/openai) client: optional **`baseURL`**, optional **`defaultHeaders`** (JSON), and an API key string the SDK expects.
86
+ ### OpenAI Configuration
72
87
 
73
- ### `LLM_*` overrides `OPENAI_*`
88
+ The plugin requires an **OpenAI-compatible** endpoint. At minimum, set an API key or base URL:
74
89
 
75
- | Variable | Purpose |
76
- | ------------------------ | ------------------------------------------------------------------------------------------- |
77
- | `OPENAI_API_KEY` | Default API key for api.openai.com or your gateway. |
78
- | `LLM_API_KEY` | Overrides `OPENAI_API_KEY` when set. |
79
- | `OPENAI_BASE_URL` | Default base URL (OpenAI-compatible). |
80
- | `LLM_BASE_URL` | Overrides `OPENAI_BASE_URL` when set. |
81
- | `OPENAI_DEFAULT_HEADERS` | JSON object of extra HTTP headers (string values only). |
82
- | `LLM_DEFAULT_HEADERS` | JSON object merged **on top of** `OPENAI_DEFAULT_HEADERS` (same header names are replaced). |
90
+ | Variable | Purpose |
91
+ | --------------------- | ------------------------------------------- |
92
+ | `OPENAI_API_KEY` | API key for api.openai.com or your gateway. |
93
+ | `LLM_BASE_URL` | Base URL for an OpenAI-compatible gateway. |
94
+ | `LLM_DEFAULT_HEADERS` | JSON object of extra HTTP headers. |
83
95
 
84
- The OpenAI Node client always sends `Authorization: Bearer <apiKey>`. If you put a raw `sk-...` value in `LLM_DEFAULT_HEADERS` / `OPENAI_DEFAULT_HEADERS` as `Authorization` **without** `Bearer`, many gateways treat that as the final header and return errors like `401` with `param: api_key`. When `LLM_API_KEY` / `OPENAI_API_KEY` is unset, this plugin detects `Authorization: sk-...` or `Authorization: Bearer sk-...` in the merged JSON headers, moves that token into the client `apiKey` (so the SDK sends a proper `Bearer` value), and removes the duplicate `Authorization` entry from `defaultHeaders` while keeping your other headers (for example `x-alfa-rbac`).
96
+ > `LLM_*` variants override their `OPENAI_*` counterparts when both are set.
97
+ > For the full list of supported environment variables, see the [`@mcarvin/smart-diff` documentation](https://github.com/mcarvin8/smart-diff#llm-configuration).
85
98
 
86
- Prefer setting `LLM_API_KEY` (or `OPENAI_API_KEY`) to your `sk-...` token when your gateway documents API-key auth that way.
87
-
88
- **PowerShell: company gateway**
99
+ **PowerShell example with a company gateway**
89
100
 
90
101
  ```powershell
91
102
  $env:LLM_BASE_URL = "https://llm-gateway.mycompany.example/v1"
@@ -94,19 +105,10 @@ sf sgai metadata summarize --from HEAD~1 --to HEAD
94
105
  ```
95
106
 
96
107
  ![Command Example with Company Gateway](https://raw.githubusercontent.com/mcarvin8/sf-git-ai-meta-insights/main/.github/images/cmd-example.png)
97
- ![Markdown Summary Example](https://raw.githubusercontent.com/mcarvin8/sf-git-ai-meta-insights/main/.github/images/summary-example.png)
98
-
99
- ### OpenAI (api.openai.com)
100
-
101
- Set `OPENAI_API_KEY` only, or `LLM_API_KEY` if you standardize on `LLM_*` in your environment.
102
-
103
- ### Token limits
104
-
105
- `OPENAI_MAX_TOKENS` caps `max_tokens`; `LLM_MAX_TOKENS` overrides it when set.
106
108
 
107
- ### Diff size (context window)
109
+ ## Built With
108
110
 
109
- The full unified diff is capped before it is sent to the LLM so requests stay within typical context limits (for example 128k tokens). If you see errors about context length exceeded, narrow `--from`/`--to`, use `--commit-message-include` / `--commit-message-exclude`, or lower `--max-diff-chars` / `LLM_MAX_DIFF_CHARS`. Only raise the cap when your model and gateway allow a larger context.
111
+ The plugin's core logic is imported from [`@mcarvin/smart-diff`](https://github.com/mcarvin8/smart-diff) library, which is a general solution to turn git diffs from any git repository into OpenAI summaries.
110
112
 
111
113
  ## License
112
114
 
package/oclif.lock CHANGED
@@ -1649,10 +1649,10 @@
1649
1649
  resolved "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz"
1650
1650
  integrity sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==
1651
1651
 
1652
- "@mcarvin/smart-diff@1.0.3":
1653
- version "1.0.3"
1654
- resolved "https://registry.yarnpkg.com/@mcarvin/smart-diff/-/smart-diff-1.0.3.tgz#52c14696593f8c5cacb8b8dc98688796dacfe93d"
1655
- integrity sha512-4ohYlihSH5oDiExOHSa5DcRB/QX/p/Ofx/StPBlqrTX1ytkrN12T6bwYiO6w1uq4kM9siVWe+dtjwgP37McawQ==
1652
+ "@mcarvin/smart-diff@1.1.0":
1653
+ version "1.1.0"
1654
+ resolved "https://registry.yarnpkg.com/@mcarvin/smart-diff/-/smart-diff-1.1.0.tgz#9d44563d10ccd849c2fa9f604bcb432247cc9ecb"
1655
+ integrity sha512-YVF5QQU7whI2QXUYiz3HH8XVIRbxKbIg2yMs79TZLyKZF/+Jt4frTgj/hzsrQsBdxOdNPnvQyc1ChFjBPpF+nA==
1656
1656
  dependencies:
1657
1657
  fs-extra "^11.3.4"
1658
1658
  openai "^6.34.0"
@@ -8647,7 +8647,16 @@ string-length@^4.0.1:
8647
8647
  char-regex "^1.0.2"
8648
8648
  strip-ansi "^6.0.0"
8649
8649
 
8650
- "string-width-cjs@npm:string-width@^4.2.0", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
8650
+ "string-width-cjs@npm:string-width@^4.2.0":
8651
+ version "4.2.3"
8652
+ resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
8653
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
8654
+ dependencies:
8655
+ emoji-regex "^8.0.0"
8656
+ is-fullwidth-code-point "^3.0.0"
8657
+ strip-ansi "^6.0.1"
8658
+
8659
+ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
8651
8660
  version "4.2.3"
8652
8661
  resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
8653
8662
  integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -8728,7 +8737,14 @@ stringify-entities@^4.0.0:
8728
8737
  character-entities-html4 "^2.0.0"
8729
8738
  character-entities-legacy "^3.0.0"
8730
8739
 
8731
- "strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1:
8740
+ "strip-ansi-cjs@npm:strip-ansi@^6.0.1":
8741
+ version "6.0.1"
8742
+ resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
8743
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
8744
+ dependencies:
8745
+ ansi-regex "^5.0.1"
8746
+
8747
+ strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1:
8732
8748
  version "6.0.1"
8733
8749
  resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
8734
8750
  integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -9451,7 +9467,7 @@ workerpool@^9.2.0:
9451
9467
  resolved "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz"
9452
9468
  integrity sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==
9453
9469
 
9454
- "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
9470
+ "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
9455
9471
  version "7.0.0"
9456
9472
  resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
9457
9473
  integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -9469,6 +9485,15 @@ wrap-ansi@^6.2.0:
9469
9485
  string-width "^4.1.0"
9470
9486
  strip-ansi "^6.0.0"
9471
9487
 
9488
+ wrap-ansi@^7.0.0:
9489
+ version "7.0.0"
9490
+ resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
9491
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
9492
+ dependencies:
9493
+ ansi-styles "^4.0.0"
9494
+ string-width "^4.1.0"
9495
+ strip-ansi "^6.0.0"
9496
+
9472
9497
  wrap-ansi@^8.1.0:
9473
9498
  version "8.1.0"
9474
9499
  resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz"
@@ -154,5 +154,5 @@
154
154
  ]
155
155
  }
156
156
  },
157
- "version": "2.0.1"
157
+ "version": "2.1.0"
158
158
  }
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "sf-git-ai-meta-insights",
3
3
  "description": "Provide AI-generated summaries on Salesforce metadata changes by analyzing the git diff.",
4
- "version": "2.0.1",
4
+ "version": "2.1.0",
5
5
  "dependencies": {
6
- "@mcarvin/smart-diff": "1.0.3",
6
+ "@mcarvin/smart-diff": "1.1.0",
7
7
  "@oclif/core": "^4",
8
8
  "@salesforce/core": "^8",
9
9
  "@salesforce/sf-plugins-core": "^12"