@ekzs/cli 0.2.0 → 0.3.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/README.md +21 -11
- package/dist/commands/agent.d.ts +0 -4
- package/dist/commands/agent.d.ts.map +1 -1
- package/dist/commands/agent.js +0 -6
- package/dist/commands/ask.d.ts +3 -5
- package/dist/commands/ask.d.ts.map +1 -1
- package/dist/commands/ask.js +36 -35
- package/dist/commands/local-agent.d.ts +0 -2
- package/dist/commands/local-agent.d.ts.map +1 -1
- package/dist/commands/local-agent.js +200 -125
- package/dist/commands/providers.d.ts +4 -0
- package/dist/commands/providers.d.ts.map +1 -0
- package/dist/commands/providers.js +6 -0
- package/dist/index.js +25 -20
- package/dist/lib/commands-i18n.d.ts +12 -1
- package/dist/lib/commands-i18n.d.ts.map +1 -1
- package/dist/lib/commands-i18n.js +69 -14
- package/dist/lib/composer-model.d.ts +1 -1
- package/dist/lib/composer-model.d.ts.map +1 -1
- package/dist/lib/composer-model.js +2 -2
- package/dist/lib/help.js +13 -12
- package/dist/lib/providers/agent-runner.d.ts +12 -0
- package/dist/lib/providers/agent-runner.d.ts.map +1 -0
- package/dist/lib/providers/agent-runner.js +167 -0
- package/dist/lib/providers/catalog.d.ts +15 -0
- package/dist/lib/providers/catalog.d.ts.map +1 -0
- package/dist/lib/providers/catalog.js +93 -0
- package/dist/lib/providers/chat.d.ts +10 -0
- package/dist/lib/providers/chat.d.ts.map +1 -0
- package/dist/lib/providers/chat.js +121 -0
- package/dist/lib/providers/credentials.d.ts +26 -0
- package/dist/lib/providers/credentials.d.ts.map +1 -0
- package/dist/lib/providers/credentials.js +54 -0
- package/dist/lib/providers/cursor-runner.d.ts +13 -0
- package/dist/lib/providers/cursor-runner.d.ts.map +1 -0
- package/dist/lib/providers/cursor-runner.js +87 -0
- package/dist/lib/providers/store.d.ts +21 -0
- package/dist/lib/providers/store.d.ts.map +1 -0
- package/dist/lib/providers/store.js +81 -0
- package/dist/lib/providers/tools.d.ts +80 -0
- package/dist/lib/providers/tools.d.ts.map +1 -0
- package/dist/lib/providers/tools.js +145 -0
- package/dist/lib/providers/ui.d.ts +4 -0
- package/dist/lib/providers/ui.d.ts.map +1 -0
- package/dist/lib/providers/ui.js +188 -0
- package/package.json +1 -1
- package/skills/ekz-sdk-cli/SKILL.md +6 -4
package/dist/index.js
CHANGED
|
@@ -3,12 +3,14 @@ import { bootstrapShellEnvironment } from "./lib/shell.js";
|
|
|
3
3
|
import { Command } from "commander";
|
|
4
4
|
bootstrapShellEnvironment();
|
|
5
5
|
import { isKnownSubcommand, resolveCliSubcommand } from "./lib/commands-i18n.js";
|
|
6
|
+
import { parseLocale } from "./lib/locale.js";
|
|
6
7
|
import { runAgentCommand } from "./commands/agent.js";
|
|
7
8
|
import { runAsk, runInteractiveAsk, resolveQuestion } from "./commands/ask.js";
|
|
8
9
|
import { runDoctor } from "./commands/doctor.js";
|
|
9
10
|
import { runFixCommand } from "./commands/agent.js";
|
|
10
11
|
import { runHealth } from "./commands/health.js";
|
|
11
12
|
import { runScan } from "./commands/scan.js";
|
|
13
|
+
import { runProvidersCommand } from "./commands/providers.js";
|
|
12
14
|
import { runWebhookTest } from "./commands/webhook.js";
|
|
13
15
|
const SUBCOMMANDS = new Set([
|
|
14
16
|
"doctor",
|
|
@@ -18,6 +20,7 @@ const SUBCOMMANDS = new Set([
|
|
|
18
20
|
"agent",
|
|
19
21
|
"fix",
|
|
20
22
|
"ask",
|
|
23
|
+
"providers",
|
|
21
24
|
]);
|
|
22
25
|
/** Bare `ekz` or `ekz "natural language task"` → agent. Resolves PT/zh CLI aliases. */
|
|
23
26
|
function normalizeArgv(argv) {
|
|
@@ -35,7 +38,7 @@ const program = new Command();
|
|
|
35
38
|
program
|
|
36
39
|
.name("ekz")
|
|
37
40
|
.description("EKZ CONNECT — e-Kwanza v2.4 coding agent by Alberto Moisés")
|
|
38
|
-
.version("0.
|
|
41
|
+
.version("0.3.0");
|
|
39
42
|
program
|
|
40
43
|
.command("doctor")
|
|
41
44
|
.description("Validate .env and run live credential checks (free)")
|
|
@@ -78,18 +81,16 @@ program
|
|
|
78
81
|
});
|
|
79
82
|
program
|
|
80
83
|
.command("agent")
|
|
81
|
-
.description("Interactive e-Kwanza agent (
|
|
84
|
+
.description("Interactive e-Kwanza agent (BYOK — configure keys with `ekz providers`)")
|
|
82
85
|
.argument("[task]", "Optional first task — stays interactive after (omit for REPL only)")
|
|
83
86
|
.option("-C, --cwd <path>", "Project directory", process.cwd())
|
|
84
|
-
.option("--api-key <key>", "Cursor API key (
|
|
87
|
+
.option("--api-key <key>", "One-off Cursor API key override (agent/plan)")
|
|
85
88
|
.option("-i, --interactive", "Stay in REPL after the first task (default)", true)
|
|
86
89
|
.option("--resume", "Resume last session in this repo")
|
|
87
90
|
.option("--fresh", "Start a new agent session")
|
|
88
91
|
.option("-m, --mode <mode>", "agent | plan | ask (default: agent)")
|
|
89
92
|
.option("--plan", "Shorthand for --mode plan")
|
|
90
93
|
.option("-l, --lang <code>", "Response language: pt (default), en, or zh")
|
|
91
|
-
.option("--ask-api-key <key>", "EKZ_AGENT_API_KEY for ask mode")
|
|
92
|
-
.option("--ask-api-url <url>", "Ekz Connect base URL for ask mode")
|
|
93
94
|
.option("--offline", "Ask mode: offline answers only")
|
|
94
95
|
.action(async (task, opts) => {
|
|
95
96
|
try {
|
|
@@ -97,8 +98,6 @@ program
|
|
|
97
98
|
cwd: opts.cwd,
|
|
98
99
|
question: task,
|
|
99
100
|
apiKey: opts.apiKey,
|
|
100
|
-
askApiKey: opts.askApiKey,
|
|
101
|
-
askApiUrl: opts.askApiUrl,
|
|
102
101
|
askOffline: opts.offline,
|
|
103
102
|
interactive: opts.interactive,
|
|
104
103
|
resume: opts.resume,
|
|
@@ -118,15 +117,13 @@ program
|
|
|
118
117
|
.description("Auto-audit and fix e-Kwanza integration in your repo")
|
|
119
118
|
.argument("[hint]", "Optional extra context")
|
|
120
119
|
.option("-C, --cwd <path>", "Project directory", process.cwd())
|
|
121
|
-
.option("--api-key <key>", "Cursor API key (
|
|
120
|
+
.option("--api-key <key>", "One-off Cursor API key override (agent/plan)")
|
|
122
121
|
.option("-i, --interactive", "Stay in REPL after fix pass (default)", true)
|
|
123
122
|
.option("--resume", "Resume last session")
|
|
124
123
|
.option("--fresh", "Start a new agent session")
|
|
125
124
|
.option("-m, --mode <mode>", "agent | plan | ask (default: agent)")
|
|
126
125
|
.option("--plan", "Shorthand for --mode plan")
|
|
127
126
|
.option("-l, --lang <code>", "Response language: pt (default), en, or zh")
|
|
128
|
-
.option("--ask-api-key <key>", "EKZ_AGENT_API_KEY for ask mode")
|
|
129
|
-
.option("--ask-api-url <url>", "Ekz Connect base URL for ask mode")
|
|
130
127
|
.option("--offline", "Ask mode: offline answers only")
|
|
131
128
|
.action(async (hint, opts) => {
|
|
132
129
|
try {
|
|
@@ -137,14 +134,27 @@ program
|
|
|
137
134
|
process.exitCode = 1;
|
|
138
135
|
}
|
|
139
136
|
});
|
|
137
|
+
program
|
|
138
|
+
.command("providers")
|
|
139
|
+
.alias("provedores")
|
|
140
|
+
.alias("fornecedores")
|
|
141
|
+
.description("Configure LLM API keys (BYOK) — stored in ~/.ekz/providers.json")
|
|
142
|
+
.option("-l, --lang <code>", "Menu language: pt (default), en, or zh")
|
|
143
|
+
.action(async (opts) => {
|
|
144
|
+
try {
|
|
145
|
+
await runProvidersCommand({ locale: opts.lang });
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
console.error(err instanceof Error ? err.message : err);
|
|
149
|
+
process.exitCode = 1;
|
|
150
|
+
}
|
|
151
|
+
});
|
|
140
152
|
program
|
|
141
153
|
.command("ask")
|
|
142
|
-
.description("
|
|
154
|
+
.description("BYOK Q&A — no local file edits (configure keys with `ekz providers`)")
|
|
143
155
|
.argument("[question]", "Your question")
|
|
144
156
|
.option("-C, --cwd <path>", "Project directory", process.cwd())
|
|
145
|
-
.option("--
|
|
146
|
-
.option("--api-url <url>", "Ekz Connect base URL")
|
|
147
|
-
.option("--offline", "Deterministic answer without API")
|
|
157
|
+
.option("--offline", "Deterministic answer without LLM")
|
|
148
158
|
.option("-i, --interactive", "Stay in ask REPL after the first question", false)
|
|
149
159
|
.option("-l, --lang <code>", "Response language: pt (default), en, or zh")
|
|
150
160
|
.action(async (question, opts) => {
|
|
@@ -152,8 +162,6 @@ program
|
|
|
152
162
|
if (opts.interactive && !question?.trim()) {
|
|
153
163
|
await runInteractiveAsk({
|
|
154
164
|
cwd: opts.cwd,
|
|
155
|
-
apiKey: opts.apiKey,
|
|
156
|
-
apiUrl: opts.apiUrl,
|
|
157
165
|
offline: opts.offline,
|
|
158
166
|
locale: opts.lang,
|
|
159
167
|
});
|
|
@@ -163,15 +171,12 @@ program
|
|
|
163
171
|
await runAsk({
|
|
164
172
|
cwd: opts.cwd,
|
|
165
173
|
question: q,
|
|
166
|
-
apiKey: opts.apiKey,
|
|
167
|
-
apiUrl: opts.apiUrl,
|
|
168
174
|
offline: opts.offline,
|
|
175
|
+
locale: parseLocale(opts.lang) ?? "pt",
|
|
169
176
|
});
|
|
170
177
|
if (opts.interactive) {
|
|
171
178
|
await runInteractiveAsk({
|
|
172
179
|
cwd: opts.cwd,
|
|
173
|
-
apiKey: opts.apiKey,
|
|
174
|
-
apiUrl: opts.apiUrl,
|
|
175
180
|
offline: opts.offline,
|
|
176
181
|
locale: opts.lang,
|
|
177
182
|
});
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import type { EkzLocale } from "./locale.js";
|
|
2
|
-
export type
|
|
2
|
+
export type ProvidersCommandLabels = {
|
|
3
|
+
cli: string;
|
|
4
|
+
repl: string;
|
|
5
|
+
cliAliases: string[];
|
|
6
|
+
replAliases: string[];
|
|
7
|
+
};
|
|
8
|
+
export declare function providersCommandLabels(locale: EkzLocale): ProvidersCommandLabels;
|
|
9
|
+
export declare function providersSetupHint(locale: EkzLocale): string;
|
|
10
|
+
export declare function isProvidersMetaCommand(token: string): boolean;
|
|
11
|
+
export type CliCommandId = "doctor" | "health" | "scan" | "webhook" | "agent" | "fix" | "ask" | "providers";
|
|
3
12
|
export declare function resolveCliSubcommand(token: string): string;
|
|
4
13
|
export declare function isKnownSubcommand(token: string): boolean;
|
|
5
14
|
export declare const SPLASH_TOOLS: Record<EkzLocale, Array<{
|
|
@@ -10,6 +19,8 @@ export declare function formatSplashTool(locale: EkzLocale, tool: {
|
|
|
10
19
|
label: string;
|
|
11
20
|
hint?: string;
|
|
12
21
|
}): string;
|
|
22
|
+
/** One-line summary of all CLI tools for help text. */
|
|
23
|
+
export declare function formatCliToolsSummary(locale: EkzLocale): string;
|
|
13
24
|
export declare function splashSessionLines(locale: EkzLocale): string[];
|
|
14
25
|
export declare function splashHelpHint(locale: EkzLocale): string;
|
|
15
26
|
export declare function welcomeMessage(locale: EkzLocale, name: string, resumed: boolean): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands-i18n.d.ts","sourceRoot":"","sources":["../../src/lib/commands-i18n.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,YAAY,GACpB,QAAQ,GACR,QAAQ,GACR,MAAM,GACN,SAAS,GACT,OAAO,GACP,KAAK,GACL,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"commands-i18n.d.ts","sourceRoot":"","sources":["../../src/lib/commands-i18n.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,sBAAsB,GAAG;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,sBAAsB,CAuBhF;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAS5D;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,MAAM,MAAM,YAAY,GACpB,QAAQ,GACR,QAAQ,GACR,MAAM,GACN,SAAS,GACT,OAAO,GACP,KAAK,GACL,KAAK,GACL,WAAW,CAAC;AAoDhB,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAK1D;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAGxD;AAED,eAAO,MAAM,YAAY,EAAE,MAAM,CAC/B,SAAS,EACT,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAgCxC,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAGlG;AAED,uDAAuD;AACvD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAE/D;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,EAAE,CAU9D;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAIxD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAQxF;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,CAMvF;AAED,wDAAwD;AACxD,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAkCpD,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI5D"}
|
|
@@ -1,3 +1,40 @@
|
|
|
1
|
+
export function providersCommandLabels(locale) {
|
|
2
|
+
if (locale === "pt") {
|
|
3
|
+
return {
|
|
4
|
+
cli: "ekz provedores",
|
|
5
|
+
repl: "/provedores",
|
|
6
|
+
cliAliases: ["fornecedores", "providers", "chaves"],
|
|
7
|
+
replAliases: ["/fornecedores", "/providers", "/chaves"],
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
if (locale === "zh") {
|
|
11
|
+
return {
|
|
12
|
+
cli: "ekz 供应商",
|
|
13
|
+
repl: "/供应商",
|
|
14
|
+
cliAliases: ["providers", "提供商", "模型"],
|
|
15
|
+
replAliases: ["/providers", "/提供商", "/模型"],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
cli: "ekz providers",
|
|
20
|
+
repl: "/providers",
|
|
21
|
+
cliAliases: ["provider"],
|
|
22
|
+
replAliases: ["/provider"],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function providersSetupHint(locale) {
|
|
26
|
+
const labels = providersCommandLabels(locale);
|
|
27
|
+
if (locale === "pt") {
|
|
28
|
+
return `Nenhum provider activo. Corre \`${labels.cli}\` ou \`${labels.repl}\` e cola a tua API key.`;
|
|
29
|
+
}
|
|
30
|
+
if (locale === "zh") {
|
|
31
|
+
return `未配置 provider。运行 \`${labels.cli}\` 或 \`${labels.repl}\` 并粘贴 API key。`;
|
|
32
|
+
}
|
|
33
|
+
return `No active provider. Run \`${labels.cli}\` or \`${labels.repl}\` and paste your API key.`;
|
|
34
|
+
}
|
|
35
|
+
export function isProvidersMetaCommand(token) {
|
|
36
|
+
return resolveReplMetaCommand(token) === "providers";
|
|
37
|
+
}
|
|
1
38
|
const EN_SUBCOMMANDS = new Set([
|
|
2
39
|
"doctor",
|
|
3
40
|
"health",
|
|
@@ -6,6 +43,7 @@ const EN_SUBCOMMANDS = new Set([
|
|
|
6
43
|
"agent",
|
|
7
44
|
"fix",
|
|
8
45
|
"ask",
|
|
46
|
+
"providers",
|
|
9
47
|
]);
|
|
10
48
|
/** Map localized CLI tokens (and English) to canonical subcommand ids. */
|
|
11
49
|
const CLI_ALIASES = {
|
|
@@ -29,6 +67,15 @@ const CLI_ALIASES = {
|
|
|
29
67
|
ask: "ask",
|
|
30
68
|
perguntar: "ask",
|
|
31
69
|
pergunta: "ask",
|
|
70
|
+
providers: "providers",
|
|
71
|
+
provider: "providers",
|
|
72
|
+
fornecedores: "providers",
|
|
73
|
+
provedores: "providers",
|
|
74
|
+
chaves: "providers",
|
|
75
|
+
modelos: "providers",
|
|
76
|
+
供应商: "providers",
|
|
77
|
+
提供商: "providers",
|
|
78
|
+
模型: "providers",
|
|
32
79
|
诊断: "doctor",
|
|
33
80
|
凭证: "health",
|
|
34
81
|
扫描: "scan",
|
|
@@ -56,6 +103,7 @@ export const SPLASH_TOOLS = {
|
|
|
56
103
|
{ label: "corrigir", hint: "fix" },
|
|
57
104
|
{ label: "agente", hint: "agent" },
|
|
58
105
|
{ label: "perguntar", hint: "ask" },
|
|
106
|
+
{ label: "provedores", hint: "BYOK" },
|
|
59
107
|
],
|
|
60
108
|
en: [
|
|
61
109
|
{ label: "doctor" },
|
|
@@ -65,6 +113,7 @@ export const SPLASH_TOOLS = {
|
|
|
65
113
|
{ label: "fix" },
|
|
66
114
|
{ label: "agent" },
|
|
67
115
|
{ label: "ask" },
|
|
116
|
+
{ label: "providers", hint: "BYOK" },
|
|
68
117
|
],
|
|
69
118
|
zh: [
|
|
70
119
|
{ label: "诊断", hint: "doctor" },
|
|
@@ -74,31 +123,28 @@ export const SPLASH_TOOLS = {
|
|
|
74
123
|
{ label: "修复", hint: "fix" },
|
|
75
124
|
{ label: "代理", hint: "agent" },
|
|
76
125
|
{ label: "问答", hint: "ask" },
|
|
126
|
+
{ label: "供应商", hint: "BYOK" },
|
|
77
127
|
],
|
|
78
128
|
};
|
|
79
129
|
export function formatSplashTool(locale, tool) {
|
|
80
|
-
if (!tool.hint
|
|
130
|
+
if (!tool.hint)
|
|
81
131
|
return tool.label;
|
|
82
132
|
return `${tool.label} · ${tool.hint}`;
|
|
83
133
|
}
|
|
134
|
+
/** One-line summary of all CLI tools for help text. */
|
|
135
|
+
export function formatCliToolsSummary(locale) {
|
|
136
|
+
return SPLASH_TOOLS[locale].map((t) => `ekz ${formatSplashTool(locale, t)}`).join(" · ");
|
|
137
|
+
}
|
|
84
138
|
export function splashSessionLines(locale) {
|
|
139
|
+
const p = providersCommandLabels(locale);
|
|
140
|
+
const providersLine = `${p.repl} · ${p.cli}`;
|
|
85
141
|
if (locale === "pt") {
|
|
86
|
-
return [
|
|
87
|
-
"/guardar <nome>",
|
|
88
|
-
"/retomar · /retomar 2",
|
|
89
|
-
"ekz --resume",
|
|
90
|
-
"ekz --fresh",
|
|
91
|
-
];
|
|
142
|
+
return [providersLine, "/guardar <nome>", "/retomar · /retomar 2", "ekz --resume", "ekz --fresh"];
|
|
92
143
|
}
|
|
93
144
|
if (locale === "zh") {
|
|
94
|
-
return [
|
|
95
|
-
"/保存 <名称>",
|
|
96
|
-
"/恢复 · /恢复 2",
|
|
97
|
-
"ekz --resume",
|
|
98
|
-
"ekz --fresh",
|
|
99
|
-
];
|
|
145
|
+
return [providersLine, "/保存 <名称>", "/恢复 · /恢复 2", "ekz --resume", "ekz --fresh"];
|
|
100
146
|
}
|
|
101
|
-
return ["/save <name>", "/resume · /resume 2", "ekz --resume", "ekz --fresh"];
|
|
147
|
+
return [providersLine, "/save <name>", "/resume · /resume 2", "ekz --resume", "ekz --fresh"];
|
|
102
148
|
}
|
|
103
149
|
export function splashHelpHint(locale) {
|
|
104
150
|
if (locale === "pt")
|
|
@@ -149,6 +195,15 @@ export const REPL_META_ALIASES = {
|
|
|
149
195
|
save: "save",
|
|
150
196
|
guardar: "save",
|
|
151
197
|
保存: "save",
|
|
198
|
+
providers: "providers",
|
|
199
|
+
provider: "providers",
|
|
200
|
+
fornecedores: "providers",
|
|
201
|
+
provedores: "providers",
|
|
202
|
+
chaves: "providers",
|
|
203
|
+
modelos: "providers",
|
|
204
|
+
供应商: "providers",
|
|
205
|
+
提供商: "providers",
|
|
206
|
+
模型: "providers",
|
|
152
207
|
};
|
|
153
208
|
export function resolveReplMetaCommand(token) {
|
|
154
209
|
const raw = token.trim().toLowerCase().replace(/^\//, "");
|
|
@@ -6,5 +6,5 @@ export type ComposerModelSelection = {
|
|
|
6
6
|
}>;
|
|
7
7
|
label: string;
|
|
8
8
|
};
|
|
9
|
-
export declare function resolveComposerModel(env?: NodeJS.ProcessEnv): ComposerModelSelection;
|
|
9
|
+
export declare function resolveComposerModel(env?: NodeJS.ProcessEnv, modelOverride?: string): ComposerModelSelection;
|
|
10
10
|
//# sourceMappingURL=composer-model.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"composer-model.d.ts","sourceRoot":"","sources":["../../src/lib/composer-model.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sBAAsB,GAAG;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9C,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAgB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"composer-model.d.ts","sourceRoot":"","sources":["../../src/lib/composer-model.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sBAAsB,GAAG;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9C,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAgB,oBAAoB,CAClC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,aAAa,CAAC,EAAE,MAAM,GACrB,sBAAsB,CAkBxB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export function resolveComposerModel(env = process.env) {
|
|
2
|
-
const raw = env.EKZ_AGENT_MODEL?.trim() || "composer-2.5-fast";
|
|
1
|
+
export function resolveComposerModel(env = process.env, modelOverride) {
|
|
2
|
+
const raw = modelOverride?.trim() || env.EKZ_AGENT_MODEL?.trim() || "composer-2.5-fast";
|
|
3
3
|
const wantFast = raw.endsWith("-fast") ||
|
|
4
4
|
env.EKZ_AGENT_FAST === "true" ||
|
|
5
5
|
(env.EKZ_AGENT_FAST !== "false" && raw === "composer-2.5-fast");
|
package/dist/lib/help.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { formatCliToolsSummary, providersCommandLabels } from "./commands-i18n.js";
|
|
2
2
|
import { MODE_LABELS } from "./mode.js";
|
|
3
3
|
import { c, muted } from "./theme.js";
|
|
4
4
|
function sectionTitle(locale, key) {
|
|
@@ -39,9 +39,11 @@ export function buildHelpSections(locale, currentMode) {
|
|
|
39
39
|
modeLine("ask"),
|
|
40
40
|
currentMode ? `Current mode: ${currentMode}` : "",
|
|
41
41
|
].filter(Boolean);
|
|
42
|
+
const p = providersCommandLabels(locale);
|
|
42
43
|
const repl = locale === "pt"
|
|
43
44
|
? [
|
|
44
45
|
"Escreve perguntas ou tarefas em linguagem natural.",
|
|
46
|
+
`${p.repl} · ${p.cli} (BYOK)`,
|
|
45
47
|
"/ajuda · /help",
|
|
46
48
|
"/modo agente|plan|ask · /mode agent|plan|ask",
|
|
47
49
|
"/idioma pt · /lang pt|en|zh",
|
|
@@ -52,6 +54,7 @@ export function buildHelpSections(locale, currentMode) {
|
|
|
52
54
|
: locale === "zh"
|
|
53
55
|
? [
|
|
54
56
|
"用自然语言提问或描述任务。",
|
|
57
|
+
`${p.repl} · ${p.cli} (BYOK)`,
|
|
55
58
|
"/帮助 · /help · /ajuda",
|
|
56
59
|
"/模式 代理|plan|ask · /mode agent|plan|ask",
|
|
57
60
|
"/语言 pt · /lang pt|en|zh",
|
|
@@ -61,6 +64,7 @@ export function buildHelpSections(locale, currentMode) {
|
|
|
61
64
|
]
|
|
62
65
|
: [
|
|
63
66
|
"Type questions or tasks in natural language.",
|
|
67
|
+
`${p.repl} · ${p.cli} (BYOK)`,
|
|
64
68
|
"/help · /ajuda · /帮助",
|
|
65
69
|
"/mode agent|plan|ask",
|
|
66
70
|
"/lang pt · /lang en · /lang zh",
|
|
@@ -68,15 +72,11 @@ export function buildHelpSections(locale, currentMode) {
|
|
|
68
72
|
"/doctor · /scan (quick diagnostics)",
|
|
69
73
|
"exit · quit · sair",
|
|
70
74
|
];
|
|
71
|
-
const cliTools = locale
|
|
72
|
-
? SPLASH_TOOLS.pt.map((t) => `ekz ${t.label} (${t.hint ?? t.label})`).join(" · ")
|
|
73
|
-
: locale === "zh"
|
|
74
|
-
? SPLASH_TOOLS.zh.map((t) => `ekz ${t.label} (${t.hint ?? t.label})`).join(" · ")
|
|
75
|
-
: "ekz doctor · ekz health · ekz scan · ekz webhook · ekz fix · ekz agent · ekz ask";
|
|
75
|
+
const cliTools = formatCliToolsSummary(locale);
|
|
76
76
|
const cli = locale === "pt"
|
|
77
77
|
? [
|
|
78
78
|
"ekz · ekz agente [tarefa] · ekz corrigir [dica]",
|
|
79
|
-
"ekz perguntar [pergunta] · ekz
|
|
79
|
+
"ekz perguntar [pergunta] · ekz provedores · ekz diagnóstico",
|
|
80
80
|
"ekz analisar · ekz webhook <url>",
|
|
81
81
|
"ekz --modo agente|plan|ask (ou --mode)",
|
|
82
82
|
cliTools,
|
|
@@ -84,33 +84,34 @@ export function buildHelpSections(locale, currentMode) {
|
|
|
84
84
|
: locale === "zh"
|
|
85
85
|
? [
|
|
86
86
|
"ekz · ekz 代理 [任务] · ekz 修复 [提示]",
|
|
87
|
-
"ekz 问答 [问题] · ekz
|
|
87
|
+
"ekz 问答 [问题] · ekz 供应商 · ekz 诊断",
|
|
88
88
|
"ekz 扫描 · ekz webhook <url>",
|
|
89
89
|
"ekz --mode 代理|plan|ask (或 --plan)",
|
|
90
90
|
cliTools,
|
|
91
91
|
]
|
|
92
92
|
: [
|
|
93
93
|
"ekz · ekz agent [task] · ekz fix [hint]",
|
|
94
|
-
"ekz ask [question] · ekz
|
|
94
|
+
"ekz ask [question] · ekz providers · ekz doctor",
|
|
95
95
|
"ekz scan · ekz webhook <url>",
|
|
96
96
|
"ekz --mode agent|plan|ask",
|
|
97
|
+
cliTools,
|
|
97
98
|
];
|
|
98
99
|
const flags = locale === "pt"
|
|
99
100
|
? [
|
|
100
101
|
"--mode agent|plan|ask · --plan (atalho para plan)",
|
|
101
102
|
"--resume · --fresh · --lang pt|en|zh",
|
|
102
|
-
"-C, --cwd <path> · --api-key <
|
|
103
|
+
"-C, --cwd <path> · --api-key <key> (Cursor one-off override)",
|
|
103
104
|
]
|
|
104
105
|
: locale === "zh"
|
|
105
106
|
? [
|
|
106
107
|
"--mode agent|plan|ask · --plan (plan 快捷方式)",
|
|
107
108
|
"--resume · --fresh · --lang pt|en|zh",
|
|
108
|
-
"-C, --cwd <path> · --api-key <key>",
|
|
109
|
+
"-C, --cwd <path> · --api-key <key> (Cursor one-off override)",
|
|
109
110
|
]
|
|
110
111
|
: [
|
|
111
112
|
"--mode agent|plan|ask · --plan (shorthand for plan)",
|
|
112
113
|
"--resume · --fresh · --lang pt|en|zh",
|
|
113
|
-
"-C, --cwd <path> · --api-key <key>",
|
|
114
|
+
"-C, --cwd <path> · --api-key <key> (Cursor one-off override)",
|
|
114
115
|
];
|
|
115
116
|
const scope = locale === "pt"
|
|
116
117
|
? ["Só integração e-Kwanza v2.4. Outras áreas do repo são só leitura."]
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type EkzLocale } from "../locale.js";
|
|
2
|
+
import { type EkzMode } from "../mode.js";
|
|
3
|
+
import { type ResolvedCredentials } from "./credentials.js";
|
|
4
|
+
export declare function runByokAgentTurn(options: {
|
|
5
|
+
cwd: string;
|
|
6
|
+
task: string;
|
|
7
|
+
creds: ResolvedCredentials;
|
|
8
|
+
locale: EkzLocale;
|
|
9
|
+
mode: EkzMode;
|
|
10
|
+
}): Promise<boolean>;
|
|
11
|
+
export declare function usesCursorSdk(creds: ResolvedCredentials): boolean;
|
|
12
|
+
//# sourceMappingURL=agent-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-runner.d.ts","sourceRoot":"","sources":["../../../src/lib/providers/agent-runner.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAG1C,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AA+L5D,wBAAsB,gBAAgB,CAAC,OAAO,EAAE;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,mBAAmB,CAAC;IAC3B,MAAM,EAAE,SAAS,CAAC;IAClB,IAAI,EAAE,OAAO,CAAC;CACf,GAAG,OAAO,CAAC,OAAO,CAAC,CAgCnB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAEjE"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { resolve } from "path";
|
|
2
|
+
import { buildAgentPrompt, buildBootstrapContext } from "../context.js";
|
|
3
|
+
import { fail } from "../output.js";
|
|
4
|
+
import { toolDone, toolError, toolRunning } from "../theme.js";
|
|
5
|
+
import { AGENT_TOOL_DEFINITIONS, executeAgentTool } from "./tools.js";
|
|
6
|
+
const MAX_TOOL_ROUNDS = 24;
|
|
7
|
+
function planInstruction(mode) {
|
|
8
|
+
if (mode === "plan") {
|
|
9
|
+
return "You are in **plan mode**: output a clear numbered plan first. Only call write_file after the plan is clear.";
|
|
10
|
+
}
|
|
11
|
+
if (mode === "ask") {
|
|
12
|
+
return "You are in **ask mode**: answer only. Do not call write_file or run_command.";
|
|
13
|
+
}
|
|
14
|
+
return "You are in **agent mode**: use tools to inspect and fix the e-Kwanza integration.";
|
|
15
|
+
}
|
|
16
|
+
async function openAiAgentLoop(creds, cwd, messages, enableTools) {
|
|
17
|
+
const base = (creds.baseUrl ?? "https://api.openai.com/v1").replace(/\/$/, "");
|
|
18
|
+
const url = base.endsWith("/chat/completions") ? base : `${base}/chat/completions`;
|
|
19
|
+
for (let round = 0; round < MAX_TOOL_ROUNDS; round++) {
|
|
20
|
+
const headers = { "Content-Type": "application/json" };
|
|
21
|
+
if (creds.apiKey && creds.apiKey !== "ollama") {
|
|
22
|
+
headers.Authorization = `Bearer ${creds.apiKey}`;
|
|
23
|
+
}
|
|
24
|
+
const body = {
|
|
25
|
+
model: creds.model,
|
|
26
|
+
messages,
|
|
27
|
+
temperature: 0.2,
|
|
28
|
+
};
|
|
29
|
+
if (enableTools)
|
|
30
|
+
body.tools = AGENT_TOOL_DEFINITIONS;
|
|
31
|
+
const res = await fetch(url, { method: "POST", headers, body: JSON.stringify(body) });
|
|
32
|
+
const data = (await res.json().catch(() => ({})));
|
|
33
|
+
if (!res.ok)
|
|
34
|
+
throw new Error(data.error?.message ?? `Provider error (${res.status})`);
|
|
35
|
+
const message = data.choices?.[0]?.message;
|
|
36
|
+
if (!message)
|
|
37
|
+
throw new Error("Empty response from provider.");
|
|
38
|
+
const toolCalls = message.tool_calls ?? [];
|
|
39
|
+
if (!toolCalls.length) {
|
|
40
|
+
const text = message.content?.trim();
|
|
41
|
+
if (!text)
|
|
42
|
+
throw new Error("Empty response from provider.");
|
|
43
|
+
return text;
|
|
44
|
+
}
|
|
45
|
+
messages.push({
|
|
46
|
+
role: "assistant",
|
|
47
|
+
content: message.content ?? null,
|
|
48
|
+
tool_calls: toolCalls,
|
|
49
|
+
});
|
|
50
|
+
for (const call of toolCalls) {
|
|
51
|
+
process.stdout.write(toolRunning(call.function.name));
|
|
52
|
+
let args = {};
|
|
53
|
+
try {
|
|
54
|
+
args = JSON.parse(call.function.arguments || "{}");
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
args = {};
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
const result = await executeAgentTool(cwd, call.function.name, args);
|
|
61
|
+
process.stdout.write(toolDone(call.function.name));
|
|
62
|
+
messages.push({ role: "tool", tool_call_id: call.id, content: result });
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
process.stdout.write(toolError(call.function.name));
|
|
66
|
+
messages.push({
|
|
67
|
+
role: "tool",
|
|
68
|
+
tool_call_id: call.id,
|
|
69
|
+
content: err instanceof Error ? err.message : String(err),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
throw new Error("Tool loop exceeded maximum rounds.");
|
|
75
|
+
}
|
|
76
|
+
async function anthropicAgentLoop(creds, cwd, system, messages, enableTools) {
|
|
77
|
+
const tools = enableTools
|
|
78
|
+
? AGENT_TOOL_DEFINITIONS.map((t) => ({
|
|
79
|
+
name: t.function.name,
|
|
80
|
+
description: t.function.description,
|
|
81
|
+
input_schema: t.function.parameters,
|
|
82
|
+
}))
|
|
83
|
+
: undefined;
|
|
84
|
+
for (let round = 0; round < MAX_TOOL_ROUNDS; round++) {
|
|
85
|
+
const res = await fetch("https://api.anthropic.com/v1/messages", {
|
|
86
|
+
method: "POST",
|
|
87
|
+
headers: {
|
|
88
|
+
"Content-Type": "application/json",
|
|
89
|
+
"x-api-key": creds.apiKey,
|
|
90
|
+
"anthropic-version": "2023-06-01",
|
|
91
|
+
},
|
|
92
|
+
body: JSON.stringify({
|
|
93
|
+
model: creds.model,
|
|
94
|
+
max_tokens: 8192,
|
|
95
|
+
system,
|
|
96
|
+
messages,
|
|
97
|
+
...(tools ? { tools } : {}),
|
|
98
|
+
}),
|
|
99
|
+
});
|
|
100
|
+
const data = (await res.json().catch(() => ({})));
|
|
101
|
+
if (!res.ok)
|
|
102
|
+
throw new Error(data.error?.message ?? `Anthropic error (${res.status})`);
|
|
103
|
+
const blocks = data.content ?? [];
|
|
104
|
+
const textParts = blocks.filter((b) => b.type === "text").map((b) => b.text ?? "");
|
|
105
|
+
const toolUses = blocks.filter((b) => b.type === "tool_use");
|
|
106
|
+
messages.push({ role: "assistant", content: blocks });
|
|
107
|
+
if (!toolUses.length || data.stop_reason === "end_turn") {
|
|
108
|
+
const text = textParts.join("").trim();
|
|
109
|
+
if (!text && !toolUses.length)
|
|
110
|
+
throw new Error("Empty response from Anthropic.");
|
|
111
|
+
if (text)
|
|
112
|
+
return text;
|
|
113
|
+
}
|
|
114
|
+
if (!toolUses.length) {
|
|
115
|
+
return textParts.join("").trim() || "(done)";
|
|
116
|
+
}
|
|
117
|
+
const toolResults = [];
|
|
118
|
+
for (const tool of toolUses) {
|
|
119
|
+
const name = tool.name ?? "unknown";
|
|
120
|
+
process.stdout.write(toolRunning(name));
|
|
121
|
+
try {
|
|
122
|
+
const result = await executeAgentTool(cwd, name, tool.input ?? {});
|
|
123
|
+
process.stdout.write(toolDone(name));
|
|
124
|
+
toolResults.push({ type: "tool_result", tool_use_id: tool.id ?? name, content: result });
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
process.stdout.write(toolError(name));
|
|
128
|
+
toolResults.push({
|
|
129
|
+
type: "tool_result",
|
|
130
|
+
tool_use_id: tool.id ?? name,
|
|
131
|
+
content: err instanceof Error ? err.message : String(err),
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
messages.push({ role: "user", content: toolResults });
|
|
136
|
+
}
|
|
137
|
+
throw new Error("Tool loop exceeded maximum rounds.");
|
|
138
|
+
}
|
|
139
|
+
export async function runByokAgentTurn(options) {
|
|
140
|
+
const cwd = resolve(options.cwd);
|
|
141
|
+
const ctx = await buildBootstrapContext(cwd);
|
|
142
|
+
const prompt = buildAgentPrompt(options.task, ctx, options.locale);
|
|
143
|
+
const system = `${planInstruction(options.mode)}\n\n${prompt.split("## Task")[0] ?? prompt}`;
|
|
144
|
+
const userTask = `## Task\n${options.task}`;
|
|
145
|
+
const enableTools = options.mode !== "ask";
|
|
146
|
+
try {
|
|
147
|
+
if (options.creds.definition.kind === "anthropic") {
|
|
148
|
+
const text = await anthropicAgentLoop(options.creds, cwd, system, [{ role: "user", content: userTask }], enableTools);
|
|
149
|
+
console.log("\n" + text);
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
const messages = [
|
|
153
|
+
{ role: "system", content: system },
|
|
154
|
+
{ role: "user", content: userTask },
|
|
155
|
+
];
|
|
156
|
+
const text = await openAiAgentLoop(options.creds, cwd, messages, enableTools);
|
|
157
|
+
console.log("\n" + text);
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
fail(err instanceof Error ? err.message : String(err));
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
export function usesCursorSdk(creds) {
|
|
166
|
+
return creds.definition.kind === "cursor";
|
|
167
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type ProviderKind = "cursor" | "openai-compatible" | "anthropic";
|
|
2
|
+
export type ProviderId = "cursor" | "openai" | "anthropic" | "deepseek" | "kimi" | "groq" | "mistral" | "google" | "ollama";
|
|
3
|
+
export type ProviderDefinition = {
|
|
4
|
+
id: ProviderId;
|
|
5
|
+
name: string;
|
|
6
|
+
kind: ProviderKind;
|
|
7
|
+
description: string;
|
|
8
|
+
defaultModel: string;
|
|
9
|
+
defaultBaseUrl?: string;
|
|
10
|
+
keyHint: string;
|
|
11
|
+
docsUrl: string;
|
|
12
|
+
};
|
|
13
|
+
export declare const PROVIDER_CATALOG: ProviderDefinition[];
|
|
14
|
+
export declare function getProviderDefinition(id: string): ProviderDefinition | undefined;
|
|
15
|
+
//# sourceMappingURL=catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../../src/lib/providers/catalog.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,mBAAmB,GAAG,WAAW,CAAC;AAExE,MAAM,MAAM,UAAU,GAClB,QAAQ,GACR,QAAQ,GACR,WAAW,GACX,UAAU,GACV,MAAM,GACN,MAAM,GACN,SAAS,GACT,QAAQ,GACR,QAAQ,CAAC;AAEb,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,EAAE,UAAU,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,kBAAkB,EAyFhD,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAEhF"}
|