gut-cli 0.1.31 → 0.1.33

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 CHANGED
@@ -540,6 +540,48 @@ Each template uses `{{variable}}` syntax for dynamic content.
540
540
 
541
541
  **Special case**: `.github/pull_request_template.md` is prioritized over `pr.md` for PR descriptions.
542
542
 
543
+ ## Custom API Endpoints
544
+
545
+ Configure custom base URLs for AI providers (useful for proxies, local instances, or API-compatible services):
546
+
547
+ ### Global Configuration
548
+ ```bash
549
+ # Set base URL for all AI commands
550
+ gut config set baseUrl https://api.example.com/v1
551
+
552
+ # View current config
553
+ gut config list
554
+ ```
555
+
556
+ ### Per-Command Override
557
+ ```bash
558
+ gut commit --base-url https://api.example.com/v1
559
+ gut pr --base-url https://my-proxy.com
560
+ ```
561
+
562
+ ### Local (Project-Specific)
563
+ ```bash
564
+ gut config set baseUrl https://api.example.com/v1 --local
565
+ ```
566
+
567
+ ### Examples
568
+ ```bash
569
+ # OpenAI-compatible API (Groq)
570
+ gut config set provider openai
571
+ gut config set baseUrl https://api.groq.com/openai/v1
572
+
573
+ # Local Ollama on different port
574
+ gut commit --provider ollama --base-url http://192.168.1.100:11434/api
575
+ ```
576
+
577
+ ### Priority Order
578
+ 1. CLI flag `--base-url` (highest)
579
+ 2. Local config (`.gut/config.json`)
580
+ 3. Global config (`~/.config/gut/config.json`)
581
+ 4. Provider defaults (lowest)
582
+
583
+ **Note**: For Ollama, the legacy `ollamaBaseUrl` config takes priority over `baseUrl` for backward compatibility.
584
+
543
585
  ## Development
544
586
 
