@ekzs/cli 0.2.0 → 0.3.3

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 (67) hide show
  1. package/README.md +49 -13
  2. package/dist/commands/agent.d.ts +0 -4
  3. package/dist/commands/agent.d.ts.map +1 -1
  4. package/dist/commands/agent.js +0 -6
  5. package/dist/commands/ask.d.ts +3 -5
  6. package/dist/commands/ask.d.ts.map +1 -1
  7. package/dist/commands/ask.js +50 -36
  8. package/dist/commands/local-agent.d.ts +0 -2
  9. package/dist/commands/local-agent.d.ts.map +1 -1
  10. package/dist/commands/local-agent.js +292 -131
  11. package/dist/commands/providers.d.ts +4 -0
  12. package/dist/commands/providers.d.ts.map +1 -0
  13. package/dist/commands/providers.js +6 -0
  14. package/dist/commands/setup.d.ts +5 -0
  15. package/dist/commands/setup.d.ts.map +1 -0
  16. package/dist/commands/setup.js +4 -0
  17. package/dist/index.js +41 -20
  18. package/dist/lib/commands-i18n.d.ts +12 -1
  19. package/dist/lib/commands-i18n.d.ts.map +1 -1
  20. package/dist/lib/commands-i18n.js +78 -14
  21. package/dist/lib/composer-model.d.ts +1 -1
  22. package/dist/lib/composer-model.d.ts.map +1 -1
  23. package/dist/lib/composer-model.js +2 -2
  24. package/dist/lib/global-config.d.ts +19 -0
  25. package/dist/lib/global-config.d.ts.map +1 -0
  26. package/dist/lib/global-config.js +52 -0
  27. package/dist/lib/help.d.ts.map +1 -1
  28. package/dist/lib/help.js +16 -12
  29. package/dist/lib/locale.d.ts.map +1 -1
  30. package/dist/lib/locale.js +2 -1
  31. package/dist/lib/onboarding.d.ts +20 -0
  32. package/dist/lib/onboarding.d.ts.map +1 -0
  33. package/dist/lib/onboarding.js +129 -0
  34. package/dist/lib/providers/agent-runner.d.ts +12 -0
  35. package/dist/lib/providers/agent-runner.d.ts.map +1 -0
  36. package/dist/lib/providers/agent-runner.js +167 -0
  37. package/dist/lib/providers/catalog.d.ts +15 -0
  38. package/dist/lib/providers/catalog.d.ts.map +1 -0
  39. package/dist/lib/providers/catalog.js +93 -0
  40. package/dist/lib/providers/chat.d.ts +10 -0
  41. package/dist/lib/providers/chat.d.ts.map +1 -0
  42. package/dist/lib/providers/chat.js +121 -0
  43. package/dist/lib/providers/credentials.d.ts +28 -0
  44. package/dist/lib/providers/credentials.d.ts.map +1 -0
  45. package/dist/lib/providers/credentials.js +70 -0
  46. package/dist/lib/providers/cursor-runner.d.ts +13 -0
  47. package/dist/lib/providers/cursor-runner.d.ts.map +1 -0
  48. package/dist/lib/providers/cursor-runner.js +89 -0
  49. package/dist/lib/providers/cursor-sdk.d.ts +8 -0
  50. package/dist/lib/providers/cursor-sdk.d.ts.map +1 -0
  51. package/dist/lib/providers/cursor-sdk.js +25 -0
  52. package/dist/lib/providers/store.d.ts +21 -0
  53. package/dist/lib/providers/store.d.ts.map +1 -0
  54. package/dist/lib/providers/store.js +84 -0
  55. package/dist/lib/providers/tools.d.ts +80 -0
  56. package/dist/lib/providers/tools.d.ts.map +1 -0
  57. package/dist/lib/providers/tools.js +145 -0
  58. package/dist/lib/providers/ui.d.ts +4 -0
  59. package/dist/lib/providers/ui.d.ts.map +1 -0
  60. package/dist/lib/providers/ui.js +188 -0
  61. package/dist/lib/setup-messages.d.ts +4 -0
  62. package/dist/lib/setup-messages.d.ts.map +1 -0
  63. package/dist/lib/setup-messages.js +13 -0
  64. package/dist/lib/ui/splash.d.ts.map +1 -1
  65. package/dist/lib/ui/splash.js +4 -0
  66. package/package.json +10 -2
  67. package/skills/ekz-sdk-cli/SKILL.md +6 -4
