oomi-ai 0.2.48 → 0.2.50
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 +186 -98
- package/agent_instructions.md +49 -10
- package/bin/oomi-ai.js +22 -22
- package/lib/personaRuntimeProcess.js +21 -8
- package/openclaw.plugin.json +1 -1
- package/package.json +15 -10
- package/templates/persona-app/README.md +30 -7
- package/templates/persona-app/src/App.css +210 -492
- package/templates/persona-app/src/App.tsx +4 -1
- package/templates/persona-app/src/index.css +24 -3
- package/templates/persona-app/src/pages/HomePage.tsx +67 -94
- package/templates/persona-app/src/pages/ScenePage.tsx +155 -2
- package/templates/persona-app/src/persona/notes.ts +5 -2
- package/templates/persona-app/src/spatial.ts +1 -1
package/README.md
CHANGED
|
@@ -1,57 +1,60 @@
|
|
|
1
|
-
# oomi-ai
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
1
|
+
# oomi-ai
|
|
2
|
+
|
|
3
|
+
Managed Oomi chat, voice bridge, and XR-first persona scaffolding for OpenClaw.
|
|
4
|
+
|
|
5
|
+
## At A Glance
|
|
6
|
+
|
|
7
|
+
- managed OpenClaw channel extension for Oomi text chat
|
|
8
|
+
- local bridge and pairing tooling for device-backed chat and voice
|
|
9
|
+
- XR-first WebSpatial persona scaffolding for generated Oomi work surfaces
|
|
10
|
+
- vendored AndroidXR WebSpatial fork sync and scaffold repair for managed persona runtimes
|
|
11
|
+
- managed persona launch, register, stop, delete, and queued persona-job execution flows
|
|
12
|
+
- repo-local runtime and TTS validation loops for package developers
|
|
13
|
+
|
|
14
|
+
This package is for two audiences:
|
|
15
|
+
- OpenClaw operators who need to connect a machine to Oomi and keep chat or voice healthy
|
|
16
|
+
- Developers evaluating the plugin on npm and deciding whether it matches their OpenClaw + Oomi setup
|
|
17
|
+
|
|
18
|
+
## Current Package Focus
|
|
19
|
+
|
|
20
|
+
The current package is centered on three operational contracts:
|
|
21
|
+
|
|
22
|
+
1. managed Oomi text transport inside OpenClaw
|
|
23
|
+
2. device-backed chat and voice through the local bridge
|
|
24
|
+
3. XR-first persona runtime generation and repair for Oomi work surfaces
|
|
25
|
+
|
|
26
|
+
## What This Package Ships
|
|
27
|
+
|
|
28
|
+
The npm package contains three Oomi integration surfaces:
|
|
29
|
+
|
|
30
|
+
1. OpenClaw channel extension
|
|
31
|
+
- File: `openclaw.extension.js`
|
|
32
|
+
- Purpose: stable managed text transport through the Oomi backend channel API
|
|
33
|
+
- This is the preferred integration surface for normal chat
|
|
34
|
+
|
|
35
|
+
2. Local bridge + CLI
|
|
36
|
+
- Files: `bin/oomi-ai.js`, `bin/sessionBridgeState.js`
|
|
37
|
+
- Purpose: pair a device, manage the OpenClaw bridge worker, and support managed gateway traffic needed by device-backed chat and voice
|
|
38
|
+
- This is the part that deals with broker sockets, local gateway sessions, challenge auth, and bridge health
|
|
39
|
+
|
|
40
|
+
3. Persona scaffold + runtime helpers
|
|
41
|
+
- Files: `templates/persona-app/*`, `lib/scaffold.js`, `lib/personaRuntime*.js`
|
|
42
|
+
- Purpose: create, launch, repair, and register XR-first managed persona apps for Oomi
|
|
43
|
+
- This is the part that matters when Oomi or an agent generates a specialist work surface
|
|
44
|
+
|
|
45
|
+
In practical terms:
|
|
46
|
+
- If you only need a clean managed chat channel, the extension is the main reason to install this package
|
|
47
|
+
- If you need Oomi device-backed chat or voice on an OpenClaw machine, you also need the bridge tooling in this package
|
|
48
|
+
- If you need Oomi-managed personas that open as real XR work surfaces, you also need the scaffold and runtime helpers in this package
|
|
46
49
|
|
|
47
50
|
## When To Install It
|
|
48
51
|
|
|
49
|
-
Install `oomi-ai` if all of the following are true:
|
|
50
|
-
- you use OpenClaw
|
|
51
|
-
- you want Oomi as a managed channel inside OpenClaw
|
|
52
|
-
- you want device-backed Oomi chat, Oomi voice, or
|
|
53
|
-
|
|
54
|
-
Do not install it just to use the Oomi web app by itself.
|
|
52
|
+
Install `oomi-ai` if all of the following are true:
|
|
53
|
+
- you use OpenClaw
|
|
54
|
+
- you want Oomi as a managed channel, bridge-backed voice surface, or persona runtime inside OpenClaw
|
|
55
|
+
- you want device-backed Oomi chat, Oomi voice, generated personas, or some combination of those
|
|
56
|
+
|
|
57
|
+
Do not install it just to use the Oomi web app by itself.
|
|
55
58
|
|
|
56
59
|
## Install And Upgrade
|
|
57
60
|
|
|
@@ -82,14 +85,15 @@ openclaw plugins install oomi-ai@latest
|
|
|
82
85
|
|
|
83
86
|
## Operator Quick Start
|
|
84
87
|
|
|
85
|
-
The packaged operator instructions live in [agent_instructions.md](./agent_instructions.md).
|
|
86
|
-
That is the primary reference for:
|
|
87
|
-
- pairing a device
|
|
88
|
-
- installing the plugin
|
|
89
|
-
- configuring `channels.oomi.accounts.default`
|
|
90
|
-
- running or supervising the bridge
|
|
91
|
-
- checking whether the system is healthy
|
|
92
|
-
- troubleshooting chat and voice failures
|
|
88
|
+
The packaged operator instructions live in [agent_instructions.md](./agent_instructions.md).
|
|
89
|
+
That is the primary reference for:
|
|
90
|
+
- pairing a device
|
|
91
|
+
- installing the plugin
|
|
92
|
+
- configuring `channels.oomi.accounts.default`
|
|
93
|
+
- running or supervising the bridge
|
|
94
|
+
- checking whether the system is healthy
|
|
95
|
+
- troubleshooting chat and voice failures
|
|
96
|
+
- generating or repairing XR-first managed persona apps
|
|
93
97
|
|
|
94
98
|
Fast-path install flow:
|
|
95
99
|
|
|
@@ -285,43 +289,119 @@ OPENROUTER_API_KEY=<your-openrouter-key>
|
|
|
285
289
|
|
|
286
290
|
The local harness uses the `openrouter-free` preset for direct-provider smoke. If `OPENROUTER_API_KEY` is present in `.env.local`, `pnpm run dev:openclaw-local` automatically uses the provider-backed testing path. Without that key, it boots in `oomi-managed` mode and waits on a future Oomi-managed provider relay.
|
|
287
291
|
|
|
288
|
-
## Persona Scaffolding
|
|
289
|
-
|
|
290
|
-
Use the scaffold flow when OpenClaw needs to build a managed persona app that will live inside Oomi:
|
|
292
|
+
## Persona Scaffolding
|
|
293
|
+
|
|
294
|
+
Use the scaffold flow when OpenClaw needs to build a managed persona app that will live inside Oomi:
|
|
291
295
|
|
|
292
296
|
```bash
|
|
293
297
|
oomi personas scaffold market-analyst --name "Market Analyst" --description "Private app for reviewing my broker positions and risk." --out ~/.openclaw/workspace/personas/market-analyst
|
|
294
298
|
```
|
|
295
299
|
|
|
296
|
-
Use:
|
|
297
|
-
- `oomi personas create <id>` for repo-local manifest work
|
|
298
|
-
- `oomi personas create-managed
|
|
299
|
-
- `oomi personas scaffold <slug>` for
|
|
300
|
-
- `oomi persona-jobs execute --message-file <job.json>` when OpenClaw receives a structured persona orchestration job from Oomi
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
```bash
|
|
305
|
-
oomi personas launch-managed market-analyst --
|
|
300
|
+
Use:
|
|
301
|
+
- `oomi personas create <id>` only for repo-local manifest work, not for the normal managed Oomi persona flow
|
|
302
|
+
- `oomi personas create-managed <slug>` to create the backend managed persona record before launch or runtime registration
|
|
303
|
+
- `oomi personas scaffold <slug>` for an XR-first WebSpatial Oomi app shell with runtime metadata and health documents
|
|
304
|
+
- `oomi persona-jobs execute --message-file <job.json>` when OpenClaw receives a structured persona orchestration job from Oomi
|
|
305
|
+
|
|
306
|
+
Managed runtime and recovery commands:
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
oomi personas launch-managed market-analyst --workspace-root ~/.openclaw/workspace/personas --force-install --json
|
|
306
310
|
oomi personas status market-analyst
|
|
307
311
|
oomi personas stop market-analyst
|
|
308
312
|
oomi personas delete market-analyst
|
|
313
|
+
# recovery only, after create-managed already exists
|
|
309
314
|
oomi personas runtime-register market-analyst --local-port 4789
|
|
310
|
-
oomi personas heartbeat market-analyst --local-port 4789
|
|
311
|
-
oomi persona-jobs start pj_123
|
|
315
|
+
oomi personas heartbeat market-analyst --local-port 4789
|
|
316
|
+
oomi persona-jobs start pj_123
|
|
312
317
|
oomi persona-jobs succeed pj_123 --workspace-path ~/.openclaw/workspace/personas/market-analyst --local-port 4789
|
|
313
|
-
oomi persona-jobs fail pj_123 --code JOB_FAILED --message "Scaffold generation failed."
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
318
|
+
oomi persona-jobs fail pj_123 --code JOB_FAILED --message "Scaffold generation failed."
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
Notes:
|
|
322
|
+
|
|
323
|
+
- For remote Oomi clients such as web and Android XR, do not manually register `http://127.0.0.1:<port>` as the persona `entryUrl`.
|
|
324
|
+
- When you pass only `--local-port`, `oomi-ai` derives a LAN-reachable endpoint automatically and keeps the healthcheck on loopback.
|
|
325
|
+
- If you pass `--endpoint` explicitly, it should be a LAN or relay URL that the client can actually open.
|
|
326
|
+
- The scaffolded XR route should default directly into a mounted scene component that calls `configurePersonaScene()`, logs `detectSpatialEnvironment()`, and renders multiple authored `enable-xr` panels.
|
|
327
|
+
- The browser route should remain valid, but the XR entry path should not fall back to a flat marketing or home page.
|
|
328
|
+
- Do not use manual `npm run dev` as the first-time persona launch path for managed Oomi personas.
|
|
329
|
+
|
|
330
|
+
Exact managed persona creation order:
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
export WORKSPACE_ROOT="$HOME/.openclaw/workspace/personas"
|
|
334
|
+
export SLUG="tokyo-guide"
|
|
335
|
+
export NAME="Tokyo Guide"
|
|
336
|
+
export DESCRIPTION="Personal travel assistant for Tokyo trip planning - itineraries, food, culture, and summer tips for July"
|
|
337
|
+
|
|
338
|
+
# 1. Scaffold the local app workspace
|
|
339
|
+
oomi personas scaffold "$SLUG" \
|
|
340
|
+
--name "$NAME" \
|
|
341
|
+
--description "$DESCRIPTION" \
|
|
342
|
+
--out "$WORKSPACE_ROOT/$SLUG" \
|
|
343
|
+
--force
|
|
344
|
+
|
|
345
|
+
# 2. Verify scaffold actually wrote files
|
|
346
|
+
test -f "$WORKSPACE_ROOT/$SLUG/persona.json"
|
|
347
|
+
test -f "$WORKSPACE_ROOT/$SLUG/oomi.runtime.json"
|
|
348
|
+
test -f "$WORKSPACE_ROOT/$SLUG/package.json"
|
|
349
|
+
|
|
350
|
+
# 3. Create the backend persona record first
|
|
351
|
+
oomi personas create-managed "$SLUG" \
|
|
352
|
+
--name "$NAME" \
|
|
353
|
+
--description "$DESCRIPTION" \
|
|
354
|
+
--json
|
|
355
|
+
|
|
356
|
+
# 4. Launch the managed runtime and register it with Oomi
|
|
357
|
+
oomi personas launch-managed "$SLUG" \
|
|
358
|
+
--workspace-root "$WORKSPACE_ROOT" \
|
|
359
|
+
--force-install \
|
|
360
|
+
--json
|
|
361
|
+
|
|
362
|
+
# 5. Verify local runtime state exists
|
|
363
|
+
test -f "$WORKSPACE_ROOT/$SLUG/.oomi/runtime.json"
|
|
364
|
+
cat "$WORKSPACE_ROOT/$SLUG/.oomi/runtime.json"
|
|
365
|
+
|
|
366
|
+
# 6. Verify Oomi-local status
|
|
367
|
+
oomi personas status "$SLUG" --json
|
|
368
|
+
|
|
369
|
+
# 7. Send a heartbeat using the actual assigned port
|
|
370
|
+
PORT="$(jq -r '.localPort' "$WORKSPACE_ROOT/$SLUG/.oomi/runtime.json")"
|
|
371
|
+
oomi personas heartbeat "$SLUG" \
|
|
372
|
+
--local-port "$PORT" \
|
|
373
|
+
--json
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
Rules for that flow:
|
|
377
|
+
|
|
378
|
+
- scaffold first
|
|
379
|
+
- verify scaffold wrote files before backend creation
|
|
380
|
+
- create-managed before any runtime registration or heartbeat
|
|
381
|
+
- launch-managed instead of manual `npm run dev`
|
|
382
|
+
- heartbeat only after `.oomi/runtime.json` exists
|
|
383
|
+
- fail fast if any `--json` command does not return success
|
|
384
|
+
- never treat local runtime success as backend registration success
|
|
385
|
+
|
|
386
|
+
Do not do this for first-time creation:
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
oomi personas runtime-register "$SLUG" --local-port 4791
|
|
390
|
+
oomi personas launch-managed "$SLUG"
|
|
391
|
+
npm run dev &
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
That sequence is wrong because `runtime-register` and `heartbeat` assume the backend persona already exists, `launch-managed` only auto-creates when the persona is missing and `--name` is present, and manual `npm run dev` bypasses the managed runtime state contract.
|
|
395
|
+
|
|
396
|
+
Queued-job shortcut:
|
|
397
|
+
|
|
398
|
+
```bash
|
|
399
|
+
oomi personas create-managed cooking-persona --name "Cooking Persona" --description "Private cooking workspace for recipes, meal planning, and kitchen notes."
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
Use that shortcut only when the backend and running bridge are already set up to consume the queued `persona_job` automatically. Do not confuse it with the explicit scaffold + launch flow above.
|
|
403
|
+
|
|
404
|
+
If you want to explicitly host or reuse the persona app on the OpenClaw machine outside the queued-job path, use:
|
|
325
405
|
|
|
326
406
|
```bash
|
|
327
407
|
oomi personas launch-managed cooking-persona --entry-url https://your-relay.example/oomi/cooking-persona
|
|
@@ -412,18 +492,26 @@ What to check:
|
|
|
412
492
|
- if the package local replay succeeds but the live machine fails, verify the OpenClaw machine is actually running the updated bridge binary
|
|
413
493
|
- if the local replay fails, fix the assistant-final contract first instead of debugging the browser or backend deployment
|
|
414
494
|
|
|
415
|
-
## Developer Notes
|
|
416
|
-
|
|
417
|
-
If you are inspecting this package on npm, the main architectural points are:
|
|
418
|
-
- the extension path is the stable managed text contract
|
|
419
|
-
- the local bridge exists because Oomi also needs device-backed and voice-capable flows
|
|
420
|
-
- the
|
|
421
|
-
|
|
422
|
-
-
|
|
423
|
-
-
|
|
424
|
-
-
|
|
425
|
-
-
|
|
426
|
-
-
|
|
495
|
+
## Developer Notes
|
|
496
|
+
|
|
497
|
+
If you are inspecting this package on npm, the main architectural points are:
|
|
498
|
+
- the extension path is the stable managed text contract
|
|
499
|
+
- the local bridge exists because Oomi also needs device-backed and voice-capable flows
|
|
500
|
+
- the persona scaffold exists because Oomi specialist personas can surface as scoped XR/web work surfaces, not just chat tabs
|
|
501
|
+
- the bridge has been hardened for:
|
|
502
|
+
- strict `connect`-first forwarding
|
|
503
|
+
- method-specific request shaping
|
|
504
|
+
- `idempotencyKey` handling
|
|
505
|
+
- bridge status that does not report `connected` before managed subscription is ready
|
|
506
|
+
- runtime fault isolation so local session failures are less likely to crash the whole provider
|
|
507
|
+
- one shared hidden managed-voice speech metadata helper used by both the extension and the local bridge
|
|
508
|
+
|
|
509
|
+
For generated WebSpatial persona apps, the intended scaffold contract is:
|
|
510
|
+
- XR mode defaults directly into the mounted scene route
|
|
511
|
+
- `configurePersonaScene()` runs from that scene component
|
|
512
|
+
- runtime diagnostics are logged on scene boot
|
|
513
|
+
- multiple meaningful UI surfaces use `enable-xr` and `xrStyle()`
|
|
514
|
+
- `html.is-spatial` keeps the host shell transparent
|
|
427
515
|
|
|
428
516
|
If you are developing the plugin, test the packaged surface with:
|
|
429
517
|
|
package/agent_instructions.md
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
# Oomi OpenClaw Operator Guide
|
|
2
|
-
|
|
3
|
-
Use these instructions when you need to connect, repair, or verify an OpenClaw machine that should talk to Oomi.
|
|
1
|
+
# Oomi OpenClaw Operator Guide
|
|
2
|
+
|
|
3
|
+
Use these instructions when you need to connect, repair, or verify an OpenClaw machine that should talk to Oomi.
|
|
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
|
|
4
9
|
|
|
5
10
|
## Primary Goal
|
|
6
11
|
|
|
@@ -194,20 +199,51 @@ Aliases allowed if needed:
|
|
|
194
199
|
|
|
195
200
|
## Persona App Generation
|
|
196
201
|
|
|
202
|
+
For persona app work, treat the scaffold as a runtime contract, not a disposable starting point.
|
|
203
|
+
|
|
197
204
|
When a user asks you in chat to create a new persona for Oomi:
|
|
198
205
|
|
|
199
|
-
1.
|
|
200
|
-
2.
|
|
201
|
-
|
|
202
|
-
|
|
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.
|
|
203
229
|
|
|
204
230
|
When generating a managed persona app for Oomi:
|
|
205
231
|
|
|
206
232
|
1. Do not build the app shell from scratch.
|
|
207
233
|
2. Always run `oomi personas scaffold <slug> --name "<name>" --description "<description>" --out <path>` first.
|
|
208
234
|
3. Only customize persona-specific files inside `src/persona/` and `persona/` unless Oomi explicitly instructs otherwise.
|
|
209
|
-
4. Preserve the scaffolded WebSpatial/Vite shell, `public/oomi.health.json`, `oomi.runtime.json`,
|
|
210
|
-
5.
|
|
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.
|
|
211
247
|
|
|
212
248
|
When editing an existing managed persona that is already open in Oomi:
|
|
213
249
|
|
|
@@ -215,7 +251,7 @@ When editing an existing managed persona that is already open in Oomi:
|
|
|
215
251
|
2. First run `oomi personas status <slug> --json`.
|
|
216
252
|
3. Use `editableWorkspacePath` from that command as the authoritative directory for reads, edits, and verification.
|
|
217
253
|
4. Treat `compatibilityWorkspacePath` only as a fallback or migration clue.
|
|
218
|
-
5. Preserve the scaffolded WebSpatial shell and runtime health files unless the user explicitly asks for a deeper structural change.
|
|
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.
|
|
219
255
|
6. Do not claim the persona changed unless you have verified the file contents changed in `editableWorkspacePath` or the runtime reflects the update.
|
|
220
256
|
|
|
221
257
|
When executing a structured persona job from Oomi:
|
|
@@ -228,5 +264,8 @@ When executing a structured persona job from Oomi:
|
|
|
228
264
|
- `oomi persona-jobs start <jobId>`
|
|
229
265
|
- `oomi persona-jobs succeed <jobId> --workspace-path <path> --local-port 4789`
|
|
230
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`.
|
|
231
270
|
|
|
232
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.
|
package/bin/oomi-ai.js
CHANGED
|
@@ -259,14 +259,14 @@ Commands:
|
|
|
259
259
|
personas sync
|
|
260
260
|
Sync personas from the repo into the Oomi backend registry.
|
|
261
261
|
|
|
262
|
-
personas create <id>
|
|
263
|
-
Create a new persona manifest
|
|
264
|
-
personas create-managed [slug]
|
|
265
|
-
Create
|
|
266
|
-
personas launch-managed [slug]
|
|
267
|
-
Launch or reuse a managed persona runtime on this OpenClaw machine.
|
|
268
|
-
personas scaffold <slug>
|
|
269
|
-
Create an Oomi-managed persona app scaffold for agent customization.
|
|
262
|
+
personas create <id>
|
|
263
|
+
Create a new persona manifest for local or repo work. For managed Oomi personas prefer create-managed.
|
|
264
|
+
personas create-managed [slug]
|
|
265
|
+
Create the managed persona record in Oomi. Run this before manual launch-managed, runtime-register, or heartbeat flows.
|
|
266
|
+
personas launch-managed [slug]
|
|
267
|
+
Launch or reuse a managed persona runtime on this OpenClaw machine and register a client-reachable runtime URL. Prefer scaffold + create-managed first.
|
|
268
|
+
personas scaffold <slug>
|
|
269
|
+
Create an Oomi-managed persona app scaffold for agent customization.
|
|
270
270
|
personas status <slug>
|
|
271
271
|
Show local managed persona runtime state for a persona slug.
|
|
272
272
|
personas stop <slug>
|
|
@@ -274,9 +274,9 @@ Commands:
|
|
|
274
274
|
personas delete <slug>
|
|
275
275
|
Stop a managed persona runtime and remove its workspace from this OpenClaw machine.
|
|
276
276
|
personas runtime-register <slug>
|
|
277
|
-
Register a running persona runtime with the Oomi backend.
|
|
278
|
-
personas heartbeat <slug>
|
|
279
|
-
Send a persona runtime heartbeat to the Oomi backend.
|
|
277
|
+
Register a running persona runtime with the Oomi backend. Recovery-only after create-managed. Prefer --local-port so the CLI can derive a reachable endpoint.
|
|
278
|
+
personas heartbeat <slug>
|
|
279
|
+
Send a persona runtime heartbeat to the Oomi backend. Recovery-only after launch-managed wrote .oomi/runtime.json.
|
|
280
280
|
personas runtime-fail <slug>
|
|
281
281
|
Report persona runtime failure to the Oomi backend.
|
|
282
282
|
persona-jobs start <jobId>
|
|
@@ -1579,21 +1579,21 @@ async function handlePersonaLaunchManagedCommand(flags = {}, positionalSlug = ''
|
|
|
1579
1579
|
const client = createCliPersonaApiClient(flags);
|
|
1580
1580
|
const safeName = String(flags.name || '').trim();
|
|
1581
1581
|
const safeDescription = String(flags.description || '').trim() || safeName;
|
|
1582
|
-
const safeSlug = String(flags.slug || positionalSlug || (safeName ? slugifyPersonaName(safeName) : '')).trim();
|
|
1583
|
-
if (!safeSlug) {
|
|
1584
|
-
throw new Error('Persona slug or name is required. Usage: oomi personas launch-managed [slug] --name "<name>"');
|
|
1585
|
-
}
|
|
1582
|
+
const safeSlug = String(flags.slug || positionalSlug || (safeName ? slugifyPersonaName(safeName) : '')).trim();
|
|
1583
|
+
if (!safeSlug) {
|
|
1584
|
+
throw new Error('Persona slug or name is required. Usage: oomi personas launch-managed [slug] --name "<name>". Prefer `oomi personas create-managed <slug> --name "<name>" --description "<description>"` first.');
|
|
1585
|
+
}
|
|
1586
1586
|
|
|
1587
1587
|
const shouldCreate = !isTruthyFlag(flags['no-create']);
|
|
1588
1588
|
let createdPersona = false;
|
|
1589
1589
|
let personaPayload = await findExistingManagedPersona(client, safeSlug);
|
|
1590
|
-
if (!personaPayload) {
|
|
1591
|
-
if (!shouldCreate) {
|
|
1592
|
-
throw new Error(`Managed persona ${safeSlug} does not exist in Oomi. Remove --no-create or create it first
|
|
1593
|
-
}
|
|
1594
|
-
if (!safeName) {
|
|
1595
|
-
throw new Error('Persona name is required when creating a new managed persona.');
|
|
1596
|
-
}
|
|
1590
|
+
if (!personaPayload) {
|
|
1591
|
+
if (!shouldCreate) {
|
|
1592
|
+
throw new Error(`Managed persona ${safeSlug} does not exist in Oomi. Remove --no-create or create it first with \`oomi personas create-managed ${safeSlug} --name "<name>" --description "<description>"\`.`);
|
|
1593
|
+
}
|
|
1594
|
+
if (!safeName) {
|
|
1595
|
+
throw new Error('Persona name is required when creating a new managed persona implicitly. Prefer running `oomi personas create-managed <slug> --name "<name>" --description "<description>"` first instead of relying on launch-managed auto-create.');
|
|
1596
|
+
}
|
|
1597
1597
|
personaPayload = await client.createManagedPersona({
|
|
1598
1598
|
slug: safeSlug,
|
|
1599
1599
|
name: safeName,
|
|
@@ -54,6 +54,7 @@ const LEGACY_WEBSPATIAL_TEMPLATE_FILE_RULES = [
|
|
|
54
54
|
shouldReplace: (content) =>
|
|
55
55
|
!content.includes('WEBSPATIAL_FORK_REPOSITORY') ||
|
|
56
56
|
!content.includes('configurePersonaScene') ||
|
|
57
|
+
!content.includes('"--xr-back": String(back)') ||
|
|
57
58
|
content.includes('WEBSPATIAL_FORK_COMMIT = "b2746721e4fe6b4f86dac0ea55938074eea00cda"') ||
|
|
58
59
|
content.includes('WEBSPATIAL_FORK_COMMIT = "8904ac8fec48fe49ee14d1739237bd1afb2894fe"'),
|
|
59
60
|
},
|
|
@@ -67,20 +68,22 @@ const LEGACY_WEBSPATIAL_TEMPLATE_FILE_RULES = [
|
|
|
67
68
|
{
|
|
68
69
|
relativePath: path.join('src', 'App.tsx'),
|
|
69
70
|
shouldReplace: (content) =>
|
|
71
|
+
!content.includes('const isSpatialRuntime = __XR_ENV_BASE__.startsWith("/webspatial/avp");') ||
|
|
72
|
+
!content.includes('<Route path="home" element={<HomePage />} />') ||
|
|
70
73
|
content.includes('<Route path="/" element={<HomePage />} />') ||
|
|
71
|
-
content.includes('<Route path="/scene" element={<ScenePage />} />')
|
|
74
|
+
content.includes('<Route path="/scene" element={<ScenePage />} />') ||
|
|
75
|
+
content.includes('<Route index element={<HomePage />} />'),
|
|
72
76
|
},
|
|
73
77
|
{
|
|
74
78
|
relativePath: path.join('src', 'pages', 'HomePage.tsx'),
|
|
75
79
|
shouldReplace: (content) =>
|
|
76
80
|
(content.includes('Open Spatial Scene') &&
|
|
77
81
|
content.includes('Open Scene Route')) ||
|
|
78
|
-
|
|
79
|
-
content.includes('
|
|
80
|
-
content.includes('
|
|
81
|
-
|
|
82
|
-
content.includes('
|
|
83
|
-
content.includes('enable-xr={sceneMode || undefined}') ||
|
|
82
|
+
content.includes('sceneMode') ||
|
|
83
|
+
content.includes('configurePersonaScene();') ||
|
|
84
|
+
content.includes('persona-preview-card') ||
|
|
85
|
+
content.includes('Launch Spatial Surface') ||
|
|
86
|
+
content.includes('Open Spatial Preview') ||
|
|
84
87
|
(
|
|
85
88
|
content.includes('persona-panel persona-runtime" enable-xr') ||
|
|
86
89
|
content.includes('persona-button" onClick={openPersonaScene} enable-xr') ||
|
|
@@ -91,6 +94,7 @@ const LEGACY_WEBSPATIAL_TEMPLATE_FILE_RULES = [
|
|
|
91
94
|
{
|
|
92
95
|
relativePath: path.join('src', 'pages', 'ScenePage.tsx'),
|
|
93
96
|
shouldReplace: (content) =>
|
|
97
|
+
content.includes('sceneMode') ||
|
|
94
98
|
(
|
|
95
99
|
!content.includes('enable-xr-monitor') &&
|
|
96
100
|
content.includes(
|
|
@@ -103,14 +107,23 @@ const LEGACY_WEBSPATIAL_TEMPLATE_FILE_RULES = [
|
|
|
103
107
|
content.includes('Fork-backed proof points')
|
|
104
108
|
),
|
|
105
109
|
},
|
|
110
|
+
{
|
|
111
|
+
relativePath: path.join('src', 'index.css'),
|
|
112
|
+
shouldReplace: (content) =>
|
|
113
|
+
!content.includes('html.is-spatial #root') ||
|
|
114
|
+
content.includes('radial-gradient(circle at top, rgba(205, 183, 143, 0.32), transparent 36%)'),
|
|
115
|
+
},
|
|
106
116
|
{
|
|
107
117
|
relativePath: path.join('src', 'App.css'),
|
|
108
118
|
shouldReplace: (content) =>
|
|
119
|
+
content.includes('.persona-shell') ||
|
|
109
120
|
(content.includes('.scene-panel') && !content.includes('.scene-interaction-grid')) ||
|
|
110
121
|
content.includes('html.is-spatial .persona-runtime {') ||
|
|
111
122
|
content.includes('html.is-spatial .persona-scene-root {') ||
|
|
112
123
|
content.includes('html.is-spatial .persona-button,') ||
|
|
113
|
-
content.includes('html.is-spatial .persona-card,')
|
|
124
|
+
content.includes('html.is-spatial .persona-card,') ||
|
|
125
|
+
!content.includes('.scene-workspace-grid') ||
|
|
126
|
+
!content.includes('.home-grid'),
|
|
114
127
|
},
|
|
115
128
|
{
|
|
116
129
|
relativePath: 'vite.config.ts',
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oomi-ai",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Oomi
|
|
3
|
+
"version": "0.2.50",
|
|
4
|
+
"description": "Managed Oomi chat, voice bridge, and XR-first persona scaffolding for OpenClaw",
|
|
5
5
|
"bin": {
|
|
6
6
|
"oomi": "bin/oomi-ai.js"
|
|
7
7
|
},
|
|
@@ -29,14 +29,19 @@
|
|
|
29
29
|
"defaultChoice": "npm"
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
|
-
"keywords": [
|
|
33
|
-
"oomi",
|
|
34
|
-
"openclaw",
|
|
35
|
-
"cli",
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
"keywords": [
|
|
33
|
+
"oomi",
|
|
34
|
+
"openclaw",
|
|
35
|
+
"cli",
|
|
36
|
+
"plugin",
|
|
37
|
+
"voice",
|
|
38
|
+
"agent",
|
|
39
|
+
"persona",
|
|
40
|
+
"webspatial",
|
|
41
|
+
"xr",
|
|
42
|
+
"androidxr"
|
|
43
|
+
],
|
|
44
|
+
"homepage": "https://www.oomi.ai",
|
|
40
45
|
"repository": {
|
|
41
46
|
"type": "git",
|
|
42
47
|
"url": "git+https://github.com/crispcode-io/oomi.git",
|