545
587
  ```bash
package/dist/index.js CHANGED
@@ -133,6 +133,29 @@ function setProvider(provider, local = false) {
133
133
  setGlobalConfig("provider", provider);
134
134
  }
135
135
  }
136
+ function getBaseUrl() {
137
+ return getConfig().baseUrl;
138
+ }
139
+ function setBaseUrl(url, local = false) {
140
+ if (url === "") {
141
+ const path2 = local ? getLocalConfigPath() : getGlobalConfigPath();
142
+ if (local && !path2) throw new Error("Not in a git repository");
143
+ const config = local ? getLocalConfig() : getGlobalConfig();
144
+ delete config.baseUrl;
145
+ writeFileSync(path2 || getGlobalConfigPath(), JSON.stringify(config, null, 2));
146
+ return;
147
+ }
148
+ try {
149
+ new URL(url);
150
+ } catch {
151
+ throw new Error(`Invalid URL: ${url}`);
152
+ }
153
+ if (local) {
154
+ setLocalConfig("baseUrl", url);
155
+ } else {
156
+ setGlobalConfig("baseUrl", url);
157
+ }
158
+ }
136
159
 
137
160
  // src/lib/credentials.ts
138
161
  var SERVICE_NAME = "gut-cli";
@@ -498,23 +521,31 @@ async function getModel(options) {
498
521
  switch (options.provider) {
499
522
  case "gemini": {
500
523
  const apiKey = await resolveApiKey();
501
- const google = createGoogleGenerativeAI({ apiKey });
524
+ const google = createGoogleGenerativeAI({
525
+ apiKey,
526
+ ...options.baseUrl && { baseURL: options.baseUrl }
527
+ });
502
528
  return google(modelName);
503
529
  }
504
530
  case "openai": {
505
531
  const apiKey = await resolveApiKey();
506
- const openai = createOpenAI({ apiKey });
532
+ const openai = createOpenAI({
533
+ apiKey,
534
+ ...options.baseUrl && { baseURL: options.baseUrl }
535
+ });
507
536
  return openai(modelName);
508
537
  }
509
538
  case "anthropic": {
510
539
  const apiKey = await resolveApiKey();
511
- const anthropic = createAnthropic({ apiKey });
540
+ const anthropic = createAnthropic({
541
+ apiKey,
542
+ ...options.baseUrl && { baseURL: options.baseUrl }
543
+ });
512
544
  return anthropic(modelName);
513
545
  }
514
546
  case "ollama": {
515
- const ollama = createOllama({
516
- baseURL: options.ollamaBaseUrl || "http://localhost:11434/api"
517
- });
547
+ const baseURL = options.ollamaBaseUrl || options.baseUrl || "http://localhost:11434/api";
548
+ const ollama = createOllama({ baseURL });
518
549
  return ollama(modelName);
519
550
  }
520
551
  }
@@ -533,7 +564,7 @@ async function generateCommitMessage(diff, options, template) {
533
564
  const result = await generateText({
534
565
  model,
535
566
  prompt,
536
- maxTokens: 500
567
+ maxTokens: 1024
537
568
  });
538
569
  return result.text.trim();
539
570
  }
@@ -769,7 +800,7 @@ async function generateBranchName(description, options, context, template) {
769
800
  const result = await generateText({
770
801
  model,
771
802
  prompt,
772
- maxTokens: 100
803
+ maxTokens: 1024
773
804
  });
774
805
  return result.text.trim().replace(/[^a-zA-Z0-9/_-]/g, "");
775
806
  }
@@ -787,7 +818,7 @@ async function generateBranchNameFromDiff(diff, options, template) {
787
818
  const result = await generateText({
788
819
  model,
789
820
  prompt,
790
- maxTokens: 100
821
+ maxTokens: 1024
791
822
  });
792
823
  return result.text.trim().replace(/[^a-zA-Z0-9/_-]/g, "");
793
824
  }
@@ -805,7 +836,7 @@ async function generateStashName(diff, options, template) {
805
836
  const result = await generateText({
806
837
  model,
807
838
  prompt,
808
- maxTokens: 100
839
+ maxTokens: 1024
809
840
  });
810
841
  return result.text.trim();
811
842
  }
@@ -983,7 +1014,7 @@ function getIssueInfo(issueNumber) {
983
1014
  return null;
984
1015
  }
985
1016
  }
986
- var branchCommand = new Command2("branch").description("Generate a branch name from issue number or description").argument("[issue]", "Issue number (e.g., 123 or #123)").option("-d, --description <description>", "Use description instead of issue").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("-t, --type <type>", "Branch type (feature, fix, hotfix, chore, refactor)").option("-c, --checkout", "Create and checkout the branch").action(async (issue, options) => {
1017
+ var branchCommand = new Command2("branch").description("Generate a branch name from issue number or description").argument("[issue]", "Issue number (e.g., 123 or #123)").option("-d, --description <description>", "Use description instead of issue").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("-t, --type <type>", "Branch type (feature, fix, hotfix, chore, refactor)").option("-c, --checkout", "Create and checkout the branch").action(async (issue, options) => {
987
1018
  const git = simpleGit();
988
1019
  const repoRoot = await git.revparse(["--show-toplevel"]).catch(() => process.cwd());
989
1020
  const isRepo = await git.checkIsRepo();
@@ -1029,7 +1060,12 @@ ${issueInfo.body || ""}`;
1029
1060
  try {
1030
1061
  const branchName = await generateBranchName(
1031
1062
  description,
1032
- { provider, model: options.model },
1063
+ {
1064
+ provider,
1065
+ model: options.model,
1066
+ baseUrl: options.baseUrl || getBaseUrl(),
1067
+ language: getLanguage()
1068
+ },
1033
1069
  { type: options.type, issue: issueNumber },
1034
1070
  template || void 0
1035
1071
  );
@@ -1090,7 +1126,7 @@ function formatChangelog(changelog) {
1090
1126
  }
1091
1127
  return lines.join("\n");
1092
1128
  }
