@datalabrotterdam/nova-ai-cli 1.2.0-alpha.16 → 1.2.0-alpha.17
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/CHANGELOG.md +7 -0
- package/README.md +7 -8
- package/dist/index.js +1 -1
- package/dist/{tui-UHITDRFM.js → tui-VP2V5DOF.js} +63 -26
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [@datalabrotterdam/nova-ai-cli-v1.2.0-alpha.17](https://github.com/Datalab-Rotterdam/nova-ai-cli/compare/@datalabrotterdam/nova-ai-cli@1.2.0-alpha.16...@datalabrotterdam/nova-ai-cli@1.2.0-alpha.17) (2026-10-25)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **cli:** /tasks to monitor and stop background tasks; drop Ctrl+B ([aaa3cb9](https://github.com/Datalab-Rotterdam/nova-ai-cli/commit/aaa3cb9dc058ab9a726964414a959084c9237669))
|
|
7
|
+
|
|
1
8
|
# [@datalabrotterdam/nova-ai-cli-v1.2.0-alpha.16](https://github.com/Datalab-Rotterdam/nova-ai-cli/compare/@datalabrotterdam/nova-ai-cli@1.2.0-alpha.15...@datalabrotterdam/nova-ai-cli@1.2.0-alpha.16) (2026-10-25)
|
|
2
9
|
|
|
3
10
|
|
package/README.md
CHANGED
|
@@ -75,9 +75,9 @@ The UI runs full screen (the terminal's alternate screen, like `less` or
|
|
|
75
75
|
`vim`) and gives your shell its screen back on exit. The mouse wheel or
|
|
76
76
|
PgUp/PgDn scroll the transcript, Esc jumps back to the newest output, and
|
|
77
77
|
while you read an answer the prompt that asked for it stays pinned on the top
|
|
78
|
-
row.
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
row. Drag over text to select it, then click (or press Enter) to copy it;
|
|
79
|
+
Shift+arrows extend the selection and Esc cancels. `/copy` copies the last
|
|
80
|
+
answer.
|
|
81
81
|
|
|
82
82
|
- **Modes** (Shift+Tab): `agent` does the work; `plan` reads the code, asks
|
|
83
83
|
questions and builds a task list but changes nothing; `ask` only answers;
|
|
@@ -99,17 +99,16 @@ again gives the wheel back). `/copy` copies the last answer.
|
|
|
99
99
|
| Key | Action |
|
|
100
100
|
|---|---|
|
|
101
101
|
| Enter / Shift+Enter | Send / new line (Shift+Enter where the terminal supports the kitty keyboard protocol: VS Code, kitty, WezTerm, Ghostty, foot, Alacritty, recent iTerm2; Alt+Enter, Ctrl+J or a trailing `\` work everywhere) |
|
|
102
|
-
| Esc |
|
|
103
|
-
| Ctrl+C
|
|
102
|
+
| Esc | Interrupt the running turn (asks whether running background tasks keep going) |
|
|
103
|
+
| Ctrl+C | Clear the prompt; on an empty prompt, twice to exit (prints `nova-ai --resume <id>`) |
|
|
104
104
|
| Shift+Tab | Cycle agent / ask / plan / autopilot and your own agents |
|
|
105
105
|
| Ctrl+R / Ctrl+P / Ctrl+K | Sessions / models / permission mode |
|
|
106
|
-
| Ctrl+O / Ctrl+T
|
|
107
|
-
| Ctrl+S | Select mode: the mouse selects text instead of scrolling (again to switch back) |
|
|
106
|
+
| Ctrl+O / Ctrl+T | Thinking and verbose tool output / tool inspector |
|
|
108
107
|
| Alt+V | Paste a clipboard image |
|
|
109
108
|
|
|
110
109
|
Slash commands: `/help`, `/model`, `/effort` (thinking models), `/mode`, `/permission`, `/session`,
|
|
111
110
|
`/resume`, `/clear`, `/compact`, `/copy`, `/rewind [n]`, `/queue`, `/steer`, `/usage` (context, and the session's tokens and estimated cost; the status line shows `≈ €0.0123` once a priced model answered),
|
|
112
|
-
`/tools`, `/mcp`, `/skills`, `/shell` and `/agent` (background jobs), `/trust`
|
|
111
|
+
`/tools`, `/tasks` (watch or stop background shells and agents), `/mcp`, `/skills`, `/shell` and `/agent` (background jobs), `/trust`
|
|
113
112
|
and `/exit`. Your own commands are markdown files in `~/.nova-ai/commands/` or
|
|
114
113
|
the repository's `.nova-ai/commands/` (Claude Code's format, so
|
|
115
114
|
`.claude/commands` works too): the file is the prompt, `$ARGUMENTS` what you
|
package/dist/index.js
CHANGED
|
@@ -2175,6 +2175,13 @@ var builtinCommands = [
|
|
|
2175
2175
|
ctx.openToolInspector();
|
|
2176
2176
|
}
|
|
2177
2177
|
},
|
|
2178
|
+
{
|
|
2179
|
+
name: "tasks",
|
|
2180
|
+
description: "Monitor background shells and agents, and stop one",
|
|
2181
|
+
run(ctx) {
|
|
2182
|
+
return ctx.openTasks();
|
|
2183
|
+
}
|
|
2184
|
+
},
|
|
2178
2185
|
{
|
|
2179
2186
|
name: "mcp",
|
|
2180
2187
|
description: "Inspect MCP servers, or sign in to one: /mcp login|logout <server>",
|
|
@@ -4212,9 +4219,6 @@ var TuiController = class {
|
|
|
4212
4219
|
case "k":
|
|
4213
4220
|
this.openPermissionModes();
|
|
4214
4221
|
return true;
|
|
4215
|
-
case "b":
|
|
4216
|
-
void this.openBackgroundTasks();
|
|
4217
|
-
return true;
|
|
4218
4222
|
case "o":
|
|
4219
4223
|
this.toggleToolDetails();
|
|
4220
4224
|
return true;
|
|
@@ -4400,36 +4404,65 @@ var TuiController = class {
|
|
|
4400
4404
|
}
|
|
4401
4405
|
);
|
|
4402
4406
|
}
|
|
4403
|
-
|
|
4407
|
+
/** /tasks: background shells and agents; pick one to read its output or stop it. */
|
|
4408
|
+
openTasks = async () => {
|
|
4409
|
+
let jobs;
|
|
4404
4410
|
try {
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4411
|
+
jobs = await this.runner.listBackgroundJobs();
|
|
4412
|
+
} catch (error) {
|
|
4413
|
+
this.showText("Background tasks", errorMessage(error, "Failed to list background tasks."));
|
|
4414
|
+
return;
|
|
4415
|
+
}
|
|
4416
|
+
if (jobs.length === 0) {
|
|
4417
|
+
this.showText("Background tasks", "No background shells or agents in this session.");
|
|
4418
|
+
return;
|
|
4419
|
+
}
|
|
4420
|
+
this.showSelection(
|
|
4421
|
+
"Background tasks",
|
|
4422
|
+
jobs.map((job) => ({ value: job.jobId, label: taskLabel(job), description: job.status })),
|
|
4423
|
+
"background-tasks",
|
|
4424
|
+
(jobId) => {
|
|
4425
|
+
const job = jobs.find((candidate) => candidate.jobId === jobId);
|
|
4426
|
+
if (job.status !== "running") {
|
|
4427
|
+
void this.showTaskOutput(jobId);
|
|
4428
|
+
return;
|
|
4429
|
+
}
|
|
4430
|
+
this.showSelection(
|
|
4431
|
+
taskLabel(job),
|
|
4432
|
+
[
|
|
4433
|
+
{ value: "output", label: "View output", description: "What it printed so far" },
|
|
4434
|
+
{ value: "stop", label: "Stop", description: "Kill this task" }
|
|
4435
|
+
],
|
|
4436
|
+
"background-tasks",
|
|
4437
|
+
(action) => void (action === "stop" ? this.stopTask(job) : this.showTaskOutput(jobId))
|
|
4438
|
+
);
|
|
4439
|
+
}
|
|
4440
|
+
);
|
|
4441
|
+
};
|
|
4442
|
+
async showTaskOutput(jobId) {
|
|
4443
|
+
try {
|
|
4444
|
+
const result = await this.runner.backgroundOutput(jobId);
|
|
4445
|
+
this.showText(
|
|
4446
|
+
taskLabel(result.job),
|
|
4447
|
+
`status: ${result.job.status}
|
|
4420
4448
|
outputPath: ${result.outputPath ?? result.job.outputPath ?? ""}
|
|
4421
4449
|
|
|
4422
4450
|
${result.output}${result.truncated ? "\n\n[output truncated]" : ""}`
|
|
4423
|
-
)
|
|
4424
|
-
).catch(
|
|
4425
|
-
(error) => this.showText("Background job", errorMessage(error, "Failed to read output."))
|
|
4426
|
-
);
|
|
4427
|
-
}
|
|
4428
4451
|
);
|
|
4429
4452
|
} catch (error) {
|
|
4430
|
-
this.showText("Background
|
|
4453
|
+
this.showText("Background task", errorMessage(error, "Failed to read output."));
|
|
4431
4454
|
}
|
|
4432
|
-
}
|
|
4455
|
+
}
|
|
4456
|
+
/** Stops one task, then shows the list again. */
|
|
4457
|
+
async stopTask(job) {
|
|
4458
|
+
try {
|
|
4459
|
+
await this.runner.killBackgroundJob(job.jobId);
|
|
4460
|
+
this.store.setState({ statusLine: `Stopped ${taskLabel(job)}.` });
|
|
4461
|
+
} catch (error) {
|
|
4462
|
+
this.store.setState({ statusLine: errorMessage(error, `Failed to stop ${taskLabel(job)}.`) });
|
|
4463
|
+
}
|
|
4464
|
+
await this.openTasks();
|
|
4465
|
+
}
|
|
4433
4466
|
openToolInspector = () => {
|
|
4434
4467
|
if (this.toolCalls().length === 0) {
|
|
4435
4468
|
this.showText("Tool calls", "No tool calls yet.");
|
|
@@ -4685,6 +4718,7 @@ ${skill.path}`
|
|
|
4685
4718
|
return "Workspace trusted: its allow rules apply now; MCP servers it declares start with the next session (/clear).";
|
|
4686
4719
|
},
|
|
4687
4720
|
openToolInspector: this.openToolInspector,
|
|
4721
|
+
openTasks: this.openTasks,
|
|
4688
4722
|
openMcpInspector: this.openMcpInspector,
|
|
4689
4723
|
openSkillInspector: this.openSkillInspector,
|
|
4690
4724
|
switchSkill: this.switchSkill,
|
|
@@ -4892,6 +4926,9 @@ function mcpCounts(runner) {
|
|
|
4892
4926
|
function errorMessage(error, fallback) {
|
|
4893
4927
|
return error instanceof Error ? error.message : fallback;
|
|
4894
4928
|
}
|
|
4929
|
+
function taskLabel(job) {
|
|
4930
|
+
return `${job.kind === "terminal" ? "shell" : "agent"}: ${job.title}`;
|
|
4931
|
+
}
|
|
4895
4932
|
|
|
4896
4933
|
// src/tui/ink/dialogs/views.tsx
|
|
4897
4934
|
import { Box as Box5, Text as Text5, useInput as useInput2, usePaste as usePaste2 } from "ink";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datalabrotterdam/nova-ai-cli",
|
|
3
|
-
"version": "1.2.0-alpha.
|
|
3
|
+
"version": "1.2.0-alpha.17",
|
|
4
4
|
"description": "Agentic coding with DataLab Rotterdam's Nova AI in your terminal: interactive TUI, headless mode, and an ACP agent for editors",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "DataLab Rotterdam",
|