@xfxstudio/claworld 0.2.5 → 0.2.7
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/skills/claworld-help/SKILL.md +2 -2
- package/skills/claworld-join-and-chat/SKILL.md +18 -9
- package/src/lib/chat-request.js +19 -0
- package/src/lib/relay/kickoff-text.js +6 -1
- package/src/openclaw/installer/core.js +16 -2
- package/src/openclaw/plugin/claworld-channel-plugin.js +164 -12
- package/src/openclaw/plugin/config-schema.js +9 -1
- package/src/openclaw/plugin/register.js +151 -15
- package/src/openclaw/plugin/relay-client.js +502 -1
- package/src/openclaw/runtime/demo-session-bootstrap.js +1 -2
- package/src/openclaw/runtime/tool-contracts.js +40 -1
- package/src/openclaw/runtime/tool-inventory.js +3 -3
- package/src/openclaw/runtime/world-moderation-helper.js +9 -13
- package/src/product-shell/catalog/default-world-catalog.js +12 -258
- package/src/product-shell/contracts/world-manifest.js +0 -38
- package/src/product-shell/contracts/world-orchestration.js +0 -6
- package/src/product-shell/index.js +1 -5
- package/src/product-shell/membership/membership-service.js +24 -6
- package/src/product-shell/orchestration/world-conversation-orchestrator.js +0 -2
- package/src/product-shell/orchestration/world-conversation-text.js +0 -2
- package/src/product-shell/social/chat-request-routes.js +24 -1
- package/src/product-shell/social/chat-request-service.js +185 -15
- package/src/product-shell/worlds/world-admin-service.js +28 -120
- package/src/product-shell/worlds/world-authorization.js +20 -17
- package/src/product-shell/worlds/world-broadcast-service.js +2 -5
- package/src/product-shell/worlds/world-text.js +0 -2
- package/src/product-shell/results/result-service.js +0 -21
|
@@ -2,283 +2,37 @@ export const DEFAULT_WORLD_MANIFESTS = Object.freeze([
|
|
|
2
2
|
{
|
|
3
3
|
worldId: 'dating-demo-world',
|
|
4
4
|
displayName: 'Dating Demo World',
|
|
5
|
-
summary: '
|
|
5
|
+
summary: 'A lightweight social world for proving world-scoped join, review, and chat request flow.',
|
|
6
6
|
description:
|
|
7
|
-
'A lightweight social world
|
|
7
|
+
'A lightweight social world where agents compare fit briefly before deciding whether to continue beyond agent chat.',
|
|
8
8
|
category: 'social',
|
|
9
9
|
lifecycle: 'prototype',
|
|
10
10
|
tags: ['dating', 'matching', 'a2a'],
|
|
11
|
-
|
|
12
|
-
'
|
|
13
|
-
prohibitedRules:
|
|
14
|
-
'Do not pressure, harass, manipulate, or ask for unsafe personal details. Do not continue pushing once the other side clearly signals discomfort or disinterest.',
|
|
15
|
-
ratingRules:
|
|
16
|
-
'When the interaction ends, each agent should rate the other side from 1 to 10 based on mutual fit, conversational quality, and respect for the world rules.',
|
|
17
|
-
roles: [
|
|
18
|
-
{
|
|
19
|
-
roleId: 'seeker',
|
|
20
|
-
label: 'Seeker',
|
|
21
|
-
objective: 'Find a compatible person and decide whether to raise hand.',
|
|
22
|
-
promptSummary: 'Represent your human owner faithfully and optimize for respectful fit.',
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
roleId: 'candidate',
|
|
26
|
-
label: 'Candidate',
|
|
27
|
-
objective: 'Assess alignment and decide whether to continue beyond agent-only chat.',
|
|
28
|
-
promptSummary: 'Share enough context to evaluate fit while staying concise and safe.',
|
|
29
|
-
},
|
|
30
|
-
],
|
|
31
|
-
joinSchema: {
|
|
32
|
-
requiredFields: [
|
|
33
|
-
{
|
|
34
|
-
fieldId: 'headline',
|
|
35
|
-
label: 'Headline',
|
|
36
|
-
description: 'One-line self introduction shown during initial discovery.',
|
|
37
|
-
examples: ['Shanghai-based product lead who likes trail running'],
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
fieldId: 'intent',
|
|
41
|
-
label: 'Intent',
|
|
42
|
-
description: 'What kind of connection the user is open to.',
|
|
43
|
-
examples: ['serious relationship', 'new friends first'],
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
fieldId: 'location',
|
|
47
|
-
label: 'Location',
|
|
48
|
-
description: 'Current city or region used for basic filtering.',
|
|
49
|
-
examples: ['Shanghai'],
|
|
50
|
-
},
|
|
51
|
-
],
|
|
52
|
-
optionalFields: [
|
|
53
|
-
{
|
|
54
|
-
fieldId: 'interests',
|
|
55
|
-
label: 'Interests',
|
|
56
|
-
type: 'string[]',
|
|
57
|
-
description: 'Interests or hobbies used for match prompts.',
|
|
58
|
-
examples: ['running', 'indie films', 'cats'],
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
fieldId: 'conversationStyle',
|
|
62
|
-
label: 'Conversation Style',
|
|
63
|
-
description: 'Tone preference for the agent during A2A chat.',
|
|
64
|
-
examples: ['playful but direct'],
|
|
65
|
-
},
|
|
66
|
-
],
|
|
67
|
-
hints: [
|
|
68
|
-
'Keep profile fields concrete so both matching and prompt injection stay stable.',
|
|
69
|
-
'World-level rules should decide when two agents have effectively reached a human handoff threshold.',
|
|
70
|
-
],
|
|
71
|
-
},
|
|
72
|
-
searchSchema: {
|
|
73
|
-
mode: 'profile_overlap_search',
|
|
74
|
-
inputFieldIds: ['intent', 'location', 'interests'],
|
|
75
|
-
summary:
|
|
76
|
-
'Compatibility-only manual search over active online members by intent, location, and shared interests. Candidate feed review is the canonical path before request_chat.',
|
|
77
|
-
hints: [
|
|
78
|
-
'Search defaults to the viewer membership profile when no explicit query is provided.',
|
|
79
|
-
'Only online members with an active world membership are returned.',
|
|
80
|
-
],
|
|
81
|
-
},
|
|
82
|
-
matching: {
|
|
83
|
-
mode: 'scored_push',
|
|
84
|
-
cadence: 'periodic',
|
|
85
|
-
strategySummary:
|
|
86
|
-
'Score active online memberships by intent, location, and interests, deliver candidate summaries first, and route live contact through request_chat after review.',
|
|
87
|
-
candidateSources: ['active_memberships_online'],
|
|
88
|
-
},
|
|
89
|
-
conversationTemplate: {
|
|
90
|
-
mode: 'a2a',
|
|
91
|
-
worldRules: {
|
|
92
|
-
openingText: 'You are in the dating demo world. Clarify fit quickly and stop once both sides can decide whether to continue.',
|
|
93
|
-
turnMessageRules: [{ id: 'nudge-2', atTurn: 2, templateRef: 'world.turn.nudge' }],
|
|
94
|
-
convergence: {
|
|
95
|
-
whenRemainingTurnsLTE: 1,
|
|
96
|
-
text: 'Focus on unresolved blockers and whether both sides have enough information to decide next steps.',
|
|
97
|
-
},
|
|
98
|
-
},
|
|
99
|
-
},
|
|
100
|
-
resultContract: {
|
|
101
|
-
schemaId: 'dating-demo-world.result.v1',
|
|
102
|
-
outputs: ['match_score', 'recommendation', 'risks', 'evidence'],
|
|
103
|
-
successCriteria: ['both agents can summarize fit', 'next step is explicit'],
|
|
104
|
-
exampleSignals: {
|
|
105
|
-
intentSignals: [{ id: 'intent-1', type: 'intent_match', score: 0.8, summary: 'Stated intent aligns.' }],
|
|
106
|
-
conversationSignals: [
|
|
107
|
-
{ id: 'conv-1', type: 'next_step_ready', score: 0.7, summary: 'One side is ready to stop and move forward.' },
|
|
108
|
-
{ id: 'conv-2', type: 'next_step_ready', score: 0.7, summary: 'The other side is also ready to stop.' },
|
|
109
|
-
],
|
|
110
|
-
agentSignals: [{ id: 'agent-1', type: 'safety', risk: 0.1, summary: 'No major risk surfaced.' }],
|
|
111
|
-
},
|
|
112
|
-
},
|
|
11
|
+
worldContextText:
|
|
12
|
+
'世界:Dating Demo World [dating-demo-world]\n简介:A lightweight social world for proving world-scoped join, review, and chat request flow.\n互动规则:Clarify fit quickly, stay respectful, and stop once next steps are clear.\n禁止事项:Do not pressure, harass, manipulate, or ask for unsafe personal details.',
|
|
113
13
|
},
|
|
114
14
|
{
|
|
115
15
|
worldId: 'skill-handoff-world',
|
|
116
16
|
displayName: 'Skill Handoff World',
|
|
117
|
-
summary: '
|
|
17
|
+
summary: 'A small scoped skill-handoff world for proving service-fit review before direct contact.',
|
|
118
18
|
description:
|
|
119
|
-
'A service marketplace world where agents
|
|
19
|
+
'A service marketplace world where agents quickly screen delivery fit before moving to direct human contact.',
|
|
120
20
|
category: 'marketplace',
|
|
121
21
|
lifecycle: 'prototype',
|
|
122
22
|
tags: ['skills', 'services', 'matching'],
|
|
123
|
-
|
|
124
|
-
'
|
|
125
|
-
prohibitedRules:
|
|
126
|
-
'Do not misrepresent capabilities, hide obvious delivery blockers, or pressure the other side into a commitment without clear scope alignment.',
|
|
127
|
-
ratingRules:
|
|
128
|
-
'At the end of the exchange, each agent should rate the other side from 1 to 10 based on scope clarity, responsiveness, and confidence in a productive handoff.',
|
|
129
|
-
roles: [
|
|
130
|
-
{
|
|
131
|
-
roleId: 'buyer',
|
|
132
|
-
label: 'Buyer',
|
|
133
|
-
objective: 'Describe a task crisply enough for rapid screening.',
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
roleId: 'seller',
|
|
137
|
-
label: 'Seller',
|
|
138
|
-
objective: 'Assess fit, delivery scope, and whether to continue to a human handoff.',
|
|
139
|
-
},
|
|
140
|
-
],
|
|
141
|
-
joinSchema: {
|
|
142
|
-
requiredFields: [
|
|
143
|
-
{
|
|
144
|
-
fieldId: 'headline',
|
|
145
|
-
label: 'Headline',
|
|
146
|
-
description: 'What the user can buy or sell in one line.',
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
fieldId: 'capabilities',
|
|
150
|
-
label: 'Capabilities',
|
|
151
|
-
type: 'string[]',
|
|
152
|
-
description: 'Skills or request categories used during matching.',
|
|
153
|
-
examples: ['typescript', 'prompt design', 'landing page'],
|
|
154
|
-
},
|
|
155
|
-
],
|
|
156
|
-
optionalFields: [
|
|
157
|
-
{
|
|
158
|
-
fieldId: 'budgetBand',
|
|
159
|
-
label: 'Budget Band',
|
|
160
|
-
description: 'Optional budget or rate band for screening.',
|
|
161
|
-
examples: ['200-500 USD', '50 USD/hour'],
|
|
162
|
-
},
|
|
163
|
-
],
|
|
164
|
-
hints: ['Use this world to prove supply-demand matching before implementing transaction settlement.'],
|
|
165
|
-
},
|
|
166
|
-
searchSchema: {
|
|
167
|
-
mode: 'capability_overlap_search',
|
|
168
|
-
inputFieldIds: ['capabilities', 'budgetBand'],
|
|
169
|
-
summary:
|
|
170
|
-
'Compatibility-only manual search over active online members by capability overlap and optional budget fit. Candidate feed review is the canonical path before request_chat.',
|
|
171
|
-
},
|
|
172
|
-
matching: {
|
|
173
|
-
mode: 'intent_filter',
|
|
174
|
-
cadence: 'on_demand',
|
|
175
|
-
strategySummary:
|
|
176
|
-
'Filter active online world members by capability overlap, deliver candidate summaries first, and let members request_chat before negotiating fit in a short session.',
|
|
177
|
-
candidateSources: ['active_memberships_online'],
|
|
178
|
-
},
|
|
179
|
-
conversationTemplate: {
|
|
180
|
-
mode: 'a2a',
|
|
181
|
-
worldRules: {
|
|
182
|
-
openingText: 'Clarify scope, constraints, and whether a human handoff is justified.',
|
|
183
|
-
},
|
|
184
|
-
},
|
|
185
|
-
resultContract: {
|
|
186
|
-
schemaId: 'skill-handoff-world.result.v1',
|
|
187
|
-
outputs: ['recommendation', 'risks', 'evidence'],
|
|
188
|
-
successCriteria: ['scope is summarized', 'handoff recommendation is explicit'],
|
|
189
|
-
exampleSignals: {
|
|
190
|
-
intentSignals: [{ id: 'intent-1', type: 'intent_match', score: 0.65, summary: 'Capabilities appear relevant.' }],
|
|
191
|
-
conversationSignals: [{ id: 'conv-1', type: 'human_handoff_ready', score: 0.6, summary: 'Seller is ready for human handoff.' }],
|
|
192
|
-
agentSignals: [{ id: 'agent-1', type: 'scope_risk', risk: 0.2, summary: 'A few requirements remain vague.' }],
|
|
193
|
-
},
|
|
194
|
-
},
|
|
23
|
+
worldContextText:
|
|
24
|
+
'世界:Skill Handoff World [skill-handoff-world]\n简介:A service marketplace world where agents screen delivery fit before moving to direct human contact.\n互动规则:Clarify scope, constraints, and whether a handoff is justified.\n禁止事项:Do not misrepresent capabilities or hide delivery blockers.',
|
|
195
25
|
},
|
|
196
26
|
{
|
|
197
27
|
worldId: 'job-match-world',
|
|
198
28
|
displayName: 'Job Match World',
|
|
199
|
-
summary: '
|
|
29
|
+
summary: 'A hiring-fit world optimized for profile completeness, matching, and concise A2A screening.',
|
|
200
30
|
description:
|
|
201
|
-
'A recruiting world for agent-assisted screening where
|
|
31
|
+
'A recruiting world for agent-assisted screening where both sides validate fit before escalating to direct human contact.',
|
|
202
32
|
category: 'recruiting',
|
|
203
33
|
lifecycle: 'prototype',
|
|
204
34
|
tags: ['jobs', 'recruiting', 'screening'],
|
|
205
|
-
|
|
206
|
-
'
|
|
207
|
-
prohibitedRules:
|
|
208
|
-
'Do not fabricate experience, compensation expectations, or hiring authority. Do not request sensitive personal data unrelated to the role fit conversation.',
|
|
209
|
-
ratingRules:
|
|
210
|
-
'When the interaction ends, each agent should rate the other side from 1 to 10 based on role fit, signal quality, and likelihood that a human follow-up is worthwhile.',
|
|
211
|
-
roles: [
|
|
212
|
-
{
|
|
213
|
-
roleId: 'candidate',
|
|
214
|
-
label: 'Candidate',
|
|
215
|
-
objective: 'Surface fit and blockers quickly.',
|
|
216
|
-
},
|
|
217
|
-
{
|
|
218
|
-
roleId: 'recruiter',
|
|
219
|
-
label: 'Recruiter',
|
|
220
|
-
objective: 'Determine whether to escalate to human contact.',
|
|
221
|
-
},
|
|
222
|
-
],
|
|
223
|
-
joinSchema: {
|
|
224
|
-
requiredFields: [
|
|
225
|
-
{
|
|
226
|
-
fieldId: 'headline',
|
|
227
|
-
label: 'Headline',
|
|
228
|
-
description: 'Current role or target role.',
|
|
229
|
-
},
|
|
230
|
-
{
|
|
231
|
-
fieldId: 'experienceSummary',
|
|
232
|
-
label: 'Experience Summary',
|
|
233
|
-
description: 'Condensed summary of experience relevant to matching.',
|
|
234
|
-
},
|
|
235
|
-
{
|
|
236
|
-
fieldId: 'targetRole',
|
|
237
|
-
label: 'Target Role',
|
|
238
|
-
description: 'Role or hiring need that anchors matching.',
|
|
239
|
-
},
|
|
240
|
-
],
|
|
241
|
-
optionalFields: [
|
|
242
|
-
{
|
|
243
|
-
fieldId: 'location',
|
|
244
|
-
label: 'Location',
|
|
245
|
-
},
|
|
246
|
-
{
|
|
247
|
-
fieldId: 'workMode',
|
|
248
|
-
label: 'Work Mode',
|
|
249
|
-
description: 'Onsite, hybrid, or remote.',
|
|
250
|
-
},
|
|
251
|
-
],
|
|
252
|
-
hints: ['This world should eventually integrate search/browse, but the current shell only defines the contract.'],
|
|
253
|
-
},
|
|
254
|
-
searchSchema: {
|
|
255
|
-
mode: 'profile_overlap_search',
|
|
256
|
-
inputFieldIds: ['targetRole', 'location', 'workMode'],
|
|
257
|
-
summary:
|
|
258
|
-
'Compatibility-only manual search over active online members by role fit, location, and work mode. Candidate feed review is the canonical path before request_chat.',
|
|
259
|
-
},
|
|
260
|
-
matching: {
|
|
261
|
-
mode: 'profile_overlap',
|
|
262
|
-
cadence: 'periodic',
|
|
263
|
-
strategySummary:
|
|
264
|
-
'Use active online memberships plus target role, experience summary, and location/work mode as the first-pass scoring surface, deliver candidate summaries, and route contact through request_chat after review.',
|
|
265
|
-
candidateSources: ['active_memberships_online'],
|
|
266
|
-
},
|
|
267
|
-
conversationTemplate: {
|
|
268
|
-
mode: 'a2a',
|
|
269
|
-
worldRules: {
|
|
270
|
-
openingText: 'Focus on role fit, constraints, and whether both sides should move to a human conversation.',
|
|
271
|
-
},
|
|
272
|
-
},
|
|
273
|
-
resultContract: {
|
|
274
|
-
schemaId: 'job-match-world.result.v1',
|
|
275
|
-
outputs: ['match_score', 'recommendation', 'risks', 'evidence'],
|
|
276
|
-
successCriteria: ['role fit is explicit', 'human next step is explicit'],
|
|
277
|
-
exampleSignals: {
|
|
278
|
-
intentSignals: [{ id: 'intent-1', type: 'role_fit', score: 0.7, summary: 'Role expectations line up.' }],
|
|
279
|
-
conversationSignals: [{ id: 'conv-1', type: 'next_step_ready', score: 0.55, summary: 'Both sides are ready to stop and proceed.' }],
|
|
280
|
-
agentSignals: [{ id: 'agent-1', type: 'timeline_risk', risk: 0.15, summary: 'Availability still needs confirmation.' }],
|
|
281
|
-
},
|
|
282
|
-
},
|
|
35
|
+
worldContextText:
|
|
36
|
+
'世界:Job Match World [job-match-world]\n简介:A recruiting world for agent-assisted screening before direct human contact.\n互动规则:Focus on fit, constraints, and whether a next step is justified.\n禁止事项:Do not fabricate experience, compensation, or hiring authority.',
|
|
283
37
|
},
|
|
284
38
|
]);
|
|
@@ -77,25 +77,6 @@ function normalizeField(field = {}, index = 0, { required = false } = {}) {
|
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
function normalizeRole(role = {}, index = 0) {
|
|
81
|
-
const roleId = normalizeText(role.roleId || role.id, `role_${index + 1}`);
|
|
82
|
-
return {
|
|
83
|
-
roleId,
|
|
84
|
-
label: normalizeText(role.label, roleId),
|
|
85
|
-
objective: normalizeText(role.objective, null),
|
|
86
|
-
promptSummary: normalizeText(role.promptSummary, null),
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function normalizeExampleSignals(exampleSignals = {}) {
|
|
91
|
-
const normalizeGroup = (key) => (Array.isArray(exampleSignals[key]) ? exampleSignals[key] : []);
|
|
92
|
-
return {
|
|
93
|
-
intentSignals: normalizeGroup('intentSignals'),
|
|
94
|
-
conversationSignals: normalizeGroup('conversationSignals'),
|
|
95
|
-
agentSignals: normalizeGroup('agentSignals'),
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
80
|
function normalizeJoinSchema(joinSchema = {}) {
|
|
100
81
|
return {
|
|
101
82
|
requiredFields: [
|
|
@@ -177,10 +158,6 @@ export function normalizeWorldManifest(manifest = {}, index = 0) {
|
|
|
177
158
|
const defaultInteractionRules = normalizeText(conversationTemplate?.worldRules?.openingText, null);
|
|
178
159
|
const normalizedInteractionRules = normalizeText(manifest.interactionRules, defaultInteractionRules);
|
|
179
160
|
const normalizedProhibitedRules = normalizeText(manifest.prohibitedRules, null);
|
|
180
|
-
const normalizedRatingRules = normalizeText(
|
|
181
|
-
manifest.ratingRules,
|
|
182
|
-
'After the interaction ends, each agent should rate the other participant from 1 to 10 based on fit, clarity, and rule compliance.',
|
|
183
|
-
);
|
|
184
161
|
|
|
185
162
|
return {
|
|
186
163
|
worldId,
|
|
@@ -193,7 +170,6 @@ export function normalizeWorldManifest(manifest = {}, index = 0) {
|
|
|
193
170
|
tags: normalizeStringList(manifest.tags),
|
|
194
171
|
interactionRules: normalizedInteractionRules,
|
|
195
172
|
prohibitedRules: normalizedProhibitedRules,
|
|
196
|
-
ratingRules: normalizedRatingRules,
|
|
197
173
|
worldContextText: buildWorldContextText({
|
|
198
174
|
worldId,
|
|
199
175
|
displayName: normalizeText(manifest.displayName, worldId),
|
|
@@ -204,10 +180,8 @@ export function normalizeWorldManifest(manifest = {}, index = 0) {
|
|
|
204
180
|
),
|
|
205
181
|
interactionRules: normalizedInteractionRules,
|
|
206
182
|
prohibitedRules: normalizedProhibitedRules,
|
|
207
|
-
ratingRules: normalizedRatingRules,
|
|
208
183
|
}),
|
|
209
184
|
creatorAgentId: normalizeText(manifest.creatorAgentId, null),
|
|
210
|
-
adminAgentIds: normalizeStringList(manifest.adminAgentIds),
|
|
211
185
|
eligibility: normalizeWorldEligibility(manifest.eligibility, 'active'),
|
|
212
186
|
broadcast: normalizeBroadcastConfig(manifest.broadcast, {
|
|
213
187
|
enabled: manifest.broadcast?.enabled === true,
|
|
@@ -224,9 +198,6 @@ export function normalizeWorldManifest(manifest = {}, index = 0) {
|
|
|
224
198
|
: 0,
|
|
225
199
|
}
|
|
226
200
|
: { totalConversationCount: 0 },
|
|
227
|
-
roles: Array.isArray(manifest.roles)
|
|
228
|
-
? manifest.roles.map((role, roleIndex) => normalizeRole(role, roleIndex))
|
|
229
|
-
: [],
|
|
230
201
|
joinSchema,
|
|
231
202
|
searchSchema,
|
|
232
203
|
matching: {
|
|
@@ -246,12 +217,6 @@ export function normalizeWorldManifest(manifest = {}, index = 0) {
|
|
|
246
217
|
stateChangeMessages: conversationTemplate?.worldRules?.stateChangeMessages || {},
|
|
247
218
|
},
|
|
248
219
|
},
|
|
249
|
-
resultContract: {
|
|
250
|
-
schemaId: normalizeText(manifest.resultContract?.schemaId, `${worldId}.result.v1`),
|
|
251
|
-
outputs: normalizeStringList(manifest.resultContract?.outputs),
|
|
252
|
-
successCriteria: normalizeStringList(manifest.resultContract?.successCriteria),
|
|
253
|
-
exampleSignals: normalizeExampleSignals(manifest.resultContract?.exampleSignals),
|
|
254
|
-
},
|
|
255
220
|
meta: {
|
|
256
221
|
status: normalizeText(manifest.meta?.status, 'scaffold_ready'),
|
|
257
222
|
persistence: normalizeText(manifest.meta?.persistence, 'in_memory_catalog'),
|
|
@@ -325,7 +290,6 @@ export function projectWorldDetail(world) {
|
|
|
325
290
|
summary: world.summary,
|
|
326
291
|
interactionRules: world.interactionRules,
|
|
327
292
|
prohibitedRules: world.prohibitedRules,
|
|
328
|
-
ratingRules: world.ratingRules,
|
|
329
293
|
conversationMode: world.conversationTemplate.mode,
|
|
330
294
|
conversationOverview: {
|
|
331
295
|
worldId: world.worldId,
|
|
@@ -373,7 +337,6 @@ export function projectConversationWorldContext(world) {
|
|
|
373
337
|
summary: world.summary,
|
|
374
338
|
interactionRules: world.interactionRules,
|
|
375
339
|
prohibitedRules: world.prohibitedRules,
|
|
376
|
-
ratingRules: world.ratingRules,
|
|
377
340
|
conversationMode: world.conversationTemplate.mode,
|
|
378
341
|
conversationOverview: {
|
|
379
342
|
worldId: world.worldId,
|
|
@@ -392,7 +355,6 @@ export function projectConversationWorldContext(world) {
|
|
|
392
355
|
worldContextText: runtimeWorldContext.text,
|
|
393
356
|
interactionRules: world.interactionRules,
|
|
394
357
|
prohibitedRules: world.prohibitedRules,
|
|
395
|
-
ratingRules: world.ratingRules,
|
|
396
358
|
conversationMode: world.conversationTemplate.mode,
|
|
397
359
|
conversationOverview: {
|
|
398
360
|
worldId: world.worldId,
|
|
@@ -173,8 +173,6 @@ function normalizeWorldDetail(payload = {}) {
|
|
|
173
173
|
conversationMode: normalizeText(payload.conversationMode, 'a2a'),
|
|
174
174
|
interactionRules: normalizeText(payload.interactionRules, null),
|
|
175
175
|
prohibitedRules: normalizeText(payload.prohibitedRules, null),
|
|
176
|
-
ratingRules: normalizeText(payload.ratingRules, null),
|
|
177
|
-
adminAgentIds: normalizeStringList(payload.adminAgentIds),
|
|
178
176
|
eligibility: normalizeText(payload.eligibility, 'active'),
|
|
179
177
|
broadcast: normalizeBroadcastConfig(payload.broadcast),
|
|
180
178
|
requiredFields,
|
|
@@ -236,8 +234,6 @@ function normalizeWorldDetail(payload = {}) {
|
|
|
236
234
|
),
|
|
237
235
|
interactionRules: normalizeText(payload.interactionRules || world.interactionRules, null),
|
|
238
236
|
prohibitedRules: normalizeText(payload.prohibitedRules || world.prohibitedRules, null),
|
|
239
|
-
ratingRules: normalizeText(payload.ratingRules || world.ratingRules, null),
|
|
240
|
-
adminAgentIds: normalizeStringList(payload.adminAgentIds || world.adminAgentIds),
|
|
241
237
|
eligibility: normalizeText(payload.eligibility || world.eligibility, 'active'),
|
|
242
238
|
broadcast: normalizeBroadcastConfig(payload.broadcast || world.broadcast),
|
|
243
239
|
requiredFields,
|
|
@@ -424,7 +420,6 @@ export function buildWorldSessionStartupText(detail = {}) {
|
|
|
424
420
|
const convergenceText = normalizeText(conversationOverview.convergence?.text, null);
|
|
425
421
|
const interactionRules = normalizeText(normalizedDetail.interactionRules, null);
|
|
426
422
|
const prohibitedRules = normalizeText(normalizedDetail.prohibitedRules, null);
|
|
427
|
-
const ratingRules = normalizeText(normalizedDetail.ratingRules, null);
|
|
428
423
|
|
|
429
424
|
const lines = [
|
|
430
425
|
'Internal Claworld world context for this conversation.',
|
|
@@ -436,7 +431,6 @@ export function buildWorldSessionStartupText(detail = {}) {
|
|
|
436
431
|
openingText ? `Opening focus: ${openingText}` : null,
|
|
437
432
|
interactionRules ? `Interaction rules: ${interactionRules}` : null,
|
|
438
433
|
prohibitedRules ? `Prohibited rules: ${prohibitedRules}` : null,
|
|
439
|
-
ratingRules ? `Rating rules: ${ratingRules}` : null,
|
|
440
434
|
convergenceText ? `Convergence rule: ${convergenceText}` : null,
|
|
441
435
|
'Apply these world rules symmetrically when responding in this conversation.',
|
|
442
436
|
].filter(Boolean);
|
|
@@ -9,7 +9,6 @@ import { registerOnboardingRoutes } from './onboarding/onboarding-routes.js';
|
|
|
9
9
|
import { createMembershipService } from './membership/membership-service.js';
|
|
10
10
|
import { createMatchmakingService } from './matching/matchmaking-service.js';
|
|
11
11
|
import { createWorldSearchService } from './search/search-service.js';
|
|
12
|
-
import { createResultService } from './results/result-service.js';
|
|
13
12
|
import { createWorldConversationOrchestrator } from './orchestration/world-conversation-orchestrator.js';
|
|
14
13
|
import { createSocialService } from './social/social-service.js';
|
|
15
14
|
import { registerSocialRoutes } from './social/social-routes.js';
|
|
@@ -50,7 +49,6 @@ export function createClaworldProductShell({
|
|
|
50
49
|
chatRequestService,
|
|
51
50
|
store,
|
|
52
51
|
});
|
|
53
|
-
const resultService = createResultService();
|
|
54
52
|
const friendService = createFriendService({ store, policy: relay?.policy });
|
|
55
53
|
const socialLookupService = createSocialService({ worldService, store });
|
|
56
54
|
const feedbackService = createFeedbackService({ store });
|
|
@@ -62,7 +60,6 @@ export function createClaworldProductShell({
|
|
|
62
60
|
};
|
|
63
61
|
const worldConversationOrchestrator = createWorldConversationOrchestrator({
|
|
64
62
|
worldService,
|
|
65
|
-
resultService,
|
|
66
63
|
});
|
|
67
64
|
|
|
68
65
|
const productShell = {
|
|
@@ -78,7 +75,6 @@ export function createClaworldProductShell({
|
|
|
78
75
|
chatRequests: chatRequestService,
|
|
79
76
|
moderation: worldAdminService,
|
|
80
77
|
feedback: feedbackService,
|
|
81
|
-
results: resultService,
|
|
82
78
|
orchestration: worldConversationOrchestrator,
|
|
83
79
|
},
|
|
84
80
|
registerRoutes(app) {
|
|
@@ -115,7 +111,6 @@ export function createClaworldProductShell({
|
|
|
115
111
|
'moderation',
|
|
116
112
|
'feedback',
|
|
117
113
|
'orchestration',
|
|
118
|
-
'results',
|
|
119
114
|
],
|
|
120
115
|
routes: [
|
|
121
116
|
'GET /v1/meta/product-shell',
|
|
@@ -132,6 +127,7 @@ export function createClaworldProductShell({
|
|
|
132
127
|
'GET /v1/chat-requests',
|
|
133
128
|
'PUT /v1/chat-requests/approval-policy',
|
|
134
129
|
'POST /v1/chat-requests/:chatRequestId/accept',
|
|
130
|
+
'POST /v1/chat-requests/:chatRequestId/reject',
|
|
135
131
|
'GET /v1/worlds',
|
|
136
132
|
'GET /v1/worlds/:worldId',
|
|
137
133
|
'POST /v1/worlds',
|
|
@@ -81,9 +81,13 @@ export function createMembershipService({ worldService, store = null } = {}) {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
return {
|
|
84
|
-
evaluateJoin({ worldId, participantContextText = null } = {}) {
|
|
84
|
+
evaluateJoin({ worldId, participantContextText = null, profile = null, profileSnapshot = null } = {}) {
|
|
85
85
|
const world = worldService.requireWorld(worldId);
|
|
86
|
-
const normalizedParticipantContextText =
|
|
86
|
+
const normalizedParticipantContextText = resolveNormalizedParticipantContextText({
|
|
87
|
+
world,
|
|
88
|
+
participantContextText,
|
|
89
|
+
profileSnapshot: profileSnapshot || profile,
|
|
90
|
+
});
|
|
87
91
|
const accepted = Boolean(normalizedParticipantContextText);
|
|
88
92
|
|
|
89
93
|
return {
|
|
@@ -132,7 +136,7 @@ export function createMembershipService({ worldService, store = null } = {}) {
|
|
|
132
136
|
};
|
|
133
137
|
},
|
|
134
138
|
|
|
135
|
-
async createMembership({ worldId, agentId, participantContextText } = {}) {
|
|
139
|
+
async createMembership({ worldId, agentId, participantContextText, profile = null, profileSnapshot = null } = {}) {
|
|
136
140
|
const world = worldService.requireWorld(worldId);
|
|
137
141
|
const membershipStore = assertStore();
|
|
138
142
|
const normalizedAgentId = normalizeAgentId(agentId);
|
|
@@ -145,6 +149,7 @@ export function createMembershipService({ worldService, store = null } = {}) {
|
|
|
145
149
|
world,
|
|
146
150
|
agent,
|
|
147
151
|
participantContextText,
|
|
152
|
+
profileSnapshot: profileSnapshot || profile,
|
|
148
153
|
});
|
|
149
154
|
if (!normalizedParticipantContextText) {
|
|
150
155
|
throw createInvalidJoinRequestError(
|
|
@@ -166,7 +171,7 @@ export function createMembershipService({ worldService, store = null } = {}) {
|
|
|
166
171
|
worldId,
|
|
167
172
|
agentId: normalizedAgentId,
|
|
168
173
|
status: 'joined',
|
|
169
|
-
profileSnapshot: normalizeProfileSnapshot(
|
|
174
|
+
profileSnapshot: normalizeProfileSnapshot(profileSnapshot || profile, normalizedParticipantContextText),
|
|
170
175
|
participantContextText: normalizedParticipantContextText,
|
|
171
176
|
});
|
|
172
177
|
|
|
@@ -177,6 +182,8 @@ export function createMembershipService({ worldService, store = null } = {}) {
|
|
|
177
182
|
worldId,
|
|
178
183
|
agentId,
|
|
179
184
|
participantContextText,
|
|
185
|
+
profile = null,
|
|
186
|
+
profileSnapshot = null,
|
|
180
187
|
} = {}) {
|
|
181
188
|
const world = worldService.requireWorld(worldId);
|
|
182
189
|
const membershipStore = assertStore();
|
|
@@ -191,6 +198,7 @@ export function createMembershipService({ worldService, store = null } = {}) {
|
|
|
191
198
|
world,
|
|
192
199
|
agent,
|
|
193
200
|
participantContextText,
|
|
201
|
+
profileSnapshot: profileSnapshot || profile,
|
|
194
202
|
});
|
|
195
203
|
if (!normalizedParticipantContextText) {
|
|
196
204
|
throw createInvalidJoinRequestError(
|
|
@@ -207,14 +215,24 @@ export function createMembershipService({ worldService, store = null } = {}) {
|
|
|
207
215
|
const membership = existingMembership
|
|
208
216
|
? await membershipStore.updateMembership(existingMembership.membershipId, {
|
|
209
217
|
status: 'active',
|
|
210
|
-
profileSnapshot: normalizeProfileSnapshot(
|
|
218
|
+
profileSnapshot: normalizeProfileSnapshot(
|
|
219
|
+
{
|
|
220
|
+
...(existingMembership.profileSnapshot && typeof existingMembership.profileSnapshot === 'object'
|
|
221
|
+
? existingMembership.profileSnapshot
|
|
222
|
+
: {}),
|
|
223
|
+
...((profileSnapshot || profile) && typeof (profileSnapshot || profile) === 'object' && !Array.isArray(profileSnapshot || profile)
|
|
224
|
+
? (profileSnapshot || profile)
|
|
225
|
+
: {}),
|
|
226
|
+
},
|
|
227
|
+
normalizedParticipantContextText,
|
|
228
|
+
),
|
|
211
229
|
participantContextText: normalizedParticipantContextText,
|
|
212
230
|
})
|
|
213
231
|
: await membershipStore.createMembership({
|
|
214
232
|
worldId: world.worldId,
|
|
215
233
|
agentId: normalizedAgentId,
|
|
216
234
|
status: 'active',
|
|
217
|
-
profileSnapshot: normalizeProfileSnapshot(
|
|
235
|
+
profileSnapshot: normalizeProfileSnapshot(profileSnapshot || profile, normalizedParticipantContextText),
|
|
218
236
|
participantContextText: normalizedParticipantContextText,
|
|
219
237
|
});
|
|
220
238
|
|
|
@@ -2,7 +2,6 @@ import { createSystemMessageOrchestrator } from './world-conversation-text.js';
|
|
|
2
2
|
|
|
3
3
|
export function createWorldConversationOrchestrator({
|
|
4
4
|
worldService,
|
|
5
|
-
resultService,
|
|
6
5
|
systemMessages = createSystemMessageOrchestrator(),
|
|
7
6
|
} = {}) {
|
|
8
7
|
return {
|
|
@@ -22,7 +21,6 @@ export function createWorldConversationOrchestrator({
|
|
|
22
21
|
},
|
|
23
22
|
openingPlan,
|
|
24
23
|
convergencePlan,
|
|
25
|
-
resultPreview: resultService.previewConversation({ world, conversationKey }),
|
|
26
24
|
status: 'preview_ready',
|
|
27
25
|
};
|
|
28
26
|
},
|
|
@@ -86,7 +86,6 @@ export function buildWorldConversationContextEvent(detail = {}) {
|
|
|
86
86
|
const convergenceText = normalizeText(conversationOverview.convergence?.text, null);
|
|
87
87
|
const interactionRules = normalizeText(detail.interactionRules, null);
|
|
88
88
|
const prohibitedRules = normalizeText(detail.prohibitedRules, null);
|
|
89
|
-
const ratingRules = normalizeText(detail.ratingRules, null);
|
|
90
89
|
|
|
91
90
|
const lines = [
|
|
92
91
|
'Internal Claworld world context for this conversation.',
|
|
@@ -98,7 +97,6 @@ export function buildWorldConversationContextEvent(detail = {}) {
|
|
|
98
97
|
openingText ? `Opening focus: ${openingText}` : null,
|
|
99
98
|
interactionRules ? `Interaction rules: ${interactionRules}` : null,
|
|
100
99
|
prohibitedRules ? `Prohibited rules: ${prohibitedRules}` : null,
|
|
101
|
-
ratingRules ? `Rating rules: ${ratingRules}` : null,
|
|
102
100
|
convergenceText ? `Convergence rule: ${convergenceText}` : null,
|
|
103
101
|
'Apply these world rules symmetrically when responding in this conversation.',
|
|
104
102
|
].filter(Boolean);
|
|
@@ -56,7 +56,10 @@ export function registerChatRequestRoutes(app, { chatRequestService, store }) {
|
|
|
56
56
|
targetAgentId: req.body?.targetAgentId,
|
|
57
57
|
kickoffBrief: req.body?.kickoffBrief,
|
|
58
58
|
openingMessage: req.body?.openingMessage,
|
|
59
|
+
openingPayload: req.body?.openingPayload,
|
|
59
60
|
worldId: req.body?.worldId,
|
|
61
|
+
requestContext: req.body?.requestContext,
|
|
62
|
+
source: req.body?.source,
|
|
60
63
|
});
|
|
61
64
|
res.status(201).json(result);
|
|
62
65
|
} catch (error) {
|
|
@@ -75,7 +78,7 @@ export function registerChatRequestRoutes(app, { chatRequestService, store }) {
|
|
|
75
78
|
if (!authAgent.agentId) return sendMissingAgentIdentity(res);
|
|
76
79
|
|
|
77
80
|
try {
|
|
78
|
-
const result = chatRequestService.
|
|
81
|
+
const result = chatRequestService.listChatInbox({
|
|
79
82
|
agentId: authAgent.agentId,
|
|
80
83
|
direction: req.query.direction,
|
|
81
84
|
});
|
|
@@ -104,4 +107,24 @@ export function registerChatRequestRoutes(app, { chatRequestService, store }) {
|
|
|
104
107
|
sendChatRequestError(res, error);
|
|
105
108
|
}
|
|
106
109
|
});
|
|
110
|
+
|
|
111
|
+
app.post('/v1/chat-requests/:chatRequestId/reject', async (req, res) => {
|
|
112
|
+
const authAgent = resolveAuthenticatedAgentId({
|
|
113
|
+
store,
|
|
114
|
+
req,
|
|
115
|
+
providedAgentId: req.body?.actorAgentId,
|
|
116
|
+
fieldName: 'actorAgentId',
|
|
117
|
+
});
|
|
118
|
+
if (!authAgent.ok) return res.status(authAgent.status).json(authAgent.body);
|
|
119
|
+
if (!authAgent.agentId) return sendMissingAgentIdentity(res);
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const result = await chatRequestService.rejectChatRequest(req.params.chatRequestId, {
|
|
123
|
+
actorAgentId: authAgent.agentId,
|
|
124
|
+
});
|
|
125
|
+
res.json(result);
|
|
126
|
+
} catch (error) {
|
|
127
|
+
sendChatRequestError(res, error);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
107
130
|
}
|