oomi-ai 0.2.50 → 0.3.0

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 +203 -507
  2. package/agent_instructions.md +244 -253
  3. package/bin/oomi-ai.js +4026 -5795
  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 +133 -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 +27 -0
  13. package/persona-app/registry/v1.json +63 -0
  14. package/persona-app/schema/persona-app.v1.schema.json +90 -0
  15. package/skills/oomi/SKILL.md +165 -182
  16. package/skills/oomi/agent_instructions.md +99 -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
@@ -7,66 +7,66 @@ const ELLIPSIS_PLACEHOLDER = '__OOMI_ELLIPSIS__';
7
7
  function stripAvatarCommandTags(text) {
8
8
  return text.replace(/\[(anim|animation|face|expression|emotion|gesture|look|gaze):[^\]]+\]/gi, ' ');
9
9
  }
10
-
11
- function clampInteger(value, fallback, { min = 1, max = Number.MAX_SAFE_INTEGER } = {}) {
12
- if (typeof value !== 'number' || !Number.isFinite(value)) return fallback;
13
- const normalized = Math.floor(value);
14
- if (normalized < min) return fallback;
15
- if (normalized > max) return max;
16
- return normalized;
17
- }
18
-
19
- const BOUNDED_LANGUAGE_TYPES = new Set([
20
- 'Auto',
21
- 'Chinese',
22
- 'English',
23
- 'German',
24
- 'Italian',
25
- 'Portuguese',
26
- 'Spanish',
27
- 'Japanese',
28
- 'Korean',
29
- 'French',
30
- 'Russian',
31
- ]);
32
-
33
- const BOUNDED_PACE_VALUES = new Set(['very_slow', 'slow', 'medium', 'medium_fast', 'fast']);
34
- const BOUNDED_PITCH_VALUES = new Set(['low', 'slightly_low', 'neutral', 'slightly_high', 'high']);
35
- const BOUNDED_ENERGY_VALUES = new Set(['soft', 'calm', 'warm', 'bright', 'intense']);
36
- const BOUNDED_VOLUME_VALUES = new Set(['soft', 'normal', 'projected']);
37
-
38
- function inferSpokenLanguage(text) {
39
- const normalized = trimString(text);
40
- if (!normalized) return 'English';
41
- return 'English';
42
- }
43
-
10
+
11
+ function clampInteger(value, fallback, { min = 1, max = Number.MAX_SAFE_INTEGER } = {}) {
12
+ if (typeof value !== 'number' || !Number.isFinite(value)) return fallback;
13
+ const normalized = Math.floor(value);
14
+ if (normalized < min) return fallback;
15
+ if (normalized > max) return max;
16
+ return normalized;
17
+ }
18
+
19
+ const BOUNDED_LANGUAGE_TYPES = new Set([
20
+ 'Auto',
21
+ 'Chinese',
22
+ 'English',
23
+ 'German',
24
+ 'Italian',
25
+ 'Portuguese',
26
+ 'Spanish',
27
+ 'Japanese',
28
+ 'Korean',
29
+ 'French',
30
+ 'Russian',
31
+ ]);
32
+
33
+ const BOUNDED_PACE_VALUES = new Set(['very_slow', 'slow', 'medium', 'medium_fast', 'fast']);
34
+ const BOUNDED_PITCH_VALUES = new Set(['low', 'slightly_low', 'neutral', 'slightly_high', 'high']);
35
+ const BOUNDED_ENERGY_VALUES = new Set(['soft', 'calm', 'warm', 'bright', 'intense']);
36
+ const BOUNDED_VOLUME_VALUES = new Set(['soft', 'normal', 'projected']);
37
+
38
+ function inferSpokenLanguage(text) {
39
+ const normalized = trimString(text);
40
+ if (!normalized) return 'English';
41
+ return 'English';
42
+ }
43
+
44
44
  function normalizeSpokenSegment(segment) {
45
45
  if (!segment || typeof segment !== 'object' || Array.isArray(segment)) return null;
46
46
 
47
47
  const text = normalizeSpeechText(trimString(segment.text));
48
48
  if (!text) return null;
49
-
50
- const normalized = { text };
51
- const pace = trimString(segment.pace);
52
- const pitch = trimString(segment.pitch);
53
- const energy = trimString(segment.energy);
54
- const volume = trimString(segment.volume);
55
- const pauseAfterMs = clampInteger(segment.pause_after_ms, 0, { min: 0, max: 1200 });
56
-
57
- if (BOUNDED_PACE_VALUES.has(pace)) normalized.pace = pace;
58
- if (BOUNDED_PITCH_VALUES.has(pitch)) normalized.pitch = pitch;
59
- if (BOUNDED_ENERGY_VALUES.has(energy)) normalized.energy = energy;
60
- if (BOUNDED_VOLUME_VALUES.has(volume)) normalized.volume = volume;
61
- normalized.pause_after_ms = pauseAfterMs;
62
-
63
- return normalized;
64
- }
65
-
66
- function stripEmoji(text) {
67
- return text.replace(/[\uFE0E\uFE0F]/g, '').replace(/\p{Extended_Pictographic}|\p{Emoji_Presentation}/gu, '');
68
- }
69
-
49
+
50
+ const normalized = { text };
51
+ const pace = trimString(segment.pace);
52
+ const pitch = trimString(segment.pitch);
53
+ const energy = trimString(segment.energy);
54
+ const volume = trimString(segment.volume);
55
+ const pauseAfterMs = clampInteger(segment.pause_after_ms, 0, { min: 0, max: 1200 });
56
+
57
+ if (BOUNDED_PACE_VALUES.has(pace)) normalized.pace = pace;
58
+ if (BOUNDED_PITCH_VALUES.has(pitch)) normalized.pitch = pitch;
59
+ if (BOUNDED_ENERGY_VALUES.has(energy)) normalized.energy = energy;
60
+ if (BOUNDED_VOLUME_VALUES.has(volume)) normalized.volume = volume;
61
+ normalized.pause_after_ms = pauseAfterMs;
62
+
63
+ return normalized;
64
+ }
65
+
66
+ function stripEmoji(text) {
67
+ return text.replace(/[\uFE0E\uFE0F]/g, '').replace(/\p{Extended_Pictographic}|\p{Emoji_Presentation}/gu, '');
68
+ }
69
+
70
70
  function normalizeSpeechText(text) {
71
71
  return stripEmoji(stripAvatarCommandTags(text))
72
72
  .replace(/\*\*(.*?)\*\*/g, '$1')
@@ -85,7 +85,7 @@ function normalizeSpeechText(text) {
85
85
  .replace(/\s+/g, ' ')
86
86
  .trim();
87
87
  }
88
-
88
+
89
89
  function splitSpeechSegments(text) {
90
90
  const normalized = normalizeSpeechText(text);
91
91
  if (!normalized) return [];
@@ -94,14 +94,14 @@ function splitSpeechSegments(text) {
94
94
  .split(/(?<=[.!?])\s+|\n+/)
95
95
  .map((segment) => segment.trim())
96
96
  .filter(Boolean);
97
-
98
- const segments = [];
99
- for (const segment of baseSegments) {
100
- if (segment.length <= 96) {
101
- segments.push(segment);
102
- continue;
103
- }
104
-
97
+
98
+ const segments = [];
99
+ for (const segment of baseSegments) {
100
+ if (segment.length <= 96) {
101
+ segments.push(segment);
102
+ continue;
103
+ }
104
+
105
105
  const clauseParts = segment
106
106
  .split(/(?<=[,;:])\s+/)
107
107
  .map((part) => part.trim())
@@ -113,15 +113,15 @@ function splitSpeechSegments(text) {
113
113
  }
114
114
  continue;
115
115
  }
116
-
117
- segments.push(segment);
118
- }
119
-
120
- if (segments.length <= 5) return segments;
121
-
122
- return [...segments.slice(0, 4), segments.slice(4).join(' ').trim()];
123
- }
124
-
116
+
117
+ segments.push(segment);
118
+ }
119
+
120
+ if (segments.length <= 5) return segments;
121
+
122
+ return [...segments.slice(0, 4), segments.slice(4).join(' ').trim()];
123
+ }
124
+
125
125
  function inferSegmentStyle(segmentText, index, totalSegments) {
126
126
  const normalized = segmentText.toLowerCase();
127
127
  const greeting = /^(hey|hi|hello|yo)\b/.test(normalized);
@@ -151,9 +151,9 @@ function inferSegmentStyle(segmentText, index, totalSegments) {
151
151
  pause_after_ms: 0,
152
152
  };
153
153
  }
