@coolclaw/coolclaw 1.0.11 → 1.0.13

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.
@@ -416,14 +416,8 @@ async function handleInboundFrame(input) {
416
416
  await ackFrameSeq(input);
417
417
  return;
418
418
  }
419
- const ackAfterDispatch = envelope.metadata.gameEvent === true;
420
- if (!ackAfterDispatch) {
421
- await ackProcessedSeq(input, envelope);
422
- }
423
419
  await input.dispatch(envelope);
424
- if (ackAfterDispatch) {
425
- await ackProcessedSeq(input, envelope);
426
- }
420
+ await ackProcessedSeq(input, envelope);
427
421
  }
428
422
  function mapNotificationFrame(frame) {
429
423
  const payload = isRecord3(frame.payload) ? frame.payload : {};
@@ -1223,6 +1217,15 @@ function logAckFailure(params) {
1223
1217
  const target = params.target ? ` target=${params.target}` : "";
1224
1218
  params.log(`${params.channel} ack cleanup failed${target}: ${String(params.error)}`);
1225
1219
  }
1220
+ function assertInboundRuntimeAvailable(runtime, context) {
1221
+ if (runtime?.channel) {
1222
+ return runtime.channel;
1223
+ }
1224
+ if (context.isGameEvent) {
1225
+ throw new Error("CoolClaw runtime.channel unavailable while dispatching GAME_EVENT");
1226
+ }
1227
+ throw new Error(`CoolClaw runtime.channel unavailable while dispatching ${context.messageType}`);
1228
+ }
1226
1229
  async function submitGameActionWithLog(action, meta, wsClient, log, source, rawResponse, auditMeta) {
1227
1230
  if (!wsClient.isConnected()) {
1228
1231
  log?.error?.(`[GAME-ACTION] submit skipped: ws not connected eventId=${meta.eventId}`);
@@ -1308,6 +1311,14 @@ async function submitBackendFallbackWithLog(params) {
1308
1311
  function isGameActionSubmitUncertainError(message) {
1309
1312
  return /request timed out|wss client stopped|websocket.*clos|socket hang up|econnreset|write epipe/i.test(message);
1310
1313
  }
1314
+ function isNoReplyText(text) {
1315
+ const trimmed = text.trim();
1316
+ if (!trimmed) return false;
1317
+ const noReplyTokens = /* @__PURE__ */ new Set(["NO_REPLY", "[NO_REPLY]", "<NO_REPLY>"]);
1318
+ const lines = trimmed.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
1319
+ const lastLine = lines.at(-1)?.toUpperCase();
1320
+ return lastLine ? noReplyTokens.has(lastLine) : false;
1321
+ }
1311
1322
  var runtimeClients = /* @__PURE__ */ new Map();
1312
1323
  function setRuntimeClient(accountKey, client) {
1313
1324
  runtimeClients.set(accountKey, client);
@@ -1469,7 +1480,13 @@ var coolclawChannelPlugin = createChatChannelPlugin({
1469
1480
  );
1470
1481
  }
1471
1482
  const runtime = getCoolclawRuntime();
1472
- if (!runtime?.channel) {
1483
+ let runtimeChannel;
1484
+ try {
1485
+ runtimeChannel = assertInboundRuntimeAvailable(runtime, {
1486
+ isGameEvent,
1487
+ messageType: envelope.messageType
1488
+ });
1489
+ } catch (err) {
1473
1490
  logInboundDrop({ log: ctx.log?.warn?.bind(ctx.log) ?? (() => {
1474
1491
  }), channel: "coolclaw", reason: "runtime not available; skipping dispatch" });
1475
1492
  if (isGameEvent && gameMeta) {
@@ -1482,29 +1499,30 @@ var coolclawChannelPlugin = createChatChannelPlugin({
1482
1499
  if (submitted === "failed") {
1483
1500
  throw new Error("game fallback submit failed: runtime_not_available");
1484
1501
  }
1502
+ return;
1485
1503
  }
1486
- return;
1504
+ throw err;
1487
1505
  }
1488
1506
  try {
1489
1507
  const isGroup = envelope.conversationId.startsWith("group:");
1490
1508
  const peer = isGroup ? { kind: "group", id: envelope.group?.groupId ?? envelope.conversationId } : { kind: "direct", id: envelope.conversationId };
1491
- if (!runtime.channel.routing?.resolveAgentRoute) {
1509
+ if (!runtimeChannel.routing?.resolveAgentRoute) {
1492
1510
  throw new Error(
1493
1511
  "CoolClaw requires runtime.channel.routing.resolveAgentRoute. Please upgrade OpenClaw to >=2026.3.22."
1494
1512
  );
1495
1513
  }
1496
- const route = await runtime.channel.routing.resolveAgentRoute({
1514
+ const route = await runtimeChannel.routing.resolveAgentRoute({
1497
1515
  cfg: ctx.cfg,
1498
1516
  channel: "coolclaw",
1499
1517
  accountId: ctx.accountId,
1500
1518
  peer
1501
1519
  });
1502
- if (!runtime.channel.session?.resolveStorePath) {
1520
+ if (!runtimeChannel.session?.resolveStorePath) {
1503
1521
  throw new Error(
1504
1522
  "CoolClaw requires runtime.channel.session.resolveStorePath. Please upgrade OpenClaw to >=2026.3.22."
1505
1523
  );
1506
1524
  }
1507
- const storePath = runtime.channel.session.resolveStorePath(
1525
+ const storePath = runtimeChannel.session.resolveStorePath(
1508
1526
  ctx.cfg.session?.store,
1509
1527
  { agentId: route.agentId }
1510
1528
  );
@@ -1520,22 +1538,22 @@ var coolclawChannelPlugin = createChatChannelPlugin({
1520
1538
  deliveryTarget = normalizeCoolclawTarget(envelope.conversationId);
1521
1539
  }
1522
1540
  const bodyForAgent = buildBodyForAgent(envelope);
1523
- if (typeof runtime.channel.reply?.finalizeInboundContext !== "function") {
1541
+ if (typeof runtimeChannel.reply?.finalizeInboundContext !== "function") {
1524
1542
  throw new Error(
1525
1543
  "CoolClaw requires runtime.channel.reply.finalizeInboundContext. Please upgrade OpenClaw to >=2026.3.22."
1526
1544
  );
1527
1545
  }
1528
- if (typeof runtime.channel.reply?.dispatchReplyWithBufferedBlockDispatcher !== "function") {
1546
+ if (typeof runtimeChannel.reply?.dispatchReplyWithBufferedBlockDispatcher !== "function") {
1529
1547
  throw new Error(
1530
1548
  "CoolClaw requires runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher. Please upgrade OpenClaw to >=2026.3.22."
1531
1549
  );
1532
1550
  }
1533
- if (typeof runtime.channel.session?.recordInboundSession !== "function") {
1551
+ if (typeof runtimeChannel.session?.recordInboundSession !== "function") {
1534
1552
  throw new Error(
1535
1553
  "CoolClaw requires runtime.channel.session.recordInboundSession. Please upgrade OpenClaw to >=2026.3.22."
1536
1554
  );
1537
1555
  }
1538
- const ctxPayload = runtime.channel.reply.finalizeInboundContext({
1556
+ const ctxPayload = runtimeChannel.reply.finalizeInboundContext({
1539
1557
  Body: envelope.text,
1540
1558
  BodyForAgent: bodyForAgent,
1541
1559
  RawBody: envelope.text,
@@ -1550,11 +1568,12 @@ var coolclawChannelPlugin = createChatChannelPlugin({
1550
1568
  Surface: "coolclaw",
1551
1569
  Channel: "coolclaw",
1552
1570
  Peer: peer,
1571
+ WasMentioned: envelope.shouldReply,
1553
1572
  Mentioned: envelope.shouldReply
1554
1573
  });
1555
1574
  const sessionKey = ctxPayload.SessionKey ?? route.sessionKey;
1556
1575
  const mainSessionKey = route.mainSessionKey;
1557
- await runtime.channel.session.recordInboundSession({
1576
+ await runtimeChannel.session.recordInboundSession({
1558
1577
  storePath,
1559
1578
  sessionKey,
1560
1579
  ctx: ctxPayload,
@@ -1563,7 +1582,7 @@ var coolclawChannelPlugin = createChatChannelPlugin({
1563
1582
  ctx.log?.warn(`recordInboundSession failed: ${err instanceof Error ? err.message : String(err)}`);
1564
1583
  }
1565
1584
  });
1566
- await runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
1585
+ await runtimeChannel.reply.dispatchReplyWithBufferedBlockDispatcher({
1567
1586
  ctx: ctxPayload,
1568
1587
  cfg: ctx.cfg,
1569
1588
  // 群聊强制走 automatic:CoolClaw 群聊业务语义就是 @ 即回,
@@ -1575,6 +1594,8 @@ var coolclawChannelPlugin = createChatChannelPlugin({
1575
1594
  dispatcherOptions: {
1576
1595
  deliver: async (payload) => {
1577
1596
  if (!payload.text) return;
1597
+ const replyText = String(payload.text);
1598
+ if (!isGameEvent && isNoReplyText(replyText)) return;
1578
1599
  if (isGameEvent && gameMeta) {
1579
1600
  if (gameSubmitted) return;
1580
1601
  gameBuffer.push(String(payload.text));
@@ -1623,7 +1644,7 @@ var coolclawChannelPlugin = createChatChannelPlugin({
1623
1644
  } else {
1624
1645
  replyTarget = normalizeCoolclawTarget(envelope.conversationId);
1625
1646
  }
1626
- await sendText({ client: wsClient, target: replyTarget, text: payload.text });
1647
+ await sendText({ client: wsClient, target: replyTarget, text: replyText });
1627
1648
  } catch (err) {
1628
1649
  ctx.log?.error(`Failed to deliver reply: ${err instanceof Error ? err.message : String(err)}`);
1629
1650
  }
@@ -1870,13 +1891,14 @@ function buildBodyForAgent(envelope) {
1870
1891
  }
1871
1892
  if (envelope.shouldReply) {
1872
1893
  lines.push(`${lines.filter((line) => /^\d+\. /.test(line)).length + 1}. \u4F60\u5DF2\u88AB\u660E\u786E @\uFF0C\u8BF7\u9488\u5BF9\u6D88\u606F\u5185\u5BB9\u8FDB\u884C\u56DE\u590D\u3002`);
1894
+ } else {
1895
+ lines.push(`${lines.filter((line) => /^\d+\. /.test(line)).length + 1}. \u4F60\u6CA1\u6709\u88AB\u660E\u786E @\uFF0C\u8BF7\u5148\u628A\u8FD9\u6761\u6D88\u606F\u4F5C\u4E3A\u7FA4\u804A\u4E0A\u4E0B\u6587\u9605\u8BFB\u3002`);
1896
+ lines.push(`${lines.filter((line) => /^\d+\. /.test(line)).length + 1}. \u5982\u679C\u4F60\u5224\u65AD\u4E0D\u9700\u8981\u516C\u5F00\u56DE\u590D\uFF0C\u8BF7\u53EA\u8F93\u51FA NO_REPLY\uFF1B\u4E0D\u8981\u89E3\u91CA\u539F\u56E0\u3002`);
1897
+ lines.push(`${lines.filter((line) => /^\d+\. /.test(line)).length + 1}. \u53EA\u6709\u5728\u6D88\u606F\u4E0E\u4F60\u5F3A\u76F8\u5173\u4E14\u786E\u5B9E\u9700\u8981\u4F60\u53C2\u4E0E\u65F6\uFF0C\u624D\u8F93\u51FA\u8981\u53D1\u9001\u5230\u7FA4\u91CC\u7684\u516C\u5F00\u56DE\u590D\u5185\u5BB9\u3002`);
1873
1898
  }
1874
1899
  for (const hint of agentMentionHelpLines) {
1875
1900
  lines.push(`${lines.filter((line) => /^\d+\. /.test(line)).length + 1}. ${hint}`);
1876
1901
  }
1877
- if (!envelope.shouldReply && hintLines.length === 0) {
1878
- lines.push(`${lines.filter((line) => /^\d+\. /.test(line)).length + 1}. \u4F60\u6CA1\u6709\u88AB\u660E\u786E @\uFF0C\u901A\u5E38\u53EA\u9700\u8BB0\u5F55\u4E0A\u4E0B\u6587\uFF0C\u4E0D\u5FC5\u4E3B\u52A8\u56DE\u590D\uFF1B\u53EA\u6709\u5728\u6D88\u606F\u4E0E\u4F60\u5F3A\u76F8\u5173\u65F6\u624D\u8C28\u614E\u53C2\u4E0E\u3002`);
1879
- }
1880
1902
  return lines.join("\n");
1881
1903
  }
1882
1904
  function buildPrivateBodyForAgent(envelope) {
@@ -3,7 +3,7 @@ import {
3
3
  coolclawChannelPlugin,
4
4
  defaultBindingFile,
5
5
  setCoolclawRuntime
6
- } from "./chunk-KHHSDAQI.js";
6
+ } from "./chunk-3RAQ3GUM.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-BRQFC427.js";
4
- import "./chunk-KHHSDAQI.js";
3
+ } from "./chunk-ITAZ7RTC.js";
4
+ import "./chunk-3RAQ3GUM.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-BRQFC427.js";
4
- import "./chunk-KHHSDAQI.js";
3
+ } from "./chunk-ITAZ7RTC.js";
4
+ import "./chunk-3RAQ3GUM.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-KHHSDAQI.js";
3
+ } from "./chunk-3RAQ3GUM.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.11",
3
+ "version": "1.0.13",
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-ApEmtqGxosTesGojSMrK56YDuSVmlS2csPFMEJa2J8WVvjq/N6jt+7HubkgXoEdPnoF1RNCHmF53OIKLJkdN2g==",
75
+ "expectedIntegrity": "sha512-lRGll+tauQxhgsqtOWlEkM+MKZwDQpib/s1A4mZSQB+PDRsvMzuXKQiX0ipEUQo1/HPjlLgDRkM/5A6GX45kag==",
76
76
  "defaultChoice": "npm",
77
77
  "minHostVersion": ">=2026.3.22"
78
78
  },