@ekzs/cli 0.3.0 → 0.3.4
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 +31 -5
- package/dist/commands/ask.d.ts.map +1 -1
- package/dist/commands/ask.js +16 -3
- package/dist/commands/local-agent.d.ts.map +1 -1
- package/dist/commands/local-agent.js +146 -60
- package/dist/commands/setup.d.ts +5 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +4 -0
- package/dist/index.js +18 -1
- package/dist/lib/commands-i18n.d.ts +2 -2
- package/dist/lib/commands-i18n.d.ts.map +1 -1
- package/dist/lib/commands-i18n.js +21 -12
- package/dist/lib/global-config.d.ts +19 -0
- package/dist/lib/global-config.d.ts.map +1 -0
- package/dist/lib/global-config.js +52 -0
- package/dist/lib/help.d.ts.map +1 -1
- package/dist/lib/help.js +3 -0
- package/dist/lib/locale.d.ts.map +1 -1
- package/dist/lib/locale.js +2 -1
- package/dist/lib/onboarding.d.ts +20 -0
- package/dist/lib/onboarding.d.ts.map +1 -0
- package/dist/lib/onboarding.js +129 -0
- package/dist/lib/providers/catalog.d.ts +5 -0
- package/dist/lib/providers/catalog.d.ts.map +1 -1
- package/dist/lib/providers/catalog.js +34 -1
- package/dist/lib/providers/credentials.d.ts +2 -0
- package/dist/lib/providers/credentials.d.ts.map +1 -1
- package/dist/lib/providers/credentials.js +19 -3
- package/dist/lib/providers/cursor-runner.d.ts +2 -2
- package/dist/lib/providers/cursor-runner.d.ts.map +1 -1
- package/dist/lib/providers/cursor-runner.js +7 -5
- package/dist/lib/providers/cursor-sdk.d.ts +8 -0
- package/dist/lib/providers/cursor-sdk.d.ts.map +1 -0
- package/dist/lib/providers/cursor-sdk.js +25 -0
- package/dist/lib/providers/store.d.ts +1 -1
- package/dist/lib/providers/store.d.ts.map +1 -1
- package/dist/lib/providers/store.js +13 -7
- package/dist/lib/providers/ui.d.ts +2 -0
- package/dist/lib/providers/ui.d.ts.map +1 -1
- package/dist/lib/providers/ui.js +60 -24
- package/dist/lib/setup-messages.d.ts +4 -0
- package/dist/lib/setup-messages.d.ts.map +1 -0
- package/dist/lib/setup-messages.js +13 -0
- package/dist/lib/ui/splash.d.ts.map +1 -1
- package/dist/lib/ui/splash.js +4 -0
- package/dist/lib/version.d.ts +2 -0
- package/dist/lib/version.d.ts.map +1 -0
- package/dist/lib/version.js +13 -0
- package/package.json +10 -2
package/README.md
CHANGED
|
@@ -8,17 +8,43 @@ Runs **in your repo** with Composer 2.5 Fast. Edits files directly.
|
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
npm install -g @ekzs/cli
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Clean install (~15 packages) — BYOK with OpenAI, Anthropic, DeepSeek, etc. Keys via `ekz providers`.
|
|
14
|
+
|
|
15
|
+
**Cursor provider only** (optional — pulls native deps + npm deprecation noise from `@cursor/sdk`):
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install -g @cursor/sdk
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or install both at once:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install -g @ekzs/cli @cursor/sdk
|
|
13
25
|
```
|
|
14
26
|
|
|
15
27
|
## Setup (BYOK)
|
|
16
28
|
|
|
17
|
-
|
|
29
|
+
First run:
|
|
18
30
|
|
|
19
31
|
```bash
|
|
20
|
-
ekz
|
|
21
|
-
#
|
|
32
|
+
ekz setup
|
|
33
|
+
# aliases: ekz configurar · ekz 设置
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Wizard steps: **language** → **your name** → **Configurar provedor** (or offline).
|
|
37
|
+
|
|
38
|
+
Stored in `~/.ekz/config.json` (name, locale) and `~/.ekz/providers.json` (API keys).
|
|
39
|
+
|
|
40
|
+
Without a provider, `ekz` shows:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Setup required · Configuração necessária · 需要设置
|
|
44
|
+
|
|
45
|
+
pt: Corre `ekz setup` ou `ekz --offline`
|
|
46
|
+
en: Run `ekz setup` or `ekz --offline`
|
|
47
|
+
zh: 运行 `ekz setup` 或 `ekz --offline`
|
|
22
48
|
```
|
|
23
49
|
|
|
24
50
|
Supported providers: **Cursor**, **OpenAI**, **Anthropic**, **DeepSeek**, **Kimi**, **Groq**, **Mistral**, **Google Gemini**, **Ollama**.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../../src/commands/ask.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,SAAS,EAA0B,MAAM,kBAAkB,CAAC;AAyC1E,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB,CAAC;AAEF,mDAAmD;AACnD,wBAAsB,cAAc,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CA0B1E;AAED,wBAAsB,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,iBAO9D;AAgDD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,
|
|
1
|
+
{"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../../src/commands/ask.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,SAAS,EAA0B,MAAM,kBAAkB,CAAC;AAyC1E,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB,CAAC;AAEF,mDAAmD;AACnD,wBAAsB,cAAc,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CA0B1E;AAED,wBAAsB,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,iBAO9D;AAgDD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,iBAwEA;AAED,wBAAsB,eAAe,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAM/E"}
|
package/dist/commands/ask.js
CHANGED
|
@@ -5,6 +5,7 @@ import { parseLocale, uiStrings } from "../lib/locale.js";
|
|
|
5
5
|
import { parseMode } from "../lib/mode.js";
|
|
6
6
|
import { fail, heading, info, ok } from "../lib/output.js";
|
|
7
7
|
import { loadPreferences, savePreferences } from "../lib/preferences.js";
|
|
8
|
+
import { ensureAgentReady, offlineModelLabel } from "../lib/onboarding.js";
|
|
8
9
|
import { executeByokAskTurn } from "../lib/providers/chat.js";
|
|
9
10
|
import { executeCursorAskTurn } from "../lib/providers/cursor-runner.js";
|
|
10
11
|
import { isCursorProvider, requireActiveCredentials, ProviderSetupError, } from "../lib/providers/credentials.js";
|
|
@@ -13,7 +14,6 @@ import { redactText } from "../lib/redact.js";
|
|
|
13
14
|
import { askWithPlaceholder, formatInputPrompt } from "../lib/ui/prompt.js";
|
|
14
15
|
import { inputPlaceholder } from "../lib/ui/splash.js";
|
|
15
16
|
function deterministicAnswer(question, ctx, locale) {
|
|
16
|
-
const p = providersCommandLabels(locale);
|
|
17
17
|
const lines = ["## Ekz assistant (offline)", "", question, ""];
|
|
18
18
|
if (ctx.doctor.issues.length) {
|
|
19
19
|
lines.push("### Issues", ...ctx.doctor.issues.map((i) => `- ${i}`), "");
|
|
@@ -21,7 +21,7 @@ function deterministicAnswer(question, ctx, locale) {
|
|
|
21
21
|
if (ctx.scan.length) {
|
|
22
22
|
lines.push("### Scan", ...ctx.scan.slice(0, 8).map((f) => `- \`${f.file}:${f.line}\` · ${f.message}`), "");
|
|
23
23
|
}
|
|
24
|
-
lines.push("### Next steps",
|
|
24
|
+
lines.push("### Next steps", "- Run `ekz setup` to configure language, name, and provider", "- Or `ekz --offline` for doctor/scan only");
|
|
25
25
|
return lines.join("\n");
|
|
26
26
|
}
|
|
27
27
|
/** Q&A via BYOK provider (no local file edits). */
|
|
@@ -94,10 +94,23 @@ function handleAskMeta(line, locale) {
|
|
|
94
94
|
export async function runInteractiveAsk(opts) {
|
|
95
95
|
const prefs = loadPreferences(opts.cwd, opts.locale, "ask");
|
|
96
96
|
let currentLocale = prefs.locale;
|
|
97
|
+
let askOffline = Boolean(opts.offline);
|
|
98
|
+
try {
|
|
99
|
+
const ready = await ensureAgentReady({
|
|
100
|
+
locale: currentLocale,
|
|
101
|
+
offlineFlag: opts.offline,
|
|
102
|
+
});
|
|
103
|
+
askOffline = ready.offline || askOffline;
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
fail(err instanceof Error ? err.message : String(err));
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
97
109
|
printWelcome({
|
|
98
110
|
cwd: opts.cwd,
|
|
99
111
|
locale: currentLocale,
|
|
100
112
|
mode: "ask",
|
|
113
|
+
model: askOffline ? offlineModelLabel(currentLocale) : undefined,
|
|
101
114
|
});
|
|
102
115
|
let turn = 0;
|
|
103
116
|
while (true) {
|
|
@@ -134,7 +147,7 @@ export async function runInteractiveAsk(opts) {
|
|
|
134
147
|
await executeAskTurn({
|
|
135
148
|
cwd: opts.cwd,
|
|
136
149
|
question: line,
|
|
137
|
-
offline:
|
|
150
|
+
offline: askOffline,
|
|
138
151
|
quiet: true,
|
|
139
152
|
locale: currentLocale,
|
|
140
153
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-agent.d.ts","sourceRoot":"","sources":["../../src/commands/local-agent.ts"],"names":[],"mappings":"AAWA,OAAO,EAAsC,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAsBlF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;
|
|
1
|
+
{"version":3,"file":"local-agent.d.ts","sourceRoot":"","sources":["../../src/commands/local-agent.ts"],"names":[],"mappings":"AAWA,OAAO,EAAsC,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAsBlF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AA2PF,wBAAsB,aAAa,CAAC,IAAI,EAAE,iBAAiB,iBA0I1D;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,aAAa,CAAC,iBAmG9F"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { resolve } from "path";
|
|
2
|
-
import { Agent, CursorAgentError } from "@cursor/sdk";
|
|
3
2
|
import { executeAskTurn } from "../commands/ask.js";
|
|
4
3
|
import { runDoctor } from "../commands/doctor.js";
|
|
5
4
|
import { runScan } from "../commands/scan.js";
|
|
6
5
|
import { inputPlaceholder, printHelp, printLangSwitch, printModeSwitch, printWelcome } from "../lib/banner.js";
|
|
7
6
|
import { loadProjectEnv } from "../lib/env.js";
|
|
7
|
+
import { ensureAgentReady, offlineAgentHint, offlineModelLabel } from "../lib/onboarding.js";
|
|
8
8
|
import { resolveReplMetaCommand, isProvidersMetaCommand } from "../lib/commands-i18n.js";
|
|
9
9
|
import { buildAgentPrompt, buildBootstrapContext } from "../lib/context.js";
|
|
10
10
|
import { resolveComposerModel } from "../lib/composer-model.js";
|
|
@@ -12,29 +12,31 @@ import { parseLocale, uiStrings } from "../lib/locale.js";
|
|
|
12
12
|
import { modeRequiresCursorAgent, parseMode } from "../lib/mode.js";
|
|
13
13
|
import { loadPreferences, savePreferences } from "../lib/preferences.js";
|
|
14
14
|
import { runByokAgentTurn, usesCursorSdk } from "../lib/providers/agent-runner.js";
|
|
15
|
+
import { CursorSdkMissingError, loadCursorSdk } from "../lib/providers/cursor-sdk.js";
|
|
15
16
|
import { disposeAgent, streamRun } from "../lib/providers/cursor-runner.js";
|
|
16
|
-
import {
|
|
17
|
-
import { requireActiveCredentials, } from "../lib/providers/credentials.js";
|
|
17
|
+
import { resolveActiveCredentials, resolveCredentialsWithOverride, } from "../lib/providers/credentials.js";
|
|
18
18
|
import { runProvidersInteractive, formatActiveProviderLabel } from "../lib/providers/ui.js";
|
|
19
|
-
import { maskApiKey } from "../lib/providers/store.js";
|
|
20
19
|
import { clearSession, getSessionByIndex, loadSession, persistSession, saveNamedSession, } from "../lib/session.js";
|
|
21
20
|
import { fail, info, ok, warn } from "../lib/output.js";
|
|
22
21
|
import { turnDivider } from "../lib/theme.js";
|
|
23
22
|
import { askWithPlaceholder, formatInputPrompt } from "../lib/ui/prompt.js";
|
|
24
|
-
function
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
23
|
+
async function prepareAgentSession(opts, prefs) {
|
|
24
|
+
try {
|
|
25
|
+
const ready = await ensureAgentReady({
|
|
26
|
+
locale: prefs.locale,
|
|
27
|
+
offlineFlag: opts.askOffline,
|
|
28
|
+
apiKey: opts.apiKey,
|
|
29
|
+
});
|
|
30
|
+
return { offline: ready.offline, creds: ready.creds };
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
fail(err instanceof Error ? err.message : String(err));
|
|
34
|
+
process.exitCode = 1;
|
|
35
|
+
return null;
|
|
36
36
|
}
|
|
37
|
-
|
|
37
|
+
}
|
|
38
|
+
function resolveAgentCredentials(override, locale = "pt") {
|
|
39
|
+
return resolveCredentialsWithOverride(override, locale);
|
|
38
40
|
}
|
|
39
41
|
function resolveCursorModel(creds) {
|
|
40
42
|
return resolveComposerModel(process.env, creds.model);
|
|
@@ -53,12 +55,12 @@ async function runAgentTurn(options) {
|
|
|
53
55
|
const ctx = await buildBootstrapContext(options.cwd);
|
|
54
56
|
const prompt = buildAgentPrompt(options.task, ctx, options.locale);
|
|
55
57
|
try {
|
|
56
|
-
await streamRun(options.cursorAgent, prompt);
|
|
58
|
+
await streamRun(options.cursorAgent, prompt, options.locale);
|
|
57
59
|
console.log("\n");
|
|
58
60
|
return { cursorAgent: options.cursorAgent, ok: true };
|
|
59
61
|
}
|
|
60
62
|
catch (err) {
|
|
61
|
-
if (err instanceof CursorAgentError) {
|
|
63
|
+
if (err instanceof Error && err.name === "CursorAgentError") {
|
|
62
64
|
fail(err.message);
|
|
63
65
|
return { cursorAgent: options.cursorAgent, ok: false };
|
|
64
66
|
}
|
|
@@ -77,6 +79,7 @@ async function runAgentTurn(options) {
|
|
|
77
79
|
async function createOrResumeAgent(opts, locale = "pt") {
|
|
78
80
|
const cwd = resolve(opts.cwd);
|
|
79
81
|
const creds = resolveAgentCredentials(opts.apiKey, locale);
|
|
82
|
+
const { Agent } = await loadCursorSdk(locale);
|
|
80
83
|
const apiKey = creds.apiKey;
|
|
81
84
|
const model = resolveCursorModel(creds);
|
|
82
85
|
const usePlan = opts.mode === "plan" || Boolean(opts.plan);
|
|
@@ -195,6 +198,7 @@ async function resumeAgentInRepl(cwd, current, agentId, locale, apiKeyOverride)
|
|
|
195
198
|
? "恢复会话仅适用于 Cursor provider。"
|
|
196
199
|
: "Resume session is Cursor-only.");
|
|
197
200
|
}
|
|
201
|
+
const { Agent } = await loadCursorSdk(locale);
|
|
198
202
|
const model = resolveCursorModel(creds);
|
|
199
203
|
const agent = await Agent.resume(agentId, {
|
|
200
204
|
apiKey: creds.apiKey,
|
|
@@ -210,24 +214,24 @@ export async function runLocalAgent(opts) {
|
|
|
210
214
|
loadProjectEnv(cwd);
|
|
211
215
|
const prefs = loadPreferences(cwd, opts.locale, opts.mode, opts.plan);
|
|
212
216
|
const mode = prefs.mode;
|
|
213
|
-
const
|
|
217
|
+
const session = await prepareAgentSession(opts, prefs);
|
|
218
|
+
if (!session)
|
|
219
|
+
return;
|
|
220
|
+
const { offline, creds: sessionCreds } = session;
|
|
221
|
+
const askOffline = offline || Boolean(opts.askOffline);
|
|
222
|
+
const providerLabel = askOffline
|
|
223
|
+
? offlineModelLabel(prefs.locale)
|
|
224
|
+
: sessionCreds
|
|
225
|
+
? formatActiveProviderLabel(prefs.locale)
|
|
226
|
+
: formatActiveProviderLabel(prefs.locale);
|
|
214
227
|
if (mode === "ask") {
|
|
215
|
-
let askCreds;
|
|
216
|
-
try {
|
|
217
|
-
askCreds = resolveAgentCredentials(opts.apiKey, prefs.locale);
|
|
218
|
-
}
|
|
219
|
-
catch (err) {
|
|
220
|
-
fail(err instanceof Error ? err.message : String(err));
|
|
221
|
-
process.exitCode = 1;
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
228
|
printWelcome({ cwd, locale: prefs.locale, mode: "ask", model: providerLabel });
|
|
225
229
|
if (opts.task.trim()) {
|
|
226
230
|
info(`${uiStrings(prefs.locale).workingOn}: ${opts.task.slice(0, 120)}${opts.task.length > 120 ? "…" : ""}\n`);
|
|
227
231
|
await executeAskTurn({
|
|
228
232
|
cwd,
|
|
229
233
|
question: opts.task.trim(),
|
|
230
|
-
offline:
|
|
234
|
+
offline: askOffline,
|
|
231
235
|
quiet: true,
|
|
232
236
|
locale: prefs.locale,
|
|
233
237
|
});
|
|
@@ -240,23 +244,54 @@ export async function runLocalAgent(opts) {
|
|
|
240
244
|
locale: prefs.locale,
|
|
241
245
|
mode: "ask",
|
|
242
246
|
apiKey: opts.apiKey,
|
|
243
|
-
askOffline
|
|
244
|
-
creds:
|
|
247
|
+
askOffline,
|
|
248
|
+
creds: sessionCreds,
|
|
249
|
+
offline: askOffline,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (askOffline) {
|
|
255
|
+
printWelcome({ cwd, locale: prefs.locale, mode, model: providerLabel });
|
|
256
|
+
savePreferences(cwd, { mode });
|
|
257
|
+
if (opts.task.trim()) {
|
|
258
|
+
info(`${uiStrings(prefs.locale).workingOn}: ${opts.task.slice(0, 120)}${opts.task.length > 120 ? "…" : ""}\n`);
|
|
259
|
+
warn(offlineAgentHint(prefs.locale));
|
|
260
|
+
}
|
|
261
|
+
if (opts.interactive !== false) {
|
|
262
|
+
await runRepl({
|
|
263
|
+
agent: null,
|
|
264
|
+
cwd,
|
|
265
|
+
locale: prefs.locale,
|
|
266
|
+
mode,
|
|
267
|
+
apiKey: opts.apiKey,
|
|
268
|
+
askOffline: true,
|
|
269
|
+
creds: null,
|
|
270
|
+
offline: true,
|
|
245
271
|
});
|
|
246
272
|
}
|
|
247
273
|
return;
|
|
248
274
|
}
|
|
275
|
+
if (!sessionCreds) {
|
|
276
|
+
fail(offlineAgentHint(prefs.locale));
|
|
277
|
+
process.exitCode = 1;
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
249
280
|
let agent = null;
|
|
250
281
|
let resumed = false;
|
|
251
|
-
|
|
282
|
+
const creds = sessionCreds;
|
|
252
283
|
try {
|
|
253
|
-
creds = resolveAgentCredentials(opts.apiKey, prefs.locale);
|
|
254
284
|
if (usesCursorSdk(creds)) {
|
|
255
285
|
({ agent, resumed } = await createOrResumeAgent({ ...opts, mode }, prefs.locale));
|
|
256
286
|
}
|
|
257
287
|
}
|
|
258
288
|
catch (err) {
|
|
259
|
-
if (err instanceof
|
|
289
|
+
if (err instanceof CursorSdkMissingError) {
|
|
290
|
+
fail(err.message);
|
|
291
|
+
process.exitCode = 1;
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
if (err instanceof Error && err.name === "CursorAgentError") {
|
|
260
295
|
fail(`Agent startup failed: ${err.message}`);
|
|
261
296
|
process.exitCode = 1;
|
|
262
297
|
return;
|
|
@@ -298,8 +333,9 @@ export async function runLocalAgent(opts) {
|
|
|
298
333
|
locale: prefs.locale,
|
|
299
334
|
mode,
|
|
300
335
|
apiKey: opts.apiKey,
|
|
301
|
-
askOffline
|
|
336
|
+
askOffline,
|
|
302
337
|
creds,
|
|
338
|
+
offline: false,
|
|
303
339
|
});
|
|
304
340
|
}
|
|
305
341
|
else {
|
|
@@ -316,17 +352,15 @@ export async function runInteractiveAgent(opts) {
|
|
|
316
352
|
loadProjectEnv(cwd);
|
|
317
353
|
const prefs = loadPreferences(cwd, opts.locale, opts.mode, opts.plan);
|
|
318
354
|
const mode = prefs.mode;
|
|
319
|
-
const
|
|
355
|
+
const session = await prepareAgentSession({ ...opts, task: "" }, prefs);
|
|
356
|
+
if (!session)
|
|
357
|
+
return;
|
|
358
|
+
const { offline, creds: sessionCreds } = session;
|
|
359
|
+
const askOffline = offline || Boolean(opts.askOffline);
|
|
360
|
+
const providerLabel = askOffline
|
|
361
|
+
? offlineModelLabel(prefs.locale)
|
|
362
|
+
: formatActiveProviderLabel(prefs.locale);
|
|
320
363
|
if (mode === "ask") {
|
|
321
|
-
let creds;
|
|
322
|
-
try {
|
|
323
|
-
creds = resolveAgentCredentials(opts.apiKey, prefs.locale);
|
|
324
|
-
}
|
|
325
|
-
catch (err) {
|
|
326
|
-
fail(err instanceof Error ? err.message : String(err));
|
|
327
|
-
process.exitCode = 1;
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
330
364
|
printWelcome({ cwd, locale: prefs.locale, mode: "ask", model: providerLabel });
|
|
331
365
|
await runRepl({
|
|
332
366
|
agent: null,
|
|
@@ -334,22 +368,47 @@ export async function runInteractiveAgent(opts) {
|
|
|
334
368
|
locale: prefs.locale,
|
|
335
369
|
mode: "ask",
|
|
336
370
|
apiKey: opts.apiKey,
|
|
337
|
-
askOffline
|
|
338
|
-
creds,
|
|
371
|
+
askOffline,
|
|
372
|
+
creds: sessionCreds,
|
|
373
|
+
offline: askOffline,
|
|
339
374
|
});
|
|
340
375
|
return;
|
|
341
376
|
}
|
|
377
|
+
if (askOffline) {
|
|
378
|
+
printWelcome({ cwd, locale: prefs.locale, mode, model: providerLabel });
|
|
379
|
+
savePreferences(cwd, { mode });
|
|
380
|
+
await runRepl({
|
|
381
|
+
agent: null,
|
|
382
|
+
cwd,
|
|
383
|
+
locale: prefs.locale,
|
|
384
|
+
mode,
|
|
385
|
+
apiKey: opts.apiKey,
|
|
386
|
+
askOffline: true,
|
|
387
|
+
creds: null,
|
|
388
|
+
offline: true,
|
|
389
|
+
});
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
if (!sessionCreds) {
|
|
393
|
+
fail(offlineAgentHint(prefs.locale));
|
|
394
|
+
process.exitCode = 1;
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
342
397
|
let agent = null;
|
|
343
398
|
let resumed = false;
|
|
344
|
-
|
|
399
|
+
const creds = sessionCreds;
|
|
345
400
|
try {
|
|
346
|
-
creds = resolveAgentCredentials(opts.apiKey, prefs.locale);
|
|
347
401
|
if (usesCursorSdk(creds)) {
|
|
348
402
|
({ agent, resumed } = await createOrResumeAgent({ ...opts, task: "", mode }, prefs.locale));
|
|
349
403
|
}
|
|
350
404
|
}
|
|
351
405
|
catch (err) {
|
|
352
|
-
if (err instanceof
|
|
406
|
+
if (err instanceof CursorSdkMissingError) {
|
|
407
|
+
fail(err.message);
|
|
408
|
+
process.exitCode = 1;
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
if (err instanceof Error && err.name === "CursorAgentError") {
|
|
353
412
|
fail(`Agent startup failed: ${err.message}`);
|
|
354
413
|
process.exitCode = 1;
|
|
355
414
|
return;
|
|
@@ -376,8 +435,9 @@ export async function runInteractiveAgent(opts) {
|
|
|
376
435
|
locale: prefs.locale,
|
|
377
436
|
mode,
|
|
378
437
|
apiKey: opts.apiKey,
|
|
379
|
-
askOffline
|
|
438
|
+
askOffline,
|
|
380
439
|
creds,
|
|
440
|
+
offline: false,
|
|
381
441
|
});
|
|
382
442
|
}
|
|
383
443
|
finally {
|
|
@@ -390,16 +450,31 @@ async function runRepl(opts) {
|
|
|
390
450
|
let currentMode = opts.mode;
|
|
391
451
|
let currentAgent = opts.agent;
|
|
392
452
|
let currentCreds = opts.creds;
|
|
453
|
+
let currentOffline = opts.offline;
|
|
393
454
|
let turn = 0;
|
|
394
455
|
const t = () => uiStrings(currentLocale);
|
|
395
456
|
const resolveCreds = () => {
|
|
457
|
+
if (currentOffline) {
|
|
458
|
+
try {
|
|
459
|
+
const live = resolveActiveCredentials();
|
|
460
|
+
if (live) {
|
|
461
|
+
currentOffline = false;
|
|
462
|
+
currentCreds = live;
|
|
463
|
+
return live;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
catch {
|
|
467
|
+
/* stay offline */
|
|
468
|
+
}
|
|
469
|
+
return null;
|
|
470
|
+
}
|
|
396
471
|
try {
|
|
397
472
|
currentCreds = resolveAgentCredentials(opts.apiKey, currentLocale);
|
|
473
|
+
return currentCreds;
|
|
398
474
|
}
|
|
399
475
|
catch {
|
|
400
|
-
|
|
476
|
+
return currentCreds;
|
|
401
477
|
}
|
|
402
|
-
return currentCreds;
|
|
403
478
|
};
|
|
404
479
|
while (true) {
|
|
405
480
|
const line = (await askWithPlaceholder({
|
|
@@ -410,7 +485,11 @@ async function runRepl(opts) {
|
|
|
410
485
|
break;
|
|
411
486
|
if (isProvidersMetaCommand(line.trim().split(/\s+/)[0] ?? "")) {
|
|
412
487
|
await runProvidersInteractive(currentLocale);
|
|
413
|
-
|
|
488
|
+
const live = resolveActiveCredentials();
|
|
489
|
+
if (live) {
|
|
490
|
+
currentOffline = false;
|
|
491
|
+
currentCreds = live;
|
|
492
|
+
}
|
|
414
493
|
continue;
|
|
415
494
|
}
|
|
416
495
|
const meta = handleMetaCommand(line, currentLocale, opts.cwd, currentMode);
|
|
@@ -432,7 +511,7 @@ async function runRepl(opts) {
|
|
|
432
511
|
}
|
|
433
512
|
else {
|
|
434
513
|
const creds = resolveCreds();
|
|
435
|
-
if (usesCursorSdk(creds)) {
|
|
514
|
+
if (creds && usesCursorSdk(creds)) {
|
|
436
515
|
currentAgent = await recreateAgentForMode(opts.cwd, currentAgent, currentMode, opts.apiKey, currentLocale);
|
|
437
516
|
}
|
|
438
517
|
else if (currentAgent) {
|
|
@@ -447,7 +526,8 @@ async function runRepl(opts) {
|
|
|
447
526
|
continue;
|
|
448
527
|
}
|
|
449
528
|
if (meta?.kind === "resume") {
|
|
450
|
-
|
|
529
|
+
const resumeCreds = resolveCreds();
|
|
530
|
+
if (currentMode === "ask" || !resumeCreds || !usesCursorSdk(resumeCreds)) {
|
|
451
531
|
warn(currentLocale === "pt"
|
|
452
532
|
? "Sessões guardadas só com provider Cursor."
|
|
453
533
|
: currentLocale === "zh"
|
|
@@ -468,7 +548,8 @@ async function runRepl(opts) {
|
|
|
468
548
|
continue;
|
|
469
549
|
}
|
|
470
550
|
if (meta?.kind === "save") {
|
|
471
|
-
|
|
551
|
+
const saveCreds = resolveCreds();
|
|
552
|
+
if (!currentAgent || !saveCreds || !usesCursorSdk(saveCreds)) {
|
|
472
553
|
warn(currentLocale === "pt"
|
|
473
554
|
? "Guardar sessão só com provider Cursor."
|
|
474
555
|
: currentLocale === "zh"
|
|
@@ -492,7 +573,7 @@ async function runRepl(opts) {
|
|
|
492
573
|
await executeAskTurn({
|
|
493
574
|
cwd: opts.cwd,
|
|
494
575
|
question: line,
|
|
495
|
-
offline: opts.askOffline,
|
|
576
|
+
offline: currentOffline || Boolean(opts.askOffline),
|
|
496
577
|
quiet: true,
|
|
497
578
|
locale: currentLocale,
|
|
498
579
|
});
|
|
@@ -500,7 +581,12 @@ async function runRepl(opts) {
|
|
|
500
581
|
turn++;
|
|
501
582
|
continue;
|
|
502
583
|
}
|
|
503
|
-
|
|
584
|
+
if (currentOffline || !resolveCreds()) {
|
|
585
|
+
warn(offlineAgentHint(currentLocale));
|
|
586
|
+
turn++;
|
|
587
|
+
continue;
|
|
588
|
+
}
|
|
589
|
+
const creds = currentCreds;
|
|
504
590
|
if (usesCursorSdk(creds) && !currentAgent) {
|
|
505
591
|
fail(currentLocale === "pt" ? "Sem agente Cursor activo." : "No active Cursor agent.");
|
|
506
592
|
continue;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAEA,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,iBAE/E"}
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,9 @@ import { runFixCommand } from "./commands/agent.js";
|
|
|
11
11
|
import { runHealth } from "./commands/health.js";
|
|
12
12
|
import { runScan } from "./commands/scan.js";
|
|
13
13
|
import { runProvidersCommand } from "./commands/providers.js";
|
|
14
|
+
import { runSetupCommand } from "./commands/setup.js";
|
|
14
15
|
import { runWebhookTest } from "./commands/webhook.js";
|
|
16
|
+
import { packageVersion } from "./lib/version.js";
|
|
15
17
|
const SUBCOMMANDS = new Set([
|
|
16
18
|
"doctor",
|
|
17
19
|
"health",
|
|
@@ -21,6 +23,7 @@ const SUBCOMMANDS = new Set([
|
|
|
21
23
|
"fix",
|
|
22
24
|
"ask",
|
|
23
25
|
"providers",
|
|
26
|
+
"setup",
|
|
24
27
|
]);
|
|
25
28
|
/** Bare `ekz` or `ekz "natural language task"` → agent. Resolves PT/zh CLI aliases. */
|
|
26
29
|
function normalizeArgv(argv) {
|
|
@@ -38,7 +41,7 @@ const program = new Command();
|
|
|
38
41
|
program
|
|
39
42
|
.name("ekz")
|
|
40
43
|
.description("EKZ CONNECT — e-Kwanza v2.4 coding agent by Alberto Moisés")
|
|
41
|
-
.version(
|
|
44
|
+
.version(packageVersion());
|
|
42
45
|
program
|
|
43
46
|
.command("doctor")
|
|
44
47
|
.description("Validate .env and run live credential checks (free)")
|
|
@@ -134,6 +137,20 @@ program
|
|
|
134
137
|
process.exitCode = 1;
|
|
135
138
|
}
|
|
136
139
|
});
|
|
140
|
+
program
|
|
141
|
+
.command("setup")
|
|
142
|
+
.alias("configurar")
|
|
143
|
+
.description("First-run setup — language, name, provider or offline")
|
|
144
|
+
.option("-l, --lang <code>", "Skip language pick: pt, en, or zh")
|
|
145
|
+
.action(async (opts) => {
|
|
146
|
+
try {
|
|
147
|
+
await runSetupCommand({ locale: opts.lang });
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
console.error(err instanceof Error ? err.message : err);
|
|
151
|
+
process.exitCode = 1;
|
|
152
|
+
}
|
|
153
|
+
});
|
|
137
154
|
program
|
|
138
155
|
.command("providers")
|
|
139
156
|
.alias("provedores")
|
|
@@ -6,9 +6,9 @@ export type ProvidersCommandLabels = {
|
|
|
6
6
|
replAliases: string[];
|
|
7
7
|
};
|
|
8
8
|
export declare function providersCommandLabels(locale: EkzLocale): ProvidersCommandLabels;
|
|
9
|
-
export declare function providersSetupHint(
|
|
9
|
+
export declare function providersSetupHint(_locale?: EkzLocale): string;
|
|
10
10
|
export declare function isProvidersMetaCommand(token: string): boolean;
|
|
11
|
-
export type CliCommandId = "doctor" | "health" | "scan" | "webhook" | "agent" | "fix" | "ask" | "providers";
|
|
11
|
+
export type CliCommandId = "doctor" | "health" | "scan" | "webhook" | "agent" | "fix" | "ask" | "providers" | "setup";
|
|
12
12
|
export declare function resolveCliSubcommand(token: string): string;
|
|
13
13
|
export declare function isKnownSubcommand(token: string): boolean;
|
|
14
14
|
export declare const SPLASH_TOOLS: Record<EkzLocale, Array<{
|
|
@@ -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;
|
|
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"}
|