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
package/dist/config.js CHANGED
@@ -1,63 +1,66 @@
1
1
  import chalk from "chalk";
2
2
  import Configstore from "configstore";
3
- const config = new Configstore("gitpt");
4
- export const getConfig = () => {
5
- try {
6
- const provider = config.get("provider");
7
- const customLLMEndpoint = config.get("customLLMEndpoint");
8
- const model = config.get("model");
9
- const apiKey = config.get("apiKey");
10
- const apiKeys = config.get("apiKeys");
11
- const contextWindow = config.get("contextWindow");
12
- return {
13
- provider,
14
- customLLMEndpoint,
15
- model,
16
- apiKey,
17
- apiKeys,
18
- contextWindow,
19
- };
20
- }
21
- catch (error) {
22
- console.error(chalk.red("Error reading configuration:"), error);
23
- return {};
24
- }
25
- };
26
- export const saveConfig = (newConfig) => {
27
- if (newConfig.provider !== undefined) {
28
- config.set("provider", newConfig.provider);
29
- }
30
- if (newConfig.customLLMEndpoint !== undefined) {
31
- config.set("customLLMEndpoint", newConfig.customLLMEndpoint);
32
- }
33
- if (newConfig.model !== undefined) {
34
- config.set("model", newConfig.model);
35
- }
36
- if (newConfig.apiKey !== undefined) {
37
- config.set("apiKey", newConfig.apiKey);
38
- }
39
- if (newConfig.apiKeys !== undefined) {
40
- config.set("apiKeys", newConfig.apiKeys);
41
- }
42
- if (newConfig.contextWindow !== undefined) {
43
- config.set("contextWindow", newConfig.contextWindow);
44
- }
45
- };
46
- export const clearConfig = () => {
47
- config.clear();
48
- };
49
- const ACCEPTED_DEFAULT_KEY = "acceptedDefault";
50
- export const getAcceptedDefault = () => {
51
- try {
52
- return config.get(ACCEPTED_DEFAULT_KEY);
53
- }
54
- catch {
55
- return undefined;
56
- }
57
- };
58
- export const setAcceptedDefault = (id) => {
59
- config.set(ACCEPTED_DEFAULT_KEY, id);
60
- };
61
- export const clearAcceptedDefault = () => {
62
- config.delete(ACCEPTED_DEFAULT_KEY);
3
+ //#region src/config.ts
4
+ var config = new Configstore("gitpt");
5
+ var getConfig = () => {
6
+ try {
7
+ return {
8
+ provider: config.get("provider"),
9
+ customLLMEndpoint: config.get("customLLMEndpoint"),
10
+ model: config.get("model"),
11
+ apiKey: config.get("apiKey"),
12
+ apiKeys: config.get("apiKeys"),
13
+ contextWindow: config.get("contextWindow"),
14
+ debug: config.get("debug")
15
+ };
16
+ } catch (error) {
17
+ console.error(chalk.red("Error reading configuration:"), error);
18
+ return {};
19
+ }
63
20
  };
21
+ var saveConfig = (newConfig) => {
22
+ if (newConfig.provider !== void 0) config.set("provider", newConfig.provider);
23
+ if (newConfig.customLLMEndpoint !== void 0) config.set("customLLMEndpoint", newConfig.customLLMEndpoint);
24
+ if (newConfig.model !== void 0) config.set("model", newConfig.model);
25
+ if (newConfig.apiKey !== void 0) config.set("apiKey", newConfig.apiKey);
26
+ if (newConfig.apiKeys !== void 0) config.set("apiKeys", newConfig.apiKeys);
27
+ if (newConfig.contextWindow !== void 0) config.set("contextWindow", newConfig.contextWindow);
28
+ if (newConfig.debug !== void 0) config.set("debug", newConfig.debug);
29
+ };
30
+ /** Env proměnná je "zapnuto" pro libovolnou non-empty hodnotu kromě
31
+ * explicitně vypínajících ("0", "false", "no", "off"). */
32
+ var isTruthyEnv = (value) => {
33
+ if (!value) return false;
34
+ const v = value.trim().toLowerCase();
35
+ return v !== "" && ![
36
+ "0",
37
+ "false",
38
+ "no",
39
+ "off"
40
+ ].includes(v);
41
+ };
42
+ /** Debug mode: extra diagnostics (tokens, latency). Off by default; on via
43
+ * the `debug` config flag, the GITPT_DEBUG env var, or `--debug`. */
44
+ var isDebug = () => getConfig().debug === true || isTruthyEnv({}.GITPT_DEBUG);
45
+ var unsetConfigKey = (key) => {
46
+ config.delete(key);
47
+ };
48
+ var clearConfig = () => {
49
+ config.clear();
50
+ };
51
+ var ACCEPTED_DEFAULT_KEY = "acceptedDefault";
52
+ var getAcceptedDefault = () => {
53
+ try {
54
+ return config.get(ACCEPTED_DEFAULT_KEY);
55
+ } catch {
56
+ return;
57
+ }
58
+ };
59
+ var setAcceptedDefault = (id) => {
60
+ config.set(ACCEPTED_DEFAULT_KEY, id);
61
+ };
62
+ var clearAcceptedDefault = () => {
63
+ config.delete(ACCEPTED_DEFAULT_KEY);
64
+ };
65
+ //#endregion
66
+ export { clearAcceptedDefault, clearConfig, getAcceptedDefault, getConfig, isDebug, saveConfig, setAcceptedDefault, unsetConfigKey };
package/dist/index.js CHANGED
@@ -1,78 +1,41 @@
1
- #!/usr/bin/env node --experimental-specifier-resolution=node
2
- import chalk from "chalk";
3
- import { execSync } from "child_process";
4
- import { Command } from "commander";
5
- import packageJSON from "../package.json" with { type: "json" };
1
+ #!/usr/bin/env node
2
+ import package_default from "./package.js";
6
3
  import { commitCommand } from "./commands/commit/index.js";
7
4
  import { configCommand } from "./commands/config.js";
5
+ import { reviewCommand } from "./commands/review/index.js";
6
+ import { hookInstallCommand, hookRunCommand, hookUninstallCommand } from "./commands/hook/index.js";
8
7
  import { modelCommand } from "./commands/model.js";
9
8
  import { prCreateCommand } from "./commands/pr/index.js";
10
9
  import { resetCommand } from "./commands/reset.js";
11
10
  import { setupCommand } from "./commands/setup.js";
12
- const program = new Command();
13
- program
14
- .name("gitpt")
15
- .description("Git Prompt Tool helps you write commit messages using AI")
16
- .version(packageJSON.version);
17
- // GitPT-specific commands
18
- program
19
- .command("setup")
20
- .description("Configure GitPT with your OpenRouter API key and model selection")
21
- .action(setupCommand);
22
- program
23
- .command("config")
24
- .description("Configure GitPT with your OpenRouter API key and model selection")
25
- .action(configCommand);
26
- program
27
- .command("model")
28
- .description("Change the AI model used for generating commit messages")
29
- .action(modelCommand);
30
- program
31
- .command("reset")
32
- .description("Reset GitPT configuration (clears provider, model, and API key)")
33
- .option("-y, --yes", "Skip the confirmation prompt")
34
- .action(resetCommand);
35
- // Enhanced git commands
36
- program
37
- .command("commit")
38
- .description("Generate AI-powered commit message based on staged changes")
39
- .option("-m, --message <message>", "use provided message instead of generating one")
40
- .option("-e, --edit", "edit the message after generation")
41
- .option("--no-edit", "do not edit the message after generation")
42
- .allowUnknownOption(true) // Pass through other git commit options
43
- .action(commitCommand);
44
- program
45
- .command("pr create")
46
- .description("Create a pull request with AI-generated title and description")
47
- .option("-t, --title <title>", "Custom pull request title")
48
- .option("-b, --body <body>", "Custom pull request description")
49
- .option("-d, --draft", "Create as draft pull request")
50
- .option("-B, --base <branch>", "Base branch to create PR against")
51
- .option("-e, --edit", "Edit PR details before submission", true)
52
- .option("--no-edit", "Skip editing PR details")
53
- .allowUnknownOption(true)
54
- .action(prCreateCommand);
55
- // Handle unknown commands by passing them to git
11
+ import chalk from "chalk";
12
+ import { spawnSync } from "child_process";
13
+ import { Command } from "commander";
14
+ //#region src/index.ts
15
+ var program = new Command();
16
+ program.name("gitpt").description("Git Prompt Tool helps you write commit messages using AI").version(package_default.version);
17
+ program.command("setup").description("Configure GitPT with your OpenRouter API key and model selection").option("--provider <id>", "Provider id (local, openrouter, openai, anthropic, apple)").option("--model <id>", "Model id").option("--endpoint <url>", "Custom LLM endpoint (for local)").option("--api-key <key>", "API key (for providers that need one)").action(setupCommand);
18
+ program.command("config").description("Configure GitPT with your OpenRouter API key and model selection").action(configCommand);
19
+ program.command("model").description("Change the AI model used for generating commit messages").action(modelCommand);
20
+ program.command("reset").description("Reset GitPT configuration (clears provider, model, and API key)").option("-y, --yes", "Skip the confirmation prompt").action(resetCommand);
21
+ program.command("commit").description("Generate AI-powered commit message based on staged changes").option("-m, --message <message>", "use provided message instead of generating one").option("-e, --edit", "edit the message after generation").option("--no-edit", "do not edit the message after generation").option("--dry-run", "generate and print the message but do not commit").option("--debug", "show diagnostics (tokens, latency) for this run").allowUnknownOption(true).allowExcessArguments(true).action(commitCommand);
22
+ program.command("pr create").description("Create a pull request with AI-generated title and description").option("-t, --title <title>", "Custom pull request title").option("-b, --body <body>", "Custom pull request description").option("-d, --draft", "Create as draft pull request").option("-B, --base <branch>", "Base branch to create PR against").option("-e, --edit", "Edit PR details before submission", true).option("--no-edit", "Skip editing PR details").allowUnknownOption(true).allowExcessArguments(true).action(prCreateCommand);
23
+ program.command("review").description("AI review of your staged changes (experimental)").action(reviewCommand);
24
+ var hook = program.command("hook").description("Manage the GitPT prepare-commit-msg git hook");
25
+ hook.command("install").description("Install the hook so `git commit` prefills an AI message").option("-f, --force", "Overwrite an existing prepare-commit-msg hook").action(hookInstallCommand);
26
+ hook.command("uninstall").description("Remove the GitPT prepare-commit-msg hook").action(hookUninstallCommand);
27
+ hook.command("run <msgFile> [source] [sha]").description("(internal) called by the installed hook").action(hookRunCommand);
56
28
  program.on("command:*", () => {
57
- try {
58
- // Get all arguments passed to the original command
59
- const args = process.argv.slice(2);
60
- // Execute git with all arguments
61
- execSync(`git ${args.join(" ")}`, { stdio: "inherit" });
62
- }
63
- catch (error) {
64
- // Git will handle its own error output through stdio: 'inherit'
65
- process.exit(1);
66
- }
29
+ const result = spawnSync("git", process.argv.slice(2), { stdio: "inherit" });
30
+ process.exit(result.status ?? 1);
67
31
  });
68
- // Main logic
69
32
  async function main() {
70
- try {
71
- await program.parseAsync();
72
- }
73
- catch (error) {
74
- console.error(chalk.red("Error:"), error instanceof Error ? error.message : String(error));
75
- process.exit(1);
76
- }
33
+ try {
34
+ await program.parseAsync();
35
+ } catch (error) {
36
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : String(error));
37
+ process.exit(1);
38
+ }
77
39
  }
