oomi-ai 0.2.50 → 0.3.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.
Files changed (88) hide show
  1. package/README.md +224 -507
  2. package/agent_instructions.md +264 -253
  3. package/bin/oomi-ai.js +4036 -5791
  4. package/bin/sessionBridgeState.js +78 -78
  5. package/lib/openclawPaths.js +70 -71
  6. package/lib/openclawProfile.js +216 -216
  7. package/lib/personaApiClient.js +142 -303
  8. package/lib/spokenMetadata.js +137 -137
  9. package/openclaw.extension.js +341 -341
  10. package/openclaw.plugin.json +17 -17
  11. package/package.json +59 -59
  12. package/persona-app/README.md +33 -0
  13. package/persona-app/registry/v1.json +85 -0
  14. package/persona-app/schema/persona-app.v1.schema.json +90 -0
  15. package/skills/oomi/SKILL.md +182 -182
  16. package/skills/oomi/agent_instructions.md +117 -80
  17. package/lib/channelPluginClient.js +0 -119
  18. package/lib/openclawDevGateway.js +0 -384
  19. package/lib/personaJobExecutor.js +0 -139
  20. package/lib/personaJobPoller.js +0 -112
  21. package/lib/personaPortAllocator.js +0 -36
  22. package/lib/personaRuntimeManager.js +0 -496
  23. package/lib/personaRuntimeProcess.js +0 -924
  24. package/lib/personaRuntimeRegistry.js +0 -67
  25. package/lib/personaRuntimeSupervisor.js +0 -330
  26. package/lib/scaffold.js +0 -108
  27. package/lib/template.js +0 -45
  28. package/skills/oomi/config.json +0 -3
  29. package/skills/oomi/scripts/get_avatar_capabilities.py +0 -40
  30. package/skills/oomi/scripts/get_data.py +0 -49
  31. package/skills/oomi/scripts/install_agent_instructions.py +0 -78
  32. package/skills/oomi/scripts/send_goal.py +0 -53
  33. package/skills/oomi/scripts/sync.py +0 -46
  34. package/skills/oomi/setup.py +0 -41
  35. package/templates/persona-app/.env.example +0 -8
  36. package/templates/persona-app/README.md +0 -58
  37. package/templates/persona-app/eslint.config.js +0 -28
  38. package/templates/persona-app/index.html +0 -18
  39. package/templates/persona-app/oomi.runtime.json +0 -13
  40. package/templates/persona-app/package.json +0 -44
  41. package/templates/persona-app/persona/brief.md +0 -14
  42. package/templates/persona-app/persona.json +0 -14
  43. package/templates/persona-app/public/manifest.webmanifest +0 -8
  44. package/templates/persona-app/public/oomi.health.json +0 -6
  45. package/templates/persona-app/src/App.css +0 -379
  46. package/templates/persona-app/src/App.tsx +0 -17
  47. package/templates/persona-app/src/index.css +0 -53
  48. package/templates/persona-app/src/main.tsx +0 -23
  49. package/templates/persona-app/src/pages/HomePage.tsx +0 -127
  50. package/templates/persona-app/src/pages/ScenePage.tsx +0 -158
  51. package/templates/persona-app/src/persona/config.ts +0 -6
  52. package/templates/persona-app/src/persona/notes.ts +0 -10
  53. package/templates/persona-app/src/spatial.ts +0 -82
  54. package/templates/persona-app/src/vite-env.d.ts +0 -3
  55. package/templates/persona-app/template.json +0 -13
  56. package/templates/persona-app/tsconfig.app.json +0 -23
  57. package/templates/persona-app/tsconfig.json +0 -7
  58. package/templates/persona-app/tsconfig.node.json +0 -21
  59. package/templates/persona-app/vendor/webspatial/FORK.md +0 -6
  60. package/templates/persona-app/vendor/webspatial/core-sdk/LICENSE +0 -21
  61. package/templates/persona-app/vendor/webspatial/core-sdk/dist/iife/index.d.ts +0 -906
  62. package/templates/persona-app/vendor/webspatial/core-sdk/dist/iife/index.global.js +0 -75
  63. package/templates/persona-app/vendor/webspatial/core-sdk/dist/iife/index.global.js.map +0 -1
  64. package/templates/persona-app/vendor/webspatial/core-sdk/dist/index.d.ts +0 -906
  65. package/templates/persona-app/vendor/webspatial/core-sdk/dist/index.js +0 -3131
  66. package/templates/persona-app/vendor/webspatial/core-sdk/dist/index.js.map +0 -1
  67. package/templates/persona-app/vendor/webspatial/core-sdk/package.json +0 -45
  68. package/templates/persona-app/vendor/webspatial/react-sdk/LICENSE +0 -21
  69. package/templates/persona-app/vendor/webspatial/react-sdk/dist/default/index.d.ts +0 -365
  70. package/templates/persona-app/vendor/webspatial/react-sdk/dist/default/index.js +0 -4167
  71. package/templates/persona-app/vendor/webspatial/react-sdk/dist/default/index.js.map +0 -1
  72. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.d.ts +0 -82
  73. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.js +0 -66
  74. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.js.map +0 -1
  75. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.web.d.ts +0 -2
  76. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.web.js +0 -18
  77. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.web.js.map +0 -1
  78. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.d.ts +0 -5
  79. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.js +0 -66
  80. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.js.map +0 -1
  81. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.web.d.ts +0 -1
  82. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.web.js +0 -18
  83. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.web.js.map +0 -1
  84. package/templates/persona-app/vendor/webspatial/react-sdk/dist/web/index.d.ts +0 -365
  85. package/templates/persona-app/vendor/webspatial/react-sdk/dist/web/index.js +0 -4207
  86. package/templates/persona-app/vendor/webspatial/react-sdk/dist/web/index.js.map +0 -1
  87. package/templates/persona-app/vendor/webspatial/react-sdk/package.json +0 -94
  88. package/templates/persona-app/vite.config.ts +0 -31
