kairn-cli 1.9.1 → 1.10.0
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/dist/cli.js +193 -114
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ import chalk14 from "chalk";
|
|
|
4
4
|
|
|
5
5
|
// src/commands/init.ts
|
|
6
6
|
import { Command } from "commander";
|
|
7
|
-
import { password, select } from "@inquirer/prompts";
|
|
7
|
+
import { input, password, select } from "@inquirer/prompts";
|
|
8
8
|
import chalk3 from "chalk";
|
|
9
9
|
import Anthropic from "@anthropic-ai/sdk";
|
|
10
10
|
import OpenAI from "openai";
|
|
@@ -62,6 +62,114 @@ async function saveConfig(config) {
|
|
|
62
62
|
await fs.writeFile(CONFIG_PATH, JSON.stringify(config, null, 2), "utf-8");
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
// src/providers.ts
|
|
66
|
+
var PROVIDER_CONFIGS = {
|
|
67
|
+
anthropic: {
|
|
68
|
+
name: "Anthropic",
|
|
69
|
+
verifyModel: "claude-haiku-4-5-20251001",
|
|
70
|
+
cheapModel: "claude-haiku-4-5-20251001"
|
|
71
|
+
},
|
|
72
|
+
openai: {
|
|
73
|
+
name: "OpenAI",
|
|
74
|
+
verifyModel: "gpt-4.1-nano",
|
|
75
|
+
cheapModel: "gpt-4.1-nano"
|
|
76
|
+
},
|
|
77
|
+
google: {
|
|
78
|
+
name: "Google Gemini",
|
|
79
|
+
baseURL: "https://generativelanguage.googleapis.com/v1beta/openai/",
|
|
80
|
+
verifyModel: "gemini-2.5-flash",
|
|
81
|
+
cheapModel: "gemini-2.5-flash"
|
|
82
|
+
},
|
|
83
|
+
xai: {
|
|
84
|
+
name: "xAI (Grok)",
|
|
85
|
+
baseURL: "https://api.x.ai/v1",
|
|
86
|
+
verifyModel: "grok-4-1-fast-non-reasoning",
|
|
87
|
+
cheapModel: "grok-4-1-fast-non-reasoning"
|
|
88
|
+
},
|
|
89
|
+
deepseek: {
|
|
90
|
+
name: "DeepSeek",
|
|
91
|
+
baseURL: "https://api.deepseek.com",
|
|
92
|
+
verifyModel: "deepseek-chat",
|
|
93
|
+
cheapModel: "deepseek-chat"
|
|
94
|
+
},
|
|
95
|
+
mistral: {
|
|
96
|
+
name: "Mistral",
|
|
97
|
+
baseURL: "https://api.mistral.ai/v1",
|
|
98
|
+
verifyModel: "mistral-small-latest",
|
|
99
|
+
cheapModel: "mistral-small-latest"
|
|
100
|
+
},
|
|
101
|
+
groq: {
|
|
102
|
+
name: "Groq (open-source models)",
|
|
103
|
+
baseURL: "https://api.groq.com/openai/v1",
|
|
104
|
+
verifyModel: "meta-llama/llama-4-scout-17b-16e-instruct",
|
|
105
|
+
cheapModel: "meta-llama/llama-4-scout-17b-16e-instruct"
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
var PROVIDER_MODELS = {
|
|
109
|
+
anthropic: [
|
|
110
|
+
{ name: "Claude Sonnet 4.6 (recommended)", value: "claude-sonnet-4-6" },
|
|
111
|
+
{ name: "Claude Opus 4.6 (highest quality)", value: "claude-opus-4-6" },
|
|
112
|
+
{ name: "Claude Haiku 4.5 (fastest, cheapest)", value: "claude-haiku-4-5-20251001" }
|
|
113
|
+
],
|
|
114
|
+
openai: [
|
|
115
|
+
{ name: "GPT-4.1 (recommended \u2014 smartest non-reasoning)", value: "gpt-4.1" },
|
|
116
|
+
{ name: "GPT-4.1 mini (faster, cheaper)", value: "gpt-4.1-mini" },
|
|
117
|
+
{ name: "o4-mini (reasoning, cost-efficient)", value: "o4-mini" },
|
|
118
|
+
{ name: "GPT-5 mini (frontier)", value: "gpt-5-mini" }
|
|
119
|
+
],
|
|
120
|
+
google: [
|
|
121
|
+
{ name: "Gemini 2.5 Flash (recommended \u2014 best value)", value: "gemini-2.5-flash" },
|
|
122
|
+
{ name: "Gemini 3 Flash (newest frontier)", value: "gemini-3-flash" },
|
|
123
|
+
{ name: "Gemini 2.5 Pro (highest quality)", value: "gemini-2.5-pro" },
|
|
124
|
+
{ name: "Gemini 3.1 Pro Preview (most advanced)", value: "gemini-3.1-pro-preview" }
|
|
125
|
+
],
|
|
126
|
+
xai: [
|
|
127
|
+
{ name: "Grok 4.1 Fast (recommended \u2014 $0.20/M, very fast)", value: "grok-4-1-fast-non-reasoning" },
|
|
128
|
+
{ name: "Grok 4.20 (frontier quality, 2M context)", value: "grok-4.20-0309-non-reasoning" }
|
|
129
|
+
],
|
|
130
|
+
deepseek: [
|
|
131
|
+
{ name: "DeepSeek V3.2 Chat (recommended \u2014 cheapest good model)", value: "deepseek-chat" },
|
|
132
|
+
{ name: "DeepSeek V3.2 Reasoner (with chain-of-thought)", value: "deepseek-reasoner" }
|
|
133
|
+
],
|
|
134
|
+
mistral: [
|
|
135
|
+
{ name: "Mistral Large 3 (recommended \u2014 open-weight flagship)", value: "mistral-large-latest" },
|
|
136
|
+
{ name: "Codestral (code-optimized, 256K context)", value: "codestral-latest" },
|
|
137
|
+
{ name: "Mistral Small 4 (cheapest)", value: "mistral-small-latest" }
|
|
138
|
+
],
|
|
139
|
+
groq: [
|
|
140
|
+
{ name: "Llama 4 Maverick (recommended \u2014 free, fast)", value: "meta-llama/llama-4-maverick-17b-128e-instruct" },
|
|
141
|
+
{ name: "Llama 4 Scout (free, fast)", value: "meta-llama/llama-4-scout-17b-16e-instruct" },
|
|
142
|
+
{ name: "DeepSeek R1 70B (free reasoning)", value: "deepseek-r1-distill-llama-70b" },
|
|
143
|
+
{ name: "Qwen 3 32B (free, multilingual)", value: "qwen/qwen3-32b" }
|
|
144
|
+
]
|
|
145
|
+
};
|
|
146
|
+
var PROVIDER_CHOICES = [
|
|
147
|
+
{ name: "Anthropic (Claude) \u2014 recommended", value: "anthropic" },
|
|
148
|
+
{ name: "OpenAI (GPT)", value: "openai" },
|
|
149
|
+
{ name: "Google (Gemini)", value: "google" },
|
|
150
|
+
{ name: "xAI (Grok)", value: "xai" },
|
|
151
|
+
{ name: "DeepSeek \u2014 cheapest", value: "deepseek" },
|
|
152
|
+
{ name: "Mistral \u2014 open-weight", value: "mistral" },
|
|
153
|
+
{ name: "Groq \u2014 free tier, open-source models", value: "groq" },
|
|
154
|
+
{ name: "Other (OpenAI-compatible endpoint)", value: "other" }
|
|
155
|
+
];
|
|
156
|
+
function getProviderName(provider) {
|
|
157
|
+
if (provider === "other") return "Custom endpoint";
|
|
158
|
+
return PROVIDER_CONFIGS[provider].name;
|
|
159
|
+
}
|
|
160
|
+
function getBaseURL(provider, customBaseURL) {
|
|
161
|
+
if (provider === "other") return customBaseURL;
|
|
162
|
+
return PROVIDER_CONFIGS[provider]?.baseURL;
|
|
163
|
+
}
|
|
164
|
+
function getCheapModel(provider, fallbackModel) {
|
|
165
|
+
if (provider === "other") return fallbackModel;
|
|
166
|
+
return PROVIDER_CONFIGS[provider].cheapModel;
|
|
167
|
+
}
|
|
168
|
+
function getVerifyModel(provider, fallbackModel) {
|
|
169
|
+
if (provider === "other") return fallbackModel;
|
|
170
|
+
return PROVIDER_CONFIGS[provider].verifyModel;
|
|
171
|
+
}
|
|
172
|
+
|
|
65
173
|
// src/ui.ts
|
|
66
174
|
import chalk from "chalk";
|
|
67
175
|
var maroon = chalk.rgb(139, 0, 0);
|
|
@@ -234,62 +342,28 @@ async function installSeedTemplates() {
|
|
|
234
342
|
console.log(ui.success(`${installed} template${installed === 1 ? "" : "s"} installed`));
|
|
235
343
|
}
|
|
236
344
|
}
|
|
237
|
-
|
|
238
|
-
anthropic: {
|
|
239
|
-
name: "Anthropic",
|
|
240
|
-
models: [
|
|
241
|
-
{ name: "Claude Sonnet 4.6 (recommended \u2014 fast, smart)", value: "claude-sonnet-4-6" },
|
|
242
|
-
{ name: "Claude Opus 4.6 (highest quality)", value: "claude-opus-4-6" },
|
|
243
|
-
{ name: "Claude Haiku 4.5 (fastest, cheapest)", value: "claude-haiku-4-5-20251001" }
|
|
244
|
-
]
|
|
245
|
-
},
|
|
246
|
-
openai: {
|
|
247
|
-
name: "OpenAI",
|
|
248
|
-
models: [
|
|
249
|
-
{ name: "GPT-4o (recommended)", value: "gpt-4o" },
|
|
250
|
-
{ name: "GPT-4o mini (faster, cheaper)", value: "gpt-4o-mini" },
|
|
251
|
-
{ name: "o3 (reasoning)", value: "o3" }
|
|
252
|
-
]
|
|
253
|
-
},
|
|
254
|
-
google: {
|
|
255
|
-
name: "Google Gemini",
|
|
256
|
-
models: [
|
|
257
|
-
{ name: "Gemini 2.5 Flash (recommended)", value: "gemini-2.5-flash-preview-05-20" },
|
|
258
|
-
{ name: "Gemini 2.5 Pro (highest quality)", value: "gemini-2.5-pro-preview-05-06" }
|
|
259
|
-
]
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
async function verifyKey(provider, apiKey, model) {
|
|
345
|
+
async function verifyKey(provider, apiKey, baseURL, model) {
|
|
263
346
|
try {
|
|
264
347
|
if (provider === "anthropic") {
|
|
265
|
-
const
|
|
266
|
-
await
|
|
267
|
-
model: "claude-haiku-4-5-20251001",
|
|
268
|
-
max_tokens: 10,
|
|
269
|
-
messages: [{ role: "user", content: "ping" }]
|
|
270
|
-
});
|
|
271
|
-
return true;
|
|
272
|
-
} else if (provider === "openai") {
|
|
273
|
-
const client = new OpenAI({ apiKey });
|
|
274
|
-
await client.chat.completions.create({
|
|
275
|
-
model: "gpt-4o-mini",
|
|
276
|
-
max_tokens: 10,
|
|
277
|
-
messages: [{ role: "user", content: "ping" }]
|
|
278
|
-
});
|
|
279
|
-
return true;
|
|
280
|
-
} else if (provider === "google") {
|
|
281
|
-
const client = new OpenAI({
|
|
282
|
-
apiKey,
|
|
283
|
-
baseURL: "https://generativelanguage.googleapis.com/v1beta/openai/"
|
|
284
|
-
});
|
|
285
|
-
await client.chat.completions.create({
|
|
286
|
-
model: "gemini-2.5-flash-preview-05-20",
|
|
348
|
+
const client2 = new Anthropic({ apiKey });
|
|
349
|
+
await client2.messages.create({
|
|
350
|
+
model: getVerifyModel(provider, model || "claude-haiku-4-5-20251001"),
|
|
287
351
|
max_tokens: 10,
|
|
288
352
|
messages: [{ role: "user", content: "ping" }]
|
|
289
353
|
});
|
|
290
354
|
return true;
|
|
291
355
|
}
|
|
292
|
-
|
|
356
|
+
const verifyModel = provider === "other" ? model || "test" : getVerifyModel(provider, model || "");
|
|
357
|
+
const resolvedBaseURL = getBaseURL(provider, baseURL);
|
|
358
|
+
const clientOptions = { apiKey };
|
|
359
|
+
if (resolvedBaseURL) clientOptions.baseURL = resolvedBaseURL;
|
|
360
|
+
const client = new OpenAI(clientOptions);
|
|
361
|
+
await client.chat.completions.create({
|
|
362
|
+
model: verifyModel,
|
|
363
|
+
max_tokens: 10,
|
|
364
|
+
messages: [{ role: "user", content: "ping" }]
|
|
365
|
+
});
|
|
366
|
+
return true;
|
|
293
367
|
} catch {
|
|
294
368
|
return false;
|
|
295
369
|
}
|
|
@@ -311,42 +385,52 @@ var initCommand = new Command("init").description("Set up Kairn with your API ke
|
|
|
311
385
|
}
|
|
312
386
|
const provider = await select({
|
|
313
387
|
message: "LLM provider",
|
|
314
|
-
choices:
|
|
315
|
-
{ name: "Anthropic (Claude) \u2014 recommended", value: "anthropic" },
|
|
316
|
-
{ name: "OpenAI (GPT)", value: "openai" },
|
|
317
|
-
{ name: "Google (Gemini)", value: "google" }
|
|
318
|
-
]
|
|
319
|
-
});
|
|
320
|
-
const providerInfo = PROVIDER_MODELS[provider];
|
|
321
|
-
const model = await select({
|
|
322
|
-
message: "Compilation model",
|
|
323
|
-
choices: providerInfo.models
|
|
388
|
+
choices: PROVIDER_CHOICES
|
|
324
389
|
});
|
|
390
|
+
let model;
|
|
391
|
+
let baseURL;
|
|
392
|
+
let providerDisplayName;
|
|
393
|
+
if (provider === "other") {
|
|
394
|
+
providerDisplayName = "Custom endpoint";
|
|
395
|
+
baseURL = await input({ message: "Base URL" });
|
|
396
|
+
model = await input({ message: "Model name" });
|
|
397
|
+
} else {
|
|
398
|
+
providerDisplayName = getProviderName(provider);
|
|
399
|
+
model = await select({
|
|
400
|
+
message: "Compilation model",
|
|
401
|
+
choices: PROVIDER_MODELS[provider]
|
|
402
|
+
});
|
|
403
|
+
}
|
|
325
404
|
const apiKey = await password({
|
|
326
|
-
message: `${
|
|
405
|
+
message: `${providerDisplayName} API key${provider === "other" ? " (Enter to skip)" : ""}`,
|
|
327
406
|
mask: "*"
|
|
328
407
|
});
|
|
329
|
-
if (!apiKey) {
|
|
408
|
+
if (!apiKey && provider !== "other") {
|
|
330
409
|
console.log(ui.error("No API key provided. Aborting."));
|
|
331
410
|
process.exit(1);
|
|
332
411
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
412
|
+
if (apiKey) {
|
|
413
|
+
console.log(chalk3.dim("\n Verifying API key..."));
|
|
414
|
+
const valid = await verifyKey(provider, apiKey, baseURL, model);
|
|
415
|
+
if (!valid) {
|
|
416
|
+
console.log(ui.error("Invalid API key. Check your key and try again."));
|
|
417
|
+
process.exit(1);
|
|
418
|
+
}
|
|
419
|
+
console.log(ui.success("API key verified"));
|
|
420
|
+
} else {
|
|
421
|
+
console.log(ui.warn("No API key \u2014 skipping verification"));
|
|
338
422
|
}
|
|
339
|
-
console.log(ui.success("API key verified"));
|
|
340
423
|
const config = {
|
|
341
424
|
provider,
|
|
342
|
-
api_key: apiKey,
|
|
425
|
+
api_key: apiKey || "",
|
|
343
426
|
model,
|
|
427
|
+
...baseURL ? { base_url: baseURL } : {},
|
|
344
428
|
default_runtime: "claude-code",
|
|
345
429
|
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
346
430
|
};
|
|
347
431
|
await saveConfig(config);
|
|
348
432
|
console.log(ui.success(`Config saved to ${chalk3.dim(getConfigPath())}`));
|
|
349
|
-
console.log(ui.kv("Provider",
|
|
433
|
+
console.log(ui.kv("Provider", providerDisplayName));
|
|
350
434
|
console.log(ui.kv("Model", model));
|
|
351
435
|
await installSeedTemplates();
|
|
352
436
|
const hasClaude = detectClaudeCode();
|
|
@@ -364,7 +448,7 @@ var initCommand = new Command("init").description("Set up Kairn with your API ke
|
|
|
364
448
|
|
|
365
449
|
// src/commands/describe.ts
|
|
366
450
|
import { Command as Command2 } from "commander";
|
|
367
|
-
import { input, confirm, select as select2 } from "@inquirer/prompts";
|
|
451
|
+
import { input as input2, confirm, select as select2 } from "@inquirer/prompts";
|
|
368
452
|
import chalk5 from "chalk";
|
|
369
453
|
import ora from "ora";
|
|
370
454
|
|
|
@@ -845,10 +929,11 @@ function classifyError(err, provider) {
|
|
|
845
929
|
return `${provider} API error: ${msg}`;
|
|
846
930
|
}
|
|
847
931
|
async function callLLM(config, userMessage) {
|
|
932
|
+
const providerName = getProviderName(config.provider);
|
|
848
933
|
if (config.provider === "anthropic") {
|
|
849
|
-
const
|
|
934
|
+
const client2 = new Anthropic2({ apiKey: config.api_key });
|
|
850
935
|
try {
|
|
851
|
-
const response = await
|
|
936
|
+
const response = await client2.messages.create({
|
|
852
937
|
model: config.model,
|
|
853
938
|
max_tokens: 8192,
|
|
854
939
|
system: SYSTEM_PROMPT,
|
|
@@ -859,35 +944,31 @@ async function callLLM(config, userMessage) {
|
|
|
859
944
|
throw new Error("No text response from compiler LLM");
|
|
860
945
|
}
|
|
861
946
|
return textBlock.text;
|
|
862
|
-
} catch (err) {
|
|
863
|
-
throw new Error(classifyError(err, "Anthropic"));
|
|
864
|
-
}
|
|
865
|
-
} else if (config.provider === "openai" || config.provider === "google") {
|
|
866
|
-
const providerName = config.provider === "google" ? "Google" : "OpenAI";
|
|
867
|
-
const clientOptions = { apiKey: config.api_key };
|
|
868
|
-
if (config.provider === "google") {
|
|
869
|
-
clientOptions.baseURL = "https://generativelanguage.googleapis.com/v1beta/openai/";
|
|
870
|
-
}
|
|
871
|
-
const client = new OpenAI2(clientOptions);
|
|
872
|
-
try {
|
|
873
|
-
const response = await client.chat.completions.create({
|
|
874
|
-
model: config.model,
|
|
875
|
-
max_tokens: 8192,
|
|
876
|
-
messages: [
|
|
877
|
-
{ role: "system", content: SYSTEM_PROMPT },
|
|
878
|
-
{ role: "user", content: userMessage }
|
|
879
|
-
]
|
|
880
|
-
});
|
|
881
|
-
const text = response.choices[0]?.message?.content;
|
|
882
|
-
if (!text) {
|
|
883
|
-
throw new Error("No text response from compiler LLM");
|
|
884
|
-
}
|
|
885
|
-
return text;
|
|
886
947
|
} catch (err) {
|
|
887
948
|
throw new Error(classifyError(err, providerName));
|
|
888
949
|
}
|
|
889
950
|
}
|
|
890
|
-
|
|
951
|
+
const resolvedBaseURL = getBaseURL(config.provider, config.base_url);
|
|
952
|
+
const clientOptions = { apiKey: config.api_key };
|
|
953
|
+
if (resolvedBaseURL) clientOptions.baseURL = resolvedBaseURL;
|
|
954
|
+
const client = new OpenAI2(clientOptions);
|
|
955
|
+
try {
|
|
956
|
+
const response = await client.chat.completions.create({
|
|
957
|
+
model: config.model,
|
|
958
|
+
max_tokens: 8192,
|
|
959
|
+
messages: [
|
|
960
|
+
{ role: "system", content: SYSTEM_PROMPT },
|
|
961
|
+
{ role: "user", content: userMessage }
|
|
962
|
+
]
|
|
963
|
+
});
|
|
964
|
+
const text = response.choices[0]?.message?.content;
|
|
965
|
+
if (!text) {
|
|
966
|
+
throw new Error("No text response from compiler LLM");
|
|
967
|
+
}
|
|
968
|
+
return text;
|
|
969
|
+
} catch (err) {
|
|
970
|
+
throw new Error(classifyError(err, providerName));
|
|
971
|
+
}
|
|
891
972
|
}
|
|
892
973
|
function validateSpec(spec, onProgress) {
|
|
893
974
|
const warnings = [];
|
|
@@ -939,9 +1020,7 @@ async function generateClarifications(intent, onProgress) {
|
|
|
939
1020
|
}
|
|
940
1021
|
onProgress?.("Analyzing your request...");
|
|
941
1022
|
const clarificationConfig = { ...config };
|
|
942
|
-
|
|
943
|
-
clarificationConfig.model = "claude-haiku-4-5-20251001";
|
|
944
|
-
}
|
|
1023
|
+
clarificationConfig.model = getCheapModel(config.provider, config.model);
|
|
945
1024
|
const response = await callLLM(clarificationConfig, CLARIFICATION_PROMPT + "\n\nUser description: " + intent);
|
|
946
1025
|
try {
|
|
947
1026
|
let cleaned = response.trim();
|
|
@@ -1653,7 +1732,7 @@ var describeCommand = new Command2("describe").description("Describe your workfl
|
|
|
1653
1732
|
);
|
|
1654
1733
|
process.exit(1);
|
|
1655
1734
|
}
|
|
1656
|
-
const intentRaw = intentArg || await
|
|
1735
|
+
const intentRaw = intentArg || await input2({
|
|
1657
1736
|
message: "What do you want your agent to do?"
|
|
1658
1737
|
});
|
|
1659
1738
|
if (!intentRaw.trim()) {
|
|
@@ -1673,7 +1752,7 @@ var describeCommand = new Command2("describe").description("Describe your workfl
|
|
|
1673
1752
|
if (clarifications.length > 0) {
|
|
1674
1753
|
const answers = [];
|
|
1675
1754
|
for (const c of clarifications) {
|
|
1676
|
-
const answer = await
|
|
1755
|
+
const answer = await input2({
|
|
1677
1756
|
message: c.question,
|
|
1678
1757
|
default: c.suggestion
|
|
1679
1758
|
});
|
|
@@ -2425,7 +2504,7 @@ var optimizeCommand = new Command6("optimize").description("Scan an existing pro
|
|
|
2425
2504
|
console.log(ui.file(file));
|
|
2426
2505
|
}
|
|
2427
2506
|
if (hasEnvVars) {
|
|
2428
|
-
await collectAndWriteKeys(summary.envSetup, targetDir
|
|
2507
|
+
await collectAndWriteKeys(summary.envSetup, targetDir);
|
|
2429
2508
|
console.log("");
|
|
2430
2509
|
}
|
|
2431
2510
|
if (summary.pluginCommands.length > 0) {
|
|
@@ -2619,7 +2698,7 @@ var doctorCommand = new Command7("doctor").description(
|
|
|
2619
2698
|
// src/commands/registry.ts
|
|
2620
2699
|
import { Command as Command8 } from "commander";
|
|
2621
2700
|
import chalk11 from "chalk";
|
|
2622
|
-
import { input as
|
|
2701
|
+
import { input as input3, select as select3 } from "@inquirer/prompts";
|
|
2623
2702
|
var listCommand2 = new Command8("list").description("List tools in the registry").option("--category <cat>", "Filter by category").option("--user-only", "Show only user-defined tools").action(async (options) => {
|
|
2624
2703
|
printCompactBanner();
|
|
2625
2704
|
let all;
|
|
@@ -2679,7 +2758,7 @@ var listCommand2 = new Command8("list").description("List tools in the registry"
|
|
|
2679
2758
|
var addCommand = new Command8("add").description("Add a tool to the user registry").action(async () => {
|
|
2680
2759
|
let id;
|
|
2681
2760
|
try {
|
|
2682
|
-
id = await
|
|
2761
|
+
id = await input3({
|
|
2683
2762
|
message: "Tool ID (kebab-case)",
|
|
2684
2763
|
validate: (v) => {
|
|
2685
2764
|
if (!v) return "ID is required";
|
|
@@ -2687,8 +2766,8 @@ var addCommand = new Command8("add").description("Add a tool to the user registr
|
|
|
2687
2766
|
return true;
|
|
2688
2767
|
}
|
|
2689
2768
|
});
|
|
2690
|
-
const name = await
|
|
2691
|
-
const description = await
|
|
2769
|
+
const name = await input3({ message: "Display name" });
|
|
2770
|
+
const description = await input3({ message: "Description" });
|
|
2692
2771
|
const category = await select3({
|
|
2693
2772
|
message: "Category",
|
|
2694
2773
|
choices: [
|
|
@@ -2732,8 +2811,8 @@ var addCommand = new Command8("add").description("Add a tool to the user registr
|
|
|
2732
2811
|
if (auth === "api_key" || auth === "connection_string") {
|
|
2733
2812
|
let addMore = true;
|
|
2734
2813
|
while (addMore) {
|
|
2735
|
-
const varName = await
|
|
2736
|
-
const varDesc = await
|
|
2814
|
+
const varName = await input3({ message: "Env var name" });
|
|
2815
|
+
const varDesc = await input3({ message: "Env var description" });
|
|
2737
2816
|
env_vars.push({ name: varName, description: varDesc });
|
|
2738
2817
|
const another = await select3({
|
|
2739
2818
|
message: "Add another env var?",
|
|
@@ -2745,14 +2824,14 @@ var addCommand = new Command8("add").description("Add a tool to the user registr
|
|
|
2745
2824
|
addMore = another;
|
|
2746
2825
|
}
|
|
2747
2826
|
}
|
|
2748
|
-
const signup_url_raw = await
|
|
2827
|
+
const signup_url_raw = await input3({ message: "Signup URL (optional, press enter to skip)" });
|
|
2749
2828
|
const signup_url = signup_url_raw.trim() || void 0;
|
|
2750
|
-
const best_for_raw = await
|
|
2829
|
+
const best_for_raw = await input3({ message: "Best-for tags, comma-separated" });
|
|
2751
2830
|
const best_for = best_for_raw.split(",").map((s) => s.trim()).filter(Boolean);
|
|
2752
2831
|
const install = {};
|
|
2753
2832
|
if (type === "mcp_server") {
|
|
2754
|
-
const command = await
|
|
2755
|
-
const args_raw = await
|
|
2833
|
+
const command = await input3({ message: "MCP command" });
|
|
2834
|
+
const args_raw = await input3({ message: "MCP args, comma-separated (leave blank for none)" });
|
|
2756
2835
|
const args = args_raw.split(",").map((s) => s.trim()).filter(Boolean);
|
|
2757
2836
|
install.mcp_config = { command, args };
|
|
2758
2837
|
}
|