154
-
155
- if (exclamatory) {
156
- return {
154
+
155
+ if (exclamatory) {
156
+ return {
157
157
  pace: 'medium_fast',
158
158
  pitch: 'slightly_high',
159
159
  energy: 'bright',
@@ -178,75 +178,75 @@ function inferSegmentStyle(segmentText, index, totalSegments) {
178
178
  energy: 'warm',
179
179
  volume: 'normal',
180
180
  pause_after_ms: index < totalSegments - 1 ? 180 : 0,
181
- };
182
- }
183
-
184
- function synthesizeSpokenSegments(text) {
185
- const language = inferSpokenLanguage(text);
186
- const rawSegments = splitSpeechSegments(text);
187
- if (rawSegments.length === 0) return null;
188
-
189
- const segments = rawSegments.map((segmentText, index) => ({
190
- text: segmentText,
191
- ...inferSegmentStyle(segmentText, index, rawSegments.length),
192
- }));
193
-
194
- return {
195
- language,
196
- segments,
197
- };
198
- }
199
-
181
+ };
182
+ }
183
+
184
+ function synthesizeSpokenSegments(text) {
185
+ const language = inferSpokenLanguage(text);
186
+ const rawSegments = splitSpeechSegments(text);
187
+ if (rawSegments.length === 0) return null;
188
+
189
+ const segments = rawSegments.map((segmentText, index) => ({
190
+ text: segmentText,
191
+ ...inferSegmentStyle(segmentText, index, rawSegments.length),
192
+ }));
193
+
194
+ return {
195
+ language,
196
+ segments,
197
+ };
198
+ }
199
+
200
200
  function normalizeSpokenMetadata(spoken) {
201
201
  if (!spoken || typeof spoken !== 'object' || Array.isArray(spoken)) return null;
202
202
 
203
203
  const text = normalizeSpeechText(trimString(spoken.text));
204
204
  if (!text) return null;
205
-
206
- const normalized = { text };
207
- const language = trimString(spoken.language);
208
- if (BOUNDED_LANGUAGE_TYPES.has(language)) {
209
- normalized.language = language;
210
- }
211
-
212
- const explicitSegments =
213
- Array.isArray(spoken.segments)
214
- ? spoken.segments.map((segment) => normalizeSpokenSegment(segment)).filter(Boolean)
215
- : [];
216
- if (explicitSegments.length > 0) {
217
- normalized.segments = explicitSegments;
218
- }
219
-
220
- const instructions = trimString(spoken.instructions);
221
- if (instructions) normalized.instructions = instructions;
222
- if (spoken.style && typeof spoken.style === 'object' && !Array.isArray(spoken.style)) {
223
- normalized.style = spoken.style;
224
- }
225
-
226
- const fallbackSegments = synthesizeSpokenSegments(text);
227
- if (!normalized.language && fallbackSegments?.language) {
228
- normalized.language = fallbackSegments.language;
229
- }
230
- if (!normalized.segments && fallbackSegments?.segments?.length) {
231
- normalized.segments = fallbackSegments.segments;
232
- }
233
-
234
- return normalized;
235
- }
236
-
205
+
206
+ const normalized = { text };
207
+ const language = trimString(spoken.language);
208
+ if (BOUNDED_LANGUAGE_TYPES.has(language)) {
209
+ normalized.language = language;
210
+ }
211
+
212
+ const explicitSegments =
213
+ Array.isArray(spoken.segments)
214
+ ? spoken.segments.map((segment) => normalizeSpokenSegment(segment)).filter(Boolean)
215
+ : [];
216
+ if (explicitSegments.length > 0) {
217
+ normalized.segments = explicitSegments;
218
+ }
219
+
220
+ const instructions = trimString(spoken.instructions);
221
+ if (instructions) normalized.instructions = instructions;
222
+ if (spoken.style && typeof spoken.style === 'object' && !Array.isArray(spoken.style)) {
223
+ normalized.style = spoken.style;
224
+ }
225
+
226
+ const fallbackSegments = synthesizeSpokenSegments(text);
227
+ if (!normalized.language && fallbackSegments?.language) {
228
+ normalized.language = fallbackSegments.language;
229
+ }
230
+ if (!normalized.segments && fallbackSegments?.segments?.length) {
231
+ normalized.segments = fallbackSegments.segments;
232
+ }
233
+
234
+ return normalized;
235
+ }
236
+
237
237
  function inferSpokenMetadataFromContent(content) {
238
238
  const text = normalizeSpeechText(trimString(content));
239
239
  if (!text) return null;
240
240
  const synthesized = synthesizeSpokenSegments(text);
241
-
242
- const normalized = text.toLowerCase();
243
- const upbeat =
244
- /!/.test(text) ||
245
- /\b(hell yeah|awesome|amazing|great|stoked|love|glad|perfect|nice|cool)\b/.test(normalized);
246
- const gentle =
247
- /\b(sorry|gentle|softly|careful|reassuring|calm|okay|it'?s okay|i know)\b/.test(normalized);
248
- const curious = /\?/.test(text);
249
-
241
+
242
+ const normalized = text.toLowerCase();
243
+ const upbeat =
244
+ /!/.test(text) ||
245
+ /\b(hell yeah|awesome|amazing|great|stoked|love|glad|perfect|nice|cool)\b/.test(normalized);
246
+ const gentle =
247
+ /\b(sorry|gentle|softly|careful|reassuring|calm|okay|it'?s okay|i know)\b/.test(normalized);
248
+ const curious = /\?/.test(text);
249
+
250
250
  if (upbeat) {
251
251
  return normalizeSpokenMetadata({
252
252
  text,
@@ -285,7 +285,7 @@ function inferSpokenMetadataFromContent(content) {
285
285
  style: { emotion: 'neutral', energy: 'medium' },
286
286
  });
287
287
  }
288
-
288
+
289
289
  export {
290
290
  inferSpokenMetadataFromContent,
291
291
  normalizeSpokenMetadata,