aiex-cli 0.0.6-beta.3 → 0.0.6

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.
@@ -3,8 +3,8 @@ import fs from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import process from "node:process";
5
5
  import { fileURLToPath } from "node:url";
6
- import { readFile, writeFile } from "jsonfile";
7
6
  import Database from "better-sqlite3";
7
+ import { readFile, writeFile } from "jsonfile";
8
8
  import * as esbuild from "esbuild";
9
9
  import lockfile from "proper-lockfile";
10
10
 
@@ -3,8 +3,10 @@ import os from "node:os";
3
3
  import path from "node:path";
4
4
  import process from "node:process";
5
5
  import { fileURLToPath } from "node:url";
6
- import Conf from "conf";
6
+ import Database from "better-sqlite3";
7
+ import { execa } from "execa";
7
8
  import { readFile, writeFile } from "jsonfile";
9
+ import Conf from "conf";
8
10
  import { z } from "zod";
9
11
 
10
12
  //#region src/core/doctor.ts
@@ -56,8 +58,13 @@ function doctorDiagnosticsTableRows(d) {
56
58
  rows.push(["aiConfig", String(p.aiConfig)]);
57
59
  rows.push(["aiApiKeySet", String(p.aiApiKeySet)]);
58
60
  rows.push(["aiModels", p.aiModelCount ? p.aiModels.join(", ") : "none"]);
61
+ rows.push(["aiVisionModels", String(p.aiVisionModelCount)]);
62
+ rows.push(["aiStructuredOutputModels", String(p.aiStructuredOutputModelCount)]);
59
63
  rows.push(["aiProvider", p.aiProvider ?? "none"]);
60
64
  rows.push(["aiConnectionOk", p.aiConnectionOk === null ? "not tested" : String(p.aiConnectionOk)]);
65
+ rows.push(["pdfConverter", p.pdfConverter ?? "none"]);
66
+ rows.push(["pdfConverterOk", p.pdfConverterOk === null ? "not tested" : String(p.pdfConverterOk)]);
67
+ if (p.pdfConverterError) rows.push(["pdfConverterError", p.pdfConverterError]);
61
68
  rows.push(["imageOcrPlatform", String(d.imageOcr.platformSupported)]);
62
69
  rows.push(["imageOcrDependency", String(d.imageOcr.dependencyLoaded)]);
63
70
  rows.push(["imageOcrOk", d.imageOcr.ocrOk === null ? "not tested" : String(d.imageOcr.ocrOk)]);
@@ -66,7 +73,11 @@ function doctorDiagnosticsTableRows(d) {
66
73
  if (typeof d.imageOcr.confidence === "number") rows.push(["imageOcrConfidence", `${(d.imageOcr.confidence * 100).toFixed(1)}%`]);
67
74
  if (d.imageOcr.error) rows.push(["imageOcrError", d.imageOcr.error]);
68
75
  rows.push(["hasDatabase", String(p.hasDatabase)]);
76
+ rows.push(["databaseTablesOk", p.databaseTablesOk === null ? "not tested" : String(p.databaseTablesOk)]);
77
+ if (p.missingDatabaseTables.length) rows.push(["missingDatabaseTables", p.missingDatabaseTables.join(", ")]);
69
78
  rows.push(["migrations", String(p.migrationCount)]);
79
+ rows.push(["schemaValid", `${p.schemaValidCount}/${p.schemaCount}`]);
80
+ for (const invalid of p.invalidSchemas) rows.push(["invalidSchema", `${invalid.file}: ${invalid.error}`]);
70
81
  for (const err of p.errors) rows.push(["error", err]);
71
82
  return rows;
72
83
  }
@@ -74,7 +85,7 @@ function doctorDiagnosticsTableRows(d) {
74
85
  //#endregion
75
86
  //#region package.json
76
87
  var name = "aiex-cli";
77
- var version = "0.0.6-beta.3";
88
+ var version = "0.0.6";
78
89
  var description = "JSON Schema → SQLite with AI-powered data extraction";
79
90
  var package_default = {
80
91
  name,
@@ -1416,6 +1427,14 @@ async function checkConnection(baseURL) {
1416
1427
  return false;
1417
1428
  }
1418
1429
  }
1430
+ async function commandAvailable(command) {
1431
+ try {
1432
+ await execa("command", ["-v", command], { shell: true });
1433
+ return true;
1434
+ } catch {
1435
+ return false;
1436
+ }
1437
+ }
1419
1438
  async function findImageOcrSelfCheckLogo() {
1420
1439
  const candidates = [
1421
1440
  path.resolve(MODULE_DIR, "logo.png"),
@@ -1450,8 +1469,13 @@ async function collectDoctorDiagnostics(options = {}) {
1450
1469
  let aiApiKeySet = false;
1451
1470
  let aiModelCount = 0;
1452
1471
  let aiModels = [];
1472
+ let aiVisionModelCount = 0;
1473
+ let aiStructuredOutputModelCount = 0;
1453
1474
  let aiProvider = null;
1454
1475
  let aiConnectionOk = null;
1476
+ let pdfConverter = null;
1477
+ let pdfConverterOk = null;
1478
+ let pdfConverterError;
1455
1479
  if (dirExists) {
1456
1480
  const cfg = await readAIConfig(aiexDir);
1457
1481
  if (cfg) {
@@ -1459,16 +1483,67 @@ async function collectDoctorDiagnostics(options = {}) {
1459
1483
  aiApiKeySet = Boolean(cfg.provider.apiKey);
1460
1484
  aiModelCount = cfg.provider.models?.length ?? 0;
1461
1485
  aiModels = cfg.provider.models?.map((m) => m.name) ?? [];
1486
+ aiVisionModelCount = cfg.provider.models?.filter((m) => m.capabilities.vision).length ?? 0;
1487
+ aiStructuredOutputModelCount = cfg.provider.models?.filter((m) => m.capabilities.structuredOutput).length ?? 0;
1462
1488
  aiProvider = cfg.provider.baseURL;
1463
1489
  aiConnectionOk = await checkConnection(cfg.provider.baseURL);
1490
+ pdfConverter = cfg.pdf?.converter ?? "unpdf";
1491
+ if (pdfConverter === "unpdf") pdfConverterOk = true;
1492
+ else if (pdfConverter === "mineru") {
1493
+ const command = cfg.pdf?.mineru?.command ?? DEFAULT_MINERU_CONFIG.command;
1494
+ pdfConverterOk = await commandAvailable(command);
1495
+ if (!pdfConverterOk) pdfConverterError = `Command not found: ${command}`;
1496
+ } else if (pdfConverter === "external") {
1497
+ const command = cfg.pdf?.external?.command;
1498
+ if (!command) {
1499
+ pdfConverterOk = false;
1500
+ pdfConverterError = "External converter command is not configured";
1501
+ } else {
1502
+ pdfConverterOk = await commandAvailable(command);
1503
+ if (!pdfConverterOk) pdfConverterError = `Command not found: ${command}`;
1504
+ }
1505
+ } else if (pdfConverter === "mineru_api") {
1506
+ pdfConverterOk = Boolean(cfg.pdf?.mineruApi?.token);
1507
+ if (!pdfConverterOk) pdfConverterError = "MinerU API token is not configured";
1508
+ }
1464
1509
  }
1465
1510
  }
1511
+ let schemaValidCount = 0;
1512
+ const invalidSchemas = [];
1513
+ const expectedTables = /* @__PURE__ */ new Set();
1514
+ if (dirExists && schemaFiles.length > 0) for (const file of schemaFiles) try {
1515
+ const schemaPath = path.join(migConfig.schemaPath, file);
1516
+ const parsed = JsonSchemaDefinitionSchema.parse(await readFile(schemaPath));
1517
+ schemaValidCount += 1;
1518
+ for (const table of parseJsonSchema(parsed).tables) expectedTables.add(table.name);
1519
+ } catch (error) {
1520
+ invalidSchemas.push({
1521
+ file,
1522
+ error: error instanceof Error ? error.message : String(error)
1523
+ });
1524
+ }
1466
1525
  let dbExists = false;
1467
1526
  if (dirExists) try {
1468
1527
  dbExists = (await fs.stat(migConfig.databasePath)).isFile();
1469
1528
  } catch {
1470
1529
  dbExists = false;
1471
1530
  }
1531
+ let databaseTablesOk = null;
1532
+ let missingDatabaseTables = [];
1533
+ if (dbExists && expectedTables.size > 0) {
1534
+ const db = new Database(migConfig.databasePath, { readonly: true });
1535
+ try {
1536
+ missingDatabaseTables = [...expectedTables].filter((table) => {
1537
+ return !db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name=?`).get(table);
1538
+ });
1539
+ databaseTablesOk = missingDatabaseTables.length === 0;
1540
+ } catch (error) {
1541
+ databaseTablesOk = false;
1542
+ errors.push(`Could not inspect database tables: ${error instanceof Error ? error.message : String(error)}`);
1543
+ } finally {
1544
+ db.close();
1545
+ }
1546
+ } else if (dbExists) databaseTablesOk = true;
1472
1547
  let migrationCount = 0;
1473
1548
  if (dirExists) try {
1474
1549
  migrationCount = (await fs.readdir(migConfig.migrationsPath).catch(() => [])).filter((f) => f.endsWith(".sql")).length;
@@ -1499,10 +1574,19 @@ async function collectDoctorDiagnostics(options = {}) {
1499
1574
  aiApiKeySet,
1500
1575
  aiModelCount,
1501
1576
  aiModels,
1577
+ aiVisionModelCount,
1578
+ aiStructuredOutputModelCount,
1502
1579
  aiProvider,
1503
1580
  aiConnectionOk,
1581
+ pdfConverter,
1582
+ pdfConverterOk,
1583
+ pdfConverterError,
1504
1584
  hasDatabase: dbExists,
1585
+ databaseTablesOk,
1586
+ missingDatabaseTables,
1505
1587
  migrationCount,
1588
+ schemaValidCount,
1589
+ invalidSchemas,
1506
1590
  errors
1507
1591
  }
1508
1592
  });
package/dist/index.d.mts CHANGED
@@ -41,10 +41,22 @@ interface DoctorDiagnostics {
41
41
  aiApiKeySet: boolean;
42
42
  aiModelCount: number;
43
43
  aiModels: string[];
44
+ aiVisionModelCount: number;
45
+ aiStructuredOutputModelCount: number;
44
46
  aiProvider: string | null;
45
47
  aiConnectionOk: boolean | null;
48
+ pdfConverter: string | null;
49
+ pdfConverterOk: boolean | null;
50
+ pdfConverterError?: string;
46
51
  hasDatabase: boolean;
52
+ databaseTablesOk: boolean | null;
53
+ missingDatabaseTables: string[];
47
54
  migrationCount: number;
55
+ schemaValidCount: number;
56
+ invalidSchemas: Array<{
57
+ file: string;
58
+ error: string;
59
+ }>;
48
60
  errors: string[];
49
61
  };
50
62
  }
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { D as buildDoctorDiagnostics, O as doctorDiagnosticsTableRows, a as parseJsonSchema, i as JsonSchemaDefinitionSchema, k as formatDoctorDiagnosticsJson, n as createMigrationConfig, r as generateDrizzleConfig, s as generateDrizzleSchema, t as collectDoctorDiagnostics } from "./doctor-collector-abgpqc5T.mjs";
1
+ import { D as buildDoctorDiagnostics, O as doctorDiagnosticsTableRows, a as parseJsonSchema, i as JsonSchemaDefinitionSchema, k as formatDoctorDiagnosticsJson, n as createMigrationConfig, r as generateDrizzleConfig, s as generateDrizzleSchema, t as collectDoctorDiagnostics } from "./doctor-collector-SgMb2oQN.mjs";
2
2
 
3
3
  export { JsonSchemaDefinitionSchema, buildDoctorDiagnostics, collectDoctorDiagnostics, createMigrationConfig, doctorDiagnosticsTableRows, formatDoctorDiagnosticsJson, generateDrizzleConfig, generateDrizzleSchema, parseJsonSchema };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "aiex-cli",
3
3
  "type": "module",
4
- "version": "0.0.6-beta.3",
4
+ "version": "0.0.6",
5
5
  "description": "JSON Schema → SQLite with AI-powered data extraction",
6
6
  "author": "OSpoon <zxin088@gmail.com>",
7
7
  "license": "MIT",