aiex-cli 0.0.4-beta.3 → 0.0.4-beta.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/dist/cli.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { A as formatDoctorDiagnosticsJson, C as seedConfig, D as version, E as package_default, S as createConfig, T as name, _ as DEFAULT_MINERU_CONFIG, a as parseJsonSchema, b as PLACEHOLDER_TEXT, c as recognizeImageText, d as t, f as getDefaultAIConfig, g as DEFAULT_MARKITDOWN_CONFIG, h as DEFAULT_MARKER_CONFIG, i as JsonSchemaDefinitionSchema, k as doctorDiagnosticsTableRows, l as shouldUseImageOcrFallback, m as writeAIConfig, n as createMigrationConfig, o as toSnakeCase, p as readAIConfig, s as generateDrizzleSchema, t as collectDoctorDiagnostics, u as initI18n, v as DEFAULT_PROMPT_CONFIG, w as description, x as AIConfigSchema, y as PLACEHOLDER_SCHEMA } from "./doctor-collector-8fLyh9lK.mjs";
1
+ import { A as formatDoctorDiagnosticsJson, C as seedConfig, D as version, E as package_default, S as createConfig, T as name, _ as DEFAULT_MINERU_CONFIG, a as parseJsonSchema, b as PLACEHOLDER_TEXT, c as recognizeImageText, d as t, f as getDefaultAIConfig, g as DEFAULT_MARKITDOWN_CONFIG, h as DEFAULT_MARKER_CONFIG, i as JsonSchemaDefinitionSchema, k as doctorDiagnosticsTableRows, l as shouldUseImageOcrFallback, m as writeAIConfig, n as createMigrationConfig, o as toSnakeCase, p as readAIConfig, s as generateDrizzleSchema, t as collectDoctorDiagnostics, u as initI18n, v as DEFAULT_PROMPT_CONFIG, w as description, x as AIConfigSchema, y as PLACEHOLDER_SCHEMA } from "./doctor-collector-BtEPFDoa.mjs";
2
2
  import { createRequire } from "node:module";
3
3
  import fs from "node:fs/promises";
4
4
  import os from "node:os";
@@ -12,7 +12,7 @@ import { consola } from "consola";
12
12
  import updateNotifier from "update-notifier";
13
13
  import CliTable3 from "cli-table3";
14
14
  import fs$1 from "node:fs";
15
- import { intro, isCancel, outro, select, spinner, text } from "@clack/prompts";
15
+ import { confirm, intro, isCancel, outro, select, spinner, text } from "@clack/prompts";
16
16
  import Database from "better-sqlite3";
17
17
  import pc from "picocolors";
18
18
  import { Buffer } from "node:buffer";
@@ -13940,9 +13940,9 @@ async function triggerWebhook(aiConfig, auditId, schemaName, event, source, data
13940
13940
  error,
13941
13941
  tokensUsed
13942
13942
  });
13943
- if (!quiet) consola.success(t("extract.file.webhookSynced"));
13943
+ if (!quiet) consola.success(t("command.extract.file.webhookSynced"));
13944
13944
  } catch (err) {
13945
- if (!quiet) consola.error(t("extract.file.webhookSyncFail", { error: err instanceof Error ? err.message : String(err) }));
13945
+ if (!quiet) consola.error(t("command.extract.file.webhookSyncFail", { error: err instanceof Error ? err.message : String(err) }));
13946
13946
  }
13947
13947
  }
13948
13948
 
