@aspct3434/distill-agent 0.2.0 → 0.2.1

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
@@ -111,7 +111,7 @@ docker compose up -d --build
111
111
 
112
112
  ### CLI Installation
113
113
 
114
- You can also install Distill globally using `npm` to get the robust interactive CLI installer:
114
+ You can also install Distill globally using `npm` to get the robust interactive CLI installer and TUI:
115
115
 
116
116
  ```powershell
117
117
  npx @aspct3434/distill-agent install
@@ -119,6 +119,13 @@ npx @aspct3434/distill-agent install
119
119
 
120
120
  After installation, use the CLI to manage the agent:
121
121
  ```bash
122
+ npm install -g @aspct3434/distill-agent
123
+ distill # Open the interactive terminal UI
124
+ distill start # Start the backend and control panel
125
+ distill logs # View running logs
126
+ distill update # Pull the latest changes
127
+
128
+ # npx works too if you prefer not to install globally:
122
129
  npx @aspct3434/distill-agent start # Start the backend and control panel
123
130
  npx @aspct3434/distill-agent logs # View running logs
124
131
  npx @aspct3434/distill-agent update # Pull the latest changes
@@ -192,6 +192,7 @@ function banner() {
192
192
  lines.push(c.bold(hex(colors[i], line)));
193
193
  });
194
194
  lines.push("");
195
+ lines.push(` ${c.bold(hex("#A855F7", "DISTILL"))}`);
195
196
  lines.push(` ${hex("#6B7280", "v" + packageVersion())} ${c.dim("·")} ${hex("#A855F7", "Autonomous Agent Framework")}`);
196
197
  lines.push(` ${hex("#6B7280", "Evidence-gated execution · Skill distillation · Hybrid memory")}`);
197
198
  lines.push("");
@@ -223,6 +224,7 @@ function usage() {
223
224
  ${c.bold("Distill")} — installer and lifecycle CLI
224
225
 
225
226
  ${hex("#A855F7", "Usage:")}
227
+ distill Launch the interactive Terminal UI
226
228
  distill install [options] Interactive guided setup
227
229
  distill doctor [options] Health check
228
230
  distill start [options] Start backend + control panel
@@ -230,6 +232,7 @@ ${hex("#A855F7", "Usage:")}
230
232
  distill restart [options] Restart all services
231
233
  distill update [options] Pull latest + restart
232
234
  distill logs [options] View service logs
235
+ distill tui [options] Launch the Terminal UI
233
236
 
234
237
  ${hex("#A855F7", "Install options:")}
235
238
  --repo-url URL Git repository URL
@@ -248,8 +251,11 @@ ${hex("#A855F7", "Lifecycle options:")}
248
251
  --sandbox on|off Override sandbox mode
249
252
  --tail NUMBER Number of log lines to show ${c.dim("(default: 200)")}
250
253
  --follow Stream logs continuously
254
+ --url URL Gateway WebSocket URL for the TUI
255
+ --theme NAME TUI theme ${c.dim("(distill|ocean|ember|mono)")}
251
256
 
252
257
  ${hex("#A855F7", "Examples:")}
258
+ ${c.dim("$")} distill
253
259
  ${c.dim("$")} npx @aspct3434/distill-agent install
254
260
  ${c.dim("$")} npx @aspct3434/distill-agent doctor
255
261
  ${c.dim("$")} npx @aspct3434/distill-agent logs --tail 100 --follow
@@ -257,7 +263,7 @@ ${hex("#A855F7", "Examples:")}
257
263
  }
258
264
 
