chatlab-cli 0.24.0 → 0.25.0
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/dist/{chunk-XJJXSOLO.mjs → chunk-4OMV4VNH.mjs} +738 -137
- package/dist/chunk-4OMV4VNH.mjs.map +1 -0
- package/dist/{chunk-A6JCL4PT.mjs → chunk-CIBTUWAE.mjs} +24 -10
- package/dist/chunk-CIBTUWAE.mjs.map +1 -0
- package/dist/{chunk-KCBIBRHL.mjs → chunk-E65ABM3C.mjs} +168 -72
- package/dist/chunk-E65ABM3C.mjs.map +1 -0
- package/dist/{chunk-NE4A6PND.mjs → chunk-FSHVDWI2.mjs} +126 -64
- package/dist/chunk-FSHVDWI2.mjs.map +1 -0
- package/dist/{chunk-36W2HWQN.mjs → chunk-GNT5G74Z.mjs} +2 -2
- package/dist/{chunk-RLCFXTTS.mjs → chunk-TCPXAX3F.mjs} +2 -2
- package/dist/cli.mjs +2 -2
- package/dist/{http-OPQ352FZ.mjs → http-PMNZ42EN.mjs} +6 -6
- package/dist/{import-GZMDLK2E.mjs → import-OP7R4CYY.mjs} +4 -4
- package/dist/index.mjs +6 -6
- package/dist/{mcp-SHZ2CVXY.mjs → mcp-ABXNFUJO.mjs} +3 -3
- package/dist/{stream-import-RDDB3N7B.mjs → stream-import-L6RJHH4L.mjs} +3 -3
- package/dist/{update-checker-JG5K67O2.mjs → update-checker-JIBA7T4U.mjs} +24 -21
- package/dist/update-checker-JIBA7T4U.mjs.map +1 -0
- package/dist-web/assets/DebugToolsPanel.vue_vue_type_script_setup_true_lang-BUwpIerl.js +161 -0
- package/dist-web/assets/{EChartWordcloud-VpNJDurs.js → EChartWordcloud-CzhfrEF_.js} +1 -1
- package/dist-web/assets/MessageExportModal-BAJKWX4y.js +1 -0
- package/dist-web/assets/{electron-BIWBW8k_.js → electron-CZt36wW5.js} +1 -1
- package/dist-web/assets/electron-CwERrTWp.js +1 -0
- package/dist-web/assets/{fetch-ChECfwh7.js → fetch-BxFAkm7O.js} +1 -1
- package/dist-web/assets/{fetch-DwPB8NOH.js → fetch-CgBIWyAo.js} +1 -1
- package/dist-web/assets/{fetch-BhsrPRzn.js → fetch-D4p9vj1A.js} +1 -1
- package/dist-web/assets/{fetch-CvaXKzA-.js → fetch-DD1EGRKV.js} +1 -1
- package/dist-web/assets/{fetch-BOevuRK_.js → fetch-DO8lty7_.js} +1 -1
- package/dist-web/assets/{fetch-CnyupWWc.js → fetch-DXfZysDf.js} +2 -2
- package/dist-web/assets/{fetch-DKD1bKt2.js → fetch-GMkMBzBS.js} +1 -1
- package/dist-web/assets/{fetch-D1_jL6PO.js → fetch-JzVEwamn.js} +1 -1
- package/dist-web/assets/{fetch-DFWZ48Xw.js → fetch-qoGEVjNg.js} +1 -1
- package/dist-web/assets/{fetch-ClDGP9DK.js → fetch-yWwp067l.js} +1 -1
- package/dist-web/assets/{index-BVQsKKwg.js → index-BrS_VrIY.js} +1 -1
- package/dist-web/assets/index-C1t-kzfo.css +1 -0
- package/dist-web/assets/index-Cvlw0RLu.js +2 -0
- package/dist-web/assets/index-DABpUm3J.js +9 -0
- package/dist-web/assets/{index-D6ga3hbF.js → index-DvWI6Yqa.js} +4 -4
- package/dist-web/assets/{index-Bzg8BftZ.js → index-O0PG26_v.js} +1 -1
- package/dist-web/assets/index-OsjX5hXw.js +173 -0
- package/dist-web/assets/vendor-echarts-CITQeskI.js +11 -0
- package/dist-web/assets/{vendor-echarts-wordcloud-CZ9gsX8l.js → vendor-echarts-wordcloud-B1kQMklB.js} +1 -1
- package/dist-web/assets/{vendor-nuxt-ui-BLMzqeB8.js → vendor-nuxt-ui-C_8CsH6e.js} +2 -2
- package/dist-web/assets/{vendor-reka-ui-CnB0mMNX.js → vendor-reka-ui-CIMXwvEp.js} +1 -1
- package/dist-web/assets/{web-DtlveK3q.js → web-4rtrAcLu.js} +1 -1
- package/dist-web/index.html +4 -4
- package/package.json +1 -1
- package/dist/chunk-A6JCL4PT.mjs.map +0 -1
- package/dist/chunk-KCBIBRHL.mjs.map +0 -1
- package/dist/chunk-NE4A6PND.mjs.map +0 -1
- package/dist/chunk-XJJXSOLO.mjs.map +0 -1
- package/dist/update-checker-JG5K67O2.mjs.map +0 -1
- package/dist-web/assets/DebugToolsPanel.vue_vue_type_script_setup_true_lang-_gbTn1ha.js +0 -161
- package/dist-web/assets/MessageExportModal-n4JgNg_F.js +0 -1
- package/dist-web/assets/electron-Bt9dK4Sr.js +0 -1
- package/dist-web/assets/index-BN79SJSr.js +0 -173
- package/dist-web/assets/index-C-5bP7_E.js +0 -2
- package/dist-web/assets/index-ESCx9pRR.js +0 -8
- package/dist-web/assets/index-JbR9Q-bb.css +0 -1
- package/dist-web/assets/model-catalog-DUuKjIVU.js +0 -1
- package/dist-web/assets/vendor-echarts-C5u62NnM.js +0 -11
- /package/dist/{chunk-36W2HWQN.mjs.map → chunk-GNT5G74Z.mjs.map} +0 -0
- /package/dist/{chunk-RLCFXTTS.mjs.map → chunk-TCPXAX3F.mjs.map} +0 -0
- /package/dist/{http-OPQ352FZ.mjs.map → http-PMNZ42EN.mjs.map} +0 -0
- /package/dist/{import-GZMDLK2E.mjs.map → import-OP7R4CYY.mjs.map} +0 -0
- /package/dist/{mcp-SHZ2CVXY.mjs.map → mcp-ABXNFUJO.mjs.map} +0 -0
- /package/dist/{stream-import-RDDB3N7B.mjs.map → stream-import-L6RJHH4L.mjs.map} +0 -0
|
@@ -4377,6 +4377,251 @@ function runMigrations(db, migrationsList, forceRepair = false) {
|
|
|
4377
4377
|
return true;
|
|
4378
4378
|
}
|
|
4379
4379
|
|
|
4380
|
+
// ../../packages/core/src/version.ts
|
|
4381
|
+
function parseStableVersion(version) {
|
|
4382
|
+
const normalized = version.trim().replace(/^v/i, "");
|
|
4383
|
+
const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(normalized);
|
|
4384
|
+
if (!match) return null;
|
|
4385
|
+
return buildParsedVersion(match);
|
|
4386
|
+
}
|
|
4387
|
+
function parseComparableCurrentVersion(version) {
|
|
4388
|
+
const normalized = version.trim().replace(/^v/i, "");
|
|
4389
|
+
const match = /^(\d+)\.(\d+)\.(\d+)(-[0-9A-Za-z.-]+)?$/.exec(normalized);
|
|
4390
|
+
if (!match) return null;
|
|
4391
|
+
return {
|
|
4392
|
+
...buildParsedVersion(match),
|
|
4393
|
+
prerelease: Boolean(match[4])
|
|
4394
|
+
};
|
|
4395
|
+
}
|
|
4396
|
+
function buildParsedVersion(match) {
|
|
4397
|
+
return {
|
|
4398
|
+
major: Number(match[1]),
|
|
4399
|
+
minor: Number(match[2]),
|
|
4400
|
+
patch: Number(match[3])
|
|
4401
|
+
};
|
|
4402
|
+
}
|
|
4403
|
+
function isNewerStableVersion(latest, current) {
|
|
4404
|
+
const latestVersion = parseStableVersion(latest);
|
|
4405
|
+
const currentVersion = parseComparableCurrentVersion(current);
|
|
4406
|
+
if (!latestVersion || !currentVersion) return false;
|
|
4407
|
+
if (latestVersion.major !== currentVersion.major) return latestVersion.major > currentVersion.major;
|
|
4408
|
+
if (latestVersion.minor !== currentVersion.minor) return latestVersion.minor > currentVersion.minor;
|
|
4409
|
+
if (latestVersion.patch !== currentVersion.patch) return latestVersion.patch > currentVersion.patch;
|
|
4410
|
+
return currentVersion.prerelease;
|
|
4411
|
+
}
|
|
4412
|
+
|
|
4413
|
+
// ../../packages/core/src/chart/index.ts
|
|
4414
|
+
var ChartValidationError = class extends Error {
|
|
4415
|
+
constructor(message) {
|
|
4416
|
+
super(message);
|
|
4417
|
+
this.name = "ChartValidationError";
|
|
4418
|
+
}
|
|
4419
|
+
};
|
|
4420
|
+
var CHART_TYPES = /* @__PURE__ */ new Set(["bar", "line", "pie", "heatmap"]);
|
|
4421
|
+
function isRecord(value) {
|
|
4422
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4423
|
+
}
|
|
4424
|
+
function asFieldName(value, label) {
|
|
4425
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
4426
|
+
throw new ChartValidationError(`${label} must be a non-empty field name`);
|
|
4427
|
+
}
|
|
4428
|
+
return value;
|
|
4429
|
+
}
|
|
4430
|
+
function assertFieldExists(rows, field) {
|
|
4431
|
+
if (rows.length === 0) return;
|
|
4432
|
+
if (!Object.prototype.hasOwnProperty.call(rows[0], field)) {
|
|
4433
|
+
throw new ChartValidationError(`Field "${field}" does not exist in SQL result`);
|
|
4434
|
+
}
|
|
4435
|
+
}
|
|
4436
|
+
function toLabel(value) {
|
|
4437
|
+
if (value === null || value === void 0 || value === "") return "(empty)";
|
|
4438
|
+
return String(value);
|
|
4439
|
+
}
|
|
4440
|
+
function toNumber(value, field) {
|
|
4441
|
+
const num = typeof value === "number" ? value : Number(value);
|
|
4442
|
+
if (!Number.isFinite(num)) {
|
|
4443
|
+
throw new ChartValidationError(`Field "${field}" contains non-numeric value "${String(value)}"`);
|
|
4444
|
+
}
|
|
4445
|
+
return num;
|
|
4446
|
+
}
|
|
4447
|
+
function inferFieldType(values) {
|
|
4448
|
+
const present = values.filter((v) => v !== null && v !== void 0);
|
|
4449
|
+
if (present.length === 0) return "string";
|
|
4450
|
+
if (present.every((v) => typeof v === "number" && Number.isInteger(v))) return "integer";
|
|
4451
|
+
if (present.every(
|
|
4452
|
+
(v) => typeof v === "number" || typeof v === "string" && v.trim() !== "" && !Number.isNaN(Number(v))
|
|
4453
|
+
)) {
|
|
4454
|
+
return "number";
|
|
4455
|
+
}
|
|
4456
|
+
if (present.every((v) => typeof v === "boolean")) return "boolean";
|
|
4457
|
+
return "category";
|
|
4458
|
+
}
|
|
4459
|
+
function normalizeChartSpec(raw) {
|
|
4460
|
+
if (!isRecord(raw)) throw new ChartValidationError("chartSpec must be an object");
|
|
4461
|
+
if (raw.version !== 1) throw new ChartValidationError("chartSpec.version must be 1");
|
|
4462
|
+
if (typeof raw.type !== "string" || !CHART_TYPES.has(raw.type)) {
|
|
4463
|
+
throw new ChartValidationError("chartSpec.type must be one of: bar, line, pie, heatmap");
|
|
4464
|
+
}
|
|
4465
|
+
if (typeof raw.title !== "string" || raw.title.trim().length === 0) {
|
|
4466
|
+
throw new ChartValidationError("chartSpec.title must be a non-empty string");
|
|
4467
|
+
}
|
|
4468
|
+
if (!isRecord(raw.encoding)) throw new ChartValidationError("chartSpec.encoding must be an object");
|
|
4469
|
+
const spec = raw;
|
|
4470
|
+
switch (spec.type) {
|
|
4471
|
+
case "bar":
|
|
4472
|
+
case "line":
|
|
4473
|
+
asFieldName(spec.encoding.x, "encoding.x");
|
|
4474
|
+
asFieldName(spec.encoding.y, "encoding.y");
|
|
4475
|
+
break;
|
|
4476
|
+
case "pie":
|
|
4477
|
+
asFieldName(spec.encoding.label, "encoding.label");
|
|
4478
|
+
asFieldName(spec.encoding.value, "encoding.value");
|
|
4479
|
+
break;
|
|
4480
|
+
case "heatmap":
|
|
4481
|
+
asFieldName(spec.encoding.x, "encoding.x");
|
|
4482
|
+
asFieldName(spec.encoding.y, "encoding.y");
|
|
4483
|
+
asFieldName(spec.encoding.value, "encoding.value");
|
|
4484
|
+
break;
|
|
4485
|
+
}
|
|
4486
|
+
return {
|
|
4487
|
+
...spec,
|
|
4488
|
+
title: spec.title.trim()
|
|
4489
|
+
};
|
|
4490
|
+
}
|
|
4491
|
+
function inferChartDataset(rows, declaredFields) {
|
|
4492
|
+
const declared = new Map((declaredFields ?? []).map((field) => [field.name, field]));
|
|
4493
|
+
const columnNames = rows.length > 0 ? Object.keys(rows[0]) : [...declared.keys()];
|
|
4494
|
+
const columns = columnNames.map((name) => {
|
|
4495
|
+
const declaredField = declared.get(name);
|
|
4496
|
+
if (declaredField) return declaredField;
|
|
4497
|
+
return {
|
|
4498
|
+
name,
|
|
4499
|
+
type: inferFieldType(rows.map((row) => row[name]))
|
|
4500
|
+
};
|
|
4501
|
+
});
|
|
4502
|
+
return { columns, rows };
|
|
4503
|
+
}
|
|
4504
|
+
function aggregateByLabel(rows, labelField, valueField) {
|
|
4505
|
+
const labels = [];
|
|
4506
|
+
const indexByLabel = /* @__PURE__ */ new Map();
|
|
4507
|
+
const values = [];
|
|
4508
|
+
for (const row of rows) {
|
|
4509
|
+
const label = toLabel(row[labelField]);
|
|
4510
|
+
let index = indexByLabel.get(label);
|
|
4511
|
+
if (index === void 0) {
|
|
4512
|
+
index = labels.length;
|
|
4513
|
+
indexByLabel.set(label, index);
|
|
4514
|
+
labels.push(label);
|
|
4515
|
+
values.push(0);
|
|
4516
|
+
}
|
|
4517
|
+
values[index] += toNumber(row[valueField], valueField);
|
|
4518
|
+
}
|
|
4519
|
+
return { labels, values };
|
|
4520
|
+
}
|
|
4521
|
+
function buildLineData(rows, spec) {
|
|
4522
|
+
const xField = spec.encoding.x;
|
|
4523
|
+
const yField = spec.encoding.y;
|
|
4524
|
+
const seriesField = spec.encoding.series;
|
|
4525
|
+
if (!seriesField) return aggregateByLabel(rows, xField, yField);
|
|
4526
|
+
assertFieldExists(rows, seriesField);
|
|
4527
|
+
const labels = [];
|
|
4528
|
+
const labelIndex = /* @__PURE__ */ new Map();
|
|
4529
|
+
const seriesNames = [];
|
|
4530
|
+
const seriesIndex = /* @__PURE__ */ new Map();
|
|
4531
|
+
const matrix = [];
|
|
4532
|
+
for (const row of rows) {
|
|
4533
|
+
const label = toLabel(row[xField]);
|
|
4534
|
+
const seriesName = toLabel(row[seriesField]);
|
|
4535
|
+
let xIndex = labelIndex.get(label);
|
|
4536
|
+
if (xIndex === void 0) {
|
|
4537
|
+
xIndex = labels.length;
|
|
4538
|
+
labelIndex.set(label, xIndex);
|
|
4539
|
+
labels.push(label);
|
|
4540
|
+
for (const values of matrix) values.push(0);
|
|
4541
|
+
}
|
|
4542
|
+
let sIndex = seriesIndex.get(seriesName);
|
|
4543
|
+
if (sIndex === void 0) {
|
|
4544
|
+
sIndex = seriesNames.length;
|
|
4545
|
+
seriesIndex.set(seriesName, sIndex);
|
|
4546
|
+
seriesNames.push(seriesName);
|
|
4547
|
+
matrix.push(Array(labels.length).fill(0));
|
|
4548
|
+
}
|
|
4549
|
+
matrix[sIndex][xIndex] += toNumber(row[yField], yField);
|
|
4550
|
+
}
|
|
4551
|
+
const series = seriesNames.map((name, index) => ({ name, values: matrix[index] }));
|
|
4552
|
+
return {
|
|
4553
|
+
labels,
|
|
4554
|
+
values: series[0]?.values ?? [],
|
|
4555
|
+
series
|
|
4556
|
+
};
|
|
4557
|
+
}
|
|
4558
|
+
function buildHeatmapData(rows, spec) {
|
|
4559
|
+
const xField = spec.encoding.x;
|
|
4560
|
+
const yField = spec.encoding.y;
|
|
4561
|
+
const valueField = spec.encoding.value;
|
|
4562
|
+
const xLabels = [];
|
|
4563
|
+
const yLabels = [];
|
|
4564
|
+
const xIndex = /* @__PURE__ */ new Map();
|
|
4565
|
+
const yIndex = /* @__PURE__ */ new Map();
|
|
4566
|
+
const values = /* @__PURE__ */ new Map();
|
|
4567
|
+
for (const row of rows) {
|
|
4568
|
+
const xLabel = toLabel(row[xField]);
|
|
4569
|
+
const yLabel = toLabel(row[yField]);
|
|
4570
|
+
let xi = xIndex.get(xLabel);
|
|
4571
|
+
if (xi === void 0) {
|
|
4572
|
+
xi = xLabels.length;
|
|
4573
|
+
xIndex.set(xLabel, xi);
|
|
4574
|
+
xLabels.push(xLabel);
|
|
4575
|
+
}
|
|
4576
|
+
let yi = yIndex.get(yLabel);
|
|
4577
|
+
if (yi === void 0) {
|
|
4578
|
+
yi = yLabels.length;
|
|
4579
|
+
yIndex.set(yLabel, yi);
|
|
4580
|
+
yLabels.push(yLabel);
|
|
4581
|
+
}
|
|
4582
|
+
const key = `${xi}:${yi}`;
|
|
4583
|
+
values.set(key, (values.get(key) ?? 0) + toNumber(row[valueField], valueField));
|
|
4584
|
+
}
|
|
4585
|
+
const data = [];
|
|
4586
|
+
for (const [key, value] of values.entries()) {
|
|
4587
|
+
const [x, y] = key.split(":").map(Number);
|
|
4588
|
+
data.push([x, y, value]);
|
|
4589
|
+
}
|
|
4590
|
+
return { xLabels, yLabels, data };
|
|
4591
|
+
}
|
|
4592
|
+
function buildChartPayload(rows, rawSpec, options) {
|
|
4593
|
+
const spec = normalizeChartSpec(rawSpec);
|
|
4594
|
+
const dataset = inferChartDataset(rows, spec.fields);
|
|
4595
|
+
const requiredFields = /* @__PURE__ */ new Set();
|
|
4596
|
+
for (const field of Object.values(spec.encoding)) {
|
|
4597
|
+
if (typeof field === "string" && field) requiredFields.add(field);
|
|
4598
|
+
}
|
|
4599
|
+
for (const field of requiredFields) assertFieldExists(rows, field);
|
|
4600
|
+
let data;
|
|
4601
|
+
switch (spec.type) {
|
|
4602
|
+
case "bar":
|
|
4603
|
+
data = aggregateByLabel(rows, spec.encoding.x, spec.encoding.y);
|
|
4604
|
+
break;
|
|
4605
|
+
case "line":
|
|
4606
|
+
data = buildLineData(rows, spec);
|
|
4607
|
+
break;
|
|
4608
|
+
case "pie":
|
|
4609
|
+
data = aggregateByLabel(rows, spec.encoding.label, spec.encoding.value);
|
|
4610
|
+
break;
|
|
4611
|
+
case "heatmap":
|
|
4612
|
+
data = buildHeatmapData(rows, spec);
|
|
4613
|
+
break;
|
|
4614
|
+
}
|
|
4615
|
+
return {
|
|
4616
|
+
version: 1,
|
|
4617
|
+
spec,
|
|
4618
|
+
dataset,
|
|
4619
|
+
data,
|
|
4620
|
+
rowCount: rows.length,
|
|
4621
|
+
truncated: options?.truncated
|
|
4622
|
+
};
|
|
4623
|
+
}
|
|
4624
|
+
|
|
4380
4625
|
// ../../packages/core/src/nlp/pos-tags.ts
|
|
4381
4626
|
var POS_TAG_DEFINITIONS = [
|
|
4382
4627
|
{ tag: "n", name: "\u540D\u8BCD", description: "\u666E\u901A\u540D\u8BCD", meaningful: true },
|
|
@@ -5215,6 +5460,7 @@ var BUILTIN_TOOL_CATALOG = [
|
|
|
5215
5460
|
{ name: "search_sessions", category: "core" },
|
|
5216
5461
|
{ name: "get_session_messages", category: "core" },
|
|
5217
5462
|
{ name: "get_members", category: "core" },
|
|
5463
|
+
{ name: "get_schema", category: "core" },
|
|
5218
5464
|
// Analysis 工具
|
|
5219
5465
|
{ name: "get_member_stats", category: "analysis" },
|
|
5220
5466
|
{ name: "get_time_stats", category: "analysis" },
|
|
@@ -5223,6 +5469,8 @@ var BUILTIN_TOOL_CATALOG = [
|
|
|
5223
5469
|
{ name: "get_session_summaries", category: "analysis" },
|
|
5224
5470
|
{ name: "response_time_analysis", category: "analysis" },
|
|
5225
5471
|
{ name: "keyword_frequency", category: "analysis" },
|
|
5472
|
+
{ name: "render_chart", category: "analysis" },
|
|
5473
|
+
{ name: "execute_sql", category: "analysis" },
|
|
5226
5474
|
// SQL Analysis 工具
|
|
5227
5475
|
{ name: "message_type_breakdown", category: "analysis" },
|
|
5228
5476
|
{ name: "peak_chat_hours_by_member", category: "analysis" },
|
|
@@ -5237,6 +5485,9 @@ var BUILTIN_TOOL_CATALOG = [
|
|
|
5237
5485
|
{ name: "unanswered_messages", category: "analysis" }
|
|
5238
5486
|
];
|
|
5239
5487
|
|
|
5488
|
+
// ../../packages/core/src/ai/chart-capability.ts
|
|
5489
|
+
var CHART_CAPABILITY_SKILL_ID = "chart_runtime";
|
|
5490
|
+
|
|
5240
5491
|
// ../../packages/core/src/ai/provider-registry.ts
|
|
5241
5492
|
var OPENAI = {
|
|
5242
5493
|
id: "openai",
|
|
@@ -13361,93 +13612,43 @@ function countMessagesTokens(messages, systemPrompt) {
|
|
|
13361
13612
|
// ../../packages/node-runtime/src/ai/skill-manager.ts
|
|
13362
13613
|
import * as fs30 from "fs";
|
|
13363
13614
|
import * as path27 from "path";
|
|
13364
|
-
|
|
13615
|
+
|
|
13616
|
+
// ../../packages/node-runtime/src/ai/skill-menu.ts
|
|
13365
13617
|
var MAX_SKILL_MENU_ITEMS = 15;
|
|
13366
|
-
var
|
|
13367
|
-
info: () => {
|
|
13368
|
-
},
|
|
13369
|
-
warn: () => {
|
|
13370
|
-
}
|
|
13371
|
-
};
|
|
13372
|
-
var SkillManager = class {
|
|
13373
|
-
skills = /* @__PURE__ */ new Map();
|
|
13374
|
-
initialized = false;
|
|
13375
|
-
skillsDir;
|
|
13376
|
-
logger;
|
|
13377
|
-
constructor(aiDataDir, logger) {
|
|
13378
|
-
this.skillsDir = path27.join(aiDataDir, SKILLS_DIR_NAME);
|
|
13379
|
-
this.logger = logger ?? defaultLogger2;
|
|
13380
|
-
}
|
|
13381
|
-
init() {
|
|
13382
|
-
this.loadAll();
|
|
13383
|
-
this.initialized = true;
|
|
13384
|
-
this.logger.info(`SkillManager initialized: ${this.skills.size} skills`);
|
|
13385
|
-
return { total: this.skills.size };
|
|
13386
|
-
}
|
|
13387
|
-
getSkillConfig(id) {
|
|
13388
|
-
this.ensureInitialized();
|
|
13389
|
-
return this.skills.get(id) ?? null;
|
|
13390
|
-
}
|
|
13391
|
-
getAllSkills() {
|
|
13392
|
-
this.ensureInitialized();
|
|
13393
|
-
return Array.from(this.skills.values()).map((def) => ({
|
|
13394
|
-
id: def.id,
|
|
13395
|
-
name: def.name,
|
|
13396
|
-
description: def.description,
|
|
13397
|
-
tags: def.tags,
|
|
13398
|
-
chatScope: def.chatScope,
|
|
13399
|
-
tools: def.tools,
|
|
13400
|
-
builtinId: def.builtinId
|
|
13401
|
-
}));
|
|
13402
|
-
}
|
|
13403
|
-
/**
|
|
13404
|
-
* 构建 AI 自选技能菜单文本
|
|
13405
|
-
* 只包含与当前 chatType + 助手工具权限兼容的技能
|
|
13406
|
-
*/
|
|
13407
|
-
getSkillMenu(chatType, allowedTools) {
|
|
13408
|
-
this.ensureInitialized();
|
|
13409
|
-
const compatible = Array.from(this.skills.values()).filter((skill) => {
|
|
13410
|
-
if (skill.chatScope !== "all" && skill.chatScope !== chatType) return false;
|
|
13411
|
-
if (skill.tools.length > 0 && allowedTools && allowedTools.length > 0) {
|
|
13412
|
-
const allCovered = skill.tools.every((t2) => allowedTools.includes(t2));
|
|
13413
|
-
if (!allCovered) return false;
|
|
13414
|
-
}
|
|
13415
|
-
return true;
|
|
13416
|
-
});
|
|
13417
|
-
if (compatible.length === 0) return null;
|
|
13418
|
-
const items = compatible.slice(0, MAX_SKILL_MENU_ITEMS);
|
|
13419
|
-
const lines = items.map((s) => `- ${s.id}: ${s.name} \u2014 ${s.description}`);
|
|
13420
|
-
return `## \u53EF\u7528\u6280\u80FD
|
|
13618
|
+
var SKILL_MENU_HEADER = `## \u53EF\u7528\u6280\u80FD
|
|
13421
13619
|
\u4EE5\u4E0B\u662F\u4F60\u53EF\u4EE5\u4F7F\u7528\u7684\u5206\u6790\u6280\u80FD\u3002\u5F53\u4F60\u5224\u65AD\u7528\u6237\u7684\u95EE\u9898\u9002\u5408\u4F7F\u7528\u67D0\u4E2A\u6280\u80FD\u65F6\uFF0C
|
|
13422
|
-
\u8BF7\u8C03\u7528 activate_skill \u5DE5\u5177\u6FC0\u6D3B\u5B83\uFF0C\u7136\u540E\u6309\u7167\u8FD4\u56DE\u7684\u6307\u5BFC\u5B8C\u6210\u4EFB\u52A1\u3002
|
|
13620
|
+
\u8BF7\u8C03\u7528 activate_skill \u5DE5\u5177\u6FC0\u6D3B\u5B83\uFF0C\u7136\u540E\u6309\u7167\u8FD4\u56DE\u7684\u6307\u5BFC\u5B8C\u6210\u4EFB\u52A1\u3002`;
|
|
13621
|
+
var SKILL_MENU_CLOSING = "\u5982\u679C\u7528\u6237\u7684\u95EE\u9898\u4E0D\u9700\u8981\u4F7F\u7528\u6280\u80FD\uFF0C\u76F4\u63A5\u56DE\u7B54\u5373\u53EF\u3002";
|
|
13622
|
+
var SKILL_MENU_CLOSING_BLOCK = `
|
|
13423
13623
|
|
|
13424
|
-
${
|
|
13624
|
+
${SKILL_MENU_CLOSING}`;
|
|
13625
|
+
function formatSkillMenuLine(item) {
|
|
13626
|
+
const guidanceSuffix = item.guidance ? `. ${item.guidance}` : "";
|
|
13627
|
+
return `- ${item.id}: ${item.name} \u2014 ${item.description}${guidanceSuffix}`;
|
|
13628
|
+
}
|
|
13629
|
+
function buildSkillMenuText(lines) {
|
|
13630
|
+
const visibleLines = normalizeSkillMenuLines(lines);
|
|
13631
|
+
if (visibleLines.length === 0) return null;
|
|
13632
|
+
return `${SKILL_MENU_HEADER}
|
|
13425
13633
|
|
|
13426
|
-
\
|
|
13427
|
-
|
|
13428
|
-
|
|
13429
|
-
|
|
13430
|
-
|
|
13431
|
-
|
|
13432
|
-
|
|
13433
|
-
|
|
13434
|
-
|
|
13435
|
-
|
|
13436
|
-
|
|
13437
|
-
|
|
13438
|
-
try {
|
|
13439
|
-
const filePath = path27.join(this.skillsDir, file);
|
|
13440
|
-
const content = fs30.readFileSync(filePath, "utf-8");
|
|
13441
|
-
const def = parseSkillFile(content, filePath);
|
|
13442
|
-
if (def) {
|
|
13443
|
-
this.skills.set(def.id, def);
|
|
13444
|
-
}
|
|
13445
|
-
} catch (error) {
|
|
13446
|
-
this.logger.warn(`Failed to load skill: ${file}`, { error: String(error) });
|
|
13447
|
-
}
|
|
13448
|
-
}
|
|
13634
|
+
${visibleLines.join("\n")}
|
|
13635
|
+
|
|
13636
|
+
${SKILL_MENU_CLOSING}`;
|
|
13637
|
+
}
|
|
13638
|
+
function appendSkillMenuLines(baseMenu, lines) {
|
|
13639
|
+
const visibleLines = normalizeSkillMenuLines(lines);
|
|
13640
|
+
if (visibleLines.length === 0) return baseMenu ?? null;
|
|
13641
|
+
if (!baseMenu) return buildSkillMenuText(visibleLines);
|
|
13642
|
+
const insertion = `
|
|
13643
|
+
${visibleLines.join("\n")}`;
|
|
13644
|
+
if (!baseMenu.includes(SKILL_MENU_CLOSING_BLOCK)) {
|
|
13645
|
+
return `${baseMenu}${insertion}`;
|
|
13449
13646
|
}
|
|
13450
|
-
};
|
|
13647
|
+
return baseMenu.replace(SKILL_MENU_CLOSING_BLOCK, `${insertion}${SKILL_MENU_CLOSING_BLOCK}`);
|
|
13648
|
+
}
|
|
13649
|
+
function normalizeSkillMenuLines(lines) {
|
|
13650
|
+
return lines.map((line) => line.trim()).filter(Boolean);
|
|
13651
|
+
}
|
|
13451
13652
|
|
|
13452
13653
|
// ../../packages/node-runtime/src/ai/skill-manager-core.ts
|
|
13453
13654
|
function toSummary2(def) {
|
|
@@ -13478,7 +13679,6 @@ function simpleHash(content) {
|
|
|
13478
13679
|
}
|
|
13479
13680
|
return hash.toString(36);
|
|
13480
13681
|
}
|
|
13481
|
-
var MAX_SKILL_MENU_ITEMS2 = 15;
|
|
13482
13682
|
var SkillManagerCore = class {
|
|
13483
13683
|
deps;
|
|
13484
13684
|
builtinDefs = /* @__PURE__ */ new Map();
|
|
@@ -13632,21 +13832,14 @@ var SkillManagerCore = class {
|
|
|
13632
13832
|
this.ensureInitialized();
|
|
13633
13833
|
const compatible = Array.from(this.cache.values()).filter((skill) => {
|
|
13634
13834
|
if (skill.chatScope !== "all" && skill.chatScope !== chatType) return false;
|
|
13635
|
-
if (skill.tools.length > 0 && allowedTools
|
|
13835
|
+
if (skill.tools.length > 0 && allowedTools !== void 0) {
|
|
13636
13836
|
if (!skill.tools.every((t2) => allowedTools.includes(t2))) return false;
|
|
13637
13837
|
}
|
|
13638
13838
|
return true;
|
|
13639
13839
|
});
|
|
13640
13840
|
if (compatible.length === 0) return null;
|
|
13641
|
-
const items = compatible.slice(0,
|
|
13642
|
-
|
|
13643
|
-
return `## \u53EF\u7528\u6280\u80FD
|
|
13644
|
-
\u4EE5\u4E0B\u662F\u4F60\u53EF\u4EE5\u4F7F\u7528\u7684\u5206\u6790\u6280\u80FD\u3002\u5F53\u4F60\u5224\u65AD\u7528\u6237\u7684\u95EE\u9898\u9002\u5408\u4F7F\u7528\u67D0\u4E2A\u6280\u80FD\u65F6\uFF0C
|
|
13645
|
-
\u8BF7\u8C03\u7528 activate_skill \u5DE5\u5177\u6FC0\u6D3B\u5B83\uFF0C\u7136\u540E\u6309\u7167\u8FD4\u56DE\u7684\u6307\u5BFC\u5B8C\u6210\u4EFB\u52A1\u3002
|
|
13646
|
-
|
|
13647
|
-
${lines.join("\n")}
|
|
13648
|
-
|
|
13649
|
-
\u5982\u679C\u7528\u6237\u7684\u95EE\u9898\u4E0D\u9700\u8981\u4F7F\u7528\u6280\u80FD\uFF0C\u76F4\u63A5\u56DE\u7B54\u5373\u53EF\u3002`;
|
|
13841
|
+
const items = compatible.slice(0, MAX_SKILL_MENU_ITEMS);
|
|
13842
|
+
return buildSkillMenuText(items.map(formatSkillMenuLine));
|
|
13650
13843
|
}
|
|
13651
13844
|
// ==================== Internal ====================
|
|
13652
13845
|
findByBuiltinId(builtinId) {
|
|
@@ -13676,6 +13869,80 @@ ${lines.join("\n")}
|
|
|
13676
13869
|
}
|
|
13677
13870
|
};
|
|
13678
13871
|
|
|
13872
|
+
// ../../packages/node-runtime/src/ai/skill-manager.ts
|
|
13873
|
+
var SKILLS_DIR_NAME = "skills";
|
|
13874
|
+
var defaultLogger2 = {
|
|
13875
|
+
info: () => {
|
|
13876
|
+
},
|
|
13877
|
+
warn: () => {
|
|
13878
|
+
}
|
|
13879
|
+
};
|
|
13880
|
+
var nodeFs = {
|
|
13881
|
+
ensureDir(dir) {
|
|
13882
|
+
fs30.mkdirSync(dir, { recursive: true });
|
|
13883
|
+
},
|
|
13884
|
+
listFiles(dir, ext) {
|
|
13885
|
+
if (!fs30.existsSync(dir)) return [];
|
|
13886
|
+
return fs30.readdirSync(dir).filter((file) => file.endsWith(ext));
|
|
13887
|
+
},
|
|
13888
|
+
readFile(filePath) {
|
|
13889
|
+
return fs30.readFileSync(filePath, "utf-8");
|
|
13890
|
+
},
|
|
13891
|
+
writeFile(filePath, content) {
|
|
13892
|
+
fs30.writeFileSync(filePath, content, "utf-8");
|
|
13893
|
+
},
|
|
13894
|
+
deleteFile(filePath) {
|
|
13895
|
+
fs30.unlinkSync(filePath);
|
|
13896
|
+
},
|
|
13897
|
+
fileExists(filePath) {
|
|
13898
|
+
return fs30.existsSync(filePath);
|
|
13899
|
+
},
|
|
13900
|
+
joinPath(...parts) {
|
|
13901
|
+
return path27.join(...parts);
|
|
13902
|
+
}
|
|
13903
|
+
};
|
|
13904
|
+
var SkillManager = class {
|
|
13905
|
+
core;
|
|
13906
|
+
logger;
|
|
13907
|
+
constructor(aiDataDir, logger) {
|
|
13908
|
+
this.logger = logger ?? defaultLogger2;
|
|
13909
|
+
this.core = new SkillManagerCore({
|
|
13910
|
+
fs: nodeFs,
|
|
13911
|
+
skillsDir: path27.join(aiDataDir, SKILLS_DIR_NAME),
|
|
13912
|
+
builtinRawSkills: [],
|
|
13913
|
+
logger: {
|
|
13914
|
+
info: () => {
|
|
13915
|
+
},
|
|
13916
|
+
warn: (_category, message, data) => this.logger.warn(message, toLoggerExtra(data)),
|
|
13917
|
+
error: (_category, message, data) => this.logger.warn(message, toLoggerExtra(data))
|
|
13918
|
+
}
|
|
13919
|
+
});
|
|
13920
|
+
}
|
|
13921
|
+
init() {
|
|
13922
|
+
const result = this.core.init();
|
|
13923
|
+
this.logger.info(`SkillManager initialized: ${result.total} skills`);
|
|
13924
|
+
return result;
|
|
13925
|
+
}
|
|
13926
|
+
getSkillConfig(id) {
|
|
13927
|
+
return this.core.getSkillConfig(id);
|
|
13928
|
+
}
|
|
13929
|
+
getAllSkills() {
|
|
13930
|
+
return this.core.getAllSkills();
|
|
13931
|
+
}
|
|
13932
|
+
/**
|
|
13933
|
+
* 构建 AI 自选技能菜单文本
|
|
13934
|
+
* 只包含与当前 chatType + 助手工具权限兼容的技能
|
|
13935
|
+
*/
|
|
13936
|
+
getSkillMenu(chatType, allowedTools) {
|
|
13937
|
+
return this.core.getSkillMenu(chatType, allowedTools);
|
|
13938
|
+
}
|
|
13939
|
+
};
|
|
13940
|
+
function toLoggerExtra(data) {
|
|
13941
|
+
if (data === void 0) return void 0;
|
|
13942
|
+
if (data && typeof data === "object" && !Array.isArray(data)) return data;
|
|
13943
|
+
return { data };
|
|
13944
|
+
}
|
|
13945
|
+
|
|
13679
13946
|
// ../../packages/node-runtime/src/ai/activate-skill-tool.ts
|
|
13680
13947
|
function createActivateSkillTool(options) {
|
|
13681
13948
|
const { chatType, allowedTools, coreToolNames, getSkillConfig, locale = "zh-CN" } = options;
|
|
@@ -13711,7 +13978,7 @@ function createActivateSkillTool(options) {
|
|
|
13711
13978
|
details: { skillId, found: true, applicable: false }
|
|
13712
13979
|
};
|
|
13713
13980
|
}
|
|
13714
|
-
if (skill.tools.length > 0 && allowedTools
|
|
13981
|
+
if (skill.tools.length > 0 && allowedTools !== void 0) {
|
|
13715
13982
|
const missing = skill.tools.filter((t2) => !(coreToolNames?.has(t2) ?? false) && !allowedTools.includes(t2));
|
|
13716
13983
|
if (missing.length > 0) {
|
|
13717
13984
|
const msg = isZh ? `\u5F53\u524D\u52A9\u624B\u7F3A\u5C11\u8BE5\u6280\u80FD\u6240\u9700\u7684\u5DE5\u5177\uFF1A${missing.join(", ")}` : `Current assistant lacks tools required by this skill: ${missing.join(", ")}`;
|
|
@@ -13730,6 +13997,175 @@ function createActivateSkillTool(options) {
|
|
|
13730
13997
|
};
|
|
13731
13998
|
}
|
|
13732
13999
|
|
|
14000
|
+
// ../../packages/node-runtime/src/ai/chart-runtime.ts
|
|
14001
|
+
var CHART_CAPABILITY_CORE_TOOLS = ["get_schema"];
|
|
14002
|
+
var CHART_CAPABILITY_ANALYSIS_TOOLS = ["render_chart"];
|
|
14003
|
+
var RAW_SQL_TOOL_NAMES = /* @__PURE__ */ new Set(["execute_sql"]);
|
|
14004
|
+
function getChartCapabilityAllowedBuiltinTools(allowedTools) {
|
|
14005
|
+
const baseTools = (allowedTools ?? []).filter((toolName) => !RAW_SQL_TOOL_NAMES.has(toolName));
|
|
14006
|
+
return Array.from(/* @__PURE__ */ new Set([...baseTools, ...CHART_CAPABILITY_ANALYSIS_TOOLS]));
|
|
14007
|
+
}
|
|
14008
|
+
function getAllowedBuiltinToolsForChartAutoSkill(allowedTools) {
|
|
14009
|
+
if (!allowedTools) return void 0;
|
|
14010
|
+
if (allowedTools.length === 0) return [];
|
|
14011
|
+
return Array.from(/* @__PURE__ */ new Set([...allowedTools, ...CHART_CAPABILITY_ANALYSIS_TOOLS]));
|
|
14012
|
+
}
|
|
14013
|
+
function shouldUseChartCapabilityForMessage(message) {
|
|
14014
|
+
const normalized = message.trim().toLowerCase();
|
|
14015
|
+
if (!normalized) return false;
|
|
14016
|
+
return /(?:画|绘制|生成|做|出|展示).{0,8}(?:图|图表)|(?:图表|可视化|饼图|柱状图|条形图|折线图|热力图|趋势图|占比图|分布图|chart|charts|plot|visuali[sz]e|visuali[sz]ation|pie chart|bar chart|line chart|heatmap)/i.test(
|
|
14017
|
+
normalized
|
|
14018
|
+
);
|
|
14019
|
+
}
|
|
14020
|
+
function resolveChartRuntimeForRequest(options) {
|
|
14021
|
+
const locale = options.locale ?? "zh-CN";
|
|
14022
|
+
const isExplicitChartSkill = options.skillId === CHART_CAPABILITY_SKILL_ID;
|
|
14023
|
+
const isAutoChartSkill = options.enableAutoDetection === true && !options.skillId && shouldUseChartCapabilityForMessage(options.userMessage ?? "");
|
|
14024
|
+
if (!isExplicitChartSkill && !isAutoChartSkill) {
|
|
14025
|
+
return { isChartCapability: false };
|
|
14026
|
+
}
|
|
14027
|
+
return {
|
|
14028
|
+
isChartCapability: true,
|
|
14029
|
+
skillDef: { ...getChartCapabilitySkill(locale), chatScope: "all" },
|
|
14030
|
+
allowedBuiltinTools: getChartCapabilityAllowedBuiltinTools(options.assistantAllowedTools)
|
|
14031
|
+
};
|
|
14032
|
+
}
|
|
14033
|
+
function getChartCapabilitySkill(locale = "zh-CN") {
|
|
14034
|
+
const isZh = locale.startsWith("zh");
|
|
14035
|
+
return {
|
|
14036
|
+
id: CHART_CAPABILITY_SKILL_ID,
|
|
14037
|
+
name: isZh ? "\u7ED8\u56FE\u52A9\u624B" : "Chart Assistant",
|
|
14038
|
+
description: isZh ? "\u6309\u672C\u8F6E\u95EE\u9898\u751F\u6210\u7075\u6D3B\u7684\u804A\u5929\u6570\u636E\u56FE\u8868" : "Generate flexible charts for this chat question",
|
|
14039
|
+
tags: [isZh ? "\u56FE\u8868" : "chart"],
|
|
14040
|
+
chatScope: "all",
|
|
14041
|
+
tools: ["render_chart", "get_schema"],
|
|
14042
|
+
prompt: isZh ? ZH_PROMPT : EN_PROMPT,
|
|
14043
|
+
builtinId: CHART_CAPABILITY_SKILL_ID
|
|
14044
|
+
};
|
|
14045
|
+
}
|
|
14046
|
+
function getChartMenuLine(locale) {
|
|
14047
|
+
const skill = getChartCapabilitySkill(locale);
|
|
14048
|
+
const isZh = locale.startsWith("zh");
|
|
14049
|
+
const guidance = isZh ? "\u7528\u6237\u660E\u786E\u8981\u6C42\u56FE\u8868\u3001\u753B\u56FE\u3001\u5360\u6BD4\u3001\u8D8B\u52BF\u3001\u5206\u5E03\u3001\u997C\u56FE\u3001\u67F1\u72B6\u56FE\u3001\u6298\u7EBF\u56FE\u6216\u70ED\u529B\u56FE\u65F6\u4F18\u5148\u6FC0\u6D3B\uFF1B\u4E0D\u8981\u8F93\u51FA Python/JS \u7ED8\u56FE\u4EE3\u7801" : "Activate first when the user explicitly asks for charts, visualization, ratios, trends, distributions, pie, bar, line, or heatmap charts; do not output Python/JS chart code";
|
|
14050
|
+
return formatSkillMenuLine({
|
|
14051
|
+
id: skill.id,
|
|
14052
|
+
name: skill.name,
|
|
14053
|
+
description: skill.description,
|
|
14054
|
+
guidance
|
|
14055
|
+
});
|
|
14056
|
+
}
|
|
14057
|
+
function buildSkillMenuWithBuiltinChart(baseMenu, locale = "zh-CN", allowedTools) {
|
|
14058
|
+
if (allowedTools && !allowedTools.includes(CHART_CAPABILITY_ANALYSIS_TOOLS[0])) return baseMenu ?? null;
|
|
14059
|
+
if (baseMenu?.includes(CHART_CAPABILITY_SKILL_ID)) return baseMenu;
|
|
14060
|
+
const chartLine = getChartMenuLine(locale);
|
|
14061
|
+
return appendSkillMenuLines(baseMenu, [chartLine]) ?? "";
|
|
14062
|
+
}
|
|
14063
|
+
function getSkillConfigWithBuiltinChart(id, locale = "zh-CN", getSkillConfig) {
|
|
14064
|
+
if (id === CHART_CAPABILITY_SKILL_ID) return getChartCapabilitySkill(locale);
|
|
14065
|
+
return getSkillConfig(id);
|
|
14066
|
+
}
|
|
14067
|
+
var ZH_PROMPT = `\u4F60\u662F ChatLab \u7ED8\u56FE\u52A9\u624B\u3002\u672C\u8F6E\u7528\u6237\u5E0C\u671B\u4F60\u5728\u56DE\u7B54\u91CC\u81EA\u7136\u5D4C\u5165\u4E00\u5F20\u6216\u591A\u5F20\u56FE\u8868\u3002
|
|
14068
|
+
|
|
14069
|
+
\u4F60\u5FC5\u987B\u901A\u8FC7 render_chart \u5DE5\u5177\u751F\u6210\u56FE\u8868\u3002\u4E0D\u8981\u8F93\u51FA HTML\u3001JavaScript\u3001SVG\u3001Canvas\u3001ECharts option \u6216\u4EFB\u4F55\u6E32\u67D3\u4EE3\u7801\u3002
|
|
14070
|
+
|
|
14071
|
+
\u786C\u6027\u89C4\u5219\uFF1A
|
|
14072
|
+
1. \u7B2C\u4E00\u6B21\u5199 SQL \u524D\u5FC5\u987B\u5148\u8C03\u7528 get_schema\u3002\u7981\u6B62\u731C\u6D4B\u8868\u540D\u3001\u5B57\u6BB5\u540D\u6216\u65F6\u95F4\u5B57\u6BB5\u3002
|
|
14073
|
+
2. \u201C\u6700\u8FD1\u201D\u201C\u5230\u73B0\u5728\u201D\u201C\u5230\u6700\u8FD1\u201D\u5FC5\u987B\u7528\u6570\u636E\u4E2D\u7684 MAX(ts) \u6216\u7B49\u4EF7\u5B57\u6BB5\u786E\u5B9A\u7ED3\u675F\u65E5\u671F\uFF1B\u4E0D\u8981\u624B\u7B97\u6216\u81C6\u6D4B\u65E5\u671F\u3002
|
|
14074
|
+
3. ChatLab \u7684 message.ts \u662F\u79D2\u7EA7 Unix \u65F6\u95F4\u6233\uFF0C\u4F7F\u7528 date(ts, 'unixepoch', 'localtime')\uFF1B\u7981\u6B62\u5199 ts/1000\u3002
|
|
14075
|
+
4. \u201C\u6700\u8FD1\u7684 N \u4EBA/\u6210\u5458\u201D\u5FC5\u987B\u5148\u7528\u6570\u636E\u5B9A\u4E49\u5E76\u7B5B\u9009\u51FA N \u4E2A\u6210\u5458\uFF0C\u518D\u53EA\u7EDF\u8BA1\u8FD9\u4E9B\u6210\u5458\u3002
|
|
14076
|
+
5. \u6298\u7EBF\u56FE\u6709\u591A\u6761\u7EBF\u65F6\uFF0C\u6BCF\u6761\u7EBF\u5FC5\u987B\u6709\u660E\u786E series \u5B57\u6BB5\u542B\u4E49\uFF1B\u6309\u65E5\u671F\u7EDF\u8BA1\u65F6\u5E94\u8865\u9F50\u65E5\u671F \xD7 series \u7684 0 \u503C\uFF0C\u907F\u514D\u7F3A\u5931\u65E5\u671F\u5BFC\u81F4\u6298\u7EBF\u65AD\u88C2\u6216\u8BEF\u8FDE\u3002
|
|
14077
|
+
6. \u5DE5\u5177\u5931\u8D25\u3001SQL \u4FEE\u6B63\u3001schema \u63A2\u7D22\u8FC7\u7A0B\u4E0D\u8981\u5199\u8FDB\u6700\u7EC8\u56DE\u7B54\uFF1B\u6700\u7EC8\u53EA\u4FDD\u7559\u56FE\u8868\u548C\u7B80\u77ED\u7ED3\u8BBA\u3002
|
|
14078
|
+
7. \u56FE\u8868\u89E3\u91CA\u53EA\u80FD\u63CF\u8FF0\u6570\u636E\u76F4\u63A5\u652F\u6301\u7684\u8D8B\u52BF\u3001\u5CF0\u503C\u3001\u4F4E\u8C37\u3001\u5DEE\u5F02\u548C\u540C\u6B65\u6027\uFF0C\u7981\u6B62\u5938\u5F20\u62DF\u4EBA\u5316\u6216\u65E0\u6CD5\u4ECE\u56FE\u4E2D\u9A8C\u8BC1\u7684\u5173\u7CFB\u5224\u65AD\u3002
|
|
14079
|
+
|
|
14080
|
+
\u5DE5\u4F5C\u6D41\u7A0B\uFF1A
|
|
14081
|
+
1. \u8C03\u7528 get_schema\u3002
|
|
14082
|
+
2. \u6839\u636E schema \u548C\u7528\u6237\u8981\u6C42\u786E\u5B9A\u7EDF\u8BA1\u5BF9\u8C61\u3001\u65F6\u95F4\u8303\u56F4\u3001\u7EF4\u5EA6\u3001\u6307\u6807\u548C\u56FE\u8868\u7C7B\u578B\u3002
|
|
14083
|
+
3. \u5FC5\u8981\u65F6\u7528\u53EA\u8BFB SQL \u5728 render_chart \u4E2D\u5B8C\u6210\u6210\u5458\u7B5B\u9009\u3001\u65F6\u95F4\u8303\u56F4\u786E\u8BA4\u3001\u805A\u5408\u548C\u8865\u96F6\u3002
|
|
14084
|
+
4. \u8C03\u7528 render_chart\uFF0C\u63D0\u4EA4\u53EA\u8BFB SQL \u548C ChartSpec v1\u3002
|
|
14085
|
+
5. \u56FE\u8868\u751F\u6210\u540E\uFF0C\u7528 1-3 \u53E5\u7B80\u6D01\u6587\u5B57\u89E3\u91CA\u7ED3\u8BBA\u3002\u7528\u6237\u8981\u6C42\u591A\u5F20\u56FE\u65F6\uFF0C\u53EF\u4EE5\u591A\u6B21\u8C03\u7528 render_chart\u3002
|
|
14086
|
+
|
|
14087
|
+
\u5E38\u7528\u8BED\u3001\u53E3\u5934\u7985\u3001\u9AD8\u9891\u77ED\u53E5\u7C7B\u56FE\u8868\u5FC5\u987B\u6392\u9664\u975E\u771F\u4EBA\u6587\u672C\uFF1A\u53D1\u9001\u8005\u4E3A\u7CFB\u7EDF\u6D88\u606F\u3001\u5A92\u4F53\u5360\u4F4D\uFF08\u5982 [\u8868\u60C5\u5305]\u3001[\u56FE\u7247]\u3001[\u8BED\u97F3]\u3001[\u89C6\u9891]\u3001[\u6587\u4EF6]\u3001[\u94FE\u63A5]\u3001[\u7EA2\u5305]\u3001[\u8F6C\u8D26]\uFF09\u4EE5\u53CA\u64A4\u56DE/\u5220\u9664\u63D0\u793A\u90FD\u4E0D\u80FD\u8FDB\u5165\u7EDF\u8BA1\u3002
|
|
14088
|
+
|
|
14089
|
+
ChartSpec v1 \u652F\u6301\uFF1A
|
|
14090
|
+
- bar: encoding.x + encoding.y
|
|
14091
|
+
- line: encoding.x + encoding.y\uFF0C\u53EF\u9009 encoding.series \u8868\u793A\u6BCF\u6761\u7EBF\u7684\u542B\u4E49
|
|
14092
|
+
- pie: encoding.label + encoding.value
|
|
14093
|
+
- heatmap: encoding.x + encoding.y + encoding.value
|
|
14094
|
+
|
|
14095
|
+
ChartSpec \u793A\u4F8B\uFF1A
|
|
14096
|
+
{
|
|
14097
|
+
"version": 1,
|
|
14098
|
+
"type": "line",
|
|
14099
|
+
"title": "\u6700\u8FD1 30 \u5929\u6210\u5458\u53D1\u8A00\u8D8B\u52BF",
|
|
14100
|
+
"encoding": { "x": "day", "y": "msg_count", "series": "member_name" },
|
|
14101
|
+
"unit": "\u6761"
|
|
14102
|
+
}
|
|
14103
|
+
|
|
14104
|
+
\u7528\u6237\u660E\u786E\u8981\u6C42\u56FE\u8868\u65F6\u5FC5\u987B\u5C1D\u8BD5\u751F\u6210\u3002\u7528\u6237\u6CA1\u6709\u660E\u786E\u8981\u6C42\u65F6\uFF0C\u53EA\u6709\u6392\u540D\u3001\u8D8B\u52BF\u3001\u5206\u5E03\u3001\u5360\u6BD4\u6216\u4E8C\u7EF4\u5BC6\u5EA6\u660E\u663E\u66F4\u6E05\u695A\u65F6\u624D\u4E3B\u52A8\u751F\u6210\uFF0C\u4E14\u9ED8\u8BA4\u6700\u591A\u4E00\u5F20\u3002`;
|
|
14105
|
+
var EN_PROMPT = `You are the ChatLab Chart Assistant. In this turn, the user wants one or more charts embedded naturally in the answer.
|
|
14106
|
+
|
|
14107
|
+
You must generate charts through the render_chart tool. Do not output HTML, JavaScript, SVG, Canvas, ECharts options, or rendering code.
|
|
14108
|
+
|
|
14109
|
+
Hard rules:
|
|
14110
|
+
1. Always call get_schema before writing the first SQL query. Do not guess table names, field names, or timestamp fields.
|
|
14111
|
+
2. For "latest", "until now", or "through the latest date", derive the end date from MAX(ts) or the equivalent timestamp field in the data. Do not hand-calculate or assume dates.
|
|
14112
|
+
3. ChatLab message.ts is a Unix timestamp in seconds. Use date(ts, 'unixepoch', 'localtime'); never write ts/1000.
|
|
14113
|
+
4. For "latest N members" or "recent N people", first define and select those N members from the data, then count only those members.
|
|
14114
|
+
5. For multi-series line charts, every line must have an explicit series field. For daily counts, fill the date x series grid with zero values so missing days do not break or mislead the line.
|
|
14115
|
+
6. Do not include failed SQL attempts, schema exploration, or retry reasoning in the final answer. Final answer should contain only the chart and a short conclusion.
|
|
14116
|
+
7. Explain only trends, peaks, lows, differences, and synchrony directly supported by chart data. Do not make exaggerated personality or relationship claims.
|
|
14117
|
+
|
|
14118
|
+
Workflow:
|
|
14119
|
+
1. Call get_schema.
|
|
14120
|
+
2. Derive the target members, time range, dimensions, metrics, and chart type from schema and the user request.
|
|
14121
|
+
3. When needed, use read-only SQL inside render_chart to select members, determine time range, aggregate data, and fill zero rows.
|
|
14122
|
+
4. Call render_chart with read-only SQL and ChartSpec v1.
|
|
14123
|
+
5. After the chart is generated, explain the key finding in 1-3 concise sentences. If the user asks for multiple charts, call render_chart multiple times.
|
|
14124
|
+
|
|
14125
|
+
For catchphrase, common phrase, or frequent short-text charts, exclude non-human text from the SQL: system-message senders, media placeholders such as [Sticker], [Image], [Photo], [Voice], [Video], [File], [Link], and recall/deletion notices must not be counted.
|
|
14126
|
+
|
|
14127
|
+
ChartSpec v1 supports:
|
|
14128
|
+
- bar: encoding.x + encoding.y
|
|
14129
|
+
- line: encoding.x + encoding.y, optional encoding.series for the meaning of each line
|
|
14130
|
+
- pie: encoding.label + encoding.value
|
|
14131
|
+
- heatmap: encoding.x + encoding.y + encoding.value
|
|
14132
|
+
|
|
14133
|
+
ChartSpec example:
|
|
14134
|
+
{
|
|
14135
|
+
"version": 1,
|
|
14136
|
+
"type": "line",
|
|
14137
|
+
"title": "Member message trend in the last 30 days",
|
|
14138
|
+
"encoding": { "x": "day", "y": "msg_count", "series": "member_name" },
|
|
14139
|
+
"unit": "messages"
|
|
14140
|
+
}
|
|
14141
|
+
|
|
14142
|
+
When the user explicitly asks for charts, you must try to generate them. If the user does not explicitly ask, add at most one chart only when ranking, trend, distribution, ratio, or two-dimensional density is clearly easier to understand visually.`;
|
|
14143
|
+
|
|
14144
|
+
// ../../packages/node-runtime/src/ai/chart-schema-gate.ts
|
|
14145
|
+
var CHART_SCHEMA_REQUIRED_MESSAGE = "Error: Call get_schema before render_chart. Do not guess table names, fields, or timestamp units.";
|
|
14146
|
+
function createChartSchemaGateState() {
|
|
14147
|
+
return { schemaSeen: false };
|
|
14148
|
+
}
|
|
14149
|
+
function wrapWithChartSchemaGate(tool, state) {
|
|
14150
|
+
const originalExecute = tool.execute;
|
|
14151
|
+
return {
|
|
14152
|
+
...tool,
|
|
14153
|
+
execute: async (toolCallId, params, signal, onUpdate) => {
|
|
14154
|
+
if (tool.name === "render_chart" && !state.schemaSeen) {
|
|
14155
|
+
return {
|
|
14156
|
+
content: [{ type: "text", text: CHART_SCHEMA_REQUIRED_MESSAGE }],
|
|
14157
|
+
details: null
|
|
14158
|
+
};
|
|
14159
|
+
}
|
|
14160
|
+
const result = await originalExecute(toolCallId, params, signal, onUpdate);
|
|
14161
|
+
if (tool.name === "get_schema") {
|
|
14162
|
+
state.schemaSeen = true;
|
|
14163
|
+
}
|
|
14164
|
+
return result;
|
|
14165
|
+
}
|
|
14166
|
+
};
|
|
14167
|
+
}
|
|
14168
|
+
|
|
13733
14169
|
// ../../packages/node-runtime/src/ai/compression/compressor.ts
|
|
13734
14170
|
var DEFAULT_CONTEXT_WINDOW = 128e3;
|
|
13735
14171
|
var INITIAL_COMPRESSION_PROMPT = `You are a context compression assistant. Compress the conversation below into a structured summary.
|
|
@@ -14132,6 +14568,7 @@ function compileRules(rules, logger) {
|
|
|
14132
14568
|
}
|
|
14133
14569
|
|
|
14134
14570
|
// ../../packages/node-runtime/src/ai/preprocessor/builtin-rules.ts
|
|
14571
|
+
var DESENSITIZE_RULES_SCHEMA_VERSION = 2;
|
|
14135
14572
|
var BUILTIN_DESENSITIZE_RULES = [
|
|
14136
14573
|
// ==================== 中国 (zh-CN) ====================
|
|
14137
14574
|
{
|
|
@@ -14141,7 +14578,8 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14141
14578
|
replacement: "[\u624B\u673A\u53F7]",
|
|
14142
14579
|
enabled: true,
|
|
14143
14580
|
builtin: true,
|
|
14144
|
-
locales: ["zh-CN"]
|
|
14581
|
+
locales: ["zh-CN"],
|
|
14582
|
+
group: "region_cn"
|
|
14145
14583
|
},
|
|
14146
14584
|
{
|
|
14147
14585
|
id: "cn_id_card",
|
|
@@ -14150,25 +14588,28 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14150
14588
|
replacement: "[\u8EAB\u4EFD\u8BC1]",
|
|
14151
14589
|
enabled: true,
|
|
14152
14590
|
builtin: true,
|
|
14153
|
-
locales: ["zh-CN"]
|
|
14591
|
+
locales: ["zh-CN"],
|
|
14592
|
+
group: "region_cn"
|
|
14154
14593
|
},
|
|
14155
14594
|
{
|
|
14156
14595
|
id: "cn_bank_card",
|
|
14157
14596
|
label: "desensitize.rules.cn_bank_card",
|
|
14158
14597
|
pattern: "(?<!\\d)\\d{16,19}(?!\\d)",
|
|
14159
14598
|
replacement: "[\u94F6\u884C\u5361]",
|
|
14160
|
-
enabled:
|
|
14599
|
+
enabled: true,
|
|
14161
14600
|
builtin: true,
|
|
14162
|
-
locales: ["zh-CN"]
|
|
14601
|
+
locales: ["zh-CN"],
|
|
14602
|
+
group: "region_cn"
|
|
14163
14603
|
},
|
|
14164
14604
|
{
|
|
14165
14605
|
id: "cn_landline",
|
|
14166
14606
|
label: "desensitize.rules.cn_landline",
|
|
14167
14607
|
pattern: "(?<!\\d)0\\d{2,3}-?\\d{7,8}(?!\\d)",
|
|
14168
14608
|
replacement: "[\u5EA7\u673A\u53F7]",
|
|
14169
|
-
enabled:
|
|
14609
|
+
enabled: true,
|
|
14170
14610
|
builtin: true,
|
|
14171
|
-
locales: ["zh-CN"]
|
|
14611
|
+
locales: ["zh-CN"],
|
|
14612
|
+
group: "region_cn"
|
|
14172
14613
|
},
|
|
14173
14614
|
// ==================== 美国 (en-US) ====================
|
|
14174
14615
|
{
|
|
@@ -14178,7 +14619,8 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14178
14619
|
replacement: "[SSN]",
|
|
14179
14620
|
enabled: true,
|
|
14180
14621
|
builtin: true,
|
|
14181
|
-
locales: ["en-US"]
|
|
14622
|
+
locales: ["en-US"],
|
|
14623
|
+
group: "region_us"
|
|
14182
14624
|
},
|
|
14183
14625
|
{
|
|
14184
14626
|
id: "us_phone",
|
|
@@ -14187,16 +14629,18 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14187
14629
|
replacement: "[Phone]",
|
|
14188
14630
|
enabled: true,
|
|
14189
14631
|
builtin: true,
|
|
14190
|
-
locales: ["en-US"]
|
|
14632
|
+
locales: ["en-US"],
|
|
14633
|
+
group: "region_us"
|
|
14191
14634
|
},
|
|
14192
14635
|
{
|
|
14193
14636
|
id: "us_drivers_license",
|
|
14194
14637
|
label: "desensitize.rules.us_drivers_license",
|
|
14195
14638
|
pattern: "(?<![A-Z])\\b[A-Z]\\d{7,8}\\b",
|
|
14196
14639
|
replacement: "[Driver's License]",
|
|
14197
|
-
enabled:
|
|
14640
|
+
enabled: true,
|
|
14198
14641
|
builtin: true,
|
|
14199
|
-
locales: ["en-US"]
|
|
14642
|
+
locales: ["en-US"],
|
|
14643
|
+
group: "region_us"
|
|
14200
14644
|
},
|
|
14201
14645
|
// ==================== 日本 (ja-JP) ====================
|
|
14202
14646
|
{
|
|
@@ -14206,16 +14650,18 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14206
14650
|
replacement: "[\u96FB\u8A71\u756A\u53F7]",
|
|
14207
14651
|
enabled: true,
|
|
14208
14652
|
builtin: true,
|
|
14209
|
-
locales: ["ja-JP"]
|
|
14653
|
+
locales: ["ja-JP"],
|
|
14654
|
+
group: "region_jp"
|
|
14210
14655
|
},
|
|
14211
14656
|
{
|
|
14212
14657
|
id: "jp_my_number",
|
|
14213
14658
|
label: "desensitize.rules.jp_my_number",
|
|
14214
14659
|
pattern: "(?<!\\d)\\d{4}\\s?\\d{4}\\s?\\d{4}(?!\\d)",
|
|
14215
14660
|
replacement: "[\u30DE\u30A4\u30CA\u30F3\u30D0\u30FC]",
|
|
14216
|
-
enabled:
|
|
14661
|
+
enabled: true,
|
|
14217
14662
|
builtin: true,
|
|
14218
|
-
locales: ["ja-JP"]
|
|
14663
|
+
locales: ["ja-JP"],
|
|
14664
|
+
group: "region_jp"
|
|
14219
14665
|
},
|
|
14220
14666
|
// ==================== 韩国 (ko-KR) ====================
|
|
14221
14667
|
{
|
|
@@ -14225,7 +14671,8 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14225
14671
|
replacement: "[\uC804\uD654\uBC88\uD638]",
|
|
14226
14672
|
enabled: true,
|
|
14227
14673
|
builtin: true,
|
|
14228
|
-
locales: ["ko-KR"]
|
|
14674
|
+
locales: ["ko-KR"],
|
|
14675
|
+
group: "region_kr"
|
|
14229
14676
|
},
|
|
14230
14677
|
{
|
|
14231
14678
|
id: "kr_rrn",
|
|
@@ -14234,7 +14681,8 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14234
14681
|
replacement: "[\uC8FC\uBBFC\uBC88\uD638]",
|
|
14235
14682
|
enabled: true,
|
|
14236
14683
|
builtin: true,
|
|
14237
|
-
locales: ["ko-KR"]
|
|
14684
|
+
locales: ["ko-KR"],
|
|
14685
|
+
group: "region_kr"
|
|
14238
14686
|
},
|
|
14239
14687
|
// ==================== 凭据 / Token (所有语言) ====================
|
|
14240
14688
|
{
|
|
@@ -14244,7 +14692,8 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14244
14692
|
replacement: "[API Key]",
|
|
14245
14693
|
enabled: true,
|
|
14246
14694
|
builtin: true,
|
|
14247
|
-
locales: []
|
|
14695
|
+
locales: [],
|
|
14696
|
+
group: "credentials"
|
|
14248
14697
|
},
|
|
14249
14698
|
{
|
|
14250
14699
|
id: "bearer_token",
|
|
@@ -14253,7 +14702,8 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14253
14702
|
replacement: "Bearer [Token]",
|
|
14254
14703
|
enabled: true,
|
|
14255
14704
|
builtin: true,
|
|
14256
|
-
locales: []
|
|
14705
|
+
locales: [],
|
|
14706
|
+
group: "credentials"
|
|
14257
14707
|
},
|
|
14258
14708
|
// ==================== 通用 (所有语言) ====================
|
|
14259
14709
|
{
|
|
@@ -14263,34 +14713,38 @@ var BUILTIN_DESENSITIZE_RULES = [
|
|
|
14263
14713
|
replacement: "[Email]",
|
|
14264
14714
|
enabled: true,
|
|
14265
14715
|
builtin: true,
|
|
14266
|
-
locales: []
|
|
14716
|
+
locales: [],
|
|
14717
|
+
group: "global_contact"
|
|
14267
14718
|
},
|
|
14268
14719
|
{
|
|
14269
14720
|
id: "credit_card",
|
|
14270
14721
|
label: "desensitize.rules.credit_card",
|
|
14271
14722
|
pattern: "(?<!\\d)(?:4\\d{3}|5[1-5]\\d{2}|3[47]\\d{2}|6(?:011|5\\d{2}))[-\\s.]?\\d{4}[-\\s.]?\\d{4}[-\\s.]?\\d{4}(?!\\d)",
|
|
14272
14723
|
replacement: "[Credit Card]",
|
|
14273
|
-
enabled:
|
|
14724
|
+
enabled: true,
|
|
14274
14725
|
builtin: true,
|
|
14275
|
-
locales: []
|
|
14726
|
+
locales: [],
|
|
14727
|
+
group: "global_financial"
|
|
14276
14728
|
},
|
|
14277
14729
|
{
|
|
14278
14730
|
id: "ipv4",
|
|
14279
14731
|
label: "desensitize.rules.ipv4",
|
|
14280
14732
|
pattern: "(?<!\\d)(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)(?!\\d)",
|
|
14281
14733
|
replacement: "[IP]",
|
|
14282
|
-
enabled:
|
|
14734
|
+
enabled: true,
|
|
14283
14735
|
builtin: true,
|
|
14284
|
-
locales: []
|
|
14736
|
+
locales: [],
|
|
14737
|
+
group: "global_network"
|
|
14285
14738
|
},
|
|
14286
14739
|
{
|
|
14287
14740
|
id: "url",
|
|
14288
14741
|
label: "desensitize.rules.url",
|
|
14289
14742
|
pattern: 'https?://[^\\s<>"]+',
|
|
14290
14743
|
replacement: "[URL]",
|
|
14291
|
-
enabled:
|
|
14744
|
+
enabled: true,
|
|
14292
14745
|
builtin: true,
|
|
14293
|
-
locales: []
|
|
14746
|
+
locales: [],
|
|
14747
|
+
group: "global_network"
|
|
14294
14748
|
}
|
|
14295
14749
|
];
|
|
14296
14750
|
function getDefaultRulesForLocale(locale) {
|
|
@@ -14298,12 +14752,16 @@ function getDefaultRulesForLocale(locale) {
|
|
|
14298
14752
|
(rule) => ({ ...rule })
|
|
14299
14753
|
);
|
|
14300
14754
|
}
|
|
14301
|
-
function
|
|
14302
|
-
|
|
14303
|
-
|
|
14304
|
-
|
|
14305
|
-
|
|
14306
|
-
|
|
14755
|
+
function applyDesensitizeRuleOverrides(rules, overrides = {}) {
|
|
14756
|
+
return rules.map((rule) => ({
|
|
14757
|
+
...rule,
|
|
14758
|
+
enabled: overrides[rule.id] ?? rule.enabled
|
|
14759
|
+
}));
|
|
14760
|
+
}
|
|
14761
|
+
function mergeRulesForLocale(existing, locale, overrides = {}) {
|
|
14762
|
+
const customRules = existing.filter((rule) => !rule.builtin);
|
|
14763
|
+
const builtinRules = applyDesensitizeRuleOverrides(getDefaultRulesForLocale(locale), overrides);
|
|
14764
|
+
return [...builtinRules, ...customRules];
|
|
14307
14765
|
}
|
|
14308
14766
|
|
|
14309
14767
|
// ../../packages/node-runtime/src/ai/preprocessor/format.ts
|
|
@@ -14487,6 +14945,11 @@ import {
|
|
|
14487
14945
|
streamSimple as defaultStreamSimple,
|
|
14488
14946
|
clampThinkingLevel
|
|
14489
14947
|
} from "@earendil-works/pi-ai";
|
|
14948
|
+
|
|
14949
|
+
// ../../packages/node-runtime/src/ai/agent/constants.ts
|
|
14950
|
+
var DEFAULT_MAX_TOOL_ROUNDS = 10;
|
|
14951
|
+
|
|
14952
|
+
// ../../packages/node-runtime/src/ai/agent/core.ts
|
|
14490
14953
|
function createEmptyPiUsage() {
|
|
14491
14954
|
return {
|
|
14492
14955
|
input: 0,
|
|
@@ -14529,7 +14992,7 @@ async function runAgentCore(options) {
|
|
|
14529
14992
|
tools,
|
|
14530
14993
|
history,
|
|
14531
14994
|
userMessage,
|
|
14532
|
-
maxToolRounds =
|
|
14995
|
+
maxToolRounds = DEFAULT_MAX_TOOL_ROUNDS,
|
|
14533
14996
|
abortSignal,
|
|
14534
14997
|
steerMessage = "Please provide your final answer based on the information gathered.",
|
|
14535
14998
|
onEvent,
|
|
@@ -15167,6 +15630,19 @@ var zh_CN_default = {
|
|
|
15167
15630
|
days: "\u7EDF\u8BA1\u6700\u8FD1\u591A\u5C11\u5929\u7684\u6570\u636E",
|
|
15168
15631
|
top_n: "\u8FD4\u56DE\u524D\u591A\u5C11\u4E2A\u5173\u952E\u8BCD"
|
|
15169
15632
|
}
|
|
15633
|
+
},
|
|
15634
|
+
get_schema: {
|
|
15635
|
+
desc: "\u67E5\u770B\u804A\u5929\u6570\u636E\u5E93\u8868\u7ED3\u6784\u3002\u7ED8\u56FE\u6216\u81EA\u5B9A\u4E49 SQL \u524D\u5E94\u5148\u7528\u5B83\u786E\u8BA4\u8868\u540D\u548C\u5B57\u6BB5\u540D\u3002",
|
|
15636
|
+
params: {}
|
|
15637
|
+
},
|
|
15638
|
+
render_chart: {
|
|
15639
|
+
desc: "\u6839\u636E\u53EA\u8BFB SQL \u548C ChartSpec v1 \u751F\u6210 ChatLab \u539F\u751F\u56FE\u8868\u3002\u652F\u6301 bar\u3001line\u3001pie\u3001heatmap\u3002\u7981\u6B62\u8F93\u51FA HTML\u3001JavaScript\u3001SVG\u3001ECharts option \u6216\u6E32\u67D3\u4EE3\u7801\u3002",
|
|
15640
|
+
params: {
|
|
15641
|
+
sql: "\u53EA\u8BFB SELECT \u6216 WITH SELECT SQL\u3002\u5FC5\u987B\u8FD4\u56DE ChartSpec encoding \u4E2D\u5F15\u7528\u7684\u5B57\u6BB5\u3002",
|
|
15642
|
+
params: "SQL \u547D\u540D\u53C2\u6570\u5BF9\u8C61\uFF1B\u4E0D\u9700\u8981\u53C2\u6570\u65F6\u4F20\u7A7A\u5BF9\u8C61\u3002",
|
|
15643
|
+
chartSpec: "ChartSpec v1\uFF0C\u5305\u542B version\u3001type\u3001title\u3001encoding\u3002",
|
|
15644
|
+
maxRows: "\u56FE\u8868\u67E5\u8BE2\u6700\u5927\u884C\u6570\uFF0C\u9ED8\u8BA4 1000\u3002"
|
|
15645
|
+
}
|
|
15170
15646
|
}
|
|
15171
15647
|
},
|
|
15172
15648
|
agent: {
|
|
@@ -15489,6 +15965,19 @@ Returned summaries are brief descriptions of each session, helping quickly locat
|
|
|
15489
15965
|
days: "Number of recent days to analyze",
|
|
15490
15966
|
top_n: "Number of top keywords to return"
|
|
15491
15967
|
}
|
|
15968
|
+
},
|
|
15969
|
+
get_schema: {
|
|
15970
|
+
desc: "Inspect the chat database schema. Use it before charting or custom SQL when table or field names are uncertain.",
|
|
15971
|
+
params: {}
|
|
15972
|
+
},
|
|
15973
|
+
render_chart: {
|
|
15974
|
+
desc: "Generate a native ChatLab chart from read-only SQL and ChartSpec v1. Supports bar, line, pie, and heatmap. Do not output HTML, JavaScript, SVG, ECharts options, or rendering code.",
|
|
15975
|
+
params: {
|
|
15976
|
+
sql: "Read-only SELECT or WITH SELECT SQL. It must return fields referenced by ChartSpec encoding.",
|
|
15977
|
+
params: "Named SQL parameters. Use an empty object when no parameters are needed.",
|
|
15978
|
+
chartSpec: "ChartSpec v1 with version, type, title, and encoding.",
|
|
15979
|
+
maxRows: "Maximum chart query rows. Default 1000."
|
|
15980
|
+
}
|
|
15492
15981
|
}
|
|
15493
15982
|
},
|
|
15494
15983
|
// ===== AI Agent system prompts =====
|
|
@@ -15807,6 +16296,19 @@ var ja_JP_default = {
|
|
|
15807
16296
|
days: "\u76F4\u8FD1\u4F55\u65E5\u9593\u306E\u30C7\u30FC\u30BF\u3092\u96C6\u8A08\u3059\u308B\u304B",
|
|
15808
16297
|
top_n: "\u4E0A\u4F4D\u4F55\u500B\u306E\u30AD\u30FC\u30EF\u30FC\u30C9\u3092\u8FD4\u5374\u3059\u308B\u304B"
|
|
15809
16298
|
}
|
|
16299
|
+
},
|
|
16300
|
+
get_schema: {
|
|
16301
|
+
desc: "\u30C1\u30E3\u30C3\u30C8\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30B9\u30AD\u30FC\u30DE\u3092\u78BA\u8A8D\u3057\u307E\u3059\u3002\u30C1\u30E3\u30FC\u30C8\u4F5C\u6210\u3084\u30AB\u30B9\u30BF\u30E0 SQL \u306E\u524D\u306B\u30C6\u30FC\u30D6\u30EB\u540D\u3068\u30D5\u30A3\u30FC\u30EB\u30C9\u540D\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
16302
|
+
params: {}
|
|
16303
|
+
},
|
|
16304
|
+
render_chart: {
|
|
16305
|
+
desc: "\u8AAD\u307F\u53D6\u308A\u5C02\u7528 SQL \u3068 ChartSpec v1 \u304B\u3089 ChatLab \u30CD\u30A4\u30C6\u30A3\u30D6\u30C1\u30E3\u30FC\u30C8\u3092\u751F\u6210\u3057\u307E\u3059\u3002bar\u3001line\u3001pie\u3001heatmap \u3092\u30B5\u30DD\u30FC\u30C8\u3057\u307E\u3059\u3002HTML\u3001JavaScript\u3001SVG\u3001ECharts option\u3001\u63CF\u753B\u30B3\u30FC\u30C9\u306F\u51FA\u529B\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002",
|
|
16306
|
+
params: {
|
|
16307
|
+
sql: "\u8AAD\u307F\u53D6\u308A\u5C02\u7528\u306E SELECT \u307E\u305F\u306F WITH SELECT SQL\u3002ChartSpec encoding \u3067\u53C2\u7167\u3059\u308B\u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u8FD4\u3059\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002",
|
|
16308
|
+
params: "SQL \u306E\u540D\u524D\u4ED8\u304D\u30D1\u30E9\u30E1\u30FC\u30BF\u3002\u4E0D\u8981\u306A\u5834\u5408\u306F\u7A7A\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3092\u6E21\u3057\u307E\u3059\u3002",
|
|
16309
|
+
chartSpec: "version\u3001type\u3001title\u3001encoding \u3092\u542B\u3080 ChartSpec v1\u3002",
|
|
16310
|
+
maxRows: "\u30C1\u30E3\u30FC\u30C8\u30AF\u30A8\u30EA\u306E\u6700\u5927\u884C\u6570\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u306F 1000\u3002"
|
|
16311
|
+
}
|
|
15810
16312
|
}
|
|
15811
16313
|
},
|
|
15812
16314
|
agent: {
|
|
@@ -16126,6 +16628,19 @@ var zh_TW_default = {
|
|
|
16126
16628
|
days: "\u7D71\u8A08\u6700\u8FD1\u591A\u5C11\u5929\u7684\u8CC7\u6599",
|
|
16127
16629
|
top_n: "\u56DE\u50B3\u524D\u591A\u5C11\u500B\u95DC\u9375\u8A5E"
|
|
16128
16630
|
}
|
|
16631
|
+
},
|
|
16632
|
+
get_schema: {
|
|
16633
|
+
desc: "\u67E5\u770B\u804A\u5929\u8CC7\u6599\u5EAB\u8868\u7D50\u69CB\u3002\u7E6A\u5716\u6216\u81EA\u8A02 SQL \u524D\u61C9\u5148\u7528\u5B83\u78BA\u8A8D\u8868\u540D\u548C\u6B04\u4F4D\u540D\u3002",
|
|
16634
|
+
params: {}
|
|
16635
|
+
},
|
|
16636
|
+
render_chart: {
|
|
16637
|
+
desc: "\u6839\u64DA\u552F\u8B80 SQL \u548C ChartSpec v1 \u751F\u6210 ChatLab \u539F\u751F\u5716\u8868\u3002\u652F\u63F4 bar\u3001line\u3001pie\u3001heatmap\u3002\u7981\u6B62\u8F38\u51FA HTML\u3001JavaScript\u3001SVG\u3001ECharts option \u6216\u6E32\u67D3\u7A0B\u5F0F\u78BC\u3002",
|
|
16638
|
+
params: {
|
|
16639
|
+
sql: "\u552F\u8B80 SELECT \u6216 WITH SELECT SQL\u3002\u5FC5\u9808\u8FD4\u56DE ChartSpec encoding \u4E2D\u5F15\u7528\u7684\u6B04\u4F4D\u3002",
|
|
16640
|
+
params: "SQL \u547D\u540D\u53C3\u6578\u7269\u4EF6\uFF1B\u4E0D\u9700\u8981\u53C3\u6578\u6642\u50B3\u7A7A\u7269\u4EF6\u3002",
|
|
16641
|
+
chartSpec: "ChartSpec v1\uFF0C\u5305\u542B version\u3001type\u3001title\u3001encoding\u3002",
|
|
16642
|
+
maxRows: "\u5716\u8868\u67E5\u8A62\u6700\u5927\u884C\u6578\uFF0C\u9810\u8A2D 1000\u3002"
|
|
16643
|
+
}
|
|
16129
16644
|
}
|
|
16130
16645
|
},
|
|
16131
16646
|
agent: {
|
|
@@ -17904,11 +18419,13 @@ var DEFAULTS = {
|
|
|
17904
18419
|
pinnedSessionIds: [],
|
|
17905
18420
|
aiPreprocessConfig: {
|
|
17906
18421
|
dataCleaning: true,
|
|
17907
|
-
mergeConsecutive:
|
|
18422
|
+
mergeConsecutive: true,
|
|
17908
18423
|
mergeWindowSeconds: 180,
|
|
17909
18424
|
blacklistKeywords: [],
|
|
17910
|
-
denoise:
|
|
17911
|
-
desensitize:
|
|
18425
|
+
denoise: true,
|
|
18426
|
+
desensitize: true,
|
|
18427
|
+
desensitizeRulesSchemaVersion: DESENSITIZE_RULES_SCHEMA_VERSION,
|
|
18428
|
+
desensitizeBuiltinRuleOverrides: {},
|
|
17912
18429
|
desensitizeRules: [],
|
|
17913
18430
|
anonymizeNames: false
|
|
17914
18431
|
},
|
|
@@ -17947,7 +18464,11 @@ var PreferencesManager = class {
|
|
|
17947
18464
|
if (fs35.existsSync(this.filePath)) {
|
|
17948
18465
|
const raw = fs35.readFileSync(this.filePath, "utf-8");
|
|
17949
18466
|
const parsed = JSON.parse(raw);
|
|
17950
|
-
|
|
18467
|
+
const migrated = this.migrateLegacyDesensitizeRules(parsed, raw);
|
|
18468
|
+
this.cache = this.mergeDefaults(migrated.preferences);
|
|
18469
|
+
if (migrated.changed) {
|
|
18470
|
+
this.writePreferences(this.cache);
|
|
18471
|
+
}
|
|
17951
18472
|
return this.cache;
|
|
17952
18473
|
}
|
|
17953
18474
|
} catch (err) {
|
|
@@ -17963,12 +18484,12 @@ var PreferencesManager = class {
|
|
|
17963
18484
|
current,
|
|
17964
18485
|
partial
|
|
17965
18486
|
);
|
|
17966
|
-
|
|
17967
|
-
|
|
17968
|
-
|
|
17969
|
-
fs35.mkdirSync(dir, { recursive: true });
|
|
18487
|
+
if (Object.prototype.hasOwnProperty.call(partial.aiPreprocessConfig ?? {}, "desensitizeBuiltinRuleOverrides")) {
|
|
18488
|
+
const mergedAiPreprocessConfig = merged.aiPreprocessConfig;
|
|
18489
|
+
mergedAiPreprocessConfig.desensitizeBuiltinRuleOverrides = partial.aiPreprocessConfig?.desensitizeBuiltinRuleOverrides;
|
|
17970
18490
|
}
|
|
17971
|
-
|
|
18491
|
+
this.cache = this.mergeDefaults(merged);
|
|
18492
|
+
this.writePreferences(this.cache);
|
|
17972
18493
|
return { success: true };
|
|
17973
18494
|
} catch (err) {
|
|
17974
18495
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -17985,7 +18506,7 @@ var PreferencesManager = class {
|
|
|
17985
18506
|
mergeDefaults(partial) {
|
|
17986
18507
|
return {
|
|
17987
18508
|
pinnedSessionIds: partial.pinnedSessionIds ?? DEFAULTS.pinnedSessionIds,
|
|
17988
|
-
aiPreprocessConfig: partial.aiPreprocessConfig ?
|
|
18509
|
+
aiPreprocessConfig: partial.aiPreprocessConfig ? this.normalizeAiPreprocessConfig(partial.aiPreprocessConfig) : { ...DEFAULTS.aiPreprocessConfig },
|
|
17989
18510
|
aiGlobalSettings: partial.aiGlobalSettings ? {
|
|
17990
18511
|
...DEFAULTS.aiGlobalSettings,
|
|
17991
18512
|
...partial.aiGlobalSettings,
|
|
@@ -18000,6 +18521,75 @@ var PreferencesManager = class {
|
|
|
18000
18521
|
filterHistory: partial.filterHistory ?? DEFAULTS.filterHistory
|
|
18001
18522
|
};
|
|
18002
18523
|
}
|
|
18524
|
+
normalizeAiPreprocessConfig(partial) {
|
|
18525
|
+
const defaults = DEFAULTS.aiPreprocessConfig;
|
|
18526
|
+
const rules = Array.isArray(partial?.desensitizeRules) ? partial.desensitizeRules : [];
|
|
18527
|
+
const customRules = rules.filter((rule) => !rule.builtin);
|
|
18528
|
+
return {
|
|
18529
|
+
dataCleaning: partial?.dataCleaning ?? defaults.dataCleaning,
|
|
18530
|
+
mergeConsecutive: partial?.mergeConsecutive ?? defaults.mergeConsecutive,
|
|
18531
|
+
mergeWindowSeconds: partial?.mergeWindowSeconds ?? defaults.mergeWindowSeconds,
|
|
18532
|
+
blacklistKeywords: partial?.blacklistKeywords ?? defaults.blacklistKeywords,
|
|
18533
|
+
denoise: partial?.denoise ?? defaults.denoise,
|
|
18534
|
+
desensitize: partial?.desensitize ?? defaults.desensitize,
|
|
18535
|
+
desensitizeRulesSchemaVersion: DESENSITIZE_RULES_SCHEMA_VERSION,
|
|
18536
|
+
desensitizeBuiltinRuleOverrides: this.normalizeBooleanMap(partial?.desensitizeBuiltinRuleOverrides),
|
|
18537
|
+
desensitizeRules: customRules,
|
|
18538
|
+
anonymizeNames: partial?.anonymizeNames ?? defaults.anonymizeNames
|
|
18539
|
+
};
|
|
18540
|
+
}
|
|
18541
|
+
normalizeBooleanMap(value) {
|
|
18542
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
18543
|
+
const result = {};
|
|
18544
|
+
for (const [key, flag] of Object.entries(value)) {
|
|
18545
|
+
if (typeof flag === "boolean") result[key] = flag;
|
|
18546
|
+
}
|
|
18547
|
+
return result;
|
|
18548
|
+
}
|
|
18549
|
+
migrateLegacyDesensitizeRules(partial, rawContent) {
|
|
18550
|
+
const rules = partial.aiPreprocessConfig?.desensitizeRules;
|
|
18551
|
+
if (!Array.isArray(rules) || !rules.some((rule) => rule.builtin)) {
|
|
18552
|
+
return { preferences: partial, changed: false };
|
|
18553
|
+
}
|
|
18554
|
+
this.backupLegacyPreferences(rawContent);
|
|
18555
|
+
const legacyBuiltinRuleOverrides = rules.filter((rule) => rule.builtin && typeof rule.enabled === "boolean").reduce((overrides, rule) => {
|
|
18556
|
+
overrides[rule.id] = rule.enabled;
|
|
18557
|
+
return overrides;
|
|
18558
|
+
}, {});
|
|
18559
|
+
const existingOverrides = this.normalizeBooleanMap(partial.aiPreprocessConfig?.desensitizeBuiltinRuleOverrides);
|
|
18560
|
+
return {
|
|
18561
|
+
preferences: {
|
|
18562
|
+
...partial,
|
|
18563
|
+
aiPreprocessConfig: {
|
|
18564
|
+
...partial.aiPreprocessConfig,
|
|
18565
|
+
desensitizeRulesSchemaVersion: DESENSITIZE_RULES_SCHEMA_VERSION,
|
|
18566
|
+
desensitizeBuiltinRuleOverrides: {
|
|
18567
|
+
...legacyBuiltinRuleOverrides,
|
|
18568
|
+
...existingOverrides
|
|
18569
|
+
},
|
|
18570
|
+
desensitizeRules: rules.filter((rule) => !rule.builtin)
|
|
18571
|
+
}
|
|
18572
|
+
},
|
|
18573
|
+
changed: true
|
|
18574
|
+
};
|
|
18575
|
+
}
|
|
18576
|
+
backupLegacyPreferences(rawContent) {
|
|
18577
|
+
const backupDir = path32.join(path32.dirname(this.filePath), "backups");
|
|
18578
|
+
if (!fs35.existsSync(backupDir)) {
|
|
18579
|
+
fs35.mkdirSync(backupDir, { recursive: true });
|
|
18580
|
+
}
|
|
18581
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
18582
|
+
const backupPath = path32.join(backupDir, `preferences-pre-desensitize-groups-${timestamp}.json`);
|
|
18583
|
+
fs35.writeFileSync(backupPath, rawContent, "utf-8");
|
|
18584
|
+
console.info(`[Preferences] Backed up legacy desensitize rules to ${backupPath}`);
|
|
18585
|
+
}
|
|
18586
|
+
writePreferences(preferences) {
|
|
18587
|
+
const dir = path32.dirname(this.filePath);
|
|
18588
|
+
if (!fs35.existsSync(dir)) {
|
|
18589
|
+
fs35.mkdirSync(dir, { recursive: true });
|
|
18590
|
+
}
|
|
18591
|
+
fs35.writeFileSync(this.filePath, JSON.stringify(preferences, null, 2), "utf-8");
|
|
18592
|
+
}
|
|
18003
18593
|
/**
|
|
18004
18594
|
* Deep merge: arrays are replaced (not concatenated), objects are merged.
|
|
18005
18595
|
*/
|
|
@@ -18794,6 +19384,8 @@ export {
|
|
|
18794
19384
|
getClusterGraph,
|
|
18795
19385
|
getRelationshipStats,
|
|
18796
19386
|
getLanguagePreferenceAnalysis,
|
|
19387
|
+
isNewerStableVersion,
|
|
19388
|
+
buildChartPayload,
|
|
18797
19389
|
POS_TAG_DEFINITIONS,
|
|
18798
19390
|
BUILTIN_TOOL_CATALOG,
|
|
18799
19391
|
BUILTIN_PROVIDERS,
|
|
@@ -18832,14 +19424,23 @@ export {
|
|
|
18832
19424
|
AIConversationManager,
|
|
18833
19425
|
initTokenizer,
|
|
18834
19426
|
countMessagesTokens,
|
|
18835
|
-
SkillManager,
|
|
18836
19427
|
SkillManagerCore,
|
|
19428
|
+
SkillManager,
|
|
18837
19429
|
createActivateSkillTool,
|
|
19430
|
+
CHART_CAPABILITY_CORE_TOOLS,
|
|
19431
|
+
getAllowedBuiltinToolsForChartAutoSkill,
|
|
19432
|
+
resolveChartRuntimeForRequest,
|
|
19433
|
+
getChartCapabilitySkill,
|
|
19434
|
+
buildSkillMenuWithBuiltinChart,
|
|
19435
|
+
getSkillConfigWithBuiltinChart,
|
|
19436
|
+
createChartSchemaGateState,
|
|
19437
|
+
wrapWithChartSchemaGate,
|
|
18838
19438
|
checkAndCompress,
|
|
18839
19439
|
createCompressionLlmAdapter,
|
|
18840
19440
|
getDefaultRulesForLocale,
|
|
18841
19441
|
mergeRulesForLocale,
|
|
18842
19442
|
applyPreprocessingPipeline,
|
|
19443
|
+
DEFAULT_MAX_TOOL_ROUNDS,
|
|
18843
19444
|
runAgentCore,
|
|
18844
19445
|
AgentEventHandler,
|
|
18845
19446
|
buildSystemPrompt,
|
|
@@ -18874,4 +19475,4 @@ export {
|
|
|
18874
19475
|
createDatabaseManagerAdapter,
|
|
18875
19476
|
MergeSessionCache
|
|
18876
19477
|
};
|
|
18877
|
-
//# sourceMappingURL=chunk-
|
|
19478
|
+
//# sourceMappingURL=chunk-4OMV4VNH.mjs.map
|