gitpt 1.6.1 → 1.7.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.
Files changed (127) hide show
  1. package/README.md +34 -167
  2. package/dist/commands/commit/commitFlags.js +7 -0
  3. package/dist/commands/commit/context/buildPrompt.js +13 -10
  4. package/dist/commands/commit/context/summaryPrompt.js +5 -2
  5. package/dist/commands/commit/context/systemPrompt.js +4 -1
  6. package/dist/commands/commit/context/userPrompt.js +4 -1
  7. package/dist/commands/commit/generateCommitMessage.js +14 -17
  8. package/dist/commands/commit/index.js +186 -179
  9. package/dist/commands/commit/summarizeDiff.js +183 -162
  10. package/dist/commands/config.js +24 -9
  11. package/dist/commands/hook/index.js +68 -0
  12. package/dist/commands/middleware/capabilitiesMiddleware/ghCapability.js +20 -20
  13. package/dist/commands/middleware/capabilitiesMiddleware/gitCapability.js +13 -10
  14. package/dist/commands/middleware/capabilitiesMiddleware/index.js +12 -11
  15. package/dist/commands/middleware/hasStagedChangesMiddleware.js +9 -6
  16. package/dist/commands/middleware/setupMiddleware/defaultModels.js +14 -10
  17. package/dist/commands/middleware/setupMiddleware/index.js +65 -71
  18. package/dist/commands/model.js +7 -4
  19. package/dist/commands/passthroughArgs.js +11 -0
  20. package/dist/commands/pr/context/systemPrompt.js +4 -1
  21. package/dist/commands/pr/context/userPrompt.js +4 -1
  22. package/dist/commands/pr/generatePRDetails.js +24 -23
  23. package/dist/commands/pr/getPRContext.js +37 -62
  24. package/dist/commands/pr/index.js +57 -62
  25. package/dist/commands/reset.js +23 -23
  26. package/dist/commands/review/index.js +31 -0
  27. package/dist/commands/setup.js +38 -13
  28. package/dist/config.js +63 -60
  29. package/dist/index.js +30 -67
  30. package/dist/llm/budget.js +10 -0
  31. package/dist/llm/index.js +12 -7
  32. package/dist/llm/providers/anthropic/index.js +30 -30
  33. package/dist/llm/providers/apiKey.js +36 -35
  34. package/dist/llm/providers/apple/client.js +73 -83
  35. package/dist/llm/providers/apple/index.js +64 -72
  36. package/dist/llm/providers/apple/models.js +27 -19
  37. package/dist/llm/providers/base.js +36 -36
  38. package/dist/llm/providers/local/index.js +79 -91
  39. package/dist/llm/providers/openai/index.js +19 -16
  40. package/dist/llm/providers/openaiCompatible.js +59 -62
  41. package/dist/llm/providers/openrouter/index.js +18 -15
  42. package/dist/llm/registry.js +30 -34
  43. package/dist/llm/setup/getAvailableModels.js +15 -9
  44. package/dist/llm/setup/selectModel.js +36 -44
  45. package/dist/llm/tokenCount.js +4 -3
  46. package/dist/package.js +67 -0
  47. package/dist/services/gh/createPullRequest.js +38 -58
  48. package/dist/services/gh/index.js +6 -3
  49. package/dist/services/gh/isAvailable.js +10 -8
  50. package/dist/services/git/executeGitAdd.js +11 -12
  51. package/dist/services/git/executeGitCommit.js +10 -11
  52. package/dist/services/git/getAmendChanges.js +23 -0
  53. package/dist/services/git/getChangedFiles.js +28 -61
  54. package/dist/services/git/getCommitsSinceBaseBranch.js +28 -56
  55. package/dist/services/git/getCurrentBranch.js +10 -8
  56. package/dist/services/git/getDefaultBranch.js +35 -60
  57. package/dist/services/git/getStagedChanges.js +10 -8
  58. package/dist/services/git/getStagedFiles.js +10 -9
  59. package/dist/services/git/hasStagedChanges.js +9 -8
  60. package/dist/services/git/index.js +17 -12
  61. package/dist/services/git/isAvailable.js +10 -8
  62. package/dist/services/git/isGitRepository.js +10 -8
  63. package/dist/utils/commitlint.js +97 -135
  64. package/dist/utils/formatBaseURL.js +7 -6
  65. package/dist/utils/maskApiKey.js +6 -7
  66. package/package.json +14 -4
  67. package/dist/commands/commit/context/buildPrompt.d.ts +0 -4
  68. package/dist/commands/commit/context/summaryPrompt.d.ts +0 -2
  69. package/dist/commands/commit/context/systemPrompt.d.ts +0 -1
  70. package/dist/commands/commit/context/userPrompt.d.ts +0 -1
  71. package/dist/commands/commit/generateCommitMessage.d.ts +0 -1
  72. package/dist/commands/commit/index.d.ts +0 -7
  73. package/dist/commands/commit/summarizeDiff.d.ts +0 -1
  74. package/dist/commands/config.d.ts +0 -1
  75. package/dist/commands/middleware/capabilitiesMiddleware/ghCapability.d.ts +0 -1
  76. package/dist/commands/middleware/capabilitiesMiddleware/gitCapability.d.ts +0 -1
  77. package/dist/commands/middleware/capabilitiesMiddleware/index.d.ts +0 -3
  78. package/dist/commands/middleware/hasStagedChangesMiddleware.d.ts +0 -1
  79. package/dist/commands/middleware/setupMiddleware/defaultModels.d.ts +0 -8
  80. package/dist/commands/middleware/setupMiddleware/index.d.ts +0 -4
  81. package/dist/commands/model.d.ts +0 -1
  82. package/dist/commands/pr/context/systemPrompt.d.ts +0 -1
  83. package/dist/commands/pr/context/userPrompt.d.ts +0 -1
  84. package/dist/commands/pr/generatePRDetails.d.ts +0 -4
  85. package/dist/commands/pr/getPRContext.d.ts +0 -1
  86. package/dist/commands/pr/index.d.ts +0 -10
  87. package/dist/commands/reset.d.ts +0 -3
  88. package/dist/commands/setup.d.ts +0 -3
  89. package/dist/config.d.ts +0 -14
  90. package/dist/index.d.ts +0 -2
  91. package/dist/llm/client.d.ts +0 -24
  92. package/dist/llm/client.js +0 -1
  93. package/dist/llm/index.d.ts +0 -6
  94. package/dist/llm/providers/anthropic/index.d.ts +0 -9
  95. package/dist/llm/providers/apiKey.d.ts +0 -3
  96. package/dist/llm/providers/apple/client.d.ts +0 -3
  97. package/dist/llm/providers/apple/index.d.ts +0 -13
  98. package/dist/llm/providers/apple/models.d.ts +0 -14
  99. package/dist/llm/providers/base.d.ts +0 -30
  100. package/dist/llm/providers/local/index.d.ts +0 -11
  101. package/dist/llm/providers/openai/index.d.ts +0 -10
  102. package/dist/llm/providers/openaiCompatible.d.ts +0 -15
  103. package/dist/llm/providers/openrouter/index.d.ts +0 -9
  104. package/dist/llm/registry.d.ts +0 -8
  105. package/dist/llm/setup/getAvailableModels.d.ts +0 -5
  106. package/dist/llm/setup/selectModel.d.ts +0 -5
  107. package/dist/llm/setup/types.d.ts +0 -13
  108. package/dist/llm/setup/types.js +0 -1
  109. package/dist/llm/tokenCount.d.ts +0 -3
  110. package/dist/services/gh/createPullRequest.d.ts +0 -1
  111. package/dist/services/gh/index.d.ts +0 -4
  112. package/dist/services/gh/isAvailable.d.ts +0 -1
  113. package/dist/services/git/executeGitAdd.d.ts +0 -1
  114. package/dist/services/git/executeGitCommit.d.ts +0 -1
  115. package/dist/services/git/getChangedFiles.d.ts +0 -1
  116. package/dist/services/git/getCommitsSinceBaseBranch.d.ts +0 -1
  117. package/dist/services/git/getCurrentBranch.d.ts +0 -1
  118. package/dist/services/git/getDefaultBranch.d.ts +0 -1
  119. package/dist/services/git/getStagedChanges.d.ts +0 -1
  120. package/dist/services/git/getStagedFiles.d.ts +0 -1
  121. package/dist/services/git/hasStagedChanges.d.ts +0 -1
  122. package/dist/services/git/index.d.ts +0 -13
  123. package/dist/services/git/isAvailable.d.ts +0 -1
  124. package/dist/services/git/isGitRepository.d.ts +0 -1
  125. package/dist/utils/commitlint.d.ts +0 -25
  126. package/dist/utils/formatBaseURL.d.ts +0 -1
  127. package/dist/utils/maskApiKey.d.ts +0 -1
