@rupayan10/aios-cli 0.1.0 → 0.1.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.
Files changed (3) hide show
  1. package/README.md +3 -2
  2. package/dist/cli.js +156 -45
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -4,10 +4,11 @@ Standalone command-line build of FlowScale AIOS. Shares `~/.flowscale` state wit
4
4
 
5
5
  ## Install
6
6
 
7
- Requires **Node ≥ 24** (it ships the built-in `node:sqlite`, so there's nothing to compile):
7
+ Requires **Node ≥ 24** (it ships the built-in `node:sqlite`, so there's nothing to compile).
8
+ It also runs on **Node 22.5+**, where `node:sqlite` is still experimental.
8
9
 
9
10
  ```sh
10
- npm i -g @flowscale/aios-cli
11
+ npm i -g @rupayan10/aios-cli
11
12
  ```
12
13
 
13
14
  Then run `aios` with no arguments (in a terminal) for a guided menu, or any command directly.
package/dist/cli.js CHANGED
@@ -3512,6 +3512,53 @@ var init_esm = __esm({
3512
3512
  }
3513
3513
  });
3514
3514
 
3515
+ // package.json
3516
+ var package_default;
3517
+ var init_package = __esm({
3518
+ "package.json"() {
3519
+ package_default = {
3520
+ name: "@rupayan10/aios-cli",
3521
+ version: "0.1.1",
3522
+ description: "FlowScale AIOS command-line interface",
3523
+ license: "AGPL-3.0-only",
3524
+ bin: {
3525
+ aios: "dist/cli.js"
3526
+ },
3527
+ engines: {
3528
+ node: ">=24"
3529
+ },
3530
+ files: [
3531
+ "dist"
3532
+ ],
3533
+ publishConfig: {
3534
+ access: "public"
3535
+ },
3536
+ scripts: {
3537
+ build: "tsup",
3538
+ prepublishOnly: "npm run build",
3539
+ typecheck: "tsc --noEmit",
3540
+ test: "vitest run",
3541
+ "sync:core": "node --import tsx scripts/sync-core.ts"
3542
+ },
3543
+ dependencies: {
3544
+ "@clack/prompts": "^1.6.0",
3545
+ "@commander-js/extra-typings": "^14.0.0",
3546
+ "adm-zip": "^0.5.17",
3547
+ "cli-table3": "^0.6.5",
3548
+ commander: "^14.0.0"
3549
+ },
3550
+ devDependencies: {
3551
+ "@types/adm-zip": "^0.5.8",
3552
+ "@types/node": "^24.0.0",
3553
+ tsup: "^8.3.0",
3554
+ tsx: "^4.22.4",
3555
+ typescript: "^5.8.3",
3556
+ vitest: "^3.0.0"
3557
+ }
3558
+ };
3559
+ }
3560
+ });
3561
+
3515
3562
  // src/core-ext/paths.ts
3516
3563
  function setHome(dir) {
3517
3564
  override = dir;
@@ -5552,14 +5599,92 @@ var init_db_retry = __esm({
5552
5599
  // src/core-ext/db.ts
5553
5600
  function getDb() {
5554
5601
  if (db) return db;
5602
+ (0, import_node_fs.mkdirSync)(flowscaleHome(), { recursive: true });
5555
5603
  const handle = new import_node_sqlite.DatabaseSync(dbPath());
5556
5604
  handle.exec("PRAGMA journal_mode = WAL");
5557
5605
  handle.exec("PRAGMA busy_timeout = 5000");
5558
5606
  handle.exec("PRAGMA synchronous = NORMAL");
5559
5607
  handle.exec("PRAGMA foreign_keys = ON");
5608
+ ensureSchema(handle);
5560
5609
  db = handle;
5561
5610
  return handle;
5562
5611
  }
5612
+ function ensureSchema(handle) {
5613
+ handle.exec(`
5614
+ CREATE TABLE IF NOT EXISTS tools (
5615
+ id TEXT PRIMARY KEY,
5616
+ name TEXT NOT NULL,
5617
+ description TEXT,
5618
+ workflow_json TEXT NOT NULL,
5619
+ workflow_hash TEXT NOT NULL,
5620
+ schema_json TEXT NOT NULL,
5621
+ layout TEXT NOT NULL DEFAULT 'left-right',
5622
+ status TEXT NOT NULL DEFAULT 'dev',
5623
+ output_dir TEXT,
5624
+ comfy_port INTEGER,
5625
+ model_version TEXT,
5626
+ version INTEGER NOT NULL DEFAULT 1,
5627
+ created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
5628
+ deployed_at INTEGER
5629
+ );
5630
+
5631
+ CREATE TABLE IF NOT EXISTS executions (
5632
+ id TEXT PRIMARY KEY,
5633
+ tool_id TEXT NOT NULL REFERENCES tools(id) ON DELETE CASCADE,
5634
+ inputs_json TEXT NOT NULL,
5635
+ outputs_json TEXT,
5636
+ seed INTEGER,
5637
+ prompt_id TEXT,
5638
+ workflow_hash TEXT NOT NULL,
5639
+ status TEXT NOT NULL DEFAULT 'running',
5640
+ error_message TEXT,
5641
+ metadata_json TEXT,
5642
+ created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
5643
+ completed_at INTEGER
5644
+ );
5645
+
5646
+ CREATE INDEX IF NOT EXISTS idx_tools_status ON tools(status);
5647
+ CREATE INDEX IF NOT EXISTS idx_executions_tool_id ON executions(tool_id);
5648
+ CREATE INDEX IF NOT EXISTS idx_executions_created_at ON executions(created_at DESC);
5649
+
5650
+ CREATE TABLE IF NOT EXISTS models (
5651
+ id TEXT PRIMARY KEY,
5652
+ filename TEXT NOT NULL,
5653
+ path TEXT NOT NULL UNIQUE,
5654
+ type TEXT NOT NULL DEFAULT 'other',
5655
+ size_bytes INTEGER,
5656
+ comfy_port INTEGER NOT NULL,
5657
+ scanned_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
5658
+ );
5659
+
5660
+ CREATE INDEX IF NOT EXISTS idx_models_type ON models(type);
5661
+ CREATE INDEX IF NOT EXISTS idx_models_comfy_port ON models(comfy_port);
5662
+ `);
5663
+ const toolCols = handle.prepare("PRAGMA table_info(tools)").all().map((c2) => c2.name);
5664
+ if (!toolCols.includes("engine")) handle.exec("ALTER TABLE tools ADD COLUMN engine TEXT NOT NULL DEFAULT 'comfyui'");
5665
+ if (!toolCols.includes("source")) handle.exec("ALTER TABLE tools ADD COLUMN source TEXT NOT NULL DEFAULT 'comfyui'");
5666
+ if (!toolCols.includes("source_url")) handle.exec("ALTER TABLE tools ADD COLUMN source_url TEXT");
5667
+ if (!toolCols.includes("tool_type")) {
5668
+ try {
5669
+ handle.exec("ALTER TABLE tools ADD COLUMN tool_type TEXT DEFAULT 'custom'");
5670
+ } catch {
5671
+ }
5672
+ }
5673
+ if (!toolCols.includes("last_used_at")) {
5674
+ try {
5675
+ handle.exec("ALTER TABLE tools ADD COLUMN last_used_at INTEGER");
5676
+ } catch {
5677
+ }
5678
+ }
5679
+ const execCols = handle.prepare("PRAGMA table_info(executions)").all().map((c2) => c2.name);
5680
+ if (!execCols.includes("user_id")) handle.exec("ALTER TABLE executions ADD COLUMN user_id TEXT");
5681
+ if (!execCols.includes("comfy_port")) {
5682
+ try {
5683
+ handle.exec("ALTER TABLE executions ADD COLUMN comfy_port INTEGER");
5684
+ } catch {
5685
+ }
5686
+ }
5687
+ }
5563
5688
  function writeTxn(fn) {
5564
5689
  const handle = getDb();
5565
5690
  return retryBusy(() => {
@@ -5577,11 +5702,12 @@ function writeTxn(fn) {
5577
5702
  }
5578
5703
  });
5579
5704
  }
5580
- var import_node_sqlite, db;
5705
+ var import_node_sqlite, import_node_fs, db;
5581
5706
  var init_db = __esm({
5582
5707
  "src/core-ext/db.ts"() {
5583
5708
  "use strict";
5584
5709
  import_node_sqlite = require("node:sqlite");
5710
+ import_node_fs = require("node:fs");
5585
5711
  init_paths();
5586
5712
  init_db_retry();
5587
5713
  }
@@ -5590,7 +5716,6 @@ var init_db = __esm({
5590
5716
  // src/core-ext/repo.ts
5591
5717
  var repo_exports = {};
5592
5718
  __export(repo_exports, {
5593
- FriendlyDbError: () => FriendlyDbError,
5594
5719
  getExecutionById: () => getExecutionById,
5595
5720
  getToolById: () => getToolById,
5596
5721
  getToolBySourceUrl: () => getToolBySourceUrl,
@@ -5604,24 +5729,10 @@ __export(repo_exports, {
5604
5729
  updateExecution: () => updateExecution,
5605
5730
  upsertModels: () => upsertModels
5606
5731
  });
5607
- function rethrowFriendly(err) {
5608
- const message = err instanceof Error ? err.message : String(err);
5609
- if (message.includes("unable to open database file") || message.includes("no such table")) {
5610
- throw new FriendlyDbError(
5611
- `No FlowScale AIOS database found at ${dbPath()}. Run the FlowScale desktop app once to create it, or build a tool first.`
5612
- );
5613
- }
5614
- throw err;
5615
- }
5616
5732
  function listTools() {
5617
- try {
5618
- const stmt = getDb().prepare(
5619
- "SELECT id, name, engine, status, source FROM tools ORDER BY name COLLATE NOCASE"
5620
- );
5621
- return stmt.all();
5622
- } catch (err) {
5623
- rethrowFriendly(err);
5624
- }
5733
+ return getDb().prepare(
5734
+ "SELECT id, name, engine, status, source FROM tools ORDER BY name COLLATE NOCASE"
5735
+ ).all();
5625
5736
  }
5626
5737
  function getToolById(id) {
5627
5738
  const row = getDb().prepare(
@@ -5707,19 +5818,12 @@ function listCompletedExecutions(toolId, limit = 50) {
5707
5818
  const stmt = getDb().prepare(sql);
5708
5819
  return toolId ? stmt.all(toolId, limit) : stmt.all(limit);
5709
5820
  }
5710
- var import_node_crypto, FriendlyDbError, EXEC_COLS;
5821
+ var import_node_crypto, EXEC_COLS;
5711
5822
  var init_repo = __esm({
5712
5823
  "src/core-ext/repo.ts"() {
5713
5824
  "use strict";
5714
5825
  init_db();
5715
- init_paths();
5716
5826
  import_node_crypto = require("node:crypto");
5717
- FriendlyDbError = class extends Error {
5718
- constructor(message) {
5719
- super(message);
5720
- this.name = "FriendlyDbError";
5721
- }
5722
- };
5723
5827
  EXEC_COLS = "id, tool_id AS toolId, user_id AS userId, inputs_json AS inputsJson, workflow_hash AS workflowHash, seed, status, comfy_port AS comfyPort, created_at AS createdAt, completed_at AS completedAt, outputs_json AS outputsJson, error_message AS errorMessage, metadata_json AS metadataJson";
5724
5828
  }
5725
5829
  });
@@ -6243,11 +6347,11 @@ async function saveComfyOutputsToDisk(outputs, comfyPort, toolId, executionId) {
6243
6347
  }
6244
6348
  function saveApiOutputs(executionId, outputs) {
6245
6349
  const outDir = (0, import_node_path2.join)(outputsDir(), executionId);
6246
- (0, import_node_fs.mkdirSync)(outDir, { recursive: true });
6350
+ (0, import_node_fs2.mkdirSync)(outDir, { recursive: true });
6247
6351
  return outputs.map(({ kind, filename, data }) => {
6248
6352
  const safe = (0, import_node_path2.basename)(filename);
6249
6353
  if (!safe || safe === "." || safe === "..") throw new Error(`Invalid output filename: ${filename}`);
6250
- (0, import_node_fs.writeFileSync)((0, import_node_path2.join)(outDir, safe), Buffer.from(data, "base64"));
6354
+ (0, import_node_fs2.writeFileSync)((0, import_node_path2.join)(outDir, safe), Buffer.from(data, "base64"));
6251
6355
  return { kind, filename: safe, path: `/api/executions/${executionId}/outputs/${safe}` };
6252
6356
  });
6253
6357
  }
@@ -6262,12 +6366,12 @@ function resolveOutputDiskPath(storedPath) {
6262
6366
  if (m) return contained((0, import_node_path2.join)(root, m[1], m[2]));
6263
6367
  return null;
6264
6368
  }
6265
- var import_promises, import_node_fs, import_node_path2;
6369
+ var import_promises, import_node_fs2, import_node_path2;
6266
6370
  var init_output_saver = __esm({
6267
6371
  "src/core-ext/output-saver.ts"() {
6268
6372
  "use strict";
6269
6373
  import_promises = require("node:fs/promises");
6270
- import_node_fs = require("node:fs");
6374
+ import_node_fs2 = require("node:fs");
6271
6375
  import_node_path2 = require("node:path");
6272
6376
  init_comfy_url();
6273
6377
  init_paths();
@@ -7152,7 +7256,7 @@ var require_utils2 = __commonJS({
7152
7256
  module2.exports = Utils;
7153
7257
  Utils.prototype.makeDir = function(folder) {
7154
7258
  const self = this;
7155
- function mkdirSync4(fpath) {
7259
+ function mkdirSync5(fpath) {
7156
7260
  let resolvedPath = fpath.split(self.sep)[0];
7157
7261
  fpath.split(self.sep).forEach(function(name) {
7158
7262
  if (!name || name.substr(-1, 1) === ":") return;
@@ -7170,7 +7274,7 @@ var require_utils2 = __commonJS({
7170
7274
  if (stat && stat.isFile()) throw Errors.FILE_IN_THE_WAY(`"${resolvedPath}"`);
7171
7275
  });
7172
7276
  }
7173
- mkdirSync4(folder);
7277
+ mkdirSync5(folder);
7174
7278
  };
7175
7279
  Utils.prototype.writeFileTo = function(path5, content, overwrite, attr) {
7176
7280
  const self = this;
@@ -10021,7 +10125,7 @@ function registerTools(program2) {
10021
10125
  const o2 = build.opts();
10022
10126
  let workflowJson;
10023
10127
  try {
10024
- workflowJson = (0, import_node_fs2.readFileSync)(file, "utf-8");
10128
+ workflowJson = (0, import_node_fs3.readFileSync)(file, "utf-8");
10025
10129
  } catch {
10026
10130
  process.stderr.write(`Workflow file not found: ${file}
10027
10131
  `);
@@ -10167,7 +10271,7 @@ function registerTools(program2) {
10167
10271
  const path5 = v.slice(1);
10168
10272
  let buf;
10169
10273
  try {
10170
- buf = (0, import_node_fs2.readFileSync)(path5);
10274
+ buf = (0, import_node_fs3.readFileSync)(path5);
10171
10275
  } catch {
10172
10276
  process.stderr.write(`Input file not found: ${path5}
10173
10277
  `);
@@ -10226,11 +10330,11 @@ function registerTools(program2) {
10226
10330
  }
10227
10331
  });
10228
10332
  }
10229
- var import_node_fs2;
10333
+ var import_node_fs3;
10230
10334
  var init_tools = __esm({
10231
10335
  "src/commands/tools.ts"() {
10232
10336
  "use strict";
10233
- import_node_fs2 = require("node:fs");
10337
+ import_node_fs3 = require("node:fs");
10234
10338
  init_repo();
10235
10339
  init_render();
10236
10340
  init_execution_runner();
@@ -10543,7 +10647,7 @@ var init_instances = __esm({
10543
10647
  function readInstanceLog(logPath, lines = 200) {
10544
10648
  let content;
10545
10649
  try {
10546
- content = (0, import_node_fs3.readFileSync)(logPath, "utf-8");
10650
+ content = (0, import_node_fs4.readFileSync)(logPath, "utf-8");
10547
10651
  } catch {
10548
10652
  return [];
10549
10653
  }
@@ -10551,11 +10655,11 @@ function readInstanceLog(logPath, lines = 200) {
10551
10655
  if (all.length && all[all.length - 1] === "") all.pop();
10552
10656
  return all.slice(-lines);
10553
10657
  }
10554
- var import_node_fs3;
10658
+ var import_node_fs4;
10555
10659
  var init_comfy_logs = __esm({
10556
10660
  "src/core-ext/comfy-logs.ts"() {
10557
10661
  "use strict";
10558
- import_node_fs3 = require("node:fs");
10662
+ import_node_fs4 = require("node:fs");
10559
10663
  }
10560
10664
  });
10561
10665
 
@@ -10971,7 +11075,7 @@ function registerAssets(program2) {
10971
11075
  process.exitCode = 1;
10972
11076
  return;
10973
11077
  }
10974
- const target = assetsForExecution(row).find((a2) => a2.diskPath && (0, import_node_fs4.existsSync)(a2.diskPath));
11078
+ const target = assetsForExecution(row).find((a2) => a2.diskPath && (0, import_node_fs5.existsSync)(a2.diskPath));
10975
11079
  if (!target?.diskPath) {
10976
11080
  process.stderr.write(`No openable output file found on disk for execution ${executionId}.
10977
11081
  `);
@@ -10983,11 +11087,11 @@ function registerAssets(program2) {
10983
11087
  `);
10984
11088
  });
10985
11089
  }
10986
- var import_node_fs4;
11090
+ var import_node_fs5;
10987
11091
  var init_assets2 = __esm({
10988
11092
  "src/commands/assets.ts"() {
10989
11093
  "use strict";
10990
- import_node_fs4 = require("node:fs");
11094
+ import_node_fs5 = require("node:fs");
10991
11095
  init_repo();
10992
11096
  init_assets();
10993
11097
  init_open_file();
@@ -12131,12 +12235,13 @@ var init_interactive = __esm({
12131
12235
  var cli_exports = {};
12132
12236
  __export(cli_exports, {
12133
12237
  buildProgram: () => buildProgram,
12238
+ formatCliError: () => formatCliError,
12134
12239
  main: () => main
12135
12240
  });
12136
12241
  module.exports = __toCommonJS(cli_exports);
12137
12242
  function buildProgram() {
12138
12243
  const program2 = new Command();
12139
- program2.name("aios").description("FlowScale AIOS command-line interface").option("--home <dir>", "override FLOWSCALE_HOME").option("--verbose", "verbose logging").hook("preAction", (thisCommand) => {
12244
+ program2.name("aios").description("FlowScale AIOS command-line interface").version(package_default.version).option("--home <dir>", "override FLOWSCALE_HOME").option("--verbose", "verbose logging").hook("preAction", (thisCommand) => {
12140
12245
  const opts = thisCommand.opts();
12141
12246
  if (opts.home) setHome(opts.home);
12142
12247
  });
@@ -12158,10 +12263,15 @@ async function main(argv) {
12158
12263
  }
12159
12264
  await buildProgram().parseAsync(argv);
12160
12265
  }
12266
+ function formatCliError(err, argv) {
12267
+ const message = err instanceof Error ? err.message : String(err);
12268
+ return argv.includes("--json") ? JSON.stringify({ error: message }) : message;
12269
+ }
12161
12270
  var isMain;
12162
12271
  var init_cli = __esm({
12163
12272
  "src/cli.ts"() {
12164
12273
  init_esm();
12274
+ init_package();
12165
12275
  init_paths();
12166
12276
  init_gpu();
12167
12277
  init_tools();
@@ -12177,7 +12287,7 @@ var init_cli = __esm({
12177
12287
  isMain = typeof require !== "undefined" && require.main === module;
12178
12288
  if (isMain) {
12179
12289
  main(process.argv).catch((err) => {
12180
- console.error(err instanceof Error ? err.message : String(err));
12290
+ console.error(formatCliError(err, process.argv));
12181
12291
  process.exit(1);
12182
12292
  });
12183
12293
  }
@@ -12187,5 +12297,6 @@ init_cli();
12187
12297
  // Annotate the CommonJS export names for ESM import in node:
12188
12298
  0 && (module.exports = {
12189
12299
  buildProgram,
12300
+ formatCliError,
12190
12301
  main
12191
12302
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rupayan10/aios-cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "FlowScale AIOS command-line interface",
5
5
  "license": "AGPL-3.0-only",
6
6
  "bin": {