@thinkingai/ae-cli 6.0.52 → 6.0.54
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 +35 -10
- package/README.zh.md +32 -10
- package/bin/ae-cli.js +6 -1
- package/cli-installation-guide.md +91 -0
- package/dist/{auth-XZNXFRJS.js → auth-MBWRZTB6.js} +171 -13
- package/dist/automation-NWWVLWG2.js +459 -0
- package/dist/{capability-RJZ4KRGP.js → capability-7SSN6PNZ.js} +11 -6
- package/dist/chunk-4655PUNX.js +43 -0
- package/dist/{chunk-4NRCTUZJ.js → chunk-5XJYLEVC.js} +4 -4
- package/dist/{chunk-JOCDD4ON.js → chunk-7QXISROD.js} +1 -1
- package/dist/{chunk-EQ255HKO.js → chunk-AP7YP2NX.js} +2 -2
- package/dist/{chunk-DVMLWQD4.js → chunk-CT7QDJS6.js} +2 -2
- package/dist/chunk-D6ACFILC.js +56 -0
- package/dist/{chunk-HFGZGYCG.js → chunk-EOYSKMXN.js} +264 -10
- package/dist/{chunk-57RRFUEZ.js → chunk-FMNNGNYO.js} +43 -8
- package/dist/{chunk-7XGFSUOM.js → chunk-GIK6EDUG.js} +291 -84
- package/dist/{chunk-WEPZ5M3Z.js → chunk-HBLK3ZHW.js} +7 -4
- package/dist/chunk-HVHR4SCP.js +133 -0
- package/dist/{chunk-DX5CDO34.js → chunk-KFNMQTZI.js} +580 -214
- package/dist/{chunk-HBGADCKA.js → chunk-PLE722AJ.js} +28 -11
- package/dist/chunk-RK6GLDGI.js +27 -0
- package/dist/{chunk-V2NUHPXF.js → chunk-S6M42KND.js} +1 -1
- package/dist/{chunk-7FTTULED.js → chunk-UQ77JXYH.js} +7 -3
- package/dist/{chunk-MAPZ7VB6.js → chunk-WNGFSIOB.js} +20 -1
- package/dist/{chunk-L2QUIZTS.js → chunk-ZIQWCZTS.js} +3 -3
- package/dist/{community-report-client-CU22W53K.js → community-report-client-PEERQCX2.js} +1 -1
- package/dist/{config-XO3LI3SA.js → config-FF6YVJKI.js} +29 -10
- package/dist/context-YAE3QXP3.js +136 -0
- package/dist/{data-integration-HNGUKFIC.js → data-integration-HESZET7E.js} +6 -6
- package/dist/index.js +169 -55
- package/dist/{local-data-upload-client-GTRIT64F.js → local-data-upload-client-TWMHFLUA.js} +1 -1
- package/dist/memory-62BJOULV.js +580 -0
- package/dist/{metadata-JAQW7KGZ.js → metadata-7CUMWIB4.js} +7 -7
- package/dist/{model-RNPQXIBI.js → model-SBV2JFJI.js} +9 -5
- package/dist/{personal-semantic-preference-QCZ2IZTK.js → personal-semantic-preference-6SRCYPGE.js} +119 -11
- package/dist/{project-semantic-64JURXKF.js → project-semantic-YYEM4OSU.js} +7 -7
- package/dist/{sync-O45NXEQY.js → sync-SU33KYX7.js} +12 -8
- package/dist/{te-agent-K5MSPNHJ.js → te-agent-F5QBZSQA.js} +423 -494
- package/dist/{te-analysis-KQKCAI5H.js → te-analysis-U4I2W2WC.js} +1090 -67
- package/dist/{te-community-4OYU3BDA.js → te-community-PFLDLPP4.js} +3 -3
- package/dist/{te-dataops-NFIPB6FX.js → te-dataops-FOQSRIAZ.js} +644 -276
- package/dist/{te-engage-HSVSRW22.js → te-engage-ZX76CNAB.js} +6 -6
- package/dist/{te-kb-3TS73NO6.js → te-kb-MHDOST62.js} +666 -244
- package/dist/{te-system-STMHLS5J.js → te-system-J2FQF5ER.js} +6 -6
- package/dist/{te-team-3I5AOX3N.js → te-team-5UOZPTU3.js} +6 -6
- package/dist/things-VPPXXLHB.js +1091 -0
- package/dist/{update-RZXLPCRH.js → update-EEUTEI6R.js} +59 -51
- package/dist/workspace-O3EEIYQM.js +554 -0
- package/package.json +30 -11
- package/skills/ae-agent/SKILL.md +95 -140
- package/skills/ae-agent/references/add-model.md +1 -1
- package/skills/ae-agent/references/create-agent.md +1 -1
- package/skills/ae-agent/references/find-archived-conversations.md +12 -5
- package/skills/ae-agent/references/get-agent.md +1 -1
- package/skills/ae-agent/references/list-agents.md +2 -2
- package/skills/ae-agent/references/list-models.md +2 -2
- package/skills/ae-agent/references/notification.md +40 -0
- package/skills/ae-agent/references/restore-conversation.md +3 -1
- package/skills/ae-analysis/SKILL.md +76 -15
- package/skills/ae-analysis/references/agent_review_submit_to_page.md +2 -0
- package/skills/ae-analysis/references/ai_models/event.md +6 -1
- package/skills/ae-analysis/references/ai_models/funnel.md +12 -4
- package/skills/ae-analysis/references/ai_models/heat_map.md +23 -0
- package/skills/ae-analysis/references/ai_models/interval.md +24 -0
- package/skills/ae-analysis/references/ai_models/path.md +20 -0
- package/skills/ae-analysis/references/ai_models/prop_analysis.md +2 -0
- package/skills/ae-analysis/references/ai_models/rank_list.md +30 -0
- package/skills/ae-analysis/references/ai_models/retention.md +45 -1
- package/skills/ae-analysis/references/ai_models/revenue.md +20 -2
- package/skills/ae-analysis/references/ai_models/tag.md +2 -0
- package/skills/ae-analysis/references/ai_models.md +96 -0
- package/skills/ae-analysis/references/analysis_data_retrieval.md +4 -0
- package/skills/ae-analysis/references/asset_batch_info_export.md +10 -0
- package/skills/ae-analysis/references/asset_batch_sql_export.md +13 -1
- package/skills/ae-analysis/references/asset_export.md +12 -1
- package/skills/ae-analysis/references/asset_list.md +1 -0
- package/skills/ae-analysis/references/asset_search.md +11 -5
- package/skills/ae-analysis/references/bi_panel_list.md +1 -1
- package/skills/ae-analysis/references/catalog_list.md +1 -1
- package/skills/ae-analysis/references/collaboration.md +48 -0
- package/skills/ae-analysis/references/command_index.md +26 -17
- package/skills/ae-analysis/references/dashboard_list.md +4 -4
- package/skills/ae-analysis/references/dashboard_move.md +21 -0
- package/skills/ae-analysis/references/dashboard_report_add.md +2 -0
- package/skills/ae-analysis/references/dashboard_report_data_export.md +2 -0
- package/skills/ae-analysis/references/dashboard_report_get.md +19 -0
- package/skills/ae-analysis/references/dashboard_report_update.md +27 -0
- package/skills/ae-analysis/references/dashboard_update.md +1 -1
- package/skills/ae-analysis/references/event_export.md +3 -1
- package/skills/ae-analysis/references/event_report_presentation.md +76 -0
- package/skills/ae-analysis/references/feedback_submit.md +37 -0
- package/skills/ae-analysis/references/governance_recommendation_auto_review.md +71 -0
- package/skills/ae-analysis/references/governance_recommendation_export.md +11 -0
- package/skills/ae-analysis/references/metadata_resolution.md +18 -3
- package/skills/ae-analysis/references/metric_export.md +3 -1
- package/skills/ae-analysis/references/metric_list.md +1 -1
- package/skills/ae-analysis/references/operation_record_export.md +10 -0
- package/skills/ae-analysis/references/personal_semantic_preference_add.md +2 -2
- package/skills/ae-analysis/references/personal_semantic_preference_get.md +6 -4
- package/skills/ae-analysis/references/personal_semantic_preference_list.md +5 -3
- package/skills/ae-analysis/references/personal_semantic_preference_review.md +9 -0
- package/skills/ae-analysis/references/personal_semantic_preference_review_list.md +7 -0
- package/skills/ae-analysis/references/personal_semantic_preference_submit.md +7 -0
- package/skills/ae-analysis/references/project_semantic_knowledge_wiki.md +91 -32
- package/skills/ae-analysis/references/project_semantic_knowledge_wiki_plan_schema.md +99 -1
- package/skills/ae-analysis/references/property_export.md +3 -1
- package/skills/ae-analysis/references/report_create.md +17 -3
- package/skills/ae-analysis/references/report_data_export.md +6 -0
- package/skills/ae-analysis/references/report_get.md +7 -1
- package/skills/ae-analysis/references/report_list.md +5 -5
- package/skills/ae-analysis/references/report_update.md +20 -3
- package/skills/ae-analysis/references/sql_table_columns.md +4 -4
- package/skills/ae-analysis/references/sql_table_list.md +5 -5
- package/skills/ae-analysis/references/system_query_monitor_overview.md +2 -0
- package/skills/ae-analysis/references/system_query_task_cancel.md +2 -0
- package/skills/ae-analysis/references/system_query_task_export.md +6 -2
- package/skills/ae-analysis/references/system_query_task_get.md +2 -0
- package/skills/ae-analysis/references/system_query_task_list.md +7 -3
- package/skills/ae-analysis/references/system_query_task_options.md +2 -2
- package/skills/ae-analysis/references/system_query_task_realtime_list.md +15 -0
- package/skills/ae-analysis/references/user_cluster_models.md +8 -0
- package/skills/ae-analysis/references/user_tag_create.md +7 -1
- package/skills/ae-analysis/references/user_tag_get.md +1 -1
- package/skills/ae-analysis/references/user_tag_models.md +20 -2
- package/skills/ae-analysis/references/user_tag_refresh.md +1 -1
- package/skills/ae-analysis/references/user_tag_update.md +2 -2
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/build-empty-skeleton.mjs +105 -0
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/build-project-semantic-wiki.mjs +669 -29
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/company-kb.mjs +21 -8
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/default-compile-rules.md +28 -10
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/default-compile-schema.md +66 -0
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/generate-build-ir.mjs +285 -24
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/package-wiki-source-zip.mjs +262 -30
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/plan-kb-source-sync.mjs +1 -1
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/precompiled-source.mjs +46 -2
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/prepare-compile-schema.mjs +64 -0
- package/skills/ae-analysis/scripts/project-semantic-knowledge-wiki/refresh-state-parts.mjs +91 -0
- package/skills/ae-automation/SKILL.md +16 -0
- package/skills/ae-automation/references/cli.md +53 -0
- package/skills/ae-automation/references/command_index.md +17 -0
- package/skills/ae-capability/SKILL.md +73 -2
- package/skills/ae-capability/references/collaboration.md +48 -0
- package/skills/ae-community/SKILL.md +5 -1
- package/skills/ae-community/references/collaboration.md +48 -0
- package/skills/ae-current-context/SKILL.md +3 -2
- package/skills/ae-data-integration/SKILL.md +4 -0
- package/skills/ae-data-integration/references/collaboration.md +48 -0
- package/skills/ae-dataops/SKILL.md +54 -74
- package/skills/ae-dataops/references/collaboration.md +48 -0
- package/skills/ae-dataops/references/dataops-backfill.md +23 -18
- package/skills/ae-dataops/references/dataops-flow-create.md +74 -23
- package/skills/ae-dataops/references/dataops-flow-monitor.md +45 -13
- package/skills/ae-dataops/references/dataops-integration.md +57 -30
- package/skills/ae-dataops/references/dataops-query.md +21 -4
- package/skills/ae-dataops/references/dataops-table.md +143 -11
- package/skills/ae-engage/SKILL.md +21 -6
- package/skills/ae-engage/references/channel-mgmt.md +3 -3
- package/skills/ae-engage/references/collaboration.md +48 -0
- package/skills/ae-engage/references/scene-config-channel.md +4 -4
- package/skills/ae-generate-tracking-plan/SKILL.md +4 -0
- package/skills/ae-generate-tracking-plan/references/collaboration.md +48 -0
- package/skills/ae-kb/SKILL.md +70 -12
- package/skills/ae-kb/references/analysis-workflow.md +73 -36
- package/skills/ae-kb/references/collaboration.md +48 -0
- package/skills/ae-kb/references/query-workflow.md +67 -33
- package/skills/ae-kb/references/schema-import.md +32 -0
- package/skills/ae-kb/references/source-mutations.md +6 -4
- package/skills/ae-kb/references/text-sources.md +53 -0
- package/skills/ae-kb-discovery/SKILL.md +8 -3
- package/skills/ae-kb-discovery/references/collaboration.md +48 -0
- package/skills/ae-metadata/SKILL.md +20 -12
- package/skills/ae-metadata/references/collaboration.md +48 -0
- package/skills/ae-team/SKILL.md +23 -17
- package/skills/ae-things/SKILL.md +85 -0
- package/skills/ae-things/references/cli.md +103 -0
- package/skills/ae-things-progress/SKILL.md +43 -0
- package/skills/ae-things-review/SKILL.md +42 -0
- package/skills/ae-workspace/SKILL.md +43 -0
- package/skills/ae-workspace/references/commands.md +51 -0
- package/dist/chunk-E2JKXMVO.js +0 -29
- package/dist/context-IFJI3LIT.js +0 -46
- package/dist/memory-QGPSNCQS.js +0 -892
- package/skills/ae-agent/references/create-automation.md +0 -125
- package/skills/ae-agent/references/list-automations.md +0 -56
- package/skills/ae-agent/references/update-automation.md +0 -107
|
@@ -2,23 +2,23 @@ import { createRequire as __createRequire } from 'node:module'; const require =
|
|
|
2
2
|
import {
|
|
3
3
|
kbApi,
|
|
4
4
|
kbUpload
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-FMNNGNYO.js";
|
|
6
6
|
import {
|
|
7
7
|
TeAgentApiError
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-PLE722AJ.js";
|
|
9
9
|
import {
|
|
10
10
|
CapabilityGatewayError
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-EOYSKMXN.js";
|
|
12
12
|
import {
|
|
13
13
|
printError
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-KFNMQTZI.js";
|
|
15
15
|
import "./chunk-Y74WTIKJ.js";
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-GIK6EDUG.js";
|
|
17
|
+
import "./chunk-UQ77JXYH.js";
|
|
18
18
|
import {
|
|
19
19
|
CliValidationError,
|
|
20
20
|
PermissionError
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-WNGFSIOB.js";
|
|
22
22
|
|
|
23
23
|
// src/commands/te-kb/target-scope.ts
|
|
24
24
|
function getExternalKnowledgeBaseTargetScope(ctx) {
|
|
@@ -30,12 +30,164 @@ function getExternalKnowledgeBaseTargetScope(ctx) {
|
|
|
30
30
|
);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
// src/commands/te-kb/source-check-updates.ts
|
|
34
|
-
var API_PATH = "/agent/api/external/knowledge-bases/sources/check-updates";
|
|
33
|
+
// src/commands/te-kb/source-check-url-updates.ts
|
|
34
|
+
var API_PATH = "/agent/api/external/knowledge-bases/sources/check-url-updates";
|
|
35
35
|
function body(ctx) {
|
|
36
36
|
const scope = getExternalKnowledgeBaseTargetScope(ctx);
|
|
37
37
|
return { name: ctx.str("name").trim(), sourceId: ctx.str("id").trim(), ...scope ? { scope } : {} };
|
|
38
38
|
}
|
|
39
|
+
var sourceCheckUrlUpdates = {
|
|
40
|
+
service: "kb",
|
|
41
|
+
resource: "source",
|
|
42
|
+
command: "check-url-updates",
|
|
43
|
+
risk: "write",
|
|
44
|
+
description: "Submit an asynchronous update check for one compiled custom URL source. Success means accepted only. Read kb +list-sources for update markers; an unchanged state does not prove completion. Does not compile.",
|
|
45
|
+
flags: [
|
|
46
|
+
{ name: "name", type: "string", required: true, minLength: 1, maxLength: 200, desc: "Knowledge base name" },
|
|
47
|
+
{ name: "id", type: "string", required: true, minLength: 1, maxLength: 191, desc: "Stable custom URL source ID from kb +list-sources" },
|
|
48
|
+
{ name: "scope", type: "string", desc: "Exact scope: personal | company (omit for personal then company lookup)" }
|
|
49
|
+
],
|
|
50
|
+
validate: (ctx) => {
|
|
51
|
+
for (const [flag2, max] of [["name", 200], ["id", 191]]) {
|
|
52
|
+
const value = ctx.str(flag2).trim();
|
|
53
|
+
if (!value || value.length > max) throw new CliValidationError(`Invalid --${flag2}: expected 1-${max} characters.`);
|
|
54
|
+
}
|
|
55
|
+
getExternalKnowledgeBaseTargetScope(ctx);
|
|
56
|
+
},
|
|
57
|
+
dryRun: (ctx) => ({ method: "POST", url: `${ctx.host().replace(/\/$/, "")}${API_PATH}`, body: body(ctx) }),
|
|
58
|
+
execute: (ctx) => kbApi(ctx, "POST", API_PATH, {}, body(ctx), { preserveErrorMetadata: true })
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// src/commands/te-kb/schema-import.ts
|
|
62
|
+
import { promises as fs } from "fs";
|
|
63
|
+
import path from "path";
|
|
64
|
+
var ROOT = "/agent/api/external/knowledge-bases/schema";
|
|
65
|
+
var options = { preserveBusinessErrorCode: true, preserveErrorMetadata: true };
|
|
66
|
+
var flag = (name, type, desc, required = false) => ({ name, type, desc, required });
|
|
67
|
+
var targetFlags = [flag("name", "string", "Knowledge base name", true), flag("scope", "string", "Exact scope: personal | company")];
|
|
68
|
+
var identityFlags = [flag("import-id", "string", "Stable import ID", true)];
|
|
69
|
+
var mutationFlags = [flag("revision", "number", "Expected candidate revision", true), flag("request-id", "string", "Idempotency key; reuse only for identical retries", true)];
|
|
70
|
+
var hashFlag = flag("hash", "string", "Expected candidate SHA256", true);
|
|
71
|
+
var fileFlag = { ...flag("file", "string", "Local UTF-8 Markdown file, at most 256 KiB", true), sensitive: true };
|
|
72
|
+
var waitFlags = [flag("wait", "boolean", "Poll until this task finishes; never abandon on timeout"), { ...flag("timeout", "number", "Wait timeout in seconds"), default: 300, min: 1, max: 3600 }];
|
|
73
|
+
var modelFlag = flag("model", "string", "Optional stable model reference");
|
|
74
|
+
function target(ctx) {
|
|
75
|
+
return { name: ctx.str("name"), scope: getExternalKnowledgeBaseTargetScope(ctx) };
|
|
76
|
+
}
|
|
77
|
+
function endpoint(ctx, action) {
|
|
78
|
+
if (action === "download") return ROOT;
|
|
79
|
+
if (action === "upload" || action === "list") return ROOT + "/imports";
|
|
80
|
+
const suffix = action === "status" ? "" : action === "save" ? "content" : action === "reject" ? "reject-optimization" : action;
|
|
81
|
+
return `${ROOT}/imports/${encodeURIComponent(ctx.str("import-id"))}${suffix ? "/" + suffix : ""}`;
|
|
82
|
+
}
|
|
83
|
+
function body2(ctx, action) {
|
|
84
|
+
const result = { expectedRevision: ctx.num("revision"), requestId: ctx.str("request-id") };
|
|
85
|
+
if (["validate", "optimize", "apply"].includes(action)) result.contentHash = ctx.str("hash");
|
|
86
|
+
if (["validate", "optimize"].includes(action) && ctx.str("model")) result.model = ctx.str("model");
|
|
87
|
+
if (action === "optimize" && ctx.list("issue-id").length) result.issueIds = ctx.list("issue-id");
|
|
88
|
+
if (action === "apply") {
|
|
89
|
+
if (ctx.str("report-id")) result.reportId = ctx.str("report-id");
|
|
90
|
+
result.expectedSchemaHash = ctx.bool("schema-absent") ? null : ctx.str("schema-hash");
|
|
91
|
+
}
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
function query(ctx, action) {
|
|
95
|
+
if (action === "download") return { ...target(ctx), download: "1" };
|
|
96
|
+
if (action === "list") return { ...target(ctx), limit: ctx.num("limit") || 20, cursor: ctx.str("cursor") || void 0 };
|
|
97
|
+
if (action === "content") return { target: ctx.str("target") || "current", download: ctx.str("output") ? "1" : void 0 };
|
|
98
|
+
if (action === "diff") return { baseline: ctx.str("baseline") || "current-schema" };
|
|
99
|
+
return {};
|
|
100
|
+
}
|
|
101
|
+
function validate(ctx, action) {
|
|
102
|
+
if (["upload", "list", "download"].includes(action)) getExternalKnowledgeBaseTargetScope(ctx);
|
|
103
|
+
for (const name of ["import-id", "request-id", "replaces-import-id"]) if (ctx.str(name) && !/^[A-Za-z0-9_-]{1,191}$/.test(ctx.str(name))) throw new CliValidationError(`Invalid --${name}`);
|
|
104
|
+
for (const name of ["hash", "schema-hash", "report-id"]) if (ctx.str(name) && !/^[a-f0-9]{64}$/.test(ctx.str(name))) throw new CliValidationError(`Invalid --${name}; expected SHA256`);
|
|
105
|
+
for (const name of ["revision", "replaced-revision"]) if (ctx.num(name) && (!Number.isInteger(ctx.num(name)) || ctx.num(name) < 1)) throw new CliValidationError(`Invalid --${name}`);
|
|
106
|
+
if (action === "apply" && Boolean(ctx.str("schema-hash")) === ctx.bool("schema-absent")) throw new CliValidationError("Specify exactly one of --schema-hash or --schema-absent");
|
|
107
|
+
if (action === "upload" && Boolean(ctx.str("replaces-import-id")) !== Boolean(ctx.num("replaced-revision"))) throw new CliValidationError("Replacement requires --replaces-import-id and --replaced-revision");
|
|
108
|
+
if (action === "content" && !["current", "original", "optimization-input", "optimized"].includes(ctx.str("target") || "current")) throw new CliValidationError("Invalid --target");
|
|
109
|
+
if (action === "diff" && !["original", "optimization-input", "current-schema"].includes(ctx.str("baseline") || "current-schema")) throw new CliValidationError("Invalid --baseline");
|
|
110
|
+
}
|
|
111
|
+
async function readMarkdown(ctx) {
|
|
112
|
+
const absolute = path.resolve(ctx.str("file")), stat = await fs.stat(absolute);
|
|
113
|
+
if (!stat.isFile() || stat.size > 262144 || path.extname(absolute).toLowerCase() !== ".md") throw new CliValidationError("--file must be a Markdown file of at most 256 KiB");
|
|
114
|
+
const bytes = await fs.readFile(absolute);
|
|
115
|
+
if (bytes.length > 262144) throw new CliValidationError("--file exceeds 256 KiB");
|
|
116
|
+
new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
117
|
+
return { absolute, bytes };
|
|
118
|
+
}
|
|
119
|
+
async function waitSchemaImport(ctx, initial, api = kbApi, sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms))) {
|
|
120
|
+
const deadline = Date.now() + (ctx.num("timeout") || 300) * 1e3;
|
|
121
|
+
let current = initial;
|
|
122
|
+
while (current.task && Date.now() < deadline) {
|
|
123
|
+
await sleep(Math.min(2e3, Math.max(1, deadline - Date.now())));
|
|
124
|
+
current = await api(ctx, "GET", `${ROOT}/imports/${encodeURIComponent(initial.id)}`, {}, void 0, options);
|
|
125
|
+
}
|
|
126
|
+
return { ...current, waitTimedOut: Boolean(current.task) };
|
|
127
|
+
}
|
|
128
|
+
async function executeSchemaImport(ctx, action, api = kbApi, upload = kbUpload) {
|
|
129
|
+
let result;
|
|
130
|
+
if (action === "upload") {
|
|
131
|
+
const { absolute, bytes } = await readMarkdown(ctx);
|
|
132
|
+
const form = new FormData();
|
|
133
|
+
form.set("file", new Blob([new Uint8Array(bytes)]), path.basename(absolute));
|
|
134
|
+
form.set("name", ctx.str("name"));
|
|
135
|
+
form.set("requestId", ctx.str("request-id"));
|
|
136
|
+
const scope = getExternalKnowledgeBaseTargetScope(ctx);
|
|
137
|
+
if (scope) form.set("scope", scope);
|
|
138
|
+
if (ctx.str("model")) form.set("model", ctx.str("model"));
|
|
139
|
+
if (ctx.str("replaces-import-id")) {
|
|
140
|
+
form.set("replacesImportId", ctx.str("replaces-import-id"));
|
|
141
|
+
form.set("expectedReplacedRevision", String(ctx.num("replaced-revision")));
|
|
142
|
+
}
|
|
143
|
+
result = await upload(ctx, endpoint(ctx, action), form, {}, options);
|
|
144
|
+
} else if (["download", "list", "status", "content", "diff"].includes(action)) {
|
|
145
|
+
const binary = action === "download" || action === "content" && Boolean(ctx.str("output"));
|
|
146
|
+
result = await api(ctx, "GET", endpoint(ctx, action), query(ctx, action), void 0, { ...options, ...binary ? { responseType: "bytes" } : {} });
|
|
147
|
+
if (binary) {
|
|
148
|
+
const output = path.resolve(ctx.str("output"));
|
|
149
|
+
const bytes = Buffer.from(result.bytes);
|
|
150
|
+
await fs.writeFile(output, bytes, { flag: "wx" });
|
|
151
|
+
return { output, sizeBytes: bytes.length };
|
|
152
|
+
}
|
|
153
|
+
if (action === "diff" && ctx.str("output")) {
|
|
154
|
+
const output = path.resolve(ctx.str("output"));
|
|
155
|
+
await fs.writeFile(output, result.diff, { flag: "wx" });
|
|
156
|
+
return { ...result, output };
|
|
157
|
+
}
|
|
158
|
+
} else {
|
|
159
|
+
const input = body2(ctx, action);
|
|
160
|
+
if (action === "save") {
|
|
161
|
+
const { bytes } = await readMarkdown(ctx);
|
|
162
|
+
input.content = bytes.toString("utf8");
|
|
163
|
+
}
|
|
164
|
+
result = await api(ctx, action === "save" ? "PUT" : "POST", endpoint(ctx, action), {}, input, options);
|
|
165
|
+
}
|
|
166
|
+
return ctx.bool("wait") && result.task ? waitSchemaImport(ctx, result, api) : result;
|
|
167
|
+
}
|
|
168
|
+
function command(action, name, description, flags, risk) {
|
|
169
|
+
return { service: "kb", command: name, description, flags, risk, validate: (ctx) => validate(ctx, action), dryRun: (ctx) => ({ method: action === "save" ? "PUT" : ["upload", "validate", "optimize", "reject", "apply", "abandon"].includes(action) ? "POST" : "GET", url: ctx.host().replace(/\/$/, "") + endpoint(ctx, action), params: query(ctx, action), body: action === "upload" ? { ...target(ctx), requestId: ctx.str("request-id"), file: "[REDACTED]", model: ctx.str("model") || void 0, replacesImportId: ctx.str("replaces-import-id") || void 0, expectedReplacedRevision: ctx.num("replaced-revision") || void 0 } : ["save", "validate", "optimize", "reject", "apply", "abandon"].includes(action) ? { ...body2(ctx, action), ...action === "save" ? { content: "[REDACTED]" } : {} } : void 0 }), execute: (ctx) => executeSchemaImport(ctx, action) };
|
|
170
|
+
}
|
|
171
|
+
var schemaDownload = command("download", "+schema-download", "Download formal schema bytes without rewriting.", [...targetFlags, flag("output", "string", "New destination file; never overwrite", true)], "read");
|
|
172
|
+
var schemaImport = command("upload", "+schema-import", "Upload a candidate with basic checks; AI validation is explicit and formal schema is unchanged.", [...targetFlags, fileFlag, flag("request-id", "string", "Upload idempotency key", true), modelFlag, flag("replaces-import-id", "string", "Explicit pending import to replace"), flag("replaced-revision", "number", "Expected revision of replaced import"), ...waitFlags], "write");
|
|
173
|
+
var schemaImportList = command("list", "+schema-import-list", "List your pending candidates.", [...targetFlags, { ...flag("limit", "number", "Page size, 1 to 100"), default: 20, min: 1, max: 100 }, flag("cursor", "string", "Continuation cursor")], "read");
|
|
174
|
+
var schemaImportStatus = command("status", "+schema-import-status", "Read candidate status, report and durable receipt.", [...identityFlags, ...waitFlags], "read");
|
|
175
|
+
var schemaImportContent = command("content", "+schema-import-content", "Read or download unmodified candidate bytes.", [...identityFlags, flag("target", "string", "current | original | optimization-input | optimized"), flag("output", "string", "Optional new destination file")], "read");
|
|
176
|
+
var schemaImportDiff = command("diff", "+schema-import-diff", "Read full actual diff and current formal hash.", [...identityFlags, flag("baseline", "string", "original | optimization-input | current-schema"), flag("output", "string", "Optional new diff file")], "read");
|
|
177
|
+
var schemaImportSave = command("save", "+schema-import-save", "Save edits without calling a model.", [...identityFlags, ...mutationFlags, fileFlag], "write");
|
|
178
|
+
var schemaImportValidate = command("validate", "+schema-import-validate", "Validate this exact saved revision.", [...identityFlags, ...mutationFlags, hashFlag, modelFlag, ...waitFlags], "write");
|
|
179
|
+
var schemaImportOptimize = command("optimize", "+schema-import-optimize", "Repair selected issues once and independently revalidate.", [...identityFlags, ...mutationFlags, hashFlag, modelFlag, { ...flag("issue-id", "string", "Repeat to select repairable issues"), variadic: true }, ...waitFlags], "write");
|
|
180
|
+
var schemaImportReject = command("reject", "+schema-import-reject", "Restore the most recent repair input.", [...identityFlags, ...mutationFlags], "write");
|
|
181
|
+
var schemaImportApply = command("apply", "+schema-import-apply", "Apply after reviewing full diff; BASE_CHANGED requires a new review.", [...identityFlags, ...mutationFlags, hashFlag, flag("report-id", "string", "Optional AI report ID; retained for compatibility"), flag("schema-hash", "string", "Formal hash from a recent diff"), flag("schema-absent", "boolean", "Explicitly confirm formal schema is absent")], "write");
|
|
182
|
+
var schemaImportAbandon = command("abandon", "+schema-import-abandon", "Abandon candidate and invalidate pending tasks.", [...identityFlags, ...mutationFlags], "high-risk-write");
|
|
183
|
+
var schemaImportCommands = [schemaDownload, schemaImport, schemaImportList, schemaImportStatus, schemaImportContent, schemaImportDiff, schemaImportSave, schemaImportValidate, schemaImportOptimize, schemaImportReject, schemaImportApply, schemaImportAbandon];
|
|
184
|
+
|
|
185
|
+
// src/commands/te-kb/source-check-updates.ts
|
|
186
|
+
var API_PATH2 = "/agent/api/external/knowledge-bases/sources/check-updates";
|
|
187
|
+
function body3(ctx) {
|
|
188
|
+
const scope = getExternalKnowledgeBaseTargetScope(ctx);
|
|
189
|
+
return { name: ctx.str("name").trim(), sourceId: ctx.str("id").trim(), ...scope ? { scope } : {} };
|
|
190
|
+
}
|
|
39
191
|
var sourceCheckUpdates = {
|
|
40
192
|
service: "kb",
|
|
41
193
|
resource: "source",
|
|
@@ -48,16 +200,16 @@ var sourceCheckUpdates = {
|
|
|
48
200
|
{ name: "scope", type: "string", desc: "Exact scope: personal | company (omit for personal then company lookup)" }
|
|
49
201
|
],
|
|
50
202
|
validate: (ctx) => {
|
|
51
|
-
for (const [
|
|
52
|
-
const value = ctx.str(
|
|
53
|
-
if (!value || value.length > max) throw new CliValidationError(`Invalid --${
|
|
203
|
+
for (const [flag2, max] of [["name", 200], ["id", 191]]) {
|
|
204
|
+
const value = ctx.str(flag2).trim();
|
|
205
|
+
if (!value || value.length > max) throw new CliValidationError(`Invalid --${flag2}: expected 1-${max} characters.`);
|
|
54
206
|
}
|
|
55
207
|
getExternalKnowledgeBaseTargetScope(ctx);
|
|
56
208
|
},
|
|
57
|
-
dryRun: (ctx) => ({ method: "POST", url: `${ctx.host().replace(/\/$/, "")}${
|
|
209
|
+
dryRun: (ctx) => ({ method: "POST", url: `${ctx.host().replace(/\/$/, "")}${API_PATH2}`, body: body3(ctx) }),
|
|
58
210
|
execute: async (ctx) => {
|
|
59
211
|
try {
|
|
60
|
-
return await kbApi(ctx, "POST",
|
|
212
|
+
return await kbApi(ctx, "POST", API_PATH2, {}, body3(ctx), { preserveErrorMetadata: true });
|
|
61
213
|
} catch (error) {
|
|
62
214
|
const hint = "Read kb +list-sources to confirm the current source state before retrying.";
|
|
63
215
|
if (error instanceof PermissionError) {
|
|
@@ -84,14 +236,185 @@ var sourceCheckUpdates = {
|
|
|
84
236
|
}
|
|
85
237
|
};
|
|
86
238
|
|
|
87
|
-
// src/commands/te-kb/source-
|
|
88
|
-
import { promises as
|
|
89
|
-
import
|
|
239
|
+
// src/commands/te-kb/source-text.ts
|
|
240
|
+
import { promises as fs2 } from "fs";
|
|
241
|
+
import path2 from "path";
|
|
90
242
|
var API = "/agent/api/external/knowledge-bases";
|
|
91
|
-
var
|
|
243
|
+
var textApiOptions = { preserveErrorMetadata: true, retryUnauthorized: false, redactErrorDetails: true };
|
|
92
244
|
var maxBytes = 50 * 1024 * 1024;
|
|
245
|
+
var targetFlags2 = [
|
|
246
|
+
{ name: "name", type: "string", required: true, desc: "Exact knowledge base name from kb +list" },
|
|
247
|
+
{ name: "scope", type: "string", required: true, desc: "Exact knowledge base scope: personal or company" }
|
|
248
|
+
];
|
|
249
|
+
var textInputFlags = [
|
|
250
|
+
{ name: "text", type: "string", sensitive: true, desc: "Complete text body; mutually exclusive with --file and --stdin" },
|
|
251
|
+
{ name: "file", type: "string", desc: "One UTF-8 .md, .markdown or .txt file, at most 50 MiB; creates a Markdown source" },
|
|
252
|
+
{ name: "stdin", type: "boolean", desc: "Explicitly read the complete UTF-8 body from stdin; mutually exclusive with --text and --file" }
|
|
253
|
+
];
|
|
254
|
+
function hasTextFlag(ctx) {
|
|
255
|
+
return ctx.has ? ctx.has("text") : Boolean(ctx.str("text"));
|
|
256
|
+
}
|
|
257
|
+
function validateTextInput(ctx) {
|
|
258
|
+
const hasFile = ctx.has ? ctx.has("file") : Boolean(ctx.str("file"));
|
|
259
|
+
const count = Number(hasTextFlag(ctx)) + Number(hasFile) + Number(ctx.bool("stdin"));
|
|
260
|
+
if (count !== 1) throw new CliValidationError("Provide exactly one of --text, --file or --stdin.");
|
|
261
|
+
if (hasFile && !ctx.str("file").trim()) throw new CliValidationError("--file must name a regular file.");
|
|
262
|
+
}
|
|
263
|
+
function validateTarget(ctx) {
|
|
264
|
+
const name = ctx.str("name");
|
|
265
|
+
if (!name.trim() || name.length > 200 || /[\x00-\x1f\x7f]/.test(name)) {
|
|
266
|
+
throw new CliValidationError("--name must contain 1 to 200 characters without control characters.");
|
|
267
|
+
}
|
|
268
|
+
if (!["personal", "company"].includes(ctx.str("scope"))) throw new CliValidationError("--scope must be personal or company.");
|
|
269
|
+
}
|
|
270
|
+
function tooLarge() {
|
|
271
|
+
return new CliValidationError("Text content exceeds 50 MiB (52428800 UTF-8 bytes).", { code: "SOURCE_FILE_TOO_LARGE" });
|
|
272
|
+
}
|
|
273
|
+
async function boundedBytes(stream) {
|
|
274
|
+
const chunks = [];
|
|
275
|
+
let size = 0;
|
|
276
|
+
for await (const chunk of stream) {
|
|
277
|
+
const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
278
|
+
size += bytes.length;
|
|
279
|
+
if (size > maxBytes) throw tooLarge();
|
|
280
|
+
chunks.push(bytes);
|
|
281
|
+
}
|
|
282
|
+
return Buffer.concat(chunks, size);
|
|
283
|
+
}
|
|
284
|
+
async function readTextInput(ctx) {
|
|
285
|
+
validateTextInput(ctx);
|
|
286
|
+
let content;
|
|
287
|
+
if (hasTextFlag(ctx)) {
|
|
288
|
+
content = ctx.str("text");
|
|
289
|
+
if (/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/u.test(content)) {
|
|
290
|
+
throw new CliValidationError("Text content must contain valid Unicode.", { code: "SOURCE_TEXT_ENCODING_UNSUPPORTED" });
|
|
291
|
+
}
|
|
292
|
+
} else {
|
|
293
|
+
let bytes;
|
|
294
|
+
if (ctx.bool("stdin")) {
|
|
295
|
+
if (process.stdin.isTTY) throw new CliValidationError("--stdin requires piped UTF-8 input; interactive input is not supported.");
|
|
296
|
+
bytes = await boundedBytes(process.stdin);
|
|
297
|
+
} else {
|
|
298
|
+
const filename = path2.resolve(ctx.str("file"));
|
|
299
|
+
if (![".md", ".markdown", ".txt"].includes(path2.extname(filename).toLowerCase())) {
|
|
300
|
+
throw new CliValidationError("--file must be a UTF-8 .md, .markdown or .txt file.");
|
|
301
|
+
}
|
|
302
|
+
const handle = await fs2.open(filename, "r");
|
|
303
|
+
try {
|
|
304
|
+
const stat = await handle.stat();
|
|
305
|
+
if (!stat.isFile()) throw new CliValidationError("--file must be a regular file.");
|
|
306
|
+
if (stat.size > maxBytes) throw tooLarge();
|
|
307
|
+
bytes = await boundedBytes(handle.createReadStream({ autoClose: false }));
|
|
308
|
+
} finally {
|
|
309
|
+
await handle.close();
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
try {
|
|
313
|
+
content = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
314
|
+
} catch {
|
|
315
|
+
throw new CliValidationError("Text input must be valid UTF-8; no encoding conversion is performed.", { code: "SOURCE_TEXT_ENCODING_UNSUPPORTED" });
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
const sizeBytes = Buffer.byteLength(content, "utf8");
|
|
319
|
+
if (sizeBytes > maxBytes) throw tooLarge();
|
|
320
|
+
if (!content.trim()) throw new CliValidationError("Text content must not be empty or whitespace-only.", { code: "SOURCE_TEXT_EMPTY" });
|
|
321
|
+
return { content, sizeBytes };
|
|
322
|
+
}
|
|
323
|
+
function target2(ctx) {
|
|
324
|
+
return { name: ctx.str("name").trim(), scope: ctx.str("scope") };
|
|
325
|
+
}
|
|
326
|
+
var sourceCreateText = {
|
|
327
|
+
service: "kb",
|
|
328
|
+
resource: "source",
|
|
329
|
+
command: "create-text",
|
|
330
|
+
risk: "write",
|
|
331
|
+
description: "Create one ordinary Markdown source from text, a UTF-8 file or stdin. Saves only; does not compile or publish.",
|
|
332
|
+
flags: [
|
|
333
|
+
...targetFlags2,
|
|
334
|
+
{ name: "title", type: "string", desc: "Optional display title (1-200 Unicode characters); the server derives it from content when omitted" },
|
|
335
|
+
...textInputFlags
|
|
336
|
+
],
|
|
337
|
+
validate: (ctx) => {
|
|
338
|
+
validateTarget(ctx);
|
|
339
|
+
validateTextInput(ctx);
|
|
340
|
+
if (ctx.has?.("title") || ctx.str("title")) {
|
|
341
|
+
const title = ctx.str("title").trim();
|
|
342
|
+
if (!title || [...title].length > 200 || /[\p{Cc}/\\]/u.test(title) || [".", ".."].includes(title)) {
|
|
343
|
+
throw new CliValidationError("--title must contain 1 to 200 Unicode characters without control characters or path separators.");
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
dryRun: async (ctx) => {
|
|
348
|
+
const { sizeBytes } = await readTextInput(ctx);
|
|
349
|
+
return {
|
|
350
|
+
method: "POST",
|
|
351
|
+
url: `${ctx.host().replace(/\/$/, "")}${API}/sources/text`,
|
|
352
|
+
body: { ...target2(ctx), ...ctx.str("title") ? { title: ctx.str("title").trim() } : {}, inputMethod: "text_input", content: "<redacted>" },
|
|
353
|
+
sizeBytes
|
|
354
|
+
};
|
|
355
|
+
},
|
|
356
|
+
execute: async (ctx) => kbApi(ctx, "POST", `${API}/sources/text`, {}, {
|
|
357
|
+
...target2(ctx),
|
|
358
|
+
...ctx.str("title") ? { title: ctx.str("title").trim() } : {},
|
|
359
|
+
content: (await readTextInput(ctx)).content,
|
|
360
|
+
inputMethod: "text_input"
|
|
361
|
+
}, textApiOptions)
|
|
362
|
+
};
|
|
363
|
+
async function outputPath(ctx) {
|
|
364
|
+
if (!ctx.str("out")) return void 0;
|
|
365
|
+
const output = path2.resolve(ctx.str("out"));
|
|
366
|
+
try {
|
|
367
|
+
await fs2.lstat(output);
|
|
368
|
+
} catch (error) {
|
|
369
|
+
if (error.code === "ENOENT") return output;
|
|
370
|
+
throw error;
|
|
371
|
+
}
|
|
372
|
+
throw new CliValidationError("--out must name a new file; existing files are never overwritten.");
|
|
373
|
+
}
|
|
374
|
+
var sourceReadText = {
|
|
375
|
+
service: "kb",
|
|
376
|
+
resource: "source",
|
|
377
|
+
command: "read-text",
|
|
378
|
+
risk: "read",
|
|
379
|
+
sensitiveOutput: true,
|
|
380
|
+
description: "Read complete ordinary UTF-8 text with its matching revision and format. Optionally save original bytes to a new local file.",
|
|
381
|
+
flags: [
|
|
382
|
+
...targetFlags2,
|
|
383
|
+
{ name: "id", type: "string", required: true, desc: "Current stable source ID from kb +list-sources" },
|
|
384
|
+
{ name: "out", type: "string", desc: "Write the complete original UTF-8 bytes to a new file; output metadata only and never overwrite" }
|
|
385
|
+
],
|
|
386
|
+
validate: (ctx) => {
|
|
387
|
+
validateTarget(ctx);
|
|
388
|
+
const id = ctx.str("id");
|
|
389
|
+
if (!id.trim() || id.length > 191 || /[\x00-\x1f\x7f]/.test(id)) throw new CliValidationError("--id must contain 1 to 191 characters without control characters.");
|
|
390
|
+
if (ctx.has?.("out") && !ctx.str("out").trim()) throw new CliValidationError("--out must name a new file.");
|
|
391
|
+
},
|
|
392
|
+
dryRun: async (ctx) => ({
|
|
393
|
+
method: "GET",
|
|
394
|
+
url: `${ctx.host().replace(/\/$/, "")}${API}/sources/${encodeURIComponent(ctx.str("id").trim())}/text`,
|
|
395
|
+
params: target2(ctx),
|
|
396
|
+
...ctx.str("out") ? { out: await outputPath(ctx) } : {}
|
|
397
|
+
}),
|
|
398
|
+
execute: async (ctx) => {
|
|
399
|
+
const output = await outputPath(ctx);
|
|
400
|
+
const result = await kbApi(ctx, "GET", `${API}/sources/${encodeURIComponent(ctx.str("id").trim())}/text`, target2(ctx), void 0, textApiOptions);
|
|
401
|
+
if (!result || typeof result.content !== "string" || !["markdown", "text"].includes(result.contentFormat) || !Number.isSafeInteger(result.item?.contentRevision) || result.item.contentRevision < 1) {
|
|
402
|
+
throw new Error("KB text protocol error: expected complete content, format and a positive contentRevision.");
|
|
403
|
+
}
|
|
404
|
+
if (!output) return result;
|
|
405
|
+
await fs2.writeFile(output, result.content, { encoding: "utf8", flag: "wx" });
|
|
406
|
+
return { item: result.item, contentFormat: result.contentFormat, out: output };
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
// src/commands/te-kb/source-mutation.ts
|
|
411
|
+
import { promises as fs3 } from "fs";
|
|
412
|
+
import path3 from "path";
|
|
413
|
+
var API2 = "/agent/api/external/knowledge-bases";
|
|
414
|
+
var apiOptions = { preserveErrorMetadata: true };
|
|
415
|
+
var maxBytes2 = 50 * 1024 * 1024;
|
|
93
416
|
var fileExtensions = /* @__PURE__ */ new Set([".md", ".markdown", ".txt", ".csv", ".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp", ".svg"]);
|
|
94
|
-
var
|
|
417
|
+
var identityFlags2 = [
|
|
95
418
|
{ name: "name", type: "string", required: true, desc: "Exact knowledge base name from kb +list" },
|
|
96
419
|
{ name: "scope", type: "string", required: true, desc: "Exact knowledge base scope: personal or company" },
|
|
97
420
|
{ name: "id", type: "string", required: true, desc: "Current stable source ID from kb +list-sources" }
|
|
@@ -100,48 +423,48 @@ var typeFlag = { name: "source-type", type: "string", required: true, desc: "Cur
|
|
|
100
423
|
var revisionFlag = { name: "expected-revision", type: "number", required: true, min: 1, max: 2147483647, desc: "Current contentRevision from kb +list-sources; never automatically retry a conflict" };
|
|
101
424
|
var previewFlag = { name: "preview-id", type: "string", required: true, desc: "Exact previewId returned by ZIP replace or restore" };
|
|
102
425
|
function validateIdentity(ctx) {
|
|
103
|
-
for (const [
|
|
104
|
-
const value = ctx.str(
|
|
105
|
-
if ((
|
|
106
|
-
throw new CliValidationError(`--${
|
|
426
|
+
for (const [flag2, max] of [["name", 200], ["id", 191], ["preview-id", 191]]) {
|
|
427
|
+
const value = ctx.str(flag2);
|
|
428
|
+
if ((flag2 !== "preview-id" || value) && (!value.trim() || value.length > max || /[\x00-\x1f\x7f]/.test(value))) {
|
|
429
|
+
throw new CliValidationError(`--${flag2} must contain 1 to ${max} characters without control characters.`);
|
|
107
430
|
}
|
|
108
431
|
}
|
|
109
432
|
if (!["personal", "company"].includes(ctx.str("scope"))) throw new CliValidationError("--scope must be personal or company.");
|
|
110
433
|
}
|
|
111
|
-
function positiveInteger(ctx,
|
|
112
|
-
const value = ctx.num(
|
|
113
|
-
if (!Number.isSafeInteger(value) || value < 1 || value > 2147483647) throw new CliValidationError(`--${
|
|
434
|
+
function positiveInteger(ctx, flag2) {
|
|
435
|
+
const value = ctx.num(flag2);
|
|
436
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > 2147483647) throw new CliValidationError(`--${flag2} must be an integer from 1 to 2147483647.`);
|
|
114
437
|
}
|
|
115
438
|
function validateMutation(ctx) {
|
|
116
439
|
validateIdentity(ctx);
|
|
117
440
|
positiveInteger(ctx, "expected-revision");
|
|
118
441
|
if (!["file", "zip"].includes(ctx.str("source-type"))) throw new CliValidationError("--source-type must be file or zip; URL sources cannot be replaced or restored.");
|
|
119
442
|
}
|
|
120
|
-
function
|
|
443
|
+
function query2(ctx) {
|
|
121
444
|
return { name: ctx.str("name").trim(), scope: ctx.str("scope") };
|
|
122
445
|
}
|
|
123
446
|
function sourceEndpoint(ctx, suffix) {
|
|
124
|
-
return `${
|
|
447
|
+
return `${API2}/sources/${encodeURIComponent(ctx.str("id").trim())}/${suffix}`;
|
|
125
448
|
}
|
|
126
449
|
function previewEndpoint(ctx) {
|
|
127
450
|
return sourceEndpoint(ctx, `directory/previews/${encodeURIComponent(ctx.str("preview-id").trim())}`);
|
|
128
451
|
}
|
|
129
|
-
function dryRequest(ctx, method,
|
|
130
|
-
return { method, url: `${ctx.host().replace(/\/$/, "")}${
|
|
452
|
+
function dryRequest(ctx, method, endpoint3, body4) {
|
|
453
|
+
return { method, url: `${ctx.host().replace(/\/$/, "")}${endpoint3}`, params: query2(ctx), ...body4 === void 0 ? {} : { body: body4 } };
|
|
131
454
|
}
|
|
132
455
|
async function replacementFile(ctx, read) {
|
|
133
|
-
const file =
|
|
134
|
-
const extension =
|
|
456
|
+
const file = path3.resolve(ctx.str("file"));
|
|
457
|
+
const extension = path3.extname(file).toLowerCase();
|
|
135
458
|
if (ctx.str("source-type") === "zip" ? extension !== ".zip" : !fileExtensions.has(extension)) {
|
|
136
459
|
throw new CliValidationError("--file must be a ZIP for a ZIP source, or a supported non-ZIP file for a file source. File sources must keep their original format.");
|
|
137
460
|
}
|
|
138
|
-
const handle = await
|
|
461
|
+
const handle = await fs3.open(file, "r");
|
|
139
462
|
try {
|
|
140
463
|
const stat = await handle.stat();
|
|
141
|
-
if (!stat.isFile() || stat.size >
|
|
464
|
+
if (!stat.isFile() || stat.size > maxBytes2) throw new CliValidationError("--file must be a regular file of at most 50 MB.");
|
|
142
465
|
const content = read ? await handle.readFile() : void 0;
|
|
143
|
-
if (content && content.length >
|
|
144
|
-
return { file, filename:
|
|
466
|
+
if (content && content.length > maxBytes2) throw new CliValidationError("--file exceeds 50 MB.");
|
|
467
|
+
return { file, filename: path3.basename(file), sizeBytes: content?.length ?? stat.size, content };
|
|
145
468
|
} finally {
|
|
146
469
|
await handle.close();
|
|
147
470
|
}
|
|
@@ -157,26 +480,40 @@ var sourceReplace = {
|
|
|
157
480
|
resource: "source",
|
|
158
481
|
command: "replace",
|
|
159
482
|
risk: "write",
|
|
160
|
-
description: "Replace a file source draft, or prepare a ZIP archive replacement preview. ZIP changes require source commit. Does not compile or publish.",
|
|
161
|
-
flags: [...
|
|
483
|
+
description: "Replace a file source draft from a file or complete text, or prepare a ZIP archive replacement preview. ZIP changes require source commit. Does not compile or publish.",
|
|
484
|
+
flags: [...identityFlags2, typeFlag, revisionFlag, ...textInputFlags.map((flag2) => flag2.name === "file" ? { ...flag2, desc: "Local replacement file, at most 50 MiB; same format, different filename allowed; mutually exclusive with --text and --stdin" } : flag2)],
|
|
162
485
|
validate: (ctx) => {
|
|
163
486
|
validateMutation(ctx);
|
|
164
|
-
|
|
487
|
+
validateTextInput(ctx);
|
|
488
|
+
if ((hasTextFlag(ctx) || ctx.bool("stdin")) && ctx.str("source-type") !== "file") {
|
|
489
|
+
throw new CliValidationError("--text and --stdin require --source-type file and an ordinary text source.");
|
|
490
|
+
}
|
|
165
491
|
},
|
|
166
492
|
dryRun: async (ctx) => {
|
|
493
|
+
if (hasTextFlag(ctx) || ctx.bool("stdin")) {
|
|
494
|
+
const { sizeBytes: sizeBytes2 } = await readTextInput(ctx);
|
|
495
|
+
return { ...dryRequest(ctx, "PUT", sourceEndpoint(ctx, "text"), { expectedRevision: ctx.num("expected-revision"), inputMethod: "text_input", content: "<redacted>" }), sizeBytes: sizeBytes2 };
|
|
496
|
+
}
|
|
167
497
|
const { file, filename, sizeBytes } = await replacementFile(ctx, false);
|
|
168
498
|
return { ...dryRequest(ctx, ctx.str("source-type") === "zip" ? "POST" : "PUT", replaceEndpoint(ctx), replaceFields(ctx)), multipart: { file, filename, sizeBytes, content: "<redacted>" } };
|
|
169
499
|
},
|
|
170
500
|
execute: async (ctx) => {
|
|
501
|
+
if (hasTextFlag(ctx) || ctx.bool("stdin")) {
|
|
502
|
+
return kbApi(ctx, "PUT", sourceEndpoint(ctx, "text"), query2(ctx), {
|
|
503
|
+
content: (await readTextInput(ctx)).content,
|
|
504
|
+
expectedRevision: ctx.num("expected-revision"),
|
|
505
|
+
inputMethod: "text_input"
|
|
506
|
+
}, textApiOptions);
|
|
507
|
+
}
|
|
171
508
|
const file = await replacementFile(ctx, true);
|
|
172
509
|
const form = new FormData();
|
|
173
510
|
form.append("file", new Blob([new Uint8Array(file.content)]), file.filename);
|
|
174
511
|
for (const [key, value] of Object.entries(replaceFields(ctx))) form.append(key, String(value));
|
|
175
|
-
return kbUpload(ctx, replaceEndpoint(ctx), form,
|
|
512
|
+
return kbUpload(ctx, replaceEndpoint(ctx), form, query2(ctx), { ...apiOptions, method: ctx.str("source-type") === "zip" ? "POST" : "PUT" });
|
|
176
513
|
}
|
|
177
514
|
};
|
|
178
515
|
function restoreEndpoint(ctx) {
|
|
179
|
-
return `${
|
|
516
|
+
return `${API2}/versions/${ctx.num("version")}/sources/${encodeURIComponent(ctx.str("id").trim())}/restore`;
|
|
180
517
|
}
|
|
181
518
|
function restoreBody(ctx) {
|
|
182
519
|
return { expectedRevision: ctx.num("expected-revision"), ...ctx.str("source-type") === "zip" ? ctx.str("path") ? { target: "file", path: ctx.str("path") } : { target: "source" } : {} };
|
|
@@ -188,7 +525,7 @@ var sourceRestore = {
|
|
|
188
525
|
risk: "write",
|
|
189
526
|
description: "Restore one current source draft from a published version. File sources restore immediately; ZIP source or child restores return a preview. Does not roll back the whole knowledge base or publish.",
|
|
190
527
|
flags: [
|
|
191
|
-
...
|
|
528
|
+
...identityFlags2,
|
|
192
529
|
typeFlag,
|
|
193
530
|
revisionFlag,
|
|
194
531
|
{ name: "version", type: "number", required: true, min: 1, max: 2147483647, desc: "Published version number from kb +versions; use the latest number to discard unpublished changes" },
|
|
@@ -203,7 +540,7 @@ var sourceRestore = {
|
|
|
203
540
|
}
|
|
204
541
|
},
|
|
205
542
|
dryRun: (ctx) => dryRequest(ctx, "POST", restoreEndpoint(ctx), restoreBody(ctx)),
|
|
206
|
-
execute: (ctx) => kbApi(ctx, "POST", restoreEndpoint(ctx),
|
|
543
|
+
execute: (ctx) => kbApi(ctx, "POST", restoreEndpoint(ctx), query2(ctx), restoreBody(ctx), apiOptions)
|
|
207
544
|
};
|
|
208
545
|
var sourcePreview = {
|
|
209
546
|
service: "kb",
|
|
@@ -212,7 +549,7 @@ var sourcePreview = {
|
|
|
212
549
|
risk: "read",
|
|
213
550
|
description: "Read one page of a ZIP replacement or restore preview, including additions, modifications and deletions.",
|
|
214
551
|
flags: [
|
|
215
|
-
...
|
|
552
|
+
...identityFlags2,
|
|
216
553
|
previewFlag,
|
|
217
554
|
{ name: "cursor", type: "string", desc: "Opaque nextCursor returned by the previous preview page" },
|
|
218
555
|
{ name: "limit", type: "number", default: 100, min: 1, max: 200, desc: "Preview page size from 1 to 200" }
|
|
@@ -222,8 +559,8 @@ var sourcePreview = {
|
|
|
222
559
|
if (!Number.isInteger(ctx.num("limit")) || ctx.num("limit") < 1 || ctx.num("limit") > 200) throw new CliValidationError("--limit must be an integer from 1 to 200.");
|
|
223
560
|
if (ctx.str("cursor").length > 4096) throw new CliValidationError("--cursor must be at most 4096 characters.");
|
|
224
561
|
},
|
|
225
|
-
dryRun: (ctx) => ({ ...dryRequest(ctx, "GET", previewEndpoint(ctx)), params: { ...
|
|
226
|
-
execute: (ctx) => kbApi(ctx, "GET", previewEndpoint(ctx), { ...
|
|
562
|
+
dryRun: (ctx) => ({ ...dryRequest(ctx, "GET", previewEndpoint(ctx)), params: { ...query2(ctx), limit: ctx.num("limit"), ...ctx.str("cursor") ? { cursor: ctx.str("cursor") } : {} } }),
|
|
563
|
+
execute: (ctx) => kbApi(ctx, "GET", previewEndpoint(ctx), { ...query2(ctx), limit: ctx.num("limit"), ...ctx.str("cursor") ? { cursor: ctx.str("cursor") } : {} }, void 0, apiOptions)
|
|
227
564
|
};
|
|
228
565
|
var sourceCommit = {
|
|
229
566
|
service: "kb",
|
|
@@ -231,13 +568,13 @@ var sourceCommit = {
|
|
|
231
568
|
command: "commit",
|
|
232
569
|
risk: "high-risk-write",
|
|
233
570
|
description: "Confirm a reviewed ZIP replacement or restore preview. May delete missing files; changes only the draft. On uncertain outcome, inspect state before any retry.",
|
|
234
|
-
flags: [...
|
|
571
|
+
flags: [...identityFlags2, previewFlag, revisionFlag],
|
|
235
572
|
validate: (ctx) => {
|
|
236
573
|
validateIdentity(ctx);
|
|
237
574
|
positiveInteger(ctx, "expected-revision");
|
|
238
575
|
},
|
|
239
576
|
dryRun: (ctx) => dryRequest(ctx, "POST", `${previewEndpoint(ctx)}/commit`, { expectedRevision: ctx.num("expected-revision"), confirmed: true }),
|
|
240
|
-
execute: (ctx) => kbApi(ctx, "POST", `${previewEndpoint(ctx)}/commit`,
|
|
577
|
+
execute: (ctx) => kbApi(ctx, "POST", `${previewEndpoint(ctx)}/commit`, query2(ctx), { expectedRevision: ctx.num("expected-revision"), confirmed: true }, apiOptions)
|
|
241
578
|
};
|
|
242
579
|
var sourceCancel = {
|
|
243
580
|
service: "kb",
|
|
@@ -245,20 +582,20 @@ var sourceCancel = {
|
|
|
245
582
|
command: "cancel",
|
|
246
583
|
risk: "high-risk-write",
|
|
247
584
|
description: "Discard an uncommitted ZIP replacement or restore preview; leaves the source draft unchanged.",
|
|
248
|
-
flags: [...
|
|
585
|
+
flags: [...identityFlags2, previewFlag],
|
|
249
586
|
validate: validateIdentity,
|
|
250
587
|
dryRun: (ctx) => dryRequest(ctx, "DELETE", previewEndpoint(ctx)),
|
|
251
588
|
execute: async (ctx) => {
|
|
252
|
-
await kbApi(ctx, "DELETE", previewEndpoint(ctx),
|
|
589
|
+
await kbApi(ctx, "DELETE", previewEndpoint(ctx), query2(ctx), void 0, { ...apiOptions, responseType: "empty" });
|
|
253
590
|
return { previewId: ctx.str("preview-id"), cancelled: true };
|
|
254
591
|
}
|
|
255
592
|
};
|
|
256
593
|
|
|
257
594
|
// src/commands/te-kb/add.ts
|
|
258
|
-
import { promises as
|
|
259
|
-
import * as
|
|
595
|
+
import { promises as fs4 } from "fs";
|
|
596
|
+
import * as path4 from "path";
|
|
260
597
|
import TurndownService from "turndown";
|
|
261
|
-
var
|
|
598
|
+
var API_PATH3 = "/agent/api/external/knowledge-bases/sources/upload";
|
|
262
599
|
var SUPPORTED_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
263
600
|
".zip",
|
|
264
601
|
".md",
|
|
@@ -305,7 +642,7 @@ function sanitizeFilename(name) {
|
|
|
305
642
|
return cleaned || "document";
|
|
306
643
|
}
|
|
307
644
|
function getMimeType(filename) {
|
|
308
|
-
const ext =
|
|
645
|
+
const ext = path4.extname(filename).toLowerCase();
|
|
309
646
|
switch (ext) {
|
|
310
647
|
case ".zip":
|
|
311
648
|
return "application/zip";
|
|
@@ -348,23 +685,23 @@ function getMimeType(filename) {
|
|
|
348
685
|
}
|
|
349
686
|
}
|
|
350
687
|
async function readLocalFile(filePath) {
|
|
351
|
-
const ext =
|
|
688
|
+
const ext = path4.extname(filePath).toLowerCase();
|
|
352
689
|
if (!SUPPORTED_EXTENSIONS.has(ext)) {
|
|
353
690
|
throw new Error(`Unsupported file extension (${ext || "none"}): ${filePath}`);
|
|
354
691
|
}
|
|
355
|
-
const content = await
|
|
356
|
-
const filename =
|
|
692
|
+
const content = await fs4.readFile(filePath);
|
|
693
|
+
const filename = path4.basename(filePath);
|
|
357
694
|
return { filename, content, mimeType: getMimeType(filename), origin: "file", source: filePath };
|
|
358
695
|
}
|
|
359
696
|
async function readDirectory(dir) {
|
|
360
|
-
const entries = await
|
|
697
|
+
const entries = await fs4.readdir(dir, { withFileTypes: true });
|
|
361
698
|
const files = [];
|
|
362
699
|
for (const entry of entries) {
|
|
363
700
|
if (!entry.isFile()) continue;
|
|
364
|
-
const ext =
|
|
701
|
+
const ext = path4.extname(entry.name).toLowerCase();
|
|
365
702
|
if (!SUPPORTED_EXTENSIONS.has(ext)) continue;
|
|
366
|
-
const full =
|
|
367
|
-
const content = await
|
|
703
|
+
const full = path4.join(dir, entry.name);
|
|
704
|
+
const content = await fs4.readFile(full);
|
|
368
705
|
files.push({ filename: entry.name, content, mimeType: getMimeType(entry.name), origin: "dir", source: full });
|
|
369
706
|
}
|
|
370
707
|
if (files.length === 0) {
|
|
@@ -399,10 +736,10 @@ async function fetchAsMarkdown(rawUrl) {
|
|
|
399
736
|
};
|
|
400
737
|
}
|
|
401
738
|
async function resolveLocalPath(p) {
|
|
402
|
-
const abs =
|
|
739
|
+
const abs = path4.resolve(p);
|
|
403
740
|
let stat;
|
|
404
741
|
try {
|
|
405
|
-
stat = await
|
|
742
|
+
stat = await fs4.stat(abs);
|
|
406
743
|
} catch {
|
|
407
744
|
throw new Error(`Path not found: ${p}`);
|
|
408
745
|
}
|
|
@@ -438,7 +775,7 @@ function dedupeByFilename(files) {
|
|
|
438
775
|
const count = used.get(f.filename) ?? 0;
|
|
439
776
|
used.set(f.filename, count + 1);
|
|
440
777
|
if (count === 0) return f;
|
|
441
|
-
const ext =
|
|
778
|
+
const ext = path4.extname(f.filename);
|
|
442
779
|
const stem = f.filename.slice(0, f.filename.length - ext.length);
|
|
443
780
|
return { ...f, filename: `${stem}-${count}${ext}` };
|
|
444
781
|
});
|
|
@@ -473,17 +810,17 @@ var add = {
|
|
|
473
810
|
},
|
|
474
811
|
dryRun: (ctx) => {
|
|
475
812
|
const items = normalizeFilesInput(ctx.json("files"));
|
|
476
|
-
const
|
|
813
|
+
const body4 = {
|
|
477
814
|
name: ctx.str("name")
|
|
478
815
|
};
|
|
479
816
|
const scope = getExternalKnowledgeBaseTargetScope(ctx);
|
|
480
|
-
if (scope)
|
|
481
|
-
|
|
482
|
-
|
|
817
|
+
if (scope) body4.scope = scope;
|
|
818
|
+
body4.files = items.map((item) => ({ value: item, type: classifyInput(item) }));
|
|
819
|
+
body4.contentType = "multipart/form-data";
|
|
483
820
|
return {
|
|
484
821
|
method: "POST",
|
|
485
|
-
url: `${ctx.host().replace(/\/$/, "")}${
|
|
486
|
-
body:
|
|
822
|
+
url: `${ctx.host().replace(/\/$/, "")}${API_PATH3}`,
|
|
823
|
+
body: body4
|
|
487
824
|
};
|
|
488
825
|
},
|
|
489
826
|
execute: async (ctx) => {
|
|
@@ -491,7 +828,7 @@ var add = {
|
|
|
491
828
|
const scope = getExternalKnowledgeBaseTargetScope(ctx);
|
|
492
829
|
const files = await collectFiles(ctx);
|
|
493
830
|
const form = buildForm(name, scope, files);
|
|
494
|
-
const result = await kbUpload(ctx,
|
|
831
|
+
const result = await kbUpload(ctx, API_PATH3, form);
|
|
495
832
|
return {
|
|
496
833
|
uploaded: files.map((f) => ({ filename: f.filename, origin: f.origin, source: f.source })),
|
|
497
834
|
result
|
|
@@ -500,7 +837,7 @@ var add = {
|
|
|
500
837
|
};
|
|
501
838
|
|
|
502
839
|
// src/commands/te-kb/compile.ts
|
|
503
|
-
var
|
|
840
|
+
var API_PATH4 = "/agent/api/external/knowledge-bases/compile";
|
|
504
841
|
var VALID_MODES = /* @__PURE__ */ new Set(["incremental", "full"]);
|
|
505
842
|
function getMode(ctx) {
|
|
506
843
|
const mode = ctx.str("mode") || "incremental";
|
|
@@ -510,15 +847,15 @@ function getMode(ctx) {
|
|
|
510
847
|
return mode;
|
|
511
848
|
}
|
|
512
849
|
function buildBody(ctx) {
|
|
513
|
-
const
|
|
850
|
+
const body4 = {
|
|
514
851
|
name: ctx.str("name"),
|
|
515
852
|
mode: getMode(ctx)
|
|
516
853
|
};
|
|
517
854
|
const scope = getExternalKnowledgeBaseTargetScope(ctx);
|
|
518
|
-
if (scope)
|
|
855
|
+
if (scope) body4.scope = scope;
|
|
519
856
|
const model = ctx.str("model");
|
|
520
|
-
if (model)
|
|
521
|
-
return
|
|
857
|
+
if (model) body4.model = model;
|
|
858
|
+
return body4;
|
|
522
859
|
}
|
|
523
860
|
var compile = {
|
|
524
861
|
service: "kb",
|
|
@@ -537,19 +874,19 @@ var compile = {
|
|
|
537
874
|
},
|
|
538
875
|
dryRun: (ctx) => ({
|
|
539
876
|
method: "POST",
|
|
540
|
-
url: `${ctx.host().replace(/\/$/, "")}${
|
|
877
|
+
url: `${ctx.host().replace(/\/$/, "")}${API_PATH4}`,
|
|
541
878
|
body: buildBody(ctx)
|
|
542
879
|
}),
|
|
543
|
-
execute: async (ctx) => kbApi(ctx, "POST",
|
|
880
|
+
execute: async (ctx) => kbApi(ctx, "POST", API_PATH4, {}, buildBody(ctx))
|
|
544
881
|
};
|
|
545
882
|
|
|
546
883
|
// src/commands/te-kb/remove.ts
|
|
547
|
-
var
|
|
884
|
+
var API_PATH5 = "/agent/api/external/knowledge-bases";
|
|
548
885
|
function buildBody2(ctx) {
|
|
549
|
-
const
|
|
886
|
+
const body4 = { name: ctx.str("name") };
|
|
550
887
|
const scope = getExternalKnowledgeBaseTargetScope(ctx);
|
|
551
|
-
if (scope)
|
|
552
|
-
return
|
|
888
|
+
if (scope) body4.scope = scope;
|
|
889
|
+
return body4;
|
|
553
890
|
}
|
|
554
891
|
var remove = {
|
|
555
892
|
service: "kb",
|
|
@@ -565,14 +902,14 @@ var remove = {
|
|
|
565
902
|
},
|
|
566
903
|
dryRun: (ctx) => ({
|
|
567
904
|
method: "DELETE",
|
|
568
|
-
url: `${ctx.host().replace(/\/$/, "")}${
|
|
905
|
+
url: `${ctx.host().replace(/\/$/, "")}${API_PATH5}`,
|
|
569
906
|
body: buildBody2(ctx)
|
|
570
907
|
}),
|
|
571
|
-
execute: async (ctx) => kbApi(ctx, "DELETE",
|
|
908
|
+
execute: async (ctx) => kbApi(ctx, "DELETE", API_PATH5, {}, buildBody2(ctx))
|
|
572
909
|
};
|
|
573
910
|
|
|
574
911
|
// src/commands/te-kb/create.ts
|
|
575
|
-
var
|
|
912
|
+
var API_PATH6 = "/agent/api/external/knowledge-bases/create";
|
|
576
913
|
var VALID_SCOPES = /* @__PURE__ */ new Set(["personal", "company"]);
|
|
577
914
|
function getScope(ctx) {
|
|
578
915
|
const scope = ctx.str("scope") || "company";
|
|
@@ -600,19 +937,19 @@ function normalizeTags(raw) {
|
|
|
600
937
|
return tags;
|
|
601
938
|
}
|
|
602
939
|
function buildBody3(ctx) {
|
|
603
|
-
const
|
|
940
|
+
const body4 = {
|
|
604
941
|
scope: getScope(ctx),
|
|
605
942
|
name: ctx.str("name")
|
|
606
943
|
};
|
|
607
944
|
const description = ctx.str("description");
|
|
608
|
-
if (description)
|
|
945
|
+
if (description) body4.description = description;
|
|
609
946
|
const tags = normalizeTags(ctx.json("tags"));
|
|
610
|
-
if (tags && tags.length > 0)
|
|
947
|
+
if (tags && tags.length > 0) body4.tags = tags;
|
|
611
948
|
const projectId = ctx.str("project-id");
|
|
612
|
-
if (projectId)
|
|
949
|
+
if (projectId) body4.projectId = projectId;
|
|
613
950
|
const projectName = ctx.str("project-name");
|
|
614
|
-
if (projectName)
|
|
615
|
-
return
|
|
951
|
+
if (projectName) body4.projectName = projectName;
|
|
952
|
+
return body4;
|
|
616
953
|
}
|
|
617
954
|
var create = {
|
|
618
955
|
service: "kb",
|
|
@@ -633,14 +970,14 @@ var create = {
|
|
|
633
970
|
},
|
|
634
971
|
dryRun: (ctx) => ({
|
|
635
972
|
method: "POST",
|
|
636
|
-
url: `${ctx.host().replace(/\/$/, "")}${
|
|
973
|
+
url: `${ctx.host().replace(/\/$/, "")}${API_PATH6}`,
|
|
637
974
|
body: buildBody3(ctx)
|
|
638
975
|
}),
|
|
639
|
-
execute: async (ctx) => kbApi(ctx, "POST",
|
|
976
|
+
execute: async (ctx) => kbApi(ctx, "POST", API_PATH6, {}, buildBody3(ctx))
|
|
640
977
|
};
|
|
641
978
|
|
|
642
979
|
// src/commands/te-kb/rm-source.ts
|
|
643
|
-
var
|
|
980
|
+
var API_PATH7 = "/agent/api/external/knowledge-bases/sources";
|
|
644
981
|
function sourceSelector(ctx) {
|
|
645
982
|
const id = ctx.str("id").trim();
|
|
646
983
|
if (id) return { id };
|
|
@@ -649,12 +986,12 @@ function sourceSelector(ctx) {
|
|
|
649
986
|
throw new CliValidationError("One of --id or --display-name is required.");
|
|
650
987
|
}
|
|
651
988
|
function buildBody4(ctx) {
|
|
652
|
-
const
|
|
989
|
+
const body4 = {
|
|
653
990
|
name: ctx.str("name")
|
|
654
991
|
};
|
|
655
992
|
const scope = getExternalKnowledgeBaseTargetScope(ctx);
|
|
656
|
-
if (scope)
|
|
657
|
-
return { ...
|
|
993
|
+
if (scope) body4.scope = scope;
|
|
994
|
+
return { ...body4, ...sourceSelector(ctx) };
|
|
658
995
|
}
|
|
659
996
|
var rmSource = {
|
|
660
997
|
service: "kb",
|
|
@@ -673,18 +1010,18 @@ var rmSource = {
|
|
|
673
1010
|
},
|
|
674
1011
|
dryRun: (ctx) => ({
|
|
675
1012
|
method: "DELETE",
|
|
676
|
-
url: `${ctx.host().replace(/\/$/, "")}${
|
|
1013
|
+
url: `${ctx.host().replace(/\/$/, "")}${API_PATH7}`,
|
|
677
1014
|
body: buildBody4(ctx)
|
|
678
1015
|
}),
|
|
679
|
-
execute: async (ctx) => kbApi(ctx, "DELETE",
|
|
1016
|
+
execute: async (ctx) => kbApi(ctx, "DELETE", API_PATH7, {}, buildBody4(ctx), {
|
|
680
1017
|
preserveErrorMetadata: true
|
|
681
1018
|
})
|
|
682
1019
|
};
|
|
683
1020
|
|
|
684
1021
|
// src/commands/te-kb/schema.ts
|
|
685
|
-
import
|
|
686
|
-
import
|
|
687
|
-
var
|
|
1022
|
+
import fs5 from "fs";
|
|
1023
|
+
import path5 from "path";
|
|
1024
|
+
var API_PATH8 = "/agent/api/external/knowledge-bases/schema";
|
|
688
1025
|
var MAX_CUSTOM_INSTRUCTIONS_CHARS = 1e4;
|
|
689
1026
|
function getCustomInstructions(ctx) {
|
|
690
1027
|
const inline = ctx.str("custom-instructions");
|
|
@@ -692,7 +1029,7 @@ function getCustomInstructions(ctx) {
|
|
|
692
1029
|
if (inline && file) {
|
|
693
1030
|
throw new Error("Use either --custom-instructions or --custom-instructions-file, not both.");
|
|
694
1031
|
}
|
|
695
|
-
const content = file ?
|
|
1032
|
+
const content = file ? fs5.readFileSync(path5.resolve(file), "utf8") : inline;
|
|
696
1033
|
if (file && !content.trim()) {
|
|
697
1034
|
throw new Error("--custom-instructions-file is empty.");
|
|
698
1035
|
}
|
|
@@ -702,20 +1039,20 @@ function getCustomInstructions(ctx) {
|
|
|
702
1039
|
return content;
|
|
703
1040
|
}
|
|
704
1041
|
function buildBody5(ctx) {
|
|
705
|
-
const
|
|
1042
|
+
const body4 = {
|
|
706
1043
|
name: ctx.str("name")
|
|
707
1044
|
};
|
|
708
1045
|
const scope = getExternalKnowledgeBaseTargetScope(ctx);
|
|
709
|
-
if (scope)
|
|
710
|
-
if (ctx.bool("force"))
|
|
1046
|
+
if (scope) body4.scope = scope;
|
|
1047
|
+
if (ctx.bool("force")) body4.force = true;
|
|
711
1048
|
const model = ctx.str("model");
|
|
712
|
-
if (model)
|
|
1049
|
+
if (model) body4.model = model;
|
|
713
1050
|
const customInstructions = getCustomInstructions(ctx);
|
|
714
|
-
if (customInstructions)
|
|
715
|
-
return
|
|
1051
|
+
if (customInstructions) body4.customInstructions = customInstructions;
|
|
1052
|
+
return body4;
|
|
716
1053
|
}
|
|
717
1054
|
async function executeSchema(ctx, api = kbApi) {
|
|
718
|
-
return api(ctx, "POST",
|
|
1055
|
+
return api(ctx, "POST", API_PATH8, {}, buildBody5(ctx), {
|
|
719
1056
|
preserveBusinessErrorCode: true
|
|
720
1057
|
});
|
|
721
1058
|
}
|
|
@@ -750,21 +1087,21 @@ var schema = {
|
|
|
750
1087
|
},
|
|
751
1088
|
dryRun: (ctx) => ({
|
|
752
1089
|
method: "POST",
|
|
753
|
-
url: `${ctx.host().replace(/\/$/, "")}${
|
|
1090
|
+
url: `${ctx.host().replace(/\/$/, "")}${API_PATH8}`,
|
|
754
1091
|
body: buildBody5(ctx)
|
|
755
1092
|
}),
|
|
756
1093
|
execute: executeSchema
|
|
757
1094
|
};
|
|
758
1095
|
|
|
759
1096
|
// src/commands/te-kb/status.ts
|
|
760
|
-
var
|
|
1097
|
+
var API_PATH9 = "/agent/api/external/knowledge-bases/status";
|
|
761
1098
|
function buildBody6(ctx) {
|
|
762
|
-
const
|
|
1099
|
+
const body4 = {
|
|
763
1100
|
name: ctx.str("name")
|
|
764
1101
|
};
|
|
765
1102
|
const scope = getExternalKnowledgeBaseTargetScope(ctx);
|
|
766
|
-
if (scope)
|
|
767
|
-
return
|
|
1103
|
+
if (scope) body4.scope = scope;
|
|
1104
|
+
return body4;
|
|
768
1105
|
}
|
|
769
1106
|
var status = {
|
|
770
1107
|
service: "kb",
|
|
@@ -780,21 +1117,21 @@ var status = {
|
|
|
780
1117
|
},
|
|
781
1118
|
dryRun: (ctx) => ({
|
|
782
1119
|
method: "POST",
|
|
783
|
-
url: `${ctx.host().replace(/\/$/, "")}${
|
|
1120
|
+
url: `${ctx.host().replace(/\/$/, "")}${API_PATH9}`,
|
|
784
1121
|
body: buildBody6(ctx)
|
|
785
1122
|
}),
|
|
786
|
-
execute: async (ctx) => kbApi(ctx, "POST",
|
|
1123
|
+
execute: async (ctx) => kbApi(ctx, "POST", API_PATH9, {}, buildBody6(ctx))
|
|
787
1124
|
};
|
|
788
1125
|
|
|
789
1126
|
// src/commands/te-kb/kb-index.ts
|
|
790
|
-
var
|
|
1127
|
+
var API_PATH10 = "/agent/api/external/knowledge-bases/index";
|
|
791
1128
|
function buildBody7(ctx) {
|
|
792
|
-
const
|
|
1129
|
+
const body4 = {};
|
|
793
1130
|
const sources = ctx.json("sources");
|
|
794
|
-
if (sources)
|
|
1131
|
+
if (sources) body4.sources = sources;
|
|
795
1132
|
const locale = ctx.str("locale");
|
|
796
|
-
if (locale)
|
|
797
|
-
return
|
|
1133
|
+
if (locale) body4.locale = locale;
|
|
1134
|
+
return body4;
|
|
798
1135
|
}
|
|
799
1136
|
var kbIndex = {
|
|
800
1137
|
service: "kb",
|
|
@@ -812,14 +1149,14 @@ var kbIndex = {
|
|
|
812
1149
|
risk: "read",
|
|
813
1150
|
dryRun: (ctx) => ({
|
|
814
1151
|
method: "POST",
|
|
815
|
-
url: `${ctx.host().replace(/\/$/, "")}${
|
|
1152
|
+
url: `${ctx.host().replace(/\/$/, "")}${API_PATH10}`,
|
|
816
1153
|
body: buildBody7(ctx)
|
|
817
1154
|
}),
|
|
818
|
-
execute: async (ctx) => kbApi(ctx, "POST",
|
|
1155
|
+
execute: async (ctx) => kbApi(ctx, "POST", API_PATH10, {}, buildBody7(ctx))
|
|
819
1156
|
};
|
|
820
1157
|
|
|
821
1158
|
// src/commands/te-kb/kb-list.ts
|
|
822
|
-
var
|
|
1159
|
+
var API_PATH11 = "/agent/api/external/knowledge-bases/list";
|
|
823
1160
|
var DEFAULT_BUILD_STATUS = "compiled";
|
|
824
1161
|
var VALID_BUILD_STATUSES = ["idle", "pending", "compiling", "compiled", "failed"];
|
|
825
1162
|
function getBuildStatus(ctx) {
|
|
@@ -836,12 +1173,12 @@ function validateBuildStatus(ctx) {
|
|
|
836
1173
|
}
|
|
837
1174
|
}
|
|
838
1175
|
function buildBody8(ctx) {
|
|
839
|
-
const
|
|
1176
|
+
const body4 = {
|
|
840
1177
|
buildStatus: getBuildStatus(ctx)
|
|
841
1178
|
};
|
|
842
1179
|
const locale = ctx.str("locale");
|
|
843
|
-
if (locale)
|
|
844
|
-
return
|
|
1180
|
+
if (locale) body4.locale = locale;
|
|
1181
|
+
return body4;
|
|
845
1182
|
}
|
|
846
1183
|
var kbList = {
|
|
847
1184
|
service: "kb",
|
|
@@ -863,23 +1200,24 @@ var kbList = {
|
|
|
863
1200
|
},
|
|
864
1201
|
dryRun: (ctx) => ({
|
|
865
1202
|
method: "POST",
|
|
866
|
-
url: `${ctx.host().replace(/\/$/, "")}${
|
|
1203
|
+
url: `${ctx.host().replace(/\/$/, "")}${API_PATH11}`,
|
|
867
1204
|
body: buildBody8(ctx)
|
|
868
1205
|
}),
|
|
869
|
-
execute: async (ctx) => kbApi(ctx, "POST",
|
|
1206
|
+
execute: async (ctx) => kbApi(ctx, "POST", API_PATH11, {}, buildBody8(ctx))
|
|
870
1207
|
};
|
|
871
1208
|
|
|
872
1209
|
// src/commands/te-kb/list-sources.ts
|
|
873
|
-
var
|
|
1210
|
+
var API_PATH12 = "/agent/api/external/knowledge-bases/sources";
|
|
874
1211
|
var MAX_KNOWLEDGE_BASE_NAME_LENGTH = 200;
|
|
875
1212
|
function knowledgeBaseName(ctx) {
|
|
876
1213
|
return ctx.str("name").trim();
|
|
877
1214
|
}
|
|
878
1215
|
function buildUrl(ctx) {
|
|
879
|
-
const url2 = new URL(`${ctx.host().replace(/\/$/, "")}${
|
|
1216
|
+
const url2 = new URL(`${ctx.host().replace(/\/$/, "")}${API_PATH12}`);
|
|
880
1217
|
url2.searchParams.set("name", knowledgeBaseName(ctx));
|
|
881
1218
|
const scope = getExternalKnowledgeBaseTargetScope(ctx);
|
|
882
1219
|
if (scope) url2.searchParams.set("scope", scope);
|
|
1220
|
+
if (ctx.str("content-type")) url2.searchParams.set("contentType", ctx.str("content-type"));
|
|
883
1221
|
return url2.toString();
|
|
884
1222
|
}
|
|
885
1223
|
var listSources = {
|
|
@@ -900,7 +1238,8 @@ var listSources = {
|
|
|
900
1238
|
type: "string",
|
|
901
1239
|
required: false,
|
|
902
1240
|
desc: "Exact knowledge base scope: personal | company (omit for personal \u2192 company fallback)"
|
|
903
|
-
}
|
|
1241
|
+
},
|
|
1242
|
+
{ name: "content-type", type: "string", desc: "Source content filter: all (default) or text (ordinary .md, .markdown and .txt files only)" }
|
|
904
1243
|
],
|
|
905
1244
|
risk: "read",
|
|
906
1245
|
validate: (ctx) => {
|
|
@@ -914,6 +1253,9 @@ var listSources = {
|
|
|
914
1253
|
);
|
|
915
1254
|
}
|
|
916
1255
|
getExternalKnowledgeBaseTargetScope(ctx);
|
|
1256
|
+
if ((ctx.has?.("content-type") || ctx.str("content-type")) && !["all", "text"].includes(ctx.str("content-type"))) {
|
|
1257
|
+
throw new CliValidationError("--content-type must be all or text.");
|
|
1258
|
+
}
|
|
917
1259
|
},
|
|
918
1260
|
dryRun: (ctx) => ({
|
|
919
1261
|
method: "GET",
|
|
@@ -923,26 +1265,82 @@ var listSources = {
|
|
|
923
1265
|
const params = { name: knowledgeBaseName(ctx) };
|
|
924
1266
|
const scope = getExternalKnowledgeBaseTargetScope(ctx);
|
|
925
1267
|
if (scope) params.scope = scope;
|
|
926
|
-
|
|
1268
|
+
if (ctx.str("content-type")) params.contentType = ctx.str("content-type");
|
|
1269
|
+
return kbApi(ctx, "GET", API_PATH12, params, void 0, {
|
|
927
1270
|
preserveErrorMetadata: true,
|
|
928
1271
|
retryUnauthorized: false
|
|
929
1272
|
});
|
|
930
1273
|
}
|
|
931
1274
|
};
|
|
932
1275
|
|
|
1276
|
+
// src/commands/te-kb/usage-list.ts
|
|
1277
|
+
var API_PATH13 = "/agent/api/external/knowledge-bases/usage-logs";
|
|
1278
|
+
function query3(ctx) {
|
|
1279
|
+
const scope = getExternalKnowledgeBaseTargetScope(ctx);
|
|
1280
|
+
return {
|
|
1281
|
+
name: ctx.str("name").trim(),
|
|
1282
|
+
...scope ? { scope } : {},
|
|
1283
|
+
page: ctx.num("page"),
|
|
1284
|
+
pageSize: ctx.num("page-size")
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
1287
|
+
var usageList = {
|
|
1288
|
+
service: "kb",
|
|
1289
|
+
resource: "usage",
|
|
1290
|
+
command: "list",
|
|
1291
|
+
risk: "read",
|
|
1292
|
+
description: "List one page of compilation usage logs. durationMs is elapsed time in milliseconds; null means not recorded.",
|
|
1293
|
+
flags: [
|
|
1294
|
+
{ name: "name", type: "string", required: true, minLength: 1, maxLength: 200, desc: "Exact knowledge base name from kb +list" },
|
|
1295
|
+
{ name: "scope", type: "string", desc: "Exact scope: personal | company (omit for personal then company lookup)" },
|
|
1296
|
+
{ name: "page", type: "number", default: 1, min: 1, max: 2147483647, desc: "Page number, starting at 1" },
|
|
1297
|
+
{ name: "page-size", type: "number", default: 20, min: 1, max: 100, desc: "Records per page, from 1 to 100" }
|
|
1298
|
+
],
|
|
1299
|
+
validate: (ctx) => {
|
|
1300
|
+
const name = ctx.str("name").trim();
|
|
1301
|
+
if (!name || name.length > 200) throw new CliValidationError("--name must contain 1 to 200 characters.");
|
|
1302
|
+
getExternalKnowledgeBaseTargetScope(ctx);
|
|
1303
|
+
for (const [flag2, max] of [["page", 2147483647], ["page-size", 100]]) {
|
|
1304
|
+
const value = ctx.num(flag2);
|
|
1305
|
+
if (!Number.isInteger(value) || value < 1 || value > max) {
|
|
1306
|
+
throw new CliValidationError(`--${flag2} must be an integer from 1 to ${max}.`);
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
},
|
|
1310
|
+
dryRun: (ctx) => ({ method: "GET", url: `${ctx.host().replace(/\/$/, "")}${API_PATH13}`, params: query3(ctx) }),
|
|
1311
|
+
execute: async (ctx) => {
|
|
1312
|
+
try {
|
|
1313
|
+
return await kbApi(ctx, "GET", API_PATH13, query3(ctx), void 0, { preserveErrorMetadata: true });
|
|
1314
|
+
} catch (error) {
|
|
1315
|
+
if (error instanceof PermissionError) {
|
|
1316
|
+
error.message = "Permission denied when reading knowledge base usage logs.";
|
|
1317
|
+
} else if (error instanceof CapabilityGatewayError) {
|
|
1318
|
+
const messages = {
|
|
1319
|
+
KB_USAGE_LOGS_INVALID_REQUEST: "Invalid knowledge base usage query parameters.",
|
|
1320
|
+
KB_USAGE_LOGS_RATE_LIMITED: "Knowledge base usage query rate limit exceeded. Try again later.",
|
|
1321
|
+
KB_USAGE_LOGS_NOT_FOUND: "Knowledge base not found in the requested scope.",
|
|
1322
|
+
KB_USAGE_LOGS_INTERNAL_ERROR: "Failed to read knowledge base usage logs. Try again later."
|
|
1323
|
+
};
|
|
1324
|
+
if (error.code && messages[error.code]) error.message = messages[error.code];
|
|
1325
|
+
}
|
|
1326
|
+
throw error;
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
};
|
|
1330
|
+
|
|
933
1331
|
// src/commands/te-kb/kb-grep.ts
|
|
934
|
-
var
|
|
1332
|
+
var API_PATH14 = "/agent/api/external/knowledge-bases/grep";
|
|
935
1333
|
function buildBody9(ctx) {
|
|
936
|
-
const
|
|
1334
|
+
const body4 = {
|
|
937
1335
|
query: ctx.str("query"),
|
|
938
1336
|
sources: ctx.json("sources"),
|
|
939
1337
|
paths: ctx.json("paths")
|
|
940
1338
|
};
|
|
941
1339
|
const topK = ctx.optionalNum("top-k");
|
|
942
|
-
if (topK !== void 0)
|
|
1340
|
+
if (topK !== void 0) body4.topK = topK;
|
|
943
1341
|
const locale = ctx.str("locale");
|
|
944
|
-
if (locale)
|
|
945
|
-
return
|
|
1342
|
+
if (locale) body4.locale = locale;
|
|
1343
|
+
return body4;
|
|
946
1344
|
}
|
|
947
1345
|
var kbGrep = {
|
|
948
1346
|
service: "kb",
|
|
@@ -974,14 +1372,14 @@ var kbGrep = {
|
|
|
974
1372
|
risk: "read",
|
|
975
1373
|
dryRun: (ctx) => ({
|
|
976
1374
|
method: "POST",
|
|
977
|
-
url: `${ctx.host().replace(/\/$/, "")}${
|
|
1375
|
+
url: `${ctx.host().replace(/\/$/, "")}${API_PATH14}`,
|
|
978
1376
|
body: buildBody9(ctx)
|
|
979
1377
|
}),
|
|
980
|
-
execute: async (ctx) => kbApi(ctx, "POST",
|
|
1378
|
+
execute: async (ctx) => kbApi(ctx, "POST", API_PATH14, {}, buildBody9(ctx))
|
|
981
1379
|
};
|
|
982
1380
|
|
|
983
1381
|
// src/commands/te-kb/kb-read.ts
|
|
984
|
-
var
|
|
1382
|
+
var API_PATH15 = "/agent/api/external/knowledge-bases/read";
|
|
985
1383
|
var VALID_EXPAND_MODES = /* @__PURE__ */ new Set(["block", "none"]);
|
|
986
1384
|
var MAX_READ_LIMIT = 2e3;
|
|
987
1385
|
function readExpand(ctx) {
|
|
@@ -1005,20 +1403,20 @@ function readLimit(ctx) {
|
|
|
1005
1403
|
return limit;
|
|
1006
1404
|
}
|
|
1007
1405
|
function buildBody10(ctx) {
|
|
1008
|
-
const
|
|
1406
|
+
const body4 = {
|
|
1009
1407
|
source: ctx.json("source"),
|
|
1010
1408
|
path: ctx.str("path")
|
|
1011
1409
|
};
|
|
1012
1410
|
const offset = ctx.optionalNum("offset");
|
|
1013
|
-
if (offset !== void 0)
|
|
1411
|
+
if (offset !== void 0) body4.offset = offset;
|
|
1014
1412
|
const limit = ctx.optionalNum("limit");
|
|
1015
|
-
if (limit !== void 0)
|
|
1413
|
+
if (limit !== void 0) body4.limit = limit;
|
|
1016
1414
|
const expand = readExpand(ctx);
|
|
1017
|
-
if (expand)
|
|
1018
|
-
if (ctx.bool("outline"))
|
|
1415
|
+
if (expand) body4.expand = expand;
|
|
1416
|
+
if (ctx.bool("outline")) body4.outline = true;
|
|
1019
1417
|
const locale = ctx.str("locale");
|
|
1020
|
-
if (locale)
|
|
1021
|
-
return
|
|
1418
|
+
if (locale) body4.locale = locale;
|
|
1419
|
+
return body4;
|
|
1022
1420
|
}
|
|
1023
1421
|
var kbRead = {
|
|
1024
1422
|
service: "kb",
|
|
@@ -1059,10 +1457,10 @@ var kbRead = {
|
|
|
1059
1457
|
},
|
|
1060
1458
|
dryRun: (ctx) => ({
|
|
1061
1459
|
method: "POST",
|
|
1062
|
-
url: `${ctx.host().replace(/\/$/, "")}${
|
|
1460
|
+
url: `${ctx.host().replace(/\/$/, "")}${API_PATH15}`,
|
|
1063
1461
|
body: buildBody10(ctx)
|
|
1064
1462
|
}),
|
|
1065
|
-
execute: async (ctx) => kbApi(ctx, "POST",
|
|
1463
|
+
execute: async (ctx) => kbApi(ctx, "POST", API_PATH15, {}, buildBody10(ctx))
|
|
1066
1464
|
};
|
|
1067
1465
|
|
|
1068
1466
|
// src/commands/te-kb/ask-shared.ts
|
|
@@ -1081,12 +1479,12 @@ function isTransientAskPollError(error) {
|
|
|
1081
1479
|
error.message
|
|
1082
1480
|
);
|
|
1083
1481
|
}
|
|
1084
|
-
async function pollUntilSettled(getStatus, executionId,
|
|
1085
|
-
const intervalMs =
|
|
1086
|
-
const timeoutMs =
|
|
1087
|
-
const maxTransientFailures =
|
|
1088
|
-
const now =
|
|
1089
|
-
const sleep =
|
|
1482
|
+
async function pollUntilSettled(getStatus, executionId, options2 = {}) {
|
|
1483
|
+
const intervalMs = options2.intervalMs ?? ASK_POLL_INTERVAL_MS;
|
|
1484
|
+
const timeoutMs = options2.timeoutMs ?? ASK_POLL_TIMEOUT_MS;
|
|
1485
|
+
const maxTransientFailures = options2.maxTransientFailures ?? ASK_MAX_TRANSIENT_POLL_FAILURES;
|
|
1486
|
+
const now = options2.now ?? Date.now;
|
|
1487
|
+
const sleep = options2.sleep ?? ((ms) => new Promise((resolve2) => setTimeout(resolve2, ms)));
|
|
1090
1488
|
const startTime = now();
|
|
1091
1489
|
let transientFailures = 0;
|
|
1092
1490
|
while (true) {
|
|
@@ -1143,16 +1541,16 @@ function validateLocale(locale) {
|
|
|
1143
1541
|
}
|
|
1144
1542
|
}
|
|
1145
1543
|
function buildBody11(ctx) {
|
|
1146
|
-
const
|
|
1544
|
+
const body4 = {
|
|
1147
1545
|
question: ctx.str("question")
|
|
1148
1546
|
};
|
|
1149
1547
|
const sources = ctx.json("sources");
|
|
1150
|
-
if (sources)
|
|
1548
|
+
if (sources) body4.sources = sources;
|
|
1151
1549
|
const modelId = ctx.str("model-id");
|
|
1152
|
-
if (modelId)
|
|
1550
|
+
if (modelId) body4.modelId = modelId;
|
|
1153
1551
|
const locale = ctx.str("locale");
|
|
1154
|
-
if (locale)
|
|
1155
|
-
return
|
|
1552
|
+
if (locale) body4.locale = locale;
|
|
1553
|
+
return body4;
|
|
1156
1554
|
}
|
|
1157
1555
|
var ask = {
|
|
1158
1556
|
service: "kb",
|
|
@@ -1272,24 +1670,24 @@ var askStatus = {
|
|
|
1272
1670
|
};
|
|
1273
1671
|
|
|
1274
1672
|
// src/commands/te-kb/url.ts
|
|
1275
|
-
var
|
|
1673
|
+
var API_PATH16 = "/agent/api/external/knowledge-bases/sources/url";
|
|
1276
1674
|
function validateUrl(url2) {
|
|
1277
1675
|
if (!/^https?:\/\//i.test(url2)) {
|
|
1278
1676
|
throw new Error(`Invalid --url: ${url2}. Must be an http(s) URL`);
|
|
1279
1677
|
}
|
|
1280
1678
|
}
|
|
1281
1679
|
function buildBody12(ctx) {
|
|
1282
|
-
const
|
|
1680
|
+
const body4 = {
|
|
1283
1681
|
name: ctx.str("name"),
|
|
1284
1682
|
url: ctx.str("url")
|
|
1285
1683
|
};
|
|
1286
1684
|
const scope = getExternalKnowledgeBaseTargetScope(ctx);
|
|
1287
|
-
if (scope)
|
|
1685
|
+
if (scope) body4.scope = scope;
|
|
1288
1686
|
const displayName = ctx.str("display-name");
|
|
1289
|
-
if (displayName)
|
|
1687
|
+
if (displayName) body4.displayName = displayName;
|
|
1290
1688
|
const parseInstruction = ctx.str("parse-instruction");
|
|
1291
|
-
if (parseInstruction)
|
|
1292
|
-
return
|
|
1689
|
+
if (parseInstruction) body4.parseInstruction = parseInstruction;
|
|
1690
|
+
return body4;
|
|
1293
1691
|
}
|
|
1294
1692
|
var url = {
|
|
1295
1693
|
service: "kb",
|
|
@@ -1309,16 +1707,16 @@ var url = {
|
|
|
1309
1707
|
},
|
|
1310
1708
|
dryRun: (ctx) => ({
|
|
1311
1709
|
method: "POST",
|
|
1312
|
-
url: `${ctx.host().replace(/\/$/, "")}${
|
|
1710
|
+
url: `${ctx.host().replace(/\/$/, "")}${API_PATH16}`,
|
|
1313
1711
|
body: buildBody12(ctx)
|
|
1314
1712
|
}),
|
|
1315
|
-
execute: async (ctx) => kbApi(ctx, "POST",
|
|
1713
|
+
execute: async (ctx) => kbApi(ctx, "POST", API_PATH16, {}, buildBody12(ctx))
|
|
1316
1714
|
};
|
|
1317
1715
|
|
|
1318
1716
|
// src/commands/te-kb/import.ts
|
|
1319
|
-
import { promises as
|
|
1320
|
-
import
|
|
1321
|
-
var
|
|
1717
|
+
import { promises as fs6 } from "fs";
|
|
1718
|
+
import path6 from "path";
|
|
1719
|
+
var API_PATH17 = "/agent/api/external/knowledge-bases/import";
|
|
1322
1720
|
var MAX_SNAPSHOT_ARCHIVE_BYTES = 50 * 1024 * 1024;
|
|
1323
1721
|
var VALID_SCOPES2 = /* @__PURE__ */ new Set(["personal", "company"]);
|
|
1324
1722
|
function getScope2(ctx) {
|
|
@@ -1354,16 +1752,16 @@ function normalizeTags2(raw) {
|
|
|
1354
1752
|
return tags;
|
|
1355
1753
|
}
|
|
1356
1754
|
function validateArchivePath(filePath) {
|
|
1357
|
-
if (
|
|
1755
|
+
if (path6.extname(filePath).toLocaleLowerCase("en-US") !== ".zip") {
|
|
1358
1756
|
throw new Error("--file must point to a .zip archive");
|
|
1359
1757
|
}
|
|
1360
1758
|
}
|
|
1361
1759
|
async function readArchive(filePath) {
|
|
1362
1760
|
validateArchivePath(filePath);
|
|
1363
|
-
const absolutePath =
|
|
1761
|
+
const absolutePath = path6.resolve(filePath);
|
|
1364
1762
|
let stat;
|
|
1365
1763
|
try {
|
|
1366
|
-
stat = await
|
|
1764
|
+
stat = await fs6.stat(absolutePath);
|
|
1367
1765
|
} catch {
|
|
1368
1766
|
throw new Error(`File not found: ${filePath}`);
|
|
1369
1767
|
}
|
|
@@ -1373,7 +1771,7 @@ async function readArchive(filePath) {
|
|
|
1373
1771
|
if (stat.size > MAX_SNAPSHOT_ARCHIVE_BYTES) {
|
|
1374
1772
|
throw new Error("--file must not exceed 50 MB");
|
|
1375
1773
|
}
|
|
1376
|
-
return { absolutePath, bytes: await
|
|
1774
|
+
return { absolutePath, bytes: await fs6.readFile(absolutePath) };
|
|
1377
1775
|
}
|
|
1378
1776
|
function appendOptionalFields(ctx, form) {
|
|
1379
1777
|
const description = ctx.str("description").trim();
|
|
@@ -1440,7 +1838,7 @@ var importSnapshot = {
|
|
|
1440
1838
|
form.append(
|
|
1441
1839
|
"file",
|
|
1442
1840
|
new Blob([Uint8Array.from(archive.bytes)], { type: "application/zip" }),
|
|
1443
|
-
|
|
1841
|
+
path6.basename(archive.absolutePath)
|
|
1444
1842
|
);
|
|
1445
1843
|
form.append("name", ctx.str("name").trim());
|
|
1446
1844
|
form.append("scope", getScope2(ctx));
|
|
@@ -1448,7 +1846,7 @@ var importSnapshot = {
|
|
|
1448
1846
|
try {
|
|
1449
1847
|
return await kbUpload(
|
|
1450
1848
|
ctx,
|
|
1451
|
-
|
|
1849
|
+
API_PATH17,
|
|
1452
1850
|
form,
|
|
1453
1851
|
{ scope: getScope2(ctx) },
|
|
1454
1852
|
{ preserveErrorMetadata: true, retryUnauthorized: true }
|
|
@@ -1477,7 +1875,7 @@ var importSnapshot = {
|
|
|
1477
1875
|
};
|
|
1478
1876
|
|
|
1479
1877
|
// src/commands/te-kb/import-status.ts
|
|
1480
|
-
var
|
|
1878
|
+
var API_PATH18 = "/agent/api/external/knowledge-bases/import";
|
|
1481
1879
|
var MAX_REQUEST_ID_LENGTH = 191;
|
|
1482
1880
|
function requestIdFrom(ctx) {
|
|
1483
1881
|
return ctx.str("request-id").trim();
|
|
@@ -1508,7 +1906,7 @@ var importStatus = {
|
|
|
1508
1906
|
},
|
|
1509
1907
|
dryRun: (ctx) => ({
|
|
1510
1908
|
method: "GET",
|
|
1511
|
-
url: `${ctx.host().replace(/\/$/, "")}${
|
|
1909
|
+
url: `${ctx.host().replace(/\/$/, "")}${API_PATH18}?requestId=${encodeURIComponent(requestIdFrom(ctx))}`
|
|
1512
1910
|
}),
|
|
1513
1911
|
execute: async (ctx) => {
|
|
1514
1912
|
const hint = "Verify the request ID and that the server supports kb +import-status. Do not retry the import until its status is known.";
|
|
@@ -1516,7 +1914,7 @@ var importStatus = {
|
|
|
1516
1914
|
return await kbApi(
|
|
1517
1915
|
ctx,
|
|
1518
1916
|
"GET",
|
|
1519
|
-
|
|
1917
|
+
API_PATH18,
|
|
1520
1918
|
{ requestId: requestIdFrom(ctx) },
|
|
1521
1919
|
void 0,
|
|
1522
1920
|
{ preserveErrorMetadata: true, retryUnauthorized: true }
|
|
@@ -1547,8 +1945,8 @@ var importStatus = {
|
|
|
1547
1945
|
};
|
|
1548
1946
|
|
|
1549
1947
|
// src/commands/te-kb/source-directory.ts
|
|
1550
|
-
import { promises as
|
|
1551
|
-
import
|
|
1948
|
+
import { promises as fs7 } from "fs";
|
|
1949
|
+
import path7 from "path";
|
|
1552
1950
|
var sourceFlags = [
|
|
1553
1951
|
{ name: "name", type: "string", required: true, desc: "Knowledge base name (personal then company)" },
|
|
1554
1952
|
{ name: "id", type: "string", required: true, desc: "ZIP source ID copied from +list-sources" }
|
|
@@ -1564,9 +1962,9 @@ var revisionFlag2 = {
|
|
|
1564
1962
|
var apiOptions2 = { preserveErrorMetadata: true, retryUnauthorized: false };
|
|
1565
1963
|
var maxFileBytes = 50 * 1024 * 1024;
|
|
1566
1964
|
function validateIdentity2(ctx) {
|
|
1567
|
-
for (const [
|
|
1568
|
-
const value = ctx.str(
|
|
1569
|
-
if (!value || value.length > max) throw new CliValidationError(`Invalid --${
|
|
1965
|
+
for (const [flag2, max] of [["name", 200], ["id", 191]]) {
|
|
1966
|
+
const value = ctx.str(flag2).trim();
|
|
1967
|
+
if (!value || value.length > max) throw new CliValidationError(`Invalid --${flag2}.`);
|
|
1570
1968
|
}
|
|
1571
1969
|
}
|
|
1572
1970
|
function relativePath(ctx, allowRoot = false) {
|
|
@@ -1584,14 +1982,14 @@ function validateMutation2(ctx) {
|
|
|
1584
1982
|
throw new CliValidationError("--expected-revision must be a positive safe integer.");
|
|
1585
1983
|
}
|
|
1586
1984
|
}
|
|
1587
|
-
function
|
|
1985
|
+
function endpoint2(ctx, suffix = "directory") {
|
|
1588
1986
|
return `/agent/api/external/knowledge-bases/sources/${encodeURIComponent(ctx.str("id").trim())}/${suffix}`;
|
|
1589
1987
|
}
|
|
1590
|
-
function
|
|
1988
|
+
function query4(ctx) {
|
|
1591
1989
|
return { name: ctx.str("name").trim(), path: ctx.str("path") };
|
|
1592
1990
|
}
|
|
1593
|
-
function preview(ctx, method, suffix = "directory",
|
|
1594
|
-
return { method, url: `${ctx.host().replace(/\/$/, "")}${
|
|
1991
|
+
function preview(ctx, method, suffix = "directory", body4) {
|
|
1992
|
+
return { method, url: `${ctx.host().replace(/\/$/, "")}${endpoint2(ctx, suffix)}`, ...body4 ? { body: body4 } : { params: query4(ctx) } };
|
|
1595
1993
|
}
|
|
1596
1994
|
function mutationBody(ctx, operation) {
|
|
1597
1995
|
return { name: ctx.str("name").trim(), expectedRevision: ctx.num("expected-revision"), operations: [operation] };
|
|
@@ -1614,9 +2012,9 @@ var sourceLs = {
|
|
|
1614
2012
|
throw new CliValidationError("--limit must be an integer from 1 to 200.");
|
|
1615
2013
|
}
|
|
1616
2014
|
},
|
|
1617
|
-
dryRun: (ctx) => ({ ...preview(ctx, "GET"), params: { ...
|
|
1618
|
-
execute: (ctx) => kbApi(ctx, "GET",
|
|
1619
|
-
...
|
|
2015
|
+
dryRun: (ctx) => ({ ...preview(ctx, "GET"), params: { ...query4(ctx), limit: ctx.num("limit"), ...ctx.str("cursor") ? { cursor: ctx.str("cursor") } : {} } }),
|
|
2016
|
+
execute: (ctx) => kbApi(ctx, "GET", endpoint2(ctx), {
|
|
2017
|
+
...query4(ctx),
|
|
1620
2018
|
limit: ctx.num("limit"),
|
|
1621
2019
|
...ctx.str("cursor") ? { cursor: ctx.str("cursor") } : {}
|
|
1622
2020
|
}, void 0, apiOptions2)
|
|
@@ -1639,12 +2037,12 @@ var sourceRead = {
|
|
|
1639
2037
|
},
|
|
1640
2038
|
dryRun: (ctx) => preview(ctx, "GET", "raw"),
|
|
1641
2039
|
execute: async (ctx) => {
|
|
1642
|
-
const result = await kbApi(ctx, "GET",
|
|
2040
|
+
const result = await kbApi(ctx, "GET", endpoint2(ctx, "raw"), query4(ctx), void 0, { ...apiOptions2, responseType: "bytes" });
|
|
1643
2041
|
const bytes = Buffer.from(result.bytes);
|
|
1644
2042
|
const metadata = { path: ctx.str("path"), sizeBytes: bytes.length, contentType: result.contentType };
|
|
1645
2043
|
if (ctx.str("output")) {
|
|
1646
|
-
const output =
|
|
1647
|
-
await
|
|
2044
|
+
const output = path7.resolve(ctx.str("output"));
|
|
2045
|
+
await fs7.writeFile(output, bytes, { flag: "wx" });
|
|
1648
2046
|
return { ...metadata, output };
|
|
1649
2047
|
}
|
|
1650
2048
|
if (ctx.str("encoding") === "base64") return { ...metadata, encoding: "base64", content: bytes.toString("base64") };
|
|
@@ -1656,8 +2054,8 @@ var sourceRead = {
|
|
|
1656
2054
|
}
|
|
1657
2055
|
};
|
|
1658
2056
|
async function fileOperation(ctx, dryRun) {
|
|
1659
|
-
const file =
|
|
1660
|
-
const handle = await
|
|
2057
|
+
const file = path7.resolve(ctx.str("file"));
|
|
2058
|
+
const handle = await fs7.open(file, "r");
|
|
1661
2059
|
try {
|
|
1662
2060
|
const stat = await handle.stat();
|
|
1663
2061
|
if (!stat.isFile() || stat.size > maxFileBytes) throw new CliValidationError("--file must be a regular file of at most 50 MB.");
|
|
@@ -1692,7 +2090,7 @@ var sourcePut = {
|
|
|
1692
2090
|
if (!["add", "replace"].includes(ctx.str("action"))) throw new CliValidationError("--action must be add or replace.");
|
|
1693
2091
|
},
|
|
1694
2092
|
dryRun: async (ctx) => preview(ctx, "POST", "directory", mutationBody(ctx, await fileOperation(ctx, true))),
|
|
1695
|
-
execute: async (ctx) => kbApi(ctx, "POST",
|
|
2093
|
+
execute: async (ctx) => kbApi(ctx, "POST", endpoint2(ctx), {}, mutationBody(ctx, await fileOperation(ctx, false)), apiOptions2)
|
|
1696
2094
|
};
|
|
1697
2095
|
function deleteOperation(ctx) {
|
|
1698
2096
|
return { action: "delete", path: ctx.str("path"), confirmed: true, ...ctx.bool("recursive") ? { recursive: true } : {} };
|
|
@@ -1710,15 +2108,15 @@ var sourceRm = {
|
|
|
1710
2108
|
],
|
|
1711
2109
|
validate: validateMutation2,
|
|
1712
2110
|
dryRun: (ctx) => preview(ctx, "POST", "directory", mutationBody(ctx, deleteOperation(ctx))),
|
|
1713
|
-
execute: (ctx) => kbApi(ctx, "POST",
|
|
2111
|
+
execute: (ctx) => kbApi(ctx, "POST", endpoint2(ctx), {}, mutationBody(ctx, deleteOperation(ctx)), apiOptions2)
|
|
1714
2112
|
};
|
|
1715
2113
|
|
|
1716
2114
|
// src/commands/te-kb/version-management.ts
|
|
1717
|
-
import { promises as
|
|
1718
|
-
import
|
|
1719
|
-
var
|
|
2115
|
+
import { promises as fs8 } from "fs";
|
|
2116
|
+
import path8 from "path";
|
|
2117
|
+
var API3 = "/agent/api/external/knowledge-bases/versions";
|
|
1720
2118
|
var apiOptions3 = { preserveErrorMetadata: true, retryUnauthorized: false };
|
|
1721
|
-
var
|
|
2119
|
+
var targetFlags3 = [
|
|
1722
2120
|
{ name: "name", type: "string", required: true, minLength: 1, maxLength: 200, desc: "Exact knowledge base name copied from +list" },
|
|
1723
2121
|
{ name: "scope", type: "string", desc: "Exact personal or company scope; omit for personal then company lookup" }
|
|
1724
2122
|
];
|
|
@@ -1729,18 +2127,18 @@ var pagingFlags = [
|
|
|
1729
2127
|
{ name: "limit", type: "number", default: 100, min: 1, max: 200, desc: "Page size from 1 to 200" }
|
|
1730
2128
|
];
|
|
1731
2129
|
var pathFlag2 = { name: "path", type: "string", desc: "Exact path relative to the historical source directory" };
|
|
1732
|
-
function positiveInteger2(ctx,
|
|
1733
|
-
const value = ctx.num(
|
|
1734
|
-
if (!Number.isSafeInteger(value) || value < 1 || value > 2147483647) throw new CliValidationError(`--${
|
|
2130
|
+
function positiveInteger2(ctx, flag2) {
|
|
2131
|
+
const value = ctx.num(flag2);
|
|
2132
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > 2147483647) throw new CliValidationError(`--${flag2} must be a positive integer no greater than 2147483647.`);
|
|
1735
2133
|
return value;
|
|
1736
2134
|
}
|
|
1737
|
-
function
|
|
2135
|
+
function validateTarget2(ctx) {
|
|
1738
2136
|
const name = ctx.str("name").trim();
|
|
1739
2137
|
if (!name || name.length > 200) throw new CliValidationError("--name must contain 1 to 200 characters.");
|
|
1740
2138
|
getExternalKnowledgeBaseTargetScope(ctx);
|
|
1741
2139
|
}
|
|
1742
2140
|
function validateVersion(ctx) {
|
|
1743
|
-
|
|
2141
|
+
validateTarget2(ctx);
|
|
1744
2142
|
positiveInteger2(ctx, "version");
|
|
1745
2143
|
}
|
|
1746
2144
|
function validateSource(ctx) {
|
|
@@ -1760,52 +2158,52 @@ function validatePath(ctx, required = false) {
|
|
|
1760
2158
|
throw new CliValidationError("--path must be a normalized relative path inside the historical source.");
|
|
1761
2159
|
}
|
|
1762
2160
|
}
|
|
1763
|
-
function
|
|
2161
|
+
function query5(ctx) {
|
|
1764
2162
|
const scope = getExternalKnowledgeBaseTargetScope(ctx);
|
|
1765
2163
|
return { name: ctx.str("name").trim(), ...scope ? { scope } : {} };
|
|
1766
2164
|
}
|
|
1767
2165
|
function pageQuery(ctx) {
|
|
1768
|
-
return { ...
|
|
2166
|
+
return { ...query5(ctx), limit: ctx.num("limit"), ...ctx.str("cursor") ? { cursor: ctx.str("cursor") } : {} };
|
|
1769
2167
|
}
|
|
1770
2168
|
function versionEndpoint(ctx, suffix = "") {
|
|
1771
|
-
return `${
|
|
2169
|
+
return `${API3}/${positiveInteger2(ctx, "version")}${suffix}`;
|
|
1772
2170
|
}
|
|
1773
2171
|
function sourceEndpoint2(ctx, action) {
|
|
1774
2172
|
return versionEndpoint(ctx, `/sources/${encodeURIComponent(ctx.str("id").trim())}/${action}`);
|
|
1775
2173
|
}
|
|
1776
|
-
function preview2(ctx,
|
|
1777
|
-
return { method:
|
|
2174
|
+
function preview2(ctx, endpoint3, params, body4) {
|
|
2175
|
+
return { method: body4 ? "POST" : "GET", url: `${ctx.host().replace(/\/$/, "")}${endpoint3}`, params, ...body4 ? { body: body4 } : {} };
|
|
1778
2176
|
}
|
|
1779
2177
|
var versions = {
|
|
1780
2178
|
service: "kb",
|
|
1781
2179
|
command: "+versions",
|
|
1782
2180
|
risk: "read",
|
|
1783
2181
|
description: "List immutable published versions and the latest version ID, one page at a time.",
|
|
1784
|
-
flags: [...
|
|
2182
|
+
flags: [...targetFlags3, ...pagingFlags],
|
|
1785
2183
|
validate: (ctx) => {
|
|
1786
|
-
|
|
2184
|
+
validateTarget2(ctx);
|
|
1787
2185
|
validatePage(ctx);
|
|
1788
2186
|
if (ctx.str("cursor") && (!/^[1-9][0-9]*$/.test(ctx.str("cursor")) || Number(ctx.str("cursor")) > 2147483647)) throw new CliValidationError("--cursor must be a version number returned as nextCursor.");
|
|
1789
2187
|
},
|
|
1790
|
-
dryRun: (ctx) => preview2(ctx,
|
|
1791
|
-
execute: (ctx) => kbApi(ctx, "GET",
|
|
2188
|
+
dryRun: (ctx) => preview2(ctx, API3, pageQuery(ctx)),
|
|
2189
|
+
execute: (ctx) => kbApi(ctx, "GET", API3, pageQuery(ctx), void 0, apiOptions3)
|
|
1792
2190
|
};
|
|
1793
2191
|
var versionShow = {
|
|
1794
2192
|
service: "kb",
|
|
1795
2193
|
command: "+version-show",
|
|
1796
2194
|
risk: "read",
|
|
1797
2195
|
description: "Read one published version summary without reading current sources.",
|
|
1798
|
-
flags: [...
|
|
2196
|
+
flags: [...targetFlags3, versionFlag],
|
|
1799
2197
|
validate: validateVersion,
|
|
1800
|
-
dryRun: (ctx) => preview2(ctx, versionEndpoint(ctx),
|
|
1801
|
-
execute: (ctx) => kbApi(ctx, "GET", versionEndpoint(ctx),
|
|
2198
|
+
dryRun: (ctx) => preview2(ctx, versionEndpoint(ctx), query5(ctx)),
|
|
2199
|
+
execute: (ctx) => kbApi(ctx, "GET", versionEndpoint(ctx), query5(ctx), void 0, apiOptions3)
|
|
1802
2200
|
};
|
|
1803
2201
|
var versionSources = {
|
|
1804
2202
|
service: "kb",
|
|
1805
2203
|
command: "+version-sources",
|
|
1806
2204
|
risk: "read",
|
|
1807
2205
|
description: "List historical sources and stable IDs from one immutable version.",
|
|
1808
|
-
flags: [...
|
|
2206
|
+
flags: [...targetFlags3, versionFlag, ...pagingFlags, { name: "source-type", type: "string", desc: "Optional source type filter: file | url | zip" }],
|
|
1809
2207
|
validate: (ctx) => {
|
|
1810
2208
|
validateVersion(ctx);
|
|
1811
2209
|
validatePage(ctx);
|
|
@@ -1819,21 +2217,21 @@ var versionDiff = {
|
|
|
1819
2217
|
command: "+version-diff",
|
|
1820
2218
|
risk: "read",
|
|
1821
2219
|
description: "Compare historical source additions, deletions, content, and metadata between two versions.",
|
|
1822
|
-
flags: [...
|
|
2220
|
+
flags: [...targetFlags3, { ...versionFlag, name: "from", desc: "Before version number" }, { ...versionFlag, name: "to", desc: "After version number" }],
|
|
1823
2221
|
validate: (ctx) => {
|
|
1824
|
-
|
|
2222
|
+
validateTarget2(ctx);
|
|
1825
2223
|
positiveInteger2(ctx, "from");
|
|
1826
2224
|
positiveInteger2(ctx, "to");
|
|
1827
2225
|
},
|
|
1828
|
-
dryRun: (ctx) => preview2(ctx, `${
|
|
1829
|
-
execute: (ctx) => kbApi(ctx, "GET", `${
|
|
2226
|
+
dryRun: (ctx) => preview2(ctx, `${API3}/compare`, { ...query5(ctx), from: ctx.num("from"), to: ctx.num("to") }),
|
|
2227
|
+
execute: (ctx) => kbApi(ctx, "GET", `${API3}/compare`, { ...query5(ctx), from: ctx.num("from"), to: ctx.num("to") }, void 0, apiOptions3)
|
|
1830
2228
|
};
|
|
1831
2229
|
var versionTree = {
|
|
1832
2230
|
service: "kb",
|
|
1833
2231
|
command: "+version-tree",
|
|
1834
2232
|
risk: "read",
|
|
1835
2233
|
description: "List a historical ZIP or URL source directory without changing current files.",
|
|
1836
|
-
flags: [...
|
|
2234
|
+
flags: [...targetFlags3, versionFlag, sourceFlag, pathFlag2, ...pagingFlags],
|
|
1837
2235
|
validate: (ctx) => {
|
|
1838
2236
|
validateSource(ctx);
|
|
1839
2237
|
validatePath(ctx);
|
|
@@ -1847,30 +2245,30 @@ var versionRead = {
|
|
|
1847
2245
|
command: "+version-read",
|
|
1848
2246
|
risk: "read",
|
|
1849
2247
|
description: "Preview one historical directory child file; unsupported or oversized files return metadata only.",
|
|
1850
|
-
flags: [...
|
|
2248
|
+
flags: [...targetFlags3, versionFlag, sourceFlag, { ...pathFlag2, required: true }],
|
|
1851
2249
|
validate: (ctx) => {
|
|
1852
2250
|
validateSource(ctx);
|
|
1853
2251
|
validatePath(ctx, true);
|
|
1854
2252
|
},
|
|
1855
|
-
dryRun: (ctx) => preview2(ctx, sourceEndpoint2(ctx, "file"), { ...
|
|
1856
|
-
execute: (ctx) => kbApi(ctx, "GET", sourceEndpoint2(ctx, "file"), { ...
|
|
2253
|
+
dryRun: (ctx) => preview2(ctx, sourceEndpoint2(ctx, "file"), { ...query5(ctx), path: ctx.str("path") }),
|
|
2254
|
+
execute: (ctx) => kbApi(ctx, "GET", sourceEndpoint2(ctx, "file"), { ...query5(ctx), path: ctx.str("path") }, void 0, apiOptions3)
|
|
1857
2255
|
};
|
|
1858
2256
|
var versionDownload = {
|
|
1859
2257
|
service: "kb",
|
|
1860
2258
|
command: "+version-download",
|
|
1861
2259
|
risk: "read",
|
|
1862
2260
|
description: "Download one ordinary historical file source to a new local file. ZIP/URL directories cannot be downloaded.",
|
|
1863
|
-
flags: [...
|
|
2261
|
+
flags: [...targetFlags3, versionFlag, sourceFlag, { name: "output", type: "string", required: true, desc: "New local output path; existing files are never overwritten" }],
|
|
1864
2262
|
validate: (ctx) => {
|
|
1865
2263
|
validateSource(ctx);
|
|
1866
2264
|
if (!ctx.str("output").trim()) throw new CliValidationError("--output is required.");
|
|
1867
2265
|
},
|
|
1868
|
-
dryRun: (ctx) => ({ ...preview2(ctx, sourceEndpoint2(ctx, "raw"),
|
|
2266
|
+
dryRun: (ctx) => ({ ...preview2(ctx, sourceEndpoint2(ctx, "raw"), query5(ctx)), output: path8.resolve(ctx.str("output")) }),
|
|
1869
2267
|
execute: async (ctx) => {
|
|
1870
|
-
const result = await kbApi(ctx, "GET", sourceEndpoint2(ctx, "raw"),
|
|
1871
|
-
const output =
|
|
2268
|
+
const result = await kbApi(ctx, "GET", sourceEndpoint2(ctx, "raw"), query5(ctx), void 0, { ...apiOptions3, responseType: "bytes" });
|
|
2269
|
+
const output = path8.resolve(ctx.str("output"));
|
|
1872
2270
|
const bytes = Buffer.from(result.bytes);
|
|
1873
|
-
await
|
|
2271
|
+
await fs8.writeFile(output, bytes, { flag: "wx" });
|
|
1874
2272
|
return { versionNumber: ctx.num("version"), sourceId: ctx.str("id").trim(), sizeBytes: String(bytes.length), output };
|
|
1875
2273
|
}
|
|
1876
2274
|
};
|
|
@@ -1883,7 +2281,7 @@ var rollback = {
|
|
|
1883
2281
|
risk: "high-risk-write",
|
|
1884
2282
|
description: "Restore an earlier version as a new publication. Replace target-source drafts, delete other compiled sources, and preserve unpublished additions. Reuse request-id on network retries.",
|
|
1885
2283
|
flags: [
|
|
1886
|
-
...
|
|
2284
|
+
...targetFlags3,
|
|
1887
2285
|
versionFlag,
|
|
1888
2286
|
{ name: "request-id", type: "string", required: true, maxLength: 191, desc: "Caller-generated stable ASCII request ID; reuse exactly for retries of this logical operation" },
|
|
1889
2287
|
{ name: "expected-latest-version-id", type: "string", required: true, maxLength: 191, desc: "latestVersionId returned by +versions; conflicts require fresh discovery and a new intentional request" }
|
|
@@ -1894,26 +2292,31 @@ var rollback = {
|
|
|
1894
2292
|
const latest = ctx.str("expected-latest-version-id");
|
|
1895
2293
|
if (!latest || latest.length > 191) throw new CliValidationError("--expected-latest-version-id must contain 1 to 191 characters.");
|
|
1896
2294
|
},
|
|
1897
|
-
dryRun: (ctx) => preview2(ctx, versionEndpoint(ctx, "/rollback"),
|
|
1898
|
-
execute: (ctx) => kbApi(ctx, "POST", versionEndpoint(ctx, "/rollback"),
|
|
2295
|
+
dryRun: (ctx) => preview2(ctx, versionEndpoint(ctx, "/rollback"), query5(ctx), rollbackBody(ctx)),
|
|
2296
|
+
execute: (ctx) => kbApi(ctx, "POST", versionEndpoint(ctx, "/rollback"), query5(ctx), rollbackBody(ctx), apiOptions3)
|
|
1899
2297
|
};
|
|
1900
2298
|
var rollbackStatus = {
|
|
1901
2299
|
service: "kb",
|
|
1902
2300
|
command: "+rollback-status",
|
|
1903
2301
|
risk: "read",
|
|
1904
2302
|
description: "Read one persisted rollback operation without polling. A running operation with errorCode requires administrator review; never retry it as a new write.",
|
|
1905
|
-
flags: [...
|
|
2303
|
+
flags: [...targetFlags3, { name: "operation-id", type: "string", required: true, minLength: 1, maxLength: 191, desc: "operationId returned by +rollback" }],
|
|
1906
2304
|
validate: (ctx) => {
|
|
1907
|
-
|
|
2305
|
+
validateTarget2(ctx);
|
|
1908
2306
|
if (!ctx.str("operation-id").trim() || ctx.str("operation-id").length > 191) throw new CliValidationError("--operation-id must contain 1 to 191 characters.");
|
|
1909
2307
|
},
|
|
1910
|
-
dryRun: (ctx) => preview2(ctx, `${
|
|
1911
|
-
execute: (ctx) => kbApi(ctx, "GET", `${
|
|
2308
|
+
dryRun: (ctx) => preview2(ctx, `${API3}/operations/${encodeURIComponent(ctx.str("operation-id").trim())}`, query5(ctx)),
|
|
2309
|
+
execute: (ctx) => kbApi(ctx, "GET", `${API3}/operations/${encodeURIComponent(ctx.str("operation-id").trim())}`, query5(ctx), void 0, apiOptions3)
|
|
1912
2310
|
};
|
|
1913
2311
|
|
|
1914
2312
|
// src/commands/te-kb/index.ts
|
|
1915
2313
|
var commands = [
|
|
2314
|
+
usageList,
|
|
2315
|
+
...schemaImportCommands,
|
|
1916
2316
|
sourceCheckUpdates,
|
|
2317
|
+
sourceCheckUrlUpdates,
|
|
2318
|
+
sourceCreateText,
|
|
2319
|
+
sourceReadText,
|
|
1917
2320
|
sourceReplace,
|
|
1918
2321
|
sourceRestore,
|
|
1919
2322
|
sourcePreview,
|
|
@@ -1958,6 +2361,7 @@ export {
|
|
|
1958
2361
|
compile,
|
|
1959
2362
|
create,
|
|
1960
2363
|
te_kb_default as default,
|
|
2364
|
+
executeSchemaImport,
|
|
1961
2365
|
importSnapshot,
|
|
1962
2366
|
importStatus,
|
|
1963
2367
|
kbGrep,
|
|
@@ -1970,23 +2374,41 @@ export {
|
|
|
1970
2374
|
rollback,
|
|
1971
2375
|
rollbackStatus,
|
|
1972
2376
|
schema,
|
|
2377
|
+
schemaDownload,
|
|
2378
|
+
schemaImport,
|
|
2379
|
+
schemaImportAbandon,
|
|
2380
|
+
schemaImportApply,
|
|
2381
|
+
schemaImportCommands,
|
|
2382
|
+
schemaImportContent,
|
|
2383
|
+
schemaImportDiff,
|
|
2384
|
+
schemaImportList,
|
|
2385
|
+
schemaImportOptimize,
|
|
2386
|
+
schemaImportReject,
|
|
2387
|
+
schemaImportSave,
|
|
2388
|
+
schemaImportStatus,
|
|
2389
|
+
schemaImportValidate,
|
|
1973
2390
|
sourceCancel,
|
|
1974
2391
|
sourceCheckUpdates,
|
|
2392
|
+
sourceCheckUrlUpdates,
|
|
1975
2393
|
sourceCommit,
|
|
2394
|
+
sourceCreateText,
|
|
1976
2395
|
sourceLs,
|
|
1977
2396
|
sourcePreview,
|
|
1978
2397
|
sourcePut,
|
|
1979
2398
|
sourceRead,
|
|
2399
|
+
sourceReadText,
|
|
1980
2400
|
sourceReplace,
|
|
1981
2401
|
sourceRestore,
|
|
1982
2402
|
sourceRm,
|
|
1983
2403
|
status,
|
|
1984
2404
|
url,
|
|
2405
|
+
usageList,
|
|
1985
2406
|
versionDiff,
|
|
1986
2407
|
versionDownload,
|
|
1987
2408
|
versionRead,
|
|
1988
2409
|
versionShow,
|
|
1989
2410
|
versionSources,
|
|
1990
2411
|
versionTree,
|
|
1991
|
-
versions
|
|
2412
|
+
versions,
|
|
2413
|
+
waitSchemaImport
|
|
1992
2414
|
};
|