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.
- package/README.md +34 -167
- package/dist/commands/commit/commitFlags.js +7 -0
- package/dist/commands/commit/context/buildPrompt.js +13 -10
- package/dist/commands/commit/context/summaryPrompt.js +5 -2
- package/dist/commands/commit/context/systemPrompt.js +4 -1
- package/dist/commands/commit/context/userPrompt.js +4 -1
- package/dist/commands/commit/generateCommitMessage.js +14 -17
- package/dist/commands/commit/index.js +186 -179
- package/dist/commands/commit/summarizeDiff.js +183 -162
- package/dist/commands/config.js +24 -9
- package/dist/commands/hook/index.js +68 -0
- package/dist/commands/middleware/capabilitiesMiddleware/ghCapability.js +20 -20
- package/dist/commands/middleware/capabilitiesMiddleware/gitCapability.js +13 -10
- package/dist/commands/middleware/capabilitiesMiddleware/index.js +12 -11
- package/dist/commands/middleware/hasStagedChangesMiddleware.js +9 -6
- package/dist/commands/middleware/setupMiddleware/defaultModels.js +14 -10
- package/dist/commands/middleware/setupMiddleware/index.js +65 -71
- package/dist/commands/model.js +7 -4
- package/dist/commands/passthroughArgs.js +11 -0
- package/dist/commands/pr/context/systemPrompt.js +4 -1
- package/dist/commands/pr/context/userPrompt.js +4 -1
- package/dist/commands/pr/generatePRDetails.js +24 -23
- package/dist/commands/pr/getPRContext.js +37 -62
- package/dist/commands/pr/index.js +57 -62
- package/dist/commands/reset.js +23 -23
- package/dist/commands/review/index.js +31 -0
- package/dist/commands/setup.js +38 -13
- package/dist/config.js +63 -60
- package/dist/index.js +30 -67
- package/dist/llm/budget.js +10 -0
- package/dist/llm/index.js +12 -7
- package/dist/llm/providers/anthropic/index.js +30 -30
- package/dist/llm/providers/apiKey.js +36 -35
- package/dist/llm/providers/apple/client.js +73 -83
- package/dist/llm/providers/apple/index.js +64 -72
- package/dist/llm/providers/apple/models.js +27 -19
- package/dist/llm/providers/base.js +36 -36
- package/dist/llm/providers/local/index.js +79 -91
- package/dist/llm/providers/openai/index.js +19 -16
- package/dist/llm/providers/openaiCompatible.js +59 -62
- package/dist/llm/providers/openrouter/index.js +18 -15
- package/dist/llm/registry.js +30 -34
- package/dist/llm/setup/getAvailableModels.js +15 -9
- package/dist/llm/setup/selectModel.js +36 -44
- package/dist/llm/tokenCount.js +4 -3
- package/dist/package.js +67 -0
- package/dist/services/gh/createPullRequest.js +38 -58
- package/dist/services/gh/index.js +6 -3
- package/dist/services/gh/isAvailable.js +10 -8
- package/dist/services/git/executeGitAdd.js +11 -12
- package/dist/services/git/executeGitCommit.js +10 -11
- package/dist/services/git/getAmendChanges.js +23 -0
- package/dist/services/git/getChangedFiles.js +28 -61
- package/dist/services/git/getCommitsSinceBaseBranch.js +28 -56
- package/dist/services/git/getCurrentBranch.js +10 -8
- package/dist/services/git/getDefaultBranch.js +35 -60
- package/dist/services/git/getStagedChanges.js +10 -8
- package/dist/services/git/getStagedFiles.js +10 -9
- package/dist/services/git/hasStagedChanges.js +9 -8
- package/dist/services/git/index.js +17 -12
- package/dist/services/git/isAvailable.js +10 -8
- package/dist/services/git/isGitRepository.js +10 -8
- package/dist/utils/commitlint.js +97 -135
- package/dist/utils/formatBaseURL.js +7 -6
- package/dist/utils/maskApiKey.js +6 -7
- package/package.json +14 -4
- package/dist/commands/commit/context/buildPrompt.d.ts +0 -4
- package/dist/commands/commit/context/summaryPrompt.d.ts +0 -2
- package/dist/commands/commit/context/systemPrompt.d.ts +0 -1
- package/dist/commands/commit/context/userPrompt.d.ts +0 -1
- package/dist/commands/commit/generateCommitMessage.d.ts +0 -1
- package/dist/commands/commit/index.d.ts +0 -7
- package/dist/commands/commit/summarizeDiff.d.ts +0 -1
- package/dist/commands/config.d.ts +0 -1
- package/dist/commands/middleware/capabilitiesMiddleware/ghCapability.d.ts +0 -1
- package/dist/commands/middleware/capabilitiesMiddleware/gitCapability.d.ts +0 -1
- package/dist/commands/middleware/capabilitiesMiddleware/index.d.ts +0 -3
- package/dist/commands/middleware/hasStagedChangesMiddleware.d.ts +0 -1
- package/dist/commands/middleware/setupMiddleware/defaultModels.d.ts +0 -8
- package/dist/commands/middleware/setupMiddleware/index.d.ts +0 -4
- package/dist/commands/model.d.ts +0 -1
- package/dist/commands/pr/context/systemPrompt.d.ts +0 -1
- package/dist/commands/pr/context/userPrompt.d.ts +0 -1
- package/dist/commands/pr/generatePRDetails.d.ts +0 -4
- package/dist/commands/pr/getPRContext.d.ts +0 -1
- package/dist/commands/pr/index.d.ts +0 -10
- package/dist/commands/reset.d.ts +0 -3
- package/dist/commands/setup.d.ts +0 -3
- package/dist/config.d.ts +0 -14
- package/dist/index.d.ts +0 -2
- package/dist/llm/client.d.ts +0 -24
- package/dist/llm/client.js +0 -1
- package/dist/llm/index.d.ts +0 -6
- package/dist/llm/providers/anthropic/index.d.ts +0 -9
- package/dist/llm/providers/apiKey.d.ts +0 -3
- package/dist/llm/providers/apple/client.d.ts +0 -3
- package/dist/llm/providers/apple/index.d.ts +0 -13
- package/dist/llm/providers/apple/models.d.ts +0 -14
- package/dist/llm/providers/base.d.ts +0 -30
- package/dist/llm/providers/local/index.d.ts +0 -11
- package/dist/llm/providers/openai/index.d.ts +0 -10
- package/dist/llm/providers/openaiCompatible.d.ts +0 -15
- package/dist/llm/providers/openrouter/index.d.ts +0 -9
- package/dist/llm/registry.d.ts +0 -8
- package/dist/llm/setup/getAvailableModels.d.ts +0 -5
- package/dist/llm/setup/selectModel.d.ts +0 -5
- package/dist/llm/setup/types.d.ts +0 -13
- package/dist/llm/setup/types.js +0 -1
- package/dist/llm/tokenCount.d.ts +0 -3
- package/dist/services/gh/createPullRequest.d.ts +0 -1
- package/dist/services/gh/index.d.ts +0 -4
- package/dist/services/gh/isAvailable.d.ts +0 -1
- package/dist/services/git/executeGitAdd.d.ts +0 -1
- package/dist/services/git/executeGitCommit.d.ts +0 -1
- package/dist/services/git/getChangedFiles.d.ts +0 -1
- package/dist/services/git/getCommitsSinceBaseBranch.d.ts +0 -1
- package/dist/services/git/getCurrentBranch.d.ts +0 -1
- package/dist/services/git/getDefaultBranch.d.ts +0 -1
- package/dist/services/git/getStagedChanges.d.ts +0 -1
- package/dist/services/git/getStagedFiles.d.ts +0 -1
- package/dist/services/git/hasStagedChanges.d.ts +0 -1
- package/dist/services/git/index.d.ts +0 -13
- package/dist/services/git/isAvailable.d.ts +0 -1
- package/dist/services/git/isGitRepository.d.ts +0 -1
- package/dist/utils/commitlint.d.ts +0 -25
- package/dist/utils/formatBaseURL.d.ts +0 -1
- 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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
|
2
|
-
import
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
program
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
program
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
58
|
-
|
|
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
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
var saveApiKey = (providerId, key) => {
|
|
10
|
+
const { apiKeys } = getConfig();
|
|
11
|
+
saveConfig({ apiKeys: {
|
|
12
|
+
...apiKeys,
|
|
13
|
+
[providerId]: key
|
|
14
|
+
} });
|
|
11
15
|
};
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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 };
|