@zleap-ai/sag-cli 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -6,7 +6,7 @@ import { confirm, password, select } from "@inquirer/prompts";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "@zleap-ai/sag-cli",
9
- version: "0.2.0",
9
+ version: "0.3.0",
10
10
  description: "Command-line client and diagnostics for SAG knowledge bases",
11
11
  type: "module",
12
12
  bin: {
@@ -15,7 +15,9 @@ var package_default = {
15
15
  files: [
16
16
  "dist",
17
17
  "README.md",
18
- "LICENSE"
18
+ "README.en.md",
19
+ "LICENSE",
20
+ "skill"
19
21
  ],
20
22
  scripts: {
21
23
  build: "tsup",
@@ -1353,6 +1355,43 @@ var mcpDescriptorSchema = z6.object({
1353
1355
  headers: z6.record(z6.string(), z6.string())
1354
1356
  }).passthrough()
1355
1357
  }).passthrough();
1358
+ var outlineItemSchema = z6.object({
1359
+ rank: z6.number().int(),
1360
+ heading: z6.string(),
1361
+ chunk_id: z6.string()
1362
+ }).passthrough();
1363
+ var outlineSchema = z6.object({
1364
+ document_id: z6.string(),
1365
+ filename: z6.string(),
1366
+ outline: z6.array(outlineItemSchema)
1367
+ }).passthrough();
1368
+ var grepMatchSchema = z6.object({
1369
+ chunk_id: z6.string(),
1370
+ heading: z6.string(),
1371
+ snippet: z6.string()
1372
+ }).passthrough();
1373
+ var grepResponseSchema = z6.object({
1374
+ pattern: z6.string(),
1375
+ matches: z6.array(grepMatchSchema),
1376
+ count: z6.number().int().nonnegative()
1377
+ }).passthrough();
1378
+ var readResponseSchema = z6.object({
1379
+ document_id: z6.string(),
1380
+ filename: z6.string(),
1381
+ total_lines: z6.number().int().nonnegative(),
1382
+ offset: z6.number().int().positive(),
1383
+ limit: z6.number().int().positive(),
1384
+ lines: z6.array(z6.string())
1385
+ }).passthrough();
1386
+ var entityContextSchema = z6.object({
1387
+ entity_id: z6.string(),
1388
+ name: z6.string(),
1389
+ type: z6.string(),
1390
+ description: z6.string(),
1391
+ context: z6.string(),
1392
+ source_id: z6.string(),
1393
+ source_name: z6.string()
1394
+ }).passthrough();
1356
1395
 
1357
1396
  // src/api/client.ts
1358
1397
  var SagClient = class {
@@ -1414,6 +1453,42 @@ var SagClient = class {
1414
1453
  body: input
1415
1454
  });
1416
1455
  }
1456
+ outline(sourceId, documentId) {
1457
+ const params = new URLSearchParams({ document_id: documentId });
1458
+ return this.#request(
1459
+ `/api/v1/sources/${encodeURIComponent(sourceId)}/outline?${params}`,
1460
+ outlineSchema
1461
+ );
1462
+ }
1463
+ grep(sourceId, pattern, limit) {
1464
+ const params = new URLSearchParams({ pattern });
1465
+ if (limit !== void 0) {
1466
+ params.set("limit", String(limit));
1467
+ }
1468
+ return this.#request(
1469
+ `/api/v1/sources/${encodeURIComponent(sourceId)}/grep?${params}`,
1470
+ grepResponseSchema
1471
+ );
1472
+ }
1473
+ readDocument(sourceId, documentId, offset, limit) {
1474
+ const params = new URLSearchParams();
1475
+ if (offset !== void 0) {
1476
+ params.set("offset", String(offset));
1477
+ }
1478
+ if (limit !== void 0) {
1479
+ params.set("limit", String(limit));
1480
+ }
1481
+ return this.#request(
1482
+ `/api/v1/sources/${encodeURIComponent(sourceId)}/documents/${encodeURIComponent(documentId)}/read?${params}`,
1483
+ readResponseSchema
1484
+ );
1485
+ }
1486
+ getEntityContext(sourceId, name) {
1487
+ return this.#request(
1488
+ `/api/v1/sources/${encodeURIComponent(sourceId)}/entities/${encodeURIComponent(name)}/context`,
1489
+ entityContextSchema
1490
+ );
1491
+ }
1417
1492
  async #request(path5, schema, options = {}) {
