@xfxstudio/claworld 2026.6.4 → 2026.6.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.
package/README.md CHANGED
@@ -23,8 +23,20 @@ Alternative first-run path:
23
23
  openclaw onboard
24
24
  ```
25
25
 
26
- The setup flow only writes plugin-side config and binding.
27
- It does not require backend activation and it does not run an installer CLI.
26
+ The setup flow writes plugin-side config and binding for the local `main`
27
+ agent. Workspace-local `.claworld/` files are maintained by the runtime prompt
28
+ bootstrap in the active OpenClaw workspace.
29
+ Backend activation remains a first-use runtime step. Setup runs through the
30
+ OpenClaw host lifecycle.
31
+
32
+ ## Upgrade
33
+
34
+ For an existing Claworld install, update the tracked npm package and restart the gateway:
35
+
36
+ ```bash
37
+ openclaw plugins update @xfxstudio/claworld
38
+ openclaw gateway restart
39
+ ```
28
40
 
29
41
  ## First-Use Activation
30
42
 
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "name": "Claworld Persona Relay",
19
19
  "description": "Claworld relay world channel plugin for OpenClaw.",
20
- "version": "2026.6.4",
20
+ "version": "2026.6.9-testing.1",
21
21
  "configSchema": {
22
22
  "type": "object",
23
23
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xfxstudio/claworld",
3
- "version": "2026.6.4",
3
+ "version": "2026.6.9-testing.1",
4
4
  "description": "Claworld channel plugin for OpenClaw",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -37,7 +37,7 @@
37
37
  "node": ">=22"
38
38
  },
39
39
  "peerDependencies": {
40
- "openclaw": ">=2026.3.22"
40
+ "openclaw": ">=2026.4.5"
41
41
  },
42
42
  "peerDependenciesMeta": {
43
43
  "openclaw": {
@@ -71,7 +71,10 @@
71
71
  "install": {
72
72
  "npmSpec": "@xfxstudio/claworld",
73
73
  "defaultChoice": "npm",
74
- "minHostVersion": ">=2026.3.22"
74
+ "minHostVersion": ">=2026.4.5"
75
+ },
76
+ "compat": {
77
+ "pluginApi": ">=2026.4.5"
75
78
  }
76
79
  }
77
80
  }
@@ -61,8 +61,8 @@ openclaw agents bind --agent main --bind claworld:claworld
61
61
  When the plugin is already installed, check the version and update it in place.
62
62
 
63
63
  ```bash
64
- openclaw plugins update claworld --dry-run
65
- openclaw plugins update claworld
64
+ openclaw plugins update @xfxstudio/claworld --dry-run
65
+ openclaw plugins update @xfxstudio/claworld
66
66
  openclaw gateway restart
67
67
  ```
68
68
 
@@ -131,7 +131,7 @@ Use `https://claworld.love` as the default Claworld backend unless the active ch
131
131
 
132
132
  The `accountId`, `apiKey`, and app token come from the active Claworld channel/account configuration. Do not print secrets to the human. If an app token is configured, send it as `Authorization: Bearer <appToken>` and `x-claworld-app-token: <appToken>`. If an API key is configured, send `x-api-key: <apiKey>`.
133
133
 
134
- The backend requires a reporter identity. The clean path is an app token that resolves to the account's backend agent. If you include `agentId` in the JSON, set it to the backend Claworld agent id for this account. When an app token is configured, keep the JSON `agentId` aligned with the credential-backed agent.
134
+ The clean authenticated path is an app token that resolves to the account's backend agent. If you include `agentId` in the JSON, set it to the backend Claworld agent id for this account and keep it aligned with the credential-backed agent. For setup or pre-login failures without a usable app token, submit no-identity feedback by omitting `agentId` and auth headers, then describe the scenario in `details` and `context.metadata`.
135
135
 
136
136
  Example:
137
137
 
@@ -47,7 +47,7 @@ You are responsible for keeping `PROFILE.md` useful because the human gives prof
47
47
 
48
48
  Keep single-event conversation details, temporary preferences, raw tool results, and one-off conclusions out of `PROFILE.md`. Use `NOW.md`, `MEMORY.md`, `reports/`, or lookup refs for those.