@@ -2,270 +2,281 @@
2
2
 
3
3
  Use these instructions when you need to connect, repair, or verify an OpenClaw machine that should talk to Oomi.
4
4
 
5
- This is the packaged agent-facing reference for:
6
- - managed OpenClaw connect and repair flows
7
- - device-backed chat and voice bridge recovery
8
- - XR-first persona generation and persona runtime repair
9
-
10
- ## Primary Goal
11
-
12
- Get OpenClaw into a state where:
13
- - Oomi managed text chat works
14
- - Oomi device-backed voice can start cleanly
15
- - the bridge is supervised or restartable
16
- - the user never has to paste raw pair identifiers or gateway secrets manually when managed connect is available
17
-
18
- ## Standard Connect Flow
19
-
20
- If the user asks to connect OpenClaw to Oomi chat or voice:
21
-
22
- 1. Refresh bootstrap first:
23
- - `curl -fsSL https://www.oomi.ai/install.sh | bash`
24
- 2. Ensure `oomi-ai` is installed:
25
- - `pnpm add -g oomi-ai@latest`
26
- - fallback: `npm install -g oomi-ai@latest`
27
- 3. Pair the device without starting a legacy one-off flow:
28
- - `oomi openclaw pair --app-url https://www.oomi.ai --no-start`
29
- 4. Install the OpenClaw plugin:
30
- - `openclaw plugins install oomi-ai@latest`
31
- 5. Print the config block and secrets:
32
- - `oomi openclaw plugin --show-secrets --backend-url https://api.oomi.ai`
33
- 6. Apply the printed `channels.oomi.accounts.default` config.
34
- 7. Restart OpenClaw.
35
- 8. Start or repair the bridge:
36
- - `oomi openclaw bridge ensure --detach`
37
- - if stale: `oomi openclaw bridge restart --detach`
38
- - on macOS, prefer supervision: `oomi openclaw bridge service install`
39
-
40
- If the user provides a specific app URL, use it directly in the pair flow:
41
- - `oomi openclaw pair --app-url <URL> --no-start`
42
-
43
- ## Required User-Facing Result
44
-
45
- When pairing completes successfully, return this exact format:
46
- - `Oomi Connect Ready`
47
- - `Auth Link: ...`
48
-
49
- Do not add extra narrative before or after those lines.
50
- Do not ask the user to enter raw pair codes, gateway passwords, or nonce values manually.
51
-
52
- ## Runtime Checks
53
-
54
- Use these commands to inspect the installed machine:
55
-
56
- ```bash
57
- oomi openclaw bridge ps
58
- oomi openclaw bridge service status
59
- oomi openclaw status
60
- tail -f ~/.openclaw/logs/oomi-bridge-live.log
61
- tail -f ~/.openclaw/logs/gateway.log
62
- tail -f ~/.openclaw/logs/gateway.err.log
63
- ```
64
-
65
- Useful local files:
66
- - `~/.openclaw/oomi-bridge-status.json`
67
- - `~/.openclaw/logs/oomi-bridge-live.log`
68
- - `~/.openclaw/logs/gateway.log`
69
- - `~/.openclaw/logs/gateway.err.log`
70
- - `~/.openclaw/agents/main/sessions/*.jsonl`
71
-
72
- ## Healthy State
73
-
74
- Treat the machine as healthy when all of the following are true:
75
- - OpenClaw loads the `oomi-ai` plugin without duplicate-id conflicts
76
- - `channels.oomi.accounts.default` is populated with a valid `backendUrl` and `deviceToken`
77
- - the bridge shows `connected` after managed subscription is confirmed
78
- - text chat reaches the Oomi assistant
79
- - voice STT can produce `asr.final`
80
- - assistant replies can come back without the bridge dropping into `stopped`
81
-
82
- Bridge status meanings:
83
- - `starting`: bridge booting or waiting for managed subscription
84
- - `connected`: ready for managed chat and voice traffic
85
- - `reconnecting`: transport dropped and retry is scheduled
86
- - `degraded`: bridge caught a runtime fault but is still alive
87
- - `error`: startup/auth failure blocked useful operation
88
- - `stopped`: not running or intentionally stopped
89
-
90
- ## Troubleshooting
91
-
92
- ### Duplicate plugin id warning
93
-
94
- Symptom:
95
- - OpenClaw reports `duplicate plugin id detected`
96
-
97
- Action:
98
- - ensure only one active `oomi-ai` plugin install is discoverable
99
- - remove stale extension copies before reinstalling
100
-
101
- ### `invalid handshake: first request must be connect`
102
-
103
- Meaning:
104
- - a gateway request was sent before `connect` had been accepted
105
-
106
- Action:
107
- - update `oomi-ai`
108
- - restart the bridge
109
- - confirm only one bridge worker is running
110
-
111
- ### Device is linked but voice start still fails
112
-
113
- Meaning:
114
- - linked ownership is not enough; the device side still needs to be live
115
-
116
- Action:
117
- - confirm the device websocket is actually online
118
- - confirm the bridge is `connected`
119
- - restart the bridge if it is stuck in `reconnecting` or `degraded`
120
-
121
- ### STT works but the assistant does not reply
122
-
123
- Meaning:
124
- - the voice turn likely reached Oomi, but the managed gateway or OpenClaw run failed later
125
-
126
- Action:
127
- - inspect `gateway.log`, `gateway.err.log`, and the session JSONL
128
- - check for `network_error`, auth failures, or repeated bridge restarts
129
-
130
- ### Bridge keeps restarting with `reason: stopped`
131
-
132
- Action:
133
- - confirm the newest `oomi-ai` is installed
134
- - inspect `~/.openclaw/logs/oomi-bridge-live.log` for runtime exceptions
135
- - use supervised mode on macOS: `oomi openclaw bridge service install`
136
- - if the process is alive but faulted, expect `degraded` rather than an immediate hard stop on newer bridge builds
137
-
138
- ## Voice Notes
139
-
140
- Voice depends on the same Oomi plugin and bridge layer as managed chat.
141
- That means:
142
- - if plugin install or bridge health is wrong, voice replies will also fail
143
- - STT can succeed even when assistant reply delivery is broken later in the run
144
- - a `voice_session_*` failure should be investigated, but it should not automatically be treated as proof that all normal Oomi chat is down
145
-
146
- ### Hidden Speech Payload
147
-
148
- For managed voice turns, keep visible assistant chat text natural and user-facing.
149
- Do not put spoken-style tags like `[happy]`, `[sad]`, or `[excited]` into visible chat text.
150
-
151
- When the runtime supports it, voice turns may include a hidden speech sidecar on the assistant message:
152
-
153
- ```json
154
- {
155
- "metadata": {
156
- "spoken": {
157
- "text": "Speech-optimized text for TTS only.",
158
- "instructions": "Speak with upbeat, warm excitement and slightly rising intonation.",
159
- "style": {
160
- "emotion": "excited",
161
- "energy": "medium_high"
162
- }
163
- }
164
- }
165
- }
166
- ```
167
-
5
+ This package is for managed Oomi connectivity. Persona UI creation and rendering happen inside Oomi-managed systems. The OpenClaw machine uses API actions only.
6
+
7
+ ## Primary Goal
8
+
9
+ Get OpenClaw into a state where:
10
+
11
+ - Oomi managed text chat works
12
+ - Oomi device-backed voice can start cleanly
13
+ - the bridge is supervised or restartable
14
+ - component-composed persona apps can be inspected and updated through Oomi API tools
15
+ - approved user context, such as HealthKit data synced by the Oomi mobile app, can be read through Oomi backend context tools
16
+ - the user never has to paste raw pair identifiers or gateway secrets manually when managed connect is available
17
+
18
+ ## Standard Connect Flow
19
+
20
+ If the user asks to connect OpenClaw to Oomi chat or voice:
21
+
22
+ 1. Refresh bootstrap first:
23
+ - `curl -fsSL https://www.oomi.ai/install.sh | bash`
24
+ 2. Ensure `oomi-ai` is installed:
25
+ - `pnpm add -g oomi-ai@latest`
26
+ - fallback: `npm install -g oomi-ai@latest`
27
+ 3. Pair the device without starting a legacy one-off flow:
28
+ - `oomi openclaw pair --app-url https://www.oomi.ai --no-start`
29
+ 4. Install the OpenClaw plugin:
30
+ - `openclaw plugins install oomi-ai@latest`
31
+ 5. Print the config block and secrets:
32
+ - `oomi openclaw plugin --show-secrets --backend-url https://api.oomi.ai`
33
+ 6. Apply the printed `channels.oomi.accounts.default` config.
34
+ 7. Restart OpenClaw.
35
+ 8. Start or repair the bridge:
36
+ - `oomi openclaw bridge ensure --detach`
37
+ - if stale: `oomi openclaw bridge restart --detach`
38
+ - on macOS, prefer supervision: `oomi openclaw bridge service install`
39
+
40
+ If the user provides a specific app URL, use it directly in the pair flow:
41
+
42
+ - `oomi openclaw pair --app-url <URL> --no-start`
43
+
44
+ ## Required User-Facing Result
45
+
46
+ When pairing completes successfully, return this exact format:
47
+
48
+ - `Oomi Connect Ready`
49
+ - `Auth Link: ...`
50
+
51
+ Do not add extra narrative before or after those lines.
52
+ Do not ask the user to enter raw pair codes, gateway passwords, or nonce values manually.
53
+
54
+ ## Update And Stale Bridge Repair
55
+
56
+ After updating `oomi-ai`, always make sure the running bridge is not still using an old package or dead gateway connection.
57
+
58
+ Preferred update flow:
59
+
60
+ ```bash
61
+ pnpm add -g oomi-ai@latest
62
+ openclaw plugins install oomi-ai@latest
63
+ oomi openclaw refresh --skip-version-check
64
+ oomi openclaw bridge ps
65
+ ```
66
+
67
+ If the bridge is stale, disconnected, duplicated, or reporting the wrong version:
68
+
69
+ ```bash
70
+ oomi openclaw bridge restart --detach
71
+ oomi openclaw bridge ps
72
+ ```
73
+
74
+ On macOS supervised installs:
75
+
76
+ ```bash
77
+ oomi openclaw bridge service restart
78
+ oomi openclaw bridge service status
79
+ ```
80
+
81
+ Healthy result:
82
+
83
+ - one bridge worker is active
84
+ - bridge status reaches `connected`
85
+ - the bridge version matches the newly installed package
86
+
87
+ ## Runtime Checks
88
+
89
+ Use these commands to inspect the installed machine:
90
+
91
+ ```bash
92
+ oomi openclaw bridge ps
93
+ oomi openclaw bridge service status
94
+ oomi openclaw status
95
+ tail -f ~/.openclaw/logs/oomi-bridge-live.log
96
+ tail -f ~/.openclaw/logs/gateway.log
97
+ tail -f ~/.openclaw/logs/gateway.err.log
98
+ ```
99
+
100
+ Useful local files:
101
+
102
+ - `~/.openclaw/oomi-bridge-status.json`
103
+ - `~/.openclaw/logs/oomi-bridge-live.log`
104
+ - `~/.openclaw/logs/gateway.log`
105
+ - `~/.openclaw/logs/gateway.err.log`
106
+ - `~/.openclaw/agents/main/sessions/*.jsonl`
107
+
108
+ ## Healthy State
109
+
110
+ Treat the machine as healthy when all of the following are true:
111
+
112
+ - OpenClaw loads the `oomi-ai` plugin without duplicate-id conflicts
113
+ - `channels.oomi.accounts.default` is populated with a valid `backendUrl` and `deviceToken`
114
+ - the bridge shows `connected` after managed subscription is confirmed
115
+ - text chat reaches the Oomi assistant
116
+ - voice STT can produce `asr.final`
117
+ - assistant replies can come back without the bridge dropping into `stopped`
118
+
119
+ Bridge status meanings:
120
+
121
+ - `starting`: bridge booting or waiting for managed subscription
122
+ - `connected`: ready for managed chat and voice traffic
123
+ - `reconnecting`: transport dropped and retry is scheduled
124
+ - `degraded`: bridge caught a runtime fault but is still alive
125
+ - `error`: startup or auth failure blocked useful operation
126
+ - `stopped`: not running or intentionally stopped
127
+
128
+ ## Troubleshooting
129
+
130
+ ### Duplicate plugin id warning
131
+
132
+ Symptom:
133
+
134
+ - OpenClaw reports `duplicate plugin id detected`
135
+
136
+ Action:
137
+
138
+ - ensure only one active `oomi-ai` plugin install is discoverable
139
+ - remove stale extension copies before reinstalling
140
+
141
+ ### `invalid handshake: first request must be connect`
142
+
143
+ Meaning:
144
+
145
+ - a gateway request was sent before `connect` had been accepted
146
+
147
+ Action:
148
+
149
+ - update `oomi-ai`
150
+ - restart the bridge
151
+ - confirm only one bridge worker is running
152
+
153
+ ### Device is linked but voice start still fails
154
+
155
+ Meaning:
156
+
157
+ - linked ownership is not enough; the device side still needs to be live
158
+
159
+ Action:
160
+
161
+ - confirm the device websocket is actually online
162
+ - confirm the bridge is `connected`
163
+ - restart the bridge if it is stuck in `reconnecting` or `degraded`
164
+
165
+ ### STT works but the assistant does not reply
166
+
167
+ Meaning:
168
+
169
+ - the voice turn likely reached Oomi, but the managed gateway or OpenClaw run failed later
170
+
171
+ Action:
172
+
173
+ - inspect `gateway.log`, `gateway.err.log`, and the session JSONL
174
+ - check for `network_error`, auth failures, repeated bridge restarts, or stale package versions
175
+
176
+ ## Voice Notes
177
+
178
+ Voice depends on the same Oomi plugin and bridge layer as managed chat.
179
+
180
+ That means:
181
+
182
+ - if plugin install or bridge health is wrong, voice replies will also fail
183
+ - STT can succeed even when assistant reply delivery is broken later in the run
184
+ - a `voice_session_*` failure should be investigated, but it should not automatically be treated as proof that all normal Oomi chat is down
185
+
186
+ ### Hidden Speech Payload
187
+
188
+ For managed voice turns, keep visible assistant chat text natural and user-facing.
189
+ Do not put spoken-style tags like `[happy]`, `[sad]`, or `[excited]` into visible chat text.
190
+
191
+ When the runtime supports it, voice turns may include a hidden speech sidecar on the assistant message:
192
+
193
+ ```json
194
+ {
195
+ "metadata": {
196
+ "spoken": {
197
+ "text": "Speech-optimized text for TTS only.",
198
+ "instructions": "Speak with upbeat, warm excitement and slightly rising intonation.",
199
+ "style": {
200
+ "emotion": "excited",
201
+ "energy": "medium_high"
202
+ }
203
+ }
204
+ }
205
+ }
206
+ ```
207
+
168
208
  Rules:
