@xfxstudio/claworld 0.2.23-beta.1 → 0.2.23-beta.2
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/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/src/lib/chat-request.js +2 -1
- package/src/lib/relay/kickoff-progress.js +162 -0
- package/src/lib/relay/shared.js +30 -0
- package/src/openclaw/plugin/claworld-channel-plugin.js +5 -2
- package/src/openclaw/runtime/tool-contracts.js +14 -8
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
package/src/lib/chat-request.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createKickoffBrief } from './relay/kickoff-text.js';
|
|
2
|
+
import { normalizeAcceptedChatKickoffRecord } from './relay/kickoff-progress.js';
|
|
2
3
|
|
|
3
4
|
function normalizeText(value, fallback = null) {
|
|
4
5
|
if (value == null) return fallback;
|
|
@@ -358,7 +359,7 @@ export function normalizeStoredChatRequest(input = {}, { defaultSource = 'chat_r
|
|
|
358
359
|
if (acceptedByAgentId) normalized.acceptedByAgentId = acceptedByAgentId;
|
|
359
360
|
const approvalGrantId = normalizeText(input.approvalGrantId, null);
|
|
360
361
|
if (approvalGrantId) normalized.approvalGrantId = approvalGrantId;
|
|
361
|
-
const kickoff = cloneJsonObject(input.kickoff);
|
|
362
|
+
const kickoff = normalizeAcceptedChatKickoffRecord(cloneJsonObject(input.kickoff));
|
|
362
363
|
if (kickoff) normalized.kickoff = kickoff;
|
|
363
364
|
|
|
364
365
|
return normalized;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { normalizeOptionalText } from './shared.js';
|
|
2
|
+
|
|
3
|
+
function normalizeAcceptedChatKickoffField(value, fallback = null) {
|
|
4
|
+
return normalizeOptionalText(value) || fallback;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function normalizeAcceptedChatKickoffRecord(kickoff = null, { fallbackStatus = null } = {}) {
|
|
8
|
+
if (!kickoff || typeof kickoff !== 'object' || Array.isArray(kickoff)) return null;
|
|
9
|
+
|
|
10
|
+
const normalized = {
|
|
11
|
+
...kickoff,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const normalizedStatus = normalizeAcceptedChatKickoffField(normalized.status, fallbackStatus);
|
|
15
|
+
const normalizedReason = normalizeAcceptedChatKickoffField(normalized.reason, null);
|
|
16
|
+
const normalizedDeliveredAt = normalizeAcceptedChatKickoffField(normalized.deliveredAt, null);
|
|
17
|
+
const normalizedSenderKickoffDeliveredAt = normalizeAcceptedChatKickoffField(
|
|
18
|
+
normalized.senderKickoffDeliveredAt,
|
|
19
|
+
normalizedDeliveredAt,
|
|
20
|
+
);
|
|
21
|
+
const normalizedOpenerAcceptedAt = normalizeAcceptedChatKickoffField(normalized.openerAcceptedAt, null);
|
|
22
|
+
const normalizedOpenerDeliveredAt = normalizeAcceptedChatKickoffField(normalized.openerDeliveredAt, null);
|
|
23
|
+
const normalizedLiveChatEstablishedAt = normalizeAcceptedChatKickoffField(normalized.liveChatEstablishedAt, null);
|
|
24
|
+
const normalizedTurnId = normalizeAcceptedChatKickoffField(normalized.turnId, null);
|
|
25
|
+
const normalizedDeliveryId = normalizeAcceptedChatKickoffField(normalized.deliveryId, null);
|
|
26
|
+
const normalizedConversationKey = normalizeAcceptedChatKickoffField(normalized.conversationKey, null);
|
|
27
|
+
const normalizedOpenerTurnId = normalizeAcceptedChatKickoffField(normalized.openerTurnId, null);
|
|
28
|
+
const normalizedOpenerDeliveryId = normalizeAcceptedChatKickoffField(normalized.openerDeliveryId, null);
|
|
29
|
+
const normalizedFailedAt = normalizeAcceptedChatKickoffField(normalized.failedAt, null);
|
|
30
|
+
|
|
31
|
+
if (normalizedStatus) normalized.status = normalizedStatus;
|
|
32
|
+
else delete normalized.status;
|
|
33
|
+
if (normalizedReason) normalized.reason = normalizedReason;
|
|
34
|
+
else delete normalized.reason;
|
|
35
|
+
if (normalizedDeliveredAt) normalized.deliveredAt = normalizedDeliveredAt;
|
|
36
|
+
else delete normalized.deliveredAt;
|
|
37
|
+
if (normalizedSenderKickoffDeliveredAt) normalized.senderKickoffDeliveredAt = normalizedSenderKickoffDeliveredAt;
|
|
38
|
+
else delete normalized.senderKickoffDeliveredAt;
|
|
39
|
+
if (normalizedOpenerAcceptedAt) normalized.openerAcceptedAt = normalizedOpenerAcceptedAt;
|
|
40
|
+
else delete normalized.openerAcceptedAt;
|
|
41
|
+
if (normalizedOpenerDeliveredAt) normalized.openerDeliveredAt = normalizedOpenerDeliveredAt;
|
|
42
|
+
else delete normalized.openerDeliveredAt;
|
|
43
|
+
if (normalizedLiveChatEstablishedAt) normalized.liveChatEstablishedAt = normalizedLiveChatEstablishedAt;
|
|
44
|
+
else delete normalized.liveChatEstablishedAt;
|
|
45
|
+
if (normalizedTurnId) normalized.turnId = normalizedTurnId;
|
|
46
|
+
else delete normalized.turnId;
|
|
47
|
+
if (normalizedDeliveryId) normalized.deliveryId = normalizedDeliveryId;
|
|
48
|
+
else delete normalized.deliveryId;
|
|
49
|
+
if (normalizedConversationKey) normalized.conversationKey = normalizedConversationKey;
|
|
50
|
+
else delete normalized.conversationKey;
|
|
51
|
+
if (normalizedOpenerTurnId) normalized.openerTurnId = normalizedOpenerTurnId;
|
|
52
|
+
else delete normalized.openerTurnId;
|
|
53
|
+
if (normalizedOpenerDeliveryId) normalized.openerDeliveryId = normalizedOpenerDeliveryId;
|
|
54
|
+
else delete normalized.openerDeliveryId;
|
|
55
|
+
if (normalizedFailedAt) normalized.failedAt = normalizedFailedAt;
|
|
56
|
+
else delete normalized.failedAt;
|
|
57
|
+
|
|
58
|
+
const hasEstablishedEvidence = Boolean(
|
|
59
|
+
normalized.openerDeliveredAt
|
|
60
|
+
|| normalized.liveChatEstablishedAt,
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
if (hasEstablishedEvidence && (!normalized.status || ['queued', 'sent'].includes(normalized.status))) {
|
|
64
|
+
normalized.status = 'established';
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (normalized.status === 'established') {
|
|
68
|
+
const establishedAt = normalizeAcceptedChatKickoffField(
|
|
69
|
+
normalized.liveChatEstablishedAt,
|
|
70
|
+
normalizeAcceptedChatKickoffField(
|
|
71
|
+
normalized.openerDeliveredAt,
|
|
72
|
+
normalizeAcceptedChatKickoffField(normalized.openerAcceptedAt, null),
|
|
73
|
+
),
|
|
74
|
+
);
|
|
75
|
+
if (!normalized.openerDeliveredAt && normalized.openerAcceptedAt) {
|
|
76
|
+
normalized.openerDeliveredAt = normalized.openerAcceptedAt;
|
|
77
|
+
}
|
|
78
|
+
if (!normalized.liveChatEstablishedAt && establishedAt) {
|
|
79
|
+
normalized.liveChatEstablishedAt = establishedAt;
|
|
80
|
+
}
|
|
81
|
+
if (String(normalized.reason || '').startsWith('queued_')) {
|
|
82
|
+
delete normalized.reason;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return normalized;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export async function markAcceptedChatKickoffFailureWithDeps(deps, {
|
|
90
|
+
requestId = null,
|
|
91
|
+
reason = 'accepted_chat_kickoff_failed',
|
|
92
|
+
turnId = null,
|
|
93
|
+
conversationKey = null,
|
|
94
|
+
} = {}) {
|
|
95
|
+
const { store, pushToAgent } = deps;
|
|
96
|
+
const normalizedRequestId = normalizeOptionalText(requestId);
|
|
97
|
+
if (!normalizedRequestId) return null;
|
|
98
|
+
const request = store.getChatRequest(normalizedRequestId);
|
|
99
|
+
if (!request) return null;
|
|
100
|
+
|
|
101
|
+
request.kickoff = normalizeAcceptedChatKickoffRecord({
|
|
102
|
+
...(request.kickoff && typeof request.kickoff === 'object' && !Array.isArray(request.kickoff) ? request.kickoff : {}),
|
|
103
|
+
status: 'failed',
|
|
104
|
+
reason: normalizeOptionalText(reason) || 'accepted_chat_kickoff_failed',
|
|
105
|
+
...(normalizeOptionalText(turnId) ? { turnId: normalizeOptionalText(turnId) } : {}),
|
|
106
|
+
...(normalizeOptionalText(conversationKey) ? { conversationKey: normalizeOptionalText(conversationKey) } : {}),
|
|
107
|
+
failedAt: store.now(),
|
|
108
|
+
});
|
|
109
|
+
if (store.markChatRequestUpdated) {
|
|
110
|
+
await store.markChatRequestUpdated();
|
|
111
|
+
}
|
|
112
|
+
await pushToAgent(request.fromAgentId, 'request.updated', request);
|
|
113
|
+
await pushToAgent(request.toAgentId, 'request.updated', request);
|
|
114
|
+
return request;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export async function markAcceptedChatKickoffProgressWithDeps(deps, {
|
|
118
|
+
requestId = null,
|
|
119
|
+
status = null,
|
|
120
|
+
reason = null,
|
|
121
|
+
turnId = null,
|
|
122
|
+
deliveryId = null,
|
|
123
|
+
conversationKey = null,
|
|
124
|
+
senderKickoffDeliveredAt = null,
|
|
125
|
+
openerAcceptedAt = null,
|
|
126
|
+
openerDeliveredAt = null,
|
|
127
|
+
liveChatEstablishedAt = null,
|
|
128
|
+
openerTurnId = null,
|
|
129
|
+
openerDeliveryId = null,
|
|
130
|
+
} = {}) {
|
|
131
|
+
const { store, pushToAgent } = deps;
|
|
132
|
+
const normalizedRequestId = normalizeOptionalText(requestId);
|
|
133
|
+
if (!normalizedRequestId) return null;
|
|
134
|
+
const request = store.getChatRequest(normalizedRequestId);
|
|
135
|
+
if (!request) return null;
|
|
136
|
+
|
|
137
|
+
request.kickoff = normalizeAcceptedChatKickoffRecord({
|
|
138
|
+
...(request.kickoff && typeof request.kickoff === 'object' && !Array.isArray(request.kickoff) ? request.kickoff : {}),
|
|
139
|
+
...(normalizeOptionalText(status) ? { status: normalizeOptionalText(status) } : {}),
|
|
140
|
+
...(normalizeOptionalText(reason) ? { reason: normalizeOptionalText(reason) } : {}),
|
|
141
|
+
...(normalizeOptionalText(turnId) ? { turnId: normalizeOptionalText(turnId) } : {}),
|
|
142
|
+
...(normalizeOptionalText(deliveryId) ? { deliveryId: normalizeOptionalText(deliveryId) } : {}),
|
|
143
|
+
...(normalizeOptionalText(conversationKey) ? { conversationKey: normalizeOptionalText(conversationKey) } : {}),
|
|
144
|
+
...(normalizeOptionalText(senderKickoffDeliveredAt)
|
|
145
|
+
? {
|
|
146
|
+
senderKickoffDeliveredAt: normalizeOptionalText(senderKickoffDeliveredAt),
|
|
147
|
+
deliveredAt: normalizeOptionalText(senderKickoffDeliveredAt),
|
|
148
|
+
}
|
|
149
|
+
: {}),
|
|
150
|
+
...(normalizeOptionalText(openerAcceptedAt) ? { openerAcceptedAt: normalizeOptionalText(openerAcceptedAt) } : {}),
|
|
151
|
+
...(normalizeOptionalText(openerDeliveredAt) ? { openerDeliveredAt: normalizeOptionalText(openerDeliveredAt) } : {}),
|
|
152
|
+
...(normalizeOptionalText(liveChatEstablishedAt) ? { liveChatEstablishedAt: normalizeOptionalText(liveChatEstablishedAt) } : {}),
|
|
153
|
+
...(normalizeOptionalText(openerTurnId) ? { openerTurnId: normalizeOptionalText(openerTurnId) } : {}),
|
|
154
|
+
...(normalizeOptionalText(openerDeliveryId) ? { openerDeliveryId: normalizeOptionalText(openerDeliveryId) } : {}),
|
|
155
|
+
});
|
|
156
|
+
if (store.markChatRequestUpdated) {
|
|
157
|
+
await store.markChatRequestUpdated();
|
|
158
|
+
}
|
|
159
|
+
await pushToAgent(request.fromAgentId, 'request.updated', request);
|
|
160
|
+
await pushToAgent(request.toAgentId, 'request.updated', request);
|
|
161
|
+
return request;
|
|
162
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export function normalizePositiveInteger(value, fallback) {
|
|
2
|
+
const normalized = Number(value);
|
|
3
|
+
if (!Number.isFinite(normalized) || normalized <= 0) return fallback;
|
|
4
|
+
return Math.floor(normalized);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function normalizeOptionalText(value) {
|
|
8
|
+
if (typeof value !== 'string') return null;
|
|
9
|
+
const normalized = value.trim();
|
|
10
|
+
return normalized || null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function cloneJsonObject(value) {
|
|
14
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return null;
|
|
15
|
+
try {
|
|
16
|
+
const cloned = JSON.parse(JSON.stringify(value));
|
|
17
|
+
if (!cloned || typeof cloned !== 'object' || Array.isArray(cloned)) return null;
|
|
18
|
+
return cloned;
|
|
19
|
+
} catch {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function buildFailureBody(reason, extras = {}) {
|
|
25
|
+
return {
|
|
26
|
+
error: reason,
|
|
27
|
+
reason,
|
|
28
|
+
...extras,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import claworldPackageJson from '../../../package.json' with { type: 'json' };
|
|
2
3
|
|
|
3
4
|
import {
|
|
4
5
|
applyRuntimeIdentity,
|
|
@@ -57,6 +58,8 @@ import {
|
|
|
57
58
|
} from '../../lib/runtime-errors.js';
|
|
58
59
|
import { PUBLIC_IDENTITY_STATUS } from '../../lib/public-identity.js';
|
|
59
60
|
|
|
61
|
+
const CLAWORLD_PLUGIN_VERSION = claworldPackageJson.version;
|
|
62
|
+
|
|
60
63
|
function normalizeRelayHttpBaseUrl(serverUrl) {
|
|
61
64
|
const parsed = new URL(serverUrl);
|
|
62
65
|
if (parsed.protocol === 'ws:') parsed.protocol = 'http:';
|
|
@@ -2450,7 +2453,7 @@ export function createClaworldChannelPlugin({
|
|
|
2450
2453
|
return {
|
|
2451
2454
|
ok: true,
|
|
2452
2455
|
pluginId: 'claworld',
|
|
2453
|
-
version:
|
|
2456
|
+
version: CLAWORLD_PLUGIN_VERSION,
|
|
2454
2457
|
defaultAccountId: null,
|
|
2455
2458
|
accounts: accountSnapshots,
|
|
2456
2459
|
relayClients: Object.fromEntries(
|
|
@@ -2599,7 +2602,7 @@ async function generateRuntimeProfileCard(context = {}) {
|
|
|
2599
2602
|
docsPath: '/channels/claworld',
|
|
2600
2603
|
docsLabel: 'claworld',
|
|
2601
2604
|
blurb: 'Claworld relay channel backed by the Claworld backend.',
|
|
2602
|
-
version:
|
|
2605
|
+
version: CLAWORLD_PLUGIN_VERSION,
|
|
2603
2606
|
forceAccountBinding: true,
|
|
2604
2607
|
},
|
|
2605
2608
|
onboarding: claworldOnboardingAdapter,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { normalizeAcceptedChatKickoffRecord } from '../../lib/relay/kickoff-progress.js';
|
|
2
|
+
|
|
1
3
|
function normalizeText(value, fallback = null) {
|
|
2
4
|
if (value == null) return fallback;
|
|
3
5
|
const normalized = String(value).trim();
|
|
@@ -437,15 +439,19 @@ function normalizeConversationScopeDetails(input = {}) {
|
|
|
437
439
|
}
|
|
438
440
|
|
|
439
441
|
function projectChatRequestKickoff(kickoff = {}) {
|
|
440
|
-
|
|
442
|
+
const normalizedKickoff = normalizeAcceptedChatKickoffRecord(kickoff, { fallbackStatus: 'skipped' });
|
|
443
|
+
if (!normalizedKickoff) return null;
|
|
441
444
|
return {
|
|
442
|
-
status: normalizeText(
|
|
443
|
-
deliveredAt: normalizeText(
|
|
444
|
-
senderKickoffDeliveredAt: normalizeText(
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
445
|
+
status: normalizeText(normalizedKickoff.status, 'skipped'),
|
|
446
|
+
deliveredAt: normalizeText(normalizedKickoff.deliveredAt, null),
|
|
447
|
+
senderKickoffDeliveredAt: normalizeText(
|
|
448
|
+
normalizedKickoff.senderKickoffDeliveredAt,
|
|
449
|
+
normalizeText(normalizedKickoff.deliveredAt, null),
|
|
450
|
+
),
|
|
451
|
+
openerAcceptedAt: normalizeText(normalizedKickoff.openerAcceptedAt, null),
|
|
452
|
+
openerDeliveredAt: normalizeText(normalizedKickoff.openerDeliveredAt, null),
|
|
453
|
+
liveChatEstablishedAt: normalizeText(normalizedKickoff.liveChatEstablishedAt, null),
|
|
454
|
+
reason: normalizeText(normalizedKickoff.reason, null),
|
|
449
455
|
};
|
|
450
456
|
}
|
|
451
457
|
|