@coolclaw/coolclaw 1.0.6 → 1.0.7

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.
@@ -154,13 +154,24 @@ function validateAgentAction(action, task) {
154
154
  if (!option) {
155
155
  return { ok: false, reason: "disallowed_action_type" };
156
156
  }
157
- if (!matchesActionDataSchema(action.actionData, option.actionDataSchema)) {
157
+ if (containsPublicPrivateInfoLeak(action.actionType, action.actionData)) {
158
+ return { ok: false, reason: "public_private_info_leak" };
159
+ }
160
+ const repaired = repairActionDataForSchema(action.actionData, option.actionDataSchema);
161
+ if (!matchesActionDataSchema(repaired.actionData, option.actionDataSchema)) {
158
162
  return { ok: false, reason: "invalid_action_shape" };
159
163
  }
160
- if (containsPublicPrivateInfoLeak(action.actionType, action.actionData)) {
164
+ if (containsPublicPrivateInfoLeak(action.actionType, repaired.actionData)) {
161
165
  return { ok: false, reason: "public_private_info_leak" };
162
166
  }
163
- return { ok: true, action };
167
+ return {
168
+ ok: true,
169
+ action: {
170
+ actionType: action.actionType,
171
+ actionData: repaired.actionData
172
+ },
173
+ repairReason: repaired.repairReason
174
+ };
164
175
  }
165
176
  function backendFallbackAction(task) {
166
177
  const fallback = task.fallbackAction;
@@ -218,6 +229,39 @@ function matchesActionDataSchema(actionData, schema) {
218
229
  }
219
230
  return true;
220
231
  }
232
+ function repairActionDataForSchema(actionData, schema) {
233
+ if (!schema || Object.keys(schema).length === 0) {
234
+ return { actionData };
235
+ }
236
+ const properties = isRecord(schema.properties) ? schema.properties : {};
237
+ let repaired = null;
238
+ const truncatedFields = [];
239
+ for (const [field, propertySchema] of Object.entries(properties)) {
240
+ const value = actionData[field];
241
+ if (typeof value !== "string" || !isRecord(propertySchema)) {
242
+ continue;
243
+ }
244
+ if (propertySchema.type !== "string" || typeof propertySchema.maxLength !== "number") {
245
+ continue;
246
+ }
247
+ const maxLength = Math.max(0, Math.floor(propertySchema.maxLength));
248
+ if (value.length <= maxLength) {
249
+ continue;
250
+ }
251
+ if (!repaired) {
252
+ repaired = { ...actionData };
253
+ }
254
+ repaired[field] = value.slice(0, maxLength);
255
+ truncatedFields.push(field);
256
+ }
257
+ if (truncatedFields.length === 0) {
258
+ return { actionData };
259
+ }
260
+ return {
261
+ actionData: repaired ?? actionData,
262
+ repairReason: `truncate:${truncatedFields.join(",")}`
263
+ };
264
+ }
221
265
  function matchesSchemaValue(value, schema, required) {
222
266
  if (value == null) return !required;
223
267
  if (!isRecord(schema)) return true;
@@ -723,6 +767,7 @@ async function sendGameAction(input) {
723
767
  timestamp: String(Date.now()),
724
768
  turnSeq: input.turnSeq,
725
769
  eventId: input.eventId,
770
+ deadlineEpochMs: input.deadlineEpochMs,
726
771
  traceId: input.traceId,
727
772
  promptPolicyVersion: input.promptPolicyVersion,
728
773
  renderedPromptHash: input.renderedPromptHash,
@@ -737,6 +782,7 @@ async function sendGameAction(input) {
737
782
  if (response.ok === false) {
738
783
  throw new Error(response.error?.message ?? "CoolClaw game action failed");
739
784
  }
785
+ return response;
740
786
  }
741
787
 
742
788
  // src/game-action-parser.ts
@@ -811,7 +857,16 @@ function parseActionJson(body) {
811
857
  try {
812
858
  obj = JSON.parse(body);
813
859
  } catch (e) {
814
- return { error: "invalid_json", detail: e instanceof Error ? e.message : String(e) };
860
+ const repaired = removeTrailingCommas(body);
861
+ if (repaired !== body) {
862
+ try {
863
+ obj = JSON.parse(repaired);
864
+ } catch {
865
+ return { error: "invalid_json", detail: e instanceof Error ? e.message : String(e) };
866
+ }
867
+ } else {
868
+ return { error: "invalid_json", detail: e instanceof Error ? e.message : String(e) };
869
+ }
815
870
  }
816
871
  if (typeof obj !== "object" || obj === null) {
817
872
  return { error: "invalid_json", detail: "not an object" };
@@ -828,6 +883,41 @@ function parseActionJson(body) {
828
883
  actionData: rec.actionData
829
884
  };
830
885
  }
886
+ function removeTrailingCommas(body) {
887
+ let out = "";
888
+ let inString = false;
889
+ let escaped = false;
890
+ for (let i = 0; i < body.length; i += 1) {
891
+ const ch = body[i];
892
+ if (inString) {
893
+ out += ch;
894
+ if (escaped) {
895
+ escaped = false;
896
+ } else if (ch === "\\") {
897
+ escaped = true;
898
+ } else if (ch === '"') {
899
+ inString = false;
900
+ }
901
+ continue;
902
+ }
903
+ if (ch === '"') {
904
+ inString = true;
905
+ out += ch;
906
+ continue;
907
+ }
908
+ if (ch === ",") {
909
+ let j = i + 1;
910
+ while (j < body.length && /\s/.test(body[j])) {
911
+ j += 1;
912
+ }
913
+ if (body[j] === "}" || body[j] === "]") {
914
+ continue;
915
+ }
916
+ }
917
+ out += ch;
918
+ }
919
+ return out;
920
+ }
831
921
 
832
922
  // src/game-action-audit.ts
833
923
  function normalizeAuditText(value, maxChars = 256) {
@@ -1149,7 +1239,7 @@ function logAckFailure(params) {
1149
1239
  async function submitGameActionWithLog(action, meta, wsClient, log, source, rawResponse, auditMeta) {
1150
1240
  if (!wsClient.isConnected()) {
1151
1241
  log?.error?.(`[GAME-ACTION] submit skipped: ws not connected eventId=${meta.eventId}`);
1152
- return false;
1242
+ return "failed";
1153
1243
  }
1154
1244
  const responseHash = rawResponse && rawResponse.length > 0 ? sha256Hex(rawResponse) : void 0;
1155
1245
  log?.info?.(
@@ -1157,7 +1247,7 @@ async function submitGameActionWithLog(action, meta, wsClient, log, source, rawR
1157
1247
  );
1158
1248
  const start = Date.now();
1159
1249
  try {
1160
- await sendGameAction({
1250
+ const response = await sendGameAction({
1161
1251
  client: wsClient,
1162
1252
  gameId: meta.gameId,
1163
1253
  roomId: meta.roomId,
@@ -1166,6 +1256,7 @@ async function submitGameActionWithLog(action, meta, wsClient, log, source, rawR
1166
1256
  actionData: action.actionData,
1167
1257
  turnSeq: meta.turnSeq,
1168
1258
  eventId: meta.eventId,
1259
+ deadlineEpochMs: meta.deadlineEpochMs,
1169
1260
  traceId: meta.traceId,
1170
1261
  promptPolicyVersion: meta.promptPolicyVersion,
1171
1262
  renderedPromptHash: meta.renderedPromptHash,
@@ -1176,16 +1267,28 @@ async function submitGameActionWithLog(action, meta, wsClient, log, source, rawR
1176
1267
  modelActionType: auditMeta?.modelActionType,
1177
1268
  validationReason: normalizeAuditText(auditMeta?.validationReason)
1178
1269
  });
1270
+ if (response.uncertain === true) {
1271
+ log?.warn?.(
1272
+ `[GAME-ACTION] submit uncertain source=${source} eventId=${meta.eventId} elapsedMs=${Date.now() - start} msg=${response.message ?? ""}`
1273
+ );
1274
+ return "uncertain";
1275
+ }
1179
1276
  log?.info?.(
1180
1277
  `[GAME-ACTION] submit ok source=${source} gameId=${meta.gameId} eventId=${meta.eventId} promptPolicyVersion=${meta.promptPolicyVersion ?? ""} renderedPromptHash=${meta.renderedPromptHash ?? ""} rawResponseHash=${responseHash ?? ""} elapsedMs=${Date.now() - start}`
1181
1278
  );
1182
- return true;
1279
+ return "submitted";
1183
1280
  } catch (err) {
1184
1281
  const errMsg = err instanceof Error ? err.message : String(err);
1282
+ if (isGameActionSubmitUncertainError(errMsg)) {
1283
+ log?.warn?.(
1284
+ `[GAME-ACTION] submit uncertain source=${source} eventId=${meta.eventId} elapsedMs=${Date.now() - start} err=${errMsg}`
1285
+ );
1286
+ return "uncertain";
1287
+ }
1185
1288
  log?.error?.(
1186
1289
  `[GAME-ACTION] submit failed source=${source} eventId=${meta.eventId} elapsedMs=${Date.now() - start} err=${errMsg}`
1187
1290
  );
1188
- return false;
1291
+ return "failed";
1189
1292
  }
1190
1293
  }
1191
1294
  async function submitBackendFallbackWithLog(params) {
@@ -1194,7 +1297,7 @@ async function submitBackendFallbackWithLog(params) {
1194
1297
  params.log?.warn?.(
1195
1298
  `[GAME-ACTION] backend fallback unavailable eventType=${params.meta.eventType} eventId=${params.meta.eventId} reason=${params.reason} promptPolicyVersion=${params.meta.promptPolicyVersion ?? ""} renderedPromptHash=${params.meta.renderedPromptHash ?? ""}`
1196
1299
  );
1197
- return false;
1300
+ return "failed";
1198
1301
  }
1199
1302
  const inferred = inferRejectedModelAction(params.rawResponse ?? "", params.meta.agentTask);
1200
1303
  const auditMeta = {
@@ -1215,6 +1318,9 @@ async function submitBackendFallbackWithLog(params) {
1215
1318
  auditMeta
1216
1319
  );
1217
1320
  }
1321
+ function isGameActionSubmitUncertainError(message) {
1322
+ return /request timed out|wss client stopped|websocket.*clos|socket hang up|econnreset|write epipe/i.test(message);
1323
+ }
1218
1324
  var runtimeClients = /* @__PURE__ */ new Map();
1219
1325
  function setRuntimeClient(accountKey, client) {
1220
1326
  runtimeClients.set(accountKey, client);
@@ -1386,7 +1492,7 @@ var coolclawChannelPlugin = createChatChannelPlugin({
1386
1492
  log: ctx.log,
1387
1493
  reason: "runtime_not_available"
1388
1494
  });
1389
- if (!submitted) {
1495
+ if (submitted === "failed") {
1390
1496
  throw new Error("game fallback submit failed: runtime_not_available");
1391
1497
  }
1392
1498
  }
@@ -1509,10 +1615,11 @@ var coolclawChannelPlugin = createChatChannelPlugin({
1509
1615
  full,
1510
1616
  {
1511
1617
  modelActionRejected: false,
1512
- modelActionType: validation.action.actionType
1618
+ modelActionType: validation.action.actionType,
1619
+ validationReason: validation.repairReason
1513
1620
  }
1514
1621
  );
1515
- if (submitted) {
1622
+ if (submitted === "submitted" || submitted === "uncertain") {
1516
1623
  gameSubmitted = true;
1517
1624
  } else {
1518
1625
  gameFallbackReason = `llm_action_submit_failed:${validation.action.actionType}`;
@@ -1580,7 +1687,7 @@ var coolclawChannelPlugin = createChatChannelPlugin({
1580
1687
  validationReason: gameFallbackReason ?? gameValidationReason ?? inferred.validationReason
1581
1688
  }
1582
1689
  });
1583
- if (!submitted) {
1690
+ if (submitted === "failed") {
1584
1691
  throw new Error(`game fallback submit failed: ${gameFallbackReason ?? "unknown"}`);
1585
1692
  }
1586
1693
  } catch (fbErr) {
@@ -3,7 +3,7 @@ import {
3
3
  coolclawChannelPlugin,
4
4
  defaultBindingFile,
5
5
  setCoolclawRuntime
6
- } from "./chunk-W6LHGLKL.js";
6
+ } from "./chunk-CPBRFMOB.js";
7
7
 
8
8
  // index.ts
9
9
  import { defineChannelPluginEntry, buildChannelConfigSchema } from "openclaw/plugin-sdk/core";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  index_default
3
- } from "./chunk-4RKDX3HY.js";
4
- import "./chunk-W6LHGLKL.js";
3
+ } from "./chunk-QAJK4WOL.js";
4
+ import "./chunk-CPBRFMOB.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-4RKDX3HY.js";
4
- import "./chunk-W6LHGLKL.js";
3
+ } from "./chunk-QAJK4WOL.js";
4
+ import "./chunk-CPBRFMOB.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-W6LHGLKL.js";
3
+ } from "./chunk-CPBRFMOB.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.6",
3
+ "version": "1.0.7",
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-7VcGcTTi2KmOCAJ76tj8uyEIUURe6LftxSpjmbrLXzcKC7YKjNrpNzwFMBnN4g4yfxtSsyf0bhT61gsI8RyUpw==",
75
+ "expectedIntegrity": "sha512-nLVphLOrmsFhxyJU8neAdx4bE+EcJjLnmzGZmt9E9ndUqiPAjbJCb8pOv7HXYfHeQeVFnf42HkmVrUeqro3ClQ==",
76
76
  "defaultChoice": "npm",
77
77
  "minHostVersion": ">=2026.3.22"
78
78
  },