vexi-cli 0.5.3 → 0.5.5

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 CHANGED
@@ -90,6 +90,22 @@ Inside the chat:
90
90
  /exit quit
91
91
  ```
92
92
 
93
+ ## ⚙️ Multi-language build support
94
+
95
+ Vexi can build and run projects in **any language** — not just JavaScript. When the AI suggests commands, it wraps them in a shell block, Vexi asks for confirmation, then executes them automatically and feeds the output back to the AI.
96
+
97
+ | Language | Commands Vexi can run |
98
+ | --- | --- |
99
+ | Python | `pip install -r requirements.txt`, `python main.py`, `pytest` |
100
+ | Java (Maven) | `mvn compile`, `mvn package`, `java -jar target/app.jar` |
101
+ | Java (Gradle) | `gradle build`, `java -jar build/libs/app.jar` |
102
+ | C / C++ | `gcc main.c -o main`, `make`, `cmake ..` |
103
+ | Rust | `cargo build`, `cargo run` |
104
+ | Go | `go build ./...`, `go run main.go` |
105
+ | JavaScript | `npm install`, `npm run build`, `npm test` |
106
+
107
+ The project scanner automatically detects `.py`, `.java`, `.c`, `.cpp`, `.rs`, `.go` files and tells the AI what language your project uses before the first message.
108
+
93
109
  ## 🧠 Project memory — Context Compression Engine
94
110
 
95
111
  Most AI coding tools forget earlier decisions once the conversation gets long.
package/dist/agent.js CHANGED
@@ -16,6 +16,7 @@
16
16
  */
17
17
  import { basename } from 'node:path';
18
18
  import { platform } from 'node:os';
19
+ import { exec as cpExec } from 'node:child_process';
19
20
  import { input, select, confirm } from '@inquirer/prompts';
20
21
  import * as nodeRl from 'node:readline';
21
22
  import ora from 'ora';
@@ -29,6 +30,26 @@ import { McpManager, parseToolCall } from './mcp/client.js';
29
30
  import { loadMcpConfig } from './mcp/config.js';
30
31
  import { ARABIC_RTL_NOTE, getStrings, t } from './i18n/index.js';
31
32
  import { accent, dim, err, ok, printBanner, printStatusLine, userPrompt, vexiLabel, warn } from './ui/index.js';
33
+ /** Extract shell commands from fenced code blocks in an AI reply. */
34
+ function extractShellBlocks(reply) {
35
+ const blocks = [];
36
+ const re = /```(?:bash|sh|shell|cmd|powershell|ps1)\n([\s\S]*?)```/gi;
37
+ let m;
38
+ while ((m = re.exec(reply)) !== null) {
39
+ const code = m[1].trim();
40
+ if (code)
41
+ blocks.push(code);
42
+ }
43
+ return blocks;
44
+ }
45
+ /** Run a shell command and return { stdout, stderr, code }. */
46
+ function runCommand(cmd, cwd) {
47
+ return new Promise((resolve) => {
48
+ cpExec(cmd, { cwd, shell: process.platform === 'win32' ? 'powershell.exe' : '/bin/sh', maxBuffer: 1024 * 1024 * 4 }, (err, stdout, stderr) => {
49
+ resolve({ stdout: stdout ?? '', stderr: stderr ?? '', code: err?.code ?? 0 });
50
+ });
51
+ });
52
+ }
32
53
  /**
33
54
  * Read a user message with multi-line paste support.
34
55
  * Creates a fresh readline interface per call so it never conflicts
@@ -258,6 +279,31 @@ export async function runAgent(opts) {
258
279
  process.stdout.write('\n\n');
259
280
  history.push({ role: 'assistant', content: reply });
260
281
  recorder.add('assistant', reply);
282
+ // ── Auto-run shell commands suggested by the AI ──────────────
283
+ const shellBlocks = extractShellBlocks(reply);
284
+ for (const cmd of shellBlocks) {
285
+ console.log(accent('▶ run? ') + dim(cmd.slice(0, 120) + (cmd.length > 120 ? '…' : '')));
286
+ const yes = await confirm({ message: 'Execute', default: true }).catch(() => false);
287
+ if (!yes) {
288
+ history.push({ role: 'user', content: `COMMAND SKIPPED: ${cmd}` });
289
+ continue;
290
+ }
291
+ const runSpinner = ora({ text: dim('running…'), spinner: 'dots' }).start();
292
+ const { stdout, stderr, code } = await runCommand(cmd, root);
293
+ runSpinner.stop();
294
+ const output = [
295
+ stdout.trim() ? `STDOUT:\n${stdout.trim()}` : '',
296
+ stderr.trim() ? `STDERR:\n${stderr.trim()}` : '',
297
+ `EXIT CODE: ${code}`,
298
+ ].filter(Boolean).join('\n');
299
+ console.log(code === 0 ? ok('✓ done') : err(`✗ exit ${code}`));
300
+ if (stdout.trim())
301
+ console.log(dim(stdout.trim().slice(0, 800)));
302
+ if (stderr.trim())
303
+ console.log(warn(stderr.trim().slice(0, 400)));
304
+ history.push({ role: 'user', content: `COMMAND RESULT (${cmd.slice(0, 60)}):\n${output.slice(0, 6000)}` });
305
+ recorder.add('user', `COMMAND RESULT:\n${output.slice(0, 6000)}`);
306
+ }
261
307
  // MCP tool call requested by the model?
262
308
  const call = mcp.tools.length > 0 && round < 5 ? parseToolCall(reply) : null;
263
309
  if (!call)
@@ -353,6 +399,21 @@ function buildSystemPrompt(lang, projectBlock, skillsText, memoryText, mcpText)
353
399
  'Format code in fenced Markdown blocks with the language tag.',
354
400
  `Environment: OS=${platform()}, cwd=${process.cwd()}.`,
355
401
  `The user's preferred language is ${langNames[lang]}; reply in that language unless asked otherwise (code and identifiers stay in English).`,
