@coolclaw/coolclaw 1.0.3 → 1.0.5
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.
|
@@ -150,9 +150,13 @@ function validateAgentAction(action, task) {
|
|
|
150
150
|
if (allowed.length === 0) {
|
|
151
151
|
return { ok: false, reason: "missing_contract" };
|
|
152
152
|
}
|
|
153
|
-
|
|
153
|
+
const option = task.actionContract.options.find((candidate) => candidate.actionType === action.actionType);
|
|
154
|
+
if (!option) {
|
|
154
155
|
return { ok: false, reason: "disallowed_action_type" };
|
|
155
156
|
}
|
|
157
|
+
if (!matchesActionDataSchema(action.actionData, option.actionDataSchema)) {
|
|
158
|
+
return { ok: false, reason: "invalid_action_shape" };
|
|
159
|
+
}
|
|
156
160
|
return { ok: true, action };
|
|
157
161
|
}
|
|
158
162
|
function backendFallbackAction(task) {
|
|
@@ -169,7 +173,7 @@ function backendFallbackAction(task) {
|
|
|
169
173
|
function sha256Hex(text) {
|
|
170
174
|
return createHash("sha256").update(text).digest("hex");
|
|
171
175
|
}
|
|
172
|
-
function rawResponsePreview(text, maxChars =
|
|
176
|
+
function rawResponsePreview(text, maxChars = 5e3) {
|
|
173
177
|
if (text.length === 0) return void 0;
|
|
174
178
|
return text.length <= maxChars ? text : `${text.slice(0, maxChars)}...`;
|
|
175
179
|
}
|
|
@@ -194,6 +198,46 @@ function normalizeActionOption(value) {
|
|
|
194
198
|
function allowedActionTypes(task) {
|
|
195
199
|
return task.actionContract.options.map((option) => option.actionType);
|
|
196
200
|
}
|
|
201
|
+
function matchesActionDataSchema(actionData, schema) {
|
|
202
|
+
if (!schema || Object.keys(schema).length === 0) return true;
|
|
203
|
+
if (typeof schema.type === "string" && schema.type !== "object") return false;
|
|
204
|
+
const properties = isRecord(schema.properties) ? schema.properties : {};
|
|
205
|
+
const required = Array.isArray(schema.required) ? schema.required.filter((field) => typeof field === "string" && field.length > 0) : [];
|
|
206
|
+
for (const field of required) {
|
|
207
|
+
if (!Object.prototype.hasOwnProperty.call(actionData, field)) return false;
|
|
208
|
+
if (!matchesSchemaValue(actionData[field], properties[field], true)) return false;
|
|
209
|
+
}
|
|
210
|
+
for (const [field, value] of Object.entries(actionData)) {
|
|
211
|
+
const propertySchema = properties[field];
|
|
212
|
+
if (propertySchema !== void 0 && !matchesSchemaValue(value, propertySchema, false)) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
function matchesSchemaValue(value, schema, required) {
|
|
219
|
+
if (value == null) return !required;
|
|
220
|
+
if (!isRecord(schema)) return true;
|
|
221
|
+
if (Array.isArray(schema.enum) && !schema.enum.includes(value)) {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
switch (schema.type) {
|
|
225
|
+
case "integer":
|
|
226
|
+
return typeof value === "number" && Number.isInteger(value);
|
|
227
|
+
case "number":
|
|
228
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
229
|
+
case "string":
|
|
230
|
+
return typeof value === "string" && (typeof schema.minLength !== "number" || value.length >= schema.minLength) && (typeof schema.maxLength !== "number" || value.length <= schema.maxLength);
|
|
231
|
+
case "boolean":
|
|
232
|
+
return typeof value === "boolean";
|
|
233
|
+
case "object":
|
|
234
|
+
return isRecord(value);
|
|
235
|
+
case "array":
|
|
236
|
+
return Array.isArray(value);
|
|
237
|
+
default:
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
197
241
|
function readString(value) {
|
|
198
242
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
199
243
|
}
|
|
@@ -327,8 +371,14 @@ async function handleInboundFrame(input) {
|
|
|
327
371
|
await ackFrameSeq(input);
|
|
328
372
|
return;
|
|
329
373
|
}
|
|
330
|
-
|
|
374
|
+
const ackAfterDispatch = envelope.metadata.gameEvent === true;
|
|
375
|
+
if (!ackAfterDispatch) {
|
|
376
|
+
await ackProcessedSeq(input, envelope);
|
|
377
|
+
}
|
|
331
378
|
await input.dispatch(envelope);
|
|
379
|
+
if (ackAfterDispatch) {
|
|
380
|
+
await ackProcessedSeq(input, envelope);
|
|
381
|
+
}
|
|
332
382
|
}
|
|
333
383
|
function mapNotificationFrame(frame) {
|
|
334
384
|
const payload = isRecord3(frame.payload) ? frame.payload : {};
|
|
@@ -442,8 +492,10 @@ async function ackFrameSeq(input) {
|
|
|
442
492
|
}
|
|
443
493
|
}
|
|
444
494
|
async function ackSeq(input, seq) {
|
|
445
|
-
const
|
|
495
|
+
const current = await input.ackStore.getLastAckedSeq(input.accountKey);
|
|
496
|
+
const lastAckedSeq = seq <= current ? current : seq;
|
|
446
497
|
await input.sendAck(createFrame("ACK", { lastAckedSeq }));
|
|
498
|
+
await input.ackStore.record(input.accountKey, seq);
|
|
447
499
|
}
|
|
448
500
|
function assertPrivatePayload(value) {
|
|
449
501
|
if (!isRecord3(value) || !isUserRef(value.sender) || !isUserRef(value.recipient)) {
|
|
@@ -651,7 +703,10 @@ async function sendGameAction(input) {
|
|
|
651
703
|
renderedPromptHash: input.renderedPromptHash,
|
|
652
704
|
parseSource: input.parseSource,
|
|
653
705
|
rawResponseHash: input.rawResponseHash,
|
|
654
|
-
rawResponsePreview: input.rawResponsePreview
|
|
706
|
+
rawResponsePreview: input.rawResponsePreview,
|
|
707
|
+
modelActionRejected: input.modelActionRejected,
|
|
708
|
+
modelActionType: input.modelActionType,
|
|
709
|
+
validationReason: input.validationReason
|
|
655
710
|
});
|
|
656
711
|
const response = await input.client.request(frame);
|
|
657
712
|
if (response.ok === false) {
|
|
@@ -661,7 +716,7 @@ async function sendGameAction(input) {
|
|
|
661
716
|
|
|
662
717
|
// src/game-action-parser.ts
|
|
663
718
|
function extractActionBlock(text) {
|
|
664
|
-
const re = /<ACTION>\s*([\s\S]+?)\s*<\/ACTION>/
|
|
719
|
+
const re = /<ACTION>\s*([\s\S]+?)\s*<\/ACTION>/gi;
|
|
665
720
|
let match;
|
|
666
721
|
let last = null;
|
|
667
722
|
while ((match = re.exec(text)) !== null) {
|
|
@@ -669,6 +724,11 @@ function extractActionBlock(text) {
|
|
|
669
724
|
}
|
|
670
725
|
return last;
|
|
671
726
|
}
|
|
727
|
+
function normalizeActionBlock(body) {
|
|
728
|
+
const trimmed = body.trim();
|
|
729
|
+
const fenced = /^```(?:json)?\s*([\s\S]*?)\s*```$/i.exec(trimmed);
|
|
730
|
+
return fenced ? fenced[1].trim() : trimmed;
|
|
731
|
+
}
|
|
672
732
|
function parseAgentAction(text) {
|
|
673
733
|
if (typeof text !== "string" || text.length === 0) {
|
|
674
734
|
return { error: "no_action_block" };
|
|
@@ -679,7 +739,7 @@ function parseAgentAction(text) {
|
|
|
679
739
|
}
|
|
680
740
|
let obj;
|
|
681
741
|
try {
|
|
682
|
-
obj = JSON.parse(body);
|
|
742
|
+
obj = JSON.parse(normalizeActionBlock(body));
|
|
683
743
|
} catch (e) {
|
|
684
744
|
return { error: "invalid_json", detail: e instanceof Error ? e.message : String(e) };
|
|
685
745
|
}
|
|
@@ -699,6 +759,46 @@ function parseAgentAction(text) {
|
|
|
699
759
|
};
|
|
700
760
|
}
|
|
701
761
|
|
|
762
|
+
// src/game-action-audit.ts
|
|
763
|
+
function normalizeAuditText(value, maxChars = 256) {
|
|
764
|
+
if (!value) return void 0;
|
|
765
|
+
return value.length <= maxChars ? value : value.slice(0, maxChars);
|
|
766
|
+
}
|
|
767
|
+
function inferRejectedModelAction(rawResponse, task) {
|
|
768
|
+
if (rawResponse.trim().length === 0) {
|
|
769
|
+
return {
|
|
770
|
+
modelActionRejected: false,
|
|
771
|
+
validationReason: "no_model_output"
|
|
772
|
+
};
|
|
773
|
+
}
|
|
774
|
+
const parsed = parseAgentAction(rawResponse);
|
|
775
|
+
if ("error" in parsed) {
|
|
776
|
+
return {
|
|
777
|
+
modelActionRejected: true,
|
|
778
|
+
validationReason: parseErrorReason(parsed)
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
const validation = validateAgentAction(parsed, task);
|
|
782
|
+
if (!validation.ok) {
|
|
783
|
+
return {
|
|
784
|
+
modelActionRejected: true,
|
|
785
|
+
modelActionType: parsed.actionType,
|
|
786
|
+
validationReason: validation.reason
|
|
787
|
+
};
|
|
788
|
+
}
|
|
789
|
+
return {
|
|
790
|
+
modelActionRejected: true,
|
|
791
|
+
modelActionType: parsed.actionType,
|
|
792
|
+
validationReason: "valid_action_not_submitted"
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
function parseErrorReason(error) {
|
|
796
|
+
if (error.error === "invalid_json") {
|
|
797
|
+
return normalizeAuditText(`invalid_json:${error.detail}`) ?? "invalid_json";
|
|
798
|
+
}
|
|
799
|
+
return error.error;
|
|
800
|
+
}
|
|
801
|
+
|
|
702
802
|
// src/ws-client.ts
|
|
703
803
|
import WebSocket from "ws";
|
|
704
804
|
var CoolclawWsClient = class {
|
|
@@ -976,10 +1076,10 @@ function logAckFailure(params) {
|
|
|
976
1076
|
const target = params.target ? ` target=${params.target}` : "";
|
|
977
1077
|
params.log(`${params.channel} ack cleanup failed${target}: ${String(params.error)}`);
|
|
978
1078
|
}
|
|
979
|
-
async function submitGameActionWithLog(action, meta, wsClient, log, source, rawResponse) {
|
|
1079
|
+
async function submitGameActionWithLog(action, meta, wsClient, log, source, rawResponse, auditMeta) {
|
|
980
1080
|
if (!wsClient.isConnected()) {
|
|
981
1081
|
log?.error?.(`[GAME-ACTION] submit skipped: ws not connected eventId=${meta.eventId}`);
|
|
982
|
-
return;
|
|
1082
|
+
return false;
|
|
983
1083
|
}
|
|
984
1084
|
const responseHash = rawResponse && rawResponse.length > 0 ? sha256Hex(rawResponse) : void 0;
|
|
985
1085
|
log?.info?.(
|
|
@@ -1001,17 +1101,49 @@ async function submitGameActionWithLog(action, meta, wsClient, log, source, rawR
|
|
|
1001
1101
|
renderedPromptHash: meta.renderedPromptHash,
|
|
1002
1102
|
parseSource: source,
|
|
1003
1103
|
rawResponseHash: responseHash,
|
|
1004
|
-
rawResponsePreview: rawResponse ? rawResponsePreview(rawResponse) : void 0
|
|
1104
|
+
rawResponsePreview: rawResponse ? rawResponsePreview(rawResponse) : void 0,
|
|
1105
|
+
modelActionRejected: auditMeta?.modelActionRejected,
|
|
1106
|
+
modelActionType: auditMeta?.modelActionType,
|
|
1107
|
+
validationReason: normalizeAuditText(auditMeta?.validationReason)
|
|
1005
1108
|
});
|
|
1006
1109
|
log?.info?.(
|
|
1007
1110
|
`[GAME-ACTION] submit ok source=${source} gameId=${meta.gameId} eventId=${meta.eventId} promptPolicyVersion=${meta.promptPolicyVersion ?? ""} renderedPromptHash=${meta.renderedPromptHash ?? ""} rawResponseHash=${responseHash ?? ""} elapsedMs=${Date.now() - start}`
|
|
1008
1111
|
);
|
|
1112
|
+
return true;
|
|
1009
1113
|
} catch (err) {
|
|
1010
1114
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
1011
1115
|
log?.error?.(
|
|
1012
1116
|
`[GAME-ACTION] submit failed source=${source} eventId=${meta.eventId} elapsedMs=${Date.now() - start} err=${errMsg}`
|
|
1013
1117
|
);
|
|
1118
|
+
return false;
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
async function submitBackendFallbackWithLog(params) {
|
|
1122
|
+
const fb = backendFallbackAction(params.meta.agentTask);
|
|
1123
|
+
if (!fb) {
|
|
1124
|
+
params.log?.warn?.(
|
|
1125
|
+
`[GAME-ACTION] backend fallback unavailable eventType=${params.meta.eventType} eventId=${params.meta.eventId} reason=${params.reason} promptPolicyVersion=${params.meta.promptPolicyVersion ?? ""} renderedPromptHash=${params.meta.renderedPromptHash ?? ""}`
|
|
1126
|
+
);
|
|
1127
|
+
return false;
|
|
1014
1128
|
}
|
|
1129
|
+
const inferred = inferRejectedModelAction(params.rawResponse ?? "", params.meta.agentTask);
|
|
1130
|
+
const auditMeta = {
|
|
1131
|
+
modelActionRejected: params.auditMeta?.modelActionRejected ?? inferred.modelActionRejected,
|
|
1132
|
+
modelActionType: params.auditMeta?.modelActionType ?? inferred.modelActionType,
|
|
1133
|
+
validationReason: params.auditMeta?.validationReason ?? params.reason ?? inferred.validationReason
|
|
1134
|
+
};
|
|
1135
|
+
params.log?.warn?.(
|
|
1136
|
+
`[GAME-ACTION] backend fallback eventType=${params.meta.eventType} eventId=${params.meta.eventId} reason=${auditMeta.validationReason ?? "unknown"} promptPolicyVersion=${params.meta.promptPolicyVersion ?? ""} renderedPromptHash=${params.meta.renderedPromptHash ?? ""} rawResponseHash=${params.rawResponse ? sha256Hex(params.rawResponse) : ""}`
|
|
1137
|
+
);
|
|
1138
|
+
return submitGameActionWithLog(
|
|
1139
|
+
fb,
|
|
1140
|
+
params.meta,
|
|
1141
|
+
params.wsClient,
|
|
1142
|
+
params.log,
|
|
1143
|
+
"backend_fallback",
|
|
1144
|
+
params.rawResponse || void 0,
|
|
1145
|
+
auditMeta
|
|
1146
|
+
);
|
|
1015
1147
|
}
|
|
1016
1148
|
var runtimeClients = /* @__PURE__ */ new Map();
|
|
1017
1149
|
function setRuntimeClient(accountKey, client) {
|
|
@@ -1160,22 +1292,36 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1160
1292
|
accountKey,
|
|
1161
1293
|
ackStore,
|
|
1162
1294
|
dispatch: async (envelope) => {
|
|
1163
|
-
const runtime = getCoolclawRuntime();
|
|
1164
|
-
if (!runtime?.channel) {
|
|
1165
|
-
logInboundDrop({ log: ctx.log?.warn?.bind(ctx.log) ?? (() => {
|
|
1166
|
-
}), channel: "coolclaw", reason: "runtime not available; skipping dispatch" });
|
|
1167
|
-
return;
|
|
1168
|
-
}
|
|
1169
1295
|
const isGameEvent = envelope.metadata?.gameEvent === true;
|
|
1170
1296
|
const gameMeta = isGameEvent ? envelope.metadata : null;
|
|
1171
1297
|
let gameSubmitted = false;
|
|
1172
1298
|
let gameFallbackReason = null;
|
|
1299
|
+
let gameModelActionType;
|
|
1300
|
+
let gameValidationReason;
|
|
1301
|
+
let gameModelActionRejected;
|
|
1173
1302
|
const gameBuffer = [];
|
|
1174
1303
|
if (isGameEvent && gameMeta) {
|
|
1175
1304
|
ctx.log?.info?.(
|
|
1176
1305
|
`[GAME-TASK] dispatch start gameId=${gameMeta.gameId} roomId=${gameMeta.roomId} eventType=${gameMeta.eventType} eventId=${gameMeta.eventId} promptPolicyVersion=${gameMeta.promptPolicyVersion ?? ""} renderedPromptHash=${gameMeta.renderedPromptHash ?? ""} conversationId=${envelope.conversationId}`
|
|
1177
1306
|
);
|
|
1178
1307
|
}
|
|
1308
|
+
const runtime = getCoolclawRuntime();
|
|
1309
|
+
if (!runtime?.channel) {
|
|
1310
|
+
logInboundDrop({ log: ctx.log?.warn?.bind(ctx.log) ?? (() => {
|
|
1311
|
+
}), channel: "coolclaw", reason: "runtime not available; skipping dispatch" });
|
|
1312
|
+
if (isGameEvent && gameMeta) {
|
|
1313
|
+
const submitted = await submitBackendFallbackWithLog({
|
|
1314
|
+
meta: gameMeta,
|
|
1315
|
+
wsClient,
|
|
1316
|
+
log: ctx.log,
|
|
1317
|
+
reason: "runtime_not_available"
|
|
1318
|
+
});
|
|
1319
|
+
if (!submitted) {
|
|
1320
|
+
throw new Error("game fallback submit failed: runtime_not_available");
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
return;
|
|
1324
|
+
}
|
|
1179
1325
|
try {
|
|
1180
1326
|
const isGroup = envelope.conversationId.startsWith("group:");
|
|
1181
1327
|
const peer = isGroup ? { kind: "group", id: envelope.group?.groupId ?? envelope.conversationId } : { kind: "direct", id: envelope.conversationId };
|
|
@@ -1275,20 +1421,34 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1275
1421
|
if ("error" in parsed) return;
|
|
1276
1422
|
const validation = validateAgentAction(parsed, gameMeta.agentTask);
|
|
1277
1423
|
if (!validation.ok) {
|
|
1424
|
+
gameModelActionRejected = true;
|
|
1425
|
+
gameModelActionType = parsed.actionType;
|
|
1426
|
+
gameValidationReason = validation.reason;
|
|
1427
|
+
gameFallbackReason = validation.reason;
|
|
1278
1428
|
ctx.log?.warn?.(
|
|
1279
1429
|
`[GAME-ACTION] rejected model action reason=${validation.reason} actionType=${parsed.actionType} eventType=${gameMeta.eventType} eventId=${gameMeta.eventId} promptPolicyVersion=${gameMeta.promptPolicyVersion ?? ""} renderedPromptHash=${gameMeta.renderedPromptHash ?? ""} rawResponseHash=${sha256Hex(full)}`
|
|
1280
1430
|
);
|
|
1281
1431
|
return;
|
|
1282
1432
|
}
|
|
1283
|
-
|
|
1284
|
-
await submitGameActionWithLog(
|
|
1433
|
+
const submitted = await submitGameActionWithLog(
|
|
1285
1434
|
validation.action,
|
|
1286
1435
|
gameMeta,
|
|
1287
1436
|
wsClient,
|
|
1288
1437
|
ctx.log,
|
|
1289
1438
|
"llm",
|
|
1290
|
-
full
|
|
1439
|
+
full,
|
|
1440
|
+
{
|
|
1441
|
+
modelActionRejected: false,
|
|
1442
|
+
modelActionType: validation.action.actionType
|
|
1443
|
+
}
|
|
1291
1444
|
);
|
|
1445
|
+
if (submitted) {
|
|
1446
|
+
gameSubmitted = true;
|
|
1447
|
+
} else {
|
|
1448
|
+
gameFallbackReason = `llm_action_submit_failed:${validation.action.actionType}`;
|
|
1449
|
+
gameModelActionRejected = false;
|
|
1450
|
+
gameModelActionType = validation.action.actionType;
|
|
1451
|
+
}
|
|
1292
1452
|
return;
|
|
1293
1453
|
}
|
|
1294
1454
|
try {
|
|
@@ -1311,7 +1471,9 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1311
1471
|
}
|
|
1312
1472
|
});
|
|
1313
1473
|
if (isGameEvent && gameMeta && !gameSubmitted) {
|
|
1314
|
-
gameFallbackReason
|
|
1474
|
+
if (!gameFallbackReason) {
|
|
1475
|
+
gameFallbackReason = "no_valid_action_in_llm_output";
|
|
1476
|
+
}
|
|
1315
1477
|
}
|
|
1316
1478
|
} catch (err) {
|
|
1317
1479
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -1328,29 +1490,34 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1328
1490
|
}
|
|
1329
1491
|
if (isGameEvent && gameMeta && !gameSubmitted) {
|
|
1330
1492
|
try {
|
|
1331
|
-
const fb = backendFallbackAction(gameMeta.agentTask);
|
|
1332
|
-
if (!fb) {
|
|
1333
|
-
ctx.log?.warn?.(
|
|
1334
|
-
`[GAME-ACTION] backend fallback unavailable eventType=${gameMeta.eventType} eventId=${gameMeta.eventId} reason=${gameFallbackReason ?? "unknown"} promptPolicyVersion=${gameMeta.promptPolicyVersion ?? ""} renderedPromptHash=${gameMeta.renderedPromptHash ?? ""}`
|
|
1335
|
-
);
|
|
1336
|
-
return;
|
|
1337
|
-
}
|
|
1338
1493
|
const rawResponse = gameBuffer.join("");
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1494
|
+
const inferred = inferRejectedModelAction(rawResponse, gameMeta.agentTask);
|
|
1495
|
+
gameModelActionRejected = gameModelActionRejected ?? inferred.modelActionRejected;
|
|
1496
|
+
gameModelActionType = gameModelActionType ?? inferred.modelActionType;
|
|
1497
|
+
gameValidationReason = gameValidationReason ?? inferred.validationReason;
|
|
1498
|
+
if (!gameFallbackReason || gameFallbackReason === "no_valid_action_in_llm_output") {
|
|
1499
|
+
gameFallbackReason = gameValidationReason ?? inferred.validationReason ?? gameFallbackReason;
|
|
1500
|
+
}
|
|
1501
|
+
const submitted = await submitBackendFallbackWithLog({
|
|
1502
|
+
meta: gameMeta,
|
|
1345
1503
|
wsClient,
|
|
1346
|
-
ctx.log,
|
|
1347
|
-
"
|
|
1348
|
-
rawResponse || void 0
|
|
1349
|
-
|
|
1504
|
+
log: ctx.log,
|
|
1505
|
+
reason: gameFallbackReason ?? gameValidationReason ?? inferred.validationReason ?? "unknown",
|
|
1506
|
+
rawResponse: rawResponse || void 0,
|
|
1507
|
+
auditMeta: {
|
|
1508
|
+
modelActionRejected: gameModelActionRejected,
|
|
1509
|
+
modelActionType: gameModelActionType,
|
|
1510
|
+
validationReason: gameFallbackReason ?? gameValidationReason ?? inferred.validationReason
|
|
1511
|
+
}
|
|
1512
|
+
});
|
|
1513
|
+
if (!submitted) {
|
|
1514
|
+
throw new Error(`game fallback submit failed: ${gameFallbackReason ?? "unknown"}`);
|
|
1515
|
+
}
|
|
1350
1516
|
} catch (fbErr) {
|
|
1351
1517
|
ctx.log?.error?.(
|
|
1352
1518
|
`[GAME-ACTION] fallback submit threw eventId=${gameMeta.eventId} err=${fbErr instanceof Error ? fbErr.message : String(fbErr)}`
|
|
1353
1519
|
);
|
|
1520
|
+
throw fbErr;
|
|
1354
1521
|
}
|
|
1355
1522
|
}
|
|
1356
1523
|
}
|
|
@@ -1362,6 +1529,7 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1362
1529
|
} catch (err) {
|
|
1363
1530
|
logAckFailure({ log: ctx.log?.warn?.bind(ctx.log) ?? (() => {
|
|
1364
1531
|
}), channel: "coolclaw", error: err });
|
|
1532
|
+
throw err;
|
|
1365
1533
|
}
|
|
1366
1534
|
}
|
|
1367
1535
|
});
|
package/dist/cli-metadata.js
CHANGED
package/dist/index.js
CHANGED
package/dist/setup-entry.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coolclaw/coolclaw",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "OpenClaw native channel plugin for Riddle/CoolClaw chat.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -38,7 +38,8 @@
|
|
|
38
38
|
"scripts": {
|
|
39
39
|
"build": "tsup index.ts setup-entry.ts cli-metadata.ts --format esm --dts --out-dir dist --clean --splitting",
|
|
40
40
|
"test": "vitest run",
|
|
41
|
-
"lint": "tsc --noEmit"
|
|
41
|
+
"lint": "tsc --noEmit",
|
|
42
|
+
"prepack": "npm run build"
|
|
42
43
|
},
|
|
43
44
|
"dependencies": {
|
|
44
45
|
"ws": "^8.20.1",
|
|
@@ -71,7 +72,7 @@
|
|
|
71
72
|
"runtimeSetupEntry": "./dist/setup-entry.js",
|
|
72
73
|
"install": {
|
|
73
74
|
"npmSpec": "@coolclaw/coolclaw",
|
|
74
|
-
"expectedIntegrity": "sha512-
|
|
75
|
+
"expectedIntegrity": "sha512-6q6+KPGtAkHBZGsHgqEXJtnwLdVoZNLrZNbxZmzKisZvItoE2y+Acl9v3bNtqtEK/DR5NLahyloy7FMRVt9Upg==",
|
|
75
76
|
"defaultChoice": "npm",
|
|
76
77
|
"minHostVersion": ">=2026.3.22"
|
|
77
78
|
},
|
|
@@ -99,4 +100,4 @@
|
|
|
99
100
|
"pluginSdkVersion": "2026.4.29"
|
|
100
101
|
}
|
|
101
102
|
}
|
|
102
|
-
}
|
|
103
|
+
}
|