@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.
- package/README.md +49 -13
- 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 +50 -36
- 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 +292 -131
- 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/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 +41 -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 +78 -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/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 +16 -12
- 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/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 +28 -0
- package/dist/lib/providers/credentials.d.ts.map +1 -0
- package/dist/lib/providers/credentials.js +70 -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 +89 -0
- 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 +21 -0
- package/dist/lib/providers/store.d.ts.map +1 -0
- package/dist/lib/providers/store.js +84 -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/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/package.json +10 -2
- package/skills/ekz-sdk-cli/SKILL.md +6 -4
|
@@ -1,83 +1,87 @@
|
|
|
1
1
|
import { resolve } from "path";
|
|
2
|
-
import { Agent, AgentBusyError, 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";
|
|
8
|
-
import {
|
|
7
|
+
import { ensureAgentReady, offlineAgentHint, offlineModelLabel } from "../lib/onboarding.js";
|
|
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";
|
|
11
11
|
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
|
+
import { runByokAgentTurn, usesCursorSdk } from "../lib/providers/agent-runner.js";
|
|
15
|
+
import { CursorSdkMissingError, loadCursorSdk } from "../lib/providers/cursor-sdk.js";
|
|
16
|
+
import { disposeAgent, streamRun } from "../lib/providers/cursor-runner.js";
|
|
17
|
+
import { resolveActiveCredentials, resolveCredentialsWithOverride, } from "../lib/providers/credentials.js";
|
|
18
|
+
import { runProvidersInteractive, formatActiveProviderLabel } from "../lib/providers/ui.js";
|
|
14
19
|
import { clearSession, getSessionByIndex, loadSession, persistSession, saveNamedSession, } from "../lib/session.js";
|
|
15
20
|
import { fail, info, ok, warn } from "../lib/output.js";
|
|
16
|
-
import {
|
|
21
|
+
import { turnDivider } from "../lib/theme.js";
|
|
17
22
|
import { askWithPlaceholder, formatInputPrompt } from "../lib/ui/prompt.js";
|
|
18
|
-
function
|
|
19
|
-
if (cwd)
|
|
20
|
-
loadProjectEnv(cwd);
|
|
21
|
-
else
|
|
22
|
-
loadProjectEnv(process.cwd());
|
|
23
|
-
const key = override ?? process.env.CURSOR_API_KEY?.trim();
|
|
24
|
-
if (!key) {
|
|
25
|
-
throw new Error("CURSOR_API_KEY required. Add it to .env.local or export it — https://cursor.com/dashboard/integrations");
|
|
26
|
-
}
|
|
27
|
-
return key;
|
|
28
|
-
}
|
|
29
|
-
async function disposeAgent(agent) {
|
|
30
|
-
const disposer = agent[Symbol.asyncDispose];
|
|
31
|
-
if (typeof disposer === "function")
|
|
32
|
-
await disposer.call(agent);
|
|
33
|
-
else
|
|
34
|
-
agent.close();
|
|
35
|
-
}
|
|
36
|
-
async function streamRun(agent, prompt, locale, opts) {
|
|
37
|
-
const t = uiStrings(locale);
|
|
38
|
-
const sendOptions = {
|
|
39
|
-
onDelta: ({ update }) => {
|
|
40
|
-
if (update.type === "text-delta" && update.text) {
|
|
41
|
-
process.stdout.write(update.text);
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
|
-
...(opts?.force ? { local: { force: true } } : {}),
|
|
45
|
-
};
|
|
46
|
-
let run;
|
|
23
|
+
async function prepareAgentSession(opts, prefs) {
|
|
47
24
|
try {
|
|
48
|
-
|
|
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 };
|
|
49
31
|
}
|
|
50
32
|
catch (err) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
throw err;
|
|
57
|
-
}
|
|
33
|
+
fail(err instanceof Error ? err.message : String(err));
|
|
34
|
+
process.exitCode = 1;
|
|
35
|
+
return null;
|
|
58
36
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
37
|
+
}
|
|
38
|
+
function resolveAgentCredentials(override, locale = "pt") {
|
|
39
|
+
return resolveCredentialsWithOverride(override, locale);
|
|
40
|
+
}
|
|
41
|
+
function resolveCursorModel(creds) {
|
|
42
|
+
return resolveComposerModel(process.env, creds.model);
|
|
43
|
+
}
|
|
44
|
+
function providerModelLabel(creds) {
|
|
45
|
+
if (usesCursorSdk(creds))
|
|
46
|
+
return resolveCursorModel(creds).label;
|
|
47
|
+
return `${creds.definition.name} · ${creds.model}`;
|
|
48
|
+
}
|
|
49
|
+
async function runAgentTurn(options) {
|
|
50
|
+
if (usesCursorSdk(options.creds)) {
|
|
51
|
+
if (!options.cursorAgent) {
|
|
52
|
+
fail(options.locale === "pt" ? "Sem agente Cursor activo." : "No active Cursor agent.");
|
|
53
|
+
return { cursorAgent: null, ok: false };
|
|
62
54
|
}
|
|
63
|
-
|
|
64
|
-
|
|
55
|
+
const ctx = await buildBootstrapContext(options.cwd);
|
|
56
|
+
const prompt = buildAgentPrompt(options.task, ctx, options.locale);
|
|
57
|
+
try {
|
|
58
|
+
await streamRun(options.cursorAgent, prompt, options.locale);
|
|
59
|
+
console.log("\n");
|
|
60
|
+
return { cursorAgent: options.cursorAgent, ok: true };
|
|
65
61
|
}
|
|
66
|
-
|
|
67
|
-
|
|
62
|
+
catch (err) {
|
|
63
|
+
if (err instanceof Error && err.name === "CursorAgentError") {
|
|
64
|
+
fail(err.message);
|
|
65
|
+
return { cursorAgent: options.cursorAgent, ok: false };
|
|
66
|
+
}
|
|
67
|
+
throw err;
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
const okResult = await runByokAgentTurn({
|
|
71
|
+
cwd: options.cwd,
|
|
72
|
+
task: options.task,
|
|
73
|
+
creds: options.creds,
|
|
74
|
+
locale: options.locale,
|
|
75
|
+
mode: options.mode,
|
|
76
|
+
});
|
|
77
|
+
return { cursorAgent: options.cursorAgent, ok: okResult };
|
|
76
78
|
}
|
|
77
|
-
async function createOrResumeAgent(opts) {
|
|
79
|
+
async function createOrResumeAgent(opts, locale = "pt") {
|
|
78
80
|
const cwd = resolve(opts.cwd);
|
|
79
|
-
const
|
|
80
|
-
const
|
|
81
|
+
const creds = resolveAgentCredentials(opts.apiKey, locale);
|
|
82
|
+
const { Agent } = await loadCursorSdk(locale);
|
|
83
|
+
const apiKey = creds.apiKey;
|
|
84
|
+
const model = resolveCursorModel(creds);
|
|
81
85
|
const usePlan = opts.mode === "plan" || Boolean(opts.plan);
|
|
82
86
|
if (opts.fresh)
|
|
83
87
|
clearSession(cwd);
|
|
@@ -100,9 +104,12 @@ async function createOrResumeAgent(opts) {
|
|
|
100
104
|
});
|
|
101
105
|
return { agent, resumed: false };
|
|
102
106
|
}
|
|
103
|
-
async function recreateAgentForMode(cwd, current, mode, apiKey) {
|
|
107
|
+
async function recreateAgentForMode(cwd, current, mode, apiKey, locale = "pt") {
|
|
104
108
|
if (!modeRequiresCursorAgent(mode))
|
|
105
109
|
return null;
|
|
110
|
+
const creds = resolveAgentCredentials(apiKey, locale);
|
|
111
|
+
if (!usesCursorSdk(creds))
|
|
112
|
+
return null;
|
|
106
113
|
if (current)
|
|
107
114
|
await disposeAgent(current);
|
|
108
115
|
const { agent } = await createOrResumeAgent({
|
|
@@ -111,12 +118,12 @@ async function recreateAgentForMode(cwd, current, mode, apiKey) {
|
|
|
111
118
|
fresh: true,
|
|
112
119
|
mode,
|
|
113
120
|
apiKey,
|
|
114
|
-
});
|
|
121
|
+
}, locale);
|
|
115
122
|
await persistAgent(cwd, agent);
|
|
116
123
|
return agent;
|
|
117
124
|
}
|
|
118
|
-
async function persistAgent(cwd, agent) {
|
|
119
|
-
const model = resolveComposerModel();
|
|
125
|
+
async function persistAgent(cwd, agent, creds) {
|
|
126
|
+
const model = creds ? resolveCursorModel(creds) : resolveComposerModel();
|
|
120
127
|
persistSession(cwd, {
|
|
121
128
|
agentId: agent.agentId,
|
|
122
129
|
cwd: resolve(cwd),
|
|
@@ -180,37 +187,53 @@ function handleMetaCommand(line, locale, cwd, currentMode) {
|
|
|
180
187
|
}
|
|
181
188
|
return null;
|
|
182
189
|
}
|
|
183
|
-
async function resumeAgentInRepl(cwd, current, agentId, locale) {
|
|
190
|
+
async function resumeAgentInRepl(cwd, current, agentId, locale, apiKeyOverride) {
|
|
184
191
|
if (current)
|
|
185
192
|
await disposeAgent(current);
|
|
186
|
-
const
|
|
187
|
-
|
|
193
|
+
const creds = resolveAgentCredentials(apiKeyOverride, locale);
|
|
194
|
+
if (!usesCursorSdk(creds)) {
|
|
195
|
+
throw new Error(locale === "pt"
|
|
196
|
+
? "Retomar sessão só com provider Cursor."
|
|
197
|
+
: locale === "zh"
|
|
198
|
+
? "恢复会话仅适用于 Cursor provider。"
|
|
199
|
+
: "Resume session is Cursor-only.");
|
|
200
|
+
}
|
|
201
|
+
const { Agent } = await loadCursorSdk(locale);
|
|
202
|
+
const model = resolveCursorModel(creds);
|
|
188
203
|
const agent = await Agent.resume(agentId, {
|
|
189
|
-
apiKey,
|
|
204
|
+
apiKey: creds.apiKey,
|
|
190
205
|
model: { id: model.id, params: model.params },
|
|
191
206
|
local: { cwd: resolve(cwd), settingSources: ["project"] },
|
|
192
207
|
});
|
|
193
|
-
await persistAgent(cwd, agent);
|
|
208
|
+
await persistAgent(cwd, agent, creds);
|
|
194
209
|
ok(locale === "pt" ? "Sessão retomada." : "Session resumed.");
|
|
195
210
|
return agent;
|
|
196
211
|
}
|
|
197
212
|
export async function runLocalAgent(opts) {
|
|
198
213
|
const cwd = resolve(opts.cwd);
|
|
199
214
|
loadProjectEnv(cwd);
|
|
200
|
-
const model = resolveComposerModel();
|
|
201
215
|
const prefs = loadPreferences(cwd, opts.locale, opts.mode, opts.plan);
|
|
202
216
|
const mode = prefs.mode;
|
|
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);
|
|
203
227
|
if (mode === "ask") {
|
|
204
|
-
printWelcome({ cwd, locale: prefs.locale, mode: "ask" });
|
|
228
|
+
printWelcome({ cwd, locale: prefs.locale, mode: "ask", model: providerLabel });
|
|
205
229
|
if (opts.task.trim()) {
|
|
206
230
|
info(`${uiStrings(prefs.locale).workingOn}: ${opts.task.slice(0, 120)}${opts.task.length > 120 ? "…" : ""}\n`);
|
|
207
231
|
await executeAskTurn({
|
|
208
232
|
cwd,
|
|
209
233
|
question: opts.task.trim(),
|
|
210
|
-
|
|
211
|
-
apiUrl: opts.askApiUrl,
|
|
212
|
-
offline: opts.askOffline,
|
|
234
|
+
offline: askOffline,
|
|
213
235
|
quiet: true,
|
|
236
|
+
locale: prefs.locale,
|
|
214
237
|
});
|
|
215
238
|
console.log("");
|
|
216
239
|
}
|
|
@@ -221,44 +244,88 @@ export async function runLocalAgent(opts) {
|
|
|
221
244
|
locale: prefs.locale,
|
|
222
245
|
mode: "ask",
|
|
223
246
|
apiKey: opts.apiKey,
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
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,
|
|
227
271
|
});
|
|
228
272
|
}
|
|
229
273
|
return;
|
|
230
274
|
}
|
|
231
|
-
|
|
275
|
+
if (!sessionCreds) {
|
|
276
|
+
fail(offlineAgentHint(prefs.locale));
|
|
277
|
+
process.exitCode = 1;
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
let agent = null;
|
|
232
281
|
let resumed = false;
|
|
282
|
+
const creds = sessionCreds;
|
|
233
283
|
try {
|
|
234
|
-
|
|
284
|
+
if (usesCursorSdk(creds)) {
|
|
285
|
+
({ agent, resumed } = await createOrResumeAgent({ ...opts, mode }, prefs.locale));
|
|
286
|
+
}
|
|
235
287
|
}
|
|
236
288
|
catch (err) {
|
|
237
|
-
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") {
|
|
238
295
|
fail(`Agent startup failed: ${err.message}`);
|
|
239
296
|
process.exitCode = 1;
|
|
240
297
|
return;
|
|
241
298
|
}
|
|
242
|
-
|
|
299
|
+
fail(err instanceof Error ? err.message : String(err));
|
|
300
|
+
process.exitCode = 1;
|
|
301
|
+
return;
|
|
243
302
|
}
|
|
244
303
|
printWelcome({
|
|
245
304
|
cwd,
|
|
246
|
-
model:
|
|
305
|
+
model: providerModelLabel(creds),
|
|
247
306
|
locale: prefs.locale,
|
|
248
307
|
mode,
|
|
249
308
|
resumed,
|
|
250
|
-
agentId: agent
|
|
309
|
+
agentId: agent?.agentId,
|
|
251
310
|
});
|
|
252
|
-
|
|
311
|
+
if (agent)
|
|
312
|
+
await persistAgent(cwd, agent, creds);
|
|
253
313
|
savePreferences(cwd, { mode });
|
|
254
|
-
const bootstrap = await buildBootstrapContext(cwd);
|
|
255
|
-
const prompt = buildAgentPrompt(opts.task, bootstrap, prefs.locale);
|
|
256
314
|
const t = uiStrings(prefs.locale);
|
|
257
315
|
try {
|
|
258
316
|
info(`${t.workingOn}: ${opts.task.slice(0, 120)}${opts.task.length > 120 ? "…" : ""}\n`);
|
|
259
|
-
const outcome = await
|
|
260
|
-
|
|
261
|
-
|
|
317
|
+
const outcome = await runAgentTurn({
|
|
318
|
+
cwd,
|
|
319
|
+
task: opts.task,
|
|
320
|
+
creds,
|
|
321
|
+
locale: prefs.locale,
|
|
322
|
+
mode,
|
|
323
|
+
cursorAgent: agent,
|
|
324
|
+
});
|
|
325
|
+
if (outcome.ok)
|
|
326
|
+
ok(t.done);
|
|
327
|
+
if (outcome.cursorAgent)
|
|
328
|
+
agent = outcome.cursorAgent;
|
|
262
329
|
if (opts.interactive !== false) {
|
|
263
330
|
await runRepl({
|
|
264
331
|
agent,
|
|
@@ -266,9 +333,9 @@ export async function runLocalAgent(opts) {
|
|
|
266
333
|
locale: prefs.locale,
|
|
267
334
|
mode,
|
|
268
335
|
apiKey: opts.apiKey,
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
336
|
+
askOffline,
|
|
337
|
+
creds,
|
|
338
|
+
offline: false,
|
|
272
339
|
});
|
|
273
340
|
}
|
|
274
341
|
else {
|
|
@@ -276,51 +343,90 @@ export async function runLocalAgent(opts) {
|
|
|
276
343
|
}
|
|
277
344
|
}
|
|
278
345
|
finally {
|
|
279
|
-
|
|
346
|
+
if (agent)
|
|
347
|
+
await disposeAgent(agent);
|
|
280
348
|
}
|
|
281
349
|
}
|
|
282
350
|
export async function runInteractiveAgent(opts) {
|
|
283
351
|
const cwd = resolve(opts.cwd);
|
|
284
352
|
loadProjectEnv(cwd);
|
|
285
|
-
const model = resolveComposerModel();
|
|
286
353
|
const prefs = loadPreferences(cwd, opts.locale, opts.mode, opts.plan);
|
|
287
354
|
const mode = prefs.mode;
|
|
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);
|
|
288
363
|
if (mode === "ask") {
|
|
289
|
-
printWelcome({ cwd, locale: prefs.locale, mode: "ask" });
|
|
364
|
+
printWelcome({ cwd, locale: prefs.locale, mode: "ask", model: providerLabel });
|
|
290
365
|
await runRepl({
|
|
291
366
|
agent: null,
|
|
292
367
|
cwd,
|
|
293
368
|
locale: prefs.locale,
|
|
294
369
|
mode: "ask",
|
|
295
370
|
apiKey: opts.apiKey,
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
371
|
+
askOffline,
|
|
372
|
+
creds: sessionCreds,
|
|
373
|
+
offline: askOffline,
|
|
299
374
|
});
|
|
300
375
|
return;
|
|
301
376
|
}
|
|
302
|
-
|
|
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
|
+
}
|
|
397
|
+
let agent = null;
|
|
303
398
|
let resumed = false;
|
|
399
|
+
const creds = sessionCreds;
|
|
304
400
|
try {
|
|
305
|
-
|
|
401
|
+
if (usesCursorSdk(creds)) {
|
|
402
|
+
({ agent, resumed } = await createOrResumeAgent({ ...opts, task: "", mode }, prefs.locale));
|
|
403
|
+
}
|
|
306
404
|
}
|
|
307
405
|
catch (err) {
|
|
308
|
-
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") {
|
|
309
412
|
fail(`Agent startup failed: ${err.message}`);
|
|
310
413
|
process.exitCode = 1;
|
|
311
414
|
return;
|
|
312
415
|
}
|
|
313
|
-
|
|
416
|
+
fail(err instanceof Error ? err.message : String(err));
|
|
417
|
+
process.exitCode = 1;
|
|
418
|
+
return;
|
|
314
419
|
}
|
|
315
420
|
printWelcome({
|
|
316
421
|
cwd,
|
|
317
|
-
model:
|
|
422
|
+
model: providerModelLabel(creds),
|
|
318
423
|
locale: prefs.locale,
|
|
319
424
|
mode,
|
|
320
425
|
resumed,
|
|
321
|
-
agentId: agent
|
|
426
|
+
agentId: agent?.agentId,
|
|
322
427
|
});
|
|
323
|
-
|
|
428
|
+
if (agent)
|
|
429
|
+
await persistAgent(cwd, agent, creds);
|
|
324
430
|
savePreferences(cwd, { mode });
|
|
325
431
|
try {
|
|
326
432
|
await runRepl({
|
|
@@ -329,21 +435,47 @@ export async function runInteractiveAgent(opts) {
|
|
|
329
435
|
locale: prefs.locale,
|
|
330
436
|
mode,
|
|
331
437
|
apiKey: opts.apiKey,
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
438
|
+
askOffline,
|
|
439
|
+
creds,
|
|
440
|
+
offline: false,
|
|
335
441
|
});
|
|
336
442
|
}
|
|
337
443
|
finally {
|
|
338
|
-
|
|
444
|
+
if (agent)
|
|
445
|
+
await disposeAgent(agent);
|
|
339
446
|
}
|
|
340
447
|
}
|
|
341
448
|
async function runRepl(opts) {
|
|
342
449
|
let currentLocale = opts.locale;
|
|
343
450
|
let currentMode = opts.mode;
|
|
344
451
|
let currentAgent = opts.agent;
|
|
452
|
+
let currentCreds = opts.creds;
|
|
453
|
+
let currentOffline = opts.offline;
|
|
345
454
|
let turn = 0;
|
|
346
455
|
const t = () => uiStrings(currentLocale);
|
|
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
|
+
}
|
|
471
|
+
try {
|
|
472
|
+
currentCreds = resolveAgentCredentials(opts.apiKey, currentLocale);
|
|
473
|
+
return currentCreds;
|
|
474
|
+
}
|
|
475
|
+
catch {
|
|
476
|
+
return currentCreds;
|
|
477
|
+
}
|
|
478
|
+
};
|
|
347
479
|
while (true) {
|
|
348
480
|
const line = (await askWithPlaceholder({
|
|
349
481
|
prompt: formatInputPrompt(),
|
|
@@ -351,6 +483,15 @@ async function runRepl(opts) {
|
|
|
351
483
|
})).trim();
|
|
352
484
|
if (!line || line === "exit" || line === "quit" || line === "sair" || line === "退出")
|
|
353
485
|
break;
|
|
486
|
+
if (isProvidersMetaCommand(line.trim().split(/\s+/)[0] ?? "")) {
|
|
487
|
+
await runProvidersInteractive(currentLocale);
|
|
488
|
+
const live = resolveActiveCredentials();
|
|
489
|
+
if (live) {
|
|
490
|
+
currentOffline = false;
|
|
491
|
+
currentCreds = live;
|
|
492
|
+
}
|
|
493
|
+
continue;
|
|
494
|
+
}
|
|
354
495
|
const meta = handleMetaCommand(line, currentLocale, opts.cwd, currentMode);
|
|
355
496
|
if (meta?.kind === "handled")
|
|
356
497
|
continue;
|
|
@@ -369,7 +510,14 @@ async function runRepl(opts) {
|
|
|
369
510
|
}
|
|
370
511
|
}
|
|
371
512
|
else {
|
|
372
|
-
|
|
513
|
+
const creds = resolveCreds();
|
|
514
|
+
if (creds && usesCursorSdk(creds)) {
|
|
515
|
+
currentAgent = await recreateAgentForMode(opts.cwd, currentAgent, currentMode, opts.apiKey, currentLocale);
|
|
516
|
+
}
|
|
517
|
+
else if (currentAgent) {
|
|
518
|
+
await disposeAgent(currentAgent);
|
|
519
|
+
currentAgent = null;
|
|
520
|
+
}
|
|
373
521
|
}
|
|
374
522
|
}
|
|
375
523
|
catch (err) {
|
|
@@ -378,8 +526,13 @@ async function runRepl(opts) {
|
|
|
378
526
|
continue;
|
|
379
527
|
}
|
|
380
528
|
if (meta?.kind === "resume") {
|
|
381
|
-
|
|
382
|
-
|
|
529
|
+
const resumeCreds = resolveCreds();
|
|
530
|
+
if (currentMode === "ask" || !resumeCreds || !usesCursorSdk(resumeCreds)) {
|
|
531
|
+
warn(currentLocale === "pt"
|
|
532
|
+
? "Sessões guardadas só com provider Cursor."
|
|
533
|
+
: currentLocale === "zh"
|
|
534
|
+
? "保存的会话仅适用于 Cursor。"
|
|
535
|
+
: "Saved sessions are Cursor-only.");
|
|
383
536
|
continue;
|
|
384
537
|
}
|
|
385
538
|
try {
|
|
@@ -387,7 +540,7 @@ async function runRepl(opts) {
|
|
|
387
540
|
fail(currentLocale === "pt" ? "Sem agente activo." : "No active agent.");
|
|
388
541
|
continue;
|
|
389
542
|
}
|
|
390
|
-
currentAgent = await resumeAgentInRepl(opts.cwd, currentAgent, meta.agentId, currentLocale);
|
|
543
|
+
currentAgent = await resumeAgentInRepl(opts.cwd, currentAgent, meta.agentId, currentLocale, opts.apiKey);
|
|
391
544
|
}
|
|
392
545
|
catch (err) {
|
|
393
546
|
fail(err instanceof Error ? err.message : String(err));
|
|
@@ -395,8 +548,13 @@ async function runRepl(opts) {
|
|
|
395
548
|
continue;
|
|
396
549
|
}
|
|
397
550
|
if (meta?.kind === "save") {
|
|
398
|
-
|
|
399
|
-
|
|
551
|
+
const saveCreds = resolveCreds();
|
|
552
|
+
if (!currentAgent || !saveCreds || !usesCursorSdk(saveCreds)) {
|
|
553
|
+
warn(currentLocale === "pt"
|
|
554
|
+
? "Guardar sessão só com provider Cursor."
|
|
555
|
+
: currentLocale === "zh"
|
|
556
|
+
? "保存会话仅适用于 Cursor。"
|
|
557
|
+
: "Save session is Cursor-only.");
|
|
400
558
|
continue;
|
|
401
559
|
}
|
|
402
560
|
const model = resolveComposerModel();
|
|
@@ -415,35 +573,38 @@ async function runRepl(opts) {
|
|
|
415
573
|
await executeAskTurn({
|
|
416
574
|
cwd: opts.cwd,
|
|
417
575
|
question: line,
|
|
418
|
-
|
|
419
|
-
apiUrl: opts.askApiUrl,
|
|
420
|
-
offline: opts.askOffline,
|
|
576
|
+
offline: currentOffline || Boolean(opts.askOffline),
|
|
421
577
|
quiet: true,
|
|
578
|
+
locale: currentLocale,
|
|
422
579
|
});
|
|
423
580
|
console.log("\n");
|
|
424
581
|
turn++;
|
|
425
582
|
continue;
|
|
426
583
|
}
|
|
427
|
-
if (!
|
|
428
|
-
|
|
584
|
+
if (currentOffline || !resolveCreds()) {
|
|
585
|
+
warn(offlineAgentHint(currentLocale));
|
|
586
|
+
turn++;
|
|
429
587
|
continue;
|
|
430
588
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
await streamRun(currentAgent, prompt, currentLocale);
|
|
436
|
-
}
|
|
437
|
-
catch (err) {
|
|
438
|
-
if (err instanceof CursorAgentError) {
|
|
439
|
-
fail(err.message);
|
|
440
|
-
turn++;
|
|
441
|
-
continue;
|
|
442
|
-
}
|
|
443
|
-
throw err;
|
|
589
|
+
const creds = currentCreds;
|
|
590
|
+
if (usesCursorSdk(creds) && !currentAgent) {
|
|
591
|
+
fail(currentLocale === "pt" ? "Sem agente Cursor activo." : "No active Cursor agent.");
|
|
592
|
+
continue;
|
|
444
593
|
}
|
|
445
|
-
|
|
446
|
-
|
|
594
|
+
if (currentAgent)
|
|
595
|
+
await persistAgent(opts.cwd, currentAgent, creds);
|
|
596
|
+
const outcome = await runAgentTurn({
|
|
597
|
+
cwd: opts.cwd,
|
|
598
|
+
task: line,
|
|
599
|
+
creds,
|
|
600
|
+
locale: currentLocale,
|
|
601
|
+
mode: currentMode,
|
|
602
|
+
cursorAgent: currentAgent,
|
|
603
|
+
});
|
|
604
|
+
if (outcome.cursorAgent)
|
|
605
|
+
currentAgent = outcome.cursorAgent;
|
|
606
|
+
if (currentAgent)
|
|
607
|
+
await persistAgent(opts.cwd, currentAgent, creds);
|
|
447
608
|
turn++;
|
|
448
609
|
}
|
|
449
610
|
ok(t().goodbye);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/commands/providers.ts"],"names":[],"mappings":"AAGA,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,iBAGlE"}
|
|
@@ -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"}
|