@@ -1,77 +1,69 @@
1
- import { spawnSync } from "child_process";
2
- import { platform } from "os";
3
- import chalk from "chalk";
4
1
  import { saveConfig } from "../../../config.js";
5
2
  import { selectModel } from "../../setup/selectModel.js";
6
3
  import { Provider } from "../base.js";
7
4
  import { getAppleFoundationClient } from "./client.js";
8
5
  import { CANDIDATE_MODELS, probeModel } from "./models.js";
9
- const MIN_MACOS_MAJOR = 27;
10
- export class AppleProvider extends Provider {
11
- static id = "apple";
12
- static label = "Apple Foundation Models (macOS 27+)";
13
- static isAvailable() {
14
- if (platform() !== "darwin")
15
- return false;
16
- const result = spawnSync("sw_vers", ["-productVersion"], {
17
- encoding: "utf-8",
18
- });
19
- if (result.error || !result.stdout)
20
- return false;
21
- const major = parseInt(result.stdout.trim().split(".")[0], 10);
22
- return Number.isFinite(major) && major >= MIN_MACOS_MAJOR;
23
- }
24
- static async setup(existingConfig) {
25
- console.log(chalk.blue("Apple Foundation Models Setup"));
26
- const probes = CANDIDATE_MODELS.map((model) => ({
27
- model,
28
- ...probeModel(model.id),
29
- }));
30
- if (probes.every((p) => p.reason === "fm-missing")) {
31
- console.error(chalk.red("The Apple Foundation Models CLI ('fm') was not found. It ships with macOS 27 and later."));
32
- process.exit(1);
33
- }
34
- const availableModels = probes
35
- .filter((p) => p.available)
36
- .map((p) => p.model);
37
- if (availableModels.length === 0) {
38
- console.error(chalk.red("No Apple Foundation Models are available in this context. Make sure Apple Intelligence is enabled in System Settings."));
39
- process.exit(1);
40
- }
41
- const notes = probes
42
- .filter((p) => !p.available)
43
- .map((p) => `Note: Apple doesn't allow ${p.model.name} access from command-line tools.`);
44
- const selectedModel = await selectModel(availableModels, existingConfig.model, notes);
45
- const updatedConfig = {
46
- ...existingConfig,
47
- provider: "apple",
48
- model: selectedModel,
49
- };
50
- saveConfig(updatedConfig);
51
- console.log(chalk.green(`✓ Model set to: ${chalk.yellow(selectedModel)}`));
52
- return updatedConfig;
53
- }
54
- constructor(model) {
55
- super(model || "system");
56
- }
57
- async getContextWindow() {
58
- // The Apple Foundation Model CLI does not provide a way to get the context window size.
59
- // `fm` only enables `system` model for programmatic use, the context window is always 4096 tokens.
60
- return 4096;
61
- }
62
- countTokens(text) {
63
- const result = spawnSync("fm", ["token-count", "-q"], {
64
- input: text,
65
- encoding: "utf-8",
66
- });
67
- if (!result.error && result.stdout) {
68
- const tokens = parseInt(result.stdout.replace(/[^0-9]/g, ""), 10);
69
- if (Number.isFinite(tokens))
70
- return tokens;
71
- }
72
- return super.countTokens(text);
73
- }
74
- getClient() {
75
- return getAppleFoundationClient();
76
- }
77
- }
6
+ import chalk from "chalk";
7
+ import { spawnSync } from "child_process";
8
+ import { platform } from "os";
9
+ //#region src/llm/providers/apple/index.ts
10
+ var MIN_MACOS_MAJOR = 27;
11
+ var AppleProvider = class extends Provider {
12
+ static id = "apple";
13
+ static label = "Apple Foundation Models (macOS 27+)";
14
+ static isAvailable() {
15
+ if (platform() !== "darwin") return false;
16
+ const result = spawnSync("sw_vers", ["-productVersion"], { encoding: "utf-8" });
17
+ if (result.error || !result.stdout) return false;
18
+ const major = parseInt(result.stdout.trim().split(".")[0], 10);
19
+ return Number.isFinite(major) && major >= MIN_MACOS_MAJOR;
20
+ }
21
+ static async setup(existingConfig) {
22
+ console.log(chalk.blue("Apple Foundation Models Setup"));
23
+ const probes = CANDIDATE_MODELS.map((model) => ({
24
+ model,
25
+ ...probeModel(model.id)
26
+ }));
27
+ if (probes.every((p) => p.reason === "fm-missing")) {
28
+ console.error(chalk.red("The Apple Foundation Models CLI ('fm') was not found. It ships with macOS 27 and later."));
29
+ process.exit(1);
30
+ }
31
+ const availableModels = probes.filter((p) => p.available).map((p) => p.model);
32
+ if (availableModels.length === 0) {
33
+ console.error(chalk.red("No Apple Foundation Models are available in this context. Make sure Apple Intelligence is enabled in System Settings."));
34
+ process.exit(1);
35
+ }
36
+ const notes = probes.filter((p) => !p.available).map((p) => `Note: Apple doesn't allow ${p.model.name} access from command-line tools.`);
37
+ const selectedModel = await selectModel(availableModels, existingConfig.model, notes);
38
+ const updatedConfig = {
39
+ ...existingConfig,
40
+ provider: "apple",
41
+ model: selectedModel
42
+ };
43
+ saveConfig(updatedConfig);
44
+ console.log(chalk.green(`✓ Model set to: ${chalk.yellow(selectedModel)}`));
45
+ return updatedConfig;
46
+ }
47
+ constructor(model) {
48
+ super(model || "system");
49
+ }
50
+ async getContextWindow() {
51
+ return 4096;
52
+ }
53
+ countTokens(text) {
54
+ const result = spawnSync("fm", ["token-count", "-q"], {
55
+ input: text,
56
+ encoding: "utf-8"
57
+ });
58
+ if (!result.error && result.stdout) {
59
+ const tokens = parseInt(result.stdout.replace(/[^0-9]/g, ""), 10);
60
+ if (Number.isFinite(tokens)) return tokens;
61
+ }
62
+ return super.countTokens(text);
63
+ }
64
+ getClient() {
65
+ return getAppleFoundationClient();
66
+ }
67
+ };
68
+ //#endregion
69
+ export { AppleProvider };
@@ -1,21 +1,29 @@
1
1
  import { spawnSync } from "child_process";
