@ynhcj/xiaoyi-channel 0.0.73-beta → 0.0.75-beta
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/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk";
|
|
2
2
|
import { xyPlugin } from "./src/channel.js";
|
|
3
|
+
import { xiaoyiProvider } from "./src/provider.js";
|
|
3
4
|
import { setXYRuntime } from "./src/runtime.js";
|
|
4
5
|
import { tryInjectSteer } from "./src/steer-injector.js";
|
|
5
6
|
import { callCsplApi } from "./src/cspl/call-api.js";
|
|
@@ -18,6 +19,7 @@ const plugin = {
|
|
|
18
19
|
register(api) {
|
|
19
20
|
setXYRuntime(api.runtime);
|
|
20
21
|
api.registerChannel({ plugin: xyPlugin });
|
|
22
|
+
api.registerProvider(xiaoyiProvider);
|
|
21
23
|
// CSPL after_tool_call hook: 监听工具结果,发送至 CSPL API 进行安全检测
|
|
22
24
|
// 如果响应为 REJECT,注入 steer 消息中止当前对话
|
|
23
25
|
api.on("after_tool_call", async (event, ctx) => {
|
package/dist/src/provider.js
CHANGED
|
@@ -4,12 +4,9 @@ import { getCurrentSessionContext } from "./tools/session-manager.js";
|
|
|
4
4
|
* Correspond to the three fields written to .xiaoyiruntime:
|
|
5
5
|
* TASK_ID, SESSION_ID, CONVERSATION_ID
|
|
6
6
|
*/
|
|
7
|
-
const
|
|
7
|
+
const HEADER_TRACE_ID = "x-hag-trace-id";
|
|
8
8
|
const HEADER_SESSION_ID = "x-session-id";
|
|
9
|
-
const
|
|
10
|
-
const EXTRA_PARAM_TASK_ID = "x-task-id";
|
|
11
|
-
const EXTRA_PARAM_SESSION_ID = "x-session-id";
|
|
12
|
-
const EXTRA_PARAM_CONVERSATION_ID = "x-conversation-id";
|
|
9
|
+
const HEADER_INTERACTION_ID = "x-interaction-id";
|
|
13
10
|
/**
|
|
14
11
|
* Encode uid to base64 and take first 32 chars.
|
|
15
12
|
*/
|
|
@@ -27,6 +24,7 @@ export const xiaoyiProvider = {
|
|
|
27
24
|
label: "Xiaoyi Provider",
|
|
28
25
|
docsPath: "/providers/models",
|
|
29
26
|
auth: [],
|
|
27
|
+
isCacheTtlEligible: () => true,
|
|
30
28
|
/**
|
|
31
29
|
* Inject dynamic session params into extraParams so they flow
|
|
32
30
|
* through to wrapStreamFn's ctx.extraParams.
|
|
@@ -39,11 +37,14 @@ export const xiaoyiProvider = {
|
|
|
39
37
|
prepareExtraParams: (ctx) => {
|
|
40
38
|
const sessionCtx = getCurrentSessionContext();
|
|
41
39
|
if (sessionCtx) {
|
|
40
|
+
const taskId = sessionCtx.taskId;
|
|
41
|
+
const sessionId = taskId.split("&")[0];
|
|
42
|
+
const interactionId = taskId.split("&")[1] || "";
|
|
42
43
|
return {
|
|
43
44
|
...ctx.extraParams,
|
|
44
|
-
[
|
|
45
|
-
[
|
|
46
|
-
[
|
|
45
|
+
[HEADER_TRACE_ID]: taskId,
|
|
46
|
+
[HEADER_SESSION_ID]: sessionId,
|
|
47
|
+
[HEADER_INTERACTION_ID]: interactionId,
|
|
47
48
|
};
|
|
48
49
|
}
|
|
49
50
|
// Fallback: uid-based values
|
|
@@ -55,9 +56,9 @@ export const xiaoyiProvider = {
|
|
|
55
56
|
const fallbackValue = `${prefix}_${ts}`;
|
|
56
57
|
return {
|
|
57
58
|
...ctx.extraParams,
|
|
58
|
-
[
|
|
59
|
-
[
|
|
60
|
-
[
|
|
59
|
+
[HEADER_TRACE_ID]: fallbackValue,
|
|
60
|
+
[HEADER_SESSION_ID]: fallbackValue,
|
|
61
|
+
[HEADER_INTERACTION_ID]: fallbackValue,
|
|
61
62
|
};
|
|
62
63
|
},
|
|
63
64
|
/**
|
|
@@ -73,25 +74,24 @@ export const xiaoyiProvider = {
|
|
|
73
74
|
return underlying;
|
|
74
75
|
const dynamicHeaders = {};
|
|
75
76
|
if (ctx.extraParams) {
|
|
76
|
-
const
|
|
77
|
-
const sessionId = ctx.extraParams[
|
|
78
|
-
const
|
|
79
|
-
if (typeof
|
|
80
|
-
dynamicHeaders[
|
|
77
|
+
const traceId = ctx.extraParams[HEADER_TRACE_ID];
|
|
78
|
+
const sessionId = ctx.extraParams[HEADER_SESSION_ID];
|
|
79
|
+
const interactionId = ctx.extraParams[HEADER_INTERACTION_ID];
|
|
80
|
+
if (typeof traceId === "string")
|
|
81
|
+
dynamicHeaders[HEADER_TRACE_ID] = traceId;
|
|
81
82
|
if (typeof sessionId === "string")
|
|
82
83
|
dynamicHeaders[HEADER_SESSION_ID] = sessionId;
|
|
83
|
-
if (typeof
|
|
84
|
-
dynamicHeaders[
|
|
84
|
+
if (typeof interactionId === "string")
|
|
85
|
+
dynamicHeaders[HEADER_INTERACTION_ID] = interactionId;
|
|
85
86
|
}
|
|
86
87
|
if (Object.keys(dynamicHeaders).length === 0)
|
|
87
88
|
return underlying;
|
|
88
89
|
return async (model, context, options) => {
|
|
89
90
|
// 记录输入
|
|
90
|
-
console.log(`[xiaoyiprovider] input messages count: ${context.messages
|
|
91
|
+
console.log(`[xiaoyiprovider] input messages count: ${context.messages?.length ?? 0}`);
|
|
91
92
|
if (context.systemPrompt) {
|
|
92
93
|
console.log(`[xiaoyiprovider] system prompt length: ${context.systemPrompt.length}`);
|
|
93
94
|
}
|
|
94
|
-
console.log(`[xiaoyiprovider] headers: ${JSON.stringify(dynamicHeaders)}`);
|
|
95
95
|
const stream = await underlying(model, context, {
|
|
96
96
|
...options,
|
|
97
97
|
headers: {
|
|
@@ -100,7 +100,7 @@ export const xiaoyiProvider = {
|
|
|
100
100
|
},
|
|
101
101
|
});
|
|
102
102
|
// 异步监听输出(不阻塞 stream 返回)
|
|
103
|
-
stream.result().then((
|
|
103
|
+
stream.result().then((err) => console.log(`[xiaoyiprovider] error: ${err}`));
|
|
104
104
|
return stream;
|
|
105
105
|
};
|
|
106
106
|
},
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getXYWebSocketManager } from "../client.js";
|
|
2
2
|
import { sendCommand } from "../formatter.js";
|
|
3
3
|
import { getCurrentSessionContext } from "./session-manager.js";
|
|
4
|
+
import { XYFileUploadService } from "../file-upload.js";
|
|
4
5
|
/**
|
|
5
6
|
* Duck-typed ToolInputError: openclaw 按 .name 字段匹配,不用 instanceof。
|
|
6
7
|
* 抛出此错误会让 openclaw 返回 HTTP 400 而非 500,
|
|
@@ -36,7 +37,7 @@ export const xiaoyiAddCollectionTool = {
|
|
|
36
37
|
},
|
|
37
38
|
uri: {
|
|
38
39
|
type: "string",
|
|
39
|
-
description: "必填字段(IMAGE/FILE
|
|
40
|
+
description: "必填字段(IMAGE/FILE类型时)。图片或文件的地址链接。",
|
|
40
41
|
},
|
|
41
42
|
sourceAppBundleName: {
|
|
42
43
|
type: "string",
|
|
@@ -70,6 +71,15 @@ export const xiaoyiAddCollectionTool = {
|
|
|
70
71
|
const { config, sessionId, taskId, messageId } = sessionContext;
|
|
71
72
|
// Get WebSocket manager
|
|
72
73
|
const wsManager = getXYWebSocketManager(config);
|
|
74
|
+
// Handle uri: upload local paths to get public URL
|
|
75
|
+
let publicUri = uri;
|
|
76
|
+
if (uri && !uri.startsWith("http://") && !uri.startsWith("https://") && !uri.startsWith("file://")) {
|
|
77
|
+
const uploadService = new XYFileUploadService(config.fileUploadUrl, config.apiKey, config.uid);
|
|
78
|
+
publicUri = await uploadService.uploadFileAndGetUrl(uri);
|
|
79
|
+
if (!publicUri) {
|
|
80
|
+
throw new Error("本地文件上传失败,无法获取公网URL");
|
|
81
|
+
}
|
|
82
|
+
}
|
|
73
83
|
// Build intentParam
|
|
74
84
|
const intentParam = {
|
|
75
85
|
dataType,
|
|
@@ -77,8 +87,8 @@ export const xiaoyiAddCollectionTool = {
|
|
|
77
87
|
if (content) {
|
|
78
88
|
intentParam.content = content;
|
|
79
89
|
}
|
|
80
|
-
if (
|
|
81
|
-
intentParam.uri =
|
|
90
|
+
if (publicUri) {
|
|
91
|
+
intentParam.uri = publicUri;
|
|
82
92
|
}
|
|
83
93
|
if (sourceAppBundleName) {
|
|
84
94
|
intentParam.sourceAppBundleName = sourceAppBundleName;
|
package/openclaw.plugin.json
CHANGED