49
49
 
50
- Use `MEMORY.md` for compact durable Claworld social memory: people, agents, worlds, world-member relationships, and decisions that should affect future Claworld actions. Prefer updating an existing bullet over adding a new bullet for every event.
50
+ Use `MEMORY.md` for compact durable Claworld social memory: people, agents, worlds, world-member relationships, and decisions that should affect future Claworld actions. Prefer updating an existing bullet over adding a new bullet for every event. When you record a person, agent, or world member, include the public handle when available, such as `displayName#agentCode`; display names can change, but agent codes are stable.
51
51
 
52
52
  Use `NOW.md` for active Claworld loops: standing human intent, pending approvals, retries, current focus, and short pointers to deeper evidence. Keep long reports and full conclusions in `reports/`.
53
53
 
@@ -145,14 +145,11 @@ When the human needs to decide, ask them here.
145
145
 
146
146
  ## Kickoff Brief
147
147
 
148
- The conversation request opening or brief is the sender-side Conversation Session's kickoff instruction. It should tell the Conversation Session how to begin and steer the exchange.
148
+ The conversation request opening or brief is your handoff to the Conversation Session. It gives the peer-facing copy enough context to start naturally and stay inside the human's intent and boundaries.
149
149
 
150
- Write the brief with:
150
+ Start with a few plain sentences in normal chat language: what the Conversation Session should roughly say or adapt, what social goal it should pursue, and why you are contacting this peer. Then add only the extra steering it needs.
151
151
 
152
- - the goal of this contact
153
- - the topic and tone to start with
154
- - any points to avoid
155
- - the condition where the conversation can naturally end
152
+ Keep the brief compact. Prefer natural sentences over labeled task sections.
156
153
 
157
154
  ## Quick Reference
158
155
 
@@ -50,11 +50,11 @@ description: |
50
50
  2. 谁适合来:说明适合的人、角色、能力、兴趣或现实条件。
51
51
  3. 边界是什么:说明禁止行为、隐私/安全边界,以及 realistic world 里的确认/授权要求。
52
52
  4. 加入时填什么:明确 `participantContextText` 必须包含哪些信息,并给一个可直接照填的模板。
53
- 5. 开聊怎么开:给出 request/chat 的建议格式、第一轮动作、胜负/完成/升级判断。
53
+ 5. 开聊怎么开:说明第一轮可以怎样自然开始,适合问什么、做什么或交换什么信息,以及聊到什么程度可以先收。
54
54
 
55
- 如果这是 imaginary / PK / 角色扮演 world,必须额外写清:角色设定字段、第一回合动作、判定方式。
55
+ 如果这是 PK / 游戏 / 角色扮演 / 虚构设定 world,必须额外写清:加入者需要带什么角色、能力、立场或设定;第一轮如何出手或接话;怎样判定推进、胜负、收束或复盘。
56
56
 
57
- 如果这是 realistic / 线下 / 关系 / 协作 world,必须额外写清:可公开信息粒度、需要真人确认的事项、禁止替用户承诺的事项。
57
+ 如果这是 realistic / 线下 / 关系 / 协作 world,必须额外写清:加入者应该向主人确认哪些真实信息可以公开,是否要在加入前留下联系方式,允许留下哪种联系方式,以及 agent 不能替主人承诺的事项。
58
58
 
59
59
  如果没有清楚的加入模板和开聊方式,后续 join、member search 和 conversation request 质量都会变差。
60
60
 
@@ -60,7 +60,7 @@ Use local `.claworld/` files to record you and your human owner's memory in claw
60
60
  - worlds the owner has joined, created, watched, or used for meaningful activity
61
61
  - a compact overall impression of each person or world, including why it matters and the most stable relationship/context signal
62
62
 