@@ -14218,7 +14218,7 @@ async function readExtractFileInput(filePath, aiConfig, modelOverride) {
14218
14218
  if (FILE_PART_EXTENSIONS.has(ext)) {
14219
14219
  if (shouldUseImageOcrFallback(aiConfig, modelOverride)) {
14220
14220
  const result = await recognizeImageText(filePath, aiConfig?.image);
14221
- consola.info(t("extract.file.ocrText", { confidence: (result.confidence * 100).toFixed(1) }));
14221
+ consola.info(t("command.extract.file.ocrText", { confidence: (result.confidence * 100).toFixed(1) }));
14222
14222
  return { text: result.text };
14223
14223
  }
14224
14224
  return {
@@ -14230,19 +14230,19 @@ async function readExtractFileInput(filePath, aiConfig, modelOverride) {
14230
14230
  const buffer = await fs.readFile(filePath);
14231
14231
  const converter = createPdfConverter(aiConfig?.pdf);
14232
14232
  const result = await converter.convert(buffer, filePath);
14233
- if (result.metadata?.fallback === "true") consola.info(t("extract.file.pdfFallback", { count: result.pageCount }));
14234
- else consola.info(t("extract.file.pdfConverted", {
14233
+ if (result.metadata?.fallback === "true") consola.info(t("command.extract.file.pdfFallback", { count: result.pageCount }));
14234
+ else consola.info(t("command.extract.file.pdfConverted", {
14235
14235
  name: converter.name,
14236
14236
  count: result.pageCount
14237
14237
  }));
14238
14238
  const mdPath = filePath.replace(PDF_EXT_RE, ".md");
14239
14239
  try {
14240
14240
  await fs.writeFile(mdPath, result.text);
14241
- consola.info(t("extract.file.markdownSaved", { path: mdPath }));
14241
+ consola.info(t("command.extract.file.markdownSaved", { path: mdPath }));
14242
14242
  } catch {
14243
14243
  const fallbackMd = path.join(os.tmpdir(), `${path.basename(filePath, ".pdf")}.md`);
14244
14244
  await fs.writeFile(fallbackMd, result.text);
14245
- consola.info(t("extract.file.markdownSaved", { path: fallbackMd }));
14245
+ consola.info(t("command.extract.file.markdownSaved", { path: fallbackMd }));
14246
14246
  }
14247
14247
  return { text: result.text };
14248
14248
  }
@@ -14291,13 +14291,13 @@ async function processOneFile(aiexDir, config, aiConfig, schemaName, filePath, m
14291
14291
  quiet: false
14292
14292
  });
14293
14293
  if (result.success) {
14294
- if (!result.skipped) consola.success(t("extract.file.processSuccess", { file: path.basename(filePath) }));
14294
+ if (!result.skipped) consola.success(t("command.extract.file.processSuccess", { file: path.basename(filePath) }));
14295
14295
  return true;
14296
14296
  }
14297
14297
  return false;
14298
14298
  }
14299
14299
  async function runBatchExtraction(aiexDir, config, aiConfig, schemaName, dir, globPattern, modelOverride, options) {
14300
- consola.info(t("extract.batch.scanning", { dir: pc.cyan(dir) }));
14300
+ consola.info(t("command.extract.batch.scanning", { dir: pc.cyan(dir) }));
14301
14301
  let files;
14302
14302
  try {
14303
14303
  files = listSupportedFiles(dir, globPattern);
@@ -14306,21 +14306,21 @@ async function runBatchExtraction(aiexDir, config, aiConfig, schemaName, dir, gl
14306
14306
  ok: false,
14307
14307
  successCount: 0,
14308
14308
  failCount: 0,
14309
- error: t("extract.batch.errors.cannotReadDir", { dir })
14309
+ error: t("command.extract.batch.errors.cannotReadDir", { dir })
14310
14310
  };
14311
14311
  }
14312
14312
  if (files.length === 0) return {
14313
14313
  ok: false,
14314
14314
  successCount: 0,
14315
14315
  failCount: 0,
14316
- error: t("extract.batch.errors.noSupportedFiles", { dir })
14316
+ error: t("command.extract.batch.errors.noSupportedFiles", { dir })
14317
14317
  };
14318
- consola.info(t("extract.batch.found", { count: files.length }));
14318
+ consola.info(t("command.extract.batch.found", { count: files.length }));
14319
14319
  let successCount = 0;
14320
14320
  let failCount = 0;
14321
14321
  for (let i = 0; i < files.length; i++) {
14322
14322
  const file = files[i];
14323
- consola.info(`\n${t("extract.batch.processing", {
14323
+ consola.info(`\n${t("command.extract.batch.processing", {
14324
14324
  current: i + 1,
14325
14325
  total: files.length,
14326
14326
  file: pc.cyan(path.basename(file))
@@ -14331,7 +14331,7 @@ async function runBatchExtraction(aiexDir, config, aiConfig, schemaName, dir, gl
14331
14331
  })) successCount++;
14332
14332
  else failCount++;
14333
14333
  }
14334
- consola.info(`\n${t("extract.batch.complete", {
14334
+ consola.info(`\n${t("command.extract.batch.complete", {
14335
14335
  success: pc.green(successCount),
14336
14336
  fail: pc.red(failCount),
14337
14337
  total: files.length
@@ -14416,7 +14416,7 @@ async function extractSingle(aiexDir, config, aiConfig, schemaName, text$1, file
14416
14416
  };
14417
14417
  }
14418
14418
  const s = spinner();
14419
- if (!options?.quiet) s.start(filePath ? t("extract.file.extractedFrom", { file: path.basename(filePath) }) : t("extract.file.extracting"));
14419
+ if (!options?.quiet) s.start(filePath ? t("command.extract.file.extractedFrom", { file: path.basename(filePath) }) : t("command.extract.file.extracting"));
14420
14420
  const result = await extractStructuredData({
14421
14421
  config: aiConfig,
14422
14422
  schema: schemaLoad.schema,
@@ -14425,7 +14425,7 @@ async function extractSingle(aiexDir, config, aiConfig, schemaName, text$1, file
14425
14425
  file: filePath,
14426
14426
  modelOverride,
14427
14427
  onRetry(info) {
14428
- if (!options?.quiet) s.message(t("extract.file.extractRetry", {
14428
+ if (!options?.quiet) s.message(t("command.extract.file.extractRetry", {
14429
14429
  code: info.statusCode,
14430
14430
  delay: info.delayMs / 1e3,
14431
14431
  attempt: info.attempt,
@@ -14435,7 +14435,7 @@ async function extractSingle(aiexDir, config, aiConfig, schemaName, text$1, file
14435
14435
  });
14436
14436
  if (!result.success) {
14437
14437
  if (!options?.quiet) {
14438
- s.stop(t("extract.file.extractFail"));
14438
+ s.stop(t("command.extract.file.extractFail"));
14439
14439
  consola.error(result.error || t("common.unknownError"));
14440
14440
  }
14441
14441
  return {
@@ -14443,19 +14443,19 @@ async function extractSingle(aiexDir, config, aiConfig, schemaName, text$1, file
14443
14443
  error: result.error || t("common.unknownError")
14444
14444
  };
14445
14445
  }
14446
- if (!options?.quiet) s.stop(t("extract.file.extractComplete"));
14447
- if (result.outputPath && !options?.quiet) consola.success(t("extract.file.resultSaved", { path: pc.cyan(result.outputPath) }));
14448
- if (result.tokensUsed && !options?.quiet) consola.info(pc.gray(t("extract.file.tokenUsage", {
14446
+ if (!options?.quiet) s.stop(t("command.extract.file.extractComplete"));
14447
+ if (result.outputPath && !options?.quiet) consola.success(t("command.extract.file.resultSaved", { path: pc.cyan(result.outputPath) }));
14448
+ if (result.tokensUsed && !options?.quiet) consola.info(pc.gray(t("command.extract.file.tokenUsage", {
14449
14449
  prompt: result.tokensUsed.prompt,
14450
14450
  completion: result.tokensUsed.completion,
14451
14451
  total: result.tokensUsed.total
14452
14452
  })));
14453
14453
  if (result.data && options?.insert !== false) {
14454
14454
  const s2 = spinner();
14455
- if (!options?.quiet) s2.start(t("extract.file.insertingDb"));
14455
+ if (!options?.quiet) s2.start(t("command.extract.file.insertingDb"));
14456
14456
  const dbError = await ensureDatabaseReady(config.databasePath, schemaLoad.schema);
14457
14457
  if (dbError) {
14458
- if (!options?.quiet) s2.stop(t("extract.file.dbNotReady"));
14458
+ if (!options?.quiet) s2.stop(t("command.extract.file.dbNotReady"));
14459
14459
  consola.error(dbError);
14460
14460
  return {
14461
14461
  success: false,
@@ -14467,7 +14467,7 @@ async function extractSingle(aiexDir, config, aiConfig, schemaName, text$1, file
14467
14467
  try {
14468
14468
  const insertResult = insertExtractedData(db, schemaLoad.schema, result.data);
14469
14469
  if (insertResult.success) {
14470
- if (!options?.quiet) s2.stop(t("extract.file.insertedTables", { count: insertResult.tablesInserted.length }));
14470
+ if (!options?.quiet) s2.stop(t("command.extract.file.insertedTables", { count: insertResult.tablesInserted.length }));
14471
14471
  return {
14472
14472
  success: true,
14473
14473
  outputPath: result.outputPath,
@@ -14476,7 +14476,7 @@ async function extractSingle(aiexDir, config, aiConfig, schemaName, text$1, file
14476
14476
  tokensUsed: result.tokensUsed
14477
14477
  };
14478
14478
  } else {
14479
- if (!options?.quiet) s2.stop(t("extract.file.dbInsertFail"));
14479
+ if (!options?.quiet) s2.stop(t("command.extract.file.dbInsertFail"));
14480
14480
  consola.error(insertResult.error || t("common.unknownError"));
14481
14481
  return {
14482
14482
  success: false,
@@ -14487,7 +14487,7 @@ async function extractSingle(aiexDir, config, aiConfig, schemaName, text$1, file
14487
14487
  db.close();
14488
14488
  }
14489
14489
  } catch (e) {
14490
- if (!options?.quiet) s2.stop(t("extract.file.dbInsertFail"));
14490
+ if (!options?.quiet) s2.stop(t("command.extract.file.dbInsertFail"));
14491
14491
  consola.error(e instanceof Error ? e.message : String(e));
14492
14492
  return {
14493
14493
  success: false,
@@ -14521,7 +14521,7 @@ async function runAuditedExtraction(options) {
14521
14521
  try {
14522
14522
  fileHash = await getFileHash(source.filePath);
14523
14523
  } catch (e) {
14524
- if (!quiet) consola.warn(t("extract.file.hashWarning", {
14524
+ if (!quiet) consola.warn(t("command.extract.file.hashWarning", {
14525
14525
  file: path.basename(source.filePath),
14526
14526
  error: e instanceof Error ? e.message : String(e)
14527
14527
  }));
@@ -14529,7 +14529,7 @@ async function runAuditedExtraction(options) {
14529
14529
  if (fileHash && !isPlainTextFile && !force) {
14530
14530
  const existing = await findSucceededAuditByHash(aiexDir, schemaName, fileHash);
14531
14531
  if (existing) {
14532
- if (!quiet) consola.info(t("extract.file.alreadyProcessed", {
14532
+ if (!quiet) consola.info(t("command.extract.file.alreadyProcessed", {
14533
14533
  file: pc.cyan(path.basename(source.filePath)),
14534
14534
  hash: fileHash.slice(0, 8)
14535
14535
  }));
@@ -14577,7 +14577,7 @@ async function runAuditedExtraction(options) {
14577
14577
  let notionPages;
14578
14578
  if (shouldSyncNotion(aiConfig, schemaName)) try {
14579
14579
  notionPages = await syncResultToNotion(aiConfig, schemaName, r.data);
14580
- if (!quiet) consola.success(t("extract.file.notionSynced", { count: notionPages.length }));
14580
+ if (!quiet) consola.success(t("command.extract.file.notionSynced", { count: notionPages.length }));
14581
14581
  } catch (error) {
14582
14582
  await updateExtractionAuditRecord(aiexDir, audit.id, {
14583
14583
  status: "failed",
@@ -14587,7 +14587,7 @@ async function runAuditedExtraction(options) {
14587
14587
  tokensUsed: r.tokensUsed,
14588
14588
  error: error instanceof Error ? error.message : String(error)
14589
14589
  });
14590
- if (!quiet) consola.error(t("extract.file.notionSyncFail", { error: error instanceof Error ? error.message : String(error) }));
14590
+ if (!quiet) consola.error(t("command.extract.file.notionSyncFail", { error: error instanceof Error ? error.message : String(error) }));
14591
14591
  await triggerWebhook(aiConfig, audit.id, schemaName, "extraction.failed", source, r.data, error instanceof Error ? error.message : String(error), r.tokensUsed, quiet);
14592
14592
  return {
14593
14593
  success: false,
@@ -14620,7 +14620,7 @@ async function runAuditedExtraction(options) {
14620
14620
  status: "failed",
14621
14621
  error: r.error || "Extraction failed"
14622
14622
  });
14623
- if (!quiet) consola.error(t("extract.file.extractionFailed", { error: r.error }));
14623
+ if (!quiet) consola.error(t("command.extract.file.extractionFailed", { error: r.error }));
14624
14624
  await triggerWebhook(aiConfig, audit.id, schemaName, "extraction.failed", source, void 0, r.error || "Extraction failed", void 0, quiet);
14625
14625
  return {
14626
14626
  success: false,
@@ -14636,7 +14636,7 @@ async function runAuditedExtraction(options) {
14636
14636
  });
14637
14637
  if (!quiet) {
14638
14638
  const name$1 = source.type === "file" ? path.basename(source.filePath) : "text input";
14639
- consola.error(t("extract.file.errorProcessing", {
14639
+ consola.error(t("command.extract.file.errorProcessing", {
14640
14640
  name: name$1,
14641
14641
  error: e instanceof Error ? e.message : String(e)
14642
14642
  }));
@@ -15144,6 +15144,15 @@ async function runInteractive(aiexDir, config, aiConfig, modelOverride) {
15144
15144
  cancel(t("common.cancelled"));
15145
15145
  return false;
15146
15146
  }
15147
+ const fp = filePathStr;
15148
+ const force = await confirm({
15149
+ message: t("command.extract.interactive.askForce"),
15150
+ initialValue: false
15151
+ });
15152
+ if (isCancel(force)) {
15153
+ cancel(t("common.cancelled"));
15154
+ return false;
15155
+ }
15147
15156
  return (await runAuditedExtraction({
15148
15157
  aiexDir,
15149
15158
  config,
@@ -15151,9 +15160,10 @@ async function runInteractive(aiexDir, config, aiConfig, modelOverride) {
15151
15160
  schemaName,
15152
15161
  source: {
15153
15162
  type: "file",
15154
- filePath: filePathStr
15163
+ filePath: fp
15155
15164
  },
15156
- modelOverride
15165
+ modelOverride,
15166
+ force
15157
15167
  })).success;
15158
15168
  } else if (inputSource === "dir") {
15159
15169
  const dirPath = await text({
@@ -15166,7 +15176,15 @@ async function runInteractive(aiexDir, config, aiConfig, modelOverride) {
15166
15176
  cancel(t("common.cancelled"));
15167
15177
  return false;
15168
15178
  }
15169
- const result = await runBatchExtraction(aiexDir, config, aiConfig, schemaName, dirPath, void 0, modelOverride);
15179
+ const force = await confirm({
15180
+ message: t("command.extract.interactive.askForce"),
15181
+ initialValue: false
15182
+ });
15183
+ if (isCancel(force)) {
15184
+ cancel(t("common.cancelled"));
15185
+ return false;
15186
+ }
15187
+ const result = await runBatchExtraction(aiexDir, config, aiConfig, schemaName, dirPath, void 0, modelOverride, { force });
15170
15188
  if (!result.ok) failCommand(result.error);
15171
15189
  return result.ok && result.failCount === 0;
15172
15190
  }
@@ -74,7 +74,7 @@ function doctorDiagnosticsTableRows(d) {
74
74
  //#endregion
75
75
  //#region package.json
76
76
  var name = "aiex-cli";
77
- var version = "0.0.4-beta.3";
77
+ var version = "0.0.4-beta.5";
78
78
  var description = "JSON Schema → SQLite with AI-powered data extraction";
79
79
  var package_default = {
80
80
  name,
@@ -490,7 +490,8 @@ const en = {
490
490
  enterFilePath: "Enter file path:",
491
491
  enterDirPath: "Enter directory path:",
492
492
  filePathRequired: "Please enter a file path",
493
- dirPathRequired: "Please enter a directory path"
493
+ dirPathRequired: "Please enter a directory path",
494
+ askForce: "Force re-extraction of already processed files?"
494
495
  },
495
496
  errors: {
496
497
  noAIConfig: "AI configuration not found. Please run \"{{cmd}}\" to configure AI settings first",
@@ -939,7 +940,7 @@ async function initI18n(lng) {
939
940
  fallbackLng: "en",
940
941
  resources: {
941
942
  "en": { translation: en },
942
- "zh-CN": { translation: await import("./zh-CN-B5QVQVm-.mjs").then((m) => m.zhCN) }
943
+ "zh-CN": { translation: await import("./zh-CN-BZihcLn3.mjs").then((m) => m.zhCN) }
943
944
  },
944
945
  interpolation: { escapeValue: false },
945
946
  returnNull: false
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { A as formatDoctorDiagnosticsJson, O as buildDoctorDiagnostics, a as parseJsonSchema, i as JsonSchemaDefinitionSchema, k as doctorDiagnosticsTableRows, n as createMigrationConfig, r as generateDrizzleConfig, s as generateDrizzleSchema, t as collectDoctorDiagnostics } from "./doctor-collector-8fLyh9lK.mjs";
1
+ import { A as formatDoctorDiagnosticsJson, O as buildDoctorDiagnostics, a as parseJsonSchema, i as JsonSchemaDefinitionSchema, k as doctorDiagnosticsTableRows, n as createMigrationConfig, r as generateDrizzleConfig, s as generateDrizzleSchema, t as collectDoctorDiagnostics } from "./doctor-collector-BtEPFDoa.mjs";
2
2
 
3
3
  export { JsonSchemaDefinitionSchema, buildDoctorDiagnostics, collectDoctorDiagnostics, createMigrationConfig, doctorDiagnosticsTableRows, formatDoctorDiagnosticsJson, generateDrizzleConfig, generateDrizzleSchema, parseJsonSchema };
@@ -64,7 +64,8 @@ const zhCN = {
64
64
  enterFilePath: "输入文件路径:",
65
65
  enterDirPath: "输入目录路径:",
66
66
  filePathRequired: "请输入文件路径",
67
- dirPathRequired: "请输入目录路径"
67
+ dirPathRequired: "请输入目录路径",
68
+ askForce: "是否强制重新抽取已成功处理过的文件?"
68
69
  },
69
70
  errors: {
70
71
  noAIConfig: "未找到 AI 配置,请运行 \"{{cmd}}\" 先配置 AI 设置",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "aiex-cli",
3
3
  "type": "module",
4
- "version": "0.0.4-beta.3",
4
+ "version": "0.0.4-beta.5",
5
5
  "description": "JSON Schema → SQLite with AI-powered data extraction",
6
6
  "author": "OSpoon <zxin088@gmail.com>",
7
7
  "license": "MIT",