@mcarvin/smart-diff 1.0.5 → 2.0.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.umd.js CHANGED
@@ -1,8 +1,8 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('node:path'), require('simple-git')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'node:path', 'simple-git'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.jsTemplate = {}, global.node_path, global.simpleGit));
5
- })(this, (function (exports, node_path, simpleGit) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('ai'), require('node:path'), require('simple-git')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'ai', 'node:path', 'simple-git'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.jsTemplate = {}, global.ai, global.node_path, global.simpleGit));
5
+ })(this, (function (exports, ai, node_path, simpleGit) { 'use strict';
6
6
 
7
7
  /******************************************************************************
8
8
  Copyright (c) Microsoft Corporation.
@@ -36,9 +36,55 @@
36
36
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
37
37
  };
38
38
 
39
+ const DEFAULT_LLM_MAX_DIFF_CHARS = 120000;
40
+ 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.
41
+ 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.
42
+ Explain what changed in terms of behavior, APIs, data, configuration, security, and operational risk. Tie claims to the patch when possible.
43
+ Produce a concise, developer-focused summary in Markdown.
44
+ 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.
45
+ Group related changes; do not list every individual file. When multiple commits appear in the context, briefly separate notable themes by commit when helpful.
46
+ If the user message includes a Team line, use that exact team name in the summary title (for example: "## <Team> – Change summary" or similar).`;
47
+ const LLM_GATEWAY_REQUIRED_MESSAGE = "No LLM provider configured. Set LLM_PROVIDER (openai | openai-compatible | anthropic | google | bedrock | mistral | cohere | groq | xai | deepseek), " +
48
+ "or a provider API key (OPENAI_API_KEY, LLM_API_KEY, ANTHROPIC_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY, MISTRAL_API_KEY, COHERE_API_KEY, GROQ_API_KEY, XAI_API_KEY, DEEPSEEK_API_KEY), " +
49
+ "or LLM_BASE_URL / OPENAI_BASE_URL for an OpenAI-compatible gateway, " +
50
+ "or JSON in OPENAI_DEFAULT_HEADERS / LLM_DEFAULT_HEADERS. " +
51
+ "Alternatively pass llmModelProvider or openAiClientProvider to generateSummary or summarizeGitDiff.";
52
+
53
+ const DEFAULT_MODEL_BY_PROVIDER = {
54
+ openai: "gpt-4o-mini",
55
+ "openai-compatible": "gpt-4o-mini",
56
+ anthropic: "claude-3-5-haiku-latest",
57
+ google: "gemini-2.0-flash",
58
+ bedrock: "anthropic.claude-3-5-haiku-20241022-v1:0",
59
+ mistral: "mistral-small-latest",
60
+ cohere: "command-r-08-2024",
61
+ groq: "llama-3.1-8b-instant",
62
+ xai: "grok-2-latest",
63
+ deepseek: "deepseek-chat",
64
+ };
65
+ const VALID_PROVIDERS = new Set([
66
+ "openai",
67
+ "openai-compatible",
68
+ "anthropic",
69
+ "google",
70
+ "bedrock",
71
+ "mistral",
72
+ "cohere",
73
+ "groq",
74
+ "xai",
75
+ "deepseek",
76
+ ]);
77
+ function readEnv(name) {
78
+ var _a;
79
+ const value = (_a = process.env[name]) === null || _a === void 0 ? void 0 : _a.trim();
80
+ return value && value.length > 0 ? value : undefined;
81
+ }
82
+ function isValidProviderId(value) {
83
+ return VALID_PROVIDERS.has(value);
84
+ }
39
85
  function resolveLlmBaseUrl() {
40
- var _a, _b, _c;
41
- return ((_b = (_a = process.env.LLM_BASE_URL) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : (_c = process.env.OPENAI_BASE_URL) === null || _c === void 0 ? void 0 : _c.trim());
86
+ var _a;
87
+ return (_a = readEnv("LLM_BASE_URL")) !== null && _a !== void 0 ? _a : readEnv("OPENAI_BASE_URL");
42
88
  }
43
89
  function parseHeaderJsonObject(raw) {
44
90
  const trimmed = raw === null || raw === void 0 ? void 0 : raw.trim();
@@ -69,87 +115,187 @@
69
115
  const merged = Object.assign(Object.assign({}, base), override);
70
116
  return Object.keys(merged).length > 0 ? merged : undefined;
71
117
  }
72
- function findAuthorizationHeaderName(headers) {
73
- return Object.keys(headers).find((k) => k.toLowerCase() === "authorization");
74
- }
75
- function stripBearerPrefix(value) {
118
+ function resolveOpenAiApiKey() {
76
119
  var _a;
77
- const trimmed = value.trim();
78
- const match = /^Bearer\s+(\S+)/i.exec(trimmed);
79
- return (_a = match === null || match === void 0 ? void 0 : match[1]) !== null && _a !== void 0 ? _a : trimmed;
80
- }
81
- function splitPromotableAuthorizationFromHeaders(headers) {
82
- const authName = findAuthorizationHeaderName(headers);
83
- if (!authName) {
84
- return { defaultHeaders: headers };
85
- }
86
- const raw = headers[authName];
87
- if (!raw) {
88
- return { defaultHeaders: headers };
89
- }
90
- const token = stripBearerPrefix(raw);
91
- const looksBearer = /^Bearer\s+\S+/i.test(raw.trim());
92
- const looksOpenAiKey = /^sk-/i.test(token);
93
- if (!looksBearer && !looksOpenAiKey) {
94
- return { defaultHeaders: headers };
95
- }
96
- const next = Object.assign({}, headers);
97
- delete next[authName];
98
- return { defaultHeaders: next, apiKeyFromAuthHeader: token };
99
- }
100
- function shouldUseLlmGateway() {
101
- var _a, _b, _c;
102
- const apiKey = (_b = (_a = process.env.LLM_API_KEY) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : (_c = process.env.OPENAI_API_KEY) === null || _c === void 0 ? void 0 : _c.trim();
103
- if (apiKey)
104
- return true;
105
- if (resolveLlmBaseUrl())
106
- return true;
107
- const jsonHeaders = parseLlmDefaultHeadersFromEnv();
108
- if (jsonHeaders && Object.keys(jsonHeaders).length > 0)
109
- return true;
110
- return false;
111
- }
112
- function resolveOpenAiLikeClientInit() {
113
- var _a, _b, _c, _d, _e;
114
- const baseURL = resolveLlmBaseUrl();
115
- const mergedHeaders = (_a = parseLlmDefaultHeadersFromEnv()) !== null && _a !== void 0 ? _a : {};
116
- const envApiKey = (_e = (_c = (_b = process.env.LLM_API_KEY) === null || _b === void 0 ? void 0 : _b.trim()) !== null && _c !== void 0 ? _c : (_d = process.env.OPENAI_API_KEY) === null || _d === void 0 ? void 0 : _d.trim()) !== null && _e !== void 0 ? _e : "";
117
- let defaultHeaders;
118
- let apiKey = envApiKey;
119
- if (apiKey.length === 0) {
120
- const split = splitPromotableAuthorizationFromHeaders(mergedHeaders);
121
- if (split.apiKeyFromAuthHeader) {
122
- apiKey = split.apiKeyFromAuthHeader;
120
+ return (_a = readEnv("LLM_API_KEY")) !== null && _a !== void 0 ? _a : readEnv("OPENAI_API_KEY");
121
+ }
122
+ function detectLlmProvider() {
123
+ var _a, _b;
124
+ const explicit = (_a = readEnv("LLM_PROVIDER")) === null || _a === void 0 ? void 0 : _a.toLowerCase();
125
+ if (explicit && isValidProviderId(explicit)) {
126
+ return explicit;
127
+ }
128
+ if (resolveLlmBaseUrl()) {
129
+ return "openai-compatible";
130
+ }
131
+ if (resolveOpenAiApiKey()) {
132
+ return "openai";
133
+ }
134
+ if (readEnv("ANTHROPIC_API_KEY"))
135
+ return "anthropic";
136
+ if ((_b = readEnv("GOOGLE_GENERATIVE_AI_API_KEY")) !== null && _b !== void 0 ? _b : readEnv("GOOGLE_API_KEY"))
137
+ return "google";
138
+ if (readEnv("MISTRAL_API_KEY"))
139
+ return "mistral";
140
+ if (readEnv("COHERE_API_KEY"))
141
+ return "cohere";
142
+ if (readEnv("GROQ_API_KEY"))
143
+ return "groq";
144
+ if (readEnv("XAI_API_KEY"))
145
+ return "xai";
146
+ if (readEnv("DEEPSEEK_API_KEY"))
147
+ return "deepseek";
148
+ if (parseLlmDefaultHeadersFromEnv())
149
+ return "openai";
150
+ return undefined;
151
+ }
152
+ function isLlmProviderConfigured() {
153
+ return detectLlmProvider() !== undefined;
154
+ }
155
+ function defaultModelForProvider(provider) {
156
+ return DEFAULT_MODEL_BY_PROVIDER[provider];
157
+ }
158
+ function createOpenAiModel(modelId) {
159
+ return __awaiter(this, void 0, void 0, function* () {
160
+ const { createOpenAI } = yield import('@ai-sdk/openai');
161
+ const apiKey = resolveOpenAiApiKey();
162
+ const headers = parseLlmDefaultHeadersFromEnv();
163
+ const provider = createOpenAI(Object.assign(Object.assign({}, (apiKey ? { apiKey } : {})), (headers ? { headers } : {})));
164
+ return provider(modelId);
165
+ });
166
+ }
167
+ function createOpenAiCompatibleModel(modelId) {
168
+ return __awaiter(this, void 0, void 0, function* () {
169
+ var _a;
170
+ const { createOpenAICompatible } = yield import('@ai-sdk/openai-compatible');
171
+ const baseURL = resolveLlmBaseUrl();
172
+ if (!baseURL) {
173
+ throw new Error("openai-compatible provider requires LLM_BASE_URL or OPENAI_BASE_URL to be set.");
123
174
  }
124
- defaultHeaders =
125
- Object.keys(split.defaultHeaders).length > 0
126
- ? split.defaultHeaders
127
- : undefined;
128
- }
129
- else {
130
- defaultHeaders =
131
- Object.keys(mergedHeaders).length > 0 ? mergedHeaders : undefined;
132
- }
133
- return Object.assign(Object.assign({ apiKey: apiKey.length > 0 ? apiKey : "unused" }, (baseURL ? { baseURL } : {})), (defaultHeaders ? { defaultHeaders } : {}));
175
+ const apiKey = resolveOpenAiApiKey();
176
+ const headers = parseLlmDefaultHeadersFromEnv();
177
+ const provider = createOpenAICompatible(Object.assign(Object.assign({ name: (_a = readEnv("LLM_PROVIDER_NAME")) !== null && _a !== void 0 ? _a : "openai-compatible", baseURL }, (apiKey ? { apiKey } : {})), (headers ? { headers } : {})));
178
+ return provider(modelId);
179
+ });
180
+ }
181
+ function wrapMissingPeer(failure) {
182
+ const err = new Error(`Failed to load optional provider package "${failure.pkg}" for LLM_PROVIDER="${failure.provider}". ` +
183
+ `Install it with \`npm install ${failure.pkg}\`.`);
184
+ err.cause = failure.cause;
185
+ return err;
134
186
  }
135
- function createOpenAiLikeClient() {
187
+ function importOptional(provider, pkg, loader) {
136
188
  return __awaiter(this, void 0, void 0, function* () {
137
- const { default: OpenAI } = yield import('openai');
138
- return new OpenAI(resolveOpenAiLikeClientInit());
189
+ try {
190
+ return yield loader();
191
+ }
192
+ catch (cause) {
193
+ throw wrapMissingPeer({ provider, pkg, cause });
194
+ }
195
+ });
196
+ }
197
+ function createAnthropicModel(modelId) {
198
+ return __awaiter(this, void 0, void 0, function* () {
199
+ const mod = yield importOptional("anthropic", "@ai-sdk/anthropic", () => import('@ai-sdk/anthropic'));
200
+ const apiKey = readEnv("ANTHROPIC_API_KEY");
201
+ const provider = mod.createAnthropic(apiKey ? { apiKey } : undefined);
202
+ return provider(modelId);
203
+ });
204
+ }
205
+ function createGoogleModel(modelId) {
206
+ return __awaiter(this, void 0, void 0, function* () {
207
+ var _a;
208
+ const mod = yield importOptional("google", "@ai-sdk/google", () => import('@ai-sdk/google'));
209
+ const apiKey = (_a = readEnv("GOOGLE_GENERATIVE_AI_API_KEY")) !== null && _a !== void 0 ? _a : readEnv("GOOGLE_API_KEY");
210
+ const provider = mod.createGoogleGenerativeAI(apiKey ? { apiKey } : undefined);
211
+ return provider(modelId);
212
+ });
213
+ }
214
+ function createBedrockModel(modelId) {
215
+ return __awaiter(this, void 0, void 0, function* () {
216
+ const mod = yield importOptional("bedrock", "@ai-sdk/amazon-bedrock", () => import('@ai-sdk/amazon-bedrock'));
217
+ const provider = mod.createAmazonBedrock();
218
+ return provider(modelId);
219
+ });
220
+ }
221
+ function createMistralModel(modelId) {
222
+ return __awaiter(this, void 0, void 0, function* () {
223
+ const mod = yield importOptional("mistral", "@ai-sdk/mistral", () => import('@ai-sdk/mistral'));
224
+ const apiKey = readEnv("MISTRAL_API_KEY");
225
+ const provider = mod.createMistral(apiKey ? { apiKey } : undefined);
226
+ return provider(modelId);
227
+ });
228
+ }
229
+ function createCohereModel(modelId) {
230
+ return __awaiter(this, void 0, void 0, function* () {
231
+ const mod = yield importOptional("cohere", "@ai-sdk/cohere", () => import('@ai-sdk/cohere'));
232
+ const apiKey = readEnv("COHERE_API_KEY");
233
+ const provider = mod.createCohere(apiKey ? { apiKey } : undefined);
234
+ return provider(modelId);
235
+ });
236
+ }
237
+ function createGroqModel(modelId) {
238
+ return __awaiter(this, void 0, void 0, function* () {
239
+ const mod = yield importOptional("groq", "@ai-sdk/groq", () => import('@ai-sdk/groq'));
240
+ const apiKey = readEnv("GROQ_API_KEY");
241
+ const provider = mod.createGroq(apiKey ? { apiKey } : undefined);
242
+ return provider(modelId);
243
+ });
244
+ }
245
+ function createXaiModel(modelId) {
246
+ return __awaiter(this, void 0, void 0, function* () {
247
+ const mod = yield importOptional("xai", "@ai-sdk/xai", () => import('@ai-sdk/xai'));
248
+ const apiKey = readEnv("XAI_API_KEY");
249
+ const provider = mod.createXai(apiKey ? { apiKey } : undefined);
250
+ return provider(modelId);
251
+ });
252
+ }
253
+ function createDeepseekModel(modelId) {
254
+ return __awaiter(this, void 0, void 0, function* () {
255
+ const mod = yield importOptional("deepseek", "@ai-sdk/deepseek", () => import('@ai-sdk/deepseek'));
256
+ const apiKey = readEnv("DEEPSEEK_API_KEY");
257
+ const provider = mod.createDeepSeek(apiKey ? { apiKey } : undefined);
258
+ return provider(modelId);
259
+ });
260
+ }
261
+ function resolveLanguageModel() {
262
+ return __awaiter(this, arguments, void 0, function* (options = {}) {
263
+ var _a, _b, _c;
264
+ const provider = (_a = options.provider) !== null && _a !== void 0 ? _a : detectLlmProvider();
265
+ if (!provider) {
266
+ throw new Error("No LLM provider could be resolved. Set LLM_PROVIDER or a provider API key " +
267
+ "(OPENAI_API_KEY, ANTHROPIC_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY, MISTRAL_API_KEY, " +
268
+ "COHERE_API_KEY, GROQ_API_KEY, XAI_API_KEY, DEEPSEEK_API_KEY), or LLM_BASE_URL for an OpenAI-compatible gateway.");
269
+ }
270
+ const modelId = (_c = (_b = options.model) !== null && _b !== void 0 ? _b : readEnv("LLM_MODEL")) !== null && _c !== void 0 ? _c : defaultModelForProvider(provider);
271
+ switch (provider) {
272
+ case "openai":
273
+ return createOpenAiModel(modelId);
274
+ case "openai-compatible":
275
+ return createOpenAiCompatibleModel(modelId);
276
+ case "anthropic":
277
+ return createAnthropicModel(modelId);
278
+ case "google":
279
+ return createGoogleModel(modelId);
280
+ case "bedrock":
281
+ return createBedrockModel(modelId);
282
+ case "mistral":
283
+ return createMistralModel(modelId);
284
+ case "cohere":
285
+ return createCohereModel(modelId);
286
+ case "groq":
287
+ return createGroqModel(modelId);
288
+ case "xai":
289
+ return createXaiModel(modelId);
290
+ case "deepseek":
291
+ return createDeepseekModel(modelId);
292
+ default: {
293
+ const _exhaustive = provider;
294
+ throw new Error(`Unhandled LLM provider: ${String(_exhaustive)}`);
295
+ }
296
+ }
139
297
  });
140
298
  }
141
-
142
- const DEFAULT_LLM_MAX_DIFF_CHARS = 120000;
143
- 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.
144
- 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.
145
- Explain what changed in terms of behavior, APIs, data, configuration, security, and operational risk. Tie claims to the patch when possible.
146
- Produce a concise, developer-focused summary in Markdown.
147
- 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.
148
- Group related changes; do not list every individual file. When multiple commits appear in the context, briefly separate notable themes by commit when helpful.
149
- If the user message includes a Team line, use that exact team name in the summary title (for example: "## <Team> – Change summary" or similar).`;
150
- 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, " +
151
- "and/or JSON in OPENAI_DEFAULT_HEADERS or LLM_DEFAULT_HEADERS. " +
152
- "Alternatively pass openAiClientProvider to generateSummary or summarizeGitDiff.";
153
299
 
154
300
  function resolveLlmMaxDiffChars(cliOverride) {
155
301
  var _a;
@@ -174,17 +320,33 @@ If the user message includes a Team line, use that exact team name in the summar
174
320
  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`;
175
321
  return diffText.slice(0, maxChars) + marker;
176
322
  }
323
+ function markdownDiffTruncationNotice(originalChars, maxChars) {
324
+ return `> **Truncated diff:** The unified diff was ${originalChars} characters; only the first ${maxChars} were sent to the model. The summary may not reflect the full change set. Narrow the ref range, adjust path filters, or raise \`maxDiffChars\` / \`LLM_MAX_DIFF_CHARS\`—often together with switching to a model whose context window can fit a larger prompt.\n\n`;
325
+ }
326
+ function resolveMaxOutputTokens() {
327
+ var _a;
328
+ const raw = (_a = process.env.LLM_MAX_TOKENS) !== null && _a !== void 0 ? _a : process.env.OPENAI_MAX_TOKENS;
329
+ const parsed = raw !== undefined ? Number.parseInt(raw, 10) : 4000;
330
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : 4000;
331
+ }
177
332
  function generateSummary(input) {
178
333
  return __awaiter(this, void 0, void 0, function* () {
179
- var _a, _b;
180
- const { diffText, fileNames, commits, flags, openAiClientProvider, diffSummary, } = input;
181
- if (!shouldUseLlmGateway() && openAiClientProvider === undefined) {
334
+ var _a;
335
+ const { diffText, fileNames, commits, flags, llmModelProvider, diffSummary, } = input;
336
+ if (!llmModelProvider && !isLlmProviderConfigured()) {
182
337
  throw new Error(LLM_GATEWAY_REQUIRED_MESSAGE);
183
338
  }
184
339
  const maxDiffChars = resolveLlmMaxDiffChars(flags.maxDiffChars);
340
+ const diffTruncated = diffText.length > maxDiffChars;
185
341
  const diffForLlm = truncateUnifiedDiffForLlm(diffText, maxDiffChars);
186
- const userContent = buildOpenAiUserContent(flags, commits, fileNames, diffForLlm, diffSummary);
187
- return callOpenAi(userContent, (_a = flags.model) !== null && _a !== void 0 ? _a : "gpt-4o-mini", (_b = flags.systemPrompt) !== null && _b !== void 0 ? _b : DEFAULT_GIT_DIFF_SYSTEM_PROMPT, openAiClientProvider !== null && openAiClientProvider !== void 0 ? openAiClientProvider : (() => __awaiter(this, void 0, void 0, function* () { return createOpenAiLikeClient(); })));
342
+ const userContent = buildUserContent(flags, commits, fileNames, diffForLlm, diffSummary);
343
+ const systemPrompt = (_a = flags.systemPrompt) !== null && _a !== void 0 ? _a : DEFAULT_GIT_DIFF_SYSTEM_PROMPT;
344
+ const maxOutputTokens = resolveMaxOutputTokens();
345
+ const summary = yield callLlm(userContent, systemPrompt, maxOutputTokens, llmModelProvider, flags);
346
+ if (!diffTruncated) {
347
+ return summary;
348
+ }
349
+ return markdownDiffTruncationNotice(diffText.length, maxDiffChars) + summary;
188
350
  });
189
351
  }
190
352
  function formatRegexFilterLines(flags) {
@@ -207,7 +369,7 @@ If the user message includes a Team line, use that exact team name in the summar
207
369
  return (`${incLine}${excLine}` +
208
370
  "Git context shape: concatenated per-commit unified patches for commits that pass the message filters.\n");
209
371
  }
210
- function buildOpenAiUserContent(flags, commits, fileNames, diffText, diffSummary) {
372
+ function buildUserContent(flags, commits, fileNames, diffText, diffSummary) {
211
373
  var _a, _b;
212
374
  const from = flags.from;
213
375
  const to = (_a = flags.to) !== null && _a !== void 0 ? _a : "HEAD";
@@ -237,31 +399,21 @@ If the user message includes a Team line, use that exact team name in the summar
237
399
  "=== Git context (unified diff(s); patches may be truncated with an explicit marker) ===\n" +
238
400
  diffText);
239
401
  }
240
- function callOpenAi(userContent, model, systemPrompt, openAiClientProvider) {
402
+ function callLlm(userContent, systemPrompt, maxOutputTokens, llmModelProvider, flags) {
241
403
  return __awaiter(this, void 0, void 0, function* () {
242
- var _a, _b, _c, _d, _e, _f;
243
- const client = yield openAiClientProvider();
244
- const maxTokensRaw = (_a = process.env.LLM_MAX_TOKENS) !== null && _a !== void 0 ? _a : process.env.OPENAI_MAX_TOKENS;
245
- const parsed = maxTokensRaw !== undefined ? Number.parseInt(maxTokensRaw, 10) : 4000;
246
- const maxTokens = Number.isFinite(parsed) && parsed > 0 ? parsed : 4000;
247
- const response = yield client.chat.completions.create({
404
+ var _a, _b;
405
+ const model = llmModelProvider
406
+ ? yield llmModelProvider()
407
+ : yield resolveLanguageModel(Object.assign(Object.assign({}, (flags.provider ? { provider: flags.provider } : {})), (flags.model ? { model: flags.model } : {})));
408
+ const result = yield ai.generateText({
248
409
  model,
249
- messages: [
250
- {
251
- role: "system",
252
- content: systemPrompt,
253
- },
254
- {
255
- role: "user",
256
- content: userContent,
257
- },
258
- ],
410
+ system: systemPrompt,
411
+ prompt: userContent,
259
412
  temperature: 0.2,
260
- max_tokens: maxTokens,
413
+ maxOutputTokens,
261
414
  });
262
- const typedResponse = response;
263
- const text = (_f = (_e = (_d = (_c = (_b = typedResponse.choices) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.message) === null || _d === void 0 ? void 0 : _d.content) === null || _e === void 0 ? void 0 : _e.trim()) !== null && _f !== void 0 ? _f : "";
264
- return text.length > 0 ? text : "No summary generated by OpenAI.";
415
+ const text = (_b = (_a = result.text) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : "";
416
+ return text.length > 0 ? text : "No summary generated by the model.";
265
417
  });
266
418
  }
267
419
 
@@ -705,6 +857,7 @@ If the user message includes a Team line, use that exact team name in the summar
705
857
  to,
706
858
  team: options.teamName,
707
859
  model: options.model,
860
+ provider: options.provider,
708
861
  maxDiffChars: options.maxDiffChars,
709
862
  systemPrompt: options.systemPrompt,
710
863
  commitMessageIncludeRegexes: options.commitMessageIncludeRegexes,
@@ -715,7 +868,7 @@ If the user message includes a Team line, use that exact team name in the summar
715
868
  fileNames,
716
869
  commits: filteredCommits,
717
870
  flags: summarizeFlags,
718
- openAiClientProvider: options.openAiClientProvider,
871
+ llmModelProvider: options.llmModelProvider,
719
872
  diffSummary,
720
873
  });
721
874
  });
@@ -725,7 +878,8 @@ If the user message includes a Team line, use that exact team name in the summar
725
878
  exports.LLM_GATEWAY_REQUIRED_MESSAGE = LLM_GATEWAY_REQUIRED_MESSAGE;
726
879
  exports.buildDiffPathspecs = buildDiffPathspecs;
727
880
  exports.createGitClient = createGitClient;
728
- exports.createOpenAiLikeClient = createOpenAiLikeClient;
881
+ exports.defaultModelForProvider = defaultModelForProvider;
882
+ exports.detectLlmProvider = detectLlmProvider;
729
883
  exports.filterCommitsByMessageRegexes = filterCommitsByMessageRegexes;
730
884
  exports.generateSummary = generateSummary;
731
885
  exports.getChangedFiles = getChangedFiles;
@@ -733,12 +887,11 @@ If the user message includes a Team line, use that exact team name in the summar
733
887
  exports.getDiff = getDiff;
734
888
  exports.getDiffSummary = getDiffSummary;
735
889
  exports.getRepoRoot = getRepoRoot;
890
+ exports.isLlmProviderConfigured = isLlmProviderConfigured;
736
891
  exports.parseLlmDefaultHeadersFromEnv = parseLlmDefaultHeadersFromEnv;
892
+ exports.resolveLanguageModel = resolveLanguageModel;
737
893
  exports.resolveLlmBaseUrl = resolveLlmBaseUrl;
738
894
  exports.resolveLlmMaxDiffChars = resolveLlmMaxDiffChars;
739
- exports.resolveOpenAiLikeClientInit = resolveOpenAiLikeClientInit;
740
- exports.shouldUseLlmGateway = shouldUseLlmGateway;
741
- exports.splitPromotableAuthorizationFromHeaders = splitPromotableAuthorizationFromHeaders;
742
895
  exports.summarizeGitDiff = summarizeGitDiff;
743
896
  exports.truncateUnifiedDiffForLlm = truncateUnifiedDiffForLlm;
744
897