402
+ '',
403
+ '## Command execution',
404
+ 'You can run shell commands directly. Wrap any command in a fenced code block tagged `bash` or `sh` — regardless of the project language.',
405
+ 'Vexi will show the command to the user, ask for confirmation, execute it, and report the output back to you.',
406
+ 'Use this to: install dependencies, build projects, run tests, start servers, scaffold files, etc.',
407
+ 'Examples by language:',
408
+ ' JavaScript/Node: ```bash\nnpm install\nnpm run build\n```',
409
+ ' Python: ```bash\npip install -r requirements.txt\npython main.py\n```',
410
+ ' Java (Maven): ```bash\nmvn compile\nmvn package\njava -jar target/app.jar\n```',
411
+ ' Java (Gradle): ```bash\ngradle build\njava -jar build/libs/app.jar\n```',
412
+ ' C/C++: ```bash\ngcc main.c -o main\n./main\n```',
413
+ ' Rust: ```bash\ncargo build\ncargo run\n```',
414
+ ' Go: ```bash\ngo build ./...\ngo run main.go\n```',
415
+ 'Always use `bash` as the code block language tag for commands — never `python`, `java`, etc.',
416
+ 'After seeing the output, continue helping based on the result.',
356
417
  ];
357
418
  if (projectBlock)
358
419
  parts.push('', '## Project map', projectBlock);
package/dist/cli.js CHANGED
@@ -32,7 +32,7 @@ import { createProvider, PROVIDER_INFO } from './providers/index.js';
32
32
  import { openInDefaultApp } from './utils/open.js';
33
33
  import { detectSystemLang, getStrings, normalizeLang, t, SUPPORTED_LANGS } from './i18n/index.js';
34
34
  import { accent, dim, err, ok } from './ui/index.js';
35
- export const VERSION = '0.5.2';
35
+ export const VERSION = '0.5.5';
36
36
  /** Resolve the active language: --lang flag > saved config > system locale. */
37
37
  async function resolveLang(flag) {
38
38
  if (flag) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vexi-cli",
3
- "version": "0.5.3",
3
+ "version": "0.5.5",
4
4
  "description": "Open-source AI coding agent for your terminal. Bring your own key, zero config, multilingual.",
5
5
  "type": "module",
6
6
  "bin": {