aiex-cli 0.0.1-beta.29 → 0.0.1-beta.30
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 +4 -15
- package/dist/cli.mjs +95 -246
- package/dist/{completions-ygS1okck.mjs → completions-C3rmTwXZ.mjs} +2 -2
- package/dist/core/schema-sqlite/migrate-helper.mjs +12 -7
- package/dist/{doctor-collector-j2dG7dG1.mjs → doctor-collector-DhiJrVw5.mjs} +14 -6
- package/dist/index.mjs +1 -1
- package/dist/web/assets/{AISettings-Dn58ZHhM.js → AISettings-BjXxD5Ts.js} +1 -1
- package/dist/web/assets/DataBrowser-CwcTG80-.js +6 -0
- package/dist/web/assets/{ExtractionViewer-CTS1RXzc.js → ExtractionViewer-CsdK1kKK.js} +1 -1
- package/dist/web/assets/{JsonSchemaEditor-Dpgu6HPz.js → JsonSchemaEditor-BhY9BNOn.js} +15 -15
- package/dist/web/assets/{cssMode-BM5FOYIl.js → cssMode-CPThwItX.js} +1 -1
- package/dist/web/assets/dist-9yHVMqQ0.js +1 -0
- package/dist/web/assets/{editor.main-C2Q97Dkk.js → editor.main-BnOkwRFv.js} +2 -2
- package/dist/web/assets/{freemarker2-BqyJTCTn.js → freemarker2-DWDTYVJR.js} +1 -1
- package/dist/web/assets/{handlebars-DxRJTefg.js → handlebars-D4DzjGQ7.js} +1 -1
- package/dist/web/assets/{html-gyvgrapw.js → html-DnzhKSoD.js} +1 -1
- package/dist/web/assets/{htmlMode-CNjCRwdY.js → htmlMode-CR7UKfEH.js} +1 -1
- package/dist/web/assets/index-DCAKotsV.js +882 -0
- package/dist/web/assets/{javascript-BK6ufvq6.js → javascript-D2srszZ8.js} +1 -1
- package/dist/web/assets/{jsonMode-m2trGjkO.js → jsonMode-B4jaPYEr.js} +1 -1
- package/dist/web/assets/{liquid-BtyuYqQQ.js → liquid-CIT2Wl_l.js} +1 -1
- package/dist/web/assets/{mdx-C8K4EvCQ.js → mdx-CWLaEOFy.js} +1 -1
- package/dist/web/assets/{monaco.contribution-BTr-G8hO.js → monaco.contribution-DDv5ldfS.js} +2 -2
- package/dist/web/assets/{python-8dyH1nS_.js → python-6CGfpCNq.js} +1 -1
- package/dist/web/assets/{razor-DtWMI74k.js → razor-DEMMh3TD.js} +1 -1
- package/dist/web/assets/{tsMode-Dv8YG-YK.js → tsMode-Cm1NtjPs.js} +1 -1
- package/dist/web/assets/{typescript-DbClKYS3.js → typescript-BM9aPEFg.js} +1 -1
- package/dist/web/assets/{xml-Bb59gjP6.js → xml-CoSbvcg5.js} +1 -1
- package/dist/web/assets/{yaml-DVMb_IfV.js → yaml-56GOgy8k.js} +1 -1
- package/dist/web/index.html +4 -3
- package/package.json +8 -3
- package/src/core/schema-sqlite/migrate-helper.ts +6 -5
- package/dist/web/assets/DataBrowser-B6WECCZM.js +0 -6
- package/dist/web/assets/index-g2pWXPQZ.js +0 -882
- /package/dist/web/assets/{abap-DiwvWnMr.js → abap-Bgec7Keq.js} +0 -0
- /package/dist/web/assets/{apex-CmtZjKlf.js → apex-VBlPwEoQ.js} +0 -0
- /package/dist/web/assets/{api-client-CbQEkaKT.js → api-client-D2Y_-4JM.js} +0 -0
- /package/dist/web/assets/{azcli-DL2My_i-.js → azcli-DKqrEFBx.js} +0 -0
- /package/dist/web/assets/{bat-B-nC98wG.js → bat-DdgQWy_0.js} +0 -0
- /package/dist/web/assets/{bicep-Ju5MwOgh.js → bicep-CRMM43EB.js} +0 -0
- /package/dist/web/assets/{cameligo-8Eu1TyBr.js → cameligo-UatALtML.js} +0 -0
- /package/dist/web/assets/{clojure-u-RpMkH3.js → clojure-D8JU08RA.js} +0 -0
- /package/dist/web/assets/{coffee-CdA7bbTe.js → coffee-C56wu358.js} +0 -0
- /package/dist/web/assets/{cpp-CzNFP8ks.js → cpp-CyZLvhJG.js} +0 -0
- /package/dist/web/assets/{csharp-j1LThmcE.js → csharp-BJl3ixva.js} +0 -0
- /package/dist/web/assets/{csp-CLRC61y6.js → csp-CxEKxmO-.js} +0 -0
- /package/dist/web/assets/{css-r6rC_7P2.js → css-B0t_muXd.js} +0 -0
- /package/dist/web/assets/{cypher-CW08XVUh.js → cypher-D1hqiMFD.js} +0 -0
- /package/dist/web/assets/{dart-Cs9aL5T_.js → dart-Bz550Pyv.js} +0 -0
- /package/dist/web/assets/{dockerfile-BWM0M184.js → dockerfile-CIXgVAuA.js} +0 -0
- /package/dist/web/assets/{ecl-MJJuer5P.js → ecl-D9qbvZoA.js} +0 -0
- /package/dist/web/assets/{editor.api-nsOUOZde.js → editor.api-C8BHpRhn.js} +0 -0
- /package/dist/web/assets/{elixir-D2AIuXqn.js → elixir-b2M38fAy.js} +0 -0
- /package/dist/web/assets/{flow9-B2H24giC.js → flow9-Dq1UYMkt.js} +0 -0
- /package/dist/web/assets/{fsharp-CFNadkg7.js → fsharp-BaeLhgfq.js} +0 -0
- /package/dist/web/assets/{go-dSur1iB2.js → go-Bd-NFKIC.js} +0 -0
- /package/dist/web/assets/{graphql-qyhAo11d.js → graphql-DZVerJfy.js} +0 -0
- /package/dist/web/assets/{hcl-DFzjMyzm.js → hcl-CAVzrZfH.js} +0 -0
- /package/dist/web/assets/{ini-TdzA8TIl.js → ini-CyXdX58t.js} +0 -0
- /package/dist/web/assets/{java-CSGA9pkE.js → java-B5pNgvhy.js} +0 -0
- /package/dist/web/assets/{julia-9izz5OsY.js → julia-XRhmV3AN.js} +0 -0
- /package/dist/web/assets/{kotlin-DuPK7AtF.js → kotlin-DOd3J5vr.js} +0 -0
- /package/dist/web/assets/{less-B8d93iCg.js → less-veZSnyw6.js} +0 -0
- /package/dist/web/assets/{lexon-DWtEIyu7.js → lexon-QWGkuK0H.js} +0 -0
- /package/dist/web/assets/{lua-Ciq0OGgt.js → lua-CYGpjuO5.js} +0 -0
- /package/dist/web/assets/{m3-Cki6JWj_.js → m3-yNnrZkdc.js} +0 -0
- /package/dist/web/assets/{markdown-Cu47xwU0.js → markdown-BCSWEPSX.js} +0 -0
- /package/dist/web/assets/{mips-BM8ui995.js → mips-OpYmcC30.js} +0 -0
- /package/dist/web/assets/{msdax-DqLio0_c.js → msdax-2oxoTO9Z.js} +0 -0
- /package/dist/web/assets/{mysql-v1wbjJOq.js → mysql-5KlC-K_9.js} +0 -0
- /package/dist/web/assets/{objective-c-CQl3PGSB.js → objective-c-CcDCgtLx.js} +0 -0
- /package/dist/web/assets/{pascal-D4iW0ZtD.js → pascal-BZGsbaEV.js} +0 -0
- /package/dist/web/assets/{pascaligo-BdC9CZdj.js → pascaligo-DtD5qU3G.js} +0 -0
- /package/dist/web/assets/{perl-BL10m4XD.js → perl-C1jNNS3E.js} +0 -0
- /package/dist/web/assets/{pgsql-Be_oqVo3.js → pgsql-CT0fhiZa.js} +0 -0
- /package/dist/web/assets/{php-BtvXSFRI.js → php-D6DrXoPM.js} +0 -0
- /package/dist/web/assets/{pla-B2vUy15C.js → pla-b3-HN2pF.js} +0 -0
- /package/dist/web/assets/{postiats-CbmTTfXr.js → postiats-Bin2ApVS.js} +0 -0
- /package/dist/web/assets/{powerquery-DszLhJGx.js → powerquery-7ASnn-ZG.js} +0 -0
- /package/dist/web/assets/{powershell-B0dYktF6.js → powershell-t4p7sU1H.js} +0 -0
- /package/dist/web/assets/{preload-helper-DWTEM3RW.js → preload-helper-Dd-HcVz_.js} +0 -0
- /package/dist/web/assets/{protobuf-CZvaj1VX.js → protobuf-BUGeWa_j.js} +0 -0
- /package/dist/web/assets/{pug-CPDx1B3S.js → pug-BuKcgC9s.js} +0 -0
- /package/dist/web/assets/{qsharp-CAxMZVjw.js → qsharp-DxLLX8mo.js} +0 -0
- /package/dist/web/assets/{r-8DbbFX2l.js → r-DMlFgn7A.js} +0 -0
- /package/dist/web/assets/{redis-DRWj9MtJ.js → redis-cXItkC5u.js} +0 -0
- /package/dist/web/assets/{redshift-C6cElE_5.js → redshift-BZVbW7HE.js} +0 -0
- /package/dist/web/assets/{restructuredtext-W9pS9n3m.js → restructuredtext-BzjxwS8h.js} +0 -0
- /package/dist/web/assets/{ruby-BKnzWnk-.js → ruby-C5nyLV4l.js} +0 -0
- /package/dist/web/assets/{rust-YPCclWwe.js → rust-BcmMsHdf.js} +0 -0
- /package/dist/web/assets/{sb-BgM4DTFb.js → sb-Dnb1iy6B.js} +0 -0
- /package/dist/web/assets/{scala-fz1OPLMl.js → scala-anMIFYpA.js} +0 -0
- /package/dist/web/assets/{scheme-8Uz1RIbu.js → scheme-BItQTe08.js} +0 -0
- /package/dist/web/assets/{scss-Djo3IYXr.js → scss-BOv51BJ5.js} +0 -0
- /package/dist/web/assets/{select-DyjIzt-v.js → select-BGex2SPs.js} +0 -0
- /package/dist/web/assets/{shell-CINF5Tx_.js → shell-BsRYRTNN.js} +0 -0
- /package/dist/web/assets/{solidity-GgiNEuUm.js → solidity-BtuLgGDx.js} +0 -0
- /package/dist/web/assets/{sophia-Culj97P9.js → sophia-B0Vkc5MF.js} +0 -0
- /package/dist/web/assets/{sparql-C2ZlpxOY.js → sparql-B7lvkZQM.js} +0 -0
- /package/dist/web/assets/{sql-BEf5Pg7Y.js → sql-DvP5MpA3.js} +0 -0
- /package/dist/web/assets/{st-CT6UUoeH.js → st-GVUeyB3U.js} +0 -0
- /package/dist/web/assets/{swift-B5g0xTG3.js → swift-DSPIoCjm.js} +0 -0
- /package/dist/web/assets/{systemverilog-CEgQz9DR.js → systemverilog-Icj2-k23.js} +0 -0
- /package/dist/web/assets/{tcl-D0qL2L0I.js → tcl-Cd8KQcm-.js} +0 -0
- /package/dist/web/assets/{twig-BFUAVf1E.js → twig-CBHmt8z3.js} +0 -0
- /package/dist/web/assets/{typespec-CjVVcNKm.js → typespec-Ckc037mq.js} +0 -0
- /package/dist/web/assets/{vb-CZJr-DQz.js → vb-B97GW9Wb.js} +0 -0
- /package/dist/web/assets/{wgsl-ivoXUo2e.js → wgsl-DIKmb3YH.js} +0 -0
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ npm install -g aiex-cli
|
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
aiex
|
|
24
|
+
aiex web # configure schemas and AI settings in the browser
|
|
25
25
|
aiex schema # generate SQLite from JSON Schema files
|
|
26
26
|
aiex extract -s invoice -f invoice.pdf # extract data with AI and insert into database
|
|
27
27
|
```
|
|
@@ -41,17 +41,7 @@ aiex extract -s invoice -f invoice.pdf # extract data with AI and insert into d
|
|
|
41
41
|
|
|
42
42
|
## 🚀 Getting Started
|
|
43
43
|
|
|
44
|
-
### 1.
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
aiex schema --init
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
Creates a `.aiex/` directory with example schemas to get you started.
|
|
51
|
-
|
|
52
|
-
Add your own JSON Schema files to `.aiex/schema/` (one file per table), then run `aiex schema` to migrate them into the database.
|
|
53
|
-
|
|
54
|
-
### 2. Visual Editor
|
|
44
|
+
### 1. Configure In Web UI
|
|
55
45
|
|
|
56
46
|
```bash
|
|
57
47
|
aiex web
|
|
@@ -59,7 +49,7 @@ aiex web
|
|
|
59
49
|
|
|
60
50
|
Opens a browser UI where you can visually design and manage your schemas, configure AI settings, preview extraction prompts, and apply changes to the database.
|
|
61
51
|
|
|
62
|
-
###
|
|
52
|
+
### 2. Generate Database
|
|
63
53
|
|
|
64
54
|
```bash
|
|
65
55
|
aiex schema
|
|
@@ -67,7 +57,7 @@ aiex schema
|
|
|
67
57
|
|
|
68
58
|
Converts your JSON Schema files into a SQLite database with full migration support.
|
|
69
59
|
|
|
70
|
-
###
|
|
60
|
+
### 3. Extract Data
|
|
71
61
|
|
|
72
62
|
```bash
|
|
73
63
|
aiex extract # interactive mode (prompts for schema & input)
|
|
@@ -97,7 +87,6 @@ By default, aiex automatically selects a model based on your input type (vision-
|
|
|
97
87
|
|
|
98
88
|
| Command | Description |
|
|
99
89
|
| --- | --- |
|
|
100
|
-
| `aiex schema --init` | Scaffold `.aiex/` directory with example schemas |
|
|
101
90
|
| `aiex schema` | Parse JSON Schema files and migrate to SQLite |
|
|
102
91
|
| `aiex schema --generate` | Generate Drizzle schema code only (skip migration) |
|
|
103
92
|
| `aiex web` | Launch visual schema editor in browser |
|
package/dist/cli.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { C as doctorDiagnosticsTableRows, _ as seedConfig, a as parseJsonSchema, b as package_default, c as getDefaultAIConfig, d as DEFAULT_MINERU_CONFIG, f as DEFAULT_PROMPT_CONFIG, g as createConfig, h as AIConfigSchema, i as JsonSchemaDefinitionSchema, l as readAIConfig, m as PLACEHOLDER_TEXT, n as createMigrationConfig, o as toSnakeCase, p as PLACEHOLDER_SCHEMA, s as generateDrizzleSchema, t as collectDoctorDiagnostics, u as writeAIConfig, v as description, w as formatDoctorDiagnosticsJson, x as version, y as name } from "./doctor-collector-
|
|
1
|
+
import { C as doctorDiagnosticsTableRows, _ as seedConfig, a as parseJsonSchema, b as package_default, c as getDefaultAIConfig, d as DEFAULT_MINERU_CONFIG, f as DEFAULT_PROMPT_CONFIG, g as createConfig, h as AIConfigSchema, i as JsonSchemaDefinitionSchema, l as readAIConfig, m as PLACEHOLDER_TEXT, n as createMigrationConfig, o as toSnakeCase, p as PLACEHOLDER_SCHEMA, s as generateDrizzleSchema, t as collectDoctorDiagnostics, u as writeAIConfig, v as description, w as formatDoctorDiagnosticsJson, x as version, y as name } from "./doctor-collector-DhiJrVw5.mjs";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import fs from "node:fs/promises";
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import process from "node:process";
|
|
7
|
-
import {
|
|
7
|
+
import { readFile, writeFile } from "jsonfile";
|
|
8
|
+
import { ZodError, z } from "zod";
|
|
8
9
|
import { fileURLToPath } from "node:url";
|
|
9
10
|
import { defineCommand, runMain } from "citty";
|
|
10
11
|
import { consola } from "consola";
|
|
@@ -16,19 +17,23 @@ import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
|
|
|
16
17
|
import { LangfuseSpanProcessor } from "@langfuse/otel";
|
|
17
18
|
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
|
|
18
19
|
import { APICallError, Output, generateText, jsonSchema } from "ai";
|
|
20
|
+
import mime from "mime";
|
|
19
21
|
import pRetry from "p-retry";
|
|
22
|
+
import { jsonrepair } from "jsonrepair";
|
|
20
23
|
import fs$1 from "node:fs";
|
|
21
24
|
import Database from "better-sqlite3";
|
|
22
|
-
import
|
|
25
|
+
import { glob, globSync } from "tinyglobby";
|
|
23
26
|
import { execa } from "execa";
|
|
24
27
|
import { Buffer } from "node:buffer";
|
|
25
28
|
import { extractText, getMeta } from "unpdf";
|
|
26
29
|
import { execFile } from "node:child_process";
|
|
27
30
|
import { promisify } from "node:util";
|
|
28
31
|
import { serve } from "@hono/node-server";
|
|
32
|
+
import open from "open";
|
|
29
33
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
30
34
|
import { Hono } from "hono";
|
|
31
35
|
import { cors } from "hono/cors";
|
|
36
|
+
import { zValidator } from "@hono/zod-validator";
|
|
32
37
|
|
|
33
38
|
//#region src/core/schema-sqlite/helpers.ts
|
|
34
39
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -12806,6 +12811,15 @@ async function withRetry(fn, onRetry, maxRetries = 5) {
|
|
|
12806
12811
|
|
|
12807
12812
|
//#endregion
|
|
12808
12813
|
//#region src/core/ai-extraction/json-utils.ts
|
|
12814
|
+
function parseJsonLike(text$1) {
|
|
12815
|
+
const trimmed = text$1.trim();
|
|
12816
|
+
try {
|
|
12817
|
+
return JSON.parse(trimmed);
|
|
12818
|
+
} catch {
|
|
12819
|
+
if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) throw new SyntaxError("JSON candidate must start with an object or array");
|
|
12820
|
+
return JSON.parse(jsonrepair(trimmed));
|
|
12821
|
+
}
|
|
12822
|
+
}
|
|
12809
12823
|
function stripFences(text$1) {
|
|
12810
12824
|
const trimmed = text$1.trim();
|
|
12811
12825
|
if (!trimmed.startsWith("```")) return null;
|
|
@@ -12835,11 +12849,11 @@ function safeParseJSON(text$1) {
|
|
|
12835
12849
|
} catch {}
|
|
12836
12850
|
const fromFence = stripFences(cleaned);
|
|
12837
12851
|
if (fromFence) try {
|
|
12838
|
-
return
|
|
12852
|
+
return parseJsonLike(fromFence);
|
|
12839
12853
|
} catch {}
|
|
12840
12854
|
const extracted = extractFirstJSON(cleaned);
|
|
12841
12855
|
if (extracted) try {
|
|
12842
|
-
return
|
|
12856
|
+
return parseJsonLike(extracted);
|
|
12843
12857
|
} catch {}
|
|
12844
12858
|
const truncated = text$1.length > 200 ? `${text$1.slice(0, 200)}...` : text$1;
|
|
12845
12859
|
throw new Error(`Failed to parse JSON from model output. Expected a valid JSON object or array but received unparseable text. Raw output: ${truncated}`);
|
|
@@ -12974,37 +12988,22 @@ function initLangfuse(config) {
|
|
|
12974
12988
|
}
|
|
12975
12989
|
const SYSTEM_PROMPT_REGEX = /## System Prompt\n([\s\S]*?)(?=## User Prompt|$)/;
|
|
12976
12990
|
const USER_PROMPT_REGEX = /## User Prompt Template\n([\s\S]*)$/;
|
|
12977
|
-
const MIME_TYPES = {
|
|
12978
|
-
png: "image/png",
|
|
12979
|
-
jpg: "image/jpeg",
|
|
12980
|
-
jpeg: "image/jpeg",
|
|
12981
|
-
gif: "image/gif",
|
|
12982
|
-
webp: "image/webp",
|
|
12983
|
-
bmp: "image/bmp",
|
|
12984
|
-
svg: "image/svg+xml",
|
|
12985
|
-
pdf: "application/pdf",
|
|
12986
|
-
txt: "text/plain",
|
|
12987
|
-
csv: "text/csv",
|
|
12988
|
-
json: "application/json",
|
|
12989
|
-
md: "text/markdown",
|
|
12990
|
-
html: "text/html"
|
|
12991
|
-
};
|
|
12992
12991
|
function detectMimeType(filePath) {
|
|
12993
|
-
return
|
|
12992
|
+
return mime.getType(filePath) ?? "application/octet-stream";
|
|
12994
12993
|
}
|
|
12995
12994
|
async function readFilePart(filePath) {
|
|
12996
|
-
const mime = detectMimeType(filePath);
|
|
12995
|
+
const mime$1 = detectMimeType(filePath);
|
|
12997
12996
|
const buffer = await fs.readFile(filePath);
|
|
12998
12997
|
const name$1 = path.basename(filePath);
|
|
12999
|
-
if (mime.startsWith("image/")) return {
|
|
12998
|
+
if (mime$1.startsWith("image/")) return {
|
|
13000
12999
|
type: "image",
|
|
13001
13000
|
image: buffer,
|
|
13002
|
-
mimeType: mime
|
|
13001
|
+
mimeType: mime$1
|
|
13003
13002
|
};
|
|
13004
13003
|
return {
|
|
13005
13004
|
type: "file",
|
|
13006
13005
|
data: buffer,
|
|
13007
|
-
mediaType: mime,
|
|
13006
|
+
mediaType: mime$1,
|
|
13008
13007
|
filename: name$1
|
|
13009
13008
|
};
|
|
13010
13009
|
}
|
|
@@ -13210,7 +13209,10 @@ async function extractStructuredData(input) {
|
|
|
13210
13209
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
13211
13210
|
const outputFileName = `${schema.table.name}-${timestamp}.json`;
|
|
13212
13211
|
const outputPath = path.join(outputDir, outputFileName);
|
|
13213
|
-
await
|
|
13212
|
+
await writeFile(outputPath, data, {
|
|
13213
|
+
spaces: 2,
|
|
13214
|
+
EOL: "\n"
|
|
13215
|
+
});
|
|
13214
13216
|
return {
|
|
13215
13217
|
success: true,
|
|
13216
13218
|
outputPath,
|
|
@@ -13395,17 +13397,11 @@ async function pathExists(filePath) {
|
|
|
13395
13397
|
}
|
|
13396
13398
|
}
|
|
13397
13399
|
async function collectMarkdownFiles(dir) {
|
|
13398
|
-
|
|
13399
|
-
|
|
13400
|
-
|
|
13401
|
-
|
|
13402
|
-
|
|
13403
|
-
files.push(...await collectMarkdownFiles(entryPath));
|
|
13404
|
-
continue;
|
|
13405
|
-
}
|
|
13406
|
-
if (entry.isFile() && entry.name.toLowerCase().endsWith(".md")) files.push(entryPath);
|
|
13407
|
-
}
|
|
13408
|
-
return files.sort();
|
|
13400
|
+
return (await glob("**/*.md", {
|
|
13401
|
+
cwd: dir,
|
|
13402
|
+
absolute: true,
|
|
13403
|
+
onlyFiles: true
|
|
13404
|
+
})).sort();
|
|
13409
13405
|
}
|
|
13410
13406
|
async function selectMarkdownFile(outputDir, basename) {
|
|
13411
13407
|
const files = await collectMarkdownFiles(outputDir);
|
|
@@ -13551,6 +13547,7 @@ const SUPPORTED_EXTENSIONS = new Set([
|
|
|
13551
13547
|
"yml"
|
|
13552
13548
|
]);
|
|
13553
13549
|
const JSON_EXT_RE = /\.json$/;
|
|
13550
|
+
const SUPPORTED_FILE_PATTERN = `*.{${[...SUPPORTED_EXTENSIONS].join(",")}}`;
|
|
13554
13551
|
async function ensureDatabaseReady(dbPath, schema) {
|
|
13555
13552
|
try {
|
|
13556
13553
|
await fs.access(dbPath);
|
|
@@ -13571,22 +13568,20 @@ async function ensureDatabaseReady(dbPath, schema) {
|
|
|
13571
13568
|
return null;
|
|
13572
13569
|
}
|
|
13573
13570
|
function listSupportedFiles(dir, pattern) {
|
|
13574
|
-
|
|
13575
|
-
|
|
13576
|
-
|
|
13577
|
-
|
|
13578
|
-
|
|
13579
|
-
|
|
13580
|
-
|
|
13581
|
-
|
|
13582
|
-
}
|
|
13583
|
-
return files.sort();
|
|
13571
|
+
if (!fs$1.statSync(dir).isDirectory()) throw new Error(`Not a directory: ${dir}`);
|
|
13572
|
+
return globSync(pattern ?? SUPPORTED_FILE_PATTERN, {
|
|
13573
|
+
cwd: dir,
|
|
13574
|
+
absolute: true,
|
|
13575
|
+
onlyFiles: true
|
|
13576
|
+
}).filter((file) => {
|
|
13577
|
+
const ext = path.extname(file).toLowerCase().replace(".", "");
|
|
13578
|
+
return SUPPORTED_EXTENSIONS.has(ext);
|
|
13579
|
+
}).sort();
|
|
13584
13580
|
}
|
|
13585
13581
|
async function loadSchema(config, schemaName) {
|
|
13586
13582
|
const schemaPath = path.join(config.schemaPath, `${schemaName}.json`);
|
|
13587
13583
|
try {
|
|
13588
|
-
const
|
|
13589
|
-
const parsed = JSON.parse(content);
|
|
13584
|
+
const parsed = await readFile(schemaPath);
|
|
13590
13585
|
return { schema: JsonSchemaDefinitionSchema.parse(parsed) };
|
|
13591
13586
|
} catch (e) {
|
|
13592
13587
|
if (e instanceof ZodError) return {
|
|
@@ -13882,7 +13877,7 @@ const extractCommand = defineCommand({
|
|
|
13882
13877
|
async function runInteractive(aiexDir, config, aiConfig, modelOverride) {
|
|
13883
13878
|
const schemas = await listSchemas(aiexDir);
|
|
13884
13879
|
if (schemas.length === 0) {
|
|
13885
|
-
failCommand(`No schema files found in ${pc.cyan(".aiex/schema/")}. Run ${pc.cyan("aiex
|
|
13880
|
+
failCommand(`No schema files found in ${pc.cyan(".aiex/schema/")}. Run ${pc.cyan("aiex web")} to create and configure schemas first.`);
|
|
13886
13881
|
return false;
|
|
13887
13882
|
}
|
|
13888
13883
|
const schemaName = await select({
|
|
@@ -13974,131 +13969,9 @@ function cancel(msg) {
|
|
|
13974
13969
|
process.exitCode = 0;
|
|
13975
13970
|
}
|
|
13976
13971
|
|
|
13977
|
-
//#endregion
|
|
13978
|
-
//#region schemas/table-schema.json
|
|
13979
|
-
var $id = "https://raw.githubusercontent.com/OSpoon/aiex-cli/main/app/cli/schemas/table-schema.json";
|
|
13980
|
-
|
|
13981
13972
|
//#endregion
|
|
13982
13973
|
//#region src/core/schema-runner.ts
|
|
13983
|
-
const execFileAsync
|
|
13984
|
-
const EXAMPLE_SCORE_REPORT_SCHEMA = {
|
|
13985
|
-
$schema: $id,
|
|
13986
|
-
title: "ScoreReport",
|
|
13987
|
-
type: "object",
|
|
13988
|
-
table: {
|
|
13989
|
-
name: "score_report",
|
|
13990
|
-
timestamps: true
|
|
13991
|
-
},
|
|
13992
|
-
properties: {
|
|
13993
|
-
name: {
|
|
13994
|
-
type: "string",
|
|
13995
|
-
description: "姓名"
|
|
13996
|
-
},
|
|
13997
|
-
reportNumber: {
|
|
13998
|
-
type: "string",
|
|
13999
|
-
description: "报告编号"
|
|
14000
|
-
},
|
|
14001
|
-
gender: {
|
|
14002
|
-
type: "string",
|
|
14003
|
-
description: "性别"
|
|
14004
|
-
},
|
|
14005
|
-
printDate: {
|
|
14006
|
-
type: "string",
|
|
14007
|
-
format: "date-time",
|
|
14008
|
-
description: "打印日期"
|
|
14009
|
-
},
|
|
14010
|
-
examYear: {
|
|
14011
|
-
type: "integer",
|
|
14012
|
-
description: "考试年份"
|
|
14013
|
-
},
|
|
14014
|
-
examType: {
|
|
14015
|
-
type: "string",
|
|
14016
|
-
description: "考试类型,如全国统考"
|
|
14017
|
-
},
|
|
14018
|
-
examCategory: {
|
|
14019
|
-
type: "string",
|
|
14020
|
-
description: "考试类别,如普通高考"
|
|
14021
|
-
},
|
|
14022
|
-
province: {
|
|
14023
|
-
type: "string",
|
|
14024
|
-
description: "考试省份"
|
|
14025
|
-
},
|
|
14026
|
-
subjectCategory: {
|
|
14027
|
-
type: "string",
|
|
14028
|
-
description: "科类,如艺术(文)"
|
|
14029
|
-
},
|
|
14030
|
-
chinese: {
|
|
14031
|
-
type: "integer",
|
|
14032
|
-
description: "语文成绩"
|
|
14033
|
-
},
|
|
14034
|
-
chineseFull: {
|
|
14035
|
-
type: "integer",
|
|
14036
|
-
description: "语文满分"
|
|
14037
|
-
},
|
|
14038
|
-
math: {
|
|
14039
|
-
type: "integer",
|
|
14040
|
-
description: "数学成绩"
|
|
14041
|
-
},
|
|
14042
|
-
mathFull: {
|
|
14043
|
-
type: "integer",
|
|
14044
|
-
description: "数学满分"
|
|
14045
|
-
},
|
|
14046
|
-
foreignLang: {
|
|
14047
|
-
type: "integer",
|
|
14048
|
-
description: "外语成绩"
|
|
14049
|
-
},
|
|
14050
|
-
foreignLangFull: {
|
|
14051
|
-
type: "integer",
|
|
14052
|
-
description: "外语满分"
|
|
14053
|
-
},
|
|
14054
|
-
comprehensive: {
|
|
14055
|
-
type: "integer",
|
|
14056
|
-
description: "综合成绩"
|
|
14057
|
-
},
|
|
14058
|
-
comprehensiveFull: {
|
|
14059
|
-
type: "integer",
|
|
14060
|
-
description: "综合满分"
|
|
14061
|
-
},
|
|
14062
|
-
totalScore: {
|
|
14063
|
-
type: "integer",
|
|
14064
|
-
description: "总分"
|
|
14065
|
-
},
|
|
14066
|
-
totalFullScore: {
|
|
14067
|
-
type: "integer",
|
|
14068
|
-
description: "总分满分"
|
|
14069
|
-
},
|
|
14070
|
-
batchLineFirst: {
|
|
14071
|
-
type: "integer",
|
|
14072
|
-
description: "本科第一批录取分数线"
|
|
14073
|
-
},
|
|
14074
|
-
batchLineSecond: {
|
|
14075
|
-
type: "integer",
|
|
14076
|
-
description: "本科第二批录取分数线"
|
|
14077
|
-
}
|
|
14078
|
-
},
|
|
14079
|
-
required: [
|
|
14080
|
-
"name",
|
|
14081
|
-
"examYear",
|
|
14082
|
-
"examType",
|
|
14083
|
-
"province",
|
|
14084
|
-
"totalScore"
|
|
14085
|
-
]
|
|
14086
|
-
};
|
|
14087
|
-
async function writeJsonIfAbsent(filePath, data) {
|
|
14088
|
-
try {
|
|
14089
|
-
await fs.writeFile(filePath, `${JSON.stringify(data, null, 2)}\n`, { flag: "wx" });
|
|
14090
|
-
return "created";
|
|
14091
|
-
} catch (error) {
|
|
14092
|
-
if (error.code === "EEXIST") return "skipped";
|
|
14093
|
-
throw error;
|
|
14094
|
-
}
|
|
14095
|
-
}
|
|
14096
|
-
async function initSchemaProject(config) {
|
|
14097
|
-
await fs.mkdir(config.schemaPath, { recursive: true });
|
|
14098
|
-
await fs.mkdir(path.dirname(config.drizzleSchemaPath), { recursive: true });
|
|
14099
|
-
await fs.mkdir(config.migrationsPath, { recursive: true });
|
|
14100
|
-
return { scoreReportStatus: await writeJsonIfAbsent(path.join(config.schemaPath, "score_report.json"), EXAMPLE_SCORE_REPORT_SCHEMA) };
|
|
14101
|
-
}
|
|
13974
|
+
const execFileAsync = promisify(execFile);
|
|
14102
13975
|
async function listSchemaFiles(schemaDir) {
|
|
14103
13976
|
try {
|
|
14104
13977
|
return (await fs.readdir(schemaDir)).filter((f) => f.endsWith(".json")).map((f) => path.join(schemaDir, f)).sort();
|
|
@@ -14163,7 +14036,7 @@ async function runSchemaMigration(config, migrationName) {
|
|
|
14163
14036
|
];
|
|
14164
14037
|
if (migrationName) helperArgs.push(migrationName);
|
|
14165
14038
|
try {
|
|
14166
|
-
const { stdout, stderr } = await execFileAsync
|
|
14039
|
+
const { stdout, stderr } = await execFileAsync(process.execPath, helperArgs, { cwd: process.cwd() });
|
|
14167
14040
|
return parseMigrationOutput(stdout, stderr);
|
|
14168
14041
|
} catch (error) {
|
|
14169
14042
|
const execError = error;
|
|
@@ -14219,12 +14092,6 @@ const schemaCommand = defineCommand({
|
|
|
14219
14092
|
description: "Sync JSON Schema to SQLite database"
|
|
14220
14093
|
},
|
|
14221
14094
|
args: {
|
|
14222
|
-
init: {
|
|
14223
|
-
type: "boolean",
|
|
14224
|
-
alias: "i",
|
|
14225
|
-
description: "Only initialize .aiex/ directory with example schema",
|
|
14226
|
-
default: false
|
|
14227
|
-
},
|
|
14228
14095
|
generate: {
|
|
14229
14096
|
type: "boolean",
|
|
14230
14097
|
alias: "g",
|
|
@@ -14239,17 +14106,9 @@ const schemaCommand = defineCommand({
|
|
|
14239
14106
|
async run({ args }) {
|
|
14240
14107
|
intro(pc.inverse(" aiex schema "));
|
|
14241
14108
|
const config = createMigrationConfig(process.cwd());
|
|
14242
|
-
if (args.init) {
|
|
14243
|
-
const initResult = await initSchemaProject(config);
|
|
14244
|
-
consola.success(`Initialized ${pc.cyan(".aiex/")} with example schemas`);
|
|
14245
|
-
if (initResult.scoreReportStatus === "skipped") consola.warn(`${pc.cyan(".aiex/schema/score_report.json")} already exists, skipped`);
|
|
14246
|
-
consola.info("Example includes: ScoreReport (college entrance exam score report)");
|
|
14247
|
-
outro("Run: aiex schema");
|
|
14248
|
-
return;
|
|
14249
|
-
}
|
|
14250
14109
|
const schemaFiles = await listSchemaFiles(config.schemaPath);
|
|
14251
14110
|
if (schemaFiles.length === 0) {
|
|
14252
|
-
consola.info("
|
|
14111
|
+
consola.info(`Run ${pc.cyan("aiex web")} to create and configure schemas in the Web UI`);
|
|
14253
14112
|
failCommand(`No schema files found in ${pc.cyan(".aiex/schema/")}`);
|
|
14254
14113
|
return;
|
|
14255
14114
|
}
|
|
@@ -14348,10 +14207,22 @@ function aiRoutes(config) {
|
|
|
14348
14207
|
//#endregion
|
|
14349
14208
|
//#region src/server/routes/data.ts
|
|
14350
14209
|
const FILE_REGEX = /\.json$/;
|
|
14351
|
-
const EXTRACTION_FILE_RE = /^[\w.-]+\.json$/;
|
|
14352
|
-
const TABLE_NAME_RE$1 = /^[a-z][a-z0-9_]*$/;
|
|
14353
14210
|
const TIMESTAMP_CLEANUP = /(\d{2})-(\d{2})-(\d{2})/;
|
|
14354
14211
|
const TIMESTAMP_TZ = /(\d{3})Z/;
|
|
14212
|
+
const tableParamSchema = z.object({ name: z.string().regex(/^[a-z][a-z0-9_]*$/) });
|
|
14213
|
+
const extractionFileParamSchema = z.object({ name: z.string().regex(/^[\w.-]+\.json$/).refine((name$1) => name$1 === path.basename(name$1) && !name$1.includes("..")) });
|
|
14214
|
+
const tableQuerySchema = z.object({
|
|
14215
|
+
page: z.coerce.number().int().min(1).catch(1),
|
|
14216
|
+
pageSize: z.coerce.number().int().min(1).max(500).catch(50),
|
|
14217
|
+
search: z.string().catch(""),
|
|
14218
|
+
sortField: z.string().optional(),
|
|
14219
|
+
sortOrder: z.preprocess((value) => typeof value === "string" ? value.toLowerCase() : value, z.enum(["asc", "desc"]).catch("asc"))
|
|
14220
|
+
});
|
|
14221
|
+
function invalidParamResponse$1(message) {
|
|
14222
|
+
return (result, c) => {
|
|
14223
|
+
if (!result.success) return c.json({ error: message }, 400);
|
|
14224
|
+
};
|
|
14225
|
+
}
|
|
14355
14226
|
function dataRoutes(config) {
|
|
14356
14227
|
const app = new Hono();
|
|
14357
14228
|
const aiexDir = path.dirname(config.schemaPath);
|
|
@@ -14406,8 +14277,7 @@ function dataRoutes(config) {
|
|
|
14406
14277
|
}
|
|
14407
14278
|
const tables = [];
|
|
14408
14279
|
for (const file of schemaFiles) try {
|
|
14409
|
-
const
|
|
14410
|
-
const schema = JSON.parse(content);
|
|
14280
|
+
const schema = await readFile(path.join(schemaDir, file));
|
|
14411
14281
|
const tableName = schema.table?.name;
|
|
14412
14282
|
if (!tableName) continue;
|
|
14413
14283
|
tables.push({
|
|
@@ -14423,14 +14293,9 @@ function dataRoutes(config) {
|
|
|
14423
14293
|
return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);
|
|
14424
14294
|
}
|
|
14425
14295
|
});
|
|
14426
|
-
app.get("/data/tables/:name", async (c) => {
|
|
14427
|
-
const tableName = c.req.
|
|
14428
|
-
|
|
14429
|
-
const sortField = c.req.query("sortField");
|
|
14430
|
-
const sortOrder = c.req.query("sortOrder") || "asc";
|
|
14431
|
-
const page = Math.max(1, Number.parseInt(c.req.query("page") || "1", 10) || 1);
|
|
14432
|
-
const pageSize = Math.min(500, Math.max(1, Number.parseInt(c.req.query("pageSize") || "50", 10) || 50));
|
|
14433
|
-
const search = c.req.query("search") || "";
|
|
14296
|
+
app.get("/data/tables/:name", zValidator("param", tableParamSchema, invalidParamResponse$1("Invalid table name")), zValidator("query", tableQuerySchema), async (c) => {
|
|
14297
|
+
const { name: tableName } = c.req.valid("param");
|
|
14298
|
+
const { page, pageSize, search, sortField, sortOrder } = c.req.valid("query");
|
|
14434
14299
|
let db;
|
|
14435
14300
|
try {
|
|
14436
14301
|
db = new Database(config.databasePath, { readonly: true });
|
|
@@ -14449,7 +14314,7 @@ function dataRoutes(config) {
|
|
|
14449
14314
|
pk: !!col.pk
|
|
14450
14315
|
}));
|
|
14451
14316
|
let orderClause = "";
|
|
14452
|
-
if (sortField && columns.some((c$1) => c$1.name === sortField)) orderClause = ` ORDER BY \`${sortField}\` ${sortOrder
|
|
14317
|
+
if (sortField && columns.some((c$1) => c$1.name === sortField)) orderClause = ` ORDER BY \`${sortField}\` ${sortOrder === "desc" ? "DESC" : "ASC"}`;
|
|
14453
14318
|
let whereClause = "";
|
|
14454
14319
|
const queryParams = [];
|
|
14455
14320
|
if (search) whereClause = ` WHERE ${columns.map((col) => {
|
|
@@ -14474,9 +14339,8 @@ function dataRoutes(config) {
|
|
|
14474
14339
|
db.close();
|
|
14475
14340
|
}
|
|
14476
14341
|
});
|
|
14477
|
-
app.get("/data/:name", async (c) => {
|
|
14478
|
-
const name$1 = c.req.
|
|
14479
|
-
if (name$1 !== path.basename(name$1) || !EXTRACTION_FILE_RE.test(name$1) || name$1.includes("..")) return c.json({ error: "Invalid extraction file name" }, 400);
|
|
14342
|
+
app.get("/data/:name", zValidator("param", extractionFileParamSchema, invalidParamResponse$1("Invalid extraction file name")), async (c) => {
|
|
14343
|
+
const { name: name$1 } = c.req.valid("param");
|
|
14480
14344
|
const filePath = path.join(extractedDir, name$1);
|
|
14481
14345
|
try {
|
|
14482
14346
|
const content = await fs.readFile(filePath, "utf-8");
|
|
@@ -14494,11 +14358,13 @@ function dataRoutes(config) {
|
|
|
14494
14358
|
|
|
14495
14359
|
//#endregion
|
|
14496
14360
|
//#region src/server/routes/schema.ts
|
|
14497
|
-
const
|
|
14498
|
-
const
|
|
14499
|
-
|
|
14500
|
-
|
|
14501
|
-
return
|
|
14361
|
+
const schemaFileNameSchema = z.string().regex(/^[\w.-]+\.json$/).refine((name$1) => name$1 === path.basename(name$1) && !name$1.includes(".."));
|
|
14362
|
+
const schemaFileParamSchema = z.object({ name: schemaFileNameSchema });
|
|
14363
|
+
const tableNameParamSchema = z.object({ name: z.string().regex(/^[a-z][a-z0-9_]*$/) });
|
|
14364
|
+
function invalidParamResponse(message) {
|
|
14365
|
+
return (result, c) => {
|
|
14366
|
+
if (!result.success) return c.json({ error: message }, 400);
|
|
14367
|
+
};
|
|
14502
14368
|
}
|
|
14503
14369
|
function schemaRoutes(config) {
|
|
14504
14370
|
const app = new Hono();
|
|
@@ -14511,23 +14377,25 @@ function schemaRoutes(config) {
|
|
|
14511
14377
|
const jsonFiles = (await fs.readdir(schemaDir)).filter((f) => f.endsWith(".json"));
|
|
14512
14378
|
return c.json(jsonFiles);
|
|
14513
14379
|
});
|
|
14514
|
-
app.get("/schema/:name", async (c) => {
|
|
14515
|
-
const
|
|
14516
|
-
|
|
14380
|
+
app.get("/schema/:name", zValidator("param", schemaFileParamSchema, invalidParamResponse("Invalid schema file name")), async (c) => {
|
|
14381
|
+
const { name: name$1 } = c.req.valid("param");
|
|
14382
|
+
const filePath = path.join(schemaDir, name$1);
|
|
14517
14383
|
try {
|
|
14518
|
-
|
|
14519
|
-
return c.json(JSON.parse(content));
|
|
14384
|
+
return c.json(await readFile(filePath));
|
|
14520
14385
|
} catch {
|
|
14521
14386
|
return c.json({ error: "Schema not found" }, 404);
|
|
14522
14387
|
}
|
|
14523
14388
|
});
|
|
14524
|
-
app.post("/schema/:name", async (c) => {
|
|
14525
|
-
const
|
|
14526
|
-
|
|
14389
|
+
app.post("/schema/:name", zValidator("param", schemaFileParamSchema, invalidParamResponse("Invalid schema file name")), async (c) => {
|
|
14390
|
+
const { name: name$1 } = c.req.valid("param");
|
|
14391
|
+
const filePath = path.join(schemaDir, name$1);
|
|
14527
14392
|
try {
|
|
14528
14393
|
const body = await c.req.json();
|
|
14529
14394
|
await ensureDir();
|
|
14530
|
-
await
|
|
14395
|
+
await writeFile(filePath, body, {
|
|
14396
|
+
spaces: 2,
|
|
14397
|
+
EOL: "\n"
|
|
14398
|
+
});
|
|
14531
14399
|
const aiexDir = path.dirname(schemaDir);
|
|
14532
14400
|
try {
|
|
14533
14401
|
await savePromptSnapshot(JsonSchemaDefinitionSchema.parse(body), aiexDir);
|
|
@@ -14537,12 +14405,8 @@ function schemaRoutes(config) {
|
|
|
14537
14405
|
return c.json({ error: "Failed to save schema" }, 500);
|
|
14538
14406
|
}
|
|
14539
14407
|
});
|
|
14540
|
-
app.get("/prompt-snapshot/:name", async (c) => {
|
|
14541
|
-
const name$1 = c.req.
|
|
14542
|
-
if (!TABLE_NAME_RE.test(name$1)) return c.json({
|
|
14543
|
-
success: false,
|
|
14544
|
-
error: "Invalid table name"
|
|
14545
|
-
}, 400);
|
|
14408
|
+
app.get("/prompt-snapshot/:name", zValidator("param", tableNameParamSchema, invalidParamResponse("Invalid table name")), async (c) => {
|
|
14409
|
+
const { name: name$1 } = c.req.valid("param");
|
|
14546
14410
|
const aiexDir = path.dirname(schemaDir);
|
|
14547
14411
|
const snapshotPath = path.join(aiexDir, "extracted", `${name$1}.prompt.md`);
|
|
14548
14412
|
try {
|
|
@@ -14558,14 +14422,13 @@ function schemaRoutes(config) {
|
|
|
14558
14422
|
}, 404);
|
|
14559
14423
|
}
|
|
14560
14424
|
});
|
|
14561
|
-
app.delete("/schema/:name", async (c) => {
|
|
14562
|
-
const
|
|
14563
|
-
|
|
14425
|
+
app.delete("/schema/:name", zValidator("param", schemaFileParamSchema, invalidParamResponse("Invalid schema file name")), async (c) => {
|
|
14426
|
+
const { name: name$1 } = c.req.valid("param");
|
|
14427
|
+
const filePath = path.join(schemaDir, name$1);
|
|
14564
14428
|
try {
|
|
14565
14429
|
const aiexDir = path.dirname(schemaDir);
|
|
14566
14430
|
try {
|
|
14567
|
-
const
|
|
14568
|
-
const parsed = JsonSchemaDefinitionSchema.safeParse(JSON.parse(content));
|
|
14431
|
+
const parsed = JsonSchemaDefinitionSchema.safeParse(await readFile(filePath));
|
|
14569
14432
|
if (parsed.success) {
|
|
14570
14433
|
const tableName = parsed.data.table.name;
|
|
14571
14434
|
const snapshotPath = path.join(aiexDir, "extracted", `${tableName}.prompt.md`);
|
|
@@ -14645,25 +14508,11 @@ function createApp(config, staticDir) {
|
|
|
14645
14508
|
|
|
14646
14509
|
//#endregion
|
|
14647
14510
|
//#region src/core/web-runner.ts
|
|
14648
|
-
const execFileAsync = promisify(execFile);
|
|
14649
14511
|
function resolveWebStaticDir() {
|
|
14650
14512
|
return path.join(resolvePackageRoot(), "dist/web");
|
|
14651
14513
|
}
|
|
14652
14514
|
async function openBrowser(url) {
|
|
14653
|
-
|
|
14654
|
-
await execFileAsync("open", [url]);
|
|
14655
|
-
return;
|
|
14656
|
-
}
|
|
14657
|
-
if (process.platform === "win32") {
|
|
14658
|
-
await execFileAsync("cmd", [
|
|
14659
|
-
"/c",
|
|
14660
|
-
"start",
|
|
14661
|
-
"",
|
|
14662
|
-
url
|
|
14663
|
-
]);
|
|
14664
|
-
return;
|
|
14665
|
-
}
|
|
14666
|
-
await execFileAsync("xdg-open", [url]);
|
|
14515
|
+
await open(url);
|
|
14667
14516
|
}
|
|
14668
14517
|
async function startWebServer(input) {
|
|
14669
14518
|
const { config, port } = input;
|
|
@@ -14744,7 +14593,7 @@ process.on("unhandledRejection", (reason) => {
|
|
|
14744
14593
|
process.exit(1);
|
|
14745
14594
|
});
|
|
14746
14595
|
if (process.argv[2] === "_complete") {
|
|
14747
|
-
const { getCompletions } = await import("./completions-
|
|
14596
|
+
const { getCompletions } = await import("./completions-C3rmTwXZ.mjs");
|
|
14748
14597
|
const suggestions = getCompletions(subCommands, process.argv.slice(3));
|
|
14749
14598
|
for (const s of suggestions) process.stdout.write(`${s}\n`);
|
|
14750
14599
|
process.exit(0);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import process from "node:process";
|
|
3
|
+
import { readFileSync } from "jsonfile";
|
|
3
4
|
import fs from "node:fs";
|
|
4
5
|
|
|
5
6
|
//#region src/core/completions.ts
|
|
@@ -27,8 +28,7 @@ function getFileCompletions(pattern) {
|
|
|
27
28
|
}
|
|
28
29
|
function getJsonModelNames(configPath) {
|
|
29
30
|
try {
|
|
30
|
-
const
|
|
31
|
-
const config = JSON.parse(content);
|
|
31
|
+
const config = readFileSync(configPath);
|
|
32
32
|
if (config.provider?.models) return config.provider.models.map((m) => m.name);
|
|
33
33
|
} catch {}
|
|
34
34
|
return [];
|