259
265
  function parseArgs(argv) {
260
- const result = { command: "help", options: {} };
266
+ const result = { command: "tui", options: {} };
261
267
  const args = [...argv];
262
268
  if (args.length > 0 && !args[0].startsWith("-")) {
263
269
  result.command = args.shift();
@@ -270,7 +276,9 @@ function parseArgs(argv) {
270
276
  "sandbox",
271
277
  "messaging",
272
278
  "mode",
273
- "tail"
279
+ "tail",
280
+ "url",
281
+ "theme"
274
282
  ]);
275
283
  const booleanOptions = new Set([
276
284
  "dry-run",
@@ -1241,9 +1249,10 @@ async function startServices(config) {
1241
1249
  `${hex("#A855F7", "Control Panel:")} ${c.underline("http://localhost:5173")}`,
1242
1250
  `${hex("#A855F7", "API Docs:")} ${c.underline("http://localhost:8000/docs")}`,
1243
1251
  `${hex("#A855F7", "Health Check:")} ${c.underline("http://localhost:8000/health")}`,
1244
- `${hex("#A855F7", "Terminal UI:")} ${c.dim("python src/tui.py")}`,
1252
+ `${hex("#A855F7", "Terminal UI:")} ${c.dim("distill")}`,
1245
1253
  "",
1246
1254
  `${c.dim("Manage with:")}`,
1255
+ ` ${c.dim("$")} distill`,
1247
1256
  ` ${c.dim("$")} npx @aspct3434/distill-agent stop`,
1248
1257
  ` ${c.dim("$")} npx @aspct3434/distill-agent logs --follow`,
1249
1258
  ` ${c.dim("$")} npx @aspct3434/distill-agent doctor`,
@@ -1347,6 +1356,19 @@ function spawnDetached(command, args, cwd, stdoutPath, stderrPath, dryRun) {
1347
1356
  logStep(`[dry-run] ${formatCommand(command, args)} > ${stdoutPath} 2> ${stderrPath}`, cwd);
1348
1357
  return { pid: 0 };
1349
1358
  }
1359
+ if (process.platform === "win32") {
1360
+ const psArgs = [
1361
+ "-NoProfile", "-NonInteractive", "-Command",
1362
+ `$proc = Start-Process -FilePath "${command}" -ArgumentList @(${args.map(a => `"${a.replace(/"/g, '""')}"`).join(", ")}) -WorkingDirectory "${cwd}" -WindowStyle Hidden -PassThru -RedirectStandardOutput "${stdoutPath}" -RedirectStandardError "${stderrPath}"; Write-Output $proc.Id`
1363
+ ];
1364
+ const result = spawnSync("powershell", psArgs, { windowsHide: true });
1365
+ const pidStr = result.stdout ? result.stdout.toString().trim() : "";
1366
+ const pid = parseInt(pidStr, 10);
1367
+ if (isNaN(pid)) {
1368
+ throw new Error(`Failed to start detached process on Windows. Output: ${result.stdout} ${result.stderr}`);
1369
+ }
1370
+ return { pid };
1371
+ }
1350
1372
  const stdout = fs.openSync(stdoutPath, "a");
1351
1373
  const stderr = fs.openSync(stderrPath, "a");
1352
1374
  const child = spawn(command, args, {
@@ -1491,6 +1513,35 @@ async function doctor(options) {
1491
1513
  }
1492
1514
  }
1493
1515
 
1516
+ // ─── TUI ─────────────────────────────────────────────────────────────────────
1517
+
1518
+ function resolveTuiPython(config) {
1519
+ for (const name of [".run-venv", "venv"]) {
1520
+ const venvDir = path.join(config.installDir, name);
1521
+ const candidate = virtualEnvPython(venvDir);
1522
+ if (fs.existsSync(candidate)) return [candidate, []];
1523
+ }
1524
+ const systemPython = pythonCommand();
1525
+ if (systemPython && isAgentRepo(config.installDir)) return systemPython;
1526
+ throw new Error(
1527
+ "Python environment not found. Run 'distill install' first, or run from a Distill checkout with dependencies installed."
1528
+ );
1529
+ }
1530
+
1531
+ async function startTui(config, options = {}) {
1532
+ if (!config.dryRun && !isAgentRepo(config.installDir)) {
1533
+ throw new Error(`Install directory is not a Distill checkout: ${config.installDir}`);
1534
+ }
1535
+ const [python, pythonPrefix] = config.dryRun
1536
+ ? (pythonCommand() || ["python3", []])
1537
+ : resolveTuiPython(config);
1538
+ const args = [...pythonPrefix, "src/tui.py"];
1539
+ if (options.url) args.push("--url", options.url);
1540
+ if (options.theme) args.push("--theme", options.theme);
1541
+
1542
+ await run(python, args, { cwd: config.installDir, stdio: "inherit", dryRun: config.dryRun });
1543
+ }
1544
+
1494
1545
  // ─── Install ─────────────────────────────────────────────────────────────────
1495
1546
 
1496
1547
  async function install(options) {
@@ -1558,6 +1609,7 @@ async function install(options) {
1558
1609
 
1559
1610
  async function main(argv = process.argv.slice(2)) {
1560
1611
  const { command, options } = parseArgs(argv);
1612
+ const implicitTui = argv.length === 0;
1561
1613
  switch (command) {
1562
1614
  case "help":
1563
1615
  case undefined:
@@ -1597,6 +1649,14 @@ async function main(argv = process.argv.slice(2)) {
1597
1649
  case "logs":
1598
1650
  await showLogs(resolveRuntimeConfig(options), options);
1599
1651
  break;
1652
+ case "tui":
1653
+ if (implicitTui && (!process.stdin.isTTY || !process.stdout.isTTY)) {
1654
+ console.log(banner());
1655
+ console.log(usage());
1656
+ break;
1657
+ }
1658
+ await startTui(resolveRuntimeConfig(options), options);
1659
+ break;
1600
1660
  default:
1601
1661
  throw new Error(`Unknown command: ${command}\n${usage()}`);
1602
1662
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aspct3434/distill-agent",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Distill — interactive installer and lifecycle CLI for the Distill autonomous agent framework.",
5
5
  "bin": {
6
6
  "distill": "bin/distill.js"