@coolclaw/coolclaw 1.0.18 → 1.0.20

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.
@@ -4,7 +4,7 @@ import {
4
4
  coolclawChannelPlugin,
5
5
  defaultBindingFile,
6
6
  setCoolclawRuntime
7
- } from "./chunk-N2OJAALL.js";
7
+ } from "./chunk-NZP7CI26.js";
8
8
 
9
9
  // index.ts
10
10
  import { defineChannelPluginEntry, buildChannelConfigSchema } from "openclaw/plugin-sdk/core";
@@ -224,19 +224,21 @@ function validateAgentAction(action, task) {
224
224
  if (!matchesActionDataSchema(repaired.actionData, option.actionDataSchema)) {
225
225
  return { ok: false, reason: "invalid_action_shape" };
226
226
  }
227
- if (isStructuredJsonTask(task) && !matchesRootOutputSchema(action, task.outputSchema)) {
228
- return { ok: false, reason: "invalid_action_shape" };
229
- }
230
227
  const normalizedAction = {
231
228
  actionType: action.actionType,
232
229
  actionData: repaired.actionData
233
230
  };
234
231
  if (typeof action.speech === "string") normalizedAction.speech = action.speech;
235
232
  if (typeof action.voteReason === "string") normalizedAction.voteReason = action.voteReason;
233
+ const shouldValidateRoot = isStructuredJsonTask(task);
234
+ const repairedRoot = shouldValidateRoot ? repairRootOutputForSchema(normalizedAction, task.outputSchema) : { action: normalizedAction };
235
+ if (!repairedRoot || shouldValidateRoot && !matchesRootOutputSchema(repairedRoot.action, task.outputSchema)) {
236
+ return { ok: false, reason: "invalid_action_shape" };
237
+ }
236
238
  return {
237
239
  ok: true,
238
- action: normalizedAction,
239
- repairReason: repaired.repairReason
240
+ action: repairedRoot.action,
241
+ repairReason: combineRepairReasons(repaired.repairReason, repairedRoot.repairReason)
240
242
  };
241
243
  }