1418
1493
  const authenticated = options.authenticated ?? true;
1419
1494
  if (authenticated && !this.#token) {
@@ -2132,6 +2207,44 @@ async function documentStatus(client, sourceId, documentId) {
2132
2207
  };
2133
2208
  }
2134
2209
 
2210
+ // src/commands/knowledge.ts
2211
+ function requiredIdentifier2(value, label) {
2212
+ const normalized = value.trim();
2213
+ if (!normalized) {
2214
+ throw new CliError("INVALID_ARGUMENT", `${label} is required`, {
2215
+ exitCode: exitCodes.invalidArgument
2216
+ });
2217
+ }
2218
+ return normalized;
2219
+ }
2220
+ async function outline(client, sourceId, documentId) {
2221
+ return client.outline(
2222
+ requiredIdentifier2(sourceId, "Source ID"),
2223
+ requiredIdentifier2(documentId, "Document ID")
2224
+ );
2225
+ }
2226
+ async function grep(client, sourceId, pattern, limit) {
2227
+ return client.grep(
2228
+ requiredIdentifier2(sourceId, "Source ID"),
2229
+ requiredIdentifier2(pattern, "Pattern"),
2230
+ limit
2231
+ );
2232
+ }
2233
+ async function read(client, sourceId, documentId, offset, limit) {
2234
+ return client.readDocument(
2235
+ requiredIdentifier2(sourceId, "Source ID"),
2236
+ requiredIdentifier2(documentId, "Document ID"),
2237
+ offset,
2238
+ limit
2239
+ );
2240
+ }
2241
+ async function getEntityContext(client, sourceId, name) {
2242
+ return client.getEntityContext(
2243
+ requiredIdentifier2(sourceId, "Source ID"),
2244
+ requiredIdentifier2(name, "Entity name")
2245
+ );
2246
+ }
2247
+
2135
2248
  // src/commands/mcp.ts
