@ynhcj/xiaoyi-channel 0.0.78-beta → 0.0.79-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
@@ -20,13 +20,13 @@ const plugin = {
20
20
  setXYRuntime(api.runtime);
21
21
  api.registerChannel({ plugin: xyPlugin });
22
22
  api.registerProvider(xiaoyiProvider);
23
- // CSPL after_tool_call hook: 监听工具结果,发送至 CSPL API 进行安全检测
23
+ // SENTINEL HOOK after_tool_call hook: 监听工具结果,发送至安全检测 API 进行安全检测
24
24
  // 如果响应为 REJECT,注入 steer 消息中止当前对话
25
25
  api.on("after_tool_call", async (event, ctx) => {
26
26
  if (!ALLOWED_TOOLS.includes(event.toolName)) {
27
27
  return;
28
28
  }
29
- console.log(`[CSPL] after_tool_call triggered: toolName=${event.toolName}, sessionKey=${ctx.sessionKey ?? "none"}`);
29
+ console.log(`[SENTINEL HOOK] after_tool_call triggered: toolName=${event.toolName}, sessionKey=${ctx.sessionKey ?? "none"}`);
30
30
  try {
31
31
  const resultText = extractResultText(event, event.toolName);
32
32
  const resultLength = resultText.length;
@@ -35,6 +35,7 @@ const plugin = {
35
35
  }
36
36
  // 构造 sentinel_hook 格式的 payload: { tool, output: [{ content }] }
37
37
  const questionText = {
38
+ subSceneID: 'TOOL_OUTPUT',
38
39
  tool: event.toolName,
39
40
  output: [{ content: "" }],
40
41
  };
@@ -49,13 +50,13 @@ const plugin = {
49
50
  }
50
51
  const response = await callCsplApi(finalJson, api.config);
51
52
  const result = parseSecurityResult(response);
52
- console.log(`[CSPL] Security result: status=${result.status}`);
53
+ console.log(`[SENTINEL HOOK] Security result: status=${result.status}`);
53
54
  if (result.status === "REJECT") {
54
55
  await tryInjectSteer(ctx.sessionKey, STEER_ABORT_MESSAGE);
55
56
  }
56
57
  }
57
58
  catch (err) {
58
- api.logger.error(`[CSPL] after_tool_call error: ${err}`);
59
+ api.logger.error(`[SENTINEL HOOK] after_tool_call error: ${err}`);
59
60
  }
60
61
  });
61
62
  },
@@ -1,4 +1,4 @@
1
- // CSPL API 请求模块
1
+ // SENTINEL HOOK API 请求模块
2
2
  import https from "node:https";
3
3
  import { URL } from "node:url";
4
4
  import { randomBytes } from "node:crypto";
@@ -8,8 +8,10 @@ function generateTraceId() {
8
8
  return randomBytes(16).toString("hex");
9
9
  }
