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.
- package/README.md +203 -507
- package/agent_instructions.md +244 -253
- package/bin/oomi-ai.js +4026 -5795
- package/bin/sessionBridgeState.js +78 -78
- package/lib/openclawPaths.js +70 -71
- package/lib/openclawProfile.js +216 -216
- package/lib/personaApiClient.js +133 -303
- package/lib/spokenMetadata.js +137 -137
- package/openclaw.extension.js +341 -341
- package/openclaw.plugin.json +17 -17
- package/package.json +59 -59
- package/persona-app/README.md +27 -0
- package/persona-app/registry/v1.json +63 -0
- package/persona-app/schema/persona-app.v1.schema.json +90 -0
- package/skills/oomi/SKILL.md +165 -182
- package/skills/oomi/agent_instructions.md +99 -80
- package/lib/channelPluginClient.js +0 -119
- package/lib/openclawDevGateway.js +0 -384
- package/lib/personaJobExecutor.js +0 -139
- package/lib/personaJobPoller.js +0 -112
- package/lib/personaPortAllocator.js +0 -36
- package/lib/personaRuntimeManager.js +0 -496
- package/lib/personaRuntimeProcess.js +0 -924
- package/lib/personaRuntimeRegistry.js +0 -67
- package/lib/personaRuntimeSupervisor.js +0 -330
- package/lib/scaffold.js +0 -108
- package/lib/template.js +0 -45
- package/skills/oomi/config.json +0 -3
- package/skills/oomi/scripts/get_avatar_capabilities.py +0 -40
- package/skills/oomi/scripts/get_data.py +0 -49
- package/skills/oomi/scripts/install_agent_instructions.py +0 -78
- package/skills/oomi/scripts/send_goal.py +0 -53
- package/skills/oomi/scripts/sync.py +0 -46
- package/skills/oomi/setup.py +0 -41
- package/templates/persona-app/.env.example +0 -8
- package/templates/persona-app/README.md +0 -58
- package/templates/persona-app/eslint.config.js +0 -28
- package/templates/persona-app/index.html +0 -18
- package/templates/persona-app/oomi.runtime.json +0 -13
- package/templates/persona-app/package.json +0 -44
- package/templates/persona-app/persona/brief.md +0 -14
- package/templates/persona-app/persona.json +0 -14
- package/templates/persona-app/public/manifest.webmanifest +0 -8
- package/templates/persona-app/public/oomi.health.json +0 -6
- package/templates/persona-app/src/App.css +0 -379
- package/templates/persona-app/src/App.tsx +0 -17
- package/templates/persona-app/src/index.css +0 -53
- package/templates/persona-app/src/main.tsx +0 -23
- package/templates/persona-app/src/pages/HomePage.tsx +0 -127
- package/templates/persona-app/src/pages/ScenePage.tsx +0 -158
- package/templates/persona-app/src/persona/config.ts +0 -6
- package/templates/persona-app/src/persona/notes.ts +0 -10
- package/templates/persona-app/src/spatial.ts +0 -82
- package/templates/persona-app/src/vite-env.d.ts +0 -3
- package/templates/persona-app/template.json +0 -13
- package/templates/persona-app/tsconfig.app.json +0 -23
- package/templates/persona-app/tsconfig.json +0 -7
- package/templates/persona-app/tsconfig.node.json +0 -21
- package/templates/persona-app/vendor/webspatial/FORK.md +0 -6
- package/templates/persona-app/vendor/webspatial/core-sdk/LICENSE +0 -21
- package/templates/persona-app/vendor/webspatial/core-sdk/dist/iife/index.d.ts +0 -906
- package/templates/persona-app/vendor/webspatial/core-sdk/dist/iife/index.global.js +0 -75
- package/templates/persona-app/vendor/webspatial/core-sdk/dist/iife/index.global.js.map +0 -1
- package/templates/persona-app/vendor/webspatial/core-sdk/dist/index.d.ts +0 -906
- package/templates/persona-app/vendor/webspatial/core-sdk/dist/index.js +0 -3131
- package/templates/persona-app/vendor/webspatial/core-sdk/dist/index.js.map +0 -1
- package/templates/persona-app/vendor/webspatial/core-sdk/package.json +0 -45
- package/templates/persona-app/vendor/webspatial/react-sdk/LICENSE +0 -21
- package/templates/persona-app/vendor/webspatial/react-sdk/dist/default/index.d.ts +0 -365
- package/templates/persona-app/vendor/webspatial/react-sdk/dist/default/index.js +0 -4167
- package/templates/persona-app/vendor/webspatial/react-sdk/dist/default/index.js.map +0 -1
- package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.d.ts +0 -82
- package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.js +0 -66
- package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.js.map +0 -1
- package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.web.d.ts +0 -2
- package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.web.js +0 -18
- package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.web.js.map +0 -1
- package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.d.ts +0 -5
- package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.js +0 -66
- package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.js.map +0 -1
- package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.web.d.ts +0 -1
- package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.web.js +0 -18
- package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.web.js.map +0 -1
- package/templates/persona-app/vendor/webspatial/react-sdk/dist/web/index.d.ts +0 -365
- package/templates/persona-app/vendor/webspatial/react-sdk/dist/web/index.js +0 -4207
- package/templates/persona-app/vendor/webspatial/react-sdk/dist/web/index.js.map +0 -1
- package/templates/persona-app/vendor/webspatial/react-sdk/package.json +0 -94
- package/templates/persona-app/vite.config.ts +0 -31
package/lib/personaApiClient.js
CHANGED
|
@@ -1,313 +1,143 @@
|
|
|
1
|
-
function trimString(value) {
|
|
2
|
-
return typeof value === 'string' ? value.trim() : '';
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
function stripTrailingSlash(value) {
|
|
6
|
-
return trimString(value).replace(/\/+$/, '');
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
async function readJsonResponse(response) {
|
|
10
|
-
return response.json().catch(() => ({}));
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
async function getJson({ fetchImpl, backendUrl, path, deviceToken }) {
|
|
14
|
-
const baseUrl = stripTrailingSlash(backendUrl);
|
|
15
|
-
if (!baseUrl) {
|
|
16
|
-
throw new Error('Backend URL is required.');
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const headers = {};
|
|
20
|
-
const token = trimString(deviceToken);
|
|
21
|
-
if (token) {
|
|
22
|
-
headers.Authorization = `Bearer ${token}`;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const response = await fetchImpl(`${baseUrl}${path}`, {
|
|
26
|
-
method: 'GET',
|
|
27
|
-
headers,
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
const payload = await readJsonResponse(response);
|
|
31
|
-
if (!response.ok) {
|
|
32
|
-
const errorMessage =
|
|
33
|
-
trimString(payload?.error) ||
|
|
34
|
-
trimString(payload?.message) ||
|
|
35
|
-
`Persona API request failed (${response.status})`;
|
|
36
|
-
const error = new Error(errorMessage);
|
|
37
|
-
error.status = response.status;
|
|
38
|
-
error.payload = payload;
|
|
39
|
-
throw error;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return payload;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
async function postJson({ fetchImpl, backendUrl, path, deviceToken, body }) {
|
|
46
|
-
const baseUrl = stripTrailingSlash(backendUrl);
|
|
47
|
-
if (!baseUrl) {
|
|
48
|
-
throw new Error('Backend URL is required.');
|
|
49
|
-
}
|
|
50
|
-
const token = trimString(deviceToken);
|
|
51
|
-
if (!token) {
|
|
52
|
-
throw new Error('Device token is required.');
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const response = await fetchImpl(`${baseUrl}${path}`, {
|
|
56
|
-
method: 'POST',
|
|
57
|
-
headers: {
|
|
58
|
-
'Content-Type': 'application/json',
|
|
59
|
-
Authorization: `Bearer ${token}`,
|
|
60
|
-
},
|
|
61
|
-
body: JSON.stringify(body),
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
const payload = await readJsonResponse(response);
|
|
65
|
-
if (!response.ok) {
|
|
66
|
-
const errorMessage =
|
|
67
|
-
trimString(payload?.error) ||
|
|
68
|
-
trimString(payload?.message) ||
|
|
69
|
-
`Persona API request failed (${response.status})`;
|
|
70
|
-
const error = new Error(errorMessage);
|
|
71
|
-
error.status = response.status;
|
|
72
|
-
error.payload = payload;
|
|
73
|
-
throw error;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return payload;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function createPersonaApiClient({
|
|
80
|
-
backendUrl,
|
|
81
|
-
deviceToken,
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
const resolvedDeviceId = trimString(deviceId);
|
|
92
|
-
|
|
93
|
-
function withDevice(body = {}) {
|
|
94
|
-
if (!resolvedDeviceId) {
|
|
95
|
-
return body;
|
|
96
|
-
}
|
|
97
|
-
return {
|
|
98
|
-
...body,
|
|
99
|
-
deviceId: resolvedDeviceId,
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
|
|
1
|
+
function trimString(value) {
|
|
2
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function stripTrailingSlash(value) {
|
|
6
|
+
return trimString(value).replace(/\/+$/, '');
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
async function readJsonResponse(response) {
|
|
10
|
+
return response.json().catch(() => ({}));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function getJson({ fetchImpl, backendUrl, path, deviceToken }) {
|
|
14
|
+
const baseUrl = stripTrailingSlash(backendUrl);
|
|
15
|
+
if (!baseUrl) {
|
|
16
|
+
throw new Error('Backend URL is required.');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const headers = {};
|
|
20
|
+
const token = trimString(deviceToken);
|
|
21
|
+
if (token) {
|
|
22
|
+
headers.Authorization = `Bearer ${token}`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const response = await fetchImpl(`${baseUrl}${path}`, {
|
|
26
|
+
method: 'GET',
|
|
27
|
+
headers,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const payload = await readJsonResponse(response);
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
const errorMessage =
|
|
33
|
+
trimString(payload?.error) ||
|
|
34
|
+
trimString(payload?.message) ||
|
|
35
|
+
`Persona API request failed (${response.status})`;
|
|
36
|
+
const error = new Error(errorMessage);
|
|
37
|
+
error.status = response.status;
|
|
38
|
+
error.payload = payload;
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return payload;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function postJson({ fetchImpl, backendUrl, path, deviceToken, body }) {
|
|
46
|
+
const baseUrl = stripTrailingSlash(backendUrl);
|
|
47
|
+
if (!baseUrl) {
|
|
48
|
+
throw new Error('Backend URL is required.');
|
|
49
|
+
}
|
|
50
|
+
const token = trimString(deviceToken);
|
|
51
|
+
if (!token) {
|
|
52
|
+
throw new Error('Device token is required.');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const response = await fetchImpl(`${baseUrl}${path}`, {
|
|
56
|
+
method: 'POST',
|
|
57
|
+
headers: {
|
|
58
|
+
'Content-Type': 'application/json',
|
|
59
|
+
Authorization: `Bearer ${token}`,
|
|
60
|
+
},
|
|
61
|
+
body: JSON.stringify(body),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const payload = await readJsonResponse(response);
|
|
65
|
+
if (!response.ok) {
|
|
66
|
+
const errorMessage =
|
|
67
|
+
trimString(payload?.error) ||
|
|
68
|
+
trimString(payload?.message) ||
|
|
69
|
+
`Persona API request failed (${response.status})`;
|
|
70
|
+
const error = new Error(errorMessage);
|
|
71
|
+
error.status = response.status;
|
|
72
|
+
error.payload = payload;
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return payload;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function createPersonaApiClient({
|
|
80
|
+
backendUrl,
|
|
81
|
+
deviceToken,
|
|
82
|
+
fetchImpl = globalThis.fetch,
|
|
83
|
+
}) {
|
|
84
|
+
if (typeof fetchImpl !== 'function') {
|
|
85
|
+
throw new Error('fetch implementation is required.');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const resolvedBackendUrl = stripTrailingSlash(backendUrl);
|
|
89
|
+
const resolvedDeviceToken = trimString(deviceToken);
|
|
90
|
+
|
|
103
91
|
return {
|
|
104
|
-
|
|
92
|
+
listPersonaApps() {
|
|
105
93
|
return getJson({
|
|
106
94
|
fetchImpl,
|
|
107
95
|
backendUrl: resolvedBackendUrl,
|
|
108
96
|
deviceToken: resolvedDeviceToken,
|
|
109
|
-
path: '/v1/
|
|
97
|
+
path: '/v1/persona_apps',
|
|
110
98
|
});
|
|
111
99
|
},
|
|
112
100
|
|
|
113
|
-
|
|
101
|
+
getPersonaApp({
|
|
114
102
|
slug,
|
|
115
103
|
}) {
|
|
116
|
-
const safeSlug = trimString(slug);
|
|
117
|
-
if (!safeSlug) {
|
|
118
|
-
throw new Error('Persona slug is required.');
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return getJson({
|
|
122
|
-
fetchImpl,
|
|
123
|
-
backendUrl: resolvedBackendUrl,
|
|
124
|
-
deviceToken: resolvedDeviceToken,
|
|
125
|
-
path: `/v1/
|
|
126
|
-
});
|
|
127
|
-
},
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
slug,
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
path: '/v1/personas/managed_create',
|
|
157
|
-
body,
|
|
158
|
-
});
|
|
159
|
-
},
|
|
160
|
-
|
|
161
|
-
registerRuntime({
|
|
162
|
-
slug,
|
|
163
|
-
endpoint,
|
|
164
|
-
healthcheckUrl,
|
|
165
|
-
transport = 'local',
|
|
166
|
-
localPort,
|
|
167
|
-
startedAt,
|
|
168
|
-
}) {
|
|
169
|
-
const safeSlug = trimString(slug);
|
|
170
|
-
if (!safeSlug) {
|
|
171
|
-
throw new Error('Persona slug is required.');
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
return postJson({
|
|
175
|
-
fetchImpl,
|
|
176
|
-
backendUrl: resolvedBackendUrl,
|
|
177
|
-
deviceToken: resolvedDeviceToken,
|
|
178
|
-
path: `/v1/personas/${encodeURIComponent(safeSlug)}/runtime_register`,
|
|
179
|
-
body: withDevice({
|
|
180
|
-
endpoint,
|
|
181
|
-
healthcheckUrl,
|
|
182
|
-
transport,
|
|
183
|
-
localPort,
|
|
184
|
-
startedAt,
|
|
185
|
-
}),
|
|
186
|
-
});
|
|
187
|
-
},
|
|
188
|
-
|
|
189
|
-
heartbeatRuntime({
|
|
190
|
-
slug,
|
|
191
|
-
endpoint,
|
|
192
|
-
healthcheckUrl,
|
|
193
|
-
transport = 'local',
|
|
194
|
-
localPort,
|
|
195
|
-
observedAt,
|
|
196
|
-
}) {
|
|
197
|
-
const safeSlug = trimString(slug);
|
|
198
|
-
if (!safeSlug) {
|
|
199
|
-
throw new Error('Persona slug is required.');
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
return postJson({
|
|
203
|
-
fetchImpl,
|
|
204
|
-
backendUrl: resolvedBackendUrl,
|
|
205
|
-
deviceToken: resolvedDeviceToken,
|
|
206
|
-
path: `/v1/personas/${encodeURIComponent(safeSlug)}/heartbeat`,
|
|
207
|
-
body: withDevice({
|
|
208
|
-
endpoint,
|
|
209
|
-
healthcheckUrl,
|
|
210
|
-
transport,
|
|
211
|
-
localPort,
|
|
212
|
-
observedAt,
|
|
213
|
-
}),
|
|
214
|
-
});
|
|
215
|
-
},
|
|
216
|
-
|
|
217
|
-
failRuntime({
|
|
218
|
-
slug,
|
|
219
|
-
code,
|
|
220
|
-
message,
|
|
221
|
-
}) {
|
|
222
|
-
const safeSlug = trimString(slug);
|
|
223
|
-
if (!safeSlug) {
|
|
224
|
-
throw new Error('Persona slug is required.');
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
return postJson({
|
|
228
|
-
fetchImpl,
|
|
229
|
-
backendUrl: resolvedBackendUrl,
|
|
230
|
-
deviceToken: resolvedDeviceToken,
|
|
231
|
-
path: `/v1/personas/${encodeURIComponent(safeSlug)}/fail`,
|
|
232
|
-
body: withDevice({
|
|
233
|
-
code,
|
|
234
|
-
message,
|
|
235
|
-
}),
|
|
236
|
-
});
|
|
237
|
-
},
|
|
238
|
-
|
|
239
|
-
startJob({
|
|
240
|
-
jobId,
|
|
241
|
-
startedAt,
|
|
242
|
-
}) {
|
|
243
|
-
const safeJobId = trimString(jobId);
|
|
244
|
-
if (!safeJobId) {
|
|
245
|
-
throw new Error('Persona job id is required.');
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
return postJson({
|
|
249
|
-
fetchImpl,
|
|
250
|
-
backendUrl: resolvedBackendUrl,
|
|
251
|
-
deviceToken: resolvedDeviceToken,
|
|
252
|
-
path: `/v1/persona_jobs/${encodeURIComponent(safeJobId)}/start`,
|
|
253
|
-
body: withDevice({
|
|
254
|
-
startedAt,
|
|
255
|
-
}),
|
|
256
|
-
});
|
|
257
|
-
},
|
|
258
|
-
|
|
259
|
-
succeedJob({
|
|
260
|
-
jobId,
|
|
261
|
-
workspacePath,
|
|
262
|
-
localPort,
|
|
263
|
-
transport = 'local',
|
|
264
|
-
endpoint,
|
|
265
|
-
healthcheckUrl,
|
|
266
|
-
completedAt,
|
|
267
|
-
}) {
|
|
268
|
-
const safeJobId = trimString(jobId);
|
|
269
|
-
if (!safeJobId) {
|
|
270
|
-
throw new Error('Persona job id is required.');
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
return postJson({
|
|
274
|
-
fetchImpl,
|
|
275
|
-
backendUrl: resolvedBackendUrl,
|
|
276
|
-
deviceToken: resolvedDeviceToken,
|
|
277
|
-
path: `/v1/persona_jobs/${encodeURIComponent(safeJobId)}/succeed`,
|
|
278
|
-
body: withDevice({
|
|
279
|
-
workspacePath,
|
|
280
|
-
localPort,
|
|
281
|
-
transport,
|
|
282
|
-
endpoint,
|
|
283
|
-
healthcheckUrl,
|
|
284
|
-
completedAt,
|
|
285
|
-
}),
|
|
286
|
-
});
|
|
287
|
-
},
|
|
288
|
-
|
|
289
|
-
failJob({
|
|
290
|
-
jobId,
|
|
291
|
-
code,
|
|
292
|
-
message,
|
|
293
|
-
completedAt,
|
|
294
|
-
}) {
|
|
295
|
-
const safeJobId = trimString(jobId);
|
|
296
|
-
if (!safeJobId) {
|
|
297
|
-
throw new Error('Persona job id is required.');
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
return postJson({
|
|
301
|
-
fetchImpl,
|
|
302
|
-
backendUrl: resolvedBackendUrl,
|
|
303
|
-
deviceToken: resolvedDeviceToken,
|
|
304
|
-
path: `/v1/persona_jobs/${encodeURIComponent(safeJobId)}/fail`,
|
|
305
|
-
body: withDevice({
|
|
306
|
-
code,
|
|
307
|
-
message,
|
|
308
|
-
completedAt,
|
|
309
|
-
}),
|
|
310
|
-
});
|
|
311
|
-
},
|
|
312
|
-
};
|
|
313
|
-
}
|
|
104
|
+
const safeSlug = trimString(slug);
|
|
105
|
+
if (!safeSlug) {
|
|
106
|
+
throw new Error('Persona app slug is required.');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return getJson({
|
|
110
|
+
fetchImpl,
|
|
111
|
+
backendUrl: resolvedBackendUrl,
|
|
112
|
+
deviceToken: resolvedDeviceToken,
|
|
113
|
+
path: `/v1/persona_apps/${encodeURIComponent(safeSlug)}`,
|
|
114
|
+
});
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
applyPersonaAppAction({
|
|
118
|
+
slug,
|
|
119
|
+
actionId,
|
|
120
|
+
payload = {},
|
|
121
|
+
}) {
|
|
122
|
+
const safeSlug = trimString(slug);
|
|
123
|
+
if (!safeSlug) {
|
|
124
|
+
throw new Error('Persona app slug is required.');
|
|
125
|
+
}
|
|
126
|
+
const safeActionId = trimString(actionId);
|
|
127
|
+
if (!safeActionId) {
|
|
128
|
+
throw new Error('Persona app action id is required.');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return postJson({
|
|
132
|
+
fetchImpl,
|
|
133
|
+
backendUrl: resolvedBackendUrl,
|
|
134
|
+
deviceToken: resolvedDeviceToken,
|
|
135
|
+
path: `/v1/persona_apps/${encodeURIComponent(safeSlug)}/actions`,
|
|
136
|
+
body: {
|
|
137
|
+
actionId: safeActionId,
|
|
138
|
+
payload: payload && typeof payload === 'object' ? payload : {},
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
}
|