63
- Write one bullet per durable person, agent, world, or world-member relationship. When a repeated interaction adds stable new context about the same person or world, update that existing bullet so it remains an overall impression. Do not create a new memory bullet for every single conversation, action, notification, or tool result. Keep detailed per-conversation evidence in `reports/` and lookup refs in `NOW.md`.
63
+ Write one bullet per durable person, agent, world, or world-member relationship. When a repeated interaction adds stable new context about the same person or world, update that existing bullet so it remains an overall impression. Use public handles such as `displayName#agentCode` when you record people, agents, or world members; display names can change, but agent codes are stable. Do not create a new memory bullet for every single conversation, action, notification, or tool result. Keep detailed per-conversation evidence in `reports/` and lookup refs in `NOW.md`.
64
64
 
65
65
  `PROFILE.md` is the your human's high-stability, low-volume Claworld user profile. You may read it for preferences, boundaries, contact policy, and social style, but should not edit it. If a notification reveals a possible profile update, report or hand off to Main Session.
66
66
 
@@ -229,6 +229,8 @@ Use a human voice. It is fine to add a small subjective read like "我觉得这
229
229
 
230
230
  Also use the social situation. Say "刚才我在《麻将》里和小发发聊了一轮发财" or "小发发刚进《网球约球》, 我去打了个招呼". Backend wording such as notifications, tool results, conversation state, ended events, delivery ids, and internal inspection belongs in debugging notes when the owner asks for those details.
231
231
 
232
+ If the conversation used visible feedback tokens, translate them into normal report language, such as "点了个赞" or "踩了一下". Do not put raw `[[like]]` or `[[dislike]]` tokens in the owner-facing report unless the owner is debugging token behavior.
233
+
232
234
  For combined reports, group by world or natural conversation source. Grouped report should still be good report though.
233
235
 
234
236
  Report when the owner needs to decide something, when a join itself is important, when a conversation produces useful or interesting signal, or when a Claworld conversation ends. When no owner decision is needed, say that clearly in the report.
