mirror of
https://github.com/modelstudioai/cli.git
synced 2026-09-14 19:49:23 +08:00
refactor(auth): remove deprecated AK/SK auth for knowledge retrieve
AK/SK signing was used only by `knowledge retrieve`'s deprecated fallback, which the api-key auth gate now makes unreachable. Drop it; the command is pure api-key. - knowledge/retrieve: remove the AK/SK path + --access-key-id/secret/workspace-id flags; api-key only - delete client/ak-sign.ts and its signRequest/AkSignConfig exports - drop access_key_id/access_key_secret from config schema, loader, and `config show` / `config set` - remove the now-unused PascalCase KnowledgeRetrieve request/response types
This commit is contained in:
@@ -156,18 +156,6 @@ Required for console capability commands (`app list`, `usage free`, `usage stats
|
||||
bl auth login --console
|
||||
```
|
||||
|
||||
### Alibaba Cloud AK/SK (Knowledge Base only)
|
||||
|
||||
Required for `knowledge retrieve`. Get your AccessKey from [RAM Console](https://ram.console.aliyun.com/manage/ak).
|
||||
|
||||
> Recommended: create a RAM sub-account with minimum privileges instead of using the root account's AK/SK.
|
||||
|
||||
```bash
|
||||
export ALIBABA_CLOUD_ACCESS_KEY_ID=LTAI5t...
|
||||
export ALIBABA_CLOUD_ACCESS_KEY_SECRET=...
|
||||
export BAILIAN_WORKSPACE_ID=ws-...
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
```bash
|
||||
|
||||
@@ -151,18 +151,6 @@ bl text chat --api-key sk-xxxxx --message "你好"
|
||||
bl auth login --console
|
||||
```
|
||||
|
||||
### 阿里云 AK/SK(仅知识库检索)
|
||||
|
||||
`knowledge retrieve` 命令需要阿里云 AccessKey。前往 [RAM 控制台](https://ram.console.aliyun.com/manage/ak) 获取。
|
||||
|
||||
> 建议:创建 RAM 子账号并授予最小权限,避免使用主账号 AK/SK。
|
||||
|
||||
```bash
|
||||
export ALIBABA_CLOUD_ACCESS_KEY_ID=LTAI5t...
|
||||
export ALIBABA_CLOUD_ACCESS_KEY_SECRET=...
|
||||
export BAILIAN_WORKSPACE_ID=ws-...
|
||||
```
|
||||
|
||||
## 配置
|
||||
|
||||
```bash
|
||||
|
||||
@@ -156,18 +156,6 @@ Required for console capability commands (`app list`, `usage free`, `usage stats
|
||||
bl auth login --console
|
||||
```
|
||||
|
||||
### Alibaba Cloud AK/SK (Knowledge Base only)
|
||||
|
||||
Required for `knowledge retrieve`. Get your AccessKey from [RAM Console](https://ram.console.aliyun.com/manage/ak).
|
||||
|
||||
> Recommended: create a RAM sub-account with minimum privileges instead of using the root account's AK/SK.
|
||||
|
||||
```bash
|
||||
export ALIBABA_CLOUD_ACCESS_KEY_ID=LTAI5t...
|
||||
export ALIBABA_CLOUD_ACCESS_KEY_SECRET=...
|
||||
export BAILIAN_WORKSPACE_ID=ws-...
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
```bash
|
||||
|
||||
@@ -151,18 +151,6 @@ bl text chat --api-key sk-xxxxx --message "你好"
|
||||
bl auth login --console
|
||||
```
|
||||
|
||||
### 阿里云 AK/SK(仅知识库检索)
|
||||
|
||||
`knowledge retrieve` 命令需要阿里云 AccessKey。前往 [RAM 控制台](https://ram.console.aliyun.com/manage/ak) 获取。
|
||||
|
||||
> 建议:创建 RAM 子账号并授予最小权限,避免使用主账号 AK/SK。
|
||||
|
||||
```bash
|
||||
export ALIBABA_CLOUD_ACCESS_KEY_ID=LTAI5t...
|
||||
export ALIBABA_CLOUD_ACCESS_KEY_SECRET=...
|
||||
export BAILIAN_WORKSPACE_ID=ws-...
|
||||
```
|
||||
|
||||
## 配置
|
||||
|
||||
```bash
|
||||
|
||||
@@ -30,11 +30,6 @@ DASHSCOPE_API_KEY=
|
||||
# -------------------------------
|
||||
BAILIAN_E2E_VIDEO_TASK_ID=b499a8cb-1fc4-4d43-9495-e23c7f78ae0d
|
||||
# -------------------------------
|
||||
# 阿里云 AK
|
||||
ALIBABA_CLOUD_ACCESS_KEY_ID=
|
||||
# 阿里云 SK
|
||||
ALIBABA_CLOUD_ACCESS_KEY_SECRET=
|
||||
# -------------------------------
|
||||
# 知识库 ID
|
||||
BAILIAN_WORKSPACE_ID=
|
||||
# 索引 ID
|
||||
|
||||
@@ -117,23 +117,11 @@ export function e2eLabelFromMetaUrl(metaUrl: string): string {
|
||||
return basename(fileURLToPath(metaUrl), ".ts").replace(/\.e2e\.test$/, "");
|
||||
}
|
||||
|
||||
/** 知识库用例:须显式索引 ID + API-KEY 或 AK/SK */
|
||||
/** 知识库用例:须显式索引 ID + API-KEY */
|
||||
export function isKnowledgeE2EReady(): boolean {
|
||||
if (!isBailianE2EEnabled()) return false;
|
||||
if (!process.env.BAILIAN_E2E_INDEX_ID) return false;
|
||||
const hasApiKey = isDashScopeE2EReady();
|
||||
const hasAkSk =
|
||||
!!process.env.ALIBABA_CLOUD_ACCESS_KEY_ID && !!process.env.ALIBABA_CLOUD_ACCESS_KEY_SECRET;
|
||||
return hasApiKey || hasAkSk;
|
||||
}
|
||||
|
||||
export function isKnowledgeAkSkReady(): boolean {
|
||||
return (
|
||||
isBailianE2EEnabled() &&
|
||||
!!process.env.ALIBABA_CLOUD_ACCESS_KEY_ID &&
|
||||
!!process.env.ALIBABA_CLOUD_ACCESS_KEY_SECRET &&
|
||||
!!process.env.BAILIAN_E2E_INDEX_ID
|
||||
);
|
||||
return isDashScopeE2EReady();
|
||||
}
|
||||
|
||||
export interface RunCliResult {
|
||||
|
||||
@@ -35,7 +35,6 @@ describe("e2e: knowledge retrieve", () => {
|
||||
expect(stderr).toMatch(/--query/i);
|
||||
expect(stderr).toMatch(/--rerank-top-n/i);
|
||||
expect(stderr).toMatch(/deprecated/i);
|
||||
expect(stderr).toMatch(/--workspace-id/i);
|
||||
});
|
||||
|
||||
test("缺少 --index-id 时打印帮助并退出 (0)", async () => {
|
||||
@@ -82,8 +81,6 @@ describe("e2e: knowledge retrieve errors", () => {
|
||||
{
|
||||
DASHSCOPE_API_KEY: undefined,
|
||||
DASHSCOPE_ACCESS_TOKEN: undefined,
|
||||
ALIBABA_CLOUD_ACCESS_KEY_ID: undefined,
|
||||
ALIBABA_CLOUD_ACCESS_KEY_SECRET: undefined,
|
||||
BAILIAN_CONFIG_DIR: tmpdir(),
|
||||
},
|
||||
);
|
||||
|
||||
@@ -21,15 +21,13 @@ const VALID_KEYS = [
|
||||
"default_image_model",
|
||||
"default_speech_model",
|
||||
"default_omni_model",
|
||||
"access_key_id",
|
||||
"access_key_secret",
|
||||
"workspace_id",
|
||||
];
|
||||
|
||||
// Keys whose values are secrets. Their stored value must never be echoed back in
|
||||
// cleartext (CI logs, pipes, shared terminals); show a masked form instead — the
|
||||
// same policy `config show` and `auth status` already follow.
|
||||
const SECRET_KEYS = new Set(["api_key", "access_token", "access_key_id", "access_key_secret"]);
|
||||
const SECRET_KEYS = new Set(["api_key", "access_token"]);
|
||||
|
||||
// Allow hyphen-style keys (e.g. default-text-model → default_text_model)
|
||||
const KEY_ALIASES: Record<string, string> = {
|
||||
@@ -42,8 +40,6 @@ const KEY_ALIASES: Record<string, string> = {
|
||||
"default-image-model": "default_image_model",
|
||||
"default-speech-model": "default_speech_model",
|
||||
"default-omni-model": "default_omni_model",
|
||||
"access-key-id": "access_key_id",
|
||||
"access-key-secret": "access_key_secret",
|
||||
"workspace-id": "workspace_id",
|
||||
};
|
||||
|
||||
@@ -56,7 +52,7 @@ export default defineCommand({
|
||||
type: "string",
|
||||
valueHint: "<key>",
|
||||
description:
|
||||
"Config key (base_url, output, output_dir, timeout, api_key, access_token, default_*_model, access_key_id, access_key_secret, workspace_id)",
|
||||
"Config key (base_url, output, output_dir, timeout, api_key, access_token, default_*_model, workspace_id)",
|
||||
required: true,
|
||||
},
|
||||
value: { type: "string", valueHint: "<value>", description: "Value to set", required: true },
|
||||
|
||||
@@ -27,11 +27,6 @@ export default defineCommand({
|
||||
if (typeof result.api_key === "string") result.api_key = maskToken(result.api_key);
|
||||
if (typeof result.access_token === "string")
|
||||
result.access_token = maskToken(result.access_token);
|
||||
if (typeof result.access_key_id === "string")
|
||||
result.access_key_id = maskToken(result.access_key_id);
|
||||
if (typeof result.access_key_secret === "string") {
|
||||
result.access_key_secret = maskToken(result.access_key_secret);
|
||||
}
|
||||
|
||||
emitResult(result, format);
|
||||
},
|
||||
|
||||
@@ -1,27 +1,13 @@
|
||||
import {
|
||||
defineCommand,
|
||||
knowledgeRetrievePath,
|
||||
signRequest,
|
||||
detectOutputFormat,
|
||||
maskToken,
|
||||
resolveApiKeyCredential,
|
||||
trackingHeaders,
|
||||
type Client,
|
||||
type Config,
|
||||
type Flags,
|
||||
type FlagsDef,
|
||||
type KnowledgeRetrieveRequest,
|
||||
type KnowledgeRetrieveResponse,
|
||||
type DashScopeKnowledgeRetrieveRequest,
|
||||
type DashScopeKnowledgeRetrieveResponse,
|
||||
type OutputFormat,
|
||||
BailianError,
|
||||
ExitCode,
|
||||
} from "bailian-cli-core";
|
||||
import { emitResult, emitBare } from "bailian-cli-runtime";
|
||||
|
||||
const BAILIAN_HOST = "bailian.cn-beijing.aliyuncs.com";
|
||||
|
||||
const RETRIEVE_FLAGS = {
|
||||
indexId: {
|
||||
type: "string",
|
||||
@@ -67,87 +53,29 @@ const RETRIEVE_FLAGS = {
|
||||
valueHint: "<n>",
|
||||
description: "Number of results (deprecated, use --rerank-top-n)",
|
||||
},
|
||||
workspaceId: {
|
||||
type: "string",
|
||||
valueHint: "<id>",
|
||||
description: "Bailian workspace ID (only needed for deprecated AK/SK auth)",
|
||||
},
|
||||
accessKeyId: {
|
||||
type: "string",
|
||||
valueHint: "<key>",
|
||||
description: "Deprecated: use global --api-key instead",
|
||||
},
|
||||
accessKeySecret: {
|
||||
type: "string",
|
||||
valueHint: "<key>",
|
||||
description: "Deprecated: use global --api-key instead",
|
||||
},
|
||||
} satisfies FlagsDef;
|
||||
type RetrieveFlags = Flags<typeof RETRIEVE_FLAGS>;
|
||||
|
||||
export default defineCommand({
|
||||
description: "Retrieve from a Bailian knowledge base",
|
||||
auth: "apiKey",
|
||||
usageArgs: "--index-id <id> --query <text> [flags]",
|
||||
flags: RETRIEVE_FLAGS,
|
||||
notes: [
|
||||
"Authentication: pass `--api-key <key>`. AK/SK auth is deprecated and will be removed in a future version.",
|
||||
"`--workspace-id` is NOT required when using --api-key.",
|
||||
],
|
||||
exampleArgs: [
|
||||
'--index-id idx_xxx --query "How to use Alibaba Cloud Bailian"',
|
||||
'--api-key $DASHSCOPE_API_KEY --index-id idx_xxx --query "RAG retrieval" --rerank --rerank-model qwen3-rerank-hybrid',
|
||||
'--index-id idx_xxx --query "RAG retrieval" --rerank --rerank-model qwen3-rerank-hybrid',
|
||||
],
|
||||
async run(ctx) {
|
||||
const { config, flags } = ctx;
|
||||
const indexId = flags.indexId;
|
||||
const query = flags.query;
|
||||
|
||||
const format = detectOutputFormat(config.output);
|
||||
|
||||
const hasExplicitApiKey = !!config.apiKey;
|
||||
const hasExplicitAkSk = !!(flags.accessKeyId && flags.accessKeySecret);
|
||||
|
||||
if (hasExplicitApiKey) {
|
||||
await runWithApiKey(ctx.client, config, flags, indexId, query, format);
|
||||
} else if (hasExplicitAkSk) {
|
||||
await runWithAkSk(config, flags, indexId, query, format);
|
||||
} else {
|
||||
let useApiKey = false;
|
||||
try {
|
||||
await resolveApiKeyCredential(config);
|
||||
useApiKey = true;
|
||||
} catch {
|
||||
// No API-KEY credential available
|
||||
}
|
||||
|
||||
if (useApiKey) {
|
||||
await runWithApiKey(ctx.client, config, flags, indexId, query, format);
|
||||
} else {
|
||||
await runWithAkSk(config, flags, indexId, query, format);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// ---- API-KEY path (DashScope gateway, snake_case) ----
|
||||
|
||||
async function runWithApiKey(
|
||||
client: Client,
|
||||
config: Config,
|
||||
flags: RetrieveFlags,
|
||||
indexId: string,
|
||||
query: string,
|
||||
format: OutputFormat,
|
||||
): Promise<void> {
|
||||
if (flags.topK !== undefined && flags.rerankTopN === undefined) {
|
||||
process.stderr.write("Warning: --top-k is deprecated. Use --rerank-top-n instead.\n");
|
||||
flags.rerankTopN = flags.topK;
|
||||
}
|
||||
|
||||
const body: DashScopeKnowledgeRetrieveRequest = {
|
||||
index_id: indexId,
|
||||
query,
|
||||
index_id: flags.indexId,
|
||||
query: flags.query,
|
||||
search_filters: [],
|
||||
};
|
||||
|
||||
@@ -168,11 +96,11 @@ async function runWithApiKey(
|
||||
}
|
||||
|
||||
if (config.dryRun) {
|
||||
emitResult({ endpoint: client.url(knowledgeRetrievePath()), request: body }, format);
|
||||
emitResult({ endpoint: ctx.client.url(knowledgeRetrievePath()), request: body }, format);
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await client.requestJson<DashScopeKnowledgeRetrieveResponse>({
|
||||
const response = await ctx.client.requestJson<DashScopeKnowledgeRetrieveResponse>({
|
||||
path: knowledgeRetrievePath(),
|
||||
method: "POST",
|
||||
body,
|
||||
@@ -184,140 +112,15 @@ async function runWithApiKey(
|
||||
} else {
|
||||
emitResult(response, format);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- AK/SK path (Bailian OpenAPI gateway, PascalCase) ----
|
||||
|
||||
async function runWithAkSk(
|
||||
config: Config,
|
||||
flags: RetrieveFlags,
|
||||
indexId: string,
|
||||
query: string,
|
||||
format: OutputFormat,
|
||||
): Promise<void> {
|
||||
const accessKeyId = flags.accessKeyId || config.accessKeyId;
|
||||
const accessKeySecret = flags.accessKeySecret || config.accessKeySecret;
|
||||
const workspaceId = flags.workspaceId || config.workspaceId;
|
||||
|
||||
if (!accessKeyId || !accessKeySecret) {
|
||||
throw new BailianError(
|
||||
"No credentials found.\n" +
|
||||
"Preferred: set DASHSCOPE_API_KEY or pass --api-key.\n" +
|
||||
"Legacy (deprecated): set ALIBABA_CLOUD_ACCESS_KEY_ID / ALIBABA_CLOUD_ACCESS_KEY_SECRET.",
|
||||
ExitCode.AUTH,
|
||||
);
|
||||
}
|
||||
|
||||
if (!workspaceId) {
|
||||
throw new BailianError(
|
||||
"Knowledge retrieve requires a workspace ID.\n" +
|
||||
`Set via: --workspace-id flag, or env: BAILIAN_WORKSPACE_ID, or config: ${config.binName} config set workspace_id <id>`,
|
||||
ExitCode.USAGE,
|
||||
);
|
||||
}
|
||||
|
||||
process.stderr.write(
|
||||
"Warning: AK/SK auth for knowledge retrieve is deprecated. Prefer --api-key or DASHSCOPE_API_KEY.\n",
|
||||
);
|
||||
|
||||
const body: KnowledgeRetrieveRequest = {
|
||||
IndexId: indexId,
|
||||
Query: query,
|
||||
};
|
||||
|
||||
if (flags.topK !== undefined && flags.rerankTopN === undefined) {
|
||||
process.stderr.write("Warning: --top-k is deprecated. Use --rerank-top-n instead.\n");
|
||||
flags.rerankTopN = flags.topK;
|
||||
}
|
||||
|
||||
if (flags.rerank) body.EnableReranking = true;
|
||||
if (flags.rerankTopN !== undefined) body.RerankTopN = flags.rerankTopN;
|
||||
if (flags.denseSimilarityTopK !== undefined) body.DenseSimilarityTopK = flags.denseSimilarityTopK;
|
||||
if (flags.sparseSimilarityTopK !== undefined)
|
||||
body.SparseSimilarityTopK = flags.sparseSimilarityTopK;
|
||||
|
||||
if (flags.rerankModel) {
|
||||
const rerank: { ModelName: string; RerankMode?: string; RerankInstruct?: string } = {
|
||||
ModelName: flags.rerankModel,
|
||||
};
|
||||
if (flags.rerankMode) rerank.RerankMode = flags.rerankMode;
|
||||
if (flags.rerankInstruct) rerank.RerankInstruct = flags.rerankInstruct;
|
||||
body.Rerank = [rerank];
|
||||
}
|
||||
|
||||
const pathname = `/${workspaceId}/index/retrieve`;
|
||||
|
||||
if (config.dryRun) {
|
||||
emitResult(
|
||||
{
|
||||
endpoint: `https://${BAILIAN_HOST}${pathname}`,
|
||||
workspaceId,
|
||||
request: body,
|
||||
},
|
||||
format,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const bodyStr = JSON.stringify(body);
|
||||
|
||||
const headers = signRequest({
|
||||
accessKeyId,
|
||||
accessKeySecret,
|
||||
action: "Retrieve",
|
||||
version: "2023-12-29",
|
||||
body: bodyStr,
|
||||
host: BAILIAN_HOST,
|
||||
pathname,
|
||||
});
|
||||
|
||||
const url = `https://${BAILIAN_HOST}${pathname}`;
|
||||
|
||||
if (config.verbose) {
|
||||
process.stderr.write(`> POST ${url}\n`);
|
||||
process.stderr.write(`> AK: ${maskToken(accessKeyId)}\n`);
|
||||
}
|
||||
|
||||
const timeoutMs = config.timeout * 1000;
|
||||
const res = await fetch(url, {
|
||||
method: "POST",
|
||||
headers: { ...headers, ...trackingHeaders() },
|
||||
body: bodyStr,
|
||||
signal: AbortSignal.timeout(timeoutMs),
|
||||
});
|
||||
|
||||
if (config.verbose) {
|
||||
process.stderr.write(`< ${res.status} ${res.statusText}\n`);
|
||||
}
|
||||
|
||||
const data = (await res.json()) as KnowledgeRetrieveResponse & {
|
||||
Code?: string;
|
||||
Message?: string;
|
||||
};
|
||||
|
||||
if (!res.ok || (data.Code && data.Code !== "Success")) {
|
||||
throw new BailianError(
|
||||
`Knowledge retrieve failed: ${data.Code || res.status} - ${data.Message || res.statusText}`,
|
||||
ExitCode.GENERAL,
|
||||
);
|
||||
}
|
||||
|
||||
const nodes = data.Data?.Nodes || [];
|
||||
if (config.quiet || format === "text") {
|
||||
emitTextNodes(nodes.map((n) => ({ text: n.Text, score: n.Score })));
|
||||
} else {
|
||||
emitResult(data, format);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Shared text output ----
|
||||
});
|
||||
|
||||
function emitTextNodes(nodes: Array<{ text: string; score: number }>): void {
|
||||
if (nodes.length === 0) {
|
||||
emitBare("No results found.");
|
||||
} else {
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
const node = nodes[i];
|
||||
const node = nodes[i]!;
|
||||
emitBare(`[${i + 1}] (score: ${node.score.toFixed(4)})`);
|
||||
emitBare(node.text);
|
||||
emitBare("");
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/**
|
||||
* Alibaba Cloud V3 Signature (ROA style) for Bailian Cloud API.
|
||||
*
|
||||
* Used by Knowledge Base Retrieve API which requires AK/SK authentication
|
||||
* instead of Bearer token.
|
||||
*
|
||||
* Reference: https://help.aliyun.com/document_detail/2712195.html
|
||||
*/
|
||||
|
||||
import { createHmac, createHash, randomUUID } from "crypto";
|
||||
|
||||
export interface AkSignConfig {
|
||||
accessKeyId: string;
|
||||
accessKeySecret: string;
|
||||
action: string;
|
||||
version: string;
|
||||
body: string;
|
||||
host: string;
|
||||
pathname: string;
|
||||
method?: string;
|
||||
}
|
||||
|
||||
export function signRequest(cfg: AkSignConfig): Record<string, string> {
|
||||
const method = cfg.method ?? "POST";
|
||||
const now = new Date();
|
||||
const dateISO = now.toISOString().replace(/\.\d{3}Z$/, "Z");
|
||||
const nonce = randomUUID();
|
||||
|
||||
const hashedBody = sha256Hex(cfg.body);
|
||||
|
||||
const headers: Record<string, string> = {
|
||||
host: cfg.host,
|
||||
"x-acs-action": cfg.action,
|
||||
"x-acs-version": cfg.version,
|
||||
"x-acs-date": dateISO,
|
||||
"x-acs-signature-nonce": nonce,
|
||||
"x-acs-content-sha256": hashedBody,
|
||||
"content-type": "application/json",
|
||||
};
|
||||
|
||||
// Build canonical headers (sorted, lowercase)
|
||||
const signedHeaderKeys = Object.keys(headers)
|
||||
.filter((k) => k === "host" || k === "content-type" || k.startsWith("x-acs-"))
|
||||
.sort();
|
||||
|
||||
const canonicalHeaders = signedHeaderKeys.map((k) => `${k}:${headers[k]}`).join("\n") + "\n";
|
||||
|
||||
const signedHeadersStr = signedHeaderKeys.join(";");
|
||||
|
||||
// Build canonical request
|
||||
const canonicalRequest = [
|
||||
method,
|
||||
cfg.pathname,
|
||||
"", // query string (empty for POST)
|
||||
canonicalHeaders,
|
||||
signedHeadersStr,
|
||||
hashedBody,
|
||||
].join("\n");
|
||||
|
||||
// Build string to sign
|
||||
const algorithm = "ACS3-HMAC-SHA256";
|
||||
const hashedCanonical = sha256Hex(canonicalRequest);
|
||||
const stringToSign = `${algorithm}\n${hashedCanonical}`;
|
||||
|
||||
// Calculate signature
|
||||
const signature = hmacSHA256Hex(cfg.accessKeySecret, stringToSign);
|
||||
|
||||
headers["authorization"] =
|
||||
`${algorithm} Credential=${cfg.accessKeyId},SignedHeaders=${signedHeadersStr},Signature=${signature}`;
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
||||
function sha256Hex(data: string): string {
|
||||
return createHash("sha256").update(data, "utf8").digest("hex");
|
||||
}
|
||||
|
||||
function hmacSHA256Hex(key: string, data: string): string {
|
||||
return createHmac("sha256", key).update(data, "utf8").digest("hex");
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
export type { AkSignConfig } from "./ak-sign.ts";
|
||||
export { signRequest } from "./ak-sign.ts";
|
||||
export {
|
||||
appCompletionPath,
|
||||
chatPath,
|
||||
|
||||
@@ -69,9 +69,6 @@ export function loadConfig(flags: GlobalFlags): Config {
|
||||
defaultImageModel: file.default_image_model,
|
||||
defaultSpeechModel: file.default_speech_model,
|
||||
defaultOmniModel: file.default_omni_model,
|
||||
accessKeyId: process.env.ALIBABA_CLOUD_ACCESS_KEY_ID || file.access_key_id || undefined,
|
||||
accessKeySecret:
|
||||
process.env.ALIBABA_CLOUD_ACCESS_KEY_SECRET || file.access_key_secret || undefined,
|
||||
workspaceId: process.env.BAILIAN_WORKSPACE_ID || file.workspace_id || undefined,
|
||||
consoleSite: (flags.consoleSite as Config["consoleSite"]) || file.console_site || undefined,
|
||||
consoleRegion: (flags.consoleRegion as string) || file.console_region || undefined,
|
||||
|
||||
@@ -27,8 +27,6 @@ export interface ConfigFile {
|
||||
default_image_model?: string;
|
||||
default_speech_model?: string;
|
||||
default_omni_model?: string;
|
||||
access_key_id?: string;
|
||||
access_key_secret?: string;
|
||||
workspace_id?: string;
|
||||
console_site?: "domestic" | "international";
|
||||
console_region?: string;
|
||||
@@ -80,10 +78,6 @@ export function parseConfigFile(raw: unknown): ConfigFile {
|
||||
out.default_speech_model = obj.default_speech_model;
|
||||
if (typeof obj.default_omni_model === "string" && obj.default_omni_model.length > 0)
|
||||
out.default_omni_model = obj.default_omni_model;
|
||||
if (typeof obj.access_key_id === "string" && obj.access_key_id.length > 0)
|
||||
out.access_key_id = obj.access_key_id;
|
||||
if (typeof obj.access_key_secret === "string" && obj.access_key_secret.length > 0)
|
||||
out.access_key_secret = obj.access_key_secret;
|
||||
if (typeof obj.workspace_id === "string" && obj.workspace_id.length > 0)
|
||||
out.workspace_id = obj.workspace_id;
|
||||
if (typeof obj.console_site === "string" && VALID_CONSOLE_SITES.has(obj.console_site))
|
||||
@@ -121,8 +115,6 @@ export interface Config {
|
||||
defaultImageModel?: string;
|
||||
defaultSpeechModel?: string;
|
||||
defaultOmniModel?: string;
|
||||
accessKeyId?: string;
|
||||
accessKeySecret?: string;
|
||||
workspaceId?: string;
|
||||
consoleSite?: "domestic" | "international";
|
||||
consoleRegion?: string;
|
||||
|
||||
@@ -352,42 +352,6 @@ export interface UserProfileResponse {
|
||||
};
|
||||
}
|
||||
|
||||
// ---- Knowledge Retrieve (Bailian Cloud API) ----
|
||||
|
||||
export interface KnowledgeRetrieveRequest {
|
||||
IndexId: string;
|
||||
Query: string;
|
||||
DenseSimilarityTopK?: number;
|
||||
SparseSimilarityTopK?: number;
|
||||
EnableReranking?: boolean;
|
||||
EnableRewrite?: boolean;
|
||||
RerankTopN?: number;
|
||||
TopK?: number;
|
||||
Rerank?: Array<{
|
||||
ModelName?: string;
|
||||
RerankMode?: string;
|
||||
RerankInstruct?: string;
|
||||
}>;
|
||||
RerankTopN_legacy?: number;
|
||||
SearchFilters?: Array<{
|
||||
Key: string;
|
||||
Value: string;
|
||||
Operator: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface KnowledgeRetrieveResponse {
|
||||
Success: boolean;
|
||||
RequestId: string;
|
||||
Data: {
|
||||
Nodes: Array<{
|
||||
Text: string;
|
||||
Score: number;
|
||||
Metadata: Record<string, unknown>;
|
||||
}>;
|
||||
};
|
||||
}
|
||||
|
||||
// ---- Knowledge Retrieve (DashScope protocol — snake_case) ----
|
||||
|
||||
export interface DashScopeKnowledgeRetrieveRequest {
|
||||
|
||||
@@ -30,8 +30,6 @@ export type {
|
||||
DashScopeVideoEditRequest,
|
||||
DashScopeVideoRefRequest,
|
||||
DashScopeVideoRequest,
|
||||
KnowledgeRetrieveRequest,
|
||||
KnowledgeRetrieveResponse,
|
||||
MemoryAddRequest,
|
||||
MemoryAddResponse,
|
||||
MemoryMessage,
|
||||
|
||||
@@ -55,7 +55,7 @@ Do not guess flags — use the reference files or `--help`.
|
||||
| Bailian agent / workflow | `bl app call` | Needs `--app-id` |
|
||||
| Find app by name | `bl app list` then `bl app call` | Console auth |
|
||||
| Memory CRUD / profile | `bl memory *` | [`reference/memory.md`](reference/memory.md) |
|
||||
| Knowledge RAG | `bl knowledge retrieve` | RAM AK/SK + index ID |
|
||||
| Knowledge RAG | `bl knowledge retrieve` | API key + index ID |
|
||||
| Upload file to temp OSS | `bl file upload` | When you need `oss://` URL explicitly |
|
||||
| Model selection / recommendation | `bl advisor recommend` | Intent → candidate recall → LLM ranking |
|
||||
| MCP tool discovery / call | `bl mcp list` / `tools` / `call` | Bailian MCP marketplace |
|
||||
|
||||
@@ -25,8 +25,8 @@ Index: [index.md](index.md)
|
||||
#### Flags
|
||||
|
||||
| Flag | Type | Required | Description |
|
||||
| ----------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `--key <key>` | string | yes | Config key (base*url, output, output_dir, timeout, api_key, access_token, default*\*\_model, access_key_id, access_key_secret, workspace_id) |
|
||||
| ----------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------- |
|
||||
| `--key <key>` | string | yes | Config key (base*url, output, output_dir, timeout, api_key, access_token, default*\*\_model, workspace_id) |
|
||||
| `--value <value>` | string | yes | Value to set |
|
||||
|
||||
#### Examples
|
||||
|
||||
@@ -24,7 +24,7 @@ Index: [index.md](index.md)
|
||||
#### Flags
|
||||
|
||||
| Flag | Type | Required | Description |
|
||||
| ------------------------------- | ------ | -------- | ------------------------------------------------------------ |
|
||||
| ------------------------------- | ------ | -------- | -------------------------------------------------- |
|
||||
| `--index-id <id>` | string | yes | Knowledge base index ID (required) |
|
||||
| `--query <text>` | string | yes | Search query (required) |
|
||||
| `--dense-similarity-top-k <n>` | number | no | Dense retrieval top K |
|
||||
@@ -35,14 +35,6 @@ Index: [index.md](index.md)
|
||||
| `--rerank-mode <mode>` | string | no | Rerank mode: qa, similar, or custom |
|
||||
| `--rerank-instruct <text>` | string | no | Custom rerank instruction, when mode=custom |
|
||||
| `--top-k <n>` | number | no | Number of results (deprecated, use --rerank-top-n) |
|
||||
| `--workspace-id <id>` | string | no | Bailian workspace ID (only needed for deprecated AK/SK auth) |
|
||||
| `--access-key-id <key>` | string | no | Deprecated: use global --api-key instead |
|
||||
| `--access-key-secret <key>` | string | no | Deprecated: use global --api-key instead |
|
||||
|
||||
#### Notes
|
||||
|
||||
- Authentication: pass `--api-key <key>`. AK/SK auth is deprecated and will be removed in a future version.
|
||||
- `--workspace-id` is NOT required when using --api-key.
|
||||
|
||||
#### Examples
|
||||
|
||||
@@ -51,5 +43,5 @@ bl knowledge retrieve --index-id idx_xxx --query "How to use Alibaba Cloud Baili
|
||||
```
|
||||
|
||||
```bash
|
||||
bl knowledge retrieve --api-key $DASHSCOPE_API_KEY --index-id idx_xxx --query "RAG retrieval" --rerank --rerank-model qwen3-rerank-hybrid
|
||||
bl knowledge retrieve --index-id idx_xxx --query "RAG retrieval" --rerank --rerank-model qwen3-rerank-hybrid
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user