2136
2249
  async function testLocalMcp(runtime2, input) {
2137
2250
  const container = await discoverSagContainer({
@@ -2680,6 +2793,45 @@ function renderLocalMcp(value) {
2680
2793
  ].join("\n")}
2681
2794
  `;
2682
2795
  }
2796
+ function renderOutline(value) {
2797
+ const filename = typeof value.filename === "string" ? value.filename : "Unknown";
2798
+ const items = Array.isArray(value.outline) ? value.outline.filter(isRecord) : [];
2799
+ const lines = items.map(
2800
+ (item) => `${String(item.rank ?? 0).padStart(3)}. ${item.heading || "(untitled)"} (chunk_id=${item.chunk_id})`
2801
+ );
2802
+ return `${filename}
2803
+ ${lines.join("\n")}
2804
+ `;
2805
+ }
2806
+ function renderGrep(value) {
2807
+ const matches = Array.isArray(value.matches) ? value.matches.filter(isRecord) : [];
2808
+ const lines = matches.map(
2809
+ (match, index) => `[${index + 1}] ${match.heading || "Match"}
2810
+ ${match.snippet}`
2811
+ );
2812
+ return lines.length ? `${lines.join("\n\n")}
2813
+ ` : "No matches.\n";
2814
+ }
2815
+ function renderRead(value) {
2816
+ const filename = typeof value.filename === "string" ? value.filename : "Unknown";
2817
+ const total = typeof value.total_lines === "number" ? value.total_lines : 0;
2818
+ const offset = typeof value.offset === "number" ? value.offset : 1;
2819
+ const lines = Array.isArray(value.lines) ? value.lines.map(String) : [];
2820
+ const header = `${filename} \xB7 lines ${offset}-${offset + lines.length - 1} / ${total}`;
2821
+ return `${header}
2822
+ ${lines.join("")}`;
2823
+ }
2824
+ function renderEntityContext(value) {
2825
+ const name = typeof value.name === "string" ? value.name : "Unknown";
2826
+ const type = typeof value.type === "string" ? value.type : "";
2827
+ const source = typeof value.source_name === "string" ? value.source_name : "";
2828
+ const context = typeof value.context === "string" ? value.context : "";
2829
+ return `Entity: ${name}${type ? ` (${type})` : ""}
2830
+ Source: ${source}
2831
+
2832
+ ${context}
2833
+ `;
2834
+ }
2683
2835
  function renderHuman(value, quiet = false) {
2684
2836
  if (quiet) {
2685
2837
  if (Array.isArray(value)) {
@@ -2702,6 +2854,18 @@ function renderHuman(value, quiet = false) {
2702
2854
  if (isRecord(value) && Array.isArray(value.sections) && "query" in value) {
2703
2855
  return renderSearch(value);
2704
2856
  }
2857
+ if (isRecord(value) && Array.isArray(value.outline) && "filename" in value) {
2858
+ return renderOutline(value);
2859
+ }
2860
+ if (isRecord(value) && Array.isArray(value.matches) && "pattern" in value) {
2861
+ return renderGrep(value);
2862
+ }
2863
+ if (isRecord(value) && Array.isArray(value.lines) && "total_lines" in value) {
2864
+ return renderRead(value);
2865
+ }
2866
+ if (isRecord(value) && "entity_id" in value && "context" in value) {
2867
+ return renderEntityContext(value);
2868
+ }
2705
2869
  if (isRecord(value) && value.provider === "docker-stdio" && "protocolVersion" in value && "container" in value) {
2706
2870
  return renderLocalMcp(value);
2707
2871
  }
@@ -2945,6 +3109,46 @@ function addKnowledgeCommands(program, dependencies2) {
2945
3109
  );
2946
3110
  }
2947
3111
  );
3112
+ program.command("outline").argument("<document-id>").requiredOption("--source <source-id>").action(async (documentId, options) => {
3113
+ const context = await runtime(program, dependencies2);
3114
+ emit(
3115
+ program,
3116
+ dependencies2,
3117
+ await outline(context.client, options.source, documentId)
3118
+ );
3119
+ });
3120
+ program.command("grep").argument("<pattern>").requiredOption("--source <source-id>").option("--limit <number>", "Maximum result count", parseInteger).action(async (pattern, options) => {
3121
+ const context = await runtime(program, dependencies2);
3122
+ emit(
3123
+ program,
3124
+ dependencies2,
3125
+ await grep(context.client, options.source, pattern, options.limit)
3126
+ );
3127
+ });
3128
+ program.command("read").argument("<document-id>").requiredOption("--source <source-id>").option("--offset <number>", "Starting line (1-based)", parseInteger).option("--limit <number>", "Lines to read", parseInteger).action(
3129
+ async (documentId, options) => {
3130
+ const context = await runtime(program, dependencies2);
3131
+ emit(
3132
+ program,
3133
+ dependencies2,
3134
+ await read(
3135
+ context.client,
3136
+ options.source,
3137
+ documentId,
3138
+ options.offset,
3139
+ options.limit
3140
+ )
3141
+ );
3142
+ }
3143
+ );
3144
+ program.command("get-entity").argument("<name>").requiredOption("--source <source-id>").action(async (name, options) => {
3145
+ const context = await runtime(program, dependencies2);
3146
+ emit(
3147
+ program,
3148
+ dependencies2,
3149
+ await getEntityContext(context.client, options.source, name)
3150
+ );
3151
+ });
2948
3152
  }
2949
3153
  function addLocalMcpCommands(program, dependencies2) {
2950
3154
  const mcp = program.command("mcp").description("Verify local SAG MCP");