@thinkingai/ae-cli 6.0.48-customer.1 → 6.0.48

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.
Files changed (76) hide show
  1. package/README.md +93 -36
  2. package/README.zh.md +93 -36
  3. package/dist/{auth-QPEVVBKT.js → auth-FUM37MHF.js} +236 -127
  4. package/dist/{capability-RUSV77CO.js → capability-J4FU4JZW.js} +47 -34
  5. package/dist/{chunk-FR2EDAQM.js → chunk-4P355ZWB.js} +69 -1
  6. package/dist/{chunk-NSIVXKJH.js → chunk-6KBBAPPP.js} +5 -5
  7. package/dist/chunk-6ZIQV5GW.js +26 -0
  8. package/dist/chunk-ATSM5XAW.js +623 -0
  9. package/dist/{chunk-6QK7SYYY.js → chunk-BBEFP4SB.js} +29 -37
  10. package/dist/{chunk-KEWVSO64.js → chunk-CZU3V3DQ.js} +4 -15
  11. package/dist/chunk-ECBLHAZO.js +15 -0
  12. package/dist/{chunk-BVDST5YT.js → chunk-HPLNYQPM.js} +8 -8
  13. package/dist/{chunk-B5HMQAOM.js → chunk-I4WQAEYB.js} +1 -1
  14. package/dist/{chunk-BE73PUFX.js → chunk-LNZBEQXW.js} +2 -2
  15. package/dist/{chunk-GJXRF7Y6.js → chunk-QJQZH5GQ.js} +47 -78
  16. package/dist/{chunk-JYMGHGCE.js → chunk-VXNMYUXU.js} +24 -13
  17. package/dist/{chunk-KZ6ZHF5J.js → chunk-WZ6YVQSF.js} +14 -14
  18. package/dist/{community-report-client-6OL6GBQW.js → community-report-client-XXWGSBSD.js} +2 -4
  19. package/dist/{config-XNMACCKX.js → config-EXUGQN5T.js} +8 -9
  20. package/dist/{data-integration-FZQQC3KW.js → data-integration-4NZ53OMT.js} +7 -9
  21. package/dist/index.js +52 -79
  22. package/dist/{local-data-upload-client-EFHDLXFG.js → local-data-upload-client-KYOKVYZV.js} +2 -4
  23. package/dist/{memory-HBJQ2GC5.js → memory-ATNKZNW5.js} +4 -6
  24. package/dist/{metadata-PGDJE5RQ.js → metadata-3J5ZAVMF.js} +7 -9
  25. package/dist/{model-BHLJ2QMT.js → model-E4JMQ4V2.js} +4 -6
  26. package/dist/{personal-semantic-preference-E5NZ56DN.js → personal-semantic-preference-32AAJ37M.js} +6 -8
  27. package/dist/{sync-MUWPRM5I.js → sync-2GTAKZYX.js} +9 -11
  28. package/dist/{te-agent-WQZTMEK4.js → te-agent-JB5T3PO7.js} +393 -90
  29. package/dist/{te-analysis-YWCSSLYL.js → te-analysis-WHYXHRJD.js} +97 -31
  30. package/dist/{te-community-BNE6KREL.js → te-community-UDBI672N.js} +9 -32
  31. package/dist/{te-dataops-TXLKM2W6.js → te-dataops-ZLYOCXZ4.js} +19 -20
  32. package/dist/{te-engage-VEW4CJHK.js → te-engage-DHKNJ5BO.js} +11 -13
  33. package/dist/{te-kb-BUD6N3NI.js → te-kb-WYQWHFSC.js} +595 -85
  34. package/dist/{te-system-44LZJDTQ.js → te-system-7G6F2LJA.js} +6 -8
  35. package/dist/{te-team-XMP47YXE.js → te-team-E7FBBXMQ.js} +6 -8
  36. package/dist/{update-UODFOZ4P.js → update-D47BUG25.js} +7 -8
  37. package/package.json +12 -9
  38. package/skills/ae-agent/SKILL.md +30 -13
  39. package/skills/ae-agent/references/agent-distribution.md +94 -0
  40. package/skills/ae-agent/references/approval-request.md +4 -0
  41. package/skills/ae-agent/references/command_index.md +9 -2
  42. package/skills/ae-agent/references/create-automation.md +20 -2
  43. package/skills/ae-agent/references/get-agent-context.md +70 -0
  44. package/skills/ae-agent/references/list-automations.md +18 -3
  45. package/skills/ae-agent/references/list-mcp-credentials.md +1 -1
  46. package/skills/ae-agent/references/mcp-token.md +3 -3
  47. package/skills/ae-agent/references/set-mcp-credential.md +0 -1
  48. package/skills/ae-agent/references/update-automation.md +18 -0
  49. package/skills/ae-analysis/SKILL.md +11 -2
  50. package/skills/ae-analysis/references/adhoc_run.md +2 -0
  51. package/skills/ae-analysis/references/ai_models.md +23 -3
  52. package/skills/ae-analysis/references/analysis_gateway_assets.md +2 -2
  53. package/skills/ae-analysis/references/command_index.md +7 -7
  54. package/skills/ae-analysis/references/cross_source_config.md +84 -0
  55. package/skills/ae-analysis/references/dashboard_update.md +1 -1
  56. package/skills/ae-analysis/references/user_tag_create.md +23 -1
  57. package/skills/ae-analysis/references/user_tag_models.md +9 -1
  58. package/skills/ae-analysis/references/user_tag_update.md +14 -2
  59. package/skills/ae-data-integration/SKILL.md +2 -1
  60. package/skills/ae-data-integration/references/dimension-routing.md +36 -0
  61. package/skills/ae-data-integration/references/local-analysis.md +2 -0
  62. package/skills/ae-data-integration/references/source-inspect.md +1 -1
  63. package/skills/ae-data-integration/references/ue-routing.md +17 -1
  64. package/skills/ae-generate-tracking-plan/SKILL.md +16 -5
  65. package/skills/ae-kb/SKILL.md +107 -36
  66. package/skills/ae-kb/references/query-workflow.md +59 -29
  67. package/skills/ae-kb/references/versions.md +46 -0
  68. package/skills/ae-system/SKILL.md +1 -1
  69. package/skills/ae-use-agent/SKILL.md +42 -0
  70. package/skills/ae-use-agent/references/local-agent.md +114 -0
  71. package/dist/auth-UMJAA72O.js +0 -15
  72. package/dist/chunk-533JK3YX.js +0 -72
  73. package/dist/chunk-O6K2ODUE.js +0 -318
  74. package/dist/chunk-RWXIXOZG.js +0 -326
  75. package/dist/client-N7NGZUNI.js +0 -204
  76. package/skills/ae-agent/references/auto-provision-mcp-credentials.md +0 -57
@@ -2,29 +2,43 @@ import { createRequire as __createRequire } from 'node:module'; const require =
2
2
  import {
3
3
  kbApi,
4
4
  kbUpload
5
- } from "./chunk-JYMGHGCE.js";
5
+ } from "./chunk-VXNMYUXU.js";
6
6
  import {
7
- printError
8
- } from "./chunk-KEWVSO64.js";
7
+ TeAgentApiError
8
+ } from "./chunk-BBEFP4SB.js";
9
9
  import {
10
10
  CapabilityGatewayError
11
- } from "./chunk-GJXRF7Y6.js";
11
+ } from "./chunk-QJQZH5GQ.js";
12
+ import {
13
+ printError
14
+ } from "./chunk-CZU3V3DQ.js";
12
15
  import "./chunk-Y74WTIKJ.js";
13
- import "./chunk-RWXIXOZG.js";
14
- import "./chunk-O6K2ODUE.js";
15
- import "./chunk-KZ6ZHF5J.js";
16
+ import "./chunk-ATSM5XAW.js";
17
+ import "./chunk-WZ6YVQSF.js";
16
18
  import {
17
19
  CliValidationError,
18
20
  PermissionError
19
- } from "./chunk-533JK3YX.js";
20
- import "./chunk-FR2EDAQM.js";
21
+ } from "./chunk-4P355ZWB.js";
21
22
 
