@qodalis/cli 2.0.0-beta.14 → 2.0.0-beta.16
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 +14 -0
- package/package.json +2 -2
- package/public-api.d.mts +1 -1
- package/public-api.d.ts +1 -1
- package/public-api.js +42 -47
- package/public-api.js.map +1 -1
- package/public-api.mjs +43 -48
- package/public-api.mjs.map +1 -1
- package/wasm/qodalis_cli_wasm_bg.wasm +0 -0
package/README.md
CHANGED
|
@@ -288,6 +288,7 @@ All three implement the same API surface:
|
|
|
288
288
|
| `/ws/v1/cli/events` | WS | Server-push event streaming |
|
|
289
289
|
| `/ws/v1/cli/shell` | WS | Interactive PTY shell session |
|
|
290
290
|
| `/api/cli/fs/*` | Various | Filesystem operations (ls, cat, upload, download, mkdir, rm) |
|
|
291
|
+
| `/api/qcli/mcp` | POST | MCP endpoint for AI clients (opt-in) |
|
|
291
292
|
|
|
292
293
|
### Connecting to a Server
|
|
293
294
|
|
|
@@ -320,6 +321,19 @@ The frontend includes built-in resilience features:
|
|
|
320
321
|
- **HTTP retry** on transient fetch failures (1 retry with 1s delay)
|
|
321
322
|
- **Configurable request timeout** per server (default 30s)
|
|
322
323
|
|
|
324
|
+
### MCP
|
|
325
|
+
|
|
326
|
+
Each server can expose the whole system to AI clients such as Claude Code over the [Model Context Protocol](https://modelcontextprotocol.io) at `POST /api/qcli/mcp` (opt-in): CLI commands, the filesystem API, the data explorer, jobs and plugin-contributed tools, each with the caller's permissions. It works with or without the users plugin, whose `token create` command issues the API tokens MCP clients sign in with:
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
# direct HTTP
|
|
330
|
+
claude mcp add --transport http qcli http://localhost:8047/api/qcli/mcp --header "Authorization: Bearer <token>"
|
|
331
|
+
# or the local stdio proxy @qodalis/mcp-cli (token or user/password, read-only mode, tool filters)
|
|
332
|
+
claude mcp add qcli -e QCLI_URL=http://localhost:8047 -e QCLI_TOKEN=<token> -- npx -y @qodalis/mcp-cli
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
See [MCP endpoint](https://cli.qodalis.com/docs/server-integration#mcp-endpoint) for enabling it, the tools and permissions, and client setup.
|
|
336
|
+
|
|
323
337
|
### Server Plugins
|
|
324
338
|
|
|
325
339
|
| Plugin | Servers | Description |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qodalis/cli",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.16",
|
|
4
4
|
"description": "Framework-agnostic CLI engine for @qodalis terminal applications.",
|
|
5
5
|
"author": "Nicolae Lupei, Qodalis Solutions",
|
|
6
6
|
"license": "MIT",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"./assets/*": "./assets/*"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@qodalis/cli-core": "2.0.0-beta.
|
|
33
|
+
"@qodalis/cli-core": "2.0.0-beta.16",
|
|
34
34
|
"@xterm/xterm": "^5.5.0",
|
|
35
35
|
"@xterm/addon-fit": "^0.10.0",
|
|
36
36
|
"@xterm/addon-web-links": "^0.11.0",
|
package/public-api.d.mts
CHANGED
|
@@ -153,7 +153,7 @@ declare const CliKeyValueStore_TOKEN = "cli-key-value-store";
|
|
|
153
153
|
*/
|
|
154
154
|
declare const SyntaxHighlighterRegistry_TOKEN = "syntax-highlighter-registry";
|
|
155
155
|
|
|
156
|
-
declare const LIBRARY_VERSION = "2.0.0-beta.
|
|
156
|
+
declare const LIBRARY_VERSION = "2.0.0-beta.16";
|
|
157
157
|
declare const API_VERSION = 2;
|
|
158
158
|
|
|
159
159
|
declare class CliAliasCommandProcessor implements ICliCommandProcessor {
|
package/public-api.d.ts
CHANGED
|
@@ -153,7 +153,7 @@ declare const CliKeyValueStore_TOKEN = "cli-key-value-store";
|
|
|
153
153
|
*/
|
|
154
154
|
declare const SyntaxHighlighterRegistry_TOKEN = "syntax-highlighter-registry";
|
|
155
155
|
|
|
156
|
-
declare const LIBRARY_VERSION = "2.0.0-beta.
|
|
156
|
+
declare const LIBRARY_VERSION = "2.0.0-beta.16";
|
|
157
157
|
declare const API_VERSION = 2;
|
|
158
158
|
|
|
159
159
|
declare class CliAliasCommandProcessor implements ICliCommandProcessor {
|
package/public-api.js
CHANGED
|
@@ -413,7 +413,7 @@ var CliKeyValueStore_TOKEN = "cli-key-value-store";
|
|
|
413
413
|
var SyntaxHighlighterRegistry_TOKEN = "syntax-highlighter-registry";
|
|
414
414
|
|
|
415
415
|
// src/lib/version.ts
|
|
416
|
-
var LIBRARY_VERSION = "2.0.0-beta.
|
|
416
|
+
var LIBRARY_VERSION = "2.0.0-beta.16";
|
|
417
417
|
var API_VERSION = 2;
|
|
418
418
|
var ANONYMOUS = "\0anonymous";
|
|
419
419
|
function aliasOwner(context2) {
|
|
@@ -12344,8 +12344,6 @@ var CliClipboard = class {
|
|
|
12344
12344
|
}
|
|
12345
12345
|
}
|
|
12346
12346
|
};
|
|
12347
|
-
|
|
12348
|
-
// src/lib/input/modes/input-mode-base.ts
|
|
12349
12347
|
var InputModeBase = class {
|
|
12350
12348
|
constructor(host, resolve) {
|
|
12351
12349
|
this.host = host;
|
|
@@ -12414,6 +12412,17 @@ var InputModeBase = class {
|
|
|
12414
12412
|
}
|
|
12415
12413
|
this.host.terminal.write(buf);
|
|
12416
12414
|
}
|
|
12415
|
+
/**
|
|
12416
|
+
* Cut a line to the terminal width. Lines redrawn in place must stay on one row:
|
|
12417
|
+
* a wrapped line takes two rows and breaks the cursor-up arithmetic of the redraw.
|
|
12418
|
+
*/
|
|
12419
|
+
fitLine(text) {
|
|
12420
|
+
return cliCore.truncateToWidth(text, Math.max(1, this.host.getTerminalCols() - 1));
|
|
12421
|
+
}
|
|
12422
|
+
/** Start a new row and write `text` cut to the terminal width. */
|
|
12423
|
+
writeRow(text) {
|
|
12424
|
+
this.host.terminal.write("\r\n" + this.fitLine(text));
|
|
12425
|
+
}
|
|
12417
12426
|
/**
|
|
12418
12427
|
* Render a dimmed help bar below the current line.
|
|
12419
12428
|
*/
|
|
@@ -12421,7 +12430,7 @@ var InputModeBase = class {
|
|
|
12421
12430
|
this.extraLines++;
|
|
12422
12431
|
this.host.terminal.write(
|
|
12423
12432
|
`\r
|
|
12424
|
-
\x1B[2m${text}\x1B[0m\x1B[${this.extraLines}A`
|
|
12433
|
+
${this.fitLine(` \x1B[2m${text}\x1B[0m`)}\x1B[${this.extraLines}A`
|
|
12425
12434
|
);
|
|
12426
12435
|
}
|
|
12427
12436
|
/**
|
|
@@ -12431,7 +12440,7 @@ var InputModeBase = class {
|
|
|
12431
12440
|
this.extraLines++;
|
|
12432
12441
|
this.host.terminal.write(
|
|
12433
12442
|
`\r
|
|
12434
|
-
\x1B[31m\u2718 ${message}\x1B[0m\x1B[${this.extraLines}A`
|
|
12443
|
+
${this.fitLine(` \x1B[31m\u2718 ${message}\x1B[0m`)}\x1B[${this.extraLines}A`
|
|
12435
12444
|
);
|
|
12436
12445
|
}
|
|
12437
12446
|
/**
|
|
@@ -12933,15 +12942,15 @@ var SelectInputMode = class extends InputModeBase {
|
|
|
12933
12942
|
if (this.selectOptions?.searchable) {
|
|
12934
12943
|
if (this.filter.length > 0) {
|
|
12935
12944
|
this.host.terminal.write(
|
|
12936
|
-
`\x1B[36m?\x1B[0m ${this.promptText}: ${this.filter}`
|
|
12945
|
+
this.fitLine(`\x1B[36m?\x1B[0m ${this.promptText}: ${this.filter}`)
|
|
12937
12946
|
);
|
|
12938
12947
|
} else {
|
|
12939
12948
|
this.host.terminal.write(
|
|
12940
|
-
`\x1B[36m?\x1B[0m ${this.promptText}: \x1B[2mType to filter...\x1B[0m`
|
|
12949
|
+
this.fitLine(`\x1B[36m?\x1B[0m ${this.promptText}: \x1B[2mType to filter...\x1B[0m`)
|
|
12941
12950
|
);
|
|
12942
12951
|
}
|
|
12943
12952
|
} else {
|
|
12944
|
-
this.host.terminal.write(`\x1B[36m?\x1B[0m ${this.promptText}:`);
|
|
12953
|
+
this.host.terminal.write(this.fitLine(`\x1B[36m?\x1B[0m ${this.promptText}:`));
|
|
12945
12954
|
}
|
|
12946
12955
|
}
|
|
12947
12956
|
/**
|
|
@@ -12956,17 +12965,15 @@ var SelectInputMode = class extends InputModeBase {
|
|
|
12956
12965
|
this.scrollOffset + this.maxVisible
|
|
12957
12966
|
);
|
|
12958
12967
|
if (visibleStart > 0) {
|
|
12959
|
-
this.
|
|
12960
|
-
\x1B[2m \u2191 ${visibleStart} more above\x1B[0m`);
|
|
12968
|
+
this.writeRow(`\x1B[2m \u2191 ${visibleStart} more above\x1B[0m`);
|
|
12961
12969
|
this.renderedLines++;
|
|
12962
12970
|
}
|
|
12963
12971
|
let selectableIdx = 0;
|
|
12964
12972
|
for (const item of items) {
|
|
12965
12973
|
if (item.type === "group-header") {
|
|
12966
12974
|
if (this.isGroupVisible(item.groupName, items, visibleStart, visibleEnd)) {
|
|
12967
|
-
this.
|
|
12968
|
-
`\
|
|
12969
|
-
\x1B[35m\u2500\u2500 ${item.groupName} \u2500\u2500\x1B[0m`
|
|
12975
|
+
this.writeRow(
|
|
12976
|
+
`\x1B[35m\u2500\u2500 ${item.groupName} \u2500\u2500\x1B[0m`
|
|
12970
12977
|
);
|
|
12971
12978
|
this.renderedLines++;
|
|
12972
12979
|
}
|
|
@@ -12989,8 +12996,7 @@ var SelectInputMode = class extends InputModeBase {
|
|
|
12989
12996
|
}
|
|
12990
12997
|
const remaining = selectables.length - visibleEnd;
|
|
12991
12998
|
if (remaining > 0) {
|
|
12992
|
-
this.
|
|
12993
|
-
\x1B[2m \u2193 ${remaining} more below\x1B[0m`);
|
|
12999
|
+
this.writeRow(`\x1B[2m \u2193 ${remaining} more below\x1B[0m`);
|
|
12994
13000
|
this.renderedLines++;
|
|
12995
13001
|
}
|
|
12996
13002
|
}
|
|
@@ -13032,19 +13038,16 @@ var SelectInputMode = class extends InputModeBase {
|
|
|
13032
13038
|
const label = this.highlightMatch(opt.label);
|
|
13033
13039
|
const desc = opt.description ? ` \x1B[2;3m\u2014 ${opt.description}\x1B[0m` : "";
|
|
13034
13040
|
if (opt.disabled) {
|
|
13035
|
-
this.
|
|
13036
|
-
|
|
13037
|
-
\x1B[2m${opt.label}${desc} (disabled)\x1B[0m`
|
|
13041
|
+
this.writeRow(
|
|
13042
|
+
` \x1B[2m${opt.label}${desc} (disabled)\x1B[0m`
|
|
13038
13043
|
);
|
|
13039
13044
|
} else if (isSelected) {
|
|
13040
|
-
this.
|
|
13041
|
-
|
|
13042
|
-
\x1B[48;5;24m\x1B[38;5;117m\u276F ${label}${desc}\x1B[0m`
|
|
13045
|
+
this.writeRow(
|
|
13046
|
+
` \x1B[48;5;24m\x1B[38;5;117m\u276F ${label}${desc}\x1B[0m`
|
|
13043
13047
|
);
|
|
13044
13048
|
} else {
|
|
13045
|
-
this.
|
|
13046
|
-
|
|
13047
|
-
${label}${desc}`
|
|
13049
|
+
this.writeRow(
|
|
13050
|
+
` ${label}${desc}`
|
|
13048
13051
|
);
|
|
13049
13052
|
}
|
|
13050
13053
|
}
|
|
@@ -13078,8 +13081,7 @@ var SelectInputMode = class extends InputModeBase {
|
|
|
13078
13081
|
} else {
|
|
13079
13082
|
help = "\u2191/\u2193 navigate \xB7 enter to select \xB7 esc to cancel";
|
|
13080
13083
|
}
|
|
13081
|
-
this.
|
|
13082
|
-
\x1B[2m${help}\x1B[0m`);
|
|
13084
|
+
this.writeRow(` \x1B[2m${help}\x1B[0m`);
|
|
13083
13085
|
this.renderedLines++;
|
|
13084
13086
|
}
|
|
13085
13087
|
};
|
|
@@ -13557,15 +13559,15 @@ var MultiSelectInputMode = class extends InputModeBase {
|
|
|
13557
13559
|
if (this.selectOptions?.searchable) {
|
|
13558
13560
|
if (this.filter.length > 0) {
|
|
13559
13561
|
this.host.terminal.write(
|
|
13560
|
-
`\x1B[36m?\x1B[0m ${this.promptText}: ${this.filter}`
|
|
13562
|
+
this.fitLine(`\x1B[36m?\x1B[0m ${this.promptText}: ${this.filter}`)
|
|
13561
13563
|
);
|
|
13562
13564
|
} else {
|
|
13563
13565
|
this.host.terminal.write(
|
|
13564
|
-
`\x1B[36m?\x1B[0m ${this.promptText}: \x1B[2mType to filter...\x1B[0m`
|
|
13566
|
+
this.fitLine(`\x1B[36m?\x1B[0m ${this.promptText}: \x1B[2mType to filter...\x1B[0m`)
|
|
13565
13567
|
);
|
|
13566
13568
|
}
|
|
13567
13569
|
} else {
|
|
13568
|
-
this.host.terminal.write(`\x1B[36m?\x1B[0m ${this.promptText}:`);
|
|
13570
|
+
this.host.terminal.write(this.fitLine(`\x1B[36m?\x1B[0m ${this.promptText}:`));
|
|
13569
13571
|
}
|
|
13570
13572
|
}
|
|
13571
13573
|
/**
|
|
@@ -13580,17 +13582,15 @@ var MultiSelectInputMode = class extends InputModeBase {
|
|
|
13580
13582
|
this.scrollOffset + this.maxVisible
|
|
13581
13583
|
);
|
|
13582
13584
|
if (visibleStart > 0) {
|
|
13583
|
-
this.
|
|
13584
|
-
\x1B[2m \u2191 ${visibleStart} more above\x1B[0m`);
|
|
13585
|
+
this.writeRow(`\x1B[2m \u2191 ${visibleStart} more above\x1B[0m`);
|
|
13585
13586
|
this.renderedLines++;
|
|
13586
13587
|
}
|
|
13587
13588
|
let selectableIdx = 0;
|
|
13588
13589
|
for (const item of items) {
|
|
13589
13590
|
if (item.type === "group-header") {
|
|
13590
13591
|
if (this.isGroupVisible(item.groupName, items, visibleStart, visibleEnd)) {
|
|
13591
|
-
this.
|
|
13592
|
-
`\
|
|
13593
|
-
\x1B[35m\u2500\u2500 ${item.groupName} \u2500\u2500\x1B[0m`
|
|
13592
|
+
this.writeRow(
|
|
13593
|
+
`\x1B[35m\u2500\u2500 ${item.groupName} \u2500\u2500\x1B[0m`
|
|
13594
13594
|
);
|
|
13595
13595
|
this.renderedLines++;
|
|
13596
13596
|
}
|
|
@@ -13613,8 +13613,7 @@ var MultiSelectInputMode = class extends InputModeBase {
|
|
|
13613
13613
|
}
|
|
13614
13614
|
const remaining = selectables.length - visibleEnd;
|
|
13615
13615
|
if (remaining > 0) {
|
|
13616
|
-
this.
|
|
13617
|
-
\x1B[2m \u2193 ${remaining} more below\x1B[0m`);
|
|
13616
|
+
this.writeRow(`\x1B[2m \u2193 ${remaining} more below\x1B[0m`);
|
|
13618
13617
|
this.renderedLines++;
|
|
13619
13618
|
}
|
|
13620
13619
|
}
|
|
@@ -13659,19 +13658,16 @@ var MultiSelectInputMode = class extends InputModeBase {
|
|
|
13659
13658
|
const checkbox = isChecked ? "\x1B[32m\u25C9\x1B[0m" : "\x1B[2m\u25CB\x1B[0m";
|
|
13660
13659
|
if (opt.disabled) {
|
|
13661
13660
|
const disabledCheckbox = isChecked ? "\x1B[2m\u25C9\x1B[0m" : "\x1B[2m\u25CB\x1B[0m";
|
|
13662
|
-
this.
|
|
13663
|
-
|
|
13664
|
-
${disabledCheckbox} \x1B[2m${opt.label}${desc} (disabled)\x1B[0m`
|
|
13661
|
+
this.writeRow(
|
|
13662
|
+
` ${disabledCheckbox} \x1B[2m${opt.label}${desc} (disabled)\x1B[0m`
|
|
13665
13663
|
);
|
|
13666
13664
|
} else if (isSelected) {
|
|
13667
|
-
this.
|
|
13668
|
-
|
|
13669
|
-
\x1B[48;5;24m\x1B[38;5;117m\u276F ${checkbox} ${label}${desc}\x1B[0m`
|
|
13665
|
+
this.writeRow(
|
|
13666
|
+
` \x1B[48;5;24m\x1B[38;5;117m\u276F ${checkbox} ${label}${desc}\x1B[0m`
|
|
13670
13667
|
);
|
|
13671
13668
|
} else {
|
|
13672
|
-
this.
|
|
13673
|
-
|
|
13674
|
-
${checkbox} ${label}${desc}`
|
|
13669
|
+
this.writeRow(
|
|
13670
|
+
` ${checkbox} ${label}${desc}`
|
|
13675
13671
|
);
|
|
13676
13672
|
}
|
|
13677
13673
|
}
|
|
@@ -13706,8 +13702,7 @@ var MultiSelectInputMode = class extends InputModeBase {
|
|
|
13706
13702
|
} else {
|
|
13707
13703
|
help = `${checkedCount} selected \xB7 space to toggle \xB7 a to select all \xB7 enter to confirm`;
|
|
13708
13704
|
}
|
|
13709
|
-
this.
|
|
13710
|
-
\x1B[2m${help}\x1B[0m`);
|
|
13705
|
+
this.writeRow(` \x1B[2m${help}\x1B[0m`);
|
|
13711
13706
|
this.renderedLines++;
|
|
13712
13707
|
}
|
|
13713
13708
|
};
|