commit-whisper 1.0.7 → 1.0.8

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.
Files changed (2) hide show
  1. package/dist/index.js +34 -12
  2. package/package.json +10 -10
package/dist/index.js CHANGED
@@ -163,6 +163,7 @@ function readProcessEnv() {
163
163
  }
164
164
 
165
165
  // src/config/config-store.ts
166
+ import { randomBytes } from "crypto";
166
167
  import { join } from "path";
167
168
  import { mkdir, readFile, rename, unlink, writeFile } from "fs/promises";
168
169
  var PROVIDERS2 = /* @__PURE__ */ new Set(["ollama", "openai", "gemini", "anthropic", "openai-compatible"]);
@@ -289,7 +290,7 @@ async function writeSettings(env, data, io = defaultConfigStoreIo) {
289
290
  return finalPath;
290
291
  }
291
292
  function randomSuffix() {
292
- return Math.random().toString(36).slice(2, 10);
293
+ return randomBytes(6).toString("hex");
293
294
  }
294
295
 
295
296
  // src/config/sources.ts
@@ -493,6 +494,15 @@ function resolveRunConfig(input) {
493
494
  });
494
495
  }
495
496
 
497
+ // src/shared/url.ts
498
+ function stripTrailingSlashes(value) {
499
+ let end = value.length;
500
+ while (end > 0 && value.codePointAt(end - 1) === 47) {
501
+ end -= 1;
502
+ }
503
+ return value.slice(0, end);
504
+ }
505
+
496
506
  // src/narrate/preflight.ts
497
507
  var OLLAMA_DEFAULT_BASE_URL = "http://localhost:11434";
498
508
  var GEMINI_MODELS_URL = "https://generativelanguage.googleapis.com/v1beta/models";
@@ -528,7 +538,7 @@ function cleanBaseUrl(baseUrl) {
528
538
  if (baseUrl === void 0) {
529
539
  return void 0;
530
540
  }
531
- const trimmed = baseUrl.trim().replace(/\/+$/, "");
541
+ const trimmed = stripTrailingSlashes(baseUrl.trim());
532
542
  return trimmed === "" ? void 0 : trimmed;
533
543
  }
534
544
  function classifyModelsResponse(res, providerLabel) {
@@ -765,7 +775,7 @@ function mapValidate(json) {
765
775
  function resolveClient(deps) {
766
776
  return {
767
777
  doFetch: deps.fetchImpl ?? fetch,
768
- apiBase: (deps.apiBase ?? DEFAULT_API_BASE).replace(/\/+$/, ""),
778
+ apiBase: stripTrailingSlashes(deps.apiBase ?? DEFAULT_API_BASE),
769
779
  timeoutMs: deps.timeoutMs ?? DEFAULT_TIMEOUT_MS2
770
780
  };
771
781
  }
@@ -815,6 +825,7 @@ function createLemonSqueezyDeactivator(deps = {}) {
815
825
  }
816
826
 
817
827
  // src/license/store.ts
828
+ import { randomBytes as randomBytes2 } from "crypto";
818
829
  import { join as join2 } from "path";
819
830
  import { mkdir as mkdir2, readFile as readFile2, rename as rename2, unlink as unlink2, writeFile as writeFile2 } from "fs/promises";
820
831
  var LICENSE_FILE_NAME = "license.json";
@@ -902,7 +913,7 @@ async function clearLicenseCache(env, io = defaultLicenseStoreIo) {
902
913
  await io.unlink(licenseFilePath(env));
903
914
  }
904
915
  function randomSuffix2() {
905
- return Math.random().toString(36).slice(2, 10);
916
+ return randomBytes2(6).toString("hex");
906
917
  }
907
918
 
908
919
  // src/retrieve/git.ts
@@ -2098,7 +2109,7 @@ var ownershipByArea = (model) => {
2098
2109
  topFiles: topAreas(fileAreas, HOTSPOT_TOP_FILES)
2099
2110
  });
2100
2111
  };