22
23
  // src/commands/te-kb/add.ts
23
24
  import { promises as fs } from "fs";
24
25
  import * as path from "path";
25
26
  import TurndownService from "turndown";
27
+
28
+ // src/commands/te-kb/target-scope.ts
29
+ function getExternalKnowledgeBaseTargetScope(ctx) {
30
+ const scope = ctx.str("scope").trim();
31
+ if (!scope) return void 0;
32
+ if (scope === "personal" || scope === "company") return scope;
33
+ throw new CliValidationError(
34
+ `Invalid --scope: ${scope}. Must be one of: personal | company`
35
+ );
36
+ }
37
+
38
+ // src/commands/te-kb/add.ts
26
39
  var API_PATH = "/agent/api/external/knowledge-bases/sources/upload";
27
40
  var SUPPORTED_EXTENSIONS = /* @__PURE__ */ new Set([
41
+ ".zip",
28
42
  ".md",
29
43
  ".markdown",
30
44
  ".txt",
@@ -71,6 +85,8 @@ function sanitizeFilename(name) {
71
85
  function getMimeType(filename) {
72
86
  const ext = path.extname(filename).toLowerCase();
73
87
  switch (ext) {
88
+ case ".zip":
89
+ return "application/zip";
74
90
  case ".md":
75
91
  case ".markdown":
76
92
  return "text/markdown";
@@ -205,9 +221,10 @@ function dedupeByFilename(files) {
205
221
  return { ...f, filename: `${stem}-${count}${ext}` };
206
222
  });
207
223
  }
208
- function buildForm(name, files) {
224
+ function buildForm(name, scope, files) {
209
225
  const form = new FormData();
210
226
  form.append("name", name);
227
+ if (scope) form.append("scope", scope);
211
228
  for (const f of files) {
212
229
  form.append("files", new Blob([f.content], { type: f.mimeType }), f.filename);
213
230
  }
@@ -219,6 +236,7 @@ var add = {
219
236
  description: "Upload sources to a knowledge. --files accepts a JSON array; each entry can be a supported file path, a directory path (supported files inside, non-recursive), or an http(s) URL (HTML auto-converted to markdown).",
220
237
  flags: [
221
238
  { name: "name", type: "string", required: true, desc: "Knowledge base name" },
239
+ { name: "scope", type: "string", required: false, desc: "Exact knowledge base scope: personal | company (omit for personal \u2192 company fallback)" },
222
240
  {
223
241
  name: "files",
224
242
  type: "json",
@@ -228,24 +246,29 @@ var add = {
228
246
  ],
229
247
  risk: "write",
230
248
  validate: (ctx) => {
249
+ getExternalKnowledgeBaseTargetScope(ctx);
231
250
  normalizeFilesInput(ctx.json("files"));
232
251
  },
233
252
  dryRun: (ctx) => {
234
253
  const items = normalizeFilesInput(ctx.json("files"));
254
+ const body = {
255
+ name: ctx.str("name")
256
+ };
257
+ const scope = getExternalKnowledgeBaseTargetScope(ctx);
258
+ if (scope) body.scope = scope;
259
+ body.files = items.map((item) => ({ value: item, type: classifyInput(item) }));
260
+ body.contentType = "multipart/form-data";
235
261
  return {
236
262
  method: "POST",
237
263
  url: `${ctx.host().replace(/\/$/, "")}${API_PATH}`,
238
- body: {
239
- name: ctx.str("name"),
240
- files: items.map((item) => ({ value: item, type: classifyInput(item) })),
241
- contentType: "multipart/form-data"
242
- }
264
+ body
243
265
  };
244
266
  },
245
267
  execute: async (ctx) => {
246
268
  const name = ctx.str("name");
269
+ const scope = getExternalKnowledgeBaseTargetScope(ctx);
247
270
  const files = await collectFiles(ctx);
248
- const form = buildForm(name, files);
271
+ const form = buildForm(name, scope, files);
249
272
  const result = await kbUpload(ctx, API_PATH, form);
250
273
  return {
251
274
  uploaded: files.map((f) => ({ filename: f.filename, origin: f.origin, source: f.source })),
@@ -265,10 +288,15 @@ function getMode(ctx) {
265
288
  return mode;
266
289
  }
267
290
  function buildBody(ctx) {
268
- return {
291
+ const body = {
269
292
  name: ctx.str("name"),
270
293
  mode: getMode(ctx)
271
294
  };
295
+ const scope = getExternalKnowledgeBaseTargetScope(ctx);
296
+ if (scope) body.scope = scope;
297
+ const model = ctx.str("model");
298
+ if (model) body.model = model;
299
+ return body;
272
300
  }
273
301
  var compile = {
274
302
  service: "kb",
@@ -276,11 +304,14 @@ var compile = {
276
304
  description: "Compile a knowledge.",
277
305
  flags: [
278
306
  { name: "name", type: "string", required: true, desc: "Knowledge base name" },
279
- { name: "mode", type: "string", required: false, default: "incremental", desc: "Compile mode: incremental | full (default: incremental)" }
307
+ { name: "mode", type: "string", required: false, default: "incremental", desc: "Compile mode: incremental | full (default: incremental)" },
308
+ { name: "scope", type: "string", required: false, desc: "Exact knowledge base scope: personal | company (omit for personal \u2192 company fallback)" },
309
+ { name: "model", type: "string", required: false, desc: "Optional model reference: Model.id, legacy modelId, or modelId::scope" }
280
310
  ],
281
311
  risk: "write",
282
312
  validate: (ctx) => {
283
313
  getMode(ctx);
314
+ getExternalKnowledgeBaseTargetScope(ctx);
284
315
  },
285
316
  dryRun: (ctx) => ({
286
317
  method: "POST",
@@ -293,16 +324,23 @@ var compile = {
293
324
  // src/commands/te-kb/remove.ts
294
325
  var API_PATH3 = "/agent/api/external/knowledge-bases";
295
326
  function buildBody2(ctx) {
296
- return { name: ctx.str("name") };
327
+ const body = { name: ctx.str("name") };
328
+ const scope = getExternalKnowledgeBaseTargetScope(ctx);
329
+ if (scope) body.scope = scope;
330
+ return body;
297
331
  }
298
332
  var remove = {
299
333
  service: "kb",
300
334
  command: "+remove",
301
335
  description: "Delete an entire knowledge.",
302
336
  flags: [
303
- { name: "name", type: "string", required: true, desc: "Knowledge base name to delete" }
337
+ { name: "name", type: "string", required: true, desc: "Knowledge base name to delete" },
338
+ { name: "scope", type: "string", required: false, desc: "Exact knowledge base scope: personal | company (omit for personal \u2192 company fallback)" }
304
339
  ],
305
340
  risk: "high-risk-write",
341
+ validate: (ctx) => {
342
+ getExternalKnowledgeBaseTargetScope(ctx);
343
+ },
306
344
  dryRun: (ctx) => ({
307
345
  method: "DELETE",
308
346
  url: `${ctx.host().replace(/\/$/, "")}${API_PATH3}`,
@@ -389,10 +427,12 @@ function sourceSelector(ctx) {
389
427
  throw new CliValidationError("One of --id or --display-name is required.");
390
428
  }
391
429
  function buildBody4(ctx) {
392
- return {
393
- name: ctx.str("name"),
394
- ...sourceSelector(ctx)
430
+ const body = {
431
+ name: ctx.str("name")
395
432
  };
433
+ const scope = getExternalKnowledgeBaseTargetScope(ctx);
434
+ if (scope) body.scope = scope;
435
+ return { ...body, ...sourceSelector(ctx) };
396
436
  }
397
437
  var rmSource = {
398
438
  service: "kb",
@@ -400,11 +440,13 @@ var rmSource = {
400
440
  description: "Delete one source from a knowledge base by ID or exact display name.",
401
441
  flags: [
402
442
  { name: "name", type: "string", required: true, desc: "Knowledge base name (looked up personal \u2192 company)" },
443
+ { name: "scope", type: "string", required: false, desc: "Exact knowledge base scope: personal | company (omit for personal \u2192 company fallback)" },
403
444
  { name: "id", type: "string", required: false, desc: "Source ID copied from +list-sources (preferred)" },
404
445
  { name: "display-name", type: "string", required: false, desc: "Exact source display name for legacy compatibility" }
405
446
  ],
406
447
  risk: "high-risk-write",
407
448
  validate: (ctx) => {
449
+ getExternalKnowledgeBaseTargetScope(ctx);
408
450
  sourceSelector(ctx);
409
451
  },
410
452
  dryRun: (ctx) => ({
@@ -413,8 +455,7 @@ var rmSource = {
413
455
  body: buildBody4(ctx)
414
456
  }),
415
457
  execute: async (ctx) => kbApi(ctx, "DELETE", API_PATH5, {}, buildBody4(ctx), {
416
- preserveErrorMetadata: true,
417
- retryUnauthorized: true
458
+ preserveErrorMetadata: true
418
459
  })
419
460
  };
420
461
 
@@ -424,6 +465,8 @@ function buildBody5(ctx) {
424
465
  const body = {
425
466
  name: ctx.str("name")
426
467
  };
468
+ const scope = getExternalKnowledgeBaseTargetScope(ctx);
469
+ if (scope) body.scope = scope;
427
470
  if (ctx.bool("force")) body.force = true;
428
471
  const model = ctx.str("model");
429
472
  if (model) body.model = model;
@@ -442,8 +485,9 @@ var schema = {
442
485
  description: "Generate the compile schema for a knowledge base via POST /agent/api/external/knowledge-bases/schema.",
443
486
  flags: [
444
487
  { name: "name", type: "string", required: true, desc: "Knowledge base name (looked up personal \u2192 company)" },
488
+ { name: "scope", type: "string", required: false, desc: "Exact knowledge base scope: personal | company (omit for personal \u2192 company fallback)" },
445
489
  { name: "force", type: "boolean", required: false, desc: "Preempt generation even when status is `generating` (use only for stuck recovery)" },
446
- { name: "model", type: "string", required: false, desc: "Optional model displayName to use for schema generation" },
490
+ { name: "model", type: "string", required: false, desc: "Optional model reference: Model.id, legacy modelId, or modelId::scope" },
447
491
  {
448
492
  name: "custom-instructions",
449
493
  type: "string",
@@ -453,6 +497,9 @@ var schema = {
453
497
  }
454
498
  ],
455
499
  risk: "write",
500
+ validate: (ctx) => {
501
+ getExternalKnowledgeBaseTargetScope(ctx);
502
+ },
456
503
  dryRun: (ctx) => ({
457
504
  method: "POST",
458
505
  url: `${ctx.host().replace(/\/$/, "")}${API_PATH6}`,
@@ -464,18 +511,25 @@ var schema = {
464
511
  // src/commands/te-kb/status.ts
465
512
  var API_PATH7 = "/agent/api/external/knowledge-bases/status";
466
513
  function buildBody6(ctx) {
467
- return {
514
+ const body = {
468
515
  name: ctx.str("name")
469
516
  };
517
+ const scope = getExternalKnowledgeBaseTargetScope(ctx);
518
+ if (scope) body.scope = scope;
519
+ return body;
470
520
  }
471
521
  var status = {
472
522
  service: "kb",
473
523
  command: "+status",
474
524
  description: "Query knowledge base status.",
475
525
  flags: [
476
- { name: "name", type: "string", required: true, desc: "Knowledge base name" }
526
+ { name: "name", type: "string", required: true, desc: "Knowledge base name" },
527
+ { name: "scope", type: "string", required: false, desc: "Exact knowledge base scope: personal | company (omit for personal \u2192 company fallback)" }
477
528
  ],
478
529
  risk: "read",
530
+ validate: (ctx) => {
531
+ getExternalKnowledgeBaseTargetScope(ctx);
532
+ },
479
533
  dryRun: (ctx) => ({
480
534
  method: "POST",
481
535
  url: `${ctx.host().replace(/\/$/, "")}${API_PATH7}`,
@@ -576,12 +630,14 @@ function knowledgeBaseName(ctx) {
576
630
  function buildUrl(ctx) {
577
631
  const url2 = new URL(`${ctx.host().replace(/\/$/, "")}${API_PATH10}`);
578
632
  url2.searchParams.set("name", knowledgeBaseName(ctx));
633
+ const scope = getExternalKnowledgeBaseTargetScope(ctx);
634
+ if (scope) url2.searchParams.set("scope", scope);
579
635
  return url2.toString();
580
636
  }
581
637
  var listSources = {
582
638
  service: "kb",
583
639
  command: "+list-sources",
584
- description: "List source metadata for a knowledge base via GET /agent/api/external/knowledge-bases/sources?name=<name>. Copy the stable source ID from this output before using +rm-source.",
640
+ description: "List source metadata for a knowledge base via GET /agent/api/external/knowledge-bases/sources?name=<name>. Copy the stable source ID from this output before using +rm-source. Preserves deletionProjection, pendingDeletions (null means undetermined), and separate cleanup state.",
585
641
  flags: [
586
642
  {
587
643
  name: "name",
@@ -590,6 +646,12 @@ var listSources = {
590
646
  minLength: 1,
591
647
  maxLength: MAX_KNOWLEDGE_BASE_NAME_LENGTH,
592
648
  desc: "Knowledge base name"
649
+ },
650
+ {
651
+ name: "scope",
652
+ type: "string",
653
+ required: false,
654
+ desc: "Exact knowledge base scope: personal | company (omit for personal \u2192 company fallback)"
593
655
  }
594
656
  ],
595
657
  risk: "read",
@@ -603,19 +665,21 @@ var listSources = {
603
665
  `Invalid --name length: ${name.length}. Must be at most ${MAX_KNOWLEDGE_BASE_NAME_LENGTH} characters.`
604
666
  );
605
667
  }
668
+ getExternalKnowledgeBaseTargetScope(ctx);
606
669
  },
607
670
  dryRun: (ctx) => ({
608
671
  method: "GET",
609
672
  url: buildUrl(ctx)
610
673
  }),
611
- execute: async (ctx) => kbApi(
612
- ctx,
613
- "GET",
614
- API_PATH10,
615
- { name: knowledgeBaseName(ctx) },
616
- void 0,
617
- { preserveErrorMetadata: true, retryUnauthorized: true }
618
- )
674
+ execute: async (ctx) => {
675
+ const params = { name: knowledgeBaseName(ctx) };
676
+ const scope = getExternalKnowledgeBaseTargetScope(ctx);
677
+ if (scope) params.scope = scope;
678
+ return kbApi(ctx, "GET", API_PATH10, params, void 0, {
679
+ preserveErrorMetadata: true,
680
+ retryUnauthorized: true
681
+ });
682
+ }
619
683
  };
620
684
 
621
685
  // src/commands/te-kb/kb-grep.ts
@@ -626,8 +690,8 @@ function buildBody9(ctx) {
626
690
  sources: ctx.json("sources"),
627
691
  paths: ctx.json("paths")
628
692
  };
629
- const topK = ctx.num("top-k");
630
- if (topK) body.topK = topK;
693
+ const topK = ctx.optionalNum("top-k");
694
+ if (topK !== void 0) body.topK = topK;
631
695
  const locale = ctx.str("locale");
632
696
  if (locale) body.locale = locale;
633
697
  return body;
@@ -635,7 +699,7 @@ function buildBody9(ctx) {
635
699
  var kbGrep = {
636
700
  service: "kb",
637
701
  command: "+grep",
638
- description: "Keyword-search knowledge base pages via POST /agent/api/external/knowledge-bases/grep. Returns matched lines with path, line number, breadcrumb, context snippet, and the section line range (sectionStartLine/sectionEndLine) of each hit. Copy --paths from +index (wiki pages or subdirectories). Use +read with the hit range to open the section.",
702
+ description: "Keyword-search knowledge base pages via POST /agent/api/external/knowledge-bases/grep. Returns a page-level results array: one entry per page with hitCount (full match count), pageKind (content/catalog), up to 4 sections previews (breadcrumb, sectionStartLine/sectionEndLine, text excerpt) and moreSections. Copy --paths from +index (wiki pages, module catalog pages, or subdirectories); read the matched section range with +read.",
639
703
  flags: [
640
704
  {
641
705
  name: "query",
@@ -656,7 +720,7 @@ var kbGrep = {
656
720
  required: true,
657
721
  desc: 'JSON array of wiki pages or subdirectories copied from +index, e.g. ["wiki/sandbox.md"] or ["wiki/guides"]'
658
722
  },
659
- { name: "top-k", type: "number", required: false, desc: "Max number of hits to return (1-50, default 10)" },
723
+ { name: "top-k", type: "number", required: false, min: 1, max: 50, desc: "Max number of pages to return (1-50, default 10)" },
660
724
  { name: "locale", type: "string", required: false, desc: "Optional locale: zh | en | ja | ko" }
661
725
  ],
662
726
  risk: "read",
@@ -670,15 +734,39 @@ var kbGrep = {
670
734
 
671
735
  // src/commands/te-kb/kb-read.ts
672
736
  var API_PATH12 = "/agent/api/external/knowledge-bases/read";
737
+ var VALID_EXPAND_MODES = /* @__PURE__ */ new Set(["block", "none"]);
738
+ var MAX_READ_LIMIT = 2e3;
739
+ function readExpand(ctx) {
740
+ const expand = ctx.str("expand").trim();
741
+ if (!expand) return void 0;
742
+ if (!VALID_EXPAND_MODES.has(expand)) {
743
+ throw new CliValidationError(
744
+ `Invalid --expand: ${expand}. Must be one of: block | none`
745
+ );
746
+ }
747
+ return expand;
748
+ }
749
+ function readLimit(ctx) {
750
+ const limit = ctx.optionalNum("limit");
751
+ if (limit === void 0) return void 0;
752
+ if (!Number.isInteger(limit) || limit < 1 || limit > MAX_READ_LIMIT) {
753
+ throw new CliValidationError(
754
+ `Invalid --limit: ${limit}. Must be an integer from 1 to ${MAX_READ_LIMIT}`
755
+ );
756
+ }
757
+ return limit;
758
+ }
673
759
  function buildBody10(ctx) {
674
760
  const body = {
675
761
  source: ctx.json("source"),
676
762
  path: ctx.str("path")
677
763
  };
678
- const offset = ctx.num("offset");
679
- if (offset) body.offset = offset;
680
- const limit = ctx.num("limit");
681
- if (limit) body.limit = limit;
764
+ const offset = ctx.optionalNum("offset");
765
+ if (offset !== void 0) body.offset = offset;
766
+ const limit = ctx.optionalNum("limit");
767
+ if (limit !== void 0) body.limit = limit;
768
+ const expand = readExpand(ctx);
769
+ if (expand) body.expand = expand;
682
770
  if (ctx.bool("outline")) body.outline = true;
683
771
  const locale = ctx.str("locale");
684
772
  if (locale) body.locale = locale;
@@ -701,8 +789,9 @@ var kbRead = {
701
789
  required: true,
702
790
  desc: "Page path relative to the knowledge base root, e.g. wiki/concepts/data-model.md or index.md"
703
791
  },
704
- { name: "offset", type: "number", required: false, desc: "Start line (1-based). Omit to read from the beginning." },
705
- { name: "limit", type: "number", required: false, desc: "Max number of lines to return (1-10000)." },
792
+ { name: "offset", type: "number", required: false, min: 1, desc: "Start line (1-based integer). Omit to read from the beginning." },
793
+ { name: "limit", type: "number", required: false, min: 1, max: MAX_READ_LIMIT, desc: "Max number of lines to return (1-2000)." },
794
+ { name: "expand", type: "string", required: false, desc: "Read-window expansion mode: block | none (omit for the server default: block)" },
706
795
  {
707
796
  name: "outline",
708
797
  type: "boolean",
@@ -712,6 +801,14 @@ var kbRead = {
712
801
  { name: "locale", type: "string", required: false, desc: "Optional locale: zh | en | ja | ko" }
713
802
  ],
714
803
  risk: "read",
804
+ validate: (ctx) => {
805
+ const offset = ctx.optionalNum("offset");
806
+ if (offset !== void 0 && !Number.isInteger(offset)) {
807
+ throw new CliValidationError("--offset must be an integer.");
808
+ }
809
+ readLimit(ctx);
810
+ readExpand(ctx);
811
+ },
715
812
  dryRun: (ctx) => ({
716
813
  method: "POST",
717
814
  url: `${ctx.host().replace(/\/$/, "")}${API_PATH12}`,
@@ -777,21 +874,13 @@ function transformCompletedResponse(response) {
777
874
  if (response.modelId !== void 0) result.modelId = response.modelId;
778
875
  if (response.modelUsage !== void 0) result.modelUsage = response.modelUsage;
779
876
  if (response.toolCallCount !== void 0) result.toolCallCount = response.toolCallCount;
780
- if (response.maxTurns !== void 0) result.maxTurns = response.maxTurns;
781
877
  return result;
782
878
  }
783
- function buildFailedMessage(response) {
784
- const type = response.error?.type || "unknown";
785
- const message = response.error?.message || "Ask execution failed";
786
- return `[${type}] ${message} (executionId: ${response.executionId})`;
787
- }
788
879
 
789
880
  // src/commands/te-kb/ask.ts
790
881
  var VALID_LOCALES = /* @__PURE__ */ new Set(["zh", "en", "ja", "ko"]);
791
882
  var MIN_QUESTION_LEN = 1;
792
883
  var MAX_QUESTION_LEN = 2e3;
793
- var MIN_MAX_TURNS = 1;
794
- var MAX_MAX_TURNS = 100;
795
884
  function validateQuestion(question) {
796
885
  const len = question.length;
797
886
  if (len < MIN_QUESTION_LEN || len > MAX_QUESTION_LEN) {
@@ -805,13 +894,6 @@ function validateLocale(locale) {
805
894
  throw new Error(`Invalid --locale: ${locale}. Must be one of: zh | en | ja | ko`);
806
895
  }
807
896
  }
808
- function validateMaxTurns(maxTurns) {
809
- if (maxTurns !== 0 && (maxTurns < MIN_MAX_TURNS || maxTurns > MAX_MAX_TURNS)) {
810
- throw new Error(
811
- `Invalid --max-turns: ${maxTurns}. Must be between ${MIN_MAX_TURNS} and ${MAX_MAX_TURNS}.`
812
- );
813
- }
814
- }
815
897
  function buildBody11(ctx) {
816
898
  const body = {
817
899
  question: ctx.str("question")
@@ -820,8 +902,6 @@ function buildBody11(ctx) {
820
902
  if (sources) body.sources = sources;
821
903
  const modelId = ctx.str("model-id");
822
904
  if (modelId) body.modelId = modelId;
823
- const maxTurns = ctx.num("max-turns");
824
- if (maxTurns) body.maxTurns = maxTurns;
825
905
  const locale = ctx.str("locale");
826
906
  if (locale) body.locale = locale;
827
907
  return body;
@@ -850,12 +930,6 @@ var ask = {
850
930
  required: false,
851
931
  desc: "Optional LLM model ID (e.g. claude-sonnet-4-6). Omit to use the platform default model."
852
932
  },
853
- {
854
- name: "max-turns",
855
- type: "number",
856
- required: false,
857
- desc: "Optional agent turn limit (1-100, default 50 on server when omitted)."
858
- },
859
933
  { name: "locale", type: "string", required: false, desc: "Optional locale: zh | en | ja | ko" },
860
934
  {
861
935
  name: "no-wait",
@@ -868,7 +942,6 @@ var ask = {
868
942
  validate: (ctx) => {
869
943
  validateQuestion(ctx.str("question"));
870
944
  validateLocale(ctx.str("locale"));
871
- validateMaxTurns(ctx.num("max-turns"));
872
945
  },
873
946
  dryRun: (ctx) => ({
874
947
  method: "POST",
@@ -896,7 +969,14 @@ var ask = {
896
969
  return transformCompletedResponse(finalResponse);
897
970
  }
898
971
  if (finalResponse.status === "failed") {
899
- throw new Error(buildFailedMessage(finalResponse));
972
+ const code = finalResponse.error?.code || "provider_failed";
973
+ const message = finalResponse.error?.message || "Ask execution failed";
974
+ throw new TeAgentApiError(
975
+ `${message} (executionId: ${finalResponse.executionId})`,
976
+ 200,
977
+ code,
978
+ finalResponse
979
+ );
900
980
  }
901
981
  throw new Error(`Unexpected execution status: ${finalResponse.status}`);
902
982
  }
@@ -955,6 +1035,8 @@ function buildBody12(ctx) {
955
1035
  name: ctx.str("name"),
956
1036
  url: ctx.str("url")
957
1037
  };
1038
+ const scope = getExternalKnowledgeBaseTargetScope(ctx);
1039
+ if (scope) body.scope = scope;
958
1040
  const displayName = ctx.str("display-name");
959
1041
  if (displayName) body.displayName = displayName;
960
1042
  const parseInstruction = ctx.str("parse-instruction");
@@ -967,12 +1049,14 @@ var url = {
967
1049
  description: "Upload a URL source to a knowledge base.",
968
1050
  flags: [
969
1051
  { name: "name", type: "string", required: true, desc: "Knowledge base name" },
1052
+ { name: "scope", type: "string", required: false, desc: "Exact knowledge base scope: personal | company (omit for personal \u2192 company fallback)" },
970
1053
  { name: "url", type: "string", required: true, desc: "Source URL to upload" },
971
1054
  { name: "display-name", type: "string", required: false, desc: "Optional display name for the URL source" },
972
1055
  { name: "parse-instruction", type: "string", required: false, desc: "Optional parsing instruction for the URL source; ignored for Lark/Feishu doc URLs (the server applies its own Feishu parsing)" }
973
1056
  ],
974
1057
  risk: "write",
975
1058
  validate: (ctx) => {
1059
+ getExternalKnowledgeBaseTargetScope(ctx);
976
1060
  validateUrl(ctx.str("url"));
977
1061
  },
978
1062
  dryRun: (ctx) => ({
@@ -988,6 +1072,16 @@ import { promises as fs2 } from "fs";
988
1072
  import path2 from "path";
989
1073
  var API_PATH14 = "/agent/api/external/knowledge-bases/import";
990
1074
  var MAX_SNAPSHOT_ARCHIVE_BYTES = 50 * 1024 * 1024;
1075
+ var VALID_SCOPES2 = /* @__PURE__ */ new Set(["personal", "company"]);
1076
+ function getScope2(ctx) {
1077
+ const scope = ctx.str("scope") || "personal";
1078
+ if (!VALID_SCOPES2.has(scope)) {
1079
+ throw new CliValidationError("Invalid --scope. Must be one of: personal | company", {
1080
+ location: { field: "scope" }
1081
+ });
1082
+ }
1083
+ return scope;
1084
+ }
991
1085
  function normalizeTags2(raw) {
992
1086
  if (raw === void 0 || raw === null) return [];
993
1087
  if (!Array.isArray(raw)) {
@@ -1043,8 +1137,15 @@ function appendOptionalFields(ctx, form) {
1043
1137
  var importSnapshot = {
1044
1138
  service: "kb",
1045
1139
  command: "+import",
1046
- description: "Import a compiled Markdown ZIP snapshot as a personal read-only knowledge base.",
1140
+ description: "Import a compiled Markdown ZIP snapshot as a personal or company read-only knowledge base.",
1047
1141
  flags: [
1142
+ {
1143
+ name: "scope",
1144
+ type: "string",
1145
+ required: false,
1146
+ default: "personal",
1147
+ desc: "Target scope: personal | company (default: personal)"
1148
+ },
1048
1149
  {
1049
1150
  name: "file",
1050
1151
  type: "string",
@@ -1056,7 +1157,7 @@ var importSnapshot = {
1056
1157
  type: "string",
1057
1158
  required: true,
1058
1159
  maxLength: 30,
1059
- desc: "Personal knowledge base name (max 30 characters)"
1160
+ desc: "Knowledge base name (max 30 characters)"
1060
1161
  },
1061
1162
  {
1062
1163
  name: "description",
@@ -1081,6 +1182,7 @@ var importSnapshot = {
1081
1182
  ],
1082
1183
  risk: "write",
1083
1184
  validate: (ctx) => {
1185
+ getScope2(ctx);
1084
1186
  validateArchivePath(ctx.str("file"));
1085
1187
  normalizeTags2(ctx.json("tags"));
1086
1188
  },
@@ -1093,13 +1195,14 @@ var importSnapshot = {
1093
1195
  path2.basename(archive.absolutePath)
1094
1196
  );
1095
1197
  form.append("name", ctx.str("name").trim());
1198
+ form.append("scope", getScope2(ctx));
1096
1199
  appendOptionalFields(ctx, form);
1097
1200
  try {
1098
1201
  return await kbUpload(
1099
1202
  ctx,
1100
1203
  API_PATH14,
1101
1204
  form,
1102
- {},
1205
+ { scope: getScope2(ctx) },
1103
1206
  { preserveErrorMetadata: true, retryUnauthorized: true }
1104
1207
  );
1105
1208
  } catch (error) {
@@ -1114,6 +1217,9 @@ var importSnapshot = {
1114
1217
  );
1115
1218
  }
1116
1219
  if (error instanceof Error) {
1220
+ if (error.constructor === Error) {
1221
+ throw new CapabilityGatewayError(`${error.message} ${hint}`, void 0, void 0, hint);
1222
+ }
1117
1223
  error.message = `${error.message} ${hint}`;
1118
1224
  throw error;
1119
1225
  }
@@ -1157,6 +1263,7 @@ var importStatus = {
1157
1263
  url: `${ctx.host().replace(/\/$/, "")}${API_PATH15}?requestId=${encodeURIComponent(requestIdFrom(ctx))}`
1158
1264
  }),
1159
1265
  execute: async (ctx) => {
1266
+ const hint = "Verify the request ID and that the server supports kb +import-status. Do not retry the import until its status is known.";
1160
1267
  try {
1161
1268
  return await kbApi(
1162
1269
  ctx,
@@ -1164,23 +1271,413 @@ var importStatus = {
1164
1271
  API_PATH15,
1165
1272
  { requestId: requestIdFrom(ctx) },
1166
1273
  void 0,
1167
- { preserveErrorMetadata: true, retryUnauthorized: true }
1274
+ { preserveErrorMetadata: true }
1168
1275
  );
1169
1276
  } catch (error) {
1170
- if (!(error instanceof CapabilityGatewayError) || error.hint) throw error;
1171
- throw new CapabilityGatewayError(
1172
- error.message,
1173
- error.code,
1174
- error.httpStatus,
1175
- "Verify the request ID and that the server supports kb +import-status. Do not retry the import until its status is known.",
1176
- error.meta
1177
- );
1277
+ if (error instanceof PermissionError) {
1278
+ throw new PermissionError(error.message, error.code, error.hint ?? hint);
1279
+ }
1280
+ if (error instanceof CapabilityGatewayError) {
1281
+ if (error.hint) throw error;
1282
+ throw new CapabilityGatewayError(
1283
+ error.message,
1284
+ error.code,
1285
+ error.httpStatus,
1286
+ hint,
1287
+ error.meta
1288
+ );
1289
+ }
1290
+ if (error instanceof Error) {
1291
+ if (error.constructor === Error) {
1292
+ throw new CapabilityGatewayError(error.message, void 0, void 0, hint);
1293
+ }
1294
+ throw error;
1295
+ }
1296
+ throw error;
1297
+ }
1298
+ }
1299
+ };
1300
+
1301
+ // src/commands/te-kb/source-directory.ts
1302
+ import { promises as fs3 } from "fs";
1303
+ import path3 from "path";
1304
+ var sourceFlags = [
1305
+ { name: "name", type: "string", required: true, desc: "Knowledge base name (personal then company)" },
1306
+ { name: "id", type: "string", required: true, desc: "ZIP source ID copied from +list-sources" }
1307
+ ];
1308
+ var pathFlag = { name: "path", type: "string", required: true, desc: "Exact path relative to the ZIP source root" };
1309
+ var revisionFlag = {
1310
+ name: "expected-revision",
1311
+ type: "number",
1312
+ required: true,
1313
+ min: 1,
1314
+ desc: "Revision returned by +source-ls; a conflict requires a fresh read and explicit retry"
1315
+ };
1316
+ var apiOptions = { preserveErrorMetadata: true, retryUnauthorized: true };
1317
+ var maxFileBytes = 50 * 1024 * 1024;
1318
+ function validateIdentity(ctx) {
1319
+ for (const [flag, max] of [["name", 200], ["id", 191]]) {
1320
+ const value = ctx.str(flag).trim();
1321
+ if (!value || value.length > max) throw new CliValidationError(`Invalid --${flag}.`);
1322
+ }
1323
+ }
1324
+ function relativePath(ctx, allowRoot = false) {
1325
+ const value = ctx.str("path");
1326
+ if (allowRoot && value === "") return value;
1327
+ if (!value || value.length > 1024 || /[\\\x00-\x1f\x7f]/.test(value) || /^[A-Za-z]:/.test(value) || value.split("/").some((part) => !part || part === "." || part === "..")) {
1328
+ throw new CliValidationError("--path must be a normalized relative path inside the ZIP source.");
1329
+ }
1330
+ return value;
1331
+ }
1332
+ function validateMutation(ctx) {
1333
+ validateIdentity(ctx);
1334
+ relativePath(ctx);
1335
+ if (!Number.isSafeInteger(ctx.num("expected-revision")) || ctx.num("expected-revision") < 1) {
1336
+ throw new CliValidationError("--expected-revision must be a positive safe integer.");
1337
+ }
1338
+ }
1339
+ function endpoint(ctx, suffix = "directory") {
1340
+ return `/agent/api/external/knowledge-bases/sources/${encodeURIComponent(ctx.str("id").trim())}/${suffix}`;
1341
+ }
1342
+ function query(ctx) {
1343
+ return { name: ctx.str("name").trim(), path: ctx.str("path") };
1344
+ }
1345
+ function preview(ctx, method, suffix = "directory", body) {
1346
+ return { method, url: `${ctx.host().replace(/\/$/, "")}${endpoint(ctx, suffix)}`, ...body ? { body } : { params: query(ctx) } };
1347
+ }
1348
+ function mutationBody(ctx, operation) {
1349
+ return { name: ctx.str("name").trim(), expectedRevision: ctx.num("expected-revision"), operations: [operation] };
1350
+ }
1351
+ var sourceLs = {
1352
+ service: "kb",
1353
+ command: "+source-ls",
1354
+ risk: "read",
1355
+ description: "List one ZIP source directory, its revision, and changes since successful compilation.",
1356
+ flags: [
1357
+ ...sourceFlags,
1358
+ { ...pathFlag, required: false, default: "" },
1359
+ { name: "cursor", type: "string", desc: "Opaque nextCursor returned by the previous page" },
1360
+ { name: "limit", type: "number", default: 100, min: 1, max: 200, desc: "Page size (1-200)" }
1361
+ ],
1362
+ validate: (ctx) => {
1363
+ validateIdentity(ctx);
1364
+ relativePath(ctx, true);
1365
+ if (!Number.isInteger(ctx.num("limit")) || ctx.num("limit") < 1 || ctx.num("limit") > 200) {
1366
+ throw new CliValidationError("--limit must be an integer from 1 to 200.");
1178
1367
  }
1368
+ },
1369
+ dryRun: (ctx) => ({ ...preview(ctx, "GET"), params: { ...query(ctx), limit: ctx.num("limit"), ...ctx.str("cursor") ? { cursor: ctx.str("cursor") } : {} } }),
1370
+ execute: (ctx) => kbApi(ctx, "GET", endpoint(ctx), {
1371
+ ...query(ctx),
1372
+ limit: ctx.num("limit"),
1373
+ ...ctx.str("cursor") ? { cursor: ctx.str("cursor") } : {}
1374
+ }, void 0, apiOptions)
1375
+ };
1376
+ var sourceRead = {
1377
+ service: "kb",
1378
+ command: "+source-read",
1379
+ risk: "read",
1380
+ description: "Read a ZIP source file as UTF-8/base64 or save its original bytes to a new local file.",
1381
+ flags: [
1382
+ ...sourceFlags,
1383
+ pathFlag,
1384
+ { name: "encoding", type: "string", default: "utf8", desc: "JSON content encoding: utf8 or base64 (ignored with --output)" },
1385
+ { name: "output", type: "string", desc: "Save original bytes to this local path; existing files are never overwritten" }
1386
+ ],
1387
+ validate: (ctx) => {
1388
+ validateIdentity(ctx);
1389
+ relativePath(ctx);
1390
+ if (!["utf8", "base64"].includes(ctx.str("encoding"))) throw new CliValidationError("--encoding must be utf8 or base64.");
1391
+ },
1392
+ dryRun: (ctx) => preview(ctx, "GET", "raw"),
1393
+ execute: async (ctx) => {
1394
+ const result = await kbApi(ctx, "GET", endpoint(ctx, "raw"), query(ctx), void 0, { ...apiOptions, responseType: "bytes" });
1395
+ const bytes = Buffer.from(result.bytes);
1396
+ const metadata = { path: ctx.str("path"), sizeBytes: bytes.length, contentType: result.contentType };
1397
+ if (ctx.str("output")) {
1398
+ const output = path3.resolve(ctx.str("output"));
1399
+ await fs3.writeFile(output, bytes, { flag: "wx" });
1400
+ return { ...metadata, output };
1401
+ }
1402
+ if (ctx.str("encoding") === "base64") return { ...metadata, encoding: "base64", content: bytes.toString("base64") };
1403
+ try {
1404
+ return { ...metadata, encoding: "utf8", content: new TextDecoder("utf-8", { fatal: true }).decode(bytes) };
1405
+ } catch {
1406
+ throw new CliValidationError("This file is not UTF-8. Use --encoding base64 or --output.");
1407
+ }
1408
+ }
1409
+ };
1410
+ async function fileOperation(ctx, dryRun) {
1411
+ const file = path3.resolve(ctx.str("file"));
1412
+ const handle = await fs3.open(file, "r");
1413
+ try {
1414
+ const stat = await handle.stat();
1415
+ if (!stat.isFile() || stat.size > maxFileBytes) throw new CliValidationError("--file must be a regular file of at most 50 MB.");
1416
+ const action = ctx.str("action");
1417
+ const content = dryRun ? void 0 : await handle.readFile();
1418
+ if (content && content.length > maxFileBytes) throw new CliValidationError("--file exceeds 50 MB.");
1419
+ return {
1420
+ action,
1421
+ path: ctx.str("path"),
1422
+ ...action === "replace" ? { confirmed: true } : {},
1423
+ ...dryRun ? { file, sizeBytes: stat.size, contentBase64: "<redacted>" } : { contentBase64: content.toString("base64") }
1424
+ };
1425
+ } finally {
1426
+ await handle.close();
1427
+ }
1428
+ }
1429
+ var sourcePut = {
1430
+ service: "kb",
1431
+ command: "+source-put",
1432
+ risk: "write",
1433
+ description: "Add or explicitly replace one file at an exact ZIP-relative path using a checked revision.",
1434
+ flags: [
1435
+ ...sourceFlags,
1436
+ pathFlag,
1437
+ revisionFlag,
1438
+ { name: "file", type: "string", required: true, desc: "Local file to upload (at most 50 MB)" },
1439
+ { name: "action", type: "string", default: "add", desc: "add rejects an existing path; replace explicitly overwrites an existing file" }
1440
+ ],
1441
+ validate: (ctx) => {
1442
+ validateMutation(ctx);
1443
+ if (!ctx.str("file").trim()) throw new CliValidationError("--file must be non-empty.");
1444
+ if (!["add", "replace"].includes(ctx.str("action"))) throw new CliValidationError("--action must be add or replace.");
1445
+ },
1446
+ dryRun: async (ctx) => preview(ctx, "POST", "directory", mutationBody(ctx, await fileOperation(ctx, true))),
1447
+ execute: async (ctx) => kbApi(ctx, "POST", endpoint(ctx), {}, mutationBody(ctx, await fileOperation(ctx, false)), apiOptions)
1448
+ };
1449
+ function deleteOperation(ctx) {
1450
+ return { action: "delete", path: ctx.str("path"), confirmed: true, ...ctx.bool("recursive") ? { recursive: true } : {} };
1451
+ }
1452
+ var sourceRm = {
1453
+ service: "kb",
1454
+ command: "+source-rm",
1455
+ risk: "high-risk-write",
1456
+ description: "Delete one ZIP child file or recursively delete one directory; keeps the parent source.",
1457
+ flags: [
1458
+ ...sourceFlags,
1459
+ pathFlag,
1460
+ revisionFlag,
1461
+ { name: "recursive", type: "boolean", desc: "Explicitly allow recursive directory deletion" }
1462
+ ],
1463
+ validate: validateMutation,
1464
+ dryRun: (ctx) => preview(ctx, "POST", "directory", mutationBody(ctx, deleteOperation(ctx))),
1465
+ execute: (ctx) => kbApi(ctx, "POST", endpoint(ctx), {}, mutationBody(ctx, deleteOperation(ctx)), apiOptions)
1466
+ };
1467
+
1468
+ // src/commands/te-kb/version-management.ts
1469
+ import { promises as fs4 } from "fs";
1470
+ import path4 from "path";
1471
+ var API = "/agent/api/external/knowledge-bases/versions";
1472
+ var apiOptions2 = { preserveErrorMetadata: true, retryUnauthorized: true };
1473
+ var targetFlags = [
1474
+ { name: "name", type: "string", required: true, minLength: 1, maxLength: 200, desc: "Exact knowledge base name copied from +list" },
1475
+ { name: "scope", type: "string", desc: "Exact personal or company scope; omit for personal then company lookup" }
1476
+ ];
1477
+ var versionFlag = { name: "version", type: "number", required: true, min: 1, max: 2147483647, desc: "Historical version number from +versions, without the v prefix" };
1478
+ var sourceFlag = { name: "id", type: "string", required: true, minLength: 1, maxLength: 191, desc: "Stable historical source ID copied from +version-sources" };
1479
+ var pagingFlags = [
1480
+ { name: "cursor", type: "string", desc: "nextCursor from the previous page; omit for the first page" },
1481
+ { name: "limit", type: "number", default: 100, min: 1, max: 200, desc: "Page size from 1 to 200" }
1482
+ ];
1483
+ var pathFlag2 = { name: "path", type: "string", desc: "Exact path relative to the historical source directory" };
1484
+ function positiveInteger(ctx, flag) {
1485
+ const value = ctx.num(flag);
1486
+ if (!Number.isSafeInteger(value) || value < 1 || value > 2147483647) throw new CliValidationError(`--${flag} must be a positive integer no greater than 2147483647.`);
1487
+ return value;
1488
+ }
1489
+ function validateTarget(ctx) {
1490
+ const name = ctx.str("name").trim();
1491
+ if (!name || name.length > 200) throw new CliValidationError("--name must contain 1 to 200 characters.");
1492
+ getExternalKnowledgeBaseTargetScope(ctx);
1493
+ }
1494
+ function validateVersion(ctx) {
1495
+ validateTarget(ctx);
1496
+ positiveInteger(ctx, "version");
1497
+ }
1498
+ function validateSource(ctx) {
1499
+ validateVersion(ctx);
1500
+ const id = ctx.str("id").trim();
1501
+ if (!id || id.length > 191) throw new CliValidationError("--id must contain 1 to 191 characters.");
1502
+ }
1503
+ function validatePage(ctx) {
1504
+ const limit = ctx.num("limit");
1505
+ if (!Number.isInteger(limit) || limit < 1 || limit > 200) throw new CliValidationError("--limit must be an integer from 1 to 200.");
1506
+ if (ctx.str("cursor").length > 500) throw new CliValidationError("--cursor must be at most 500 characters.");
1507
+ }
1508
+ function validatePath(ctx, required = false) {
1509
+ const value = ctx.str("path");
1510
+ if (!value && !required) return;
1511
+ if (!value || value.length > 500 || /[\\\x00-\x1f\x7f]/.test(value) || /^[A-Za-z]:/.test(value) || value.split("/").some((part) => !part || part === "." || part === "..")) {
1512
+ throw new CliValidationError("--path must be a normalized relative path inside the historical source.");
1513
+ }
1514
+ }
1515
+ function query2(ctx) {
1516
+ const scope = getExternalKnowledgeBaseTargetScope(ctx);
1517
+ return { name: ctx.str("name").trim(), ...scope ? { scope } : {} };
1518
+ }
1519
+ function pageQuery(ctx) {
1520
+ return { ...query2(ctx), limit: ctx.num("limit"), ...ctx.str("cursor") ? { cursor: ctx.str("cursor") } : {} };
1521
+ }
1522
+ function versionEndpoint(ctx, suffix = "") {
1523
+ return `${API}/${positiveInteger(ctx, "version")}${suffix}`;
1524
+ }
1525
+ function sourceEndpoint(ctx, action) {
1526
+ return versionEndpoint(ctx, `/sources/${encodeURIComponent(ctx.str("id").trim())}/${action}`);
1527
+ }
1528
+ function preview2(ctx, endpoint2, params, body) {
1529
+ return { method: body ? "POST" : "GET", url: `${ctx.host().replace(/\/$/, "")}${endpoint2}`, params, ...body ? { body } : {} };
1530
+ }
1531
+ var versions = {
1532
+ service: "kb",
1533
+ command: "+versions",
1534
+ risk: "read",
1535
+ description: "List immutable published versions and the latest version ID, one page at a time.",
1536
+ flags: [...targetFlags, ...pagingFlags],
1537
+ validate: (ctx) => {
1538
+ validateTarget(ctx);
1539
+ validatePage(ctx);
1540
+ 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.");
1541
+ },
1542
+ dryRun: (ctx) => preview2(ctx, API, pageQuery(ctx)),
1543
+ execute: (ctx) => kbApi(ctx, "GET", API, pageQuery(ctx), void 0, apiOptions2)
1544
+ };
1545
+ var versionShow = {
1546
+ service: "kb",
1547
+ command: "+version-show",
1548
+ risk: "read",
1549
+ description: "Read one published version summary without reading current sources.",
1550
+ flags: [...targetFlags, versionFlag],
1551
+ validate: validateVersion,
1552
+ dryRun: (ctx) => preview2(ctx, versionEndpoint(ctx), query2(ctx)),
1553
+ execute: (ctx) => kbApi(ctx, "GET", versionEndpoint(ctx), query2(ctx), void 0, apiOptions2)
1554
+ };
1555
+ var versionSources = {
1556
+ service: "kb",
1557
+ command: "+version-sources",
1558
+ risk: "read",
1559
+ description: "List historical sources and stable IDs from one immutable version.",
1560
+ flags: [...targetFlags, versionFlag, ...pagingFlags, { name: "source-type", type: "string", desc: "Optional source type filter: file | url | zip" }],
1561
+ validate: (ctx) => {
1562
+ validateVersion(ctx);
1563
+ validatePage(ctx);
1564
+ if (ctx.str("source-type") && !["file", "url", "zip"].includes(ctx.str("source-type"))) throw new CliValidationError("--source-type must be file, url, or zip.");
1565
+ },
1566
+ dryRun: (ctx) => preview2(ctx, versionEndpoint(ctx, "/sources"), { ...pageQuery(ctx), ...ctx.str("source-type") ? { sourceType: ctx.str("source-type") } : {} }),
1567
+ execute: (ctx) => kbApi(ctx, "GET", versionEndpoint(ctx, "/sources"), { ...pageQuery(ctx), ...ctx.str("source-type") ? { sourceType: ctx.str("source-type") } : {} }, void 0, apiOptions2)
1568
+ };
1569
+ var versionDiff = {
1570
+ service: "kb",
1571
+ command: "+version-diff",
1572
+ risk: "read",
1573
+ description: "Compare historical source additions, deletions, content, and metadata between two versions.",
1574
+ flags: [...targetFlags, { ...versionFlag, name: "from", desc: "Before version number" }, { ...versionFlag, name: "to", desc: "After version number" }],
1575
+ validate: (ctx) => {
1576
+ validateTarget(ctx);
1577
+ positiveInteger(ctx, "from");
1578
+ positiveInteger(ctx, "to");
1579
+ },
1580
+ dryRun: (ctx) => preview2(ctx, `${API}/compare`, { ...query2(ctx), from: ctx.num("from"), to: ctx.num("to") }),
1581
+ execute: (ctx) => kbApi(ctx, "GET", `${API}/compare`, { ...query2(ctx), from: ctx.num("from"), to: ctx.num("to") }, void 0, apiOptions2)
1582
+ };
1583
+ var versionTree = {
1584
+ service: "kb",
1585
+ command: "+version-tree",
1586
+ risk: "read",
1587
+ description: "List a historical ZIP or URL source directory without changing current files.",
1588
+ flags: [...targetFlags, versionFlag, sourceFlag, pathFlag2, ...pagingFlags],
1589
+ validate: (ctx) => {
1590
+ validateSource(ctx);
1591
+ validatePath(ctx);
1592
+ validatePage(ctx);
1593
+ },
1594
+ dryRun: (ctx) => preview2(ctx, sourceEndpoint(ctx, "tree"), { ...pageQuery(ctx), path: ctx.str("path") }),
1595
+ execute: (ctx) => kbApi(ctx, "GET", sourceEndpoint(ctx, "tree"), { ...pageQuery(ctx), path: ctx.str("path") }, void 0, apiOptions2)
1596
+ };
1597
+ var versionRead = {
1598
+ service: "kb",
1599
+ command: "+version-read",
1600
+ risk: "read",
1601
+ description: "Preview one historical directory child file; unsupported or oversized files return metadata only.",
1602
+ flags: [...targetFlags, versionFlag, sourceFlag, { ...pathFlag2, required: true }],
1603
+ validate: (ctx) => {
1604
+ validateSource(ctx);
1605
+ validatePath(ctx, true);
1606
+ },
1607
+ dryRun: (ctx) => preview2(ctx, sourceEndpoint(ctx, "file"), { ...query2(ctx), path: ctx.str("path") }),
1608
+ execute: (ctx) => kbApi(ctx, "GET", sourceEndpoint(ctx, "file"), { ...query2(ctx), path: ctx.str("path") }, void 0, apiOptions2)
1609
+ };
1610
+ var versionDownload = {
1611
+ service: "kb",
1612
+ command: "+version-download",
1613
+ risk: "read",
1614
+ description: "Download one ordinary historical file source to a new local file. ZIP/URL directories cannot be downloaded.",
1615
+ flags: [...targetFlags, versionFlag, sourceFlag, { name: "output", type: "string", required: true, desc: "New local output path; existing files are never overwritten" }],
1616
+ validate: (ctx) => {
1617
+ validateSource(ctx);
1618
+ if (!ctx.str("output").trim()) throw new CliValidationError("--output is required.");
1619
+ },
1620
+ dryRun: (ctx) => ({ ...preview2(ctx, sourceEndpoint(ctx, "raw"), query2(ctx)), output: path4.resolve(ctx.str("output")) }),
1621
+ execute: async (ctx) => {
1622
+ const result = await kbApi(ctx, "GET", sourceEndpoint(ctx, "raw"), query2(ctx), void 0, { ...apiOptions2, responseType: "bytes" });
1623
+ const output = path4.resolve(ctx.str("output"));
1624
+ const bytes = Buffer.from(result.bytes);
1625
+ await fs4.writeFile(output, bytes, { flag: "wx" });
1626
+ return { versionNumber: ctx.num("version"), sourceId: ctx.str("id").trim(), sizeBytes: String(bytes.length), output };
1179
1627
  }
1180
1628
  };
1629
+ function rollbackBody(ctx) {
1630
+ return { requestId: ctx.str("request-id"), expectedLatestVersionId: ctx.str("expected-latest-version-id") };
1631
+ }
1632
+ var rollback = {
1633
+ service: "kb",
1634
+ command: "+rollback",
1635
+ risk: "high-risk-write",
1636
+ 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.",
1637
+ flags: [
1638
+ ...targetFlags,
1639
+ versionFlag,
1640
+ { name: "request-id", type: "string", required: true, maxLength: 191, desc: "Caller-generated stable ASCII request ID; reuse exactly for retries of this logical operation" },
1641
+ { 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" }
1642
+ ],
1643
+ validate: (ctx) => {
1644
+ validateVersion(ctx);
1645
+ if (!/^[A-Za-z0-9_-]{1,191}$/.test(ctx.str("request-id"))) throw new CliValidationError("--request-id must contain 1-191 ASCII letters, digits, underscores, or hyphens.");
1646
+ const latest = ctx.str("expected-latest-version-id");
1647
+ if (!latest || latest.length > 191) throw new CliValidationError("--expected-latest-version-id must contain 1 to 191 characters.");
1648
+ },
1649
+ dryRun: (ctx) => preview2(ctx, versionEndpoint(ctx, "/rollback"), query2(ctx), rollbackBody(ctx)),
1650
+ execute: (ctx) => kbApi(ctx, "POST", versionEndpoint(ctx, "/rollback"), query2(ctx), rollbackBody(ctx), apiOptions2)
1651
+ };
1652
+ var rollbackStatus = {
1653
+ service: "kb",
1654
+ command: "+rollback-status",
1655
+ risk: "read",
1656
+ description: "Read one persisted rollback operation without polling. A running operation with errorCode requires administrator review; never retry it as a new write.",
1657
+ flags: [...targetFlags, { name: "operation-id", type: "string", required: true, minLength: 1, maxLength: 191, desc: "operationId returned by +rollback" }],
1658
+ validate: (ctx) => {
1659
+ validateTarget(ctx);
1660
+ if (!ctx.str("operation-id").trim() || ctx.str("operation-id").length > 191) throw new CliValidationError("--operation-id must contain 1 to 191 characters.");
1661
+ },
1662
+ dryRun: (ctx) => preview2(ctx, `${API}/operations/${encodeURIComponent(ctx.str("operation-id").trim())}`, query2(ctx)),
1663
+ execute: (ctx) => kbApi(ctx, "GET", `${API}/operations/${encodeURIComponent(ctx.str("operation-id").trim())}`, query2(ctx), void 0, apiOptions2)
1664
+ };
1181
1665
 
1182
1666
  // src/commands/te-kb/index.ts
1183
1667
  var commands = [
1668
+ versions,
1669
+ versionShow,
1670
+ versionSources,
1671
+ versionDiff,
1672
+ versionTree,
1673
+ versionRead,
1674
+ versionDownload,
1675
+ rollback,
1676
+ rollbackStatus,
1677
+ sourceLs,
1678
+ sourceRead,
1679
+ sourcePut,
1680
+ sourceRm,
1184
1681
  ask,
1185
1682
  askStatus,
1186
1683
  add,
@@ -1216,7 +1713,20 @@ export {
1216
1713
  listSources,
1217
1714
  remove,
1218
1715
  rmSource,
1716
+ rollback,
1717
+ rollbackStatus,
1219
1718
  schema,
1719
+ sourceLs,
1720
+ sourcePut,
1721
+ sourceRead,
1722
+ sourceRm,
1220
1723
  status,
1221
- url
1724
+ url,
1725
+ versionDiff,
1726
+ versionDownload,
1727
+ versionRead,
1728
+ versionShow,
1729
+ versionSources,
1730
+ versionTree,
1731
+ versions
1222
1732
  };