oomi-ai 0.2.38 → 0.2.40

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 (49) hide show
  1. package/README.md +24 -14
  2. package/agent_instructions.md +9 -0
  3. package/bin/oomi-ai.js +1 -1
  4. package/lib/openclawPaths.js +27 -18
  5. package/lib/personaRuntimeManager.js +181 -61
  6. package/lib/personaRuntimeProcess.js +392 -49
  7. package/lib/personaRuntimeSupervisor.js +20 -7
  8. package/lib/scaffold.js +14 -14
  9. package/openclaw.plugin.json +1 -1
  10. package/package.json +10 -8
  11. package/templates/persona-app/package.json +6 -4
  12. package/templates/persona-app/src/App.css +564 -79
  13. package/templates/persona-app/src/App.tsx +2 -2
  14. package/templates/persona-app/src/main.tsx +13 -0
  15. package/templates/persona-app/src/pages/HomePage.tsx +120 -39
  16. package/templates/persona-app/src/pages/ScenePage.tsx +2 -15
  17. package/templates/persona-app/src/persona/notes.ts +3 -1
  18. package/templates/persona-app/src/spatial.ts +82 -0
  19. package/templates/persona-app/template.json +1 -1
  20. package/templates/persona-app/vendor/webspatial/FORK.md +6 -0
  21. package/templates/persona-app/vendor/webspatial/core-sdk/LICENSE +21 -0
  22. package/templates/persona-app/vendor/webspatial/core-sdk/dist/iife/index.d.ts +906 -0
  23. package/templates/persona-app/vendor/webspatial/core-sdk/dist/iife/index.global.js +75 -0
  24. package/templates/persona-app/vendor/webspatial/core-sdk/dist/iife/index.global.js.map +1 -0
  25. package/templates/persona-app/vendor/webspatial/core-sdk/dist/index.d.ts +906 -0
  26. package/templates/persona-app/vendor/webspatial/core-sdk/dist/index.js +3131 -0
  27. package/templates/persona-app/vendor/webspatial/core-sdk/dist/index.js.map +1 -0
  28. package/templates/persona-app/vendor/webspatial/core-sdk/package.json +45 -0
  29. package/templates/persona-app/vendor/webspatial/react-sdk/LICENSE +21 -0
  30. package/templates/persona-app/vendor/webspatial/react-sdk/dist/default/index.d.ts +365 -0
  31. package/templates/persona-app/vendor/webspatial/react-sdk/dist/default/index.js +4296 -0
  32. package/templates/persona-app/vendor/webspatial/react-sdk/dist/default/index.js.map +1 -0
  33. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.d.ts +82 -0
  34. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.js +66 -0
  35. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.js.map +1 -0
  36. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.web.d.ts +2 -0
  37. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.web.js +18 -0
  38. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.web.js.map +1 -0
  39. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.d.ts +5 -0
  40. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.js +66 -0
  41. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.js.map +1 -0
  42. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.web.d.ts +1 -0
  43. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.web.js +18 -0
  44. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.web.js.map +1 -0
  45. package/templates/persona-app/vendor/webspatial/react-sdk/dist/web/index.d.ts +365 -0
  46. package/templates/persona-app/vendor/webspatial/react-sdk/dist/web/index.js +4336 -0
  47. package/templates/persona-app/vendor/webspatial/react-sdk/dist/web/index.js.map +1 -0
  48. package/templates/persona-app/vendor/webspatial/react-sdk/package.json +94 -0
  49. package/templates/persona-app/vite.config.ts +13 -0
