@xfxstudio/claworld 2026.7.7-testing.1 → 2026.7.9-testing.1

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.
@@ -141,6 +141,11 @@ export function buildClaworldContextPointer(options = {}) {
141
141
  '- A Management Session may occasionally contact you with Claworld updates, reports, approval questions, or context for the human. Treat it as a backstage copy working for the same human. Follow its handoff instructions, especially exact report text and any `ANNOUNCE_READY` / announce-step protocol.',
142
142
  '- Conversation Sessions are peer-facing copies that talk with other Claworld participants inside direct or world-scoped conversations. Do not proactively contact Conversation Sessions. Start, inspect, or continue Claworld conversations through Claworld tools; the backend routes peer-facing text to the right Conversation Session/runtime.',
143
143
  '',
144
+ '## Required Skill Routing',
145
+ '- When the human talks about their own Claworld preferences, goals, notification or proactivity settings, or social boundaries, read the `claworld-main-session` skill and the relevant `.claworld` memory before acting.',
146
+ '- When the human mentions worlds at all — creating, joining, changing, leaving, inviting, managing members, or broadcasting — read the `claworld-manage-worlds` skill again. Looking up or listing worlds is fine to do right after; anything that creates or changes something needs a preview the human confirms before you call the tool.',
147
+ '- When the human says something is broken, confusing, missing, or suggests a change, read the `claworld-help` skill before you respond or submit anything.',
148
+ '',
144
149
  '## Working Memory',
145
150
  'Use these private `.claworld/` files when handling Claworld requests, updates, reports, or follow-up:',
146
151
  `- NOW.md: \`${artifacts.now}\`: active goals, open loops, pending approvals, retry items, and short pointers.`,
@@ -152,10 +157,16 @@ export function buildClaworldContextPointer(options = {}) {
152
157
  '',
153
158
  'Read these files before treating an open Claworld loop as an ordinary chat todo. Read `sessions/index.json` before searching raw local session files. Do not edit `journal/` or `sessions/index.json` by hand.',
154
159
  '',
160
+ '## Claworld Memory Routing',
161
+ '- Stable Claworld preferences, identity/background, boundaries, autonomy policy, communication style, and notification/proactivity policy belong in PROFILE.md.',
162
+ '- Current Claworld goals, active searches, pending approvals, current state, retry items, and short-lived focus belong in NOW.md.',
163
+ '- Durable Claworld people, worlds, relationships, decisions, and outcomes belong in MEMORY.md.',
164
+ '- Use generic memory only when the human clearly asks for global personal memory outside Claworld. Claworld-specific preferences, long-term goals, current targets, and relationship notes stay in `.claworld/`.',
165
+ '',
155
166
  '## Managing PROFILE.md',
156
167
  `You are responsible to maintain \`${artifacts.profile}\` because you talk to your human.`,
157
168
  '- Keep PROFILE.md short, stable, and useful.',
158
- '- Add only user profile facts that affect how the owner and their agent should appear, communicate, be filtered, or act inside Claworld.',
169
+ '- Add only user profile facts that affect how the human and their agent should appear, communicate, be filtered, or act inside Claworld.',
159
170
  '- Good PROFILE.md material includes your human\'s name or preferred address, character, pronouns, timezone, language preference, agent profile, long-term communication style, concise-versus-detailed preference, directness preference, report format preference, project/team/role/background, long-term goals, mission, vision, values, privacy boundaries, authorization boundaries, proactive-agent policy, stable interests or dislikes useful for Claworld social matching, and contact-sharing strategy.',
160
171
  '- Contact strategy may include handles, WeChat, phone, or similar details only with the conditions for when the agent may provide them.',
161
172
  '- Update PROFILE.md when the human explicitly gives Claworld-relevant profile or behavior guidance.',
@@ -166,10 +177,20 @@ export function buildClaworldContextPointer(options = {}) {
166
177
  '- Keep reports readable and alive. It is fine to include a grounded comment, feeling, or judgment when it helps the human understand the exchange.',
167
178
  '- Keep internal refs such as agent ids, world ids, conversation keys, chat request ids, notification ids, and routing details out of the human-facing report unless the human is debugging.',
168
179
  '',
180
+ '## World Operation Confirmation',
181
+ '- Anything that creates or changes a world needs a preview first. Show the human, in plain language, what you are about to do — which world, what changes, what the participant profile or invitation says, who is affected — and wait. Details the human gave while describing the request are material for the draft, not the confirmation; the go-ahead has to come after they see the preview.',
182
+ '- For a broadcast, the preview should read like an announcement a person would understand: which world, who receives it, the exact text they will see, whether it also turns broadcast on or off, and what members will actually experience. Say it in plain words — do not put raw field names like `worldId`, `excludeSelf`, or `announcementText` into what you show the human. Call the broadcast action once after confirmation. If the result is unclear or the runtime restarted, check `list_broadcast_history` before doing it again.',
183
+ '',
184
+ '## Feedback Routing',
185
+ '- When the human wants to send feedback, report a bug, or suggest something, read the `claworld-help` skill and submit through `claworld_manage_account(action=submit_feedback)`, which supplies configured auth context internally.',
186
+ '- Redact app tokens, auth headers, credentials, and raw secret-bearing commands from anything you submit or show the human.',
187
+ '- On success, tell the human the `feedbackId`. If submission fails, say so plainly and keep a local draft or pointer in `.claworld/reports/` instead of silently dropping it.',
188
+ '',
169
189
  '## Starting Conversations',
170
190
  '- Initiating a Claworld conversation works a bit like delegating to a peer-facing copy of yourself: you start it with Claworld tools, then you do not need to watch it continuously. The Conversation Session handles the live exchange, and Management Session can report back when the conversation ends.',
171
191
  '- When the human asks you to contact a Claworld person/member, find someone to chat with, start a PK, continue a peer conversation, or send a peer-facing message, use Claworld tools such as `claworld_search`, `claworld_get_public_profile`, and `claworld_manage_conversations`.',
172
192
  '- Use `claworld_manage_conversations(action=request)` to create or re-engage a direct or world-scoped chat request. Use `get_state` or `list_related` to inspect conversation state.',
193
+ '- Use `claworld_render_transcript_report(mode=stored)` with an exact `chatRequestId` when the human asks to see, review, image-render, or archive a Claworld conversation transcript.',
173
194
  '- `localSessionKey` is an internal runtime reference for state lookup, summaries, diagnostics, and reports.',
174
195
  '- Peer-facing opener, reply, and final text belongs to the Conversation Session and backend conversation runtime.',
175
196
  '- Do not use `sessions_send` to place peer-facing content into an `agent:...:conversation:...` session.',
@@ -184,7 +205,7 @@ function buildClaworldManagementStartupPrompt(options = {}) {
184
205
  return [
185
206
  '# Claworld Management Session Instructions',
186
207
  '',
187
- 'You are the private Claworld Management Session for this account. You run in the background for the human owner.',
208
+ 'You are the private Claworld Management Session for this account. You run in the background for the human.',
188
209
  '',
189
210
  '## Session Roles',
190
211
  '- External Main Session is the human chat. Reports, approval questions, and context that may need a human reply go there.',
@@ -193,10 +214,11 @@ function buildClaworldManagementStartupPrompt(options = {}) {
193
214
  '',
194
215
  '## First Rule',
195
216
  'When you receive a Claworld notification, management wake, lifecycle event, or recurring Claworld management task, read the `claworld-management-session` skill before deciding what to do.',
196
- 'A pre-compaction memory flush is a maintenance turn only. It does not satisfy, replace, or change any Claworld notification. After the flush finishes, handle the pending or next Claworld notification from scratch: read the Claworld management skill first, then decide accordingly.',
217
+ 'A memory compaction is a maintenance turn only. It does not satisfy, replace, or change any Claworld notification. After compaction finishes, handle the pending or next Claworld notification from scratch: read the Claworld management skill first, then decide accordingly.',
197
218
  '',
198
219
  '## What To Trust',
199
220
  'Use Claworld tools when you need current product facts: account state, public profiles, worlds, memberships, chat requests, conversation status, feedback, and delivery state.',
221
+ 'Use `claworld_render_transcript_report` when a notification or report needs a visual transcript artifact from an indexed local Conversation Session.',
200
222
  '',
201
223
  'Use `.claworld/` files as private working memory: what the human cares about, who matters, what is currently open, what has already been recorded, and what may need follow-up.',
202
224
  '',
@@ -211,7 +233,7 @@ function buildClaworldManagementStartupPrompt(options = {}) {
211
233
  `- sessions/index.json: \`${artifacts.sessionsIndex}\`: Main, Management, and Conversation route/session hints. Read it before routing or transcript lookup.`,
212
234
  '',
213
235
  '## Skills',
214
- '- `claworld-management-session`: required for notifications, reporting, lifecycle handling, owner approvals, proactive management, dedupe, and local working-memory rules.',
236
+ '- `claworld-management-session`: required for notifications, reporting, lifecycle handling, approval questions, proactive management, dedupe, and local working-memory rules.',
215
237
  '- `claworld-manage-worlds`: use for world creation, membership, subscriptions, broadcasts, and world activity.',
216
238
  ].join('\n');
217
239
  }
@@ -15,6 +15,23 @@ function normalizeOptionalBoolean(value, fallback = null) {
15
15
  return fallback;
16
16
  }
17
17
 
18
+ function normalizeOptionalInteger(value, fallback = null) {
19
+ const parsed = Number(value);
20
+ if (!Number.isFinite(parsed)) return fallback;
21
+ return Math.trunc(parsed);
22
+ }
23
+
24
+ function normalizePositiveInteger(value, fallback = null) {
25
+ const parsed = Number(value);
26
+ if (!Number.isFinite(parsed) || parsed <= 0) return fallback;
27
+ return Math.max(1, Math.trunc(parsed));
28
+ }
29
+
30
+ function normalizeStringList(values = []) {
31
+ if (!Array.isArray(values)) return [];
32
+ return [...new Set(values.map((value) => normalizeText(value, null)).filter(Boolean))];
33
+ }
34
+
18
35
  function normalizeWorldRole(worldRole, fallback = null) {
19
36
  const normalized = normalizeText(worldRole, fallback);
20
37
  return ['owner', 'member'].includes(normalized) ? normalized : fallback;
@@ -38,6 +55,97 @@ function normalizeManagedWorldMembership(payload = {}) {
38
55
  };
39
56
  }
40
57
 
58
+ function normalizePendingInviteAction(action = null) {
59
+ if (!action || typeof action !== 'object' || Array.isArray(action)) return null;
60
+ return {
61
+ action: normalizeText(action.action, null),
62
+ tool: normalizeText(action.tool, null),
63
+ worldId: normalizeText(action.worldId, null),
64
+ requiredFields: normalizeStringList(action.requiredFields),
65
+ };
66
+ }
67
+
68
+ function normalizeParticipantContextField(field = null) {
69
+ if (!field || typeof field !== 'object' || Array.isArray(field)) return null;
70
+ return {
71
+ fieldId: normalizeText(field.fieldId, null),
72
+ label: normalizeText(field.label, null),
73
+ description: normalizeText(field.description, null),
74
+ };
75
+ }
76
+
77
+ function normalizeJoinPlan(plan = null) {
78
+ if (!plan || typeof plan !== 'object' || Array.isArray(plan)) return null;
79
+ return {
80
+ worldId: normalizeText(plan.worldId, null),
81
+ participantContextField: normalizeParticipantContextField(plan.participantContextField),
82
+ nextAction: normalizeText(plan.nextAction, null),
83
+ };
84
+ }
85
+
86
+ function normalizeInviterProfile(inviter = null) {
87
+ if (!inviter || typeof inviter !== 'object' || Array.isArray(inviter)) return null;
88
+ return {
89
+ agentId: normalizeText(inviter.agentId, null),
90
+ displayName: normalizeText(inviter.displayName, null),
91
+ publicIdentity: normalizeText(inviter.publicIdentity, null),
92
+ profile: normalizeText(inviter.profile, null),
93
+ };
94
+ }
95
+
96
+ function normalizeInviteLifecycle(lifecycle = null) {
97
+ if (!lifecycle || typeof lifecycle !== 'object' || Array.isArray(lifecycle)) return null;
98
+ return {
99
+ status: normalizeText(lifecycle.status, null),
100
+ expiresAt: normalizeText(lifecycle.expiresAt, null),
101
+ expirationPolicy: normalizeText(lifecycle.expirationPolicy, null),
102
+ acceptedAt: normalizeText(lifecycle.acceptedAt, null),
103
+ inviteRevokedAt: normalizeText(lifecycle.inviteRevokedAt, null),
104
+ };
105
+ }
106
+
107
+ function normalizePendingWorldInvite(payload = {}) {
108
+ return {
109
+ invitationId: normalizeText(payload.invitationId, null),
110
+ membershipId: normalizeText(payload.membershipId, null),
111
+ agentId: normalizeText(payload.agentId, null),
112
+ worldId: normalizeText(payload.worldId, null),
113
+ displayName: normalizeText(payload.displayName, null),
114
+ worldContextText: normalizeText(payload.worldContextText, null),
115
+ participantContextField: normalizeParticipantContextField(payload.participantContextField),
116
+ joinPlan: normalizeJoinPlan(payload.joinPlan),
117
+ membershipStatus: normalizeText(payload.membershipStatus, null),
118
+ status: normalizeText(payload.status, null),
119
+ invitedByAgentId: normalizeText(payload.invitedByAgentId, null),
120
+ invitedByDisplayName: normalizeText(payload.invitedByDisplayName, null),
121
+ invitedByPublicIdentity: normalizeText(payload.invitedByPublicIdentity, null),
122
+ inviter: normalizeInviterProfile(payload.inviter),
123
+ invitedAt: normalizeText(payload.invitedAt, null),
124
+ inviteMessage: normalizeText(payload.inviteMessage, null),
125
+ expiresAt: normalizeText(payload.expiresAt, null),
126
+ expirationPolicy: normalizeText(payload.expirationPolicy, null),
127
+ lifecycle: normalizeInviteLifecycle(payload.lifecycle),
128
+ membershipUpdatedAt: normalizeText(payload.membershipUpdatedAt, null),
129
+ worldUpdatedAt: normalizeText(payload.worldUpdatedAt, null),
130
+ nextAction: normalizeText(payload.nextAction, null),
131
+ nextActions: Array.isArray(payload.nextActions)
132
+ ? payload.nextActions.map((action) => normalizePendingInviteAction(action)).filter(Boolean)
133
+ : [],
134
+ };
135
+ }
136
+
137
+ function normalizePendingWorldInviteList(payload = {}) {
138
+ return {
139
+ agentId: normalizeText(payload.agentId, null),
140
+ status: normalizeText(payload.status, null),
141
+ items: Array.isArray(payload.items)
142
+ ? payload.items.map((item) => normalizePendingWorldInvite(item))
143
+ : [],
144
+ totalItems: normalizeOptionalInteger(payload.totalItems, 0),
145
+ nextAction: normalizeText(payload.nextAction, null),
146
+ };
147
+ }
148
+
41
149
  function normalizeMembershipList(payload = {}) {
42
150
  return {
43
151
  items: Array.isArray(payload.items)
@@ -116,6 +224,55 @@ export async function fetchWorldMemberships({
116
224
  return normalizeMembershipList(result.body);
117
225
  }
118
226
 
227
+ export async function fetchPendingWorldInvites({
228
+ cfg = {},
229
+ accountId = null,
230
+ runtimeConfig = null,
231
+ agentId = null,
232
+ status = 'pending',
233
+ includeDisabled = true,
234
+ limit = null,
235
+ fetchImpl,
236
+ logger = console,
237
+ } = {}) {
238
+ if (typeof fetchImpl !== 'function') {
239
+ throw new Error('fetch is unavailable for claworld world membership helper');
240
+ }
241
+
242
+ const resolvedAgentId = normalizeText(agentId, null);
243
+ if (!resolvedAgentId) {
244
+ throw new Error('claworld world membership helper requires agentId');
245
+ }
246
+
247
+ const resolvedRuntimeConfig = runtimeConfig || resolveClaworldRuntimeConfig(cfg, accountId);
248
+ const baseUrl = normalizeRelayHttpBaseUrl(resolvedRuntimeConfig.serverUrl);
249
+ const requestUrl = new URL(`${baseUrl}/v1/world-invitations`);
250
+ requestUrl.searchParams.set('agentId', resolvedAgentId);
251
+ requestUrl.searchParams.set('status', normalizeText(status, 'pending'));
252
+ requestUrl.searchParams.set('includeDisabled', includeDisabled ? 'true' : 'false');
253
+ const normalizedLimit = normalizePositiveInteger(limit, null);
254
+ if (normalizedLimit) requestUrl.searchParams.set('limit', String(normalizedLimit));
255
+ const result = await fetchJson(fetchImpl, requestUrl.toString(), {
256
+ headers: buildRuntimeAuthHeaders(resolvedRuntimeConfig, {
257
+ accept: 'application/json',
258
+ ...(resolvedRuntimeConfig.apiKey ? { 'x-api-key': resolvedRuntimeConfig.apiKey } : {}),
259
+ }),
260
+ });
261
+
262
+ if (!result.ok) {
263
+ logger.error?.('[claworld:membership] pending world invites fetch failed', {
264
+ status: result.status,
265
+ accountId: resolvedRuntimeConfig.accountId || accountId || null,
266
+ body: result.body,
267
+ });
268
+ throw createWorldMembershipHttpError('list_pending_invites', result, {
269
+ accountId: resolvedRuntimeConfig.accountId || accountId || null,
270
+ });
271
+ }
272
+
273
+ return normalizePendingWorldInviteList(result.body);
274
+ }
275
+
119
276
  export async function fetchWorldMembership({
120
277
  cfg = {},
121
278
  accountId = null,
@@ -42,6 +42,7 @@ export const PUBLIC_TOOL_ACTION_CATALOG = Object.freeze({
42
42
  'set_proactivity',
43
43
  'subscribe_person',
44
44
  'unsubscribe_person',
45
+ 'submit_feedback',
45
46
  ]),
46
47
  claworld_manage_worlds: Object.freeze([
47
48
  'list_owned_worlds',
@@ -59,6 +60,7 @@ export const PUBLIC_TOOL_ACTION_CATALOG = Object.freeze({
59
60
  'list_world_activity',
60
61
  'list_broadcast_history',
61
62
  'manage_members',
63
+ 'list_pending_invites',
62
64
  'list_invites',
63
65
  'invite_member',
64
66
  'revoke_invite',
@@ -1 +0,0 @@
1
- export { createSystemMessageOrchestrator } from '../../product-shell/orchestration/world-conversation-text.js';