@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/README.en.md +214 -0
- package/README.md +120 -66
- package/dist/cli.js +206 -2
- package/dist/cli.js.map +1 -1
- package/package.json +4 -2
- package/skill/SKILL.md +59 -0
- package/skill/references/citation-rules.md +85 -0
- package/skill/references/cli-reference.md +223 -0
- package/skill/references/search-strategies.md +73 -0
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.
|
|
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
|
-
"
|
|
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");
|