209
+
169
210
  - visible `content` remains the source of truth for Oomi chat rendering
170
- - for managed cloned-voice replies, include `metadata.spoken` whenever backend TTS should speak the turn
211
+ - for managed voice replies, include `metadata.spoken` whenever backend TTS should speak the turn
171
212
  - `metadata.spoken.text` is for backend TTS only
172
- - `metadata.spoken.language` should be one of the supported Qwen language values such as `English`
213
+ - `metadata.spoken.language` should use the backend-supported language value for the active provider; use `English` only when no more specific locale is supplied
173
214
  - `metadata.spoken.segments` can carry bounded per-segment prosody for pace, pitch, volume, and pause timing
174
215
  - `metadata.spoken.instructions` should be natural-language guidance, not raw bracket tags
175
- - `metadata.spoken.style` is optional metadata for debugging/future mapping
176
-
177
- Current package behavior:
178
- - if you provide `metadata.spoken`, the package preserves it unchanged
179
- - if you omit `metadata.spoken`, the shared package helper may synthesize it as a compatibility guardrail before backend TTS
180
216
  - visible chat text is never rewritten by the package
181
- - backend cloned voice is strict: if `metadata.spoken` does not reach Oomi, playback fails instead of falling back to flat speech
182
-
183
- ## Avatar Commands
184
-
185
- Before using avatar commands, call `get_avatar_capabilities` and prefer canonical values.
186
- Inline tags are stripped from user-visible text.
187
-
188
- Use inline tags like:
189
- - `[anim:Waving]`, `[anim:Walking]`, `[anim:Idle]`, `[anim:Sitting Idle]`
190
- - `[face:happy]`, `[face:sad]`, `[face:surprised]`, `[face:focused]`, `[face:gentle]`, `[face:thinking]`
191
- - `[gesture:nod]`, `[gesture:think]`, `[gesture:shrug]`, `[gesture:wave]`, `[gesture:bow]`
217
+
218
+ ## Avatar Commands
219
+
220
+ Prefer canonical avatar values.
221
+ Inline tags are stripped from user-visible text.
222
+
223
+ Use inline tags like:
224
+
225
+ - `[anim:Waving]`, `[anim:Walking]`, `[anim:Idle]`, `[anim:Sitting Idle]`
226
+ - `[face:happy]`, `[face:sad]`, `[face:surprised]`, `[face:focused]`, `[face:gentle]`, `[face:thinking]`
227
+ - `[gesture:nod]`, `[gesture:think]`, `[gesture:shrug]`, `[gesture:wave]`, `[gesture:bow]`
192
228
  - `[look:camera]`, `[look:left]`, `[look:right]`, `[look:up]`, `[look:down]`
