@coolclaw/coolclaw 1.0.15 → 1.0.16
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 +19 -150
- package/dist/{chunk-R4H3YAWU.js → chunk-BVFSS5UA.js} +528 -91
- package/dist/{chunk-RCPRLBZL.js → chunk-TCWYIFNP.js} +13 -9
- package/dist/cli-metadata.js +2 -2
- package/dist/index.js +2 -2
- package/dist/setup-entry.js +1 -1
- package/openclaw.plugin.json +6 -6
- package/package.json +3 -19
|
@@ -1,10 +1,68 @@
|
|
|
1
|
+
// flavors/coolclaw.flavor.json
|
|
2
|
+
var coolclaw_flavor_default = {
|
|
3
|
+
productKey: "coolclaw",
|
|
4
|
+
displayName: "CoolClaw",
|
|
5
|
+
npmScope: "@coolclaw",
|
|
6
|
+
channelPackageName: "@coolclaw/coolclaw",
|
|
7
|
+
cliPackageName: "@coolclaw/coolclaw-cli",
|
|
8
|
+
skillsPackageName: "@coolclaw/coolclaw-skills",
|
|
9
|
+
channelId: "coolclaw",
|
|
10
|
+
pluginId: "coolclaw",
|
|
11
|
+
skillName: "coolclaw",
|
|
12
|
+
envPrefix: "COOLCLAW",
|
|
13
|
+
configDirName: "coolclaw",
|
|
14
|
+
defaultGatewayUrl: "https://agits-xa.baidu.com/riddle",
|
|
15
|
+
targetPrefix: "coolclaw"
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// flavors/clawtopia.flavor.json
|
|
19
|
+
var clawtopia_flavor_default = {
|
|
20
|
+
productKey: "clawtopia",
|
|
21
|
+
displayName: "Clawtopia",
|
|
22
|
+
npmScope: "@clawtopia",
|
|
23
|
+
channelPackageName: "@clawtopia/clawtopia",
|
|
24
|
+
cliPackageName: "@clawtopia/clawtopia-cli",
|
|
25
|
+
skillsPackageName: "@clawtopia/clawtopia-skills",
|
|
26
|
+
channelId: "clawtopia",
|
|
27
|
+
pluginId: "clawtopia",
|
|
28
|
+
skillName: "clawtopia",
|
|
29
|
+
envPrefix: "CLAWTOPIA",
|
|
30
|
+
configDirName: "clawtopia",
|
|
31
|
+
defaultGatewayUrl: "https://clawtopia.baidu.com/riddle",
|
|
32
|
+
targetPrefix: "clawtopia"
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// src/flavor-build.ts
|
|
36
|
+
var BUILT_PRODUCT_FLAVOR = "coolclaw";
|
|
37
|
+
|
|
38
|
+
// src/flavor.ts
|
|
39
|
+
var FLAVORS = {
|
|
40
|
+
coolclaw: coolclaw_flavor_default,
|
|
41
|
+
clawtopia: clawtopia_flavor_default
|
|
42
|
+
};
|
|
43
|
+
function getFlavorByKey(key) {
|
|
44
|
+
const flavor = FLAVORS[key];
|
|
45
|
+
if (!flavor) {
|
|
46
|
+
throw new Error(`Unknown PRODUCT_FLAVOR: ${key}`);
|
|
47
|
+
}
|
|
48
|
+
return flavor;
|
|
49
|
+
}
|
|
50
|
+
function activeFlavor(env = process.env) {
|
|
51
|
+
return getFlavorByKey(env.PRODUCT_FLAVOR ?? BUILT_PRODUCT_FLAVOR);
|
|
52
|
+
}
|
|
53
|
+
function resolveFlavor(input) {
|
|
54
|
+
if (!input) return activeFlavor();
|
|
55
|
+
return typeof input === "string" ? getFlavorByKey(input) : input;
|
|
56
|
+
}
|
|
57
|
+
|
|
1
58
|
// src/binding.ts
|
|
2
59
|
import { mkdir, readFile, rename, writeFile, chmod } from "fs/promises";
|
|
3
60
|
import { homedir } from "os";
|
|
4
61
|
import path from "path";
|
|
5
62
|
import { fileURLToPath } from "url";
|
|
6
|
-
function defaultBindingFile(home = homedir()) {
|
|
7
|
-
|
|
63
|
+
function defaultBindingFile(home = homedir(), flavorInput) {
|
|
64
|
+
const flavor = resolveFlavor(flavorInput);
|
|
65
|
+
return path.join(home, ".config", flavor.configDirName, "agent_binding.json");
|
|
8
66
|
}
|
|
9
67
|
async function readTokenRef(tokenRef) {
|
|
10
68
|
if (!tokenRef) return void 0;
|
|
@@ -358,14 +416,19 @@ function isRecord2(value) {
|
|
|
358
416
|
// src/inbound.ts
|
|
359
417
|
var ARENA_REPORT_SHARE_NOTIFY_TYPE = "ARENA_REPORT_SHARE_REQUEST";
|
|
360
418
|
var ARENA_MODEL_QUERY_NOTIFY_TYPE = "ARENA_MODEL_QUERY_REQUEST";
|
|
419
|
+
var ARENA_VOICE_SELECT_NOTIFY_TYPE = "ARENA_VOICE_SELECT_REQUEST";
|
|
361
420
|
var REPORT_SHARE_DEDUPE_LIMIT = 500;
|
|
362
421
|
var MODEL_QUERY_DEDUPE_LIMIT = 500;
|
|
422
|
+
var VOICE_SELECT_DEDUPE_LIMIT = 500;
|
|
363
423
|
var processedArenaReportShareEventIds = /* @__PURE__ */ new Set();
|
|
364
424
|
var processedArenaReportShareEventOrder = [];
|
|
365
425
|
var inFlightArenaReportShareEventIds = /* @__PURE__ */ new Map();
|
|
366
426
|
var processedArenaModelQueryEventIds = /* @__PURE__ */ new Set();
|
|
367
427
|
var processedArenaModelQueryEventOrder = [];
|
|
368
428
|
var inFlightArenaModelQueryEventIds = /* @__PURE__ */ new Map();
|
|
429
|
+
var processedArenaVoiceSelectEventIds = /* @__PURE__ */ new Set();
|
|
430
|
+
var processedArenaVoiceSelectEventOrder = [];
|
|
431
|
+
var inFlightArenaVoiceSelectEventIds = /* @__PURE__ */ new Map();
|
|
369
432
|
function mapInboundFrame(frame) {
|
|
370
433
|
if (frame.type === "PRIVATE_MESSAGE") {
|
|
371
434
|
const payload = assertPrivatePayload(frame.payload);
|
|
@@ -441,6 +504,13 @@ async function handleInboundFrame(input) {
|
|
|
441
504
|
inFlight: inFlightArenaModelQueryEventIds,
|
|
442
505
|
remember: rememberArenaModelQueryEventId
|
|
443
506
|
};
|
|
507
|
+
} else if (isArenaVoiceSelectEnvelope(envelope)) {
|
|
508
|
+
dedupeState = {
|
|
509
|
+
eventId: String(envelope.metadata.eventId),
|
|
510
|
+
processed: processedArenaVoiceSelectEventIds,
|
|
511
|
+
inFlight: inFlightArenaVoiceSelectEventIds,
|
|
512
|
+
remember: rememberArenaVoiceSelectEventId
|
|
513
|
+
};
|
|
444
514
|
}
|
|
445
515
|
if (dedupeState) {
|
|
446
516
|
if (dedupeState.processed.has(dedupeState.eventId)) {
|
|
@@ -493,6 +563,9 @@ function isArenaReportShareEnvelope(envelope) {
|
|
|
493
563
|
function isArenaModelQueryEnvelope(envelope) {
|
|
494
564
|
return envelope.metadata?.arenaModelQueryRequest === true && typeof envelope.metadata.eventId === "string" && envelope.metadata.eventId.length > 0 && typeof envelope.metadata.callbackUrl === "string" && envelope.metadata.callbackUrl.length > 0;
|
|
495
565
|
}
|
|
566
|
+
function isArenaVoiceSelectEnvelope(envelope) {
|
|
567
|
+
return envelope.metadata?.arenaVoiceSelectRequest === true && typeof envelope.metadata.eventId === "string" && envelope.metadata.eventId.length > 0 && typeof envelope.metadata.callbackUrl === "string" && envelope.metadata.callbackUrl.length > 0;
|
|
568
|
+
}
|
|
496
569
|
function mapNotificationFrame(frame) {
|
|
497
570
|
const payload = isRecord3(frame.payload) ? frame.payload : {};
|
|
498
571
|
const seq = typeof payload.seq === "number" ? payload.seq : void 0;
|
|
@@ -534,6 +607,9 @@ function mapNotificationFrame(frame) {
|
|
|
534
607
|
if (notifyType === ARENA_MODEL_QUERY_NOTIFY_TYPE) {
|
|
535
608
|
return mapArenaModelQueryFrame(frame, payload, seq);
|
|
536
609
|
}
|
|
610
|
+
if (notifyType === ARENA_VOICE_SELECT_NOTIFY_TYPE) {
|
|
611
|
+
return mapArenaVoiceSelectFrame(frame, payload, seq);
|
|
612
|
+
}
|
|
537
613
|
const postId = payload.postId != null ? String(payload.postId) : "";
|
|
538
614
|
return {
|
|
539
615
|
id: frame.id,
|
|
@@ -548,6 +624,43 @@ function mapNotificationFrame(frame) {
|
|
|
548
624
|
}
|
|
549
625
|
return null;
|
|
550
626
|
}
|
|
627
|
+
function mapArenaVoiceSelectFrame(frame, payload, seq) {
|
|
628
|
+
const voicePayload = isRecord3(payload.payload) ? payload.payload : {};
|
|
629
|
+
const eventId = firstText(payload.eventId, voicePayload.eventId) ?? frame.id;
|
|
630
|
+
const traceId = typeof payload.traceId === "string" ? payload.traceId : "";
|
|
631
|
+
const roomId = Number(voicePayload.roomId ?? 0);
|
|
632
|
+
const seatNumber = Number(voicePayload.seatNumber ?? 0);
|
|
633
|
+
const seatEpoch = voicePayload.seatEpoch != null ? String(voicePayload.seatEpoch) : "";
|
|
634
|
+
const callbackUrl = typeof voicePayload.callbackUrl === "string" ? voicePayload.callbackUrl : "";
|
|
635
|
+
if (!callbackUrl || !roomId || !seatNumber || !seatEpoch) {
|
|
636
|
+
return null;
|
|
637
|
+
}
|
|
638
|
+
const deadlineEpochMs = Number(voicePayload.deadlineEpochMs ?? 0);
|
|
639
|
+
const voiceOptions = Array.isArray(voicePayload.voiceOptions) ? voicePayload.voiceOptions.filter(isRecord3).map((option) => option) : [];
|
|
640
|
+
return {
|
|
641
|
+
id: eventId,
|
|
642
|
+
channel: "coolclaw",
|
|
643
|
+
conversationId: `notification:arena_voice_select:${eventId}`,
|
|
644
|
+
text: "/arena-voice-select",
|
|
645
|
+
messageType: frame.type,
|
|
646
|
+
seq,
|
|
647
|
+
shouldReply: true,
|
|
648
|
+
metadata: {
|
|
649
|
+
sourceFrameId: frame.id,
|
|
650
|
+
payload: frame.payload,
|
|
651
|
+
voiceSelectPayload: voicePayload,
|
|
652
|
+
arenaVoiceSelectRequest: true,
|
|
653
|
+
eventId,
|
|
654
|
+
traceId,
|
|
655
|
+
roomId,
|
|
656
|
+
seatNumber,
|
|
657
|
+
seatEpoch,
|
|
658
|
+
callbackUrl,
|
|
659
|
+
deadlineEpochMs,
|
|
660
|
+
voiceOptions
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
}
|
|
551
664
|
function mapArenaModelQueryFrame(frame, payload, seq) {
|
|
552
665
|
const eventId = typeof payload.eventId === "string" && payload.eventId.length > 0 ? payload.eventId : frame.id;
|
|
553
666
|
const traceId = typeof payload.traceId === "string" ? payload.traceId : "";
|
|
@@ -583,6 +696,14 @@ function mapArenaModelQueryFrame(frame, payload, seq) {
|
|
|
583
696
|
}
|
|
584
697
|
};
|
|
585
698
|
}
|
|
699
|
+
function firstText(...values) {
|
|
700
|
+
for (const value of values) {
|
|
701
|
+
if (typeof value === "string" && value.length > 0) {
|
|
702
|
+
return value;
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
return null;
|
|
706
|
+
}
|
|
586
707
|
function mapArenaReportShareFrame(frame, payload, seq) {
|
|
587
708
|
const eventId = typeof payload.eventId === "string" && payload.eventId.length > 0 ? payload.eventId : frame.id;
|
|
588
709
|
const traceId = typeof payload.traceId === "string" ? payload.traceId : "";
|
|
@@ -624,6 +745,15 @@ function rememberArenaModelQueryEventId(eventId) {
|
|
|
624
745
|
if (expired) processedArenaModelQueryEventIds.delete(expired);
|
|
625
746
|
}
|
|
626
747
|
}
|
|
748
|
+
function rememberArenaVoiceSelectEventId(eventId) {
|
|
749
|
+
if (processedArenaVoiceSelectEventIds.has(eventId)) return;
|
|
750
|
+
processedArenaVoiceSelectEventIds.add(eventId);
|
|
751
|
+
processedArenaVoiceSelectEventOrder.push(eventId);
|
|
752
|
+
while (processedArenaVoiceSelectEventOrder.length > VOICE_SELECT_DEDUPE_LIMIT) {
|
|
753
|
+
const expired = processedArenaVoiceSelectEventOrder.shift();
|
|
754
|
+
if (expired) processedArenaVoiceSelectEventIds.delete(expired);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
627
757
|
function mapGameEventFrame(frame, payload) {
|
|
628
758
|
const eventType = typeof payload.eventType === "string" ? payload.eventType : "UNKNOWN";
|
|
629
759
|
const agentTask = normalizeAgentTask(payload.agentTask);
|
|
@@ -782,15 +912,16 @@ var TargetParseError = class extends Error {
|
|
|
782
912
|
this.name = "TargetParseError";
|
|
783
913
|
}
|
|
784
914
|
};
|
|
785
|
-
function parseCoolclawTarget(raw) {
|
|
786
|
-
const
|
|
915
|
+
function parseCoolclawTarget(raw, flavorInput) {
|
|
916
|
+
const flavor = resolveFlavor(flavorInput);
|
|
917
|
+
const normalized = normalizeCoolclawTarget(raw, flavor);
|
|
787
918
|
const parts = normalized.split(":");
|
|
788
919
|
if (parts.length !== 3) {
|
|
789
|
-
throw new TargetParseError(`Invalid
|
|
920
|
+
throw new TargetParseError(`Invalid ${flavor.displayName} target: ${raw}`);
|
|
790
921
|
}
|
|
791
922
|
const [channel, type, id] = parts;
|
|
792
|
-
if (channel !==
|
|
793
|
-
throw new TargetParseError(`Invalid
|
|
923
|
+
if (channel !== flavor.targetPrefix || id.length === 0) {
|
|
924
|
+
throw new TargetParseError(`Invalid ${flavor.displayName} target: ${raw}`);
|
|
794
925
|
}
|
|
795
926
|
if (type === "human") {
|
|
796
927
|
return { kind: "private", userType: "HUMAN", userId: id };
|
|
@@ -801,9 +932,10 @@ function parseCoolclawTarget(raw) {
|
|
|
801
932
|
if (type === "group") {
|
|
802
933
|
return { kind: "group", groupId: id };
|
|
803
934
|
}
|
|
804
|
-
throw new TargetParseError(`Invalid
|
|
935
|
+
throw new TargetParseError(`Invalid ${flavor.displayName} target type: ${type}`);
|
|
805
936
|
}
|
|
806
|
-
function normalizeCoolclawTarget(raw) {
|
|
937
|
+
function normalizeCoolclawTarget(raw, flavorInput) {
|
|
938
|
+
resolveFlavor(flavorInput);
|
|
807
939
|
const trimmed = raw.trim();
|
|
808
940
|
const parts = trimmed.split(":");
|
|
809
941
|
if (parts.length !== 3) {
|
|
@@ -812,25 +944,27 @@ function normalizeCoolclawTarget(raw) {
|
|
|
812
944
|
const [channel, type, id] = parts;
|
|
813
945
|
return `${channel.toLowerCase()}:${type.toLowerCase()}:${id.trim()}`;
|
|
814
946
|
}
|
|
815
|
-
function inferCoolclawTargetChatType(raw) {
|
|
947
|
+
function inferCoolclawTargetChatType(raw, flavorInput) {
|
|
816
948
|
try {
|
|
817
|
-
const target = parseCoolclawTarget(raw);
|
|
949
|
+
const target = parseCoolclawTarget(raw, flavorInput);
|
|
818
950
|
return target.kind === "private" ? "direct" : "group";
|
|
819
951
|
} catch {
|
|
820
952
|
return void 0;
|
|
821
953
|
}
|
|
822
954
|
}
|
|
823
|
-
function isCoolclawTargetId(raw, normalized = normalizeCoolclawTarget(raw)) {
|
|
955
|
+
function isCoolclawTargetId(raw, normalized = normalizeCoolclawTarget(raw), flavorInput) {
|
|
956
|
+
const flavor = resolveFlavor(flavorInput);
|
|
824
957
|
try {
|
|
825
|
-
parseCoolclawTarget(normalized);
|
|
826
|
-
return normalized.startsWith(
|
|
958
|
+
parseCoolclawTarget(normalized, flavor);
|
|
959
|
+
return normalized.startsWith(`${flavor.targetPrefix}:`);
|
|
827
960
|
} catch {
|
|
828
961
|
return false;
|
|
829
962
|
}
|
|
830
963
|
}
|
|
831
|
-
async function resolveCoolclawMessagingTarget(raw, preferredKind) {
|
|
832
|
-
const
|
|
833
|
-
const
|
|
964
|
+
async function resolveCoolclawMessagingTarget(raw, preferredKind, flavorInput) {
|
|
965
|
+
const flavor = resolveFlavor(flavorInput);
|
|
966
|
+
const normalized = normalizeCoolclawTarget(raw, flavor);
|
|
967
|
+
const target = parseCoolclawTarget(normalized, flavor);
|
|
834
968
|
const kind = target.kind === "private" ? "user" : "group";
|
|
835
969
|
if (preferredKind && preferredKind !== kind) {
|
|
836
970
|
return null;
|
|
@@ -1207,6 +1341,223 @@ function isRecord4(value) {
|
|
|
1207
1341
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1208
1342
|
}
|
|
1209
1343
|
|
|
1344
|
+
// src/arena-voice-select.ts
|
|
1345
|
+
var FALLBACK_REASON = "\u672A\u89E3\u6790\u5230\u6A21\u578B\u97F3\u8272\u504F\u597D\uFF0C\u4EA4\u7531\u540E\u7AEF\u515C\u5E95\u9009\u62E9\u3002";
|
|
1346
|
+
var DEFAULT_REASON = "\u57FA\u4E8E\u6A21\u578B\u8F93\u51FA\u9009\u62E9\u5019\u9009\u73A9\u5BB6\u97F3\u8272\u3002";
|
|
1347
|
+
function parseArenaVoiceSelection(rawText, voiceOptions) {
|
|
1348
|
+
const structured = parseStructuredVoiceSelection(rawText, voiceOptions);
|
|
1349
|
+
if (structured) return structured;
|
|
1350
|
+
const topVoiceIds = extractVoiceIdsFromText(rawText, voiceOptions);
|
|
1351
|
+
return {
|
|
1352
|
+
topVoiceIds,
|
|
1353
|
+
reason: topVoiceIds.length > 0 ? DEFAULT_REASON : FALLBACK_REASON
|
|
1354
|
+
};
|
|
1355
|
+
}
|
|
1356
|
+
async function submitArenaVoiceSelectCallback(input) {
|
|
1357
|
+
const start = Date.now();
|
|
1358
|
+
const rawHash = input.rawText ? sha256Hex(input.rawText) : "";
|
|
1359
|
+
const rawPreview = rawResponsePreview(input.rawText) ?? "";
|
|
1360
|
+
const selection = parseArenaVoiceSelection(input.rawText, input.meta.voiceOptions);
|
|
1361
|
+
try {
|
|
1362
|
+
if (!input.meta.callbackUrl || !input.token) {
|
|
1363
|
+
input.log?.warn?.(
|
|
1364
|
+
`[ARENA-VOICE] callback skipped eventId=${input.meta.eventId} reason=missing_callback_or_token rawHash=${rawHash} rawPreview=${rawPreview}`
|
|
1365
|
+
);
|
|
1366
|
+
return { ok: false, error: "missing_callback_or_token" };
|
|
1367
|
+
}
|
|
1368
|
+
const fetchImpl = input.fetchImpl ?? globalThis.fetch;
|
|
1369
|
+
if (typeof fetchImpl !== "function") {
|
|
1370
|
+
input.log?.warn?.(`[ARENA-VOICE] callback skipped eventId=${input.meta.eventId} reason=fetch_unavailable`);
|
|
1371
|
+
return { ok: false, error: "fetch_unavailable" };
|
|
1372
|
+
}
|
|
1373
|
+
const response = await fetchImpl(input.meta.callbackUrl, {
|
|
1374
|
+
method: "POST",
|
|
1375
|
+
headers: {
|
|
1376
|
+
Authorization: `Bearer ${input.token}`,
|
|
1377
|
+
"Content-Type": "application/json"
|
|
1378
|
+
},
|
|
1379
|
+
body: JSON.stringify({
|
|
1380
|
+
eventId: input.meta.eventId,
|
|
1381
|
+
roomId: input.meta.roomId,
|
|
1382
|
+
seatNumber: input.meta.seatNumber,
|
|
1383
|
+
seatEpoch: input.meta.seatEpoch,
|
|
1384
|
+
topVoiceIds: selection.topVoiceIds,
|
|
1385
|
+
reason: selection.reason
|
|
1386
|
+
})
|
|
1387
|
+
});
|
|
1388
|
+
const body = await readJsonObject2(response);
|
|
1389
|
+
const data = isRecord5(body.data) ? body.data : body;
|
|
1390
|
+
const accepted = data.accepted === true;
|
|
1391
|
+
const result = { ok: response.ok, status: response.status, accepted };
|
|
1392
|
+
const level = response.ok ? "info" : "warn";
|
|
1393
|
+
input.log?.[level]?.(
|
|
1394
|
+
`[ARENA-VOICE] callback status=${response.status} accepted=${accepted} eventId=${input.meta.eventId} roomId=${input.meta.roomId} seatEpoch=${input.meta.seatEpoch} selected=${selection.topVoiceIds.length} elapsedMs=${Date.now() - start} rawHash=${rawHash} rawPreview=${rawPreview}`
|
|
1395
|
+
);
|
|
1396
|
+
return result;
|
|
1397
|
+
} catch (error) {
|
|
1398
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1399
|
+
input.log?.warn?.(
|
|
1400
|
+
`[ARENA-VOICE] callback failed eventId=${input.meta.eventId} roomId=${input.meta.roomId} seatEpoch=${input.meta.seatEpoch} elapsedMs=${Date.now() - start} err=${message} rawHash=${rawHash} rawPreview=${rawPreview}`
|
|
1401
|
+
);
|
|
1402
|
+
return { ok: false, error: message };
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
function createArenaVoiceSelectReplyCollector(input) {
|
|
1406
|
+
const blocks = [];
|
|
1407
|
+
let submitted = false;
|
|
1408
|
+
const submit = input.submit ?? ((rawText) => submitArenaVoiceSelectCallback({
|
|
1409
|
+
meta: input.meta,
|
|
1410
|
+
token: input.token,
|
|
1411
|
+
rawText,
|
|
1412
|
+
log: input.log
|
|
1413
|
+
}));
|
|
1414
|
+
async function submitOnce(rawText, reason) {
|
|
1415
|
+
if (submitted) return;
|
|
1416
|
+
submitted = true;
|
|
1417
|
+
const parsed = parseArenaVoiceSelection(rawText, input.meta.voiceOptions);
|
|
1418
|
+
input.log?.info?.(
|
|
1419
|
+
`[ARENA-VOICE] dispatch submit reason=${reason} eventId=${input.meta.eventId} roomId=${input.meta.roomId} seatEpoch=${input.meta.seatEpoch} blocks=${blocks.length} selected=${parsed.topVoiceIds.length}`
|
|
1420
|
+
);
|
|
1421
|
+
await submit(rawText);
|
|
1422
|
+
}
|
|
1423
|
+
return {
|
|
1424
|
+
async deliver(text) {
|
|
1425
|
+
if (submitted || !text) return;
|
|
1426
|
+
blocks.push(text);
|
|
1427
|
+
const full = blocks.join("");
|
|
1428
|
+
const structured = parseStructuredVoiceSelection(full, input.meta.voiceOptions);
|
|
1429
|
+
input.log?.info?.(
|
|
1430
|
+
`[ARENA-VOICE] dispatch block eventId=${input.meta.eventId} roomId=${input.meta.roomId} seatEpoch=${input.meta.seatEpoch} blocks=${blocks.length} parsed=${structured?.topVoiceIds.length ? "true" : "false"}`
|
|
1431
|
+
);
|
|
1432
|
+
if (structured?.topVoiceIds.length) {
|
|
1433
|
+
await submitOnce(full, "parsed");
|
|
1434
|
+
}
|
|
1435
|
+
},
|
|
1436
|
+
async finalize() {
|
|
1437
|
+
if (submitted) return;
|
|
1438
|
+
await submitOnce(blocks.join(""), "final");
|
|
1439
|
+
}
|
|
1440
|
+
};
|
|
1441
|
+
}
|
|
1442
|
+
function parseStructuredVoiceSelection(rawText, voiceOptions) {
|
|
1443
|
+
if (!rawText) return null;
|
|
1444
|
+
const body = parseFirstJsonObject(rawText);
|
|
1445
|
+
if (!body) return null;
|
|
1446
|
+
const rawIds = Array.isArray(body.topVoiceIds) ? body.topVoiceIds : [];
|
|
1447
|
+
const topVoiceIds = sanitizeVoiceIds(rawIds, voiceOptions);
|
|
1448
|
+
const reason = normalizeReason(body.reason);
|
|
1449
|
+
if (topVoiceIds.length === 0 && !reason) return null;
|
|
1450
|
+
return {
|
|
1451
|
+
topVoiceIds,
|
|
1452
|
+
reason: reason || (topVoiceIds.length > 0 ? DEFAULT_REASON : FALLBACK_REASON)
|
|
1453
|
+
};
|
|
1454
|
+
}
|
|
1455
|
+
function extractVoiceIdsFromText(rawText, voiceOptions) {
|
|
1456
|
+
if (!rawText) return [];
|
|
1457
|
+
const allowed = allowedVoiceIds(voiceOptions);
|
|
1458
|
+
const result = [];
|
|
1459
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1460
|
+
const regex = /\b\d{3,8}\b/g;
|
|
1461
|
+
for (const match of rawText.matchAll(regex)) {
|
|
1462
|
+
const voiceId = match[0];
|
|
1463
|
+
if (!allowed.has(voiceId) || seen.has(voiceId)) continue;
|
|
1464
|
+
seen.add(voiceId);
|
|
1465
|
+
result.push(voiceId);
|
|
1466
|
+
if (result.length >= 3) break;
|
|
1467
|
+
}
|
|
1468
|
+
return result;
|
|
1469
|
+
}
|
|
1470
|
+
function sanitizeVoiceIds(rawIds, voiceOptions) {
|
|
1471
|
+
const allowed = allowedVoiceIds(voiceOptions);
|
|
1472
|
+
const result = [];
|
|
1473
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1474
|
+
for (const rawId of rawIds) {
|
|
1475
|
+
const voiceId = typeof rawId === "string" ? rawId.trim() : "";
|
|
1476
|
+
if (!voiceId || !allowed.has(voiceId) || seen.has(voiceId)) continue;
|
|
1477
|
+
seen.add(voiceId);
|
|
1478
|
+
result.push(voiceId);
|
|
1479
|
+
if (result.length >= 3) break;
|
|
1480
|
+
}
|
|
1481
|
+
return result;
|
|
1482
|
+
}
|
|
1483
|
+
function allowedVoiceIds(voiceOptions) {
|
|
1484
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1485
|
+
if (!Array.isArray(voiceOptions)) return ids;
|
|
1486
|
+
for (const option of voiceOptions) {
|
|
1487
|
+
const voiceId = typeof option?.voiceId === "string" ? option.voiceId.trim() : "";
|
|
1488
|
+
if (voiceId) ids.add(voiceId);
|
|
1489
|
+
}
|
|
1490
|
+
return ids;
|
|
1491
|
+
}
|
|
1492
|
+
function normalizeReason(value) {
|
|
1493
|
+
if (typeof value !== "string") return "";
|
|
1494
|
+
return value.replace(/\s+/g, " ").trim().slice(0, 160);
|
|
1495
|
+
}
|
|
1496
|
+
function parseFirstJsonObject(rawText) {
|
|
1497
|
+
const direct = tryParseJsonObject(rawText.trim());
|
|
1498
|
+
if (direct) return direct;
|
|
1499
|
+
const candidates = extractJsonObjectCandidates(rawText);
|
|
1500
|
+
for (const candidate of candidates) {
|
|
1501
|
+
const parsed = tryParseJsonObject(candidate);
|
|
1502
|
+
if (parsed) return parsed;
|
|
1503
|
+
}
|
|
1504
|
+
return null;
|
|
1505
|
+
}
|
|
1506
|
+
function extractJsonObjectCandidates(rawText) {
|
|
1507
|
+
const candidates = [];
|
|
1508
|
+
let start = -1;
|
|
1509
|
+
let depth = 0;
|
|
1510
|
+
let inString = false;
|
|
1511
|
+
let escaped = false;
|
|
1512
|
+
for (let index = 0; index < rawText.length; index += 1) {
|
|
1513
|
+
const char = rawText[index];
|
|
1514
|
+
if (inString) {
|
|
1515
|
+
if (escaped) {
|
|
1516
|
+
escaped = false;
|
|
1517
|
+
} else if (char === "\\") {
|
|
1518
|
+
escaped = true;
|
|
1519
|
+
} else if (char === '"') {
|
|
1520
|
+
inString = false;
|
|
1521
|
+
}
|
|
1522
|
+
continue;
|
|
1523
|
+
}
|
|
1524
|
+
if (char === '"') {
|
|
1525
|
+
inString = true;
|
|
1526
|
+
continue;
|
|
1527
|
+
}
|
|
1528
|
+
if (char === "{") {
|
|
1529
|
+
if (depth === 0) start = index;
|
|
1530
|
+
depth += 1;
|
|
1531
|
+
} else if (char === "}" && depth > 0) {
|
|
1532
|
+
depth -= 1;
|
|
1533
|
+
if (depth === 0 && start >= 0) {
|
|
1534
|
+
candidates.push(rawText.slice(start, index + 1));
|
|
1535
|
+
start = -1;
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
return candidates;
|
|
1540
|
+
}
|
|
1541
|
+
async function readJsonObject2(response) {
|
|
1542
|
+
try {
|
|
1543
|
+
const body = await response.json();
|
|
1544
|
+
return isRecord5(body) ? body : {};
|
|
1545
|
+
} catch {
|
|
1546
|
+
return {};
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
function isRecord5(value) {
|
|
1550
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1551
|
+
}
|
|
1552
|
+
function tryParseJsonObject(value) {
|
|
1553
|
+
try {
|
|
1554
|
+
const parsed = JSON.parse(value);
|
|
1555
|
+
return isRecord5(parsed) ? parsed : null;
|
|
1556
|
+
} catch {
|
|
1557
|
+
return null;
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1210
1561
|
// src/ws-client.ts
|
|
1211
1562
|
import WebSocket from "ws";
|
|
1212
1563
|
var CoolclawWsClient = class {
|
|
@@ -1419,18 +1770,18 @@ var CoolclawWsClient = class {
|
|
|
1419
1770
|
}
|
|
1420
1771
|
};
|
|
1421
1772
|
function readPingInterval(payload) {
|
|
1422
|
-
if (!
|
|
1773
|
+
if (!isRecord6(payload) || typeof payload.pingIntervalMs !== "number" || payload.pingIntervalMs <= 0) {
|
|
1423
1774
|
return void 0;
|
|
1424
1775
|
}
|
|
1425
1776
|
return payload.pingIntervalMs;
|
|
1426
1777
|
}
|
|
1427
1778
|
function readErrorMessage(payload) {
|
|
1428
|
-
if (
|
|
1779
|
+
if (isRecord6(payload) && typeof payload.message === "string") {
|
|
1429
1780
|
return payload.message;
|
|
1430
1781
|
}
|
|
1431
1782
|
return "CoolClaw request failed";
|
|
1432
1783
|
}
|
|
1433
|
-
function
|
|
1784
|
+
function isRecord6(value) {
|
|
1434
1785
|
return typeof value === "object" && value !== null;
|
|
1435
1786
|
}
|
|
1436
1787
|
|
|
@@ -1452,9 +1803,12 @@ function getPluginVersion() {
|
|
|
1452
1803
|
}
|
|
1453
1804
|
|
|
1454
1805
|
// src/channel.ts
|
|
1806
|
+
import { homedir as homedir3 } from "os";
|
|
1807
|
+
import path2 from "path";
|
|
1455
1808
|
import {
|
|
1456
1809
|
createChatChannelPlugin
|
|
1457
1810
|
} from "openclaw/plugin-sdk/core";
|
|
1811
|
+
var productFlavor = activeFlavor();
|
|
1458
1812
|
function createAccountStatusSink(params) {
|
|
1459
1813
|
return (patch) => {
|
|
1460
1814
|
params.setStatus({ accountId: params.accountId, ...patch });
|
|
@@ -1587,7 +1941,7 @@ function isNoReplyText(text) {
|
|
|
1587
1941
|
return lastLine ? noReplyTokens.has(lastLine) : false;
|
|
1588
1942
|
}
|
|
1589
1943
|
function shouldSuppressCoolclawTextDelivery(envelope) {
|
|
1590
|
-
return envelope.metadata?.gameEvent === true || isArenaReportShareEnvelope(envelope) || isArenaModelQueryEnvelope(envelope);
|
|
1944
|
+
return envelope.metadata?.gameEvent === true || isArenaReportShareEnvelope(envelope) || isArenaModelQueryEnvelope(envelope) || isArenaVoiceSelectEnvelope(envelope);
|
|
1591
1945
|
}
|
|
1592
1946
|
async function finalizeArenaModelQueryAfterDispatchError(params) {
|
|
1593
1947
|
if (!params.collector) {
|
|
@@ -1609,19 +1963,19 @@ function clearRuntimeClient(accountKey) {
|
|
|
1609
1963
|
runtimeClients.delete(accountKey);
|
|
1610
1964
|
}
|
|
1611
1965
|
function extractAccountFromConfig(cfg, accountId) {
|
|
1612
|
-
const
|
|
1613
|
-
const accounts =
|
|
1966
|
+
const channelSection = cfg.channels?.[productFlavor.channelId];
|
|
1967
|
+
const accounts = channelSection?.accounts;
|
|
1614
1968
|
return accounts?.[accountId ?? "default"] ?? {};
|
|
1615
1969
|
}
|
|
1616
1970
|
var coolclawChannelPlugin = createChatChannelPlugin({
|
|
1617
1971
|
base: {
|
|
1618
|
-
id:
|
|
1972
|
+
id: productFlavor.channelId,
|
|
1619
1973
|
meta: {
|
|
1620
|
-
id:
|
|
1621
|
-
label:
|
|
1622
|
-
selectionLabel:
|
|
1623
|
-
docsPath:
|
|
1624
|
-
blurb:
|
|
1974
|
+
id: productFlavor.channelId,
|
|
1975
|
+
label: productFlavor.displayName,
|
|
1976
|
+
selectionLabel: productFlavor.displayName,
|
|
1977
|
+
docsPath: `/plugins/${productFlavor.channelId}`,
|
|
1978
|
+
blurb: `Connect OpenClaw to the ${productFlavor.displayName} chat platform.`
|
|
1625
1979
|
},
|
|
1626
1980
|
capabilities: {
|
|
1627
1981
|
chatTypes: ["direct", "group"],
|
|
@@ -1636,15 +1990,15 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1636
1990
|
},
|
|
1637
1991
|
agentPrompt: {
|
|
1638
1992
|
messageToolHints: () => [
|
|
1639
|
-
|
|
1993
|
+
`To send a message on ${productFlavor.displayName}, use the message tool with action='send' and set 'to' to a ${productFlavor.displayName} target like '${productFlavor.targetPrefix}:human:<userId>', '${productFlavor.targetPrefix}:agent:<agentId>', or '${productFlavor.targetPrefix}:group:<groupId>'.`,
|
|
1640
1994
|
"To send an image or file, use the message tool with action='send' and set 'media' to a local file path or a remote URL.",
|
|
1641
|
-
|
|
1642
|
-
|
|
1995
|
+
`When sending a message to a ${productFlavor.displayName} group, the agent will only reply if it was mentioned in the group message.`,
|
|
1996
|
+
`When creating a cron job for ${productFlavor.displayName}, set delivery.to to the target ${productFlavor.displayName} ID and delivery.accountId to the current accountId.`
|
|
1643
1997
|
]
|
|
1644
1998
|
},
|
|
1645
1999
|
config: {
|
|
1646
2000
|
listAccountIds(cfg) {
|
|
1647
|
-
return Object.keys(cfg.channels?.
|
|
2001
|
+
return Object.keys(cfg.channels?.[productFlavor.channelId]?.accounts ?? {});
|
|
1648
2002
|
},
|
|
1649
2003
|
resolveAccount(cfg, accountId) {
|
|
1650
2004
|
return extractAccountFromConfig(cfg, accountId);
|
|
@@ -1676,9 +2030,9 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1676
2030
|
async resolveTargets({ inputs }) {
|
|
1677
2031
|
return inputs.map((input) => {
|
|
1678
2032
|
try {
|
|
1679
|
-
const normalized = normalizeCoolclawTarget(input);
|
|
2033
|
+
const normalized = normalizeCoolclawTarget(input, productFlavor);
|
|
1680
2034
|
const [, type, id] = normalized.split(":");
|
|
1681
|
-
parseCoolclawTarget(normalized);
|
|
2035
|
+
parseCoolclawTarget(normalized, productFlavor);
|
|
1682
2036
|
return { input, resolved: true, id: normalized, name: `${type}:${id}` };
|
|
1683
2037
|
} catch (error) {
|
|
1684
2038
|
return { input, resolved: false, note: error instanceof Error ? error.message : String(error) };
|
|
@@ -1689,23 +2043,23 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1689
2043
|
messaging: {
|
|
1690
2044
|
normalizeTarget(raw) {
|
|
1691
2045
|
try {
|
|
1692
|
-
const normalized = normalizeCoolclawTarget(raw);
|
|
1693
|
-
parseCoolclawTarget(normalized);
|
|
2046
|
+
const normalized = normalizeCoolclawTarget(raw, productFlavor);
|
|
2047
|
+
parseCoolclawTarget(normalized, productFlavor);
|
|
1694
2048
|
return normalized;
|
|
1695
2049
|
} catch {
|
|
1696
2050
|
return void 0;
|
|
1697
2051
|
}
|
|
1698
2052
|
},
|
|
1699
2053
|
inferTargetChatType({ to }) {
|
|
1700
|
-
return inferCoolclawTargetChatType(to);
|
|
2054
|
+
return inferCoolclawTargetChatType(to, productFlavor);
|
|
1701
2055
|
},
|
|
1702
2056
|
targetResolver: {
|
|
1703
|
-
hint:
|
|
2057
|
+
hint: `Use ${productFlavor.targetPrefix}:human:<id>, ${productFlavor.targetPrefix}:agent:<id>, or ${productFlavor.targetPrefix}:group:<id>.`,
|
|
1704
2058
|
looksLikeId(raw, normalized) {
|
|
1705
|
-
return isCoolclawTargetId(raw, normalized);
|
|
2059
|
+
return isCoolclawTargetId(raw, normalized, productFlavor);
|
|
1706
2060
|
},
|
|
1707
2061
|
resolveTarget({ input, normalized, preferredKind }) {
|
|
1708
|
-
return resolveCoolclawMessagingTarget(normalized || input, preferredKind);
|
|
2062
|
+
return resolveCoolclawMessagingTarget(normalized || input, preferredKind, productFlavor);
|
|
1709
2063
|
}
|
|
1710
2064
|
}
|
|
1711
2065
|
},
|
|
@@ -1714,17 +2068,19 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1714
2068
|
const account = coolclawChannelPlugin.config.resolveAccount(ctx.cfg, ctx.accountId);
|
|
1715
2069
|
const token = await resolveAccountToken(account);
|
|
1716
2070
|
if (!account.gatewayUrl || !account.agentId || !token) {
|
|
1717
|
-
ctx.log?.error(`[${ctx.accountId}]
|
|
2071
|
+
ctx.log?.error(`[${ctx.accountId}] ${productFlavor.displayName} account is not fully configured`);
|
|
1718
2072
|
return;
|
|
1719
2073
|
}
|
|
1720
|
-
const accountKey =
|
|
1721
|
-
const ackStore = new FileAckStore(
|
|
2074
|
+
const accountKey = `${productFlavor.channelId}:${ctx.accountId ?? "default"}`;
|
|
2075
|
+
const ackStore = new FileAckStore(
|
|
2076
|
+
path2.join(homedir3(), ".openclaw", "extensions", productFlavor.channelId, ".ack-store")
|
|
2077
|
+
);
|
|
1722
2078
|
const statusSink = createAccountStatusSink({
|
|
1723
2079
|
accountId: ctx.accountId,
|
|
1724
2080
|
setStatus: ctx.setStatus
|
|
1725
2081
|
});
|
|
1726
2082
|
statusSink({ statusState: "connecting" });
|
|
1727
|
-
ctx.log?.info(`[${ctx.accountId}] starting
|
|
2083
|
+
ctx.log?.info(`[${ctx.accountId}] starting ${productFlavor.displayName} provider (${account.gatewayUrl})`);
|
|
1728
2084
|
await runPassiveAccountLifecycle({
|
|
1729
2085
|
abortSignal: ctx.abortSignal,
|
|
1730
2086
|
start: async () => {
|
|
@@ -1748,9 +2104,11 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1748
2104
|
const isGameEvent = envelope.metadata?.gameEvent === true;
|
|
1749
2105
|
const isArenaReportShare = isArenaReportShareEnvelope(envelope);
|
|
1750
2106
|
const isArenaModelQuery = isArenaModelQueryEnvelope(envelope);
|
|
2107
|
+
const isArenaVoiceSelect = isArenaVoiceSelectEnvelope(envelope);
|
|
1751
2108
|
const suppressChatTextDelivery = shouldSuppressCoolclawTextDelivery(envelope);
|
|
1752
2109
|
const gameMeta = isGameEvent ? envelope.metadata : null;
|
|
1753
2110
|
const modelQueryMeta = isArenaModelQuery ? envelope.metadata : null;
|
|
2111
|
+
const voiceSelectMeta = isArenaVoiceSelect ? envelope.metadata : null;
|
|
1754
2112
|
let gameSubmitted = false;
|
|
1755
2113
|
let gameFallbackReason = null;
|
|
1756
2114
|
let gameModelActionType;
|
|
@@ -1762,6 +2120,11 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1762
2120
|
token,
|
|
1763
2121
|
log: ctx.log
|
|
1764
2122
|
}) : null;
|
|
2123
|
+
const voiceSelectCollector = voiceSelectMeta ? createArenaVoiceSelectReplyCollector({
|
|
2124
|
+
meta: voiceSelectMeta,
|
|
2125
|
+
token,
|
|
2126
|
+
log: ctx.log
|
|
2127
|
+
}) : null;
|
|
1765
2128
|
if (isGameEvent && gameMeta) {
|
|
1766
2129
|
ctx.log?.info?.(
|
|
1767
2130
|
`[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}`
|
|
@@ -1778,6 +2141,17 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1778
2141
|
`[ARENA-MODEL] inbound eventId=${modelQueryMeta.eventId} traceId=${modelQueryMeta.traceId ?? ""} roomId=${modelQueryMeta.roomId} seatEpoch=${modelQueryMeta.seatEpoch} callbackHost=${callbackHost} conversationId=${envelope.conversationId}`
|
|
1779
2142
|
);
|
|
1780
2143
|
}
|
|
2144
|
+
if (voiceSelectMeta) {
|
|
2145
|
+
let callbackHost = "";
|
|
2146
|
+
try {
|
|
2147
|
+
callbackHost = new URL(voiceSelectMeta.callbackUrl).host;
|
|
2148
|
+
} catch {
|
|
2149
|
+
callbackHost = "invalid";
|
|
2150
|
+
}
|
|
2151
|
+
ctx.log?.info?.(
|
|
2152
|
+
`[ARENA-VOICE] inbound eventId=${voiceSelectMeta.eventId} traceId=${voiceSelectMeta.traceId ?? ""} roomId=${voiceSelectMeta.roomId} seatEpoch=${voiceSelectMeta.seatEpoch} callbackHost=${callbackHost} conversationId=${envelope.conversationId}`
|
|
2153
|
+
);
|
|
2154
|
+
}
|
|
1781
2155
|
const runtime = getCoolclawRuntime();
|
|
1782
2156
|
let runtimeChannel;
|
|
1783
2157
|
try {
|
|
@@ -1787,7 +2161,7 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1787
2161
|
});
|
|
1788
2162
|
} catch (err) {
|
|
1789
2163
|
logInboundDrop({ log: ctx.log?.warn?.bind(ctx.log) ?? (() => {
|
|
1790
|
-
}), channel:
|
|
2164
|
+
}), channel: productFlavor.channelId, reason: "runtime not available; skipping dispatch" });
|
|
1791
2165
|
if (isGameEvent && gameMeta) {
|
|
1792
2166
|
const submitted = await submitBackendFallbackWithLog({
|
|
1793
2167
|
meta: gameMeta,
|
|
@@ -1809,6 +2183,15 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1809
2183
|
});
|
|
1810
2184
|
return;
|
|
1811
2185
|
}
|
|
2186
|
+
if (voiceSelectMeta) {
|
|
2187
|
+
await submitArenaVoiceSelectCallback({
|
|
2188
|
+
meta: voiceSelectMeta,
|
|
2189
|
+
token,
|
|
2190
|
+
rawText: "",
|
|
2191
|
+
log: ctx.log
|
|
2192
|
+
});
|
|
2193
|
+
return;
|
|
2194
|
+
}
|
|
1812
2195
|
throw err;
|
|
1813
2196
|
}
|
|
1814
2197
|
try {
|
|
@@ -1821,7 +2204,7 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1821
2204
|
}
|
|
1822
2205
|
const route = await runtimeChannel.routing.resolveAgentRoute({
|
|
1823
2206
|
cfg: ctx.cfg,
|
|
1824
|
-
channel:
|
|
2207
|
+
channel: productFlavor.channelId,
|
|
1825
2208
|
accountId: ctx.accountId,
|
|
1826
2209
|
peer
|
|
1827
2210
|
});
|
|
@@ -1834,18 +2217,18 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1834
2217
|
ctx.cfg.session?.store,
|
|
1835
2218
|
{ agentId: route.agentId }
|
|
1836
2219
|
);
|
|
1837
|
-
const senderLabel = envelope.sender ? `${envelope.sender.userType.toLowerCase()}:${envelope.sender.userId}` : isGameEvent ? `game:${gameMeta.gameId}` : modelQueryMeta ? `arena-model:${modelQueryMeta.roomId}` : "unknown";
|
|
2220
|
+
const senderLabel = envelope.sender ? `${envelope.sender.userType.toLowerCase()}:${envelope.sender.userId}` : isGameEvent ? `game:${gameMeta.gameId}` : modelQueryMeta ? `arena-model:${modelQueryMeta.roomId}` : voiceSelectMeta ? `arena-voice:${voiceSelectMeta.roomId}` : "unknown";
|
|
1838
2221
|
let deliveryTarget;
|
|
1839
2222
|
if (envelope.group) {
|
|
1840
|
-
deliveryTarget =
|
|
2223
|
+
deliveryTarget = `${productFlavor.targetPrefix}:group:${envelope.group.groupId}`;
|
|
1841
2224
|
} else if (envelope.sender) {
|
|
1842
|
-
deliveryTarget =
|
|
1843
|
-
} else if (isGameEvent || isArenaModelQuery) {
|
|
1844
|
-
deliveryTarget =
|
|
2225
|
+
deliveryTarget = `${productFlavor.targetPrefix}:${envelope.sender.userType.toLowerCase()}:${envelope.sender.userId}`;
|
|
2226
|
+
} else if (isGameEvent || isArenaModelQuery || isArenaVoiceSelect) {
|
|
2227
|
+
deliveryTarget = `${productFlavor.targetPrefix}:agent:${account.agentId}`;
|
|
1845
2228
|
} else {
|
|
1846
|
-
deliveryTarget = normalizeCoolclawTarget(envelope.conversationId);
|
|
2229
|
+
deliveryTarget = normalizeCoolclawTarget(envelope.conversationId, productFlavor);
|
|
1847
2230
|
}
|
|
1848
|
-
const bodyForAgent = buildBodyForAgent(envelope);
|
|
2231
|
+
const bodyForAgent = buildBodyForAgent(envelope, productFlavor);
|
|
1849
2232
|
if (typeof runtimeChannel.reply?.finalizeInboundContext !== "function") {
|
|
1850
2233
|
throw new Error(
|
|
1851
2234
|
"CoolClaw requires runtime.channel.reply.finalizeInboundContext. Please upgrade OpenClaw to >=2026.3.22."
|
|
@@ -1866,15 +2249,15 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1866
2249
|
BodyForAgent: bodyForAgent,
|
|
1867
2250
|
RawBody: envelope.text,
|
|
1868
2251
|
CommandBody: envelope.text,
|
|
1869
|
-
From:
|
|
2252
|
+
From: `${productFlavor.targetPrefix}:${senderLabel}`,
|
|
1870
2253
|
To: deliveryTarget,
|
|
1871
2254
|
SessionKey: route.sessionKey,
|
|
1872
2255
|
AccountId: ctx.accountId,
|
|
1873
2256
|
ChatType: isGroup ? "channel" : "direct",
|
|
1874
2257
|
CommandAuthorized: true,
|
|
1875
|
-
Provider:
|
|
1876
|
-
Surface:
|
|
1877
|
-
Channel:
|
|
2258
|
+
Provider: productFlavor.channelId,
|
|
2259
|
+
Surface: productFlavor.channelId,
|
|
2260
|
+
Channel: productFlavor.channelId,
|
|
1878
2261
|
Peer: peer,
|
|
1879
2262
|
WasMentioned: envelope.shouldReply,
|
|
1880
2263
|
Mentioned: envelope.shouldReply
|
|
@@ -1885,7 +2268,7 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1885
2268
|
storePath,
|
|
1886
2269
|
sessionKey,
|
|
1887
2270
|
ctx: ctxPayload,
|
|
1888
|
-
updateLastRoute: mainSessionKey && mainSessionKey !== sessionKey ? { sessionKey: mainSessionKey, channel:
|
|
2271
|
+
updateLastRoute: mainSessionKey && mainSessionKey !== sessionKey ? { sessionKey: mainSessionKey, channel: productFlavor.channelId, to: deliveryTarget, accountId: ctx.accountId ?? void 0 } : void 0,
|
|
1889
2272
|
onRecordError: (err) => {
|
|
1890
2273
|
ctx.log?.warn(`recordInboundSession failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1891
2274
|
}
|
|
@@ -1908,6 +2291,10 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1908
2291
|
await modelQueryCollector.deliver(replyText);
|
|
1909
2292
|
return;
|
|
1910
2293
|
}
|
|
2294
|
+
if (voiceSelectCollector) {
|
|
2295
|
+
await voiceSelectCollector.deliver(replyText);
|
|
2296
|
+
return;
|
|
2297
|
+
}
|
|
1911
2298
|
if (isGameEvent && gameMeta) {
|
|
1912
2299
|
if (gameSubmitted) return;
|
|
1913
2300
|
gameBuffer.push(String(payload.text));
|
|
@@ -1952,17 +2339,17 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1952
2339
|
return;
|
|
1953
2340
|
}
|
|
1954
2341
|
if (suppressChatTextDelivery) {
|
|
1955
|
-
ctx.log?.error?.(`[ARENA-
|
|
2342
|
+
ctx.log?.error?.(`[ARENA-CALLBACK] chat delivery blocked eventId=${envelope.metadata.eventId ?? ""}`);
|
|
1956
2343
|
return;
|
|
1957
2344
|
}
|
|
1958
2345
|
try {
|
|
1959
2346
|
let replyTarget;
|
|
1960
2347
|
if (envelope.group) {
|
|
1961
|
-
replyTarget =
|
|
2348
|
+
replyTarget = `${productFlavor.targetPrefix}:group:${envelope.group.groupId}`;
|
|
1962
2349
|
} else if (envelope.sender) {
|
|
1963
|
-
replyTarget =
|
|
2350
|
+
replyTarget = `${productFlavor.targetPrefix}:${envelope.sender.userType.toLowerCase()}:${envelope.sender.userId}`;
|
|
1964
2351
|
} else {
|
|
1965
|
-
replyTarget = normalizeCoolclawTarget(envelope.conversationId);
|
|
2352
|
+
replyTarget = normalizeCoolclawTarget(envelope.conversationId, productFlavor);
|
|
1966
2353
|
}
|
|
1967
2354
|
await sendText({ client: wsClient, target: replyTarget, text: replyText });
|
|
1968
2355
|
} catch (err) {
|
|
@@ -1982,6 +2369,9 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1982
2369
|
if (modelQueryCollector) {
|
|
1983
2370
|
await modelQueryCollector.finalize();
|
|
1984
2371
|
}
|
|
2372
|
+
if (voiceSelectCollector) {
|
|
2373
|
+
await voiceSelectCollector.finalize();
|
|
2374
|
+
}
|
|
1985
2375
|
} catch (err) {
|
|
1986
2376
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
1987
2377
|
ctx.log?.error(`Inbound dispatch error: ${errMsg}`);
|
|
@@ -1993,6 +2383,11 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1993
2383
|
})) {
|
|
1994
2384
|
return;
|
|
1995
2385
|
}
|
|
2386
|
+
if (voiceSelectCollector) {
|
|
2387
|
+
ctx.log?.warn?.(`[ARENA-VOICE] dispatch failed; submitting fallback callback eventId=${voiceSelectMeta?.eventId ?? ""} err=${errMsg}`);
|
|
2388
|
+
await voiceSelectCollector.finalize();
|
|
2389
|
+
return;
|
|
2390
|
+
}
|
|
1996
2391
|
if (isGameEvent && gameMeta && !gameSubmitted) {
|
|
1997
2392
|
gameFallbackReason = `dispatch_error: ${errMsg}`;
|
|
1998
2393
|
}
|
|
@@ -2043,7 +2438,7 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
2043
2438
|
ctx.log?.debug?.(`ACK sent: type=${ackFrame.type} lastAckedSeq=${ackFrame.payload?.lastAckedSeq}`);
|
|
2044
2439
|
} catch (err) {
|
|
2045
2440
|
logAckFailure({ log: ctx.log?.warn?.bind(ctx.log) ?? (() => {
|
|
2046
|
-
}), channel:
|
|
2441
|
+
}), channel: productFlavor.channelId, error: err });
|
|
2047
2442
|
throw err;
|
|
2048
2443
|
}
|
|
2049
2444
|
}
|
|
@@ -2056,7 +2451,7 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
2056
2451
|
await client.start();
|
|
2057
2452
|
setRuntimeClient(accountKey, client);
|
|
2058
2453
|
statusSink({ statusState: "connected" });
|
|
2059
|
-
ctx.log?.info(`[${ctx.accountId}]
|
|
2454
|
+
ctx.log?.info(`[${ctx.accountId}] ${productFlavor.displayName} provider connected`);
|
|
2060
2455
|
return client;
|
|
2061
2456
|
},
|
|
2062
2457
|
stop: async (client) => {
|
|
@@ -2065,25 +2460,25 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
2065
2460
|
},
|
|
2066
2461
|
onStop: () => {
|
|
2067
2462
|
statusSink({ statusState: "disconnected" });
|
|
2068
|
-
ctx.log?.info(`[${ctx.accountId}]
|
|
2463
|
+
ctx.log?.info(`[${ctx.accountId}] ${productFlavor.displayName} provider stopped`);
|
|
2069
2464
|
}
|
|
2070
2465
|
});
|
|
2071
2466
|
},
|
|
2072
2467
|
/** 显式停止账户连接,清理 WebSocket 客户端资源 */
|
|
2073
2468
|
async stopAccount(ctx) {
|
|
2074
|
-
const accountKey =
|
|
2469
|
+
const accountKey = `${productFlavor.channelId}:${ctx.accountId ?? "default"}`;
|
|
2075
2470
|
const client = getRuntimeClient(accountKey);
|
|
2076
2471
|
if (client) {
|
|
2077
2472
|
await client.stop();
|
|
2078
2473
|
clearRuntimeClient(accountKey);
|
|
2079
|
-
ctx.log?.info(`[${ctx.accountId}]
|
|
2474
|
+
ctx.log?.info(`[${ctx.accountId}] ${productFlavor.displayName} client stopped via stopAccount`);
|
|
2080
2475
|
}
|
|
2081
2476
|
}
|
|
2082
2477
|
}
|
|
2083
2478
|
},
|
|
2084
2479
|
security: {
|
|
2085
2480
|
dm: {
|
|
2086
|
-
channelKey:
|
|
2481
|
+
channelKey: productFlavor.channelId,
|
|
2087
2482
|
resolvePolicy: (account) => account.dmPolicy ?? "allowlist",
|
|
2088
2483
|
resolveAllowFrom: (account) => account.allowFrom ?? [],
|
|
2089
2484
|
defaultPolicy: "allowlist",
|
|
@@ -2092,10 +2487,10 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
2092
2487
|
},
|
|
2093
2488
|
pairing: {
|
|
2094
2489
|
text: {
|
|
2095
|
-
idLabel:
|
|
2490
|
+
idLabel: `${productFlavor.displayName} user ID`,
|
|
2096
2491
|
message: "You are not authorized to message this agent. Send this pairing code to verify:",
|
|
2097
2492
|
notify: async ({ id, message }) => {
|
|
2098
|
-
const client = getRuntimeClient(
|
|
2493
|
+
const client = getRuntimeClient(`${productFlavor.channelId}:default`);
|
|
2099
2494
|
if (client) {
|
|
2100
2495
|
await sendText({
|
|
2101
2496
|
client,
|
|
@@ -2114,11 +2509,11 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
2114
2509
|
deliveryMode: "direct",
|
|
2115
2510
|
resolveTarget({ to }) {
|
|
2116
2511
|
if (!to) {
|
|
2117
|
-
return { ok: false, error: new Error(
|
|
2512
|
+
return { ok: false, error: new Error(`${productFlavor.displayName} target is required`) };
|
|
2118
2513
|
}
|
|
2119
2514
|
try {
|
|
2120
|
-
const normalized = normalizeCoolclawTarget(to);
|
|
2121
|
-
parseCoolclawTarget(normalized);
|
|
2515
|
+
const normalized = normalizeCoolclawTarget(to, productFlavor);
|
|
2516
|
+
parseCoolclawTarget(normalized, productFlavor);
|
|
2122
2517
|
return { ok: true, to: normalized };
|
|
2123
2518
|
} catch (error) {
|
|
2124
2519
|
return { ok: false, error: error instanceof Error ? error : new Error(String(error)) };
|
|
@@ -2126,14 +2521,14 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
2126
2521
|
}
|
|
2127
2522
|
},
|
|
2128
2523
|
attachedResults: {
|
|
2129
|
-
channel:
|
|
2524
|
+
channel: productFlavor.channelId,
|
|
2130
2525
|
async sendText(ctx) {
|
|
2131
2526
|
const account = coolclawChannelPlugin.config.resolveAccount(ctx.cfg, ctx.accountId);
|
|
2132
2527
|
const token = await resolveAccountToken(account);
|
|
2133
2528
|
if (!account.gatewayUrl || !account.agentId || !token) {
|
|
2134
|
-
throw new Error(
|
|
2529
|
+
throw new Error(`${productFlavor.displayName} account is not fully configured`);
|
|
2135
2530
|
}
|
|
2136
|
-
const accountKey =
|
|
2531
|
+
const accountKey = `${productFlavor.channelId}:${ctx.accountId ?? "default"}`;
|
|
2137
2532
|
let client = getRuntimeClient(accountKey);
|
|
2138
2533
|
if (!client || !client.isConnected()) {
|
|
2139
2534
|
client = new CoolclawWsClient({
|
|
@@ -2159,9 +2554,9 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
2159
2554
|
const account = coolclawChannelPlugin.config.resolveAccount(ctx.cfg, ctx.accountId);
|
|
2160
2555
|
const token = await resolveAccountToken(account);
|
|
2161
2556
|
if (!account.gatewayUrl || !account.agentId || !token) {
|
|
2162
|
-
throw new Error(
|
|
2557
|
+
throw new Error(`${productFlavor.displayName} account is not fully configured`);
|
|
2163
2558
|
}
|
|
2164
|
-
const accountKey =
|
|
2559
|
+
const accountKey = `${productFlavor.channelId}:${ctx.accountId ?? "default"}`;
|
|
2165
2560
|
let client = getRuntimeClient(accountKey);
|
|
2166
2561
|
if (!client || !client.isConnected()) {
|
|
2167
2562
|
client = new CoolclawWsClient({
|
|
@@ -2186,13 +2581,17 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
2186
2581
|
}
|
|
2187
2582
|
}
|
|
2188
2583
|
});
|
|
2189
|
-
function buildBodyForAgent(envelope) {
|
|
2584
|
+
function buildBodyForAgent(envelope, flavorInput) {
|
|
2585
|
+
const flavor = resolveFlavor(flavorInput);
|
|
2586
|
+
if (isArenaVoiceSelectEnvelope(envelope)) {
|
|
2587
|
+
return buildArenaVoiceSelectBodyForAgent(envelope, flavor);
|
|
2588
|
+
}
|
|
2190
2589
|
if (isArenaReportShareEnvelope(envelope)) {
|
|
2191
|
-
return buildArenaReportShareBodyForAgent(envelope);
|
|
2590
|
+
return buildArenaReportShareBodyForAgent(envelope, flavor);
|
|
2192
2591
|
}
|
|
2193
2592
|
if (!envelope.group) {
|
|
2194
2593
|
if (envelope.sender && envelope.recipient) {
|
|
2195
|
-
return buildPrivateBodyForAgent(envelope);
|
|
2594
|
+
return buildPrivateBodyForAgent(envelope, flavor);
|
|
2196
2595
|
}
|
|
2197
2596
|
const hints = [
|
|
2198
2597
|
envelope.metadata?.securityHint,
|
|
@@ -2203,7 +2602,7 @@ function buildBodyForAgent(envelope) {
|
|
|
2203
2602
|
const sender = formatUserRef(envelope.sender, "\u672A\u77E5\u53D1\u9001\u4EBA");
|
|
2204
2603
|
const owner = formatUserRef(envelope.owner, "\u672A\u77E5\u4E3B\u4EBA");
|
|
2205
2604
|
const lines = [
|
|
2206
|
-
|
|
2605
|
+
`\u4F60\u6536\u5230\u4E00\u6761 ${flavor.displayName} \u7FA4\u804A\u6D88\u606F\u3002`,
|
|
2207
2606
|
"",
|
|
2208
2607
|
`\u7FA4\u804A\uFF1A${envelope.group.groupName}(${envelope.group.groupId})`,
|
|
2209
2608
|
`\u53D1\u9001\u4EBA\uFF1A${sender}`,
|
|
@@ -2211,7 +2610,7 @@ function buildBodyForAgent(envelope) {
|
|
|
2211
2610
|
envelope.text,
|
|
2212
2611
|
"",
|
|
2213
2612
|
"\u8EAB\u4EFD\u4E0A\u4E0B\u6587\uFF1A",
|
|
2214
|
-
`\u4F60\u7684\u4E3B\u4EBA\u662F ${owner}\u3002\u8FD9\u662F\u4F60\u5728
|
|
2613
|
+
`\u4F60\u7684\u4E3B\u4EBA\u662F ${owner}\u3002\u8FD9\u662F\u4F60\u5728 ${flavor.displayName} \u5E73\u53F0\u4E0A\u7684\u7ED1\u5B9A\u5173\u7CFB\uFF0C\u4EC5\u7528\u4E8E\u5224\u65AD\u6D88\u606F\u6765\u6E90\u548C\u5B89\u5168\u8FB9\u754C\u3002`,
|
|
2215
2614
|
"",
|
|
2216
2615
|
"---",
|
|
2217
2616
|
"\u7CFB\u7EDF\u63D0\u793A\uFF1A",
|
|
@@ -2235,7 +2634,44 @@ function buildBodyForAgent(envelope) {
|
|
|
2235
2634
|
}
|
|
2236
2635
|
return lines.join("\n");
|
|
2237
2636
|
}
|
|
2238
|
-
function
|
|
2637
|
+
function buildArenaVoiceSelectBodyForAgent(envelope, flavor) {
|
|
2638
|
+
const voiceOptions = Array.isArray(envelope.metadata.voiceOptions) ? envelope.metadata.voiceOptions : [];
|
|
2639
|
+
const optionLines = voiceOptions.map((rawOption) => {
|
|
2640
|
+
const option = isPlainRecord(rawOption) ? rawOption : {};
|
|
2641
|
+
const voiceId = formatUnknown(option.voiceId);
|
|
2642
|
+
const voiceName = formatUnknown(option.voiceName);
|
|
2643
|
+
const description = formatUnknown(option.description);
|
|
2644
|
+
const speed = formatUnknown(option.speed);
|
|
2645
|
+
const detail = [
|
|
2646
|
+
voiceName ? `\u540D\u79F0=${voiceName}` : "",
|
|
2647
|
+
description ? `\u63CF\u8FF0=${description}` : "",
|
|
2648
|
+
speed ? `\u8BED\u901F=${speed}` : ""
|
|
2649
|
+
].filter(Boolean).join("\uFF1B");
|
|
2650
|
+
return detail ? `- ${voiceId}\uFF1A${detail}` : `- ${voiceId}`;
|
|
2651
|
+
}).filter((line) => line !== "- ");
|
|
2652
|
+
return [
|
|
2653
|
+
`\u4F60\u6536\u5230\u4E00\u4E2A ${flavor.displayName} \u72FC\u4EBA\u6740\u8D5B\u524D\u97F3\u8272\u9009\u62E9\u4EFB\u52A1\u3002`,
|
|
2654
|
+
"",
|
|
2655
|
+
"\u4EFB\u52A1\u6027\u8D28\uFF1A\u8BF7\u9009\u62E9\u8D5B\u524D\u73A9\u5BB6\u97F3\u8272\u3002\u4F60\u53EA\u8D1F\u8D23\u7ED9\u51FA\u504F\u597D\uFF0C\u63D2\u4EF6\u4F1A\u8D1F\u8D23\u9274\u6743\u548C\u63D0\u4EA4\u3002",
|
|
2656
|
+
`eventId\uFF1A${formatUnknown(envelope.metadata.eventId)}`,
|
|
2657
|
+
`roomId\uFF1A${formatUnknown(envelope.metadata.roomId)}`,
|
|
2658
|
+
`seatNumber\uFF1A${formatUnknown(envelope.metadata.seatNumber)}`,
|
|
2659
|
+
`seatEpoch\uFF1A${formatUnknown(envelope.metadata.seatEpoch)}`,
|
|
2660
|
+
"",
|
|
2661
|
+
"\u53EF\u9009\u73A9\u5BB6\u97F3\u8272\uFF1A",
|
|
2662
|
+
...optionLines.length > 0 ? optionLines : ["- \u65E0"],
|
|
2663
|
+
"",
|
|
2664
|
+
"\u8F93\u51FA\u8981\u6C42\uFF1A",
|
|
2665
|
+
"\u53EA\u8F93\u51FA\u4E00\u4E2A JSON \u5BF9\u8C61\uFF0C\u4E0D\u8981\u8F93\u51FA Markdown\uFF0C\u4E0D\u8981\u8C03\u7528\u63A5\u53E3\uFF0C\u4E0D\u8981\u4F7F\u7528\u5DE5\u5177\uFF0C\u4E0D\u8981\u89E3\u91CA\u63D0\u4EA4\u8FC7\u7A0B\u3002",
|
|
2666
|
+
'{"topVoiceIds":["4139","4172","5977"],"reason":"\u4E00\u53E5\u8BDD\u8BF4\u660E\u6574\u4F53\u9009\u62E9\u503E\u5411"}',
|
|
2667
|
+
"",
|
|
2668
|
+
"\u7EA6\u675F\uFF1A",
|
|
2669
|
+
"1. topVoiceIds \u53EA\u80FD\u5305\u542B\u4E0A\u65B9\u53EF\u9009\u5217\u8868\u91CC\u7684 voiceId \u5B57\u7B26\u4E32\uFF0C\u6700\u591A 3 \u4E2A\uFF0C\u6309\u504F\u597D\u6392\u5E8F\u3002",
|
|
2670
|
+
"2. \u4E0D\u8981\u628A voiceId \u8F6C\u6210\u6570\u5B57\u3002",
|
|
2671
|
+
"3. \u97F3\u8272\u53EA\u5F71\u54CD\u53D1\u58F0\u98CE\u683C\uFF0C\u4E0D\u4EE3\u8868\u4F60\u7684\u6E38\u620F\u8EAB\u4EFD\u3001\u63A8\u7406\u4F9D\u636E\u6216\u53EF\u4FE1\u5EA6\u3002"
|
|
2672
|
+
].join("\n");
|
|
2673
|
+
}
|
|
2674
|
+
function buildArenaReportShareBodyForAgent(envelope, flavor) {
|
|
2239
2675
|
const payload = isPlainRecord(envelope.metadata.reportPayload) ? envelope.metadata.reportPayload : {};
|
|
2240
2676
|
const gameId = formatUnknown(payload.gameId);
|
|
2241
2677
|
const roomId = formatUnknown(payload.roomId);
|
|
@@ -2248,7 +2684,7 @@ function buildArenaReportShareBodyForAgent(envelope) {
|
|
|
2248
2684
|
const eventId = formatUnknown(envelope.metadata.eventId);
|
|
2249
2685
|
const traceId = formatUnknown(envelope.metadata.traceId);
|
|
2250
2686
|
return [
|
|
2251
|
-
|
|
2687
|
+
`\u4F60\u6536\u5230\u4E00\u4E2A ${flavor.displayName} \u7ADE\u6280\u573A\u6218\u62A5\u5206\u4EAB\u59D4\u6258\u4EFB\u52A1\u3002`,
|
|
2252
2688
|
"",
|
|
2253
2689
|
"\u4EFB\u52A1\u6027\u8D28\uFF1A\u8FD9\u662F\u4E3B\u4EBA\u59D4\u6258\u4F60\u6267\u884C\u7684\u7ADE\u6280\u573A\u6218\u62A5\u5206\u4EAB\u4EFB\u52A1\uFF0C\u4E0D\u662F\u666E\u901A\u8BC4\u8BBA\u901A\u77E5\uFF0C\u4E5F\u4E0D\u662F\u804A\u5929\u56DE\u590D\u3002",
|
|
2254
2690
|
`eventId\uFF1A${eventId}`,
|
|
@@ -2264,14 +2700,14 @@ function buildArenaReportShareBodyForAgent(envelope) {
|
|
|
2264
2700
|
`result\uFF1A${result}`,
|
|
2265
2701
|
"",
|
|
2266
2702
|
"\u6267\u884C\u6B65\u9AA4\uFF1A",
|
|
2267
|
-
|
|
2703
|
+
`1. \u8BFB\u53D6\u5F53\u524D ${flavor.displayName} channel/plugin \u914D\u7F6E\u7684 Gateway Base URL\uFF1B\u4F18\u5148\u4F7F\u7528 channels.${flavor.channelId}.accounts.default.gatewayUrl\uFF0C\u5176\u6B21\u4F7F\u7528 ${flavor.envPrefix}_GATEWAY_URL \u73AF\u5883\u53D8\u91CF\u3002`,
|
|
2268
2704
|
"2. \u5982\u679C\u65E0\u6CD5\u89E3\u6790 Gateway Base URL\uFF0C\u505C\u6B62\u4EFB\u52A1\u5E76\u62A5\u544A\u914D\u7F6E\u7F3A\u5931\uFF1B\u4E0D\u8981\u81C6\u9020\u57DF\u540D\u3002",
|
|
2269
2705
|
`3. \u4F7F\u7528 Gateway Base URL \u62FC\u63A5 replayApiPath=${replayApiPath} \u8BFB\u53D6\u672C\u5C40\u6218\u62A5\u3002`,
|
|
2270
2706
|
`4. \u4F7F\u7528\u540C\u4E00\u4E2A Gateway Base URL \u62FC\u63A5 boardListApiPath=${boardListApiPath} \u67E5\u8BE2\u5185\u5BB9\u5E7F\u573A\u677F\u5757\uFF0C\u4F18\u5148\u9009\u62E9\u201C\u7ADE\u6280\u573A\u6218\u62A5 & \u590D\u76D8\u201D\u3002`,
|
|
2271
2707
|
`5. \u4F7F\u7528\u540C\u4E00\u4E2A Gateway Base URL \u62FC\u63A5 createPostApiPath=${createPostApiPath} \u53D1\u5E03\u5E16\u5B50\u3002`,
|
|
2272
2708
|
"6. \u53D1\u5E16\u6807\u9898\u548C\u6B63\u6587\u7531\u4F60\u57FA\u4E8E\u6218\u62A5\u5185\u5BB9\u751F\u6210\uFF0C\u6B63\u6587\u4E0D\u8981\u5305\u542B\u6218\u62A5\u94FE\u63A5\u3002",
|
|
2273
2709
|
"7. eventId \u662F\u672C\u4EFB\u52A1\u7684\u5E42\u7B49\u952E\uFF1B\u5982\u679C\u5F53\u524D\u8FD0\u884C\u8FDB\u7A0B\u5DF2\u5904\u7406\u8FC7\u540C\u4E00 eventId\uFF0C\u4E0D\u8981\u518D\u6B21\u53D1\u5E16\u3002",
|
|
2274
|
-
|
|
2710
|
+
`8. \u5B8C\u6210\u540E\u53EA\u4FDD\u7559\u7B80\u77ED\u6267\u884C\u6458\u8981\uFF0C\u4E0D\u8981\u628A\u5B8C\u6210\u6458\u8981\u53D1\u9001\u5230 ${flavor.displayName} \u804A\u5929\u7A97\u53E3\u3002`,
|
|
2275
2711
|
"",
|
|
2276
2712
|
"\u7981\u6B62\u4E8B\u9879\uFF1A\u4E0D\u8981\u4F7F\u7528 arena prompt \u4E2D\u7684\u56FA\u5B9A host\uFF0C\u4E0D\u8981\u4F7F\u7528\u672C\u5730/\u5185\u7F51\u5730\u5740\uFF0C\u4E0D\u8981\u6784\u9020\u6218\u62A5\u9875\u9762\u8DEF\u5F84\uFF0C\u4E0D\u8981\u8981\u6C42\u6B63\u6587\u9644\u6218\u62A5\u94FE\u63A5\u3002"
|
|
2277
2713
|
].join("\n");
|
|
@@ -2285,18 +2721,18 @@ function formatUnknown(value) {
|
|
|
2285
2721
|
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
2286
2722
|
return JSON.stringify(value);
|
|
2287
2723
|
}
|
|
2288
|
-
function buildPrivateBodyForAgent(envelope) {
|
|
2724
|
+
function buildPrivateBodyForAgent(envelope, flavor) {
|
|
2289
2725
|
const sender = formatUserRef(envelope.sender, "\u672A\u77E5\u53D1\u9001\u4EBA");
|
|
2290
2726
|
const owner = formatUserRef(envelope.owner, "\u672A\u77E5\u4E3B\u4EBA");
|
|
2291
2727
|
const lines = [
|
|
2292
|
-
|
|
2728
|
+
`\u4F60\u6536\u5230\u4E00\u6761 ${flavor.displayName} \u79C1\u804A\u6D88\u606F\u3002`,
|
|
2293
2729
|
"",
|
|
2294
2730
|
`\u53D1\u9001\u4EBA\uFF1A${sender}`,
|
|
2295
2731
|
"\u6D88\u606F\u5185\u5BB9\uFF1A",
|
|
2296
2732
|
envelope.text,
|
|
2297
2733
|
"",
|
|
2298
2734
|
"\u8EAB\u4EFD\u4E0A\u4E0B\u6587\uFF1A",
|
|
2299
|
-
`\u4F60\u7684\u4E3B\u4EBA\u662F ${owner}\u3002\u8FD9\u662F\u4F60\u5728
|
|
2735
|
+
`\u4F60\u7684\u4E3B\u4EBA\u662F ${owner}\u3002\u8FD9\u662F\u4F60\u5728 ${flavor.displayName} \u5E73\u53F0\u4E0A\u7684\u7ED1\u5B9A\u5173\u7CFB\uFF0C\u4EC5\u7528\u4E8E\u5224\u65AD\u6D88\u606F\u6765\u6E90\u548C\u5B89\u5168\u8FB9\u754C\u3002`,
|
|
2300
2736
|
"",
|
|
2301
2737
|
"---",
|
|
2302
2738
|
"\u7CFB\u7EDF\u63D0\u793A\uFF1A",
|
|
@@ -2326,6 +2762,7 @@ function normalizeDirectHintLines(raw) {
|
|
|
2326
2762
|
}
|
|
2327
2763
|
|
|
2328
2764
|
export {
|
|
2765
|
+
activeFlavor,
|
|
2329
2766
|
defaultBindingFile,
|
|
2330
2767
|
CoolclawConfigSchema,
|
|
2331
2768
|
setCoolclawRuntime,
|