1093
- var changelogCommand = new Command3("changelog").description("Generate a changelog from commits between refs").argument("[from]", "Starting ref (tag, branch, commit)", "HEAD~10").argument("[to]", "Ending ref", "HEAD").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("-t, --tag <tag>", "Generate changelog since this tag").option("--json", "Output as JSON").action(async (from, to, options) => {
1129
+ var changelogCommand = new Command3("changelog").description("Generate a changelog from commits between refs").argument("[from]", "Starting ref (tag, branch, commit)", "HEAD~10").argument("[to]", "Ending ref", "HEAD").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("-t, --tag <tag>", "Generate changelog since this tag").option("--json", "Output as JSON").action(async (from, to, options) => {
1094
1130
  const git = simpleGit2();
1095
1131
  const isRepo = await git.checkIsRepo();
1096
1132
  if (!isRepo) {
@@ -1126,7 +1162,12 @@ var changelogCommand = new Command3("changelog").description("Generate a changel
1126
1162
  }
1127
1163
  const changelog = await generateChangelog(
1128
1164
  { commits, diff, fromRef, toRef },
1129
- { provider, model: options.model },
1165
+ {
1166
+ provider,
1167
+ model: options.model,
1168
+ baseUrl: options.baseUrl || getBaseUrl(),
1169
+ language: getLanguage()
1170
+ },
1130
1171
  template || void 0
1131
1172
  );
1132
1173
  spinner.stop();
@@ -1155,7 +1196,7 @@ import chalk5 from "chalk";
1155
1196
  import { Command as Command4 } from "commander";
1156
1197
  import ora3 from "ora";
1157
1198
  import { simpleGit as simpleGit3 } from "simple-git";
1158
- var checkoutCommand = new Command4("checkout").description("Generate a branch name from current diff and checkout").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("-y, --yes", "Skip confirmation and checkout directly").option("-s, --staged", "Use staged changes only instead of all changes").action(async (options) => {
1199
+ var checkoutCommand = new Command4("checkout").description("Generate a branch name from current diff and checkout").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("-y, --yes", "Skip confirmation and checkout directly").option("-s, --staged", "Use staged changes only instead of all changes").action(async (options) => {
1159
1200
  const git = simpleGit3();
1160
1201
  const isRepo = await git.checkIsRepo();
1161
1202
  if (!isRepo) {
@@ -1194,7 +1235,12 @@ ${untrackedFiles.map((f) => `+ ${f}`).join("\n")}`;
1194
1235
  try {
1195
1236
  const branchName = await generateBranchNameFromDiff(
1196
1237
  diff,
1197
- { provider, model: options.model },
1238
+ {
1239
+ provider,
1240
+ model: options.model,
1241
+ baseUrl: options.baseUrl || getBaseUrl(),
1242
+ language: getLanguage()
1243
+ },
1198
1244
  template
1199
1245
  );
1200
1246
  spinner.stop();
@@ -1316,7 +1362,7 @@ import chalk7 from "chalk";
1316
1362
  import { Command as Command6 } from "commander";
1317
1363
  import ora5 from "ora";
1318
1364
  import { simpleGit as simpleGit5 } from "simple-git";
1319
- var commitCommand = new Command6("commit").description("Generate a commit message using AI").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("-c, --commit", "Automatically commit with the generated message").option("-a, --all", "Force stage all changes (default: auto-stage if nothing staged)").action(async (options) => {
1365
+ var commitCommand = new Command6("commit").description("Generate a commit message using AI").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("-c, --commit", "Automatically commit with the generated message").option("-a, --all", "Force stage all changes (default: auto-stage if nothing staged)").action(async (options) => {
1320
1366
  const git = simpleGit5();
1321
1367
  const repoRoot = await git.revparse(["--show-toplevel"]).catch(() => process.cwd());
1322
1368
  const isRepo = await git.checkIsRepo();
@@ -1349,7 +1395,12 @@ var commitCommand = new Command6("commit").description("Generate a commit messag
1349
1395
  try {
1350
1396
  const message = await generateCommitMessage(
1351
1397
  diff,
1352
- { provider, model: options.model },
1398
+ {
1399
+ provider,
1400
+ model: options.model,
1401
+ baseUrl: options.baseUrl || getBaseUrl(),
1402
+ language: getLanguage()
1403
+ },
1353
1404
  template || void 0
1354
1405
  );
1355
1406
  spinner.stop();
@@ -1468,9 +1519,19 @@ configCommand.command("set <key> <value>").description("Set a configuration valu
1468
1519
  console.error(chalk8.red(err.message));
1469
1520
  process.exit(1);
1470
1521
  }
1522
+ } else if (key === "baseUrl") {
1523
+ try {
1524
+ setBaseUrl(value, options.local ?? false);
1525
+ const scope = options.local ? "(local)" : "(global)";
1526
+ console.log(chalk8.green(`\u2713 Base URL set to: ${value} ${scope}`));
1527
+ console.log(chalk8.gray("Applies to all AI providers (OpenAI, Anthropic, Gemini, Ollama)"));
1528
+ } catch (err) {
1529
+ console.error(chalk8.red(err.message));
1530
+ process.exit(1);
1531
+ }
1471
1532
  } else {
1472
1533
  console.error(chalk8.red(`Unknown config key: ${key}`));
1473
- console.error(chalk8.gray("Available keys: lang, model, provider"));
1534
+ console.error(chalk8.gray("Available keys: lang, model, provider, baseUrl"));
1474
1535
  process.exit(1);
1475
1536
  }
1476
1537
  });
@@ -1543,7 +1604,7 @@ import { simpleGit as simpleGit7 } from "simple-git";
1543
1604
  var explainCommand = new Command8("explain").description("Get an AI-powered explanation of changes, commits, PRs, or files").argument(
1544
1605
  "[target]",
1545
1606
  "Commit hash, PR number, PR URL, or file path (default: uncommitted changes)"
1546
- ).option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("-s, --staged", "Explain only staged changes").option("-n, --commits <n>", "Number of commits to analyze for file history (default: 1)", "1").option("--history", "Explain file change history instead of content").option("--json", "Output as JSON").action(async (target, options) => {
1607
+ ).option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("-s, --staged", "Explain only staged changes").option("-n, --commits <n>", "Number of commits to analyze for file history (default: 1)", "1").option("--history", "Explain file change history instead of content").option("--json", "Output as JSON").action(async (target, options) => {
1547
1608
  const git = simpleGit7();
1548
1609
  const isRepo = await git.checkIsRepo();
1549
1610
  if (!isRepo) {
@@ -1595,7 +1656,12 @@ var explainCommand = new Command8("explain").description("Get an AI-powered expl
1595
1656
  spinner.text = "AI is generating explanation...";
1596
1657
  const explanation = await generateExplanation(
1597
1658
  context,
1598
- { provider, model: options.model },
1659
+ {
1660
+ provider,
1661
+ model: options.model,
1662
+ baseUrl: options.baseUrl || getBaseUrl(),
1663
+ language: getLanguage()
1664
+ },
1599
1665
  template || void 0
1600
1666
  );
1601
1667
  spinner.stop();
@@ -1794,7 +1860,7 @@ import { simpleGit as simpleGit8 } from "simple-git";
1794
1860
  var findCommand = new Command9("find").description("Find commits matching a vague description using AI").argument(
1795
1861
  "<query>",
1796
1862
  'Description of the change you are looking for (e.g., "login feature added")'
1797
- ).option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("-n, --num <n>", "Number of commits to search through", "100").option("--path <path>", "Limit search to commits affecting this path").option("--author <author>", "Limit search to commits by this author").option("--since <date>", "Limit search to commits after this date").option("--until <date>", "Limit search to commits before this date").option("--max-results <n>", "Maximum number of matching commits to return", "5").option("--json", "Output as JSON").action(async (query, options) => {
1863
+ ).option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("-n, --num <n>", "Number of commits to search through", "100").option("--path <path>", "Limit search to commits affecting this path").option("--author <author>", "Limit search to commits by this author").option("--since <date>", "Limit search to commits after this date").option("--until <date>", "Limit search to commits before this date").option("--max-results <n>", "Maximum number of matching commits to return", "5").option("--json", "Output as JSON").action(async (query, options) => {
1798
1864
  const git = simpleGit8();
1799
1865
  const isRepo = await git.checkIsRepo();
1800
1866
  if (!isRepo) {
@@ -1836,7 +1902,12 @@ var findCommand = new Command9("find").description("Find commits matching a vagu
1836
1902
  const results = await searchCommits(
1837
1903
  query,
1838
1904
  commits,
1839
- { provider, model: options.model },
1905
+ {
1906
+ provider,
1907
+ model: options.model,
1908
+ baseUrl: options.baseUrl || getBaseUrl(),
1909
+ language: getLanguage()
1910
+ },
1840
1911
  parseInt(options.maxResults, 10),
1841
1912
  template || void 0
1842
1913
  );
@@ -1984,7 +2055,7 @@ function findConfigFiles(repoRoot) {
1984
2055
  }
1985
2056
  return found;
1986
2057
  }
1987
- var gitignoreCommand = new Command10("gitignore").description("Generate .gitignore from current codebase").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("-o, --output <file>", "Output file (default: .gitignore)", ".gitignore").option("--stdout", "Print to stdout instead of file").option("-y, --yes", "Overwrite existing .gitignore without confirmation").action(async (options) => {
2058
+ var gitignoreCommand = new Command10("gitignore").description("Generate .gitignore from current codebase").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("-o, --output <file>", "Output file (default: .gitignore)", ".gitignore").option("--stdout", "Print to stdout instead of file").option("-y, --yes", "Overwrite existing .gitignore without confirmation").action(async (options) => {
1988
2059
  const git = simpleGit9();
1989
2060
  const repoRoot = await git.revparse(["--show-toplevel"]).catch(() => process.cwd());
1990
2061
  const root = repoRoot.trim();
@@ -2020,7 +2091,12 @@ ${content}
2020
2091
  configFiles: configFilesStr,
2021
2092
  existingGitignore
2022
2093
  },
2023
- { provider, model: options.model },
2094
+ {
2095
+ provider,
2096
+ model: options.model,
2097
+ baseUrl: options.baseUrl || getBaseUrl(),
2098
+ language: getLanguage()
2099
+ },
2024
2100
  template || void 0
2025
2101
  );
2026
2102
  spinner.stop();
@@ -2279,7 +2355,7 @@ import chalk14 from "chalk";
2279
2355
  import { Command as Command13 } from "commander";
2280
2356
  import ora10 from "ora";
2281
2357
  import { simpleGit as simpleGit11 } from "simple-git";
2282
- var mergeCommand = new Command13("merge").description("Merge a branch with AI-powered conflict resolution").argument("<branch>", "Branch to merge").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--no-commit", "Do not auto-commit after resolving").action(async (branch, options) => {
2358
+ var mergeCommand = new Command13("merge").description("Merge a branch with AI-powered conflict resolution").argument("<branch>", "Branch to merge").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("--no-commit", "Do not auto-commit after resolving").action(async (branch, options) => {
2283
2359
  const git = simpleGit11();
2284
2360
  const isRepo = await git.checkIsRepo();
2285
2361
  if (!isRepo) {
@@ -2342,7 +2418,12 @@ Merging ${chalk14.cyan(branch)} into ${chalk14.cyan(currentBranch)}...
2342
2418
  oursRef: currentBranch,
2343
2419
  theirsRef: branch
2344
2420
  },
2345
- { provider, model: options.model },
2421
+ {
2422
+ provider,
2423
+ model: options.model,
2424
+ baseUrl: options.baseUrl || getBaseUrl(),
2425
+ language: getLanguage()
2426
+ },
2346
2427
  template || void 0
2347
2428
  );
2348
2429
  spinner.stop();
@@ -2416,7 +2497,7 @@ function findPRTemplate(repoRoot) {
2416
2497
  }
2417
2498
  return findTemplate(repoRoot, "pr");
2418
2499
  }
2419
- var prCommand = new Command14("pr").description("Generate a pull request title and description using AI").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("-b, --base <branch>", "Base branch to compare against (default: main or master)").option("--create", "Create the PR using gh CLI").option("--copy", "Copy the description to clipboard").action(async (options) => {
2500
+ var prCommand = new Command14("pr").description("Generate a pull request title and description using AI").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("-b, --base <branch>", "Base branch to compare against (default: main or master)").option("--create", "Create the PR using gh CLI").option("--copy", "Copy the description to clipboard").action(async (options) => {
2420
2501
  const git = simpleGit12();
2421
2502
  const isRepo = await git.checkIsRepo();
2422
2503
  if (!isRepo) {
@@ -2467,7 +2548,12 @@ var prCommand = new Command14("pr").description("Generate a pull request title a
2467
2548
  commits,
2468
2549
  diff
2469
2550
  },
2470
- { provider, model: options.model },
2551
+ {
2552
+ provider,
2553
+ model: options.model,
2554
+ baseUrl: options.baseUrl || getBaseUrl(),
2555
+ language: getLanguage()
2556
+ },
2471
2557
  template || void 0
2472
2558
  );
2473
2559
  spinner.stop();
@@ -2633,7 +2719,7 @@ async function getPRDiff(prNumber) {
2633
2719
  throw err;
2634
2720
  }
2635
2721
  }
2636
- var reviewCommand = new Command15("review").description("Get an AI code review of your changes or a GitHub PR").argument("[pr-number]", "GitHub PR number to review").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("-s, --staged", "Review only staged changes").option("-c, --commit <hash>", "Review a specific commit").option("--json", "Output as JSON").action(async (prNumber, options) => {
2722
+ var reviewCommand = new Command15("review").description("Get an AI code review of your changes or a GitHub PR").argument("[pr-number]", "GitHub PR number to review").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("-s, --staged", "Review only staged changes").option("-c, --commit <hash>", "Review a specific commit").option("--json", "Output as JSON").action(async (prNumber, options) => {
2637
2723
  const git = simpleGit13();
2638
2724
  const isRepo = await git.checkIsRepo();
2639
2725
  if (!isRepo) {
@@ -2677,7 +2763,12 @@ ${diff}`;
2677
2763
  const template = findTemplate(repoRoot.trim(), "review");
2678
2764
  const review = await generateCodeReview(
2679
2765
  diff,
2680
- { provider, model: options.model },
2766
+ {
2767
+ provider,
2768
+ model: options.model,
2769
+ baseUrl: options.baseUrl || getBaseUrl(),
2770
+ language: getLanguage()
2771
+ },
2681
2772
  template || void 0
2682
2773
  );
2683
2774
  spinner.stop();
@@ -2749,7 +2840,7 @@ import chalk17 from "chalk";
2749
2840
  import { Command as Command16 } from "commander";
2750
2841
  import ora13 from "ora";
2751
2842
  import { simpleGit as simpleGit14 } from "simple-git";
2752
- var stashCommand = new Command16("stash").description("Stash changes with AI-generated name").argument("[name]", "Custom stash name (skips AI generation)").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("-l, --list", "List all stashes").option("-a, --apply [index]", "Apply stash (default: latest)").option("--pop [index]", "Pop stash (default: latest)").option("-d, --drop [index]", "Drop stash").option("--clear", "Clear all stashes").action(async (name, options) => {
2843
+ var stashCommand = new Command16("stash").description("Stash changes with AI-generated name").argument("[name]", "Custom stash name (skips AI generation)").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("-l, --list", "List all stashes").option("-a, --apply [index]", "Apply stash (default: latest)").option("--pop [index]", "Pop stash (default: latest)").option("-d, --drop [index]", "Drop stash").option("--clear", "Clear all stashes").action(async (name, options) => {
2753
2844
  const git = simpleGit14();
2754
2845
  const isRepo = await git.checkIsRepo();
2755
2846
  if (!isRepo) {
@@ -2851,7 +2942,12 @@ ${stagedDiff}`;
2851
2942
  const template = findTemplate(repoRoot.trim(), "stash");
2852
2943
  stashName = await generateStashName(
2853
2944
  fullDiff,
2854
- { provider, model: options.model },
2945
+ {
2946
+ provider,
2947
+ model: options.model,
2948
+ baseUrl: options.baseUrl || getBaseUrl(),
2949
+ language: getLanguage()
2950
+ },
2855
2951
  template || void 0
2856
2952
  );
2857
2953
  spinner.stop();
@@ -2870,7 +2966,7 @@ import chalk18 from "chalk";
2870
2966
  import { Command as Command17 } from "commander";
2871
2967
  import ora14 from "ora";
2872
2968
  import { simpleGit as simpleGit15 } from "simple-git";
2873
- var summaryCommand = new Command17("summary").description("Generate a work summary from your commits (for daily/weekly reports)").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--since <date>", "Start date (default: today)", "today").option("--until <date>", "End date").option("--author <author>", "Filter by author (default: current user)").option("--daily", "Generate daily report (alias for --since today)").option("--weekly", 'Generate weekly report (alias for --since "1 week ago")').option("--with-diff", "Include diff analysis for more detail").option("--markdown", "Output as markdown").option("--json", "Output as JSON").option("--copy", "Copy to clipboard").action(async (options) => {
2969
+ var summaryCommand = new Command17("summary").description("Generate a work summary from your commits (for daily/weekly reports)").option("-p, --provider <provider>", "AI provider (gemini, openai, anthropic, ollama)").option("-m, --model <model>", "Model to use (provider-specific)").option("--base-url <url>", "Base URL for API provider").option("--since <date>", "Start date (default: today)", "today").option("--until <date>", "End date").option("--author <author>", "Filter by author (default: current user)").option("--daily", "Generate daily report (alias for --since today)").option("--weekly", 'Generate weekly report (alias for --since "1 week ago")').option("--with-diff", "Include diff analysis for more detail").option("--markdown", "Output as markdown").option("--json", "Output as JSON").option("--copy", "Copy to clipboard").action(async (options) => {
2874
2970
  const git = simpleGit15();
2875
2971
  const isRepo = await git.checkIsRepo();
2876
2972
  if (!isRepo) {
@@ -2930,7 +3026,12 @@ var summaryCommand = new Command17("summary").description("Generate a work summa
2930
3026
  const template = findTemplate(repoRoot.trim(), "summary");
2931
3027
  const summary = await generateWorkSummary(
2932
3028
  { commits, author, since, until: options.until, diff },
2933
- { provider, model: options.model },
3029
+ {
3030
+ provider,
3031
+ model: options.model,
3032
+ baseUrl: options.baseUrl || getBaseUrl(),
3033
+ language: getLanguage()
3034
+ },
2934
3035
  format,
2935
3036
  template || void 0
2936
3037
  );