Skip to content

Commit 92a978a

Browse files
committed
fix(knowledge): 验证并限制查询时间范围为过去时间
- 修改时间参数说明,明确要求起止时间必须为过去时间 - 添加起始时间未来时报错机制,避免无意义查询 - 截断结束时间未来时间至当前时间,保障监控接口正确响应 - 添加测试覆盖,验证时间范围边界行为及错误处理 - 补充对应端到端测试路由映射,完善测试用例组织结构
1 parent 8195914 commit 92a978a

4 files changed

Lines changed: 130 additions & 11 deletions

File tree

packages/commands/src/commands/knowledge/kb-stats.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ const KB_STATS_FLAGS = {
2121
start: {
2222
type: "string",
2323
valueHint: "<time>",
24-
description: "Range start: Unix seconds or ISO date (default: 24 hours ago)",
24+
description:
25+
"Range start: Unix seconds or ISO date, must be in the past (default: 24 hours ago)",
2526
},
2627
end: {
2728
type: "string",
2829
valueHint: "<time>",
29-
description: "Range end: Unix seconds or ISO date (default: now)",
30+
description: "Range end: Unix seconds or ISO date, must be in the past (default: now)",
3031
},
3132
...WORKSPACE_FLAG,
3233
} satisfies FlagsDef;
@@ -56,6 +57,7 @@ export default defineCommand({
5657
notes: [
5758
"Defaults to the last 24 hours when --start/--end are omitted.",
5859
"Timestamps are normalized to epoch seconds as required by the server.",
60+
"Future timestamps are rejected for --start and clamped to now for --end, since the monitor API only returns past data.",
5961
],
6062
exampleArgs: [
6163
"--index-id idx-xxx --workspace-id ws-xxx",
@@ -70,7 +72,21 @@ export default defineCommand({
7072
const startTimestamp = flags.start
7173
? toEpochSecondsString(flags.start)
7274
: String(nowSeconds - 24 * 3600);
73-
const endTimestamp = flags.end ? toEpochSecondsString(flags.end) : String(nowSeconds);
75+
let endTimestamp = flags.end ? toEpochSecondsString(flags.end) : String(nowSeconds);
76+
77+
// The monitor API rejects future timestamps with a misleading
78+
// "missing or invalid" error — validate here with a clear message.
79+
if (Number(startTimestamp) > nowSeconds) {
80+
throw new BailianError(
81+
`Start time is in the future; the monitor API only accepts past or current timestamps.`,
82+
ExitCode.USAGE,
83+
"Use a start date/time at or before now, or omit --start to default to 24 hours ago.",
84+
);
85+
}
86+
const clampedEnd = Number(endTimestamp) > nowSeconds;
87+
if (clampedEnd) {
88+
endTimestamp = String(nowSeconds);
89+
}
7490

7591
const body = { indexId: flags.indexId, startTimestamp, endTimestamp };
7692
const endpoint = ragEndpoint(workspaceId, RAG_PATHS.indexMonitor);
@@ -90,6 +106,9 @@ export default defineCommand({
90106
emitResult(response, format === "text" ? "json" : format);
91107
return;
92108
}
109+
if (clampedEnd) {
110+
emitBare("note: end time was in the future, clamped to now.");
111+
}
93112
// Shape verified against the live API: the monitor fields are objects, not arrays
94113
const storage = response.data?.storageMonitorData;
95114
const qps = response.data?.qpsMonitorData;
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { describe, expect, test } from "vite-plus/test";
2+
import { parseStdoutJson, runCommandE2e } from "../helpers.ts";
3+
import { KNOWLEDGE_KB_STATS_ROUTES } from "../topic-routes.ts";
4+
5+
interface DryRunBody {
6+
endpoint?: string;
7+
request?: {
8+
indexId?: string;
9+
startTimestamp?: string;
10+
endTimestamp?: string;
11+
};
12+
}
13+
14+
describe("e2e: knowledge stats dry-run", () => {
15+
test("--dry-run 正常日期范围输出正确时间戳", async () => {
16+
const { stdout, stderr, exitCode } = await runCommandE2e(
17+
KNOWLEDGE_KB_STATS_ROUTES,
18+
[
19+
"knowledge",
20+
"stats",
21+
"--dry-run",
22+
"--index-id",
23+
"idx_test",
24+
"--start",
25+
"2026-07-30",
26+
"--end",
27+
"2026-08-10",
28+
"--workspace-id",
29+
"ws_test",
30+
"--output",
31+
"json",
32+
],
33+
{ DASHSCOPE_API_KEY: "sk-fake-for-dryrun" },
34+
);
35+
expect(exitCode, stderr).toBe(0);
36+
const data = parseStdoutJson<DryRunBody>(stdout);
37+
expect(data.endpoint).toMatch(/api\/v1\/indices\/rag\/index\/monitor/);
38+
expect(data.request?.indexId).toBe("idx_test");
39+
expect(data.request?.startTimestamp).toBe("1785369600"); // 2026-07-30 00:00:00 UTC
40+
expect(data.request?.endTimestamp).toBe("1786320000"); // 2026-08-10 00:00:00 UTC (11 days after start)
41+
});
42+
43+
test("--end 未来时间被截断为当前时间", async () => {
44+
const beforeRun = Math.floor(Date.now() / 1000);
45+
const { stdout, stderr, exitCode } = await runCommandE2e(
46+
KNOWLEDGE_KB_STATS_ROUTES,
47+
[
48+
"knowledge",
49+
"stats",
50+
"--dry-run",
51+
"--index-id",
52+
"idx_test",
53+
"--start",
54+
"2026-07-30",
55+
"--end",
56+
"2026-12-31",
57+
"--workspace-id",
58+
"ws_test",
59+
"--output",
60+
"json",
61+
],
62+
{ DASHSCOPE_API_KEY: "sk-fake-for-dryrun" },
63+
);
64+
const afterRun = Math.floor(Date.now() / 1000);
65+
expect(exitCode, stderr).toBe(0);
66+
const data = parseStdoutJson<DryRunBody>(stdout);
67+
expect(data.request?.startTimestamp).toBe("1785369600"); // 2026-07-30 unchanged
68+
// endTimestamp should be clamped to now, within the run window
69+
const endTs = Number(data.request?.endTimestamp);
70+
expect(endTs).toBeGreaterThanOrEqual(beforeRun);
71+
expect(endTs).toBeLessThanOrEqual(afterRun);
72+
});
73+
74+
test("--start 未来时间报用法错误 (exit 2)", async () => {
75+
const { stderr, exitCode } = await runCommandE2e(
76+
KNOWLEDGE_KB_STATS_ROUTES,
77+
[
78+
"knowledge",
79+
"stats",
80+
"--dry-run",
81+
"--index-id",
82+
"idx_test",
83+
"--start",
84+
"2026-12-31",
85+
"--workspace-id",
86+
"ws_test",
87+
"--output",
88+
"json",
89+
],
90+
{ DASHSCOPE_API_KEY: "sk-fake-for-dryrun" },
91+
);
92+
expect(exitCode).toBe(2);
93+
expect(stderr).toMatch(/future/i);
94+
});
95+
});

packages/commands/tests/e2e/topic-routes.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,10 @@ export const KNOWLEDGE_DOC_TAG_ROUTES: E2eRouteExports = {
244244
"knowledge file delete": "knowledgeFileDelete", // live cleanup of data-center files
245245
};
246246

247+
export const KNOWLEDGE_KB_STATS_ROUTES: E2eRouteExports = {
248+
"knowledge stats": "knowledgeKbStats",
249+
};
250+
247251
export const KNOWLEDGE_SERVICE_ROUTES: E2eRouteExports = {
248252
"knowledge service list": "knowledgeServiceList",
249253
"knowledge service get": "knowledgeServiceGet",

skills/bailian-cli/reference/knowledge.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,19 +1207,20 @@ bl knowledge service update --agent-id aid-xxx --agent-version 1 --version-desc
12071207

12081208
#### Flags
12091209

1210-
| Flag | Type | Required | Description |
1211-
| --------------------- | ------ | -------- | --------------------------------------------------------------- |
1212-
| `--index-id <id>` | string | yes | Knowledge base ID |
1213-
| `--start <time>` | string | no | Range start: Unix seconds or ISO date (default: 24 hours ago) |
1214-
| `--end <time>` | string | no | Range end: Unix seconds or ISO date (default: now) |
1215-
| `--workspace-id <id>` | string | no | Workspace ID for API endpoint URL (or set BAILIAN_WORKSPACE_ID) |
1216-
| `--api-key <key>` | string | no | API key |
1217-
| `--base-url <url>` | string | no | API base URL |
1210+
| Flag | Type | Required | Description |
1211+
| --------------------- | ------ | -------- | ---------------------------------------------------------------------------------- |
1212+
| `--index-id <id>` | string | yes | Knowledge base ID |
1213+
| `--start <time>` | string | no | Range start: Unix seconds or ISO date, must be in the past (default: 24 hours ago) |
1214+
| `--end <time>` | string | no | Range end: Unix seconds or ISO date, must be in the past (default: now) |
1215+
| `--workspace-id <id>` | string | no | Workspace ID for API endpoint URL (or set BAILIAN_WORKSPACE_ID) |
1216+
| `--api-key <key>` | string | no | API key |
1217+
| `--base-url <url>` | string | no | API base URL |
12181218

12191219
#### Notes
12201220

12211221
- Defaults to the last 24 hours when --start/--end are omitted.
12221222
- Timestamps are normalized to epoch seconds as required by the server.
1223+
- Future timestamps are rejected for --start and clamped to now for --end, since the monitor API only returns past data.
12231224

12241225
#### Examples
12251226

0 commit comments

Comments
 (0)