@infimind-next/ai-hive-mcp 0.4.2 → 0.5.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.md +16 -8
- package/dist/api-client.d.ts +8 -2
- package/dist/api-client.js +64 -16
- package/dist/config.d.ts +6 -0
- package/dist/config.js +47 -0
- package/dist/index.js +0 -0
- package/dist/managed-config.js +5 -4
- package/dist/managed-download.d.ts +5 -0
- package/dist/managed-download.js +18 -12
- package/dist/managed-files.d.ts +25 -1
- package/dist/managed-files.js +98 -26
- package/dist/managed-images.d.ts +65 -21
- package/dist/managed-images.js +148 -60
- package/dist/managed-server.js +71 -36
- package/dist/model-response.d.ts +831 -0
- package/dist/model-response.js +296 -0
- package/dist/package-version.d.ts +1 -0
- package/dist/package-version.js +1 -0
- package/dist/rest-commands.js +33 -12
- package/dist/schemas.d.ts +14 -7
- package/dist/schemas.js +3 -8
- package/dist/server.d.ts +1 -1
- package/dist/server.js +29 -17
- package/dist/setup/run-setup.js +126 -7
- package/dist/user-notices.d.ts +44 -0
- package/dist/user-notices.js +39 -21
- package/package.json +8 -9
- package/skills/ai-hive-billing/SKILL.md +2 -0
- package/skills/ai-hive-image-video-generation/SKILL.md +2 -0
- package/skills/ai-hive-media-upload/SKILL.md +2 -0
- package/skills/ai-hive-model-selection/SKILL.md +7 -4
- package/skills/ai-hive-text-generation/SKILL.md +3 -1
package/dist/setup/run-setup.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
import { chmod, mkdir, readFile, rename, stat, unlink, writeFile, } from "node:fs/promises";
|
|
3
|
-
import { basename, dirname, join } from "node:path";
|
|
3
|
+
import { basename, dirname, isAbsolute, join, relative, resolve, sep, } from "node:path";
|
|
4
4
|
import { detectTarget } from "./detect.js";
|
|
5
5
|
import { mergeJsonMcpServers, mergeOpenCodeServer, readJsonServerEnv, upsertCodexServer, } from "./merge.js";
|
|
6
6
|
import { readBundledSkills } from "./skills.js";
|
|
@@ -127,7 +127,11 @@ async function detectAll(targets, dependencies) {
|
|
|
127
127
|
}
|
|
128
128
|
function buildServerEnv(config, key) {
|
|
129
129
|
return {
|
|
130
|
-
...(key
|
|
130
|
+
...(key
|
|
131
|
+
? { AI_HIVE_MCP_KEY: key }
|
|
132
|
+
: {
|
|
133
|
+
AI_HIVE_WORKBUDDY_CREDENTIALS_FILE: resolve(config.credentialsFile),
|
|
134
|
+
}),
|
|
131
135
|
...(config.endpointExplicit
|
|
132
136
|
? { AI_HIVE_API_ENDPOINT: config.endpoint }
|
|
133
137
|
: {}),
|
|
@@ -245,7 +249,8 @@ async function configureClaudeCode(input) {
|
|
|
245
249
|
};
|
|
246
250
|
}
|
|
247
251
|
// 重复执行时 claude 会因为同名服务器报错; 先移除再添加, 保证 setup 可重复运行.
|
|
248
|
-
const runner = input.dependencies.runCommand ??
|
|
252
|
+
const runner = input.dependencies.runCommand ??
|
|
253
|
+
((command, args) => defaultRunner(command, args, input.dependencies));
|
|
249
254
|
await runner("claude", ["mcp", "remove", MCP_SERVER_NAME, "--scope", "user"]);
|
|
250
255
|
const result = await runner("claude", args);
|
|
251
256
|
if (!result.ok) {
|
|
@@ -270,15 +275,129 @@ function maskedCommand(args) {
|
|
|
270
275
|
.map((part) => part.startsWith("AI_HIVE_MCP_KEY=") ? "AI_HIVE_MCP_KEY=***" : part)
|
|
271
276
|
.join(" ");
|
|
272
277
|
}
|
|
273
|
-
async function defaultRunner(command, args) {
|
|
274
|
-
const
|
|
278
|
+
async function defaultRunner(command, args, input) {
|
|
279
|
+
const executable = input.platform === "win32"
|
|
280
|
+
? await resolveWindowsCommand(command, input.env)
|
|
281
|
+
: { command, prefix: [] };
|
|
282
|
+
if (!executable)
|
|
283
|
+
return { ok: false };
|
|
284
|
+
const result = spawnSync(executable.command, [...executable.prefix, ...args], {
|
|
275
285
|
stdio: "ignore",
|
|
276
|
-
|
|
277
|
-
shell:
|
|
286
|
+
env: input.env,
|
|
287
|
+
shell: false,
|
|
278
288
|
timeout: 30_000,
|
|
279
289
|
});
|
|
280
290
|
return { ok: result.status === 0 };
|
|
281
291
|
}
|
|
292
|
+
async function resolveWindowsCommand(command, env) {
|
|
293
|
+
const pathKey = Object.keys(env)
|
|
294
|
+
.sort()
|
|
295
|
+
.find((key) => key.toLowerCase() === "path");
|
|
296
|
+
const pathExtKey = Object.keys(env)
|
|
297
|
+
.sort()
|
|
298
|
+
.find((key) => key.toLowerCase() === "pathext");
|
|
299
|
+
const extensions = (pathExtKey ? env[pathExtKey] : undefined)?.split(";") ?? [
|
|
300
|
+
".com",
|
|
301
|
+
".exe",
|
|
302
|
+
".bat",
|
|
303
|
+
".cmd",
|
|
304
|
+
];
|
|
305
|
+
for (const rawDirectory of (pathKey ? (env[pathKey] ?? "") : "").split(";")) {
|
|
306
|
+
const directory = rawDirectory.replace(/^"(.*)"$/, "$1");
|
|
307
|
+
if (!directory)
|
|
308
|
+
continue;
|
|
309
|
+
for (const rawExtension of extensions) {
|
|
310
|
+
const extension = rawExtension.toLowerCase();
|
|
311
|
+
if (![".exe", ".com", ".cmd", ".bat"].includes(extension))
|
|
312
|
+
continue;
|
|
313
|
+
const file = join(directory, `${command}${extension}`);
|
|
314
|
+
if (!(await stat(file).catch(() => null))?.isFile())
|
|
315
|
+
continue;
|
|
316
|
+
if (extension === ".exe" || extension === ".com") {
|
|
317
|
+
return { command: file, prefix: [] };
|
|
318
|
+
}
|
|
319
|
+
// 凭据路径不能交给 cmd 解释; npm shim 只用于定位同一安装的真实入口.
|
|
320
|
+
const packageRoot = join(directory, "node_modules/@anthropic-ai/claude-code");
|
|
321
|
+
try {
|
|
322
|
+
const metadata = JSON.parse(await readFile(join(packageRoot, "package.json"), "utf8"));
|
|
323
|
+
const bin = typeof metadata.bin === "string"
|
|
324
|
+
? metadata.bin
|
|
325
|
+
: metadata.bin?.[command];
|
|
326
|
+
if (metadata.name !== "@anthropic-ai/claude-code" ||
|
|
327
|
+
typeof bin !== "string")
|
|
328
|
+
return null;
|
|
329
|
+
const entry = resolve(packageRoot, bin);
|
|
330
|
+
const local = relative(packageRoot, entry);
|
|
331
|
+
if (local === ".." ||
|
|
332
|
+
local.startsWith(`..${sep}`) ||
|
|
333
|
+
isAbsolute(local) ||
|
|
334
|
+
!(await stat(entry)).isFile())
|
|
335
|
+
return null;
|
|
336
|
+
const javascript = /\.(?:c|m)?js$/i.test(entry);
|
|
337
|
+
if (!javascript && !/\.(?:exe|com)$/i.test(entry))
|
|
338
|
+
return null;
|
|
339
|
+
// 邻接官方包不能证明 wrapper 没有自定义账号环境或参数, 必须同时校验 shim 本身.
|
|
340
|
+
if (!isStandardNpmShim(await readFile(file, "utf8"), relative(directory, entry).replaceAll("/", "\\"), javascript))
|
|
341
|
+
return null;
|
|
342
|
+
return javascript
|
|
343
|
+
? { command: process.execPath, prefix: [entry] }
|
|
344
|
+
: { command: entry, prefix: [] };
|
|
345
|
+
}
|
|
346
|
+
catch {
|
|
347
|
+
// 已命中的 shim 无法安全解析时停止, 不切到 PATH 中另一份客户端安装.
|
|
348
|
+
}
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
function isStandardNpmShim(source, target, javascript) {
|
|
355
|
+
const lines = source
|
|
356
|
+
.replaceAll("\r\n", "\n")
|
|
357
|
+
.trim()
|
|
358
|
+
.split("\n")
|
|
359
|
+
.map((line) => line.trim().replace(/[ \t]+(?=%\*$)/, " "))
|
|
360
|
+
.filter(Boolean);
|
|
361
|
+
const head = [
|
|
362
|
+
"@ECHO off",
|
|
363
|
+
"GOTO start",
|
|
364
|
+
":find_dp0",
|
|
365
|
+
"SET dp0=%~dp0",
|
|
366
|
+
"EXIT /b",
|
|
367
|
+
":start",
|
|
368
|
+
"SETLOCAL",
|
|
369
|
+
"CALL :find_dp0",
|
|
370
|
+
];
|
|
371
|
+
const nodeBranch = [
|
|
372
|
+
'IF EXIST "%dp0%\\node.exe" (',
|
|
373
|
+
'SET "_prog=%dp0%\\node.exe"',
|
|
374
|
+
") ELSE (",
|
|
375
|
+
'SET "_prog=node"',
|
|
376
|
+
];
|
|
377
|
+
const finish = "endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & ";
|
|
378
|
+
const invoke = `"%_prog%" "%dp0%\\${target}" %*`;
|
|
379
|
+
// npm cmd-shim 8 与 9 将 PATHEXT 放在不同位置, 只接受已实测生成的两种标准结构.
|
|
380
|
+
const bodies = javascript
|
|
381
|
+
? [
|
|
382
|
+
[
|
|
383
|
+
...nodeBranch,
|
|
384
|
+
"SET PATHEXT=%PATHEXT:;.JS;=;%",
|
|
385
|
+
")",
|
|
386
|
+
`${finish}${invoke}`,
|
|
387
|
+
],
|
|
388
|
+
[
|
|
389
|
+
...nodeBranch,
|
|
390
|
+
")",
|
|
391
|
+
`${finish}set PATHEXT=%PATHEXT:;.JS;=;% & ${invoke}`,
|
|
392
|
+
],
|
|
393
|
+
]
|
|
394
|
+
: [[`"%dp0%\\${target}" %*`]];
|
|
395
|
+
return bodies.some((body) => {
|
|
396
|
+
const expected = [...head, ...body];
|
|
397
|
+
return (lines.length === expected.length &&
|
|
398
|
+
lines.every((line, index) => line === expected[index]));
|
|
399
|
+
});
|
|
400
|
+
}
|
|
282
401
|
async function installSkills(input) {
|
|
283
402
|
const errors = [];
|
|
284
403
|
let changed = 0;
|
package/dist/user-notices.d.ts
CHANGED
|
@@ -1,3 +1,47 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const noticeSchema: z.ZodObject<{
|
|
3
|
+
id: z.ZodString;
|
|
4
|
+
revision: z.ZodString;
|
|
5
|
+
kind: z.ZodEnum<["RECHARGE_PROMOTION", "ANNOUNCEMENT"]>;
|
|
6
|
+
title: z.ZodString;
|
|
7
|
+
message: z.ZodString;
|
|
8
|
+
details: z.ZodString;
|
|
9
|
+
expiresAt: z.ZodNullable<z.ZodString>;
|
|
10
|
+
action: z.ZodOptional<z.ZodObject<{
|
|
11
|
+
label: z.ZodString;
|
|
12
|
+
url: z.ZodEffects<z.ZodString, string, string>;
|
|
13
|
+
}, "strip", z.ZodTypeAny, {
|
|
14
|
+
label: string;
|
|
15
|
+
url: string;
|
|
16
|
+
}, {
|
|
17
|
+
label: string;
|
|
18
|
+
url: string;
|
|
19
|
+
}>>;
|
|
20
|
+
}, "strip", z.ZodTypeAny, {
|
|
21
|
+
id: string;
|
|
22
|
+
revision: string;
|
|
23
|
+
kind: "RECHARGE_PROMOTION" | "ANNOUNCEMENT";
|
|
24
|
+
message: string;
|
|
25
|
+
title: string;
|
|
26
|
+
details: string;
|
|
27
|
+
expiresAt: string | null;
|
|
28
|
+
action?: {
|
|
29
|
+
label: string;
|
|
30
|
+
url: string;
|
|
31
|
+
} | undefined;
|
|
32
|
+
}, {
|
|
33
|
+
id: string;
|
|
34
|
+
revision: string;
|
|
35
|
+
kind: "RECHARGE_PROMOTION" | "ANNOUNCEMENT";
|
|
36
|
+
message: string;
|
|
37
|
+
title: string;
|
|
38
|
+
details: string;
|
|
39
|
+
expiresAt: string | null;
|
|
40
|
+
action?: {
|
|
41
|
+
label: string;
|
|
42
|
+
url: string;
|
|
43
|
+
} | undefined;
|
|
44
|
+
}>;
|
|
1
45
|
export declare function toolResultContent(value: unknown): {
|
|
2
46
|
type: "text";
|
|
3
47
|
text: string;
|
package/dist/user-notices.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
// 独立 npm 包不能依赖私有 workspace, 与 contracts 的通知文本通过跨包用例校验.
|
|
3
|
-
const noticeSchema = z.object({
|
|
3
|
+
export const noticeSchema = z.object({
|
|
4
4
|
id: z.string().min(1),
|
|
5
5
|
revision: z.string().min(1),
|
|
6
6
|
kind: z.enum(["RECHARGE_PROMOTION", "ANNOUNCEMENT"]),
|
|
@@ -18,16 +18,9 @@ const noticeSchema = z.object({
|
|
|
18
18
|
})
|
|
19
19
|
.optional(),
|
|
20
20
|
});
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
Array.isArray(value) ||
|
|
25
|
-
!("userNotices" in value)) {
|
|
26
|
-
return [{ type: "text", text: JSON.stringify(value) }];
|
|
27
|
-
}
|
|
28
|
-
const { userNotices, ...businessResult } = value;
|
|
29
|
-
const notices = Array.isArray(userNotices)
|
|
30
|
-
? userNotices.flatMap((raw) => {
|
|
21
|
+
function noticeContent(value, deduplicate = false) {
|
|
22
|
+
const valid = Array.isArray(value)
|
|
23
|
+
? value.flatMap((raw) => {
|
|
31
24
|
const parsed = noticeSchema.safeParse(raw);
|
|
32
25
|
return parsed.success &&
|
|
33
26
|
(parsed.data.expiresAt === null ||
|
|
@@ -36,17 +29,42 @@ export function toolResultContent(value) {
|
|
|
36
29
|
: [];
|
|
37
30
|
})
|
|
38
31
|
: [];
|
|
32
|
+
const notices = deduplicate
|
|
33
|
+
? [
|
|
34
|
+
...new Map(valid.map((notice) => [`${notice.id}:${notice.revision}`, notice])).values(),
|
|
35
|
+
]
|
|
36
|
+
: valid;
|
|
37
|
+
return notices.map((notice) => ({
|
|
38
|
+
type: "text",
|
|
39
|
+
text: [
|
|
40
|
+
`${notice.title}:${notice.message}`,
|
|
41
|
+
...(notice.action
|
|
42
|
+
? [`${notice.action.label}:${notice.action.url}`]
|
|
43
|
+
: []),
|
|
44
|
+
...(notice.details ? [`充值档位:\n${notice.details}`] : []),
|
|
45
|
+
].join("\n"),
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
export function toolResultContent(value) {
|
|
49
|
+
if (value &&
|
|
50
|
+
typeof value === "object" &&
|
|
51
|
+
!Array.isArray(value) &&
|
|
52
|
+
"schemaVersion" in value &&
|
|
53
|
+
value.schemaVersion === 2 &&
|
|
54
|
+
"notices" in value) {
|
|
55
|
+
return [
|
|
56
|
+
{ type: "text", text: JSON.stringify(value) },
|
|
57
|
+
...noticeContent(value.notices, true),
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
if (!value ||
|
|
61
|
+
typeof value !== "object" ||
|
|
62
|
+
Array.isArray(value) ||
|
|
63
|
+
!("userNotices" in value))
|
|
64
|
+
return [{ type: "text", text: JSON.stringify(value) }];
|
|
65
|
+
const { userNotices, ...businessResult } = value;
|
|
39
66
|
return [
|
|
40
67
|
{ type: "text", text: JSON.stringify(businessResult) },
|
|
41
|
-
...
|
|
42
|
-
type: "text",
|
|
43
|
-
text: [
|
|
44
|
-
`${notice.title}:${notice.message}`,
|
|
45
|
-
...(notice.action
|
|
46
|
-
? [`${notice.action.label}:${notice.action.url}`]
|
|
47
|
-
: []),
|
|
48
|
-
...(notice.details ? [`充值档位:\n${notice.details}`] : []),
|
|
49
|
-
].join("\n"),
|
|
50
|
-
})),
|
|
68
|
+
...noticeContent(userNotices),
|
|
51
69
|
];
|
|
52
70
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@infimind-next/ai-hive-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -13,13 +13,6 @@
|
|
|
13
13
|
"dist",
|
|
14
14
|
"skills"
|
|
15
15
|
],
|
|
16
|
-
"scripts": {
|
|
17
|
-
"build": "tsc -p tsconfig.json",
|
|
18
|
-
"dev": "tsc -p tsconfig.json --watch --preserveWatchOutput",
|
|
19
|
-
"lint": "eslint \"src/**/*.ts\"",
|
|
20
|
-
"prepack": "pnpm run build",
|
|
21
|
-
"test": "vitest run"
|
|
22
|
-
},
|
|
23
16
|
"dependencies": {
|
|
24
17
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
25
18
|
"file-type": "^21.3.4",
|
|
@@ -30,5 +23,11 @@
|
|
|
30
23
|
"typescript": "^5.0.0",
|
|
31
24
|
"typescript-eslint": "^8.0.0",
|
|
32
25
|
"vitest": "^3.0.0"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsc -p tsconfig.json",
|
|
29
|
+
"dev": "tsc -p tsconfig.json --watch --preserveWatchOutput",
|
|
30
|
+
"lint": "eslint \"src/**/*.ts\"",
|
|
31
|
+
"test": "vitest run"
|
|
33
32
|
}
|
|
34
|
-
}
|
|
33
|
+
}
|
|
@@ -31,3 +31,5 @@ MCP 工具:`get_billing_summary`、`list_billing_records`、`get_billing_recor
|
|
|
31
31
|
## 账户信息
|
|
32
32
|
|
|
33
33
|
需要账户资料或充值入口时用 `get_user_info`。该工具同时返回当前活动,有活动时可以把活动信息转达给用户。
|
|
34
|
+
|
|
35
|
+
新版包模型查询默认 V2。先按类型或关键词查轻目录,找到候选即可 get_model,默认读取参数和价格;已知模型 ID 直接 get_model。无需遍历所有分页,完整目录需求才读取 nextCursor。正式调用前预检并确认费用;未知提交先查原任务,不自动付费重试。
|
|
@@ -31,3 +31,5 @@ description: 把本机图片、视频、音频或文档传给蜂巢,换取可
|
|
|
31
31
|
- `complete_media_upload` 失败时不要直接拿去生成,先重试确认或重新上传。
|
|
32
32
|
- 单文件大小和格式限制以 `get_model` 返回的媒体要求为准。
|
|
33
33
|
- 不要把文件内容贴进对话文本,必须走上传换取 `mediaId`。
|
|
34
|
+
|
|
35
|
+
新版包模型查询默认 V2。先按类型或关键词查轻目录,找到候选即可 get_model,默认读取参数和价格;已知模型 ID 直接 get_model。无需遍历所有分页,完整目录需求才读取 nextCursor。正式调用前预检并确认费用;未知提交先查原任务,不自动付费重试。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ai-hive-model-selection
|
|
3
|
-
description: 在蜂巢 AI
|
|
3
|
+
description: 在蜂巢 AI 开放平台选择模型。用户要调用文字、图片或视频模型,但还没指定模型时使用;先筛选轻目录,再读取候选模型的参数和价格,避免按记忆猜参数。也可用于比较同类模型的价格和线路。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# 选择模型
|
|
@@ -14,7 +14,7 @@ description: 在蜂巢 AI 开放平台选择模型。用户要调用文字、图
|
|
|
14
14
|
|
|
15
15
|
## 步骤
|
|
16
16
|
|
|
17
|
-
1.
|
|
17
|
+
1. 按类型或关键词列出候选模型(目录每行仅 ID、名称、类型和素材模式):
|
|
18
18
|
|
|
19
19
|
```
|
|
20
20
|
ai-hive-mcp models --type IMAGE --json
|
|
@@ -27,7 +27,7 @@ description: 在蜂巢 AI 开放平台选择模型。用户要调用文字、图
|
|
|
27
27
|
- 图片:`IMAGE`
|
|
28
28
|
- 视频:`VIDEO`
|
|
29
29
|
|
|
30
|
-
3.
|
|
30
|
+
3. 找到候选即可读取 `get_model` 默认参数与价格;已知 ID 可直接读取。比较 `pricingSnapshot` 里的 `saleMicros`。这是客户实际结算价,单位是蜂蜜微单位(1,000,000 微单位 = 1 蜂蜜),不要引用 `originalMicros`。只有充值实付金额才是元。
|
|
31
31
|
4. 用 `get_model` / `ai-hive-mcp model <模型 ID> --json` 读取:
|
|
32
32
|
- 支持的 `routingModes`
|
|
33
33
|
- 参数 schema
|
|
@@ -46,5 +46,8 @@ description: 在蜂巢 AI 开放平台选择模型。用户要调用文字、图
|
|
|
46
46
|
## 失败处理
|
|
47
47
|
|
|
48
48
|
- 返回"模型不存在或当前不可用":重新列一遍模型,不要重试同一个 ID。
|
|
49
|
-
-
|
|
49
|
+
- V2 轻目录不包含价格是正常行为:使用目录返回的 `publicModelId` 调用 `get_model`,读取价格和参数后再比较,不因此判定模型不可售。
|
|
50
|
+
- `get_model` 详情价格缺失或不可用:暂停调用并核验详情的 pricing 章节与服务端状态,不自动换模型或发起生成。恢复后仍按原流程预检并确认费用。
|
|
50
51
|
- 不要猜测参数名。`get_model` 没有给出的字段一律不要传。
|
|
52
|
+
|
|
53
|
+
新版包模型查询默认 V2。先按类型或关键词查轻目录,找到候选即可 get_model,默认读取参数和价格;已知模型 ID 直接 get_model。无需遍历所有分页,完整目录需求才读取 nextCursor。正式调用前预检并确认费用;未知提交先查原任务,不自动付费重试。
|
|
@@ -20,7 +20,7 @@ ai-hive-mcp run <模型 ID> "你的提示词" --json
|
|
|
20
20
|
## 必须遵守
|
|
21
21
|
|
|
22
22
|
1. **每次付费调用都带 `clientRequestId`**,同一次业务请求重试必须复用同一个值。改参数后必须换新值,否则会被当成同一次请求去重。
|
|
23
|
-
2. `pricingSnapshot` 可选。省略时客户端会自动向服务端取当前快照;手动传时必须是 `
|
|
23
|
+
2. `pricingSnapshot` 可选。省略时客户端会自动向服务端取当前快照;手动传时必须是 `get_model` 返回的对应快照对象,且 `publicModelId`、`routingMode` 一致。
|
|
24
24
|
3. 多轮对话时把历史消息按 `system` / `user` / `assistant` 顺序传入。
|
|
25
25
|
4. 图片理解:先把图片上传为 `mediaId`(见 `ai-hive-media-upload`),再放进 `messages[].mediaIds`。
|
|
26
26
|
|
|
@@ -37,3 +37,5 @@ ai-hive-mcp run <模型 ID> "你的提示词" --json
|
|
|
37
37
|
- 给出生成结果。
|
|
38
38
|
- 结果里包含 `chargeMicros` 时,换算成蜂蜜(除以 1,000,000)告诉用户本次消费;只有充值实付金额才是元。
|
|
39
39
|
- 不要展示内部错误码或上游响应体。
|
|
40
|
+
|
|
41
|
+
新版包模型查询默认 V2。先按类型或关键词查轻目录,找到候选即可 get_model,默认读取参数和价格;已知模型 ID 直接 get_model。无需遍历所有分页,完整目录需求才读取 nextCursor。正式调用前预检并确认费用;未知提交先查原任务,不自动付费重试。
|