78
40
  main();
41
+ //#endregion
@@ -0,0 +1,10 @@
1
+ //#region src/llm/budget.ts
2
+ /** Rezerva: necháme 10 % použitelného okna jako bezpečnostní polštář. */
3
+ var MARGIN = .9;
4
+ /**
5
+ * Maximální počet tokenů promptu, který se vejde do `window`,
6
+ * když si necháme `reserved` tokenů na odpověď modelu.
7
+ */
8
+ var fitBudget = (window, reserved) => Math.floor((window - reserved) * MARGIN);
9
+ //#endregion
10
+ export { fitBudget };
package/dist/llm/index.js CHANGED
@@ -1,9 +1,14 @@
1
- import openai from "openai";
2
1
  import { formatBaseURL } from "../utils/formatBaseURL.js";
3
- export const OPENROUTER_API_URL = "https://openrouter.ai/api/v1";
4
- export const getLLMClient = (options) => {
5
- const baseURL = formatBaseURL(options?.baseURLOverride ?? OPENROUTER_API_URL);
6
- // The OpenAI SDK requires a non-empty key even when the server ignores it.
7
- const apiKey = options?.apiKey || "not-needed";
8
- return new openai.OpenAI({ apiKey, baseURL });
2
+ import openai from "openai";
3
+ //#region src/llm/index.ts
4
+ var OPENROUTER_API_URL = "https://openrouter.ai/api/v1";
5
+ var getLLMClient = (options) => {
6
+ const baseURL = formatBaseURL(options?.baseURLOverride ?? "https://openrouter.ai/api/v1");
7
+ const apiKey = options?.apiKey || "not-needed";
8
+ return new openai.OpenAI({
9
+ apiKey,
10
+ baseURL
11
+ });
9
12
  };
13
+ //#endregion
14
+ export { OPENROUTER_API_URL, getLLMClient };
@@ -1,31 +1,31 @@
1
- import { OpenAICompatibleProvider, setupApiKeyProvider, } from "../openaiCompatible.js";
2
- const ANTHROPIC_VERSION = "2023-06-01";
3
- // Anthropic's /v1/models uses x-api-key auth (not the OpenAI SDK's bearer token).
4
- const listAnthropicModels = async (apiKey) => {
5
- const response = await fetch("https://api.anthropic.com/v1/models?limit=100", {
6
- headers: { "x-api-key": apiKey, "anthropic-version": ANTHROPIC_VERSION },
7
- });
8
- if (!response.ok) {
9
- throw new Error(`${response.status} ${await response.text()}`);
10
- }
11
- const data = (await response.json())?.data ?? [];
12
- return data.map((m) => ({
13
- id: m.id,
14
- name: m.display_name,
15
- }));
1
+ import { OpenAICompatibleProvider, setupApiKeyProvider } from "../openaiCompatible.js";
2
+ //#region src/llm/providers/anthropic/index.ts
3
+ var ANTHROPIC_VERSION = "2023-06-01";
4
+ var listAnthropicModels = async (apiKey) => {
5
+ const response = await fetch("https://api.anthropic.com/v1/models?limit=100", { headers: {
6
+ "x-api-key": apiKey,
7
+ "anthropic-version": ANTHROPIC_VERSION
8
+ } });
9
+ if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
10
+ return ((await response.json())?.data ?? []).map((m) => ({
11
+ id: m.id,
12
+ name: m.display_name
13
+ }));
16
14
  };
17
- export class AnthropicProvider extends OpenAICompatibleProvider {
18
- static id = "anthropic";
19
- static label = "Anthropic";
20
- static baseURL = "https://api.anthropic.com/v1";
21
- static setup(existingConfig) {
22
- return setupApiKeyProvider(existingConfig, {
23
- baseURL: AnthropicProvider.baseURL,
24
- label: AnthropicProvider.label,
25
- listModels: listAnthropicModels,
26
- });
27
- }
28
- baseURL() {
29
- return AnthropicProvider.baseURL;
30
- }
31
- }
15
+ var AnthropicProvider = class AnthropicProvider extends OpenAICompatibleProvider {
16
+ static id = "anthropic";
17
+ static label = "Anthropic";
18
+ static baseURL = "https://api.anthropic.com/v1";
19
+ static setup(existingConfig) {
20
+ return setupApiKeyProvider(existingConfig, {
21
+ baseURL: AnthropicProvider.baseURL,
22
+ label: AnthropicProvider.label,
23
+ listModels: listAnthropicModels
24
+ });
25
+ }
26
+ baseURL() {
27
+ return AnthropicProvider.baseURL;
28
+ }
29
+ };
30
+ //#endregion
31
+ export { AnthropicProvider };
@@ -1,40 +1,41 @@
1
- import inquirer from "inquirer";
2
1
  import { getConfig, saveConfig } from "../../config.js";
3
2
  import { maskApiKey } from "../../utils/maskApiKey.js";
4
- export const getApiKey = () => {
5
- const { provider, apiKeys, apiKey } = getConfig();
6
- return (provider && apiKeys?.[provider]) || apiKey;
3
+ import inquirer from "inquirer";
4
+ //#region src/llm/providers/apiKey.ts
5
+ var getApiKey = () => {
6
+ const { provider, apiKeys, apiKey } = getConfig();
7
+ return provider && apiKeys?.[provider] || apiKey;
7
8
  };
8
- export const saveApiKey = (providerId, key) => {
9
- const { apiKeys } = getConfig();
10
- saveConfig({ apiKeys: { ...apiKeys, [providerId]: key } });
9
+ var saveApiKey = (providerId, key) => {
10
+ const { apiKeys } = getConfig();
11
+ saveConfig({ apiKeys: {
12
+ ...apiKeys,
13
+ [providerId]: key
14
+ } });
11
15
  };
12
- export const promptApiKey = async (existingKey, label = "the provider") => {
13
- if (existingKey) {
14
- const { useExistingKey } = await inquirer.prompt([
15
- {
16
- type: "list",
17
- name: "useExistingKey",
18
- message: `${label} API key:`,
19
- choices: [
20
- {
21
- name: `Use existing key (${maskApiKey(existingKey)})`,
22
- value: true,
23
- },
24
- { name: "Enter a new API key", value: false },
25
- ],
26
- },
27
- ]);
28
- if (useExistingKey)
29
- return existingKey;
30
- }
31
- const { apiKey } = await inquirer.prompt([
32
- {
33
- type: "input",
34
- name: "apiKey",
35
- message: `Enter your ${label} API key:`,
36
- validate: (input) => (input ? true : "API key is required"),
37
- },
38
- ]);
39
- return apiKey;
16
+ var promptApiKey = async (existingKey, label = "the provider") => {
17
+ if (existingKey) {
18
+ const { useExistingKey } = await inquirer.prompt([{
19
+ type: "list",
20
+ name: "useExistingKey",
21
+ message: `${label} API key:`,
22
+ choices: [{
23
+ name: `Use existing key (${maskApiKey(existingKey)})`,
24
+ value: true
25
+ }, {
26
+ name: "Enter a new API key",
27
+ value: false
28
+ }]
29
+ }]);
30
+ if (useExistingKey) return existingKey;
31
+ }
32
+ const { apiKey } = await inquirer.prompt([{
33
+ type: "input",
34
+ name: "apiKey",
35
+ message: `Enter your ${label} API key:`,
36
+ validate: (input) => input ? true : "API key is required"
37
+ }]);
38
+ return apiKey;
40
39
  };
40
+ //#endregion
41
+ export { getApiKey, promptApiKey, saveApiKey };
@@ -1,87 +1,77 @@
1
1
  import { spawn } from "child_process";
2
- export const FM_BINARY = "fm";
3
- const clean = (text) => text
4
- .replace(/\x1b\[[0-9;]*m/g, "")
5
- .replace(/[⠀-⣿]/g, "")
6
- .trim();
7
- const messageText = (content) => {
8
- if (typeof content === "string")
9
- return content;
10
- if (Array.isArray(content)) {
11
- return content
12
- .map((part) => (part.type === "text" ? part.text : ""))
13
- .join("");
14
- }
15
- return "";
2
+ var clean = (text) => text.replace(/\x1b\[[0-9;]*m/g, "").replace(/[⠀-⣿]/g, "").trim();
3
+ var messageText = (content) => {
4
+ if (typeof content === "string") return content;
5
+ if (Array.isArray(content)) return content.map((part) => part.type === "text" ? part.text : "").join("");
6
+ return "";
16
7
  };
17
- const runFm = (args, stdin) => new Promise((resolve, reject) => {
18
- const child = spawn(FM_BINARY, args, {
19
- stdio: ["pipe", "pipe", "pipe"],
20
- });
21
- let stdout = "";
22
- let stderr = "";
23
- child.stdout.on("data", (chunk) => {
24
- stdout += chunk.toString();
25
- });
26
- child.stderr.on("data", (chunk) => {
27
- stderr += chunk.toString();
28
- });
29
- child.on("error", (error) => {
30
- if (error.code === "ENOENT") {
31
- reject(new Error("The Apple Foundation Models CLI ('fm') was not found. It ships with macOS 27 and later."));
32
- return;
33
- }
34
- reject(error);
35
- });
36
- child.on("close", (code) => {
37
- const out = stdout.trim();
38
- const err = clean(stderr);
39
- if (code !== 0 || !out) {
40
- reject(new Error(err || out || `'fm' exited with code ${code} and no output`));
41
- return;
42
- }
43
- resolve(out);
44
- });
45
- child.stdin.on("error", () => { });
46
- child.stdin.write(stdin);
47
- child.stdin.end();
8
+ var runFm = (args, stdin) => new Promise((resolve, reject) => {
9
+ const child = spawn("fm", args, { stdio: [
10
+ "pipe",
11
+ "pipe",
12
+ "pipe"
13
+ ] });
14
+ let stdout = "";
15
+ let stderr = "";
16
+ child.stdout.on("data", (chunk) => {
17
+ stdout += chunk.toString();
18
+ });
19
+ child.stderr.on("data", (chunk) => {
20
+ stderr += chunk.toString();
21
+ });
22
+ child.on("error", (error) => {
23
+ if (error.code === "ENOENT") {
24
+ reject(/* @__PURE__ */ new Error("The Apple Foundation Models CLI ('fm') was not found. It ships with macOS 27 and later."));
25
+ return;
26
+ }
27
+ reject(error);
28
+ });
29
+ child.on("close", (code) => {
30
+ const out = stdout.trim();
31
+ const err = clean(stderr);
32
+ if (code !== 0 || !out) {
33
+ reject(new Error(err || out || `'fm' exited with code ${code} and no output`));
34
+ return;
35
+ }
36
+ resolve(out);
37
+ });
38
+ child.stdin.on("error", () => {});
39
+ child.stdin.write(stdin);
40
+ child.stdin.end();
48
41
  });
49
- export const getAppleFoundationClient = () => {
50
- return {
51
- chat: {
52
- completions: {
53
- create: async (params) => {
54
- const model = params.model || "system";
55
- const instructions = params.messages
56
- .filter((m) => m.role === "system")
57
- .map((m) => messageText(m.content))
58
- .join("\n\n")
59
- .trim();
60
- const prompt = params.messages
61
- .filter((m) => m.role !== "system")
62
- .map((m) => messageText(m.content))
63
- .join("\n\n")
64
- .trim();
65
- const args = ["respond", "--no-stream", "--model", model];
66
- if (instructions) {
67
- args.push("--instructions", instructions);
68
- }
69
- const content = await runFm(args, prompt);
70
- return { choices: [{ message: { content } }] };
71
- },
72
- },
73
- },
74
- models: {
75
- list: async () => ({
76
- data: [
77
- { id: "system", created: 0, object: "model", owned_by: "apple" },
78
- { id: "pcc", created: 0, object: "model", owned_by: "apple" },
79
- ],
80
- hasNextPage: () => false,
81
- getNextPage: async () => {
82
- throw new Error("No more pages");
83
- },
84
- }),
85
- },
86
- };
42
+ var getAppleFoundationClient = () => {
43
+ return {
44
+ chat: { completions: { create: async (params) => {
45
+ const model = params.model || "system";
46
+ const instructions = params.messages.filter((m) => m.role === "system").map((m) => messageText(m.content)).join("\n\n").trim();
47
+ const prompt = params.messages.filter((m) => m.role !== "system").map((m) => messageText(m.content)).join("\n\n").trim();
48
+ const args = [
49
+ "respond",
50
+ "--no-stream",
51
+ "--model",
52
+ model
53
+ ];
54
+ if (instructions) args.push("--instructions", instructions);
55
+ return { choices: [{ message: { content: await runFm(args, prompt) } }] };
56
+ } } },
57
+ models: { list: async () => ({
58
+ data: [{
59
+ id: "system",
60
+ created: 0,
61
+ object: "model",
62
+ owned_by: "apple"
63
+ }, {
64
+ id: "pcc",
65
+ created: 0,
66
+ object: "model",
67
+ owned_by: "apple"
68
+ }],
69
+ hasNextPage: () => false,
70
+ getNextPage: async () => {
71
+ throw new Error("No more pages");
72
+ }
73
+ }) }
74
+ };
87
75
  };
76
+ //#endregion
77
+ export { getAppleFoundationClient };