package/dist/index.js CHANGED
@@ -3,12 +3,15 @@ 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";
14
+ import { runSetupCommand } from "./commands/setup.js";
12
15
  import { runWebhookTest } from "./commands/webhook.js";
13
16
  const SUBCOMMANDS = new Set([
14
17
  "doctor",
@@ -18,6 +21,8 @@ const SUBCOMMANDS = new Set([
18
21
  "agent",
19
22
  "fix",
20
23
  "ask",
24
+ "providers",
25
+ "setup",
21
26
  ]);
22
27
  /** Bare `ekz` or `ekz "natural language task"` → agent. Resolves PT/zh CLI aliases. */
23
28
  function normalizeArgv(argv) {
@@ -35,7 +40,7 @@ const program = new Command();
35
40
  program
36
41
  .name("ekz")
37
42
  .description("EKZ CONNECT — e-Kwanza v2.4 coding agent by Alberto Moisés")
38
- .version("0.2.0");
43
+ .version("0.3.0");
39
44
  program
40
45
  .command("doctor")
41
46
  .description("Validate .env and run live credential checks (free)")
@@ -78,18 +83,16 @@ program
78
83
  });
79
84
  program
80
85
  .command("agent")
81
- .description("Interactive e-Kwanza agent (requires CURSOR_API_KEY for agent/plan modes)")
86
+ .description("Interactive e-Kwanza agent (BYOK configure keys with `ekz providers`)")
82
87
  .argument("[task]", "Optional first task — stays interactive after (omit for REPL only)")
83
88
  .option("-C, --cwd <path>", "Project directory", process.cwd())
84
- .option("--api-key <key>", "Cursor API key (or CURSOR_API_KEY env)")
89
+ .option("--api-key <key>", "One-off Cursor API key override (agent/plan)")
85
90
  .option("-i, --interactive", "Stay in REPL after the first task (default)", true)
86
91
  .option("--resume", "Resume last session in this repo")
87
92
  .option("--fresh", "Start a new agent session")
88
93
  .option("-m, --mode <mode>", "agent | plan | ask (default: agent)")
89
94
  .option("--plan", "Shorthand for --mode plan")
90
95
  .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
96
  .option("--offline", "Ask mode: offline answers only")
94
97
  .action(async (task, opts) => {
95
98
  try {
@@ -97,8 +100,6 @@ program
97
100
  cwd: opts.cwd,
98
101
  question: task,
99
102
  apiKey: opts.apiKey,
100
- askApiKey: opts.askApiKey,
101
- askApiUrl: opts.askApiUrl,
102
103
  askOffline: opts.offline,
103
104
  interactive: opts.interactive,
104
105
  resume: opts.resume,
@@ -118,15 +119,13 @@ program
118
119
  .description("Auto-audit and fix e-Kwanza integration in your repo")
119
120
  .argument("[hint]", "Optional extra context")
120
121
  .option("-C, --cwd <path>", "Project directory", process.cwd())
121
- .option("--api-key <key>", "Cursor API key (or CURSOR_API_KEY env)")
122
+ .option("--api-key <key>", "One-off Cursor API key override (agent/plan)")
122
123
  .option("-i, --interactive", "Stay in REPL after fix pass (default)", true)
123
124
  .option("--resume", "Resume last session")
124
125
  .option("--fresh", "Start a new agent session")
125
126
  .option("-m, --mode <mode>", "agent | plan | ask (default: agent)")
126
127
  .option("--plan", "Shorthand for --mode plan")
127
128
  .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
129
  .option("--offline", "Ask mode: offline answers only")
131
130
  .action(async (hint, opts) => {
132
131
  try {
@@ -137,14 +136,41 @@ program
137
136
  process.exitCode = 1;
138
137
  }
139
138
  });
139
+ program
140
+ .command("setup")
141
+ .alias("configurar")
142
+ .description("First-run setup — language, name, provider or offline")
143
+ .option("-l, --lang <code>", "Skip language pick: pt, en, or zh")
144
+ .action(async (opts) => {
145
+ try {
146
+ await runSetupCommand({ locale: opts.lang });
147
+ }
148
+ catch (err) {
149
+ console.error(err instanceof Error ? err.message : err);
150
+ process.exitCode = 1;
151
+ }
152
+ });
153
+ program
154
+ .command("providers")
155
+ .alias("provedores")
156
+ .alias("fornecedores")
157
+ .description("Configure LLM API keys (BYOK) — stored in ~/.ekz/providers.json")
158
+ .option("-l, --lang <code>", "Menu language: pt (default), en, or zh")
159
+ .action(async (opts) => {
160
+ try {
161
+ await runProvidersCommand({ locale: opts.lang });
162
+ }
163
+ catch (err) {
164
+ console.error(err instanceof Error ? err.message : err);
165
+ process.exitCode = 1;
166
+ }
167
+ });
140
168
  program
141
169
  .command("ask")
142
- .description("Remote Q&A via Ekz Connect API — no local file edits")
170
+ .description("BYOK Q&A — no local file edits (configure keys with `ekz providers`)")
143
171
  .argument("[question]", "Your question")
144
172
  .option("-C, --cwd <path>", "Project directory", process.cwd())
145
- .option("--api-key <key>", "EKZ_AGENT_API_KEY")
146
- .option("--api-url <url>", "Ekz Connect base URL")
147
- .option("--offline", "Deterministic answer without API")
173
+ .option("--offline", "Deterministic answer without LLM")
148
174
  .option("-i, --interactive", "Stay in ask REPL after the first question", false)
149
175
  .option("-l, --lang <code>", "Response language: pt (default), en, or zh")
150
176
  .action(async (question, opts) => {
@@ -152,8 +178,6 @@ program
152
178
  if (opts.interactive && !question?.trim()) {
153
179
  await runInteractiveAsk({
154
180
  cwd: opts.cwd,
155
- apiKey: opts.apiKey,
156
- apiUrl: opts.apiUrl,
157
181
  offline: opts.offline,
158
182
  locale: opts.lang,
159
183
  });
@@ -163,15 +187,12 @@ program
163
187
  await runAsk({
164
188
  cwd: opts.cwd,
165
189
  question: q,
166
- apiKey: opts.apiKey,
167
- apiUrl: opts.apiUrl,
168
190
  offline: opts.offline,
191
+ locale: parseLocale(opts.lang) ?? "pt",
169
192
  });
170
193
  if (opts.interactive) {
171
194
  await runInteractiveAsk({
172
195
  cwd: opts.cwd,
173
- apiKey: opts.apiKey,
174
- apiUrl: opts.apiUrl,
175
196
  offline: opts.offline,
176
197
  locale: opts.lang,
177
198
  });
@@ -1,5 +1,14 @@
1
1
  import type { EkzLocale } from "./locale.js";
2
- export type CliCommandId = "doctor" | "health" | "scan" | "webhook" | "agent" | "fix" | "ask";
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" | "setup";
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;AA0CV,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,CA6BxC,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,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,EAAE,CAkB9D;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,CAyBpD,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI5D"}
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;AAG7C,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,OAAO,CAAC,EAAE,SAAS,GAAG,MAAM,CAE9D;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,GACX,OAAO,CAAC;AA2DZ,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,CAmCxC,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,CAgB9D;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,34 @@
1
+ import { formatSetupRequiredMessage } from "./setup-messages.js";
2
+ export function providersCommandLabels(locale) {
3
+ if (locale === "pt") {
4
+ return {
5
+ cli: "ekz provedores",
6
+ repl: "/provedores",
7
+ cliAliases: ["fornecedores", "providers", "chaves"],
8
+ replAliases: ["/fornecedores", "/providers", "/chaves"],
9
+ };
10
+ }
11
+ if (locale === "zh") {
12
+ return {
13
+ cli: "ekz 供应商",
14
+ repl: "/供应商",
15
+ cliAliases: ["providers", "提供商", "模型"],
16
+ replAliases: ["/providers", "/提供商", "/模型"],
17
+ };
18
+ }
19
+ return {
20
+ cli: "ekz providers",
21
+ repl: "/providers",
22
+ cliAliases: ["provider"],
23
+ replAliases: ["/provider"],
24
+ };
25
+ }
26
+ export function providersSetupHint(_locale) {
27
+ return formatSetupRequiredMessage();
28
+ }
29
+ export function isProvidersMetaCommand(token) {
30
+ return resolveReplMetaCommand(token) === "providers";
31
+ }
1
32
  const EN_SUBCOMMANDS = new Set([
2
33
  "doctor",
3
34
  "health",
@@ -6,6 +37,8 @@ const EN_SUBCOMMANDS = new Set([
6
37
  "agent",
7
38
  "fix",
8
39
  "ask",
40
+ "providers",
41
+ "setup",
9
42
  ]);
10
43
  /** Map localized CLI tokens (and English) to canonical subcommand ids. */
11
44
  const CLI_ALIASES = {
@@ -29,6 +62,21 @@ const CLI_ALIASES = {
29
62
  ask: "ask",
30
63
  perguntar: "ask",
31
64
  pergunta: "ask",
65
+ providers: "providers",
66
+ provider: "providers",
67
+ fornecedores: "providers",
68
+ provedores: "providers",
69
+ chaves: "providers",
70
+ modelos: "providers",
71
+ 供应商: "providers",
72
+ 提供商: "providers",
73
+ 模型: "providers",
74
+ setup: "setup",
75
+ configurar: "setup",
76
+ configuracao: "setup",
77
+ "configuração": "setup",
78
+ 设置: "setup",
79
+ 配置: "setup",
32
80
  诊断: "doctor",
33
81
  凭证: "health",
34
82
  扫描: "scan",
@@ -56,6 +104,8 @@ export const SPLASH_TOOLS = {
56
104
  { label: "corrigir", hint: "fix" },
57
105
  { label: "agente", hint: "agent" },
58
106
  { label: "perguntar", hint: "ask" },
107
+ { label: "provedores", hint: "BYOK" },
108
+ { label: "setup", hint: "configurar" },
59
109
  ],
60
110
  en: [
61
111
  { label: "doctor" },
@@ -65,6 +115,8 @@ export const SPLASH_TOOLS = {
65
115
  { label: "fix" },
66
116
  { label: "agent" },
67
117
  { label: "ask" },
118
+ { label: "providers", hint: "BYOK" },
119
+ { label: "setup" },
68
120
  ],
69
121
  zh: [
70
122
  { label: "诊断", hint: "doctor" },
@@ -74,31 +126,34 @@ export const SPLASH_TOOLS = {
74
126
  { label: "修复", hint: "fix" },
75
127
  { label: "代理", hint: "agent" },
76
128
  { label: "问答", hint: "ask" },
129
+ { label: "供应商", hint: "BYOK" },
130
+ { label: "设置", hint: "setup" },
77
131
  ],
78
132
  };
79
133
  export function formatSplashTool(locale, tool) {
80
- if (!tool.hint || locale === "en")
134
+ if (!tool.hint)
81
135
  return tool.label;
82
136
  return `${tool.label} · ${tool.hint}`;
83
137
  }
138
+ /** One-line summary of all CLI tools for help text. */
139
+ export function formatCliToolsSummary(locale) {
140
+ return SPLASH_TOOLS[locale].map((t) => `ekz ${formatSplashTool(locale, t)}`).join(" · ");
141
+ }
84
142
  export function splashSessionLines(locale) {
143
+ const p = providersCommandLabels(locale);
144
+ const setupLine = locale === "pt"
145
+ ? "ekz setup · ekz configurar"
146
+ : locale === "zh"
147
+ ? "ekz setup · ekz 设置"
148
+ : "ekz setup";
149
+ const providersLine = `${p.repl} · ${p.cli}`;
85
150
  if (locale === "pt") {
86
- return [
87
- "/guardar <nome>",
88
- "/retomar · /retomar 2",
89
- "ekz --resume",
90
- "ekz --fresh",
91
- ];
151
+ return [setupLine, providersLine, "/guardar <nome>", "/retomar · /retomar 2", "ekz --resume", "ekz --fresh"];
92
152
  }
93
153
  if (locale === "zh") {
94
- return [
95
- "/保存 <名称>",
96
- "/恢复 · /恢复 2",
97
- "ekz --resume",
98
- "ekz --fresh",
99
- ];
154
+ return [setupLine, providersLine, "/保存 <名称>", "/恢复 · /恢复 2", "ekz --resume", "ekz --fresh"];
100
155
  }
101
- return ["/save <name>", "/resume · /resume 2", "ekz --resume", "ekz --fresh"];
156
+ return [setupLine, providersLine, "/save <name>", "/resume · /resume 2", "ekz --resume", "ekz --fresh"];
102
157
  }
103
158
  export function splashHelpHint(locale) {
104
159
  if (locale === "pt")
@@ -149,6 +204,15 @@ export const REPL_META_ALIASES = {
149
204
  save: "save",
150
205
  guardar: "save",
151
206
  保存: "save",
207
+ providers: "providers",
208
+ provider: "providers",
209
+ fornecedores: "providers",
210
+ provedores: "providers",
211
+ chaves: "providers",
212
+ modelos: "providers",
213
+ 供应商: "providers",
214
+ 提供商: "providers",
215
+ 模型: "providers",
152
216
  };
153
217
  export function resolveReplMetaCommand(token) {
154
218
  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,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,sBAAsB,CAkBjG"}
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");
@@ -0,0 +1,19 @@
1
+ import type { EkzLocale } from "./locale.js";
2
+ export type EkzGlobalConfig = {
3
+ locale?: EkzLocale;
4
+ userName?: string;
5
+ /** User chose offline mode (no LLM provider). */
6
+ offline?: boolean;
7
+ setupComplete?: boolean;
8
+ };
9
+ export declare function globalConfigPath(): string;
10
+ export declare function loadGlobalConfig(): EkzGlobalConfig;
11
+ export declare function saveGlobalConfig(patch: Partial<EkzGlobalConfig>): void;
12
+ export declare function getGlobalLocale(): EkzLocale | undefined;
13
+ export declare function getGlobalUserName(): string | undefined;
14
+ export declare function isGlobalOffline(): boolean;
15
+ export declare function setGlobalOffline(offline: boolean): void;
16
+ export declare function clearGlobalOffline(): void;
17
+ export declare function isSetupComplete(): boolean;
18
+ export declare function markSetupComplete(): void;
19
+ //# sourceMappingURL=global-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global-config.d.ts","sourceRoot":"","sources":["../../src/lib/global-config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAK7C,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAMF,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,gBAAgB,IAAI,eAAe,CAQlD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,eAAe,CAAC,QAI/D;AAED,wBAAgB,eAAe,IAAI,SAAS,GAAG,SAAS,CAGvD;AAED,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAEtD;AAED,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,QAEhD;AAED,wBAAgB,kBAAkB,SAGjC;AAED,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED,wBAAgB,iBAAiB,SAEhC"}
@@ -0,0 +1,52 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
2
+ import { homedir } from "os";
3
+ import { join } from "path";
4
+ const EKZ_HOME = join(homedir(), ".ekz");
5
+ const CONFIG_PATH = join(EKZ_HOME, "config.json");
6
+ function ensureEkzHome() {
7
+ if (!existsSync(EKZ_HOME))
8
+ mkdirSync(EKZ_HOME, { recursive: true, mode: 0o700 });
9
+ }
10
+ export function globalConfigPath() {
11
+ return CONFIG_PATH;
12
+ }
13
+ export function loadGlobalConfig() {
14
+ ensureEkzHome();
15
+ if (!existsSync(CONFIG_PATH))
16
+ return {};
17
+ try {
18
+ return JSON.parse(readFileSync(CONFIG_PATH, "utf8"));
19
+ }
20
+ catch {
21
+ return {};
22
+ }
23
+ }
24
+ export function saveGlobalConfig(patch) {
25
+ ensureEkzHome();
26
+ const next = { ...loadGlobalConfig(), ...patch };
27
+ writeFileSync(CONFIG_PATH, JSON.stringify(next, null, 2) + "\n", { mode: 0o600 });
28
+ }
29
+ export function getGlobalLocale() {
30
+ const l = loadGlobalConfig().locale;
31
+ return l === "pt" || l === "en" || l === "zh" ? l : undefined;
32
+ }
33
+ export function getGlobalUserName() {
34
+ return loadGlobalConfig().userName?.trim() || undefined;
35
+ }
36
+ export function isGlobalOffline() {
37
+ return loadGlobalConfig().offline === true;
38
+ }
39
+ export function setGlobalOffline(offline) {
40
+ saveGlobalConfig({ offline, setupComplete: true });
41
+ }
42
+ export function clearGlobalOffline() {
43
+ const cfg = loadGlobalConfig();
44
+ if (cfg.offline)
45
+ saveGlobalConfig({ offline: false });
46
+ }
47
+ export function isSetupComplete() {
48
+ return loadGlobalConfig().setupComplete === true;
49
+ }
50
+ export function markSetupComplete() {
51
+ saveGlobalConfig({ setupComplete: true });
52
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../src/lib/help.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EAAe,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAGtD,KAAK,WAAW,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAatD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE,CA4HzF;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,OAAO,QAezE"}
1
+ {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../src/lib/help.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EAAe,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAGtD,KAAK,WAAW,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAatD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE,CA+HzF;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,OAAO,QAezE"}
package/dist/lib/help.js CHANGED
@@ -1,4 +1,4 @@
1
- import { SPLASH_TOOLS } from "./commands-i18n.js";
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,12 @@ 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)`,
47
+ "ekz setup · ekz configurar",
45
48
  "/ajuda · /help",
46
49
  "/modo agente|plan|ask · /mode agent|plan|ask",
47
50
  "/idioma pt · /lang pt|en|zh",
@@ -52,6 +55,8 @@ export function buildHelpSections(locale, currentMode) {
52
55
  : locale === "zh"
53
56
  ? [
54
57
  "用自然语言提问或描述任务。",
58
+ `${p.repl} · ${p.cli} (BYOK)`,
59
+ "ekz setup · ekz 设置",
55
60
  "/帮助 · /help · /ajuda",
56
61
  "/模式 代理|plan|ask · /mode agent|plan|ask",
57
62
  "/语言 pt · /lang pt|en|zh",
@@ -61,6 +66,8 @@ export function buildHelpSections(locale, currentMode) {
61
66
  ]
62
67
  : [
63
68
  "Type questions or tasks in natural language.",
69
+ `${p.repl} · ${p.cli} (BYOK)`,
70
+ "ekz setup",
64
71
  "/help · /ajuda · /帮助",
65
72
  "/mode agent|plan|ask",
66
73
  "/lang pt · /lang en · /lang zh",
@@ -68,15 +75,11 @@ export function buildHelpSections(locale, currentMode) {
68
75
  "/doctor · /scan (quick diagnostics)",
69
76
  "exit · quit · sair",
70
77
  ];
71
- const cliTools = locale === "pt"
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";
78
+ const cliTools = formatCliToolsSummary(locale);
76
79
  const cli = locale === "pt"
77
80
  ? [
78
81
  "ekz · ekz agente [tarefa] · ekz corrigir [dica]",
79
- "ekz perguntar [pergunta] · ekz diagnóstico · ekz credenciais",
82
+ "ekz perguntar [pergunta] · ekz provedores · ekz diagnóstico",
80
83
  "ekz analisar · ekz webhook <url>",
81
84
  "ekz --modo agente|plan|ask (ou --mode)",
82
85
  cliTools,
@@ -84,33 +87,34 @@ export function buildHelpSections(locale, currentMode) {
84
87
  : locale === "zh"
85
88
  ? [
86
89
  "ekz · ekz 代理 [任务] · ekz 修复 [提示]",
87
- "ekz 问答 [问题] · ekz 诊断 · ekz 凭证",
90
+ "ekz 问答 [问题] · ekz 供应商 · ekz 诊断",
88
91
  "ekz 扫描 · ekz webhook <url>",
89
92
  "ekz --mode 代理|plan|ask (或 --plan)",
90
93
  cliTools,
91
94
  ]
92
95
  : [
93
96
  "ekz · ekz agent [task] · ekz fix [hint]",
94
- "ekz ask [question] · ekz doctor · ekz health",
97
+ "ekz ask [question] · ekz providers · ekz doctor",
95
98
  "ekz scan · ekz webhook <url>",
96
99
  "ekz --mode agent|plan|ask",
100
+ cliTools,
97
101
  ];
98
102
  const flags = locale === "pt"
99
103
  ? [
100
104
  "--mode agent|plan|ask · --plan (atalho para plan)",
101
105
  "--resume · --fresh · --lang pt|en|zh",
102
- "-C, --cwd <path> · --api-key <chave>",
106
+ "-C, --cwd <path> · --api-key <key> (Cursor one-off override)",
103
107
  ]
104
108
  : locale === "zh"
105
109
  ? [
106
110
  "--mode agent|plan|ask · --plan (plan 快捷方式)",
107
111
  "--resume · --fresh · --lang pt|en|zh",
108
- "-C, --cwd <path> · --api-key <key>",
112
+ "-C, --cwd <path> · --api-key <key> (Cursor one-off override)",
109
113
  ]
110
114
  : [
111
115
  "--mode agent|plan|ask · --plan (shorthand for plan)",
112
116
  "--resume · --fresh · --lang pt|en|zh",
113
- "-C, --cwd <path> · --api-key <key>",
117
+ "-C, --cwd <path> · --api-key <key> (Cursor one-off override)",
114
118
  ];
115
119
  const scope = locale === "pt"
116
120
  ? ["Só integração e-Kwanza v2.4. Outras áreas do repo são só leitura."]
@@ -1 +1 @@
1
- {"version":3,"file":"locale.d.ts","sourceRoot":"","sources":["../../src/lib/locale.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3C,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAInD,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAIlD,CAAC;AAEF,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAOnE;AAED,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,CAE3F;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAgB7D;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS;;;;;;;;;;;;;;;;;;;sBAqBnB,MAAM;;;;;;;;;;EA4H7B"}
1
+ {"version":3,"file":"locale.d.ts","sourceRoot":"","sources":["../../src/lib/locale.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3C,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAInD,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAIlD,CAAC;AAEF,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAOnE;AAED,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,CAE3F;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAgB7D;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS;;;;;;;;;;;;;;;;;;;sBAqBnB,MAAM;;;;;;;;;;EA4H7B"}
@@ -1,3 +1,4 @@
1
+ import { getGlobalLocale } from "./global-config.js";
1
2
  export const LOCALE_LABELS = {
2
3
  pt: "Português (Angola)",
3
4
  en: "English",
@@ -22,7 +23,7 @@ export function parseLocale(input) {
22
23
  }
23
24
  /** Default: Portuguese (Angola). Override with EKZ_LANG or --lang. */
24
25
  export function resolveLocale(explicit, saved) {
25
- return parseLocale(explicit) ?? parseLocale(process.env.EKZ_LANG) ?? saved ?? "pt";
26
+ return parseLocale(explicit) ?? parseLocale(process.env.EKZ_LANG) ?? saved ?? getGlobalLocale() ?? "pt";
26
27
  }
27
28
  export function languageInstruction(locale) {
28
29
  if (locale === "pt") {
@@ -0,0 +1,20 @@
1
+ import { type EkzLocale } from "./locale.js";
2
+ import { type ResolvedCredentials } from "./providers/credentials.js";
3
+ export type AgentReadyState = {
4
+ offline: boolean;
5
+ creds: ResolvedCredentials | null;
6
+ };
7
+ export declare function offlineModelLabel(locale: EkzLocale): string;
8
+ /** Full first-run wizard: language → name → provider/offline. */
9
+ export declare function runSetupWizard(opts?: {
10
+ locale?: string;
11
+ force?: boolean;
12
+ }): Promise<void>;
13
+ /** Ensures the agent can start — provider, offline, or throws setup hint. */
14
+ export declare function ensureAgentReady(options: {
15
+ locale: EkzLocale;
16
+ offlineFlag?: boolean;
17
+ apiKey?: string;
18
+ }): Promise<AgentReadyState>;
19
+ export declare function offlineAgentHint(locale: EkzLocale): string;
20
+ //# sourceMappingURL=onboarding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onboarding.d.ts","sourceRoot":"","sources":["../../src/lib/onboarding.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,SAAS,EAAe,MAAM,aAAa,CAAC;AAG1D,OAAO,EAIL,KAAK,mBAAmB,EACzB,MAAM,4BAA4B,CAAC;AAyBpC,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAAC;CACnC,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAI3D;AAoFD,iEAAiE;AACjE,wBAAsB,cAAc,CAAC,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,iBA6B/E;AAED,6EAA6E;AAC7E,wBAAsB,gBAAgB,CAAC,OAAO,EAAE;IAC9C,MAAM,EAAE,SAAS,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,eAAe,CAAC,CAgB3B;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAQ1D"}