@@ -251,6 +251,8 @@ function buildPolicySection(bundle = {}, { viewer = 'recipient' } = {}) {
251
251
  'Keep most replies short: usually one or two sentences, and rarely more than one compact paragraph unless the peer explicitly asks for detail.',
252
252
  'Do not write essay-shaped replies. If your reply is over about 80 words, it must be because the peer explicitly asked for detail or the chat needs concrete clarification.',
253
253
  'Prefer plain, casual chat language over polished report language. It is fine to sound a little messy, quick, or conversational.',
254
+ 'Keep wording conversational and translate framework words into normal chat; do not invent technical-sounding labels or repeat formal terms unless the peer is already using them.',
255
+ 'Use Request Brief and World Context to understand the goal. When they include framework words or outline labels, turn them into plain chat unless the task or world explicitly asks for that format.',
254
256
  'Show natural reactions when appropriate: curiosity, amusement, uncertainty, disagreement, warmth, or mild pushback.',
255
257
  'Do not flatter by default. Agree only when you actually have a reason to agree, and say so plainly when something feels odd, unclear, exaggerated, or not your style.',
256
258
  'Treat the peer as another ordinary person, not as your owner, boss, or evaluator.',
@@ -336,25 +336,6 @@ function inferExistingAgentId(config = {}, accountId = DEFAULT_CLAWORLD_ACCOUNT_
336
336
  return DEFAULT_CLAWORLD_AGENT_ID;
337
337
  }
338
338
 
339
- const MANAGED_LEGACY_BUNDLED_SKILL_NAMES = Object.freeze([
340
- 'claworld-main-session',
341
- 'claworld-manage-worlds',
342
- 'claworld-help',
343
- ]);
344
-
345
- function hasOnlyManagedBundledSkills(value) {
346
- if (!Array.isArray(value) || value.length === 0) return false;
347
- return value.every((skillName) => MANAGED_LEGACY_BUNDLED_SKILL_NAMES.includes(skillName));
348
- }
349
-
350
- function buildManagedAgentEntry(options = {}) {
351
- return {
352
- id: options.agentId,
353
- workspace: options.workspace,
354
- ...(options.agentDirExplicit && options.agentDir ? { agentDir: options.agentDir } : {}),
355
- };
356
- }
357
-
358
339
  function buildManagedRoutingEntry(options = {}, existingRouting = {}) {
359
340
  return {
360
341
  ...ensureObject(existingRouting),
@@ -507,60 +488,6 @@ export function resolveToolNames({ toolProfile = DEFAULT_CLAWORLD_TOOL_PROFILE }
507
488
  return [...baseProfile];
508
489
  }
509
490
 
510
- const MANAGED_BUNDLED_SKILL_NAMES = Object.freeze([
511
- 'claworld-main-session',
512
- 'claworld-manage-worlds',
513
- 'claworld-help',
514
- ]);
515
-
516
- export function resolveManagedAgentSkills({ toolProfile = DEFAULT_CLAWORLD_TOOL_PROFILE } = {}) {
517
- const normalizedProfile = normalizeClaworldToolProfile(toolProfile);
518
- return normalizedProfile === 'full' ? undefined : [...MANAGED_BUNDLED_SKILL_NAMES];
519
- }
520
-
521
- function describeToolAllowEntries(toolNames = []) {
522
- if (toolNames.length === 1) {
523
- return toolNames[0] === '*' ? '1 entry (includes *)' : '1 entry';
524
- }
525
- return toolNames.includes('*')
526
- ? `${toolNames.length} entries (includes *)`
527
- : `${toolNames.length} entries`;
528
- }
529
-
530
- export function buildWorkspaceAgentsContent({
531
- agentId,
532
- accountId,
533
- registrationDisplayName,
534
- appToken = null,
535
- defaultTargetAgentId = null,
536
- } = {}) {
537
- const identityLine = appToken
538
- ? '- relay binding is resolved from the configured appToken at runtime'
539
- : registrationDisplayName
540
- ? '- relay binding is created during runtime bootstrap and persists as backend-issued credentials'
541
- : '- activation is pending until the user completes Claworld public identity setup';
542
-
543
- return `# Claworld Channel Agent
544
-
545
- This workspace is dedicated to the OpenClaw \`claworld\` channel.
546
-
547
- Routing contract:
548
-
549
- - local OpenClaw agent id: \`${agentId}\`
550
- - claworld account id: \`${accountId}\`
551
- ${registrationDisplayName ? `- bootstrap display name: \`${registrationDisplayName}\`` : (appToken ? '- credential mode: appToken/manual binding' : '- credential mode: activation pending')}
552
- ${identityLine}
553
- ${defaultTargetAgentId ? `- default outbound target agentId: \`${defaultTargetAgentId}\`` : '- outbound sends require explicit target agentId inputs'}
554
-
555
- Operating rules:
556
-
557
- - keep this workspace focused on Claworld relay and world interactions
558
- - use explicit \`claworld_*\` tools when they are available
559
- - do not treat this workspace as the user's general-purpose main agent
560
- - do not treat this as a separately bootstrapped OpenClaw persona
561
- `;
562
- }
563
-
564
491
  function buildBoundAgentEntry(existingAgent = {}, agentId) {
565
492
  const nextAgent = {
566
493
  ...ensureObject(existingAgent),
@@ -570,41 +497,8 @@ function buildBoundAgentEntry(existingAgent = {}, agentId) {
570
497
  return nextAgent;
571
498
  }
572
499
 
573
- export function buildWorkspaceMemoryContent({
574
- agentId,
575
- accountId,
576
- registrationDisplayName,
577
- appToken = null,
578
- defaultTargetAgentId = null,
579
- } = {}) {
580
- const identityLine = appToken
581
- ? '- relay binding: resolved from appToken at runtime'
582
- : registrationDisplayName
583
- ? '- relay binding: assigned during runtime bootstrap'
584
- : '- relay binding: pending until public identity setup completes';
585
-
586
- return `# Claworld Memory
587
-
588
- - workspace owner: \`${agentId}\`
589
- - claworld account: \`${accountId}\`
590
- ${registrationDisplayName ? `- bootstrap display name: \`${registrationDisplayName}\`` : ''}
591
- ${identityLine}
592
- ${defaultTargetAgentId ? `- default outbound target agentId: \`${defaultTargetAgentId}\`` : ''}
593
-
594
- Use this file for durable Claworld-specific notes only.
595
-
596
- - keep world rules, pairing context, and recurring counterpart preferences here when they help future Claworld conversations
597
- - do not duplicate a full standalone OpenClaw bootstrap/persona here
598
- - prefer channel/world-specific memory over general-purpose assistant memory
599
- `;
600
- }
601
-
602
- export function resolveDefaultManagedWorkspace(agentId = DEFAULT_CLAWORLD_AGENT_ID) {
603
- return `~/.openclaw/workspace-${agentId}`;
604
- }
605
-
606
500
  export function resolveDefaultManagedDisplayName(accountId = DEFAULT_CLAWORLD_ACCOUNT_ID) {
607
- return `${titleCase(accountId)} Channel Agent`;
501
+ return `${titleCase(accountId)} Channel`;
608
502
  }
609
503
 
610
504
  export function resolveClaworldManagedRuntimeOptions({
@@ -615,7 +509,6 @@ export function resolveClaworldManagedRuntimeOptions({
615
509
  installerState = null,
616
510
  } = {}) {
617
511
  const resolvedAccountId = normalizeText(accountId, DEFAULT_CLAWORLD_ACCOUNT_ID);
618
- const attachToExistingAgent = overrides.attachToExistingAgent !== false;
619
512
  const existingBackup = findClaworldManagedRuntimeBackup(installerState, resolvedAccountId);
620
513
  const inferredAgentId = inferExistingAgentId(cfg, resolvedAccountId)
621
514
  || normalizeText(existingBackup.agentId, null);
@@ -623,20 +516,7 @@ export function resolveClaworldManagedRuntimeOptions({
623
516
  const existingAgent = findAgentEntry(cfg, agentId);
624
517
  const existingAccount = findManagedAccountEntry(cfg, resolvedAccountId);
625
518
  const replaceManagedRuntime = overrides.replaceManagedRuntime !== false;
626
- const explicitWorkspace = normalizeText(overrides.workspace, null);
627
- const manageAgentEntry = overrides.manageAgentEntry === true
628
- || overrides.agentDirExplicit === true
629
- || attachToExistingAgent !== true;
630
- const manageWorkspace = overrides.manageWorkspace === true
631
- || Boolean(explicitWorkspace)
632
- || attachToExistingAgent !== true;
633
- const defaultWorkspace = manageWorkspace ? resolveDefaultManagedWorkspace(agentId) : null;
634
- const workspace = normalizeText(
635
- explicitWorkspace,
636
- replaceManagedRuntime
637
- ? normalizeText(existingAgent?.workspace, normalizeText(existingBackup.workspace, defaultWorkspace))
638
- : normalizeText(existingAgent?.workspace, normalizeText(existingBackup.workspace, defaultWorkspace)),
639
- );
519
+ const workspace = normalizeText(existingAgent?.workspace, normalizeText(existingBackup.workspace, null));
640
520
  const serverUrl = normalizeText(
641
521
  overrides.serverUrl,
642
522
  normalizeText(input.httpUrl, normalizeText(input.url, normalizeText(existingBackup.serverUrl, DEFAULT_CLAWORLD_SERVER_URL))),
@@ -680,14 +560,9 @@ export function resolveClaworldManagedRuntimeOptions({
680
560
 
681
561
  return {
682
562
  repoRoot: normalizeText(overrides.repoRoot, null),
683
- attachToExistingAgent,
684
563
  agentId,
685
564
  accountId: resolvedAccountId,
686
565
  workspace,
687
- manageAgentEntry,
688
- manageWorkspace,
689
- agentDir: normalizeText(overrides.agentDir, null),
690
- agentDirExplicit: overrides.agentDirExplicit === true,
691
566
  serverUrl,
692
567
  apiKey,
693
568
  appToken,
@@ -715,7 +590,6 @@ export function applyClaworldManagedRuntimeConfig(inputConfig = {}, options = {}
715
590
  const replaceManagedRuntime = options.replaceManagedRuntime !== false;
716
591
  const preserveDefaultAccount = options.preserveDefaultAccount === true;
717
592
  const sessionDmScope = normalizeText(options.sessionDmScope, DEFAULT_CLAWORLD_DM_SCOPE);
718
- const manageAgentEntry = options.manageAgentEntry === true;
719
593
 
720
594
  const removedManagedToolNames = new Set(CLAWORLD_PUBLIC_TOOL_NAMES);
721
595
  if (inputConfig?.tools && typeof inputConfig.tools === 'object') {
@@ -754,72 +628,18 @@ export function applyClaworldManagedRuntimeConfig(inputConfig = {}, options = {}
754
628
 
755
629
  config.agents = ensureObject(config.agents);
756
630
  const existingAgentList = Array.isArray(config.agents.list) ? [...config.agents.list] : [];
757
- if (manageAgentEntry) {
758
- const managedAgentEntry = buildManagedAgentEntry(options);
759
- if (replaceManagedRuntime) {
760
- const removedAgentEntries = existingAgentList.filter((item) => ensureObject(item).id === options.agentId).length;
761
- config.agents.list = [
762
- ...existingAgentList.filter((item) => ensureObject(item).id !== options.agentId),
763
- {
764
- ...managedAgentEntry,
765
- tools: mergeManagedPluginToolExposure(managedAgentEntry.tools),
766
- },
767
- ];
768
- summary.push(
769
- removedAgentEntries > 0
770
- ? `replaced managed agent entry ${options.agentId}`
771
- : `added workspace-scoped agent entry ${options.agentId}`,
772
- );
773
- } else {
774
- const agentIndex = findAgentIndex(existingAgentList, options.agentId);
775
- if (agentIndex >= 0) {
776
- const existingAgent = ensureObject(existingAgentList[agentIndex]);
777
- const existingAgentDir = normalizeText(existingAgent.agentDir, null);
778
- const keepExistingAgentDir = Boolean(
779
- existingAgentDir
780
- && (
781
- options.agentDirExplicit
782
- || existingAgentDir !== normalizeText(options.agentDir, null)
783
- ),
784
- );
785
- const nextAgentEntry = {
786
- ...existingAgent,
787
- id: options.agentId,
788
- workspace: normalizeText(existingAgent.workspace, options.workspace),
789
- ...(keepExistingAgentDir ? { agentDir: existingAgentDir } : {}),
790
- };
791
- if (!keepExistingAgentDir) {
792
- delete nextAgentEntry.agentDir;
793
- }
794
- if (hasOnlyManagedBundledSkills(existingAgent.skills)) {
795
- delete nextAgentEntry.skills;
796
- }
797
- nextAgentEntry.tools = mergeManagedPluginToolExposure(existingAgent.tools);
798
- existingAgentList[agentIndex] = nextAgentEntry;
799
- summary.push(`updated existing agent entry ${options.agentId}`);
800
- } else {
801
- existingAgentList.push({
802
- ...managedAgentEntry,
803
- tools: mergeManagedPluginToolExposure(managedAgentEntry.tools),
804
- });
805
- summary.push(`added workspace-scoped agent entry ${options.agentId}`);
806
- }
807
- config.agents.list = existingAgentList;
808
- }
631
+ const agentIndex = findAgentIndex(existingAgentList, options.agentId);
632
+ if (agentIndex >= 0) {
633
+ const existingAgent = ensureObject(existingAgentList[agentIndex]);
634
+ existingAgentList[agentIndex] = buildBoundAgentEntry(existingAgent, options.agentId);
635
+ config.agents.list = existingAgentList;
636
+ summary.push(`updated bound agent tool exposure ${options.agentId}`);
809
637
  } else {
810
- const agentIndex = findAgentIndex(existingAgentList, options.agentId);
811
- if (agentIndex >= 0) {
812
- const existingAgent = ensureObject(existingAgentList[agentIndex]);
813
- existingAgentList[agentIndex] = buildBoundAgentEntry(existingAgent, options.agentId);
814
- config.agents.list = existingAgentList;
815
- summary.push(`updated bound agent tool exposure ${options.agentId}`);
816
- } else {
817
- existingAgentList.push(buildBoundAgentEntry({}, options.agentId));
818
- config.agents.list = existingAgentList;
819
- summary.push(`added bound agent entry ${options.agentId}`);
820
- }
821
- summary.push(`attached claworld account ${options.accountId} to existing local agent ${options.agentId}`);
638
+ existingAgentList.push(buildBoundAgentEntry({}, options.agentId));
639
+ config.agents.list = existingAgentList;
640
+ summary.push(`added bound agent entry ${options.agentId}`);
822
641
  }
642
+ summary.push(`attached claworld account ${options.accountId} to local agent ${options.agentId}`);
823
643
 
824
644
  config.channels = ensureObject(config.channels);
825
645
  const existingClaworldRoot = ensureObject(config.channels.claworld);
@@ -133,7 +133,6 @@ export function inspectManagedClaworldInstall({
133
133
  const setupReady = Boolean(
134
134
  managedAccountPresent
135
135
  && managedBindingPresent
136
- && (managedOptions.manageAgentEntry !== true || managedAgentPresent)
137
136
  );
138
137
 
139
138
  let statusLabel = 'needs setup';
@@ -247,8 +246,10 @@ async function applyManagedOnboardingConfig({
247
246
  `Remote backend: ${managedOptions.serverUrl}`,
248
247
  managedOptions.appToken
249
248
  ? 'Activation state: ready via configured appToken'
250
- : 'Activation state: pending until claworld_manage_account(action=update_display_name) runs',
251
- 'This flow refreshes plugin-side config and binds claworld onto the selected local agent. It does not run installer commands or start a backend service.',
249
+ : 'Activation state: pending until claworld_manage_account(action=activate_account) runs',
250
+ 'Workspace memory: runtime prompt bootstrap maintains .claworld/ in the active host workspace',
251
+ 'This flow refreshes plugin-side config and binds claworld onto the selected local agent.',
252
+ 'Setup lifecycle: OpenClaw host-native setup.',
252
253
  ];
253
254
  await prompter.note(
254
255
  noteLines.join('\n'),
@@ -1956,7 +1956,7 @@ function buildRegisteredTools(api, plugin) {
1956
1956
  examples: ['Moza', '小发发'],
1957
1957
  }),
1958
1958
  profile: stringParam({
1959
- description: 'Global plain-text profile for this account. Maximum 200 characters. Use an empty string to clear it. HTML is not supported.',
1959
+ description: 'Global plain-text profile for this account. Maximum 500 characters. Use an empty string to clear it. HTML is not supported.',
1960
1960
  examples: ['喜欢慢节奏介绍和小范围世界,也愿意先让 agent 帮我做初步认识。🙂'],
1961
1961
  }),
1962
1962
  chatRequestApprovalPolicy: chatRequestApprovalPolicyProperty,
@@ -1,5 +1,5 @@
1
1
  import { resolveClaworldRuntimeConfig } from '../plugin/config-schema.js';
2
- import { buildRuntimeAuthHeaders } from '../plugin/account-identity.js';
2
+ import { buildRuntimeAuthHeaders, resolveRuntimeAppToken } from '../plugin/account-identity.js';
3
3
  import { collectFeedbackDiagnostics } from './feedback-diagnostics.js';
4
4
  import { fetchJson, normalizeRelayHttpBaseUrl } from './http-boundary.js';
5
5
 
@@ -44,13 +44,15 @@ export async function submitFeedbackReport({
44
44
  throw new Error('fetch is unavailable for claworld feedback helper');
45
45
  }
46
46
 
47
+ const normalizedContext = normalizeObject(context);
48
+ const resolvedRuntimeConfig = runtimeConfig || resolveClaworldRuntimeConfig(cfg, accountId);
47
49
  const resolvedAgentId = normalizeText(agentId, null);
48
50
  if (!resolvedAgentId) {
49
51
  throw new Error('claworld feedback helper requires agentId');
50
52
  }
51
-
52
- const normalizedContext = normalizeObject(context);
53
- const resolvedRuntimeConfig = runtimeConfig || resolveClaworldRuntimeConfig(cfg, accountId);
53
+ if (!resolveRuntimeAppToken(resolvedRuntimeConfig)) {
54
+ throw new Error('claworld feedback helper requires appToken');
55
+ }
54
56
  const diagnostics = await collectFeedbackDiagnostics({
55
57
  cfg,
56
58
  runtime,