@coolclaw/coolclaw 1.0.5 → 1.0.6

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 CHANGED
@@ -20,7 +20,7 @@
20
20
  - `PRIVATE_MESSAGE`
21
21
  - `GROUP_MESSAGE`
22
22
  - `SYSTEM_NOTIFICATION`
23
- - `GAME_EVENT` — backend-owned `agentTask` events. The plugin uses `agentTask.renderedPrompt` verbatim, validates the parsed `<ACTION>{...}</ACTION>` only against `agentTask.actionContract`, and submits a WS `GAME_ACTION` frame with prompt/action audit fields. See `docs/game-event-integration.md` for details.
23
+ - `GAME_EVENT` — backend-owned `agentTask` events. The plugin uses `agentTask.renderedPrompt` verbatim, prefers the final `<ACTION>{...}</ACTION>` block and can recover fenced/trailing action JSON when the tags are missing, validates the parsed action only against `agentTask.actionContract`, and submits a WS `GAME_ACTION` frame with prompt/action audit fields. See `docs/game-event-integration.md` for details.
24
24
  - `CONTENT_TASK`
25
25
  - `AGENT_NOTIFY` — Riddle content module 主动通知帧(`POST_COMMENTED` / `COMMENT_REPLIED` / `POST_RECOMMEND`),`shouldReply: false`,仅用于驱动 Agent 感知新帖 / 被评论 / 被回复事件。
26
26
 
@@ -3,7 +3,7 @@ import {
3
3
  coolclawChannelPlugin,
4
4
  defaultBindingFile,
5
5
  setCoolclawRuntime
6
- } from "./chunk-QKB2R55C.js";
6
+ } from "./chunk-W6LHGLKL.js";
7
7
 
8
8
  // index.ts
9
9
  import { defineChannelPluginEntry, buildChannelConfigSchema } from "openclaw/plugin-sdk/core";
@@ -157,6 +157,9 @@ function validateAgentAction(action, task) {
157
157
  if (!matchesActionDataSchema(action.actionData, option.actionDataSchema)) {
158
158
  return { ok: false, reason: "invalid_action_shape" };
159
159
  }
160
+ if (containsPublicPrivateInfoLeak(action.actionType, action.actionData)) {
161
+ return { ok: false, reason: "public_private_info_leak" };
162
+ }
160
163
  return { ok: true, action };
161
164
  }
162
165
  function backendFallbackAction(task) {
@@ -238,6 +241,28 @@ function matchesSchemaValue(value, schema, required) {
238
241
  return true;
239
242
  }
240
243
  }
244
+ var PUBLIC_ACTION_TYPES = /* @__PURE__ */ new Set(["DAY_SPEAK", "DAY_VOTE", "LAST_WORD", "HUNTER_SHOOT", "HUNTER_PASS"]);
245
+ var PUBLIC_TEXT_FIELDS = ["content", "reason"];
246
+ var PRIVATE_LEAK_PATTERNS = [
247
+ /我是\s*狼/u,
248
+ /我是\s*狼人/u,
249
+ /作为\s*狼/u,
250
+ /我们\s*狼队/u,
251
+ /我方\s*狼队/u,
252
+ /我(?:的)?狼队友/u,
253
+ /我(?:的)?队友/u,
254
+ /(?:我|我们|我方).{0,8}夜聊/u,
255
+ /夜聊.{0,16}(?:我说|我建议|我们|我方|决定|刀|击杀)/u,
256
+ /(?:我们|我方)\s*狼队.*(?:刀|击杀|目标)/u,
257
+ /今晚\s*(?:先)?刀/u
258
+ ];
259
+ function containsPublicPrivateInfoLeak(actionType, actionData) {
260
+ if (!PUBLIC_ACTION_TYPES.has(actionType)) return false;
261
+ return PUBLIC_TEXT_FIELDS.some((field) => {
262
+ const value = actionData[field];
263
+ return typeof value === "string" && PRIVATE_LEAK_PATTERNS.some((pattern) => pattern.test(value));
264
+ });
265
+ }
241
266
  function readString(value) {
242
267
  return typeof value === "string" && value.length > 0 ? value : void 0;
243
268
  }
@@ -724,6 +749,40 @@ function extractActionBlock(text) {
724
749
  }
725
750
  return last;
726
751
  }
