@thinkingai/ae-cli 6.1.16 → 6.1.17
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 +5 -2
- package/README.zh.md +5 -2
- package/dist/{data-integration-2MYMANJI.js → data-integration-XQYB4X4F.js} +141 -21
- package/dist/index.js +2 -2
- package/dist/{te-kb-APXBWBDY.js → te-kb-SQCLHG6X.js} +245 -121
- package/package.json +2 -1
- package/skills/ae-data-integration/references/source-inspect.md +14 -1
- package/skills/ae-kb/SKILL.md +55 -50
- package/skills/ae-kb/references/query-workflow.md +112 -0
- package/skills/ae-kb-discovery/SKILL.md +105 -0
package/README.md
CHANGED
|
@@ -200,7 +200,10 @@ ae-cli kb +add --name engineering-handbook --files '["./docs/guide.md","https://
|
|
|
200
200
|
ae-cli kb +schema --name engineering-handbook
|
|
201
201
|
ae-cli kb +compile --name engineering-handbook
|
|
202
202
|
ae-cli kb +status --name engineering-handbook
|
|
203
|
-
ae-cli kb +
|
|
203
|
+
ae-cli kb +ask -q "How is the sandbox configured?"
|
|
204
|
+
# Submit only, poll later:
|
|
205
|
+
ae-cli kb +ask -q "Another question" --no-wait
|
|
206
|
+
ae-cli kb +ask-status --execution-id <id>
|
|
204
207
|
```
|
|
205
208
|
|
|
206
209
|
External Agents can use deterministic retrieval without a server-side LLM:
|
|
@@ -208,7 +211,7 @@ External Agents can use deterministic retrieval without a server-side LLM:
|
|
|
208
211
|
```bash
|
|
209
212
|
ae-cli kb +list
|
|
210
213
|
ae-cli kb +index --sources '[{"scope":"company","name":"engineering-handbook"}]'
|
|
211
|
-
ae-cli kb +grep -q "sandbox config" --sources '[{"scope":"company","name":"engineering-handbook"}]'
|
|
214
|
+
ae-cli kb +grep -q "sandbox config" --sources '[{"scope":"company","name":"engineering-handbook"}]' --paths '["wiki/sandbox.md"]'
|
|
212
215
|
ae-cli kb +read --source '{"scope":"company","name":"engineering-handbook"}' --path "wiki/sandbox.md"
|
|
213
216
|
```
|
|
214
217
|
|
package/README.zh.md
CHANGED
|
@@ -200,7 +200,10 @@ ae-cli kb +add --name engineering-handbook --files '["./docs/guide.md","https://
|
|
|
200
200
|
ae-cli kb +schema --name engineering-handbook
|
|
201
201
|
ae-cli kb +compile --name engineering-handbook
|
|
202
202
|
ae-cli kb +status --name engineering-handbook
|
|
203
|
-
ae-cli kb +
|
|
203
|
+
ae-cli kb +ask -q "如何配置沙盒?"
|
|
204
|
+
# 仅提交,后续轮询:
|
|
205
|
+
ae-cli kb +ask -q "另一个问题" --no-wait
|
|
206
|
+
ae-cli kb +ask-status --execution-id <id>
|
|
204
207
|
```
|
|
205
208
|
|
|
206
209
|
外部 Agent 可以使用不依赖服务端 LLM 的确定性检索:
|
|
@@ -208,7 +211,7 @@ ae-cli kb +query -q "如何配置沙盒?" --top-k 10
|
|
|
208
211
|
```bash
|
|
209
212
|
ae-cli kb +list
|
|
210
213
|
ae-cli kb +index --sources '[{"scope":"company","name":"engineering-handbook"}]'
|
|
211
|
-
ae-cli kb +grep -q "沙盒配置" --sources '[{"scope":"company","name":"engineering-handbook"}]'
|
|
214
|
+
ae-cli kb +grep -q "沙盒配置" --sources '[{"scope":"company","name":"engineering-handbook"}]' --paths '["wiki/sandbox.md"]'
|
|
212
215
|
ae-cli kb +read --source '{"scope":"company","name":"engineering-handbook"}' --path "wiki/sandbox.md"
|
|
213
216
|
```
|
|
214
217
|
|
|
@@ -7,6 +7,94 @@ import "./chunk-QGM4M3NI.js";
|
|
|
7
7
|
// src/commands/data-integration/local-data/inspect.ts
|
|
8
8
|
import { basename as basename3 } from "path";
|
|
9
9
|
|
|
10
|
+
// src/commands/data-integration/local-data/estimate.ts
|
|
11
|
+
var XLS_SIZE_WARN_BYTES = 100 * 1024 * 1024;
|
|
12
|
+
var LARGE_FILE_WARN_BYTES = 1024 * 1024 * 1024;
|
|
13
|
+
var XLS_HARD_LIMIT_BYTES = 1024 * 1024 * 1024;
|
|
14
|
+
var THROUGHPUT_BYTES_PER_SECOND = {
|
|
15
|
+
jsonl: 10 * 1024 * 1024,
|
|
16
|
+
json: 8 * 1024 * 1024,
|
|
17
|
+
csv: 4 * 1024 * 1024,
|
|
18
|
+
tsv: 4 * 1024 * 1024,
|
|
19
|
+
xlsx: 2 * 1024 * 1024
|
|
20
|
+
};
|
|
21
|
+
var SLOW_ENCODINGS = /* @__PURE__ */ new Set(["gbk", "gb2312", "gb18030", "big5", "shift_jis", "euc-jp", "euc-kr"]);
|
|
22
|
+
function estimateProcessingSeconds(format, sizeBytes, encoding) {
|
|
23
|
+
if (format === "xls") return 0;
|
|
24
|
+
let throughput = THROUGHPUT_BYTES_PER_SECOND[format];
|
|
25
|
+
if (encoding && SLOW_ENCODINGS.has(encoding.toLowerCase())) throughput /= 2;
|
|
26
|
+
return sizeBytes / throughput;
|
|
27
|
+
}
|
|
28
|
+
function formatDuration(seconds) {
|
|
29
|
+
if (seconds < 60) {
|
|
30
|
+
const low2 = Math.max(1, Math.round(seconds * 0.5));
|
|
31
|
+
const high2 = Math.max(low2 + 1, Math.round(seconds * 1.5));
|
|
32
|
+
return `roughly ${low2} to ${high2} seconds`;
|
|
33
|
+
}
|
|
34
|
+
const low = Math.max(1, Math.round(seconds / 60 * 0.5));
|
|
35
|
+
const high = Math.max(low + 1, Math.round(seconds / 60 * 1.5));
|
|
36
|
+
return `roughly ${low} to ${high} minutes`;
|
|
37
|
+
}
|
|
38
|
+
function humanSize(bytes) {
|
|
39
|
+
if (bytes >= 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
|
|
40
|
+
return `${Math.round(bytes / (1024 * 1024))} MB`;
|
|
41
|
+
}
|
|
42
|
+
function xlsMemoryWarning(fileName, sizeBytes) {
|
|
43
|
+
return `Warning: ${fileName} is ${humanSize(sizeBytes)} (XLS). The legacy XLS parser loads the entire workbook into memory, roughly 5-10x the file size. Prefer converting to XLSX or splitting the workbook first.`;
|
|
44
|
+
}
|
|
45
|
+
function largeFileTimeWarning(fileName, sizeBytes, format, encoding) {
|
|
46
|
+
const duration = formatDuration(estimateProcessingSeconds(format, sizeBytes, encoding));
|
|
47
|
+
return `Warning: ${fileName} is ${humanSize(sizeBytes)}; processing is estimated to take ${duration}. Consider splitting the file if that is too long.`;
|
|
48
|
+
}
|
|
49
|
+
function largeFileMemoryWarning(format) {
|
|
50
|
+
if (format === "xlsx") {
|
|
51
|
+
return "Memory risk: XLSX processing keeps the workbook's shared string table in memory, so peak memory can substantially exceed the file size.";
|
|
52
|
+
}
|
|
53
|
+
if (format === "json") {
|
|
54
|
+
return "Memory risk: a JSON root object or a very large record may be materialized in memory during inspection, so peak memory can substantially exceed the file size.";
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
function assessFileSize(fileName, format, sizeBytes, encoding) {
|
|
59
|
+
const baseAssessment = {
|
|
60
|
+
size: humanSize(sizeBytes),
|
|
61
|
+
estimatedDuration: null,
|
|
62
|
+
warning: null,
|
|
63
|
+
reason: null,
|
|
64
|
+
memoryRisk: false,
|
|
65
|
+
rejected: false
|
|
66
|
+
};
|
|
67
|
+
if (format === "xls") {
|
|
68
|
+
if (sizeBytes > XLS_HARD_LIMIT_BYTES) {
|
|
69
|
+
return {
|
|
70
|
+
...baseAssessment,
|
|
71
|
+
reason: "XLS files larger than 1 GB are not supported; convert the workbook to XLSX or split it first.",
|
|
72
|
+
memoryRisk: true,
|
|
73
|
+
rejected: true
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (sizeBytes > XLS_SIZE_WARN_BYTES) {
|
|
77
|
+
return {
|
|
78
|
+
...baseAssessment,
|
|
79
|
+
warning: xlsMemoryWarning(fileName, sizeBytes),
|
|
80
|
+
memoryRisk: true
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return baseAssessment;
|
|
84
|
+
}
|
|
85
|
+
if (sizeBytes > LARGE_FILE_WARN_BYTES) {
|
|
86
|
+
const memoryWarning = largeFileMemoryWarning(format);
|
|
87
|
+
const timeWarning = largeFileTimeWarning(fileName, sizeBytes, format, encoding);
|
|
88
|
+
return {
|
|
89
|
+
...baseAssessment,
|
|
90
|
+
estimatedDuration: formatDuration(estimateProcessingSeconds(format, sizeBytes, encoding)),
|
|
91
|
+
warning: memoryWarning ? `${timeWarning} ${memoryWarning}` : timeWarning,
|
|
92
|
+
memoryRisk: Boolean(memoryWarning)
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return baseAssessment;
|
|
96
|
+
}
|
|
97
|
+
|
|
10
98
|
// src/commands/data-integration/local-data/input.ts
|
|
11
99
|
import { createHash } from "crypto";
|
|
12
100
|
import { createReadStream as createReadStream2, statSync } from "fs";
|
|
@@ -486,12 +574,10 @@ function isStrongDateTime(value) {
|
|
|
486
574
|
}
|
|
487
575
|
|
|
488
576
|
// src/commands/data-integration/local-data/input.ts
|
|
489
|
-
var MAX_STREAMING_FILE_BYTES = 200 * 1024 * 1024;
|
|
490
|
-
var MAX_XLS_FILE_BYTES = 50 * 1024 * 1024;
|
|
491
577
|
var XLSX = XLSXMod.default ?? XLSXMod;
|
|
492
578
|
var require3 = createRequire2(import.meta.url);
|
|
493
579
|
var ExcelWorksheetReader = require3("exceljs/lib/stream/xlsx/worksheet-reader");
|
|
494
|
-
|
|
580
|
+
function resolveLocalDataInputMeta(filePath) {
|
|
495
581
|
let format = resolveFormat(filePath);
|
|
496
582
|
let delimiter;
|
|
497
583
|
let encoding;
|
|
@@ -512,33 +598,43 @@ async function inspectLocalDataInput(filePath) {
|
|
|
512
598
|
location: { field: "input-file" }
|
|
513
599
|
});
|
|
514
600
|
}
|
|
515
|
-
const maxBytes = format === "xls" ? MAX_XLS_FILE_BYTES : MAX_STREAMING_FILE_BYTES;
|
|
516
|
-
if (sizeBytes > maxBytes) {
|
|
517
|
-
throw new CliValidationError(
|
|
518
|
-
`${format.toUpperCase()} input exceeds the supported file size limit.`,
|
|
519
|
-
{
|
|
520
|
-
code: "LOCAL_DATA_FILE_TOO_LARGE",
|
|
521
|
-
hint: `Split the file below ${format === "xls" ? "50" : "200"} MB and retry.`,
|
|
522
|
-
location: { field: "input-file" }
|
|
523
|
-
}
|
|
524
|
-
);
|
|
525
|
-
}
|
|
526
601
|
if (format !== "xls" && format !== "xlsx" && !encoding) {
|
|
527
602
|
encoding = detectEncoding(filePath);
|
|
528
603
|
}
|
|
604
|
+
return {
|
|
605
|
+
filePath,
|
|
606
|
+
format,
|
|
607
|
+
sizeBytes,
|
|
608
|
+
...delimiter ? { delimiter } : {},
|
|
609
|
+
...encoding ? { encoding } : {}
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
async function inspectLocalDataInput(filePath) {
|
|
613
|
+
const meta = resolveLocalDataInputMeta(filePath);
|
|
614
|
+
emitSizeWarning(meta.filePath, meta.format, meta.sizeBytes, meta.encoding);
|
|
529
615
|
try {
|
|
530
616
|
return {
|
|
531
|
-
|
|
532
|
-
format,
|
|
533
|
-
sizeBytes,
|
|
617
|
+
...meta,
|
|
534
618
|
sha256: await sha256File(filePath),
|
|
535
|
-
dataSets: await discoverDataSets(filePath, format)
|
|
536
|
-
...delimiter ? { delimiter } : {},
|
|
537
|
-
...encoding ? { encoding } : {}
|
|
619
|
+
dataSets: await discoverDataSets(filePath, meta.format)
|
|
538
620
|
};
|
|
539
621
|
} catch (error) {
|
|
540
622
|
if (error instanceof CliValidationError) throw error;
|
|
541
|
-
throw localDataParseError(format);
|
|
623
|
+
throw localDataParseError(meta.format);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
function emitSizeWarning(filePath, format, sizeBytes, encoding) {
|
|
627
|
+
const assessment = assessFileSize(basename(filePath), format, sizeBytes, encoding);
|
|
628
|
+
if (assessment.rejected) {
|
|
629
|
+
throw new CliValidationError("XLS input exceeds the supported file size limit.", {
|
|
630
|
+
code: "LOCAL_DATA_FILE_TOO_LARGE",
|
|
631
|
+
hint: "XLS files larger than 1 GB are not supported; convert the workbook to XLSX or split it first.",
|
|
632
|
+
location: { field: "input-file" }
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
if (assessment.warning) {
|
|
636
|
+
process.stderr.write(`${assessment.warning}
|
|
637
|
+
`);
|
|
542
638
|
}
|
|
543
639
|
}
|
|
544
640
|
function selectDataSet(input, requested) {
|
|
@@ -1847,6 +1943,30 @@ var dataIntegrationInspect = {
|
|
|
1847
1943
|
{ name: "headerless", type: "boolean", default: false, desc: "Treat the first row as data and auto-generate col_1..col_N names." }
|
|
1848
1944
|
],
|
|
1849
1945
|
risk: "read",
|
|
1946
|
+
// Fast size/time pre-check (stat + format/encoding sniff only — no sha256, no profile).
|
|
1947
|
+
// Lets agents surface the estimate before committing to a multi-minute full inspection.
|
|
1948
|
+
dryRun: async (ctx) => {
|
|
1949
|
+
const files = ctx.list("input-file").map((filePath) => {
|
|
1950
|
+
const meta = resolveLocalDataInputMeta(filePath);
|
|
1951
|
+
const assessment = assessFileSize(basename3(filePath), meta.format, meta.sizeBytes, meta.encoding);
|
|
1952
|
+
return {
|
|
1953
|
+
file: basename3(filePath),
|
|
1954
|
+
format: meta.format,
|
|
1955
|
+
size_bytes: meta.sizeBytes,
|
|
1956
|
+
size: assessment.size,
|
|
1957
|
+
...assessment.estimatedDuration ? { estimated_duration: assessment.estimatedDuration } : {},
|
|
1958
|
+
...assessment.warning ? { warning: assessment.warning } : {},
|
|
1959
|
+
...assessment.reason ? { reason: assessment.reason } : {},
|
|
1960
|
+
...assessment.memoryRisk ? { memory_risk: true } : {},
|
|
1961
|
+
...assessment.rejected ? { rejected: true } : {}
|
|
1962
|
+
};
|
|
1963
|
+
});
|
|
1964
|
+
return {
|
|
1965
|
+
version: "ae-local-data-estimate/v1",
|
|
1966
|
+
files,
|
|
1967
|
+
has_large_file: files.some((file) => Boolean(file.warning) || file.rejected)
|
|
1968
|
+
};
|
|
1969
|
+
},
|
|
1850
1970
|
execute: async (ctx) => {
|
|
1851
1971
|
const inputFiles = ctx.list("input-file");
|
|
1852
1972
|
const headerNames = splitHeaders(ctx.str("headers"));
|
package/dist/index.js
CHANGED
|
@@ -3496,7 +3496,7 @@ async function loadCommands() {
|
|
|
3496
3496
|
} catch {
|
|
3497
3497
|
}
|
|
3498
3498
|
try {
|
|
3499
|
-
const teKb = await import("./te-kb-
|
|
3499
|
+
const teKb = await import("./te-kb-SQCLHG6X.js");
|
|
3500
3500
|
commands.push(...teKb.default);
|
|
3501
3501
|
} catch {
|
|
3502
3502
|
}
|
|
@@ -3526,7 +3526,7 @@ async function loadCommands() {
|
|
|
3526
3526
|
} catch {
|
|
3527
3527
|
}
|
|
3528
3528
|
try {
|
|
3529
|
-
const dataIntegration = await import("./data-integration-
|
|
3529
|
+
const dataIntegration = await import("./data-integration-XQYB4X4F.js");
|
|
3530
3530
|
commands.push(...dataIntegration.default);
|
|
3531
3531
|
} catch {
|
|
3532
3532
|
}
|