193
229
 
194
230
  Aliases allowed if needed:
231
+
195
232
  - `wave -> Waving`
196
233
  - `walk -> Walking`
197
234
  - `idle -> Idle`
198
235
  - `sit` or `sitting -> Sitting Idle`
199
236
 
200
- ## Persona App Generation
201
-
202
- For persona app work, treat the scaffold as a runtime contract, not a disposable starting point.
203
-
204
- When a user asks you in chat to create a new persona for Oomi:
205
-
206
- 1. First clarify the persona `name`, `slug`, `description`, permissions, tools, and the ideal work surface.
207
- 2. After that, use this exact manual creation order on the OpenClaw machine:
208
- - `export WORKSPACE_ROOT="$HOME/.openclaw/workspace/personas"`
209
- - `export SLUG="<persona-slug>"`
210
- - `export NAME="<persona-name>"`
211
- - `export DESCRIPTION="<persona-description>"`
212
- - `oomi personas scaffold "$SLUG" --name "$NAME" --description "$DESCRIPTION" --out "$WORKSPACE_ROOT/$SLUG" --force`
213
- - `test -f "$WORKSPACE_ROOT/$SLUG/persona.json"`
214
- - `test -f "$WORKSPACE_ROOT/$SLUG/oomi.runtime.json"`
215
- - `test -f "$WORKSPACE_ROOT/$SLUG/package.json"`
216
- - `oomi personas create-managed "$SLUG" --name "$NAME" --description "$DESCRIPTION" --json`
217
- - `oomi personas launch-managed "$SLUG" --workspace-root "$WORKSPACE_ROOT" --force-install --json`
218
- - `test -f "$WORKSPACE_ROOT/$SLUG/.oomi/runtime.json"`
219
- - `cat "$WORKSPACE_ROOT/$SLUG/.oomi/runtime.json"`
220
- - `oomi personas status "$SLUG" --json`
221
- - `PORT="$(jq -r '.localPort' "$WORKSPACE_ROOT/$SLUG/.oomi/runtime.json")"`
222
- - `oomi personas heartbeat "$SLUG" --local-port "$PORT" --json`
223
- 3. Fail fast if scaffold verification fails or if any `--json` command does not return success.
224
- 4. Treat backend registration as incomplete until `create-managed`, `launch-managed`, `status`, and `heartbeat` all succeed.
225
- 5. Do not present a localhost URL like `http://127.0.0.1:4789` as the final persona runtime URL for Oomi clients.
226
- 6. Do not rely on `launch-managed` auto-creating the backend persona record. Run `create-managed` explicitly first.
227
- 7. Do not use `oomi personas runtime-register <slug>` or `oomi personas heartbeat <slug>` before `create-managed` succeeds.
228
- 8. Do not use manual `npm run dev` or any unmanaged dev server as the persona launch path.
229
-
230
- When generating a managed persona app for Oomi:
231
-
232
- 1. Do not build the app shell from scratch.
233
- 2. Always run `oomi personas scaffold <slug> --name "<name>" --description "<description>" --out <path>` first.
234
- 3. Only customize persona-specific files inside `src/persona/` and `persona/` unless Oomi explicitly instructs otherwise.
235
- 4. Preserve the scaffolded WebSpatial/Vite shell, `public/oomi.health.json`, `oomi.runtime.json`, `public/manifest.webmanifest`, and the vendored WebSpatial fork.
236
- 5. Keep the browser route and the XR route split. In XR mode, the index route should open directly into the mounted scene component, not a flat homepage.
237
- 6. Call `configurePersonaScene()` from that mounted scene component and log `detectSpatialEnvironment()` on scene boot so the runtime can be verified in headset.
238
- 7. Author multiple meaningful XR surfaces with `enable-xr`, `--xr-back`, and `--xr-background-material` values instead of putting one outer `enable-xr` wrapper around the whole page.
239
- 8. Keep `html.is-spatial` shell styles transparent so the host recedes and the authored panels carry the spatial material.
240
- 9. Keep `snapdom` and `html2canvas` exposed from `main.tsx` because AndroidXR DOM capture depends on them.
241
- 10. After customization, bring the persona online through `oomi personas launch-managed <slug> --workspace-root <root> --force-install --json`, then verify `oomi personas status <slug> --json`, then heartbeat using the assigned local port from `.oomi/runtime.json`.
242
- 11. For normal OpenClaw-hosted persona apps on the same LAN, the managed runtime registration contract is:
243
- - backend `entryUrl`: LAN-reachable host such as `http://192.168.x.x:<port>`
244
- - backend `healthcheckUrl`: local loopback such as `http://127.0.0.1:<port>/webspatial/avp/oomi.health.json`
245
- 12. Do not override `--endpoint` with `127.0.0.1` unless the persona is intentionally local-only and not meant to open from Oomi web/XR.
246
- 13. Do not replace the managed runtime flow with manual `npm run dev`, ad hoc `runtime-register`, or ad hoc `heartbeat` commands during first-time creation.
247
-
248
- When editing an existing managed persona that is already open in Oomi:
249
-
250
- 1. Do not ask the user to find the app path manually if Oomi already selected the persona tab for you.
251
- 2. First run `oomi personas status <slug> --json`.
252
- 3. Use `editableWorkspacePath` from that command as the authoritative directory for reads, edits, and verification.
253
- 4. Treat `compatibilityWorkspacePath` only as a fallback or migration clue.
254
- 5. Preserve the scaffolded WebSpatial shell and runtime health files unless the user explicitly asks for a deeper structural change, and do not regress the XR route back into a flat home page.
255
- 6. Do not claim the persona changed unless you have verified the file contents changed in `editableWorkspacePath` or the runtime reflects the update.
256
-
257
- When executing a structured persona job from Oomi:
258
-
259
- 1. Prefer `oomi persona-jobs execute --message-file <job.json>` when the backend has already produced a machine-readable job payload.
260
- 2. That command is allowed to scaffold the app, install dependencies, start the local runtime, wait for the health document, register the runtime, and report job success or failure.
261
- 3. Use the lower-level commands only for recovery or partial reruns:
262
- - `oomi personas runtime-register <slug> --local-port 4789`
263
- - `oomi personas heartbeat <slug> --local-port 4789`
264
- - `oomi persona-jobs start <jobId>`
265
- - `oomi persona-jobs succeed <jobId> --workspace-path <path> --local-port 4789`
266
- - `oomi persona-jobs fail <jobId> --code <code> --message "<text>"`
267
- 4. Before any low-level `runtime-register` or `heartbeat` recovery command, make sure the backend persona already exists via `create-managed`.
268
- 5. If you use the low-level `runtime-register` or `heartbeat` commands, prefer `--local-port` by itself and let `oomi-ai` derive the LAN-reachable endpoint automatically.
269
- 6. If you must pass `--endpoint` explicitly, it must be the LAN-reachable host or a relay URL, not `127.0.0.1`.
270
-
271
- When the Oomi bridge is running on the machine, queued persona jobs from Oomi are now polled and executed automatically through the filtered control-message lane. You should still use the explicit commands above for manual retries, recovery, or direct operator workflows.
237
+ ## Persona App API Tools
238
+
239
+ Oomi persona apps are component-composed client surfaces backed by approved templates, components, data bindings, actions, and permissions.
240
+
241
+ The OpenClaw agent should inspect and update persona app state through the Oomi API tools in this package.
242
+
243
+ When a user asks about an existing persona app:
244
+
245
+ 1. Run `oomi persona-apps list --json` to see the persona apps linked to this user's account.
246
+ 2. Run `oomi persona-apps show <slug> --json` before answering detailed questions about that persona's state.
247
+ 3. Answer from the returned `appState.bindings`, not from memory or guesses.
248
+ 4. To update state, use a validated action: `oomi persona-apps apply-action <slug> --action <action-id> --payload-json '<json>' --json`.
249
+ 5. If `persona-apps list` returns no app for the user's request, tell the user they can add that persona from the Oomi client so the client can collect the right permissions and data sources.
250
+
251
+ For the Fitness v0 slice:
252
+
253
+ - Use `fitness.complete_goal` with payload `{"goalId":"easy-run"}` to mark a known goal complete.
254
+ - Use `fitness.complete_workout` with payload like `{"goalId":"easy-run","minutes":20}` when the user says they finished a workout.
255
+
256
+ Strict rules:
257
+
258
+ - Do not create local persona UI projects.
259
+ - Do not run local persona app runtimes.
260
+ - Do not execute persona UI jobs.
261
+ - Do not install app framework dependencies for persona UI work.
262
+ - Do not present local URLs as persona app URLs.
263
+ - If a persona app needs to be created, tell the user to add it from the Oomi client first so permissions and hydration run correctly.
264
+
265
+ ## Permissioned Context Tools
266
+
267
+ Use Oomi context tools when the user asks about personal data that should come from mobile permissions instead of model memory.
268
+
269
+ For health, fitness, sleep, workout, cardio, or movement questions:
270
+
271
+ ```bash
272
+ oomi context health --json
273
+ ```
274
+
275
+ Rules:
276
+
277
+ - Answer only from `healthContext.summary` and `healthContext.derived`.
278
+ - Respect `healthContext.agentGuidance.canAnswerFromContext`.
279
+ - If `canAnswerFromContext` is false, tell the user the relevant `healthContext.repair.label` or `healthContext.repair.reason`.
280
+ - If `healthContext.status` is `stale`, mention that the latest HealthKit sync may be out of date when timing matters.
281
+ - Do not infer unavailable health fields.
282
+ - Do not request HealthKit directly from the phone; the Oomi mobile app owns permission prompts and syncs approved data to the backend.