oomi-ai 0.2.18 → 0.2.19
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 +10 -2
- package/agent_instructions.md +7 -0
- package/bin/oomi-ai.js +60 -6
- package/lib/personaApiClient.js +32 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,8 +4,9 @@ OpenClaw channel plugin and bridge tooling for Oomi managed chat and voice.
|
|
|
4
4
|
|
|
5
5
|
## Current Focus
|
|
6
6
|
|
|
7
|
-
`0.2.
|
|
7
|
+
`0.2.19` adds the first live persona automation lane:
|
|
8
8
|
- WebSpatial-based persona scaffolding for generated Oomi apps
|
|
9
|
+
- a high-level `oomi personas create-managed` command for agent-driven persona creation
|
|
9
10
|
- device-authenticated persona runtime registration and job callbacks
|
|
10
11
|
- automatic bridge-side polling for queued `persona_job` control messages
|
|
11
12
|
- end-to-end local persona startup from a structured orchestration payload
|
|
@@ -153,6 +154,7 @@ oomi personas scaffold market-analyst --name "Market Analyst" --description "Pri
|
|
|
153
154
|
|
|
154
155
|
Use:
|
|
155
156
|
- `oomi personas create <id>` for repo-local manifest work
|
|
157
|
+
- `oomi personas create-managed --name "Cooking Persona" --description "Private cooking workspace"` for the end-to-end Oomi-managed persona flow
|
|
156
158
|
- `oomi personas scaffold <slug>` for a WebSpatial-based Oomi app shell with runtime metadata and health documents
|
|
157
159
|
- `oomi persona-jobs execute --message-file <job.json>` when OpenClaw receives a structured persona orchestration job from Oomi
|
|
158
160
|
|
|
@@ -166,7 +168,13 @@ oomi persona-jobs succeed pj_123 --workspace-path ~/.openclaw/personas/market-an
|
|
|
166
168
|
oomi persona-jobs fail pj_123 --code JOB_FAILED --message "Scaffold generation failed."
|
|
167
169
|
```
|
|
168
170
|
|
|
169
|
-
|
|
171
|
+
Recommended agent flow:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
oomi personas create-managed --name "Cooking Persona" --description "Private cooking workspace for recipes, meal planning, and kitchen notes."
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
That command creates the managed persona record in Oomi using the linked device identity. The backend then enqueues the `persona_job`, and the running bridge consumes that job automatically. The poll path is filtered to `metadata.type = persona_job`, so it does not consume normal queued chat traffic.
|
|
170
178
|
|
|
171
179
|
## Bridge Health States
|
|
172
180
|
|
package/agent_instructions.md
CHANGED
|
@@ -194,6 +194,13 @@ Aliases allowed if needed:
|
|
|
194
194
|
|
|
195
195
|
## Persona App Generation
|
|
196
196
|
|
|
197
|
+
When a user asks you in chat to create a new persona for Oomi:
|
|
198
|
+
|
|
199
|
+
1. Prefer `oomi personas create-managed --name "<name>" --description "<description>"`.
|
|
200
|
+
2. That is the primary end-to-end command for agent-driven persona creation.
|
|
201
|
+
3. It creates the managed persona record in Oomi and relies on the running bridge to consume the queued `persona_job` automatically.
|
|
202
|
+
4. Do not manually scaffold first unless you are recovering a failed persona job or working outside the queued Oomi flow.
|
|
203
|
+
|
|
197
204
|
When generating a managed persona app for Oomi:
|
|
198
205
|
|
|
199
206
|
1. Do not build the app shell from scratch.
|
package/bin/oomi-ai.js
CHANGED
|
@@ -190,6 +190,8 @@ Commands:
|
|
|
190
190
|
|
|
191
191
|
personas create <id>
|
|
192
192
|
Create a new persona manifest and optionally sync it to the backend.
|
|
193
|
+
personas create-managed [slug]
|
|
194
|
+
Create a managed persona in Oomi and enqueue its build job for the linked device.
|
|
193
195
|
personas scaffold <slug>
|
|
194
196
|
Create an Oomi-managed persona app scaffold for agent customization.
|
|
195
197
|
personas runtime-register <slug>
|
|
@@ -225,9 +227,10 @@ Common flags:
|
|
|
225
227
|
--json Print pairing result as JSON (for automation)
|
|
226
228
|
--backend-url URL Override Oomi backend URL
|
|
227
229
|
--root PATH Override repo root path for persona discovery
|
|
228
|
-
--name NAME Persona display name (for create)
|
|
229
|
-
--description TEXT Persona description (for scaffold)
|
|
230
|
-
--
|
|
230
|
+
--name NAME Persona display name (for create)
|
|
231
|
+
--description TEXT Persona description (for scaffold)
|
|
232
|
+
--slug SLUG Explicit slug override (for create-managed)
|
|
233
|
+
--summary TEXT Persona summary (for create)
|
|
231
234
|
--status STATUS Persona status (for create)
|
|
232
235
|
--type TYPE Persona type (for create)
|
|
233
236
|
--tags a,b,c Persona tags (for create)
|
|
@@ -595,6 +598,32 @@ function printPersonaScaffoldResult(result, asJson = false) {
|
|
|
595
598
|
}
|
|
596
599
|
}
|
|
597
600
|
|
|
601
|
+
function printManagedPersonaCreateResult(result, asJson = false) {
|
|
602
|
+
if (asJson) {
|
|
603
|
+
console.log(JSON.stringify(result, null, 2));
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
const persona = result?.persona && typeof result.persona === 'object' ? result.persona : {};
|
|
608
|
+
const personaJob = result?.personaJob && typeof result.personaJob === 'object' ? result.personaJob : {};
|
|
609
|
+
console.log(`Managed persona created: ${String(persona.name || persona.slug || 'unknown')}`);
|
|
610
|
+
if (persona.slug) {
|
|
611
|
+
console.log(`Slug: ${persona.slug}`);
|
|
612
|
+
}
|
|
613
|
+
if (persona.lifecycle) {
|
|
614
|
+
console.log(`Lifecycle: ${persona.lifecycle}`);
|
|
615
|
+
}
|
|
616
|
+
if (personaJob.jobId) {
|
|
617
|
+
console.log(`Persona job: ${personaJob.jobId}`);
|
|
618
|
+
}
|
|
619
|
+
if (personaJob.status) {
|
|
620
|
+
console.log(`Job status: ${personaJob.status}`);
|
|
621
|
+
}
|
|
622
|
+
if (personaJob.deviceId) {
|
|
623
|
+
console.log(`Assigned device: ${personaJob.deviceId}`);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
598
627
|
function parseOptionalPositiveInteger(value) {
|
|
599
628
|
if (value === undefined || value === null || value === '') return null;
|
|
600
629
|
const parsed = Number(value);
|
|
@@ -932,6 +961,26 @@ async function handlePersonaJobExecuteCommand(flags = {}) {
|
|
|
932
961
|
|
|
933
962
|
printStructuredResult(result, isTruthyFlag(flags.json));
|
|
934
963
|
}
|
|
964
|
+
|
|
965
|
+
async function handlePersonaCreateManagedCommand(flags = {}, positionalSlug = '') {
|
|
966
|
+
const name = String(flags.name || '').trim();
|
|
967
|
+
if (!name) {
|
|
968
|
+
throw new Error('Persona name is required. Usage: oomi personas create-managed [slug] --name "<name>" --description "<description>"');
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
const description = String(flags.description || '').trim() || name;
|
|
972
|
+
const explicitSlug = String(flags.slug || positionalSlug || '').trim();
|
|
973
|
+
const client = createCliPersonaApiClient(flags);
|
|
974
|
+
const result = await client.createManagedPersona({
|
|
975
|
+
slug: explicitSlug,
|
|
976
|
+
name,
|
|
977
|
+
description,
|
|
978
|
+
templateType: String(flags['template-type'] || 'persona-app').trim() || 'persona-app',
|
|
979
|
+
promptTemplateVersion: String(flags['template-version'] || 'v1').trim() || 'v1',
|
|
980
|
+
});
|
|
981
|
+
|
|
982
|
+
printManagedPersonaCreateResult(result, isTruthyFlag(flags.json));
|
|
983
|
+
}
|
|
935
984
|
|
|
936
985
|
function resolveOpenclawConfigPath() {
|
|
937
986
|
const candidates = [
|
|
@@ -3964,15 +4013,20 @@ async function main() {
|
|
|
3964
4013
|
return;
|
|
3965
4014
|
}
|
|
3966
4015
|
|
|
3967
|
-
if (command === 'personas' && subcommand === 'create') {
|
|
4016
|
+
if (command === 'personas' && subcommand === 'create') {
|
|
3968
4017
|
const id = args.positionals[0];
|
|
3969
4018
|
if (!id) {
|
|
3970
4019
|
throw new Error('Persona id is required. Usage: oomi personas create <id>');
|
|
3971
4020
|
}
|
|
3972
4021
|
await createPersona({ id, root: args.flags.root, flags: args.flags });
|
|
3973
4022
|
return;
|
|
3974
|
-
}
|
|
3975
|
-
|
|
4023
|
+
}
|
|
4024
|
+
|
|
4025
|
+
if (command === 'personas' && subcommand === 'create-managed') {
|
|
4026
|
+
await handlePersonaCreateManagedCommand(args.flags, args.positionals[0]);
|
|
4027
|
+
return;
|
|
4028
|
+
}
|
|
4029
|
+
|
|
3976
4030
|
if (command === 'personas' && subcommand === 'scaffold') {
|
|
3977
4031
|
const slug = args.positionals[0];
|
|
3978
4032
|
if (!slug) {
|
package/lib/personaApiClient.js
CHANGED
|
@@ -66,6 +66,38 @@ export function createPersonaApiClient({
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
return {
|
|
69
|
+
createManagedPersona({
|
|
70
|
+
slug,
|
|
71
|
+
name,
|
|
72
|
+
description,
|
|
73
|
+
templateType = 'persona-app',
|
|
74
|
+
promptTemplateVersion = 'v1',
|
|
75
|
+
}) {
|
|
76
|
+
const safeName = trimString(name);
|
|
77
|
+
if (!safeName) {
|
|
78
|
+
throw new Error('Persona name is required.');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const body = withDevice({
|
|
82
|
+
name: safeName,
|
|
83
|
+
description: trimString(description) || safeName,
|
|
84
|
+
templateType: trimString(templateType) || 'persona-app',
|
|
85
|
+
promptTemplateVersion: trimString(promptTemplateVersion) || 'v1',
|
|
86
|
+
});
|
|
87
|
+
const safeSlug = trimString(slug);
|
|
88
|
+
if (safeSlug) {
|
|
89
|
+
body.slug = safeSlug;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return postJson({
|
|
93
|
+
fetchImpl,
|
|
94
|
+
backendUrl: resolvedBackendUrl,
|
|
95
|
+
deviceToken: resolvedDeviceToken,
|
|
96
|
+
path: '/v1/personas/managed_create',
|
|
97
|
+
body,
|
|
98
|
+
});
|
|
99
|
+
},
|
|
100
|
+
|
|
69
101
|
registerRuntime({
|
|
70
102
|
slug,
|
|
71
103
|
endpoint,
|
package/openclaw.plugin.json
CHANGED