2101
- var CO_AUTHOR_TRAILER = /^[ \t]*co-authored-by:[ \t]*(.+?)[ \t]*$/gim;
2112
+ var CO_AUTHOR_TRAILER = /^[ \t]*co-authored-by:[ \t]*(.+)$/gim;
2102
2113
  function coAuthorKey(trailer) {
2103
2114
  const angle = /<([^<>]+)>/.exec(trailer);
2104
2115
  return (angle ? angle[1] : trailer).trim().toLowerCase();
@@ -3529,7 +3540,11 @@ function resolveModel(config) {
3529
3540
  return createOpenAICompatible({ name: "openai-compatible", baseURL, apiKey: config.aiKey?.reveal() })(model);
3530
3541
  }
3531
3542
  case "ollama": {
3532
- const baseURL = `${cleanBaseUrl2(config.llmBaseUrl) ?? OLLAMA_DEFAULT_BASE_URL2}/v1`.replace(/(\/v1)+$/, "/v1");
3543
+ let base = cleanBaseUrl2(config.llmBaseUrl) ?? OLLAMA_DEFAULT_BASE_URL2;
3544
+ while (base.endsWith("/v1")) {
3545
+ base = base.slice(0, -3);
3546
+ }
3547
+ const baseURL = `${base}/v1`;
3533
3548
  return createOpenAICompatible({ name: "ollama", baseURL })(model);
3534
3549
  }
3535
3550
  case void 0:
@@ -3565,7 +3580,7 @@ function cleanBaseUrl2(baseUrl) {
3565
3580
  if (baseUrl === void 0) {
3566
3581
  return void 0;
3567
3582
  }
3568
- const trimmed = baseUrl.trim().replace(/\/+$/, "");
3583
+ const trimmed = stripTrailingSlashes(baseUrl.trim());
3569
3584
  return trimmed === "" ? void 0 : trimmed;
3570
3585
  }
3571
3586
  function assertNeverProvider(provider) {
@@ -4810,10 +4825,17 @@ function resolveNumstatPath(raw) {
4810
4825
  if (!raw.includes(" => ")) {
4811
4826
  return raw;
4812
4827
  }
4813
- const brace = /^(.*)\{(.*) => (.*)\}(.*)$/.exec(raw);
4814
- if (brace) {
4815
- const [, prefix, , next, suffix] = brace;
4816
- return `${prefix}${next}${suffix}`.replace(/\/{2,}/g, "/");
4828
+ const open2 = raw.indexOf("{");
4829
+ const close = open2 === -1 ? -1 : raw.indexOf("}", open2 + 1);
4830
+ if (open2 !== -1 && close !== -1) {
4831
+ const inside = raw.slice(open2 + 1, close);
4832
+ const arrow = inside.indexOf(" => ");
4833
+ if (arrow !== -1) {
4834
+ const prefix = raw.slice(0, open2);
4835
+ const next = inside.slice(arrow + " => ".length);
4836
+ const suffix = raw.slice(close + 1);
4837
+ return `${prefix}${next}${suffix}`.replace(/\/{2,}/g, "/");
4838
+ }
4817
4839
  }
4818
4840
  return raw.slice(raw.indexOf(" => ") + " => ".length);
4819
4841
  }
@@ -5242,7 +5264,7 @@ function formatShowConfig(config, secrets) {
5242
5264
  }
5243
5265
 
5244
5266
  // src/cli/version.ts
5245
- var VERSION = "1.0.7";
5267
+ var VERSION = "1.0.8";
5246
5268
 
5247
5269
  // src/cli/cli.ts
5248
5270
  var PROVIDERS3 = ["ollama", "openai", "gemini", "anthropic", "openai-compatible"];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "commit-whisper",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "Deterministic git history analysis with a grounded, BYOK AI narrative — terminal-native CLI.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -45,24 +45,24 @@
45
45
  },
46
46
  "homepage": "https://github.com/georgiosnikitas/commit-whisper#readme",
47
47
  "dependencies": {
48
- "@ai-sdk/anthropic": "3.0.84",
49
- "@ai-sdk/google": "3.0.82",
50
- "@ai-sdk/openai": "3.0.71",
51
- "@ai-sdk/openai-compatible": "2.0.50",
48
+ "@ai-sdk/anthropic": "3.0.85",
49
+ "@ai-sdk/google": "3.0.83",
50
+ "@ai-sdk/openai": "3.0.72",
51
+ "@ai-sdk/openai-compatible": "2.0.51",
52
52
  "@clack/prompts": "1.5.1",
53
- "ai": "6.0.203",
53
+ "ai": "6.0.207",
54
54
  "commander": "15.0.0",
55
55
  "picocolors": "1.1.1",
56
56
  "zod": "4.4.3"
57
57
  },
58
58
  "devDependencies": {
59
- "@types/node": "22.19.21",
60
- "@vitest/coverage-v8": "4.1.8",
59
+ "@types/node": "25.9.3",
60
+ "@vitest/coverage-v8": "4.1.9",
61
61
  "eslint": "10.5.0",
62
62
  "tsup": "8.5.1",
63
63
  "typescript": "6.0.3",
64
- "typescript-eslint": "8.61.0",
65
- "vitest": "4.1.8"
64
+ "typescript-eslint": "8.61.1",
65
+ "vitest": "4.1.9"
66
66
  },
67
67
  "overrides": {
68
68
  "esbuild": "^0.28.1"