@@ -6,8 +6,8 @@ export default function App() {
6
6
  return (
7
7
  <Router basename={__XR_ENV_BASE__}>
8
8
  <Routes>
9
- <Route path="/" element={<HomePage />} />
10
- <Route path="/scene" element={<ScenePage />} />
9
+ <Route index element={<HomePage />} />
10
+ <Route path="scene" element={<ScenePage />} />
11
11
  </Routes>
12
12
  </Router>
13
13
  );
@@ -1,8 +1,21 @@
1
1
  import { StrictMode } from "react";
2
2
  import { createRoot } from "react-dom/client";
3
+ import { snapdom } from "@zumer/snapdom";
4
+ import html2canvas from "html2canvas";
3
5
  import "./index.css";
4
6
  import App from "./App";
5
7
 
8
+ // WebSpatial AndroidXR uses DOM capture to turn enable-xr surfaces into native panels.
9
+ // Expose both libraries globally so the SDK can pick the fast path when available.
10
+ (window as Window & {
11
+ snapdom?: typeof snapdom;
12
+ html2canvas?: typeof html2canvas;
13
+ }).snapdom = snapdom;
14
+ (window as Window & {
15
+ snapdom?: typeof snapdom;
16
+ html2canvas?: typeof html2canvas;
17
+ }).html2canvas = html2canvas;
18
+
6
19
  createRoot(document.getElementById("root")!).render(
7
20
  <StrictMode>
8
21
  <App />
@@ -1,70 +1,151 @@
1
- import { initScene } from "@webspatial/react-sdk";
1
+ import { useEffect } from "react";
2
2
  import { Link } from "react-router-dom";
3
3
  import "../App.css";
4
4
  import { personaConfig } from "../persona/config";
5
5
  import { personaNotes } from "../persona/notes";
6
+ import {
7
+ WEBSPATIAL_FORK_COMMIT,
8
+ configurePersonaScene,
9
+ detectSpatialEnvironment,
10
+ openPersonaScene,
11
+ xrStyle,
12
+ } from "../spatial";
6
13
 
7
- export function HomePage() {
8
- const openSpatialScene = () => {
9
- initScene("personaScene", prevConfig => ({
10
- ...prevConfig,
11
- defaultSize: {
12
- width: 720,
13
- height: 720,
14
- },
15
- }));
16
- window.open(`${__XR_ENV_BASE__}/scene`, "personaScene");
17
- };
14
+ const previewCards = [
15
+ {
16
+ tone: "ocean",
17
+ title: "Focused surface",
18
+ body: "Use the persona site as a real operator board, planner, studio, or dashboard instead of another chat clone.",
19
+ depth: 34,
20
+ material: "translucent",
21
+ },
22
+ {
23
+ tone: "coral",
24
+ title: "Depth-authored cards",
25
+ body: "Key controls should declare their own depth and material so AndroidXR reads them as layered surfaces.",
26
+ depth: 84,
27
+ material: "thin",
28
+ },
29
+ {
30
+ tone: "violet",
31
+ title: "Persistent handoff",
32
+ body: "Let Oomi keep the live conversation thread while the persona page stays focused on structured work.",
33
+ depth: 140,
34
+ material: "thick",
35
+ },
36
+ ];
37
+
38
+ type HomePageProps = {
39
+ sceneMode?: boolean;
40
+ };
41
+
42
+ export function HomePage({ sceneMode = false }: HomePageProps) {
43
+ const environment = detectSpatialEnvironment();
44
+
45
+ useEffect(() => {
46
+ configurePersonaScene();
47
+ }, []);
18
48
 
19
49
  return (
20
- <main className="persona-shell">
50
+ <main className="persona-shell" enable-xr-monitor={sceneMode || undefined}>
21
51
  <section className="persona-header">
22
- <div className="persona-panel persona-hero">
23
- <p className="persona-eyebrow">WebSpatial Persona</p>
24
- <h1 className="persona-title">{personaConfig.name}</h1>
25
- <p className="persona-description">{personaConfig.description}</p>
52
+ <div className="persona-panel persona-hero" enable-xr style={xrStyle(22, "translucent")}>
53
+ <div>
54
+ <p className="persona-eyebrow">{sceneMode ? "Spatial Persona Surface" : "WebSpatial Persona"}</p>
55
+ <h1 className="persona-title">{personaConfig.name}</h1>
56
+ <p className="persona-description">{personaConfig.description}</p>
57
+ </div>
26
58
 
27
59
  <div className="persona-actions">
28
- <button className="persona-button" onClick={openSpatialScene} enable-xr>
29
- Open Spatial Scene
30
- </button>
31
- <Link className="persona-link" to="/scene" target="_blank" enable-xr>
32
- Open Scene Route
33
- </Link>
60
+ {!sceneMode ? (
61
+ <>
62
+ <button className="persona-button" onClick={openPersonaScene} enable-xr style={xrStyle(52, "regular")}>
63
+ Launch Spatial Surface
64
+ </button>
65
+ <Link className="persona-link" to="/scene" target="_blank" enable-xr style={xrStyle(92, "thin")}>
66
+ Open Spatial Preview
67
+ </Link>
68
+ </>
69
+ ) : (
70
+ <Link className="persona-button" to="/" enable-xr style={xrStyle(52, "regular")}>
71
+ Return To Browser View
72
+ </Link>
73
+ )}
74
+ </div>
75
+
76
+ <div className="persona-preview-strip">
77
+ {previewCards.map(card => (
78
+ <article
79
+ key={card.title}
80
+ className="persona-preview-card"
81
+ data-tone={card.tone}
82
+ enable-xr
83
+ style={xrStyle(card.depth, card.material)}
84
+ >
85
+ <h3>{card.title}</h3>
86
+ <p>{card.body}</p>
87
+ </article>
88
+ ))}
34
89
  </div>
35
90
  </div>
36
91
 
37
- <aside className="persona-panel persona-runtime">
92
+ <aside className="persona-panel persona-runtime" enable-xr style={xrStyle(72, "thin")}>
38
93
  <p className="persona-eyebrow">Runtime</p>
39
94
  <div className="runtime-list">
40
- <div>Slug: {personaConfig.slug}</div>
41
- <div>Template: {personaConfig.templateVersion}</div>
42
- <div>Engine: WebSpatial + React + Vite</div>
43
- <div>Mode: local/private</div>
95
+ <div className="runtime-row">
96
+ <span className="runtime-label">Slug</span>
97
+ <span className="runtime-value">{personaConfig.slug}</span>
98
+ </div>
99
+ <div className="runtime-row">
100
+ <span className="runtime-label">SDK</span>
101
+ <span className="runtime-value">@webspatial/react-sdk {environment.sdkVersion}</span>
102
+ </div>
103
+ <div className="runtime-row">
104
+ <span className="runtime-label">Bridge</span>
105
+ <span className="runtime-value">{environment.hasBridge ? "available" : "waiting"}</span>
106
+ </div>
107
+ <div className="runtime-row">
108
+ <span className="runtime-label">Native</span>
109
+ <span className="runtime-value">{environment.nativeVersion ?? "browser fallback"}</span>
110
+ </div>
111
+ <div className="runtime-row">
112
+ <span className="runtime-label">Fork</span>
113
+ <span className="runtime-value">{WEBSPATIAL_FORK_COMMIT.slice(0, 7)}</span>
114
+ </div>
44
115
  </div>
45
116
  </aside>
46
117
  </section>
47
118
 
48
119
  <section className="persona-grid">
49
- <article className="persona-panel persona-card">
50
- <h2>Editable Persona Notes</h2>
120
+ <article className="persona-panel persona-card" enable-xr style={xrStyle(34, "translucent")}>
121
+ <h2>What Good XR Feels Like</h2>
122
+ <p>
123
+ Treat the generated persona site like a spatial work surface. The XR route should keep
124
+ the actual persona shell intact, then layer depth, materials, and anchored surfaces on
125
+ top instead of swapping in a disconnected demo board.
126
+ </p>
51
127
  <p>
52
- This scaffold follows the WebSpatial quick-example structure so the app can render
53
- well in both the browser and future XR clients. Keep persona-specific logic in
54
- <code> src/persona/</code>.
128
+ {sceneMode
129
+ ? "This route is the AndroidXR work surface. It should feel like the same persona site, just spatialized."
130
+ : "This home route exists for browser parity and one-click launch into the spatial work surface."}
55
131
  </p>
56
- <ul>
132
+ </article>
133
+
134
+ <article className="persona-panel persona-card" enable-xr style={xrStyle(74, "thin")}>
135
+ <h2>Editing Notes</h2>
136
+ <ul className="persona-note-list">
57
137
  {personaNotes.map(note => (
58
138
  <li key={note}>{note}</li>
59
139
  ))}
60
140
  </ul>
61
141
  </article>
62
142
 
63
- <article className="persona-panel persona-card persona-scene-card" enable-xr>
64
- <h2>Scene Surface</h2>
65
- <p enable-xr>
66
- Use this card as the main spatial handoff. It already uses WebSpatial router
67
- basenames, scene launching, and `enable-xr` affordances taken from the quick example.
143
+ <article className="persona-panel persona-card persona-scene-card" enable-xr style={xrStyle(118, "regular")}>
144
+ <h2>Scene Contract</h2>
145
+ <p>
146
+ The page should import WebSpatial helpers, self-configure the scene, and keep using
147
+ explicit <code>enable-xr</code>, <code>--xr-back</code>, and
148
+ <code> --xr-background-material</code> values on important surfaces.
68
149
  </p>
69
150
  </article>
70
151
  </section>
@@ -1,18 +1,5 @@
1
- import "../App.css";
2
- import { personaConfig } from "../persona/config";
1
+ import { HomePage } from "./HomePage";
3
2
 
4
3
  export function ScenePage() {
5
- return (
6
- <main className="scene-shell">
7
- <section className="persona-panel scene-panel">
8
- <p className="persona-eyebrow">Scene</p>
9
- <h1>{personaConfig.name}</h1>
10
- <p>{personaConfig.description}</p>
11
- <p>
12
- This route is intentionally separate so WebSpatial scene launching has a dedicated
13
- surface. Extend this page with persona-specific spatial UI.
14
- </p>
15
- </section>
16
- </main>
17
- );
4
+ return <HomePage sceneMode />;
18
5
  }
@@ -1,5 +1,7 @@
1
1
  export const personaNotes = [
2
2
  "Keep persona-specific logic inside src/persona/ unless Oomi explicitly instructs otherwise.",
3
- "Preserve the WebSpatial router basename and scene-launch flow.",
3
+ "Preserve the WebSpatial router basename, the scene self-init helper, and the scene-launch flow.",
4
+ "Keep using the vendored AndroidXR-enabled WebSpatial fork instead of switching back to the stock npm packages.",
5
+ "Author key surfaces with explicit enable-xr, --xr-back, and --xr-background-material values so the page reads as spatial instead of flat.",
4
6
  "Do not remove public/oomi.runtime.json, public/oomi.health.json, or public/manifest.webmanifest.",
5
7
  ];
@@ -0,0 +1,82 @@
1
+ import type { CSSProperties } from "react";
2
+ import { initScene, version as webSpatialSdkVersion } from "@webspatial/react-sdk";
3
+
4
+ export const PERSONA_SCENE_NAME = "personaScene";
5
+ export const WEBSPATIAL_FORK_REPOSITORY = "https://github.com/zill4/webspatial-sdk";
6
+ export const WEBSPATIAL_FORK_COMMIT = "b2746721e4fe6b4f86dac0ea55938074eea00cda";
7
+
8
+ type SpatialWindow = Window & {
9
+ webspatialBridge?: unknown;
10
+ __WebSpatialData?: {
11
+ getNativeVersion?: () => string;
12
+ };
13
+ };
14
+
15
+ export type SpatialEnvironmentSnapshot = {
16
+ isWebSpatial: boolean;
17
+ sdkVersion: string;
18
+ nativeVersion: string | null;
19
+ hasBridge: boolean;
20
+ hasWebSpatialData: boolean;
21
+ };
22
+
23
+ export type XrStyle = CSSProperties & {
24
+ "--xr-back"?: number | string;
25
+ "--xr-background-material"?: string;
26
+ };
27
+
28
+ export function xrStyle(back: number, material: string): XrStyle {
29
+ return {
30
+ "--xr-back": `${back}px`,
31
+ "--xr-background-material": material,
32
+ };
33
+ }
34
+
35
+ export function detectSpatialEnvironment(): SpatialEnvironmentSnapshot {
36
+ const typedWindow = window as SpatialWindow;
37
+ const userAgent = navigator.userAgent;
38
+ const userAgentVersion = userAgent.match(/WebSpatial\/([\d.]+)/)?.[1] ?? null;
39
+ const nativeVersion = (() => {
40
+ try {
41
+ return typedWindow.__WebSpatialData?.getNativeVersion?.() ?? userAgentVersion;
42
+ } catch {
43
+ return userAgentVersion;
44
+ }
45
+ })();
46
+
47
+ return {
48
+ isWebSpatial: userAgent.includes("WebSpatial/"),
49
+ sdkVersion: webSpatialSdkVersion,
50
+ nativeVersion,
51
+ hasBridge: typeof typedWindow.webspatialBridge !== "undefined",
52
+ hasWebSpatialData: typeof typedWindow.__WebSpatialData !== "undefined",
53
+ };
54
+ }
55
+
56
+ export function configurePersonaScene() {
57
+ initScene(
58
+ PERSONA_SCENE_NAME,
59
+ previous => ({
60
+ ...previous,
61
+ defaultSize: {
62
+ width: 1440,
63
+ height: 960,
64
+ },
65
+ resizability: {
66
+ minWidth: 960,
67
+ minHeight: 720,
68
+ maxWidth: 1800,
69
+ maxHeight: 1280,
70
+ },
71
+ worldAlignment: "gravityAligned",
72
+ worldScaling: "automatic",
73
+ baseplateVisibility: "hidden",
74
+ }),
75
+ { type: "window" },
76
+ );
77
+ }
78
+
79
+ export function openPersonaScene() {
80
+ configurePersonaScene();
81
+ window.open(`${__XR_ENV_BASE__}/scene`, PERSONA_SCENE_NAME);
82
+ }
@@ -5,7 +5,7 @@
5
5
  "appKind": "oomi-persona-app",
6
6
  "defaultPort": 4789,
7
7
  "healthPath": "/oomi.health.json",
8
- "startCommand": "npm run dev",
8
+ "startCommand": "npm run dev:avp",
9
9
  "editableZones": [
10
10
  "src/persona",
11
11
  "persona"
@@ -0,0 +1,6 @@
1
+ This persona template vendors the AndroidXR-capable WebSpatial runtime packages from:
2
+
3
+ - Repository: https://github.com/zill4/webspatial-sdk
4
+ - Commit: 8904ac8fec48fe49ee14d1739237bd1afb2894fe
5
+
6
+ Oomi uses these vendored packages for persona runtimes so OpenClaw installs the AndroidXR-enabled fork instead of the stock npm release.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Spatial Web
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.