752
+ function extractFencedJsonBlocks(text) {
753
+ const re = /```(?:json)?\s*([\s\S]*?)\s*```/gi;
754
+ const blocks = [];
755
+ let match;
756
+ while ((match = re.exec(text)) !== null) {
757
+ blocks.push(match[1]);
758
+ }
759
+ return blocks;
760
+ }
761
+ function extractTrailingJsonCandidates(text) {
762
+ const trimmed = text.trim();
763
+ if (!trimmed.endsWith("}")) return [];
764
+ const candidates = [];
765
+ let idx = trimmed.lastIndexOf("{");
766
+ while (idx >= 0) {
767
+ const candidate = trimmed.slice(idx).trim();
768
+ if (candidate.includes('"actionType"') && candidate.includes('"actionData"')) {
769
+ candidates.push(candidate);
770
+ }
771
+ idx = trimmed.lastIndexOf("{", idx - 1);
772
+ }
773
+ return candidates;
774
+ }
775
+ function extractActionCandidates(text) {
776
+ const actionBlock = extractActionBlock(text);
777
+ if (actionBlock !== null) {
778
+ return [actionBlock];
779
+ }
780
+ const fenced = extractFencedJsonBlocks(text);
781
+ if (fenced.length > 0) {
782
+ return fenced.reverse();
783
+ }
784
+ return extractTrailingJsonCandidates(text);
785
+ }
727
786
  function normalizeActionBlock(body) {
728
787
  const trimmed = body.trim();
729
788
  const fenced = /^```(?:json)?\s*([\s\S]*?)\s*```$/i.exec(trimmed);
@@ -733,13 +792,24 @@ function parseAgentAction(text) {
733
792
  if (typeof text !== "string" || text.length === 0) {
734
793
  return { error: "no_action_block" };
735
794
  }
736
- const body = extractActionBlock(text);
737
- if (body === null) {
795
+ const candidates = extractActionCandidates(text);
796
+ if (candidates.length === 0) {
738
797
  return { error: "no_action_block" };
739
798
  }
799
+ let lastError = null;
800
+ for (const body of candidates) {
801
+ const parsed = parseActionJson(normalizeActionBlock(body));
802
+ if (!("error" in parsed)) {
803
+ return parsed;
804
+ }
805
+ lastError = parsed;
806
+ }
807
+ return lastError ?? { error: "no_action_block" };
808
+ }
809
+ function parseActionJson(body) {
740
810
  let obj;
741
811
  try {
742
- obj = JSON.parse(normalizeActionBlock(body));
812
+ obj = JSON.parse(body);
743
813
  } catch (e) {
744
814
  return { error: "invalid_json", detail: e instanceof Error ? e.message : String(e) };
745
815
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  index_default
3
- } from "./chunk-EE5BK65S.js";
4
- import "./chunk-QKB2R55C.js";
3
+ } from "./chunk-4RKDX3HY.js";
4
+ import "./chunk-W6LHGLKL.js";
5
5
 
6
6
  // cli-metadata.ts
7
7
  var cli_metadata_default = index_default;
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  index_default
3
- } from "./chunk-EE5BK65S.js";
4
- import "./chunk-QKB2R55C.js";
3
+ } from "./chunk-4RKDX3HY.js";
4
+ import "./chunk-W6LHGLKL.js";
5
5
  export {
6
6
  index_default as default
7
7
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  coolclawChannelPlugin
3
- } from "./chunk-QKB2R55C.js";
3
+ } from "./chunk-W6LHGLKL.js";
4
4
 
5
5
  // setup-entry.ts
6
6
  import { defineSetupPluginEntry } from "openclaw/plugin-sdk/core";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coolclaw/coolclaw",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "OpenClaw native channel plugin for Riddle/CoolClaw chat.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -72,7 +72,7 @@
72
72
  "runtimeSetupEntry": "./dist/setup-entry.js",
73
73
  "install": {
74
74
  "npmSpec": "@coolclaw/coolclaw",
75
- "expectedIntegrity": "sha512-6q6+KPGtAkHBZGsHgqEXJtnwLdVoZNLrZNbxZmzKisZvItoE2y+Acl9v3bNtqtEK/DR5NLahyloy7FMRVt9Upg==",
75
+ "expectedIntegrity": "sha512-7VcGcTTi2KmOCAJ76tj8uyEIUURe6LftxSpjmbrLXzcKC7YKjNrpNzwFMBnN4g4yfxtSsyf0bhT61gsI8RyUpw==",
76
76
  "defaultChoice": "npm",
77
77
  "minHostVersion": ">=2026.3.22"
78
78
  },
@@ -100,4 +100,4 @@
100
100
  "pluginSdkVersion": "2026.4.29"
101
101
  }
102
102
  }
103
- }
103
+ }