10
10
  function buildHeaders(config) {
11
+ const traceId = generateTraceId();
12
+ console.log(`[SENTINEL HOOK] trace-id: ${traceId}`);
11
13
  return {
12
- "x-hag-trace-id": generateTraceId(),
14
+ "x-hag-trace-id": traceId,
13
15
  "x-uid": config.uid,
14
16
  "x-api-key": config.apiKey,
15
17
  "x-request-from": config.requestFrom,
@@ -30,13 +32,13 @@ function buildRequestOptions(url, headers, timeout) {
30
32
  }
31
33
  function parseResponse(data) {
32
34
  if (!data?.trim())
33
- throw new Error("[CSPL] API response is empty");
35
+ throw new Error("[SENTINEL HOOK] API response is empty");
34
36
  const json = JSON.parse(data);
35
37
  if (json.retCode && json.retCode !== "0") {
36
- throw new Error(`[CSPL] API error: ${json.retMsg || "unknown"}`);
38
+ throw new Error(`[SENTINEL HOOK] API error: ${json.retMsg || "unknown"}`);
37
39
  }
38
40
  if (!json.retCode && json.code) {
39
- throw new Error(`[CSPL] Backend error: ${json.desc || "unknown"}`);
41
+ throw new Error(`[SENTINEL HOOK] Backend error: ${json.desc || "unknown"}`);
40
42
  }
41
43
  return json;
42
44
  }
@@ -47,12 +49,13 @@ export async function callCsplApi(questionText, cfg) {
47
49
  questionText,
48
50
  textSource: config.textSource,
49
51
  action: config.action,
52
+ extra: JSON.stringify({ userId: config.uid }),
50
53
  };
51
54
  return new Promise((resolve, reject) => {
52
55
  const options = buildRequestOptions(config.api.url, headers, config.api.timeout);
53
56
  const req = https.request(options, (res) => {
54
57
  if (res.statusCode && res.statusCode >= HTTP_STATUS_BAD_REQUEST) {
55
- reject(new Error(`[CSPL] HTTP error: ${res.statusCode}`));
58
+ reject(new Error(`[SENTINEL HOOK] HTTP error: ${res.statusCode}`));
56
59
  return;
57
60
  }
58
61
  let data = "";
@@ -62,23 +65,23 @@ export async function callCsplApi(questionText, cfg) {
62
65
  res.on("end", () => {
63
66
  try {
64
67
  const result = parseResponse(data);
65
- console.log(`[CSPL API] ✅ 请求成功`);
68
+ console.log(`[SENTINEL HOOK] ✅ 请求成功`);
66
69
  resolve(result);
67
70
  }
68
71
  catch (e) {
69
- console.error(`[CSPL API] ❌ 请求失败: ${e instanceof Error ? e.message : String(e)}`);
72
+ console.error(`[SENTINEL HOOK] ❌ 请求失败: ${e instanceof Error ? e.message : String(e)}`);
70
73
  reject(e);
71
74
  }
72
75
  });
73
76
  });
74
77
  req.on("error", (error) => {
75
- console.error(`[CSPL API] ❌ 请求错误: ${error instanceof Error ? error.message : String(error)}`);
78
+ console.error(`[SENTINEL HOOK] ❌ 请求错误: ${error instanceof Error ? error.message : String(error)}`);
76
79
  reject(error);
77
80
  });
78
81
  req.on("timeout", () => {
79
- console.error(`[CSPL API] ⏰ 请求超时 (${config.api.timeout}ms)`);
82
+ console.error(`[SENTINEL HOOK] ⏰ 请求超时 (${config.api.timeout}ms)`);
80
83
  req.destroy();
81
- reject(new Error("[CSPL] Request timeout"));
84
+ reject(new Error("[SENTINEL HOOK] Request timeout"));
82
85
  });
83
86
  req.write(JSON.stringify(payload));
84
87
  req.end();
@@ -7,7 +7,7 @@ import { logger } from "../utils/logger.js";
7
7
  let cachedConfig = null;
8
8
  function readServiceUrl() {
9
9
  if (!fs.existsSync(ENV_FILE_PATH)) {
10
- throw new Error(`[CSPL] Environment file not found: ${ENV_FILE_PATH}`);
10
+ throw new Error(`[SENTINEL HOOK] Environment file not found: ${ENV_FILE_PATH}`);
11
11
  }
12
12
  const envData = fs.readFileSync(ENV_FILE_PATH, "utf-8");
13
13
  for (const line of envData.split("\n")) {
@@ -22,7 +22,7 @@ function readServiceUrl() {
22
22
  if (key === "SERVICE_URL" && value)
23
23
  return value;
24
24
  }
25
- throw new Error("[CSPL] Missing SERVICE_URL in env file");
25
+ throw new Error("[SENTINEL HOOK] Missing SERVICE_URL in env file");
26
26
  }
27
27
  /**
28
28
  * 构建 CSPL 配置。uid 和 apiKey 复用 XYChannelConfig,避免重复配置。
@@ -45,6 +45,6 @@ export function getCsplConfig(cfg) {
45
45
  textSource: CSPL_STATIC_CONFIG.textSource,
46
46
  action: CSPL_STATIC_CONFIG.action,
47
47
  };
48
- logger.log("[CSPL] Config loaded (uid/apiKey from XYChannelConfig)");
48
+ logger.log("[SENTINEL HOOK] Config loaded (uid/apiKey from XYChannelConfig)");
49
49
  return cachedConfig;
50
50
  }
@@ -10,6 +10,7 @@ export interface ApiPayload {
10
10
  questionText: string;
11
11
  textSource: string;
12
12
  action: string;
13
+ extra: string;
13
14
  }
14
15
  export interface ApiResponse {
15
16
  data?: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ynhcj/xiaoyi-channel",
3
- "version": "0.0.78-beta",
3
+ "version": "0.0.79-beta",
4
4
  "description": "OpenClaw Xiaoyi Channel plugin - Xiaoyi A2A protocol integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",