2
- export const CANDIDATE_MODELS = [
3
- {
4
- id: "system",
5
- name: "Apple On-Device Foundation Model",
6
- context_length: 4096,
7
- },
8
- { id: "pcc", name: "Private Cloud Compute (PCC)" },
9
- ];
10
- export const probeModel = (modelId) => {
11
- const result = spawnSync("fm", ["available", "--model", modelId], {
12
- encoding: "utf-8",
13
- });
14
- if (result.error) {
15
- return { available: false, reason: "fm-missing" };
16
- }
17
- const output = `${result.stdout ?? ""}${result.stderr ?? ""}`;
18
- const available = /available/i.test(output) && !/not available|error/i.test(output);
19
- return { available, reason: output.trim() };
2
+ //#region src/llm/providers/apple/models.ts
3
+ var CANDIDATE_MODELS = [{
4
+ id: "system",
5
+ name: "Apple On-Device Foundation Model",
6
+ context_length: 4096
7
+ }, {
8
+ id: "pcc",
9
+ name: "Private Cloud Compute (PCC)"
10
+ }];
11
+ var probeModel = (modelId) => {
12
+ const result = spawnSync("fm", [
13
+ "available",
14
+ "--model",
15
+ modelId
16
+ ], { encoding: "utf-8" });
17
+ if (result.error) return {
18
+ available: false,
19
+ reason: "fm-missing"
20
+ };
21
+ const output = `${result.stdout ?? ""}${result.stderr ?? ""}`;
22
+ return {
23
+ available: /available/i.test(output) && !/not available|error/i.test(output),
24
+ reason: output.trim()
25
+ };
20
26
  };
21
- export const isAppleModelAvailable = (modelId) => probeModel(modelId).available;
27
+ var isAppleModelAvailable = (modelId) => probeModel(modelId).available;
28
+ //#endregion
29
+ export { CANDIDATE_MODELS, isAppleModelAvailable, probeModel };
@@ -1,36 +1,36 @@
1
- export class Provider {
2
- model;
3
- static requiresApiKey = false;
4
- static requiresEndpoint = false;
5
- static isAvailable() {
6
- return true;
7
- }
8
- maxOutputTokens = 1024;
9
- // Newer OpenAI models require `max_completion_tokens`; most others use `max_tokens`.
10
- usesCompletionTokensParam = false;
11
- constructor(model) {
12
- this.model = model;
13
- }
14
- async getContextWindow() {
15
- return Number.POSITIVE_INFINITY;
16
- }
17
- countTokens(text) {
18
- // Conservative estimate (code tokenizes higher than the usual ~4 chars/token),
19
- // so chunks stay under the real context window when no exact tokenizer exists.
20
- return Math.ceil(text.length / 3);
21
- }
22
- async complete(req) {
23
- const tokenLimit = this.usesCompletionTokensParam
24
- ? { max_completion_tokens: req.maxTokens }
25
- : { max_tokens: req.maxTokens };
26
- const response = await this.getClient().chat.completions.create({
27
- model: this.model,
28
- messages: [
29
- { role: "system", content: req.system },
30
- { role: "user", content: req.user },
31
- ],
32
- ...tokenLimit,
33
- });
34
- return response.choices[0].message.content ?? "";
35
- }
36
- }
1
+ //#region src/llm/providers/base.ts
2
+ var Provider = class {
3
+ model;
4
+ static requiresApiKey = false;
5
+ static requiresEndpoint = false;
6
+ static isAvailable() {
7
+ return true;
8
+ }
9
+ maxOutputTokens = 1024;
10
+ usesCompletionTokensParam = false;
11
+ constructor(model) {
12
+ this.model = model;
13
+ }
14
+ async getContextWindow() {
15
+ return Number.POSITIVE_INFINITY;
16
+ }
17
+ countTokens(text) {
18
+ return Math.ceil(text.length / 3);
19
+ }
20
+ async complete(req) {
21
+ const tokenLimit = this.usesCompletionTokensParam ? { max_completion_tokens: req.maxTokens } : { max_tokens: req.maxTokens };
22
+ return (await this.getClient().chat.completions.create({
23
+ model: this.model,
24
+ messages: [{
25
+ role: "system",
26
+ content: req.system
27
+ }, {
28
+ role: "user",
29
+ content: req.user
30
+ }],
31
+ ...tokenLimit
32
+ })).choices[0].message.content ?? "";
33
+ }
34
+ };
35
+ //#endregion
36
+ export { Provider };
@@ -1,96 +1,84 @@
1
- import chalk from "chalk";
2
- import inquirer from "inquirer";
3
1
  import { getConfig, saveConfig } from "../../../config.js";
4
2
  import { getAvailableModels } from "../../setup/getAvailableModels.js";
5
3
  import { selectModel } from "../../setup/selectModel.js";
6
4
  import { OpenAICompatibleProvider } from "../openaiCompatible.js";
7
- const DEFAULT_CONTEXT_WINDOW = 4096;
8
- const detectContextWindow = async (endpoint, modelId) => {
9
- try {
10
- const origin = new URL(endpoint).origin;
11
- const response = await fetch(`${origin}/api/v0/models`);
12
- if (!response.ok)
13
- return undefined;
14
- const models = (await response.json())?.data ?? [];
15
- const model = models.find((m) => m.id === modelId) ??
16
- models.find((m) => m.state === "loaded");
17
- const window = model?.loaded_context_length ?? model?.max_context_length;
18
- return typeof window === "number" && window > 0 ? window : undefined;
19
- }
20
- catch {
21
- return undefined;
22
- }
5
+ import chalk from "chalk";
6
+ import inquirer from "inquirer";
7
+ //#region src/llm/providers/local/index.ts
8
+ var DEFAULT_CONTEXT_WINDOW = 4096;
9
+ var detectContextWindow = async (endpoint, modelId) => {
10
+ try {
11
+ const origin = new URL(endpoint).origin;
12
+ const response = await fetch(`${origin}/api/v0/models`);
13
+ if (!response.ok) return void 0;
14
+ const models = (await response.json())?.data ?? [];
15
+ const model = models.find((m) => m.id === modelId) ?? models.find((m) => m.state === "loaded");
16
+ const window = model?.loaded_context_length ?? model?.max_context_length;
17
+ return typeof window === "number" && window > 0 ? window : void 0;
18
+ } catch {
19
+ return;
20
+ }
21
+ };
22
+ var LocalProvider = class extends OpenAICompatibleProvider {
23
+ static id = "local";
24
+ static label = "Local LLM";
25
+ static requiresApiKey = false;
26
+ static requiresEndpoint = true;
27
+ static async setup(existingConfig) {
28
+ console.log(chalk.blue("Local LLM Setup"));
29
+ const endpoint = (await inquirer.prompt([{
30
+ type: "input",
31
+ name: "localLLMEndpoint",
32
+ message: "Enter local LLM API endpoint (e.g., http://127.0.0.1:1234):",
33
+ default: existingConfig.customLLMEndpoint || "http://127.0.0.1:1234",
34
+ validate: (input) => {
35
+ if (!input) return "API endpoint is required";
36
+ if (!input.startsWith("http://") && !input.startsWith("https://")) return "Must be a valid URL starting with http:// or https://";
37
+ return true;
38
+ }
39
+ }])).localLLMEndpoint;
40
+ console.log(chalk.gray("Trying to fetch available models from local LLM server..."));
41
+ const models = await getAvailableModels({ baseURLOverride: endpoint });
42
+ let selectedModel;
43
+ if (models.length > 0) {
44
+ console.log(chalk.green(`✓ Found ${models.length} models available on your local LLM server`));
45
+ selectedModel = await selectModel(models, existingConfig.model);
46
+ } else {
47
+ console.log(chalk.yellow("Could not fetch models from local LLM server, please enter model name manually"));
48
+ selectedModel = (await inquirer.prompt([{
49
+ type: "input",
50
+ name: "model",
51
+ message: "Enter model name to use with local endpoint:",
52
+ default: existingConfig.model,
53
+ validate: (input) => input ? true : "Model name is required"
54
+ }])).model;
55
+ }
56
+ const contextWindow = await detectContextWindow(endpoint, selectedModel) ?? DEFAULT_CONTEXT_WINDOW;
57
+ console.log(chalk.gray(`Using a context window of ${contextWindow} tokens.`));
58
+ const updatedConfig = {
59
+ ...existingConfig,
60
+ provider: "local",
61
+ model: selectedModel,
62
+ customLLMEndpoint: endpoint,
63
+ contextWindow
64
+ };
65
+ saveConfig(updatedConfig);
66
+ console.log(chalk.green("✓ Local LLM configuration saved"));
67
+ return updatedConfig;
68
+ }
69
+ async getContextWindow() {
70
+ const { contextWindow, customLLMEndpoint, model } = getConfig();
71
+ if (contextWindow) return contextWindow;
72
+ const detected = await detectContextWindow(customLLMEndpoint ?? "", model ?? "");
73
+ if (detected) {
74
+ saveConfig({ contextWindow: detected });
75
+ return detected;
76
+ }
77
+ return DEFAULT_CONTEXT_WINDOW;
78
+ }
79
+ baseURL() {
80
+ return getConfig().customLLMEndpoint ?? "";
81
+ }
23
82
  };
24
- export class LocalProvider extends OpenAICompatibleProvider {
25
- static id = "local";
26
- static label = "Local LLM";
27
- static requiresApiKey = false;
28
- static requiresEndpoint = true;
29
- static async setup(existingConfig) {
30
- console.log(chalk.blue("Local LLM Setup"));
31
- const endpointAnswer = await inquirer.prompt([
32
- {
33
- type: "input",
34
- name: "localLLMEndpoint",
35
- message: "Enter local LLM API endpoint (e.g., http://127.0.0.1:1234):",
36
- default: existingConfig.customLLMEndpoint || "http://127.0.0.1:1234",
37
- validate: (input) => {
38
- if (!input)
39
- return "API endpoint is required";
40
- if (!input.startsWith("http://") && !input.startsWith("https://")) {
41
- return "Must be a valid URL starting with http:// or https://";
42
- }
43
- return true;
44
- },
45
- },
46
- ]);
47
- const endpoint = endpointAnswer.localLLMEndpoint;
48
- console.log(chalk.gray("Trying to fetch available models from local LLM server..."));
49
- const models = await getAvailableModels({ baseURLOverride: endpoint });
50
- let selectedModel;
51
- if (models.length > 0) {
52
- console.log(chalk.green(`✓ Found ${models.length} models available on your local LLM server`));
53
- selectedModel = await selectModel(models, existingConfig.model);
54
- }
55
- else {
56
- console.log(chalk.yellow("Could not fetch models from local LLM server, please enter model name manually"));
57
- const modelAnswer = await inquirer.prompt([
58
- {
59
- type: "input",
60
- name: "model",
61
- message: "Enter model name to use with local endpoint:",
62
- default: existingConfig.model,
63
- validate: (input) => input ? true : "Model name is required",
64
- },
65
- ]);
66
- selectedModel = modelAnswer.model;
67
- }
68
- const contextWindow = (await detectContextWindow(endpoint, selectedModel)) ??
69
- DEFAULT_CONTEXT_WINDOW;
70
- console.log(chalk.gray(`Using a context window of ${contextWindow} tokens.`));
71
- const updatedConfig = {
72
- ...existingConfig,
73
- provider: "local",
74
- model: selectedModel,
75
- customLLMEndpoint: endpoint,
76
- contextWindow,
77
- };
78
- saveConfig(updatedConfig);
79
- console.log(chalk.green("✓ Local LLM configuration saved"));
80
- return updatedConfig;
81
- }
82
- async getContextWindow() {
83
- const { contextWindow, customLLMEndpoint, model } = getConfig();
84
- if (contextWindow)
85
- return contextWindow;
86
- const detected = await detectContextWindow(customLLMEndpoint ?? "", model ?? "");
87
- if (detected) {
88
- saveConfig({ contextWindow: detected });
89
- return detected;
90
- }
91
- return DEFAULT_CONTEXT_WINDOW;
92
- }
93
- baseURL() {
94
- return getConfig().customLLMEndpoint ?? "";
95
- }
96
- }
83
+ //#endregion
84
+ export { LocalProvider };
@@ -1,16 +1,19 @@
1
- import { OpenAICompatibleProvider, setupApiKeyProvider, } from "../openaiCompatible.js";
2
- export class OpenAIProvider extends OpenAICompatibleProvider {
3
- static id = "openai";
4
- static label = "OpenAI";
5
- static baseURL = "https://api.openai.com/v1";
6
- usesCompletionTokensParam = true;
7
- static setup(existingConfig) {
8
- return setupApiKeyProvider(existingConfig, {
9
- baseURL: OpenAIProvider.baseURL,
10
- label: OpenAIProvider.label,
11
- });
12
- }
13
- baseURL() {
14
- return OpenAIProvider.baseURL;
15
- }
16
- }
1
+ import { OpenAICompatibleProvider, setupApiKeyProvider } from "../openaiCompatible.js";
2
+ //#region src/llm/providers/openai/index.ts
3
+ var OpenAIProvider = class OpenAIProvider extends OpenAICompatibleProvider {
4
+ static id = "openai";
5
+ static label = "OpenAI";
6
+ static baseURL = "https://api.openai.com/v1";
7
+ usesCompletionTokensParam = true;
8
+ static setup(existingConfig) {
9
+ return setupApiKeyProvider(existingConfig, {
10
+ baseURL: OpenAIProvider.baseURL,
11
+ label: OpenAIProvider.label
12
+ });
13
+ }
14
+ baseURL() {
15
+ return OpenAIProvider.baseURL;
16
+ }
17
+ };
18
+ //#endregion
19
+ export { OpenAIProvider };
@@ -1,69 +1,66 @@
1
- import chalk from "chalk";
2
- import inquirer from "inquirer";
3
1
  import { saveConfig } from "../../config.js";
4
2
  import { getLLMClient } from "../index.js";
5
3
  import { getAvailableModels } from "../setup/getAvailableModels.js";
6
4
  import { selectModel } from "../setup/selectModel.js";
7
5
  import { getApiKey, promptApiKey, saveApiKey } from "./apiKey.js";
8
6
  import { Provider } from "./base.js";
9
- export class OpenAICompatibleProvider extends Provider {
10
- static requiresApiKey = true;
11
- // Headroom for reasoning models, which spend output tokens "thinking"
12
- // before emitting the answer.
13
- maxOutputTokens = 2048;
14
- getClient() {
15
- return getLLMClient({
16
- baseURLOverride: this.baseURL(),
17
- apiKey: getApiKey(),
18
- });
19
- }
20
- }
21
- export const setupApiKeyProvider = async (existingConfig, opts) => {
22
- const { baseURL, label } = opts;
23
- const listModels = opts.listModels ??
24
- ((key) => getAvailableModels({ baseURLOverride: baseURL, apiKey: key }));
25
- const providerId = existingConfig.provider ?? "";
26
- const existingKey = existingConfig.apiKeys?.[providerId] ?? existingConfig.apiKey;
27
- const apiKey = await promptApiKey(existingKey, label);
28
- if (!apiKey) {
29
- console.error(chalk.red(`API key is required for ${label}.`));
30
- process.exit(1);
31
- }
32
- if (existingConfig.model) {
33
- console.log("Current model:", chalk.yellow(existingConfig.model));
34
- console.log("");
35
- }
36
- let selectedModel;
37
- try {
38
- console.log(chalk.gray(`Fetching available models from ${label}...`));
39
- const models = await listModels(apiKey);
40
- if (models.length > 0) {
41
- console.log(chalk.green(`✓ Found ${models.length} models available with your API key`));
42
- }
43
- else {
44
- console.log(chalk.yellow(`No models found from ${label}. Please specify a model manually.`));
45
- }
46
- selectedModel = await selectModel(models, existingConfig.model);
47
- }
48
- catch (error) {
49
- console.error(chalk.yellow(`Error fetching models: ${error}`));
50
- const modelAnswer = await inquirer.prompt([
51
- {
52
- type: "input",
53
- name: "model",
54
- message: "Enter model identifier:",
55
- validate: (input) => input ? true : "Model identifier is required",
56
- },
57
- ]);
58
- selectedModel = modelAnswer.model;
59
- }
60
- saveApiKey(providerId, apiKey);
61
- const finalConfig = {
62
- ...existingConfig,
63
- model: selectedModel,
64
- apiKeys: { ...existingConfig.apiKeys, [providerId]: apiKey },
65
- };
66
- saveConfig(finalConfig);
67
- console.log(chalk.green(`✓ Model set to: ${chalk.yellow(selectedModel)}`));
68
- return finalConfig;
7
+ import chalk from "chalk";
8
+ import inquirer from "inquirer";
9
+ //#region src/llm/providers/openaiCompatible.ts
10
+ var OpenAICompatibleProvider = class extends Provider {
11
+ static requiresApiKey = true;
12
+ maxOutputTokens = 2048;
13
+ getClient() {
14
+ return getLLMClient({
15
+ baseURLOverride: this.baseURL(),
16
+ apiKey: getApiKey()
17
+ });
18
+ }
19
+ };
20
+ var setupApiKeyProvider = async (existingConfig, opts) => {
21
+ const { baseURL, label } = opts;
22
+ const listModels = opts.listModels ?? ((key) => getAvailableModels({
23
+ baseURLOverride: baseURL,
24
+ apiKey: key
25
+ }));
26
+ const providerId = existingConfig.provider ?? "";
27
+ const apiKey = await promptApiKey(existingConfig.apiKeys?.[providerId] ?? existingConfig.apiKey, label);
28
+ if (!apiKey) {
29
+ console.error(chalk.red(`API key is required for ${label}.`));
30
+ process.exit(1);
31
+ }
32
+ if (existingConfig.model) {
33
+ console.log("Current model:", chalk.yellow(existingConfig.model));
34
+ console.log("");
35
+ }
36
+ let selectedModel;
37
+ try {
38
+ console.log(chalk.gray(`Fetching available models from ${label}...`));
39
+ const models = await listModels(apiKey);
40
+ if (models.length > 0) console.log(chalk.green(`✓ Found ${models.length} models available with your API key`));
41
+ else console.log(chalk.yellow(`No models found from ${label}. Please specify a model manually.`));
42
+ selectedModel = await selectModel(models, existingConfig.model);
43
+ } catch (error) {
44
+ console.error(chalk.yellow(`Error fetching models: ${error}`));
45
+ selectedModel = (await inquirer.prompt([{
46
+ type: "input",
47
+ name: "model",
48
+ message: "Enter model identifier:",
49
+ validate: (input) => input ? true : "Model identifier is required"
50
+ }])).model;
51
+ }
52
+ saveApiKey(providerId, apiKey);
53
+ const finalConfig = {
54
+ ...existingConfig,
55
+ model: selectedModel,
56
+ apiKeys: {
57
+ ...existingConfig.apiKeys,
58
+ [providerId]: apiKey
59
+ }
60
+ };
61
+ saveConfig(finalConfig);
62
+ console.log(chalk.green(`✓ Model set to: ${chalk.yellow(selectedModel)}`));
63
+ return finalConfig;
69
64
  };
65
+ //#endregion
66
+ export { OpenAICompatibleProvider, setupApiKeyProvider };
@@ -1,16 +1,19 @@
1
1
  import { OPENROUTER_API_URL } from "../../index.js";
2
- import { OpenAICompatibleProvider, setupApiKeyProvider, } from "../openaiCompatible.js";
3
- export class OpenRouterProvider extends OpenAICompatibleProvider {
4
- static id = "openrouter";
5
- static label = "OpenRouter (remote)";
6
- static baseURL = OPENROUTER_API_URL;
7
- static setup(existingConfig) {
8
- return setupApiKeyProvider(existingConfig, {
9
- baseURL: OpenRouterProvider.baseURL,
10
- label: OpenRouterProvider.label,
11
- });
12
- }
13
- baseURL() {
14
- return OpenRouterProvider.baseURL;
15
- }
16
- }
2
+ import { OpenAICompatibleProvider, setupApiKeyProvider } from "../openaiCompatible.js";
3
+ //#region src/llm/providers/openrouter/index.ts
4
+ var OpenRouterProvider = class OpenRouterProvider extends OpenAICompatibleProvider {
5
+ static id = "openrouter";
6
+ static label = "OpenRouter (remote)";
7
+ static baseURL = OPENROUTER_API_URL;
8
+ static setup(existingConfig) {
9
+ return setupApiKeyProvider(existingConfig, {
10
+ baseURL: OpenRouterProvider.baseURL,
11
+ label: OpenRouterProvider.label
12
+ });
13
+ }
14
+ baseURL() {
15
+ return OpenRouterProvider.baseURL;
16
+ }
17
+ };
18
+ //#endregion
19
+ export { OpenRouterProvider };