242
244
  function backendFallbackAction(task) {
@@ -330,7 +332,7 @@ function repairActionDataForSchema(actionData, schema) {
330
332
  if (!repaired) {
331
333
  repaired = { ...actionData };
332
334
  }
333
- repaired[field] = value.slice(0, maxLength);
335
+ repaired[field] = truncateWithEllipsis(value, maxLength);
334
336
  truncatedFields.push(field);
335
337
  }
336
338
  if (truncatedFields.length === 0) {
@@ -341,6 +343,54 @@ function repairActionDataForSchema(actionData, schema) {
341
343
  repairReason: truncatedFields.map((field) => `${field}_too_long`).join(",")
342
344
  };
343
345
  }
346
+ function repairRootOutputForSchema(action, schema) {
347
+ if (!schema || Object.keys(schema).length === 0) {
348
+ return { action };
349
+ }
350
+ const properties = isRecord(schema.properties) ? schema.properties : {};
351
+ let repaired = null;
352
+ const truncatedFields = [];
353
+ for (const field of ["speech", "voteReason"]) {
354
+ const propertySchema = properties[field];
355
+ const value = action[field];
356
+ if (typeof value !== "string" || !isRecord(propertySchema)) {
357
+ continue;
358
+ }
359
+ if (!schemaAllowsType(propertySchema.type, "string") || typeof propertySchema.maxLength !== "number") {
360
+ continue;
361
+ }
362
+ const maxLength = Math.max(0, Math.floor(propertySchema.maxLength));
363
+ if (value.length <= maxLength) {
364
+ continue;
365
+ }
366
+ if (!repaired) {
367
+ repaired = { ...action };
368
+ }
369
+ repaired[field] = truncateWithEllipsis(value, maxLength);
370
+ truncatedFields.push(field);
371
+ }
372
+ if (truncatedFields.length === 0) {
373
+ return { action };
374
+ }
375
+ return {
376
+ action: repaired ?? action,
377
+ repairReason: truncatedFields.map((field) => `${field}_too_long`).join(",")
378
+ };
379
+ }
380
+ function combineRepairReasons(first, second) {
381
+ if (!first) return second;
382
+ if (!second) return first;
383
+ return `${first},${second}`;
384
+ }
385
+ function truncateWithEllipsis(value, maxLength) {
386
+ if (value.length <= maxLength) {
387
+ return value;
388
+ }
389
+ if (maxLength <= 3) {
390
+ return value.slice(0, Math.max(0, maxLength));
391
+ }
392
+ return `${value.slice(0, maxLength - 3)}...`;
393
+ }
344
394
  function matchesSchemaValue(value, schema, required) {
345
395
  if (!isRecord(schema)) return true;
346
396
  if (value == null) {
@@ -1985,12 +2035,50 @@ function logAckFailure(params) {
1985
2035
  const target = params.target ? ` target=${params.target}` : "";
1986
2036
  params.log(`${params.channel} ack cleanup failed${target}: ${String(params.error)}`);
1987
2037
  }
1988
- function buildStructuredActionRetryPrompt(renderedPrompt, reason) {
2038
+ function buildStructuredActionRetryPrompt(renderedPrompt, reason, agentTask) {
1989
2039
  const reasonText = reason && reason.trim().length > 0 ? reason.trim() : "invalid_output";
2040
+ const translatedReason = translateStructuredRetryReason(reasonText);
2041
+ const allowedActionTypes2 = agentTask?.actionContract?.options?.map((option) => option.actionType).filter((actionType) => typeof actionType === "string" && actionType.length > 0) ?? [];
2042
+ const allowedLine = allowedActionTypes2.length > 0 ? `
2043
+ \u5F53\u524D\u53EA\u5141\u8BB8 actionType\uFF1A${allowedActionTypes2.join("\u3001")}\u3002` : "";
2044
+ const forbiddenNames = [...forbiddenLegacyActionNames(allowedActionTypes2), "SUBMIT_ACTION", "reason", "content"];
2045
+ const forbiddenLine = allowedActionTypes2.length > 0 ? `
2046
+ \u4E0D\u8981\u4F7F\u7528 ${joinChineseOr(forbiddenNames)}\u3002` : "";
1990
2047
  return `${renderedPrompt}
1991
2048
 
1992
- \u4E0A\u4E00\u6B21\u8F93\u51FA\u672A\u88AB\u72FC\u4EBA\u6740\u7ED3\u6784\u5316\u52A8\u4F5C\u534F\u8BAE\u63A5\u53D7\uFF0C\u5931\u8D25\u539F\u56E0\uFF1A${reasonText}\u3002
1993
- \u8BF7\u91CD\u65B0\u4F5C\u7B54\uFF1A\u53EA\u8F93\u51FA\u4E00\u4E2A\u5B8C\u6574 JSON \u5BF9\u8C61\uFF0C\u4E0D\u8981\u8F93\u51FA Markdown\u3001\u89E3\u91CA\u6587\u5B57\u6216\u4EE3\u7801\u5757\u3002`;
2049
+ ${translatedReason}${allowedLine}${forbiddenLine}
2050
+ \u8BF7\u6309\u4E0A\u65B9\u3010\u8F93\u51FA\u683C\u5F0F\u3011\u91CD\u65B0\u8F93\u51FA\u5B8C\u6574 JSON\uFF1B\u53EA\u8F93\u51FA\u4E00\u4E2A\u5B8C\u6574 JSON \u5BF9\u8C61\uFF0C\u4E0D\u8981\u8F93\u51FA Markdown\u3001\u89E3\u91CA\u6587\u5B57\u6216\u4EE3\u7801\u5757\u3002`;
2051
+ }
2052
+ function translateStructuredRetryReason(reasonText) {
2053
+ if (reasonText === "disallowed_action_type") {
2054
+ return "\u4E0A\u4E00\u6B21\u8F93\u51FA\u672A\u88AB\u63A5\u53D7\uFF1AactionType \u4E0D\u5728\u5F53\u524D\u5141\u8BB8\u5217\u8868\u3002";
2055
+ }
2056
+ if (reasonText === "invalid_action_shape") {
2057
+ return "\u4E0A\u4E00\u6B21\u8F93\u51FA\u672A\u88AB\u63A5\u53D7\uFF1AJSON \u5B57\u6BB5\u7ED3\u6784\u4E0D\u7B26\u5408\u5F53\u524D\u3010\u8F93\u51FA\u683C\u5F0F\u3011\u3002";
2058
+ }
2059
+ if (reasonText === "missing_contract") {
2060
+ return "\u4E0A\u4E00\u6B21\u8F93\u51FA\u672A\u88AB\u63A5\u53D7\uFF1A\u5F53\u524D\u4EFB\u52A1\u7F3A\u5C11\u53EF\u63D0\u4EA4\u7684\u52A8\u4F5C\u5951\u7EA6\u3002";
2061
+ }
2062
+ return `\u4E0A\u4E00\u6B21\u8F93\u51FA\u672A\u88AB\u63A5\u53D7\uFF0C\u5931\u8D25\u539F\u56E0\uFF1A${reasonText}\u3002`;
2063
+ }
2064
+ function forbiddenLegacyActionNames(allowedActionTypes2) {
2065
+ const legacyNames = allowedActionTypes2.map((actionType) => {
2066
+ if (actionType === "WOLF_KILL") return "WOLF_TURN";
2067
+ if (actionType === "WITCH_SAVE" || actionType === "WITCH_POISON" || actionType === "WITCH_PASS") return "WITCH_TURN";
2068
+ if (actionType === "SEER_CHECK") return "SEER_TURN";
2069
+ if (actionType === "DAY_SPEAK") return "DAY_SPEAK_TURN";
2070
+ if (actionType === "DAY_VOTE") return "DAY_VOTE_TURN";
2071
+ if (actionType === "LAST_WORD") return "LAST_WORD_TURN";
2072
+ if (actionType === "HUNTER_SHOOT" || actionType === "HUNTER_PASS") return "HUNTER_SKILL_TURN";
2073
+ return void 0;
2074
+ }).filter((name) => Boolean(name));
2075
+ return [...new Set(legacyNames)];
2076
+ }
2077
+ function joinChineseOr(values) {
2078
+ if (values.length <= 1) {
2079
+ return values.join("");
2080
+ }
2081
+ return `${values.slice(0, -1).join("\u3001")} \u6216 ${values[values.length - 1]}`;
1994
2082
  }
1995
2083
  function hasStructuredRetryBudget(deadlineEpochMs, nowEpochMs = Date.now(), safetyMarginMs = 1e3) {
1996
2084
  if (!deadlineEpochMs || deadlineEpochMs <= 0) {
@@ -2835,7 +2923,7 @@ var coolclawChannelPlugin = createChatChannelPlugin({
2835
2923
  gameModelActionRejected = void 0;
2836
2924
  gameModelActionType = void 0;
2837
2925
  gameValidationReason = void 0;
2838
- const retryPrompt = buildStructuredActionRetryPrompt(envelope.text, retryReason);
2926
+ const retryPrompt = buildStructuredActionRetryPrompt(envelope.text, retryReason, gameMeta.agentTask);
2839
2927
  await dispatchGameReply({
2840
2928
  ...gameBaseReplyContext,
2841
2929
  Body: retryPrompt,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  index_default
3
- } from "./chunk-G2JZSRZF.js";
4
- import "./chunk-N2OJAALL.js";
3
+ } from "./chunk-7HQ3P7XX.js";
4
+ import "./chunk-NZP7CI26.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-G2JZSRZF.js";
4
- import "./chunk-N2OJAALL.js";
3
+ } from "./chunk-7HQ3P7XX.js";
4
+ import "./chunk-NZP7CI26.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-N2OJAALL.js";
3
+ } from "./chunk-NZP7CI26.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.18",
3
+ "version": "1.0.20",
4
4
  "description": "OpenClaw native channel plugin for CoolClaw chat.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",