@kurtel/cli 0.1.5 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/run.js +7 -2
- package/dist/session/repl.js +92 -19
- package/package.json +1 -1
package/dist/commands/run.js
CHANGED
|
@@ -5,12 +5,12 @@ export async function runCommand(task, opts) {
|
|
|
5
5
|
if (!task || task.trim() === "") {
|
|
6
6
|
console.log(`${c.red(symbols.cross)} Provide a task, e.g. ${c.indigo('kurtel run "fix the flaky auth test"')}`);
|
|
7
7
|
process.exitCode = 1;
|
|
8
|
-
return;
|
|
8
|
+
return undefined;
|
|
9
9
|
}
|
|
10
10
|
if (opts.engine && !isEngineName(opts.engine)) {
|
|
11
11
|
console.log(`${c.red(symbols.cross)} Unknown engine ${c.white(opts.engine)}. Use ${c.indigo("claude-code")} or ${c.indigo("codex")}.`);
|
|
12
12
|
process.exitCode = 1;
|
|
13
|
-
return;
|
|
13
|
+
return undefined;
|
|
14
14
|
}
|
|
15
15
|
try {
|
|
16
16
|
const run = await createRun({
|
|
@@ -18,16 +18,20 @@ export async function runCommand(task, opts) {
|
|
|
18
18
|
repo: opts.repo,
|
|
19
19
|
branch: opts.branch,
|
|
20
20
|
engine: opts.engine,
|
|
21
|
+
model: opts.model,
|
|
21
22
|
});
|
|
22
23
|
console.log("");
|
|
23
24
|
console.log(`${symbols.check} Launched ${c.indigo(run.id)}`);
|
|
24
25
|
console.log(`${c.gray("task")} ${c.white(run.task)}`);
|
|
25
26
|
console.log(`${c.gray("engine")} ${c.white(run.engine)}`);
|
|
27
|
+
if (run.model)
|
|
28
|
+
console.log(`${c.gray("model")} ${c.white(run.model)}`);
|
|
26
29
|
if (run.repo)
|
|
27
30
|
console.log(`${c.gray("repo")} ${c.white(run.repo)}`);
|
|
28
31
|
console.log(`${c.gray("status")} ${c.indigo(run.status)}`);
|
|
29
32
|
console.log("");
|
|
30
33
|
console.log(`${c.dim("Follow it with")} ${c.indigo(`kurtel logs ${run.id} --follow`)}`);
|
|
34
|
+
return run.id;
|
|
31
35
|
}
|
|
32
36
|
catch (e) {
|
|
33
37
|
if (e instanceof AuthError) {
|
|
@@ -37,5 +41,6 @@ export async function runCommand(task, opts) {
|
|
|
37
41
|
console.log(`${c.red(symbols.cross)} Failed to launch: ${e instanceof Error ? e.message : String(e)}`);
|
|
38
42
|
}
|
|
39
43
|
process.exitCode = 1;
|
|
44
|
+
return undefined;
|
|
40
45
|
}
|
|
41
46
|
}
|
package/dist/session/repl.js
CHANGED
|
@@ -1,21 +1,29 @@
|
|
|
1
1
|
import * as readline from "node:readline";
|
|
2
2
|
import { c, symbols } from "../ui/colors.js";
|
|
3
3
|
import { banner, welcomeBox } from "../ui/banner.js";
|
|
4
|
-
import { Spinner, sleep } from "../ui/spinner.js";
|
|
5
4
|
import { loadConfig } from "../lib/config.js";
|
|
6
5
|
import { agentsCommand } from "../commands/agents.js";
|
|
7
6
|
import { loginCommand } from "../commands/auth.js";
|
|
8
7
|
import { configCommand } from "../commands/config.js";
|
|
9
|
-
import {
|
|
8
|
+
import { runCommand } from "../commands/run.js";
|
|
9
|
+
import { runsCommand } from "../commands/runs.js";
|
|
10
|
+
import { logsCommand, statusCommand, stopCommand } from "../commands/runtime.js";
|
|
10
11
|
const SLASH_COMMANDS = [
|
|
11
12
|
["/help", "Show this help"],
|
|
12
13
|
["/run <task>", "Launch a cloud agent on a task"],
|
|
14
|
+
["/runs", "List your recent runs"],
|
|
15
|
+
["/logs [id]", "Stream a run's logs (defaults to the last one)"],
|
|
16
|
+
["/status [id]", "Show a run's status & result"],
|
|
17
|
+
["/stop [id]", "Cancel a run and tear down its sandbox"],
|
|
13
18
|
["/agents", "List active agents"],
|
|
14
19
|
["/login", "Sign in to Kurtel"],
|
|
15
20
|
["/config", "Show local configuration"],
|
|
16
21
|
["/clear", "Clear the screen"],
|
|
17
22
|
["/exit", "Quit the session"],
|
|
18
23
|
];
|
|
24
|
+
// Remember the most recently launched run so `/logs` and `/status` can default
|
|
25
|
+
// to it without making the user paste an id.
|
|
26
|
+
let lastRunId = null;
|
|
19
27
|
function prompt() {
|
|
20
28
|
return `${c.indigo("kurtel")} ${c.indigo(symbols.arrow)} `;
|
|
21
29
|
}
|
|
@@ -29,14 +37,51 @@ function printHelp() {
|
|
|
29
37
|
console.log(c.dim("Anything else you type is treated as a task and launches an agent."));
|
|
30
38
|
console.log("");
|
|
31
39
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
let asking = false;
|
|
41
|
+
function ask(rl, query) {
|
|
42
|
+
return new Promise((resolve) => {
|
|
43
|
+
rl.question(query, (answer) => resolve(answer.trim()));
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
async function launchFromPrompt(rl, task) {
|
|
47
|
+
const cfg = loadConfig();
|
|
48
|
+
const defBranch = cfg.defaultBranch || "main";
|
|
49
|
+
const defEngine = cfg.engine || "claude-code";
|
|
50
|
+
let repo = "";
|
|
51
|
+
let branch = defBranch;
|
|
52
|
+
let engine = defEngine;
|
|
53
|
+
let model = "";
|
|
54
|
+
asking = true;
|
|
55
|
+
try {
|
|
56
|
+
console.log("");
|
|
57
|
+
repo = await ask(rl, ` ${c.gray("repo")} ${c.dim("(owner/name, empty for none)")} ${c.indigo(symbols.arrow)} `);
|
|
58
|
+
branch =
|
|
59
|
+
(await ask(rl, ` ${c.gray("branch")} ${c.dim(`(default ${defBranch})`)} ${c.indigo(symbols.arrow)} `)) || defBranch;
|
|
60
|
+
engine =
|
|
61
|
+
(await ask(rl, ` ${c.gray("engine")} ${c.dim(`(default ${defEngine})`)} ${c.indigo(symbols.arrow)} `)) || defEngine;
|
|
62
|
+
model = await ask(rl, ` ${c.gray("model")} ${c.dim("(optional)")} ${c.indigo(symbols.arrow)} `);
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
asking = false;
|
|
66
|
+
}
|
|
67
|
+
const id = await runCommand(task, {
|
|
68
|
+
repo: repo || undefined,
|
|
69
|
+
branch,
|
|
70
|
+
engine,
|
|
71
|
+
model: model || undefined,
|
|
72
|
+
});
|
|
73
|
+
if (id) {
|
|
74
|
+
lastRunId = id;
|
|
75
|
+
console.log(`${c.dim("In here:")} ${c.indigo("/logs")} ${c.dim("to watch ·")} ${c.indigo("/runs")} ${c.dim("to list")}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function resolveId(arg) {
|
|
79
|
+
if (arg)
|
|
80
|
+
return arg;
|
|
81
|
+
if (lastRunId)
|
|
82
|
+
return lastRunId;
|
|
83
|
+
console.log(`${c.red(symbols.cross)} No run id given and no recent run. Try ${c.indigo("/runs")}.`);
|
|
84
|
+
return null;
|
|
40
85
|
}
|
|
41
86
|
export async function startSession(model) {
|
|
42
87
|
console.log(banner());
|
|
@@ -53,6 +98,8 @@ export async function startSession(model) {
|
|
|
53
98
|
});
|
|
54
99
|
rl.prompt();
|
|
55
100
|
rl.on("line", async (input) => {
|
|
101
|
+
if (asking)
|
|
102
|
+
return;
|
|
56
103
|
const line = input.trim();
|
|
57
104
|
if (line === "") {
|
|
58
105
|
rl.prompt();
|
|
@@ -75,6 +122,39 @@ export async function startSession(model) {
|
|
|
75
122
|
console.clear();
|
|
76
123
|
console.log(banner());
|
|
77
124
|
break;
|
|
125
|
+
case "runs":
|
|
126
|
+
case "ls":
|
|
127
|
+
rl.pause();
|
|
128
|
+
await runsCommand();
|
|
129
|
+
rl.resume();
|
|
130
|
+
break;
|
|
131
|
+
case "logs": {
|
|
132
|
+
const id = resolveId(arg);
|
|
133
|
+
if (id) {
|
|
134
|
+
rl.pause();
|
|
135
|
+
await logsCommand(id, { follow: true });
|
|
136
|
+
rl.resume();
|
|
137
|
+
}
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
case "status": {
|
|
141
|
+
const id = resolveId(arg);
|
|
142
|
+
if (id) {
|
|
143
|
+
rl.pause();
|
|
144
|
+
await statusCommand(id);
|
|
145
|
+
rl.resume();
|
|
146
|
+
}
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
case "stop": {
|
|
150
|
+
const id = resolveId(arg);
|
|
151
|
+
if (id) {
|
|
152
|
+
rl.pause();
|
|
153
|
+
await stopCommand(id);
|
|
154
|
+
rl.resume();
|
|
155
|
+
}
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
78
158
|
case "agents":
|
|
79
159
|
case "ps":
|
|
80
160
|
rl.pause();
|
|
@@ -92,14 +172,12 @@ export async function startSession(model) {
|
|
|
92
172
|
rl.resume();
|
|
93
173
|
break;
|
|
94
174
|
case "run":
|
|
95
|
-
rl.pause();
|
|
96
175
|
if (!arg) {
|
|
97
176
|
console.log(`${c.red(symbols.cross)} Usage: ${c.indigo("/run <task>")}`);
|
|
98
177
|
}
|
|
99
178
|
else {
|
|
100
|
-
await launchFromPrompt(arg);
|
|
179
|
+
await launchFromPrompt(rl, arg);
|
|
101
180
|
}
|
|
102
|
-
rl.resume();
|
|
103
181
|
break;
|
|
104
182
|
default:
|
|
105
183
|
console.log(`${c.red(symbols.cross)} Unknown command ${c.white("/" + cmd)}. Type ${c.indigo("/help")}.`);
|
|
@@ -107,21 +185,16 @@ export async function startSession(model) {
|
|
|
107
185
|
rl.prompt();
|
|
108
186
|
return;
|
|
109
187
|
}
|
|
110
|
-
|
|
111
|
-
rl.pause();
|
|
112
|
-
await launchFromPrompt(line);
|
|
113
|
-
rl.resume();
|
|
188
|
+
await launchFromPrompt(rl, line);
|
|
114
189
|
rl.prompt();
|
|
115
190
|
});
|
|
116
191
|
rl.on("close", () => {
|
|
117
192
|
console.log(`\n${c.dim("See you soon. ")}${c.indigo("›")}\n`);
|
|
118
193
|
process.exit(0);
|
|
119
194
|
});
|
|
120
|
-
// Ctrl+C: confirm-style behavior — first clears line, prompt again.
|
|
121
195
|
rl.on("SIGINT", () => {
|
|
122
196
|
console.log(`\n${c.dim("(use /exit or Ctrl+D to quit)")}`);
|
|
123
197
|
rl.prompt();
|
|
124
198
|
});
|
|
125
|
-
// Touch config so a fresh user has it.
|
|
126
199
|
loadConfig();
|
|
127
200
|
}
|