crewly 1.20.209 → 1.20.210
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/config/skills/agent/core/app-data/SKILL.md +88 -0
- package/config/skills/agent/core/app-data/execute.sh +141 -0
- package/config/skills/agent/core/app-data/execute.test.sh +108 -0
- package/config/skills/agent/core/publish-app/SKILL.md +181 -0
- package/config/skills/agent/core/publish-app/execute.sh +181 -0
- package/config/skills/agent/core/publish-app/execute.test.sh +114 -0
- package/dist/backend/backend/src/constants.d.ts +62 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +62 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/apps/apps.controller.d.ts +39 -0
- package/dist/backend/backend/src/controllers/apps/apps.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/apps/apps.controller.js +94 -0
- package/dist/backend/backend/src/controllers/apps/apps.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/apps/apps.routes.d.ts +46 -0
- package/dist/backend/backend/src/controllers/apps/apps.routes.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/apps/apps.routes.js +94 -0
- package/dist/backend/backend/src/controllers/apps/apps.routes.js.map +1 -0
- package/dist/backend/backend/src/index.d.ts +1 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +57 -5
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/middleware/body-parser-except.d.ts +25 -0
- package/dist/backend/backend/src/middleware/body-parser-except.d.ts.map +1 -0
- package/dist/backend/backend/src/middleware/body-parser-except.js +33 -0
- package/dist/backend/backend/src/middleware/body-parser-except.js.map +1 -0
- package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.js +4 -0
- package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js +4 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
- package/dist/backend/backend/src/services/apps/app-wake-message.d.ts +95 -0
- package/dist/backend/backend/src/services/apps/app-wake-message.d.ts.map +1 -0
- package/dist/backend/backend/src/services/apps/app-wake-message.js +161 -0
- package/dist/backend/backend/src/services/apps/app-wake-message.js.map +1 -0
- package/dist/backend/backend/src/services/apps/app-wake.service.d.ts +118 -0
- package/dist/backend/backend/src/services/apps/app-wake.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/apps/app-wake.service.js +325 -0
- package/dist/backend/backend/src/services/apps/app-wake.service.js.map +1 -0
- package/dist/backend/backend/src/services/apps/apps-cloud.client.d.ts +74 -0
- package/dist/backend/backend/src/services/apps/apps-cloud.client.d.ts.map +1 -0
- package/dist/backend/backend/src/services/apps/apps-cloud.client.js +120 -0
- package/dist/backend/backend/src/services/apps/apps-cloud.client.js.map +1 -0
- package/dist/backend/backend/src/services/apps/apps-registry.service.d.ts +107 -0
- package/dist/backend/backend/src/services/apps/apps-registry.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/apps/apps-registry.service.js +178 -0
- package/dist/backend/backend/src/services/apps/apps-registry.service.js.map +1 -0
- package/dist/backend/backend/src/services/apps/apps.service.d.ts +217 -0
- package/dist/backend/backend/src/services/apps/apps.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/apps/apps.service.js +383 -0
- package/dist/backend/backend/src/services/apps/apps.service.js.map +1 -0
- package/dist/backend/backend/src/services/apps/apps.wiring.d.ts +83 -0
- package/dist/backend/backend/src/services/apps/apps.wiring.d.ts.map +1 -0
- package/dist/backend/backend/src/services/apps/apps.wiring.js +133 -0
- package/dist/backend/backend/src/services/apps/apps.wiring.js.map +1 -0
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +62 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +62 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js +4 -0
- package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AppsService — publish, roll back and read/write the data of Crewly Apps
|
|
3
|
+
* on behalf of an agent (or the owner), through {@link AppsCloudClient}.
|
|
4
|
+
*
|
|
5
|
+
* Backs `/api/apps` and the publish-app / app-data skills
|
|
6
|
+
* (specs/2026-10-04-crewly-apps-p2.md).
|
|
7
|
+
*
|
|
8
|
+
* @module services/apps/apps.service
|
|
9
|
+
*/
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import { CREWLY_APPS_CONSTANTS } from '../../constants.js';
|
|
12
|
+
import { AppsCloudError } from './apps-cloud.client.js';
|
|
13
|
+
const C = CREWLY_APPS_CONSTANTS;
|
|
14
|
+
const APP_ID_RE = /^[a-km-np-z2-9]{10}$/;
|
|
15
|
+
const COLLECTION_RE = /^[A-Za-z0-9_-]{1,64}$/;
|
|
16
|
+
const DOC_ID_RE = /^[A-Za-z0-9_.:-]{1,128}$/;
|
|
17
|
+
function validation(message) {
|
|
18
|
+
return new AppsCloudError(400, C.ERROR_CODES.VALIDATION, message);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Check an app id's shape.
|
|
22
|
+
*
|
|
23
|
+
* @param appId - Candidate
|
|
24
|
+
* @returns The id
|
|
25
|
+
* @throws AppsCloudError validation
|
|
26
|
+
*/
|
|
27
|
+
export function requireAppId(appId) {
|
|
28
|
+
if (typeof appId !== 'string' || !APP_ID_RE.test(appId))
|
|
29
|
+
throw validation('appId must be a 10-character Crewly app id.');
|
|
30
|
+
return appId;
|
|
31
|
+
}
|
|
32
|
+
function requireCollection(c) {
|
|
33
|
+
if (typeof c !== 'string' || !COLLECTION_RE.test(c))
|
|
34
|
+
throw validation('collection must be 1-64 of A-Z a-z 0-9 _ -.');
|
|
35
|
+
return c;
|
|
36
|
+
}
|
|
37
|
+
function requireDocId(id) {
|
|
38
|
+
if (typeof id !== 'string' || !DOC_ID_RE.test(id) || id === '.' || id === '..') {
|
|
39
|
+
throw validation('docId must be 1-128 of A-Z a-z 0-9 _ . : - (and not "." or "..").');
|
|
40
|
+
}
|
|
41
|
+
return id;
|
|
42
|
+
}
|
|
43
|
+
function notYourApp() {
|
|
44
|
+
return new AppsCloudError(403, C.ERROR_CODES.NOT_YOUR_APP, 'This app was published by another agent. Only its publisher can publish or roll it back, and only the publisher and its team can use its data. Ask the owner if you need it.');
|
|
45
|
+
}
|
|
46
|
+
function requireData(data) {
|
|
47
|
+
if (!data || typeof data !== 'object' || Array.isArray(data))
|
|
48
|
+
throw validation('data must be a JSON object.');
|
|
49
|
+
return data;
|
|
50
|
+
}
|
|
51
|
+
function optString(v) {
|
|
52
|
+
return typeof v === 'string' && v.trim() ? v.trim() : undefined;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The "📱 <name> · Open app" card text. Markdown link: the reply path turns
|
|
56
|
+
* it into a Slack link.
|
|
57
|
+
*
|
|
58
|
+
* @param name - App name
|
|
59
|
+
* @param appId - App id
|
|
60
|
+
* @returns Card text
|
|
61
|
+
*/
|
|
62
|
+
export function appCardText(name, appId) {
|
|
63
|
+
const clean = name.replace(/[[\]()\r\n]/g, ' ').replace(/\s+/g, ' ').trim() || 'App';
|
|
64
|
+
return `📱 ${clean} · [Open app](${C.APPS_ORIGIN}/${appId})`;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Publishing and data access for Crewly Apps.
|
|
68
|
+
*/
|
|
69
|
+
export class AppsService {
|
|
70
|
+
deps;
|
|
71
|
+
constructor(deps) {
|
|
72
|
+
this.deps = deps;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Publish a bundle: find the caller's app (or create one), upload a new
|
|
76
|
+
* version, record it locally, and optionally post the Slack card.
|
|
77
|
+
*
|
|
78
|
+
* @param input - Files and options from the skill
|
|
79
|
+
* @param caller - Agent session or owner
|
|
80
|
+
* @returns appId, url, version, whether it was created / notified
|
|
81
|
+
* @throws AppsCloudError on validation or a Cloud failure
|
|
82
|
+
*/
|
|
83
|
+
async publish(input, caller) {
|
|
84
|
+
const files = this.validateFiles(input.files);
|
|
85
|
+
const explicitId = input.appId !== undefined && input.appId !== null && input.appId !== '' ? requireAppId(input.appId) : undefined;
|
|
86
|
+
const source = optString(input.source) ?? null;
|
|
87
|
+
const name = optString(input.name);
|
|
88
|
+
const agentSession = caller.agentSession ?? null;
|
|
89
|
+
if (name && name.length > 80)
|
|
90
|
+
throw validation('name is at most 80 characters.');
|
|
91
|
+
const { registry, client } = this.deps;
|
|
92
|
+
let entry = await registry.find({ appId: explicitId, agentSession, source, name });
|
|
93
|
+
// An agent publishes only to its own apps; adopting an app made elsewhere is the owner's call.
|
|
94
|
+
if (explicitId && agentSession && (!entry || entry.agentSession !== agentSession))
|
|
95
|
+
throw notYourApp();
|
|
96
|
+
let app = null;
|
|
97
|
+
let created = false;
|
|
98
|
+
if (entry && !explicitId) {
|
|
99
|
+
// Found by source/name: if the owner deleted it, publish a new app instead.
|
|
100
|
+
try {
|
|
101
|
+
app = await client.request('GET', `/apps/${entry.appId}`, { agent: caller.agentSession });
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
if (!(err instanceof AppsCloudError) || err.status !== 404)
|
|
105
|
+
throw err;
|
|
106
|
+
await registry.markDeleted(entry.appId);
|
|
107
|
+
entry = null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
else if (entry) {
|
|
111
|
+
app = await client.request('GET', `/apps/${entry.appId}`, { agent: caller.agentSession });
|
|
112
|
+
}
|
|
113
|
+
if (entry && app) {
|
|
114
|
+
if (name && name !== app.name) {
|
|
115
|
+
app = await client.request('PATCH', `/apps/${app.appId}`, { body: { name }, agent: caller.agentSession });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else if (explicitId) {
|
|
119
|
+
// An app made elsewhere (another machine, the portal): adopt it.
|
|
120
|
+
app = await client.request('GET', `/apps/${explicitId}`, { agent: caller.agentSession });
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
const newName = name ?? (source ? path.basename(source).replace(/\.[^.]+$/, '') : '');
|
|
124
|
+
app = await client.request('POST', '/apps', { body: { name: newName.slice(0, 80) || 'App' }, agent: caller.agentSession });
|
|
125
|
+
created = true;
|
|
126
|
+
}
|
|
127
|
+
const entryFile = optString(input.entry);
|
|
128
|
+
const note = optString(input.note);
|
|
129
|
+
const version = await client.request('POST', `/apps/${app.appId}/versions`, {
|
|
130
|
+
body: {
|
|
131
|
+
files,
|
|
132
|
+
...(entryFile ? { entry: entryFile } : {}),
|
|
133
|
+
...(note ? { note: note.slice(0, 200) } : {}),
|
|
134
|
+
},
|
|
135
|
+
agent: caller.agentSession,
|
|
136
|
+
});
|
|
137
|
+
entry = await registry.upsert(app.appId, {
|
|
138
|
+
name: app.name,
|
|
139
|
+
url: app.url,
|
|
140
|
+
// The last agent to publish owns the wake; an owner publish keeps it.
|
|
141
|
+
...(agentSession ? { agentSession } : {}),
|
|
142
|
+
...(source ? { source } : {}),
|
|
143
|
+
currentVersion: version.version,
|
|
144
|
+
// A brand-new app has no history: start right before its first change,
|
|
145
|
+
// so an owner edit made before the first poll is not skipped.
|
|
146
|
+
...(created ? { cursor: 0 } : {}),
|
|
147
|
+
deleted: false,
|
|
148
|
+
});
|
|
149
|
+
let notified = false;
|
|
150
|
+
let notifyError;
|
|
151
|
+
if (input.notify === true) {
|
|
152
|
+
if (!caller.agentSession) {
|
|
153
|
+
notifyError = 'Only an agent can post the app card (it goes out under the agent’s identity).';
|
|
154
|
+
}
|
|
155
|
+
else if (!this.deps.notifyCard) {
|
|
156
|
+
notifyError = 'Posting the app card is not available on this instance.';
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
const r = await this.deps.notifyCard(caller.agentSession, appCardText(app.name, app.appId)).catch((err) => ({
|
|
160
|
+
ok: false,
|
|
161
|
+
error: err instanceof Error ? err.message : String(err),
|
|
162
|
+
}));
|
|
163
|
+
notified = r.ok;
|
|
164
|
+
if (!r.ok)
|
|
165
|
+
notifyError = r.error ?? 'The card could not be delivered.';
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
appId: app.appId,
|
|
170
|
+
name: app.name,
|
|
171
|
+
url: `${C.APPS_ORIGIN}/${app.appId}`,
|
|
172
|
+
version: version.version,
|
|
173
|
+
created,
|
|
174
|
+
notified,
|
|
175
|
+
...(notifyError ? { notifyError } : {}),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Make an earlier retained version current.
|
|
180
|
+
*
|
|
181
|
+
* @param appId - App id
|
|
182
|
+
* @param version - Version number
|
|
183
|
+
* @param caller - Agent or owner
|
|
184
|
+
* @returns The app after rollback
|
|
185
|
+
*/
|
|
186
|
+
async rollback(appId, version, caller) {
|
|
187
|
+
const id = requireAppId(appId);
|
|
188
|
+
const v = typeof version === 'string' ? Number(version) : version;
|
|
189
|
+
if (typeof v !== 'number' || !Number.isInteger(v) || v < 1)
|
|
190
|
+
throw validation('version must be a positive integer.');
|
|
191
|
+
await this.assertPublisher(id, caller);
|
|
192
|
+
const app = await this.deps.client.request('POST', `/apps/${id}/rollback`, { body: { version: v }, agent: caller.agentSession });
|
|
193
|
+
if (await this.deps.registry.get(id))
|
|
194
|
+
await this.deps.registry.upsert(id, { currentVersion: app.currentVersion });
|
|
195
|
+
return app;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Versions of an app, newest first.
|
|
199
|
+
*
|
|
200
|
+
* @param appId - App id
|
|
201
|
+
* @param caller - Agent or owner
|
|
202
|
+
* @returns Versions
|
|
203
|
+
*/
|
|
204
|
+
async versions(appId, caller) {
|
|
205
|
+
const id = requireAppId(appId);
|
|
206
|
+
await this.assertPublisher(id, caller);
|
|
207
|
+
return this.deps.client.request('GET', `/apps/${id}/versions`, { agent: caller.agentSession });
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Agents may manage (publish, roll back, list versions of) only apps they
|
|
211
|
+
* published. The owner may manage any.
|
|
212
|
+
*
|
|
213
|
+
* @param appId - App id
|
|
214
|
+
* @param caller - Agent or owner
|
|
215
|
+
* @throws AppsCloudError 403 not_your_app
|
|
216
|
+
*/
|
|
217
|
+
async assertPublisher(appId, caller) {
|
|
218
|
+
if (!caller.agentSession)
|
|
219
|
+
return;
|
|
220
|
+
const entry = await this.deps.registry.get(appId);
|
|
221
|
+
if (!entry || entry.agentSession !== caller.agentSession)
|
|
222
|
+
throw notYourApp();
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Agents may read and write the data of apps they published, or that a
|
|
226
|
+
* teammate published. The owner may use any.
|
|
227
|
+
*
|
|
228
|
+
* @param appId - App id
|
|
229
|
+
* @param caller - Agent or owner
|
|
230
|
+
* @throws AppsCloudError 403 not_your_app
|
|
231
|
+
*/
|
|
232
|
+
async assertDataAccess(appId, caller) {
|
|
233
|
+
const me = caller.agentSession;
|
|
234
|
+
if (!me)
|
|
235
|
+
return;
|
|
236
|
+
const entry = await this.deps.registry.get(appId);
|
|
237
|
+
const publisher = entry?.agentSession;
|
|
238
|
+
if (!publisher)
|
|
239
|
+
throw notYourApp();
|
|
240
|
+
if (publisher === me)
|
|
241
|
+
return;
|
|
242
|
+
if (this.deps.sameTeam && (await this.deps.sameTeam(me, publisher).catch(() => false)))
|
|
243
|
+
return;
|
|
244
|
+
throw notYourApp();
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Apps this instance published (local registry, not Cloud).
|
|
248
|
+
*
|
|
249
|
+
* @returns Entries without the poller cursor
|
|
250
|
+
*/
|
|
251
|
+
async list(caller = {}) {
|
|
252
|
+
return (await this.deps.registry.list())
|
|
253
|
+
.filter((e) => !caller.agentSession || e.agentSession === caller.agentSession)
|
|
254
|
+
.map(({ cursor: _cursor, delivered: _delivered, wakes: _wakes, ...rest }) => rest);
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* One page of a collection.
|
|
258
|
+
*
|
|
259
|
+
* @param appId - App id
|
|
260
|
+
* @param collection - Collection
|
|
261
|
+
* @param opts - limit / after
|
|
262
|
+
* @param caller - Agent or owner
|
|
263
|
+
* @returns `{ docs, next }`
|
|
264
|
+
*/
|
|
265
|
+
async listDocs(appId, collection, opts, caller) {
|
|
266
|
+
const limit = opts.limit !== undefined && opts.limit !== '' ? Number(opts.limit) : undefined;
|
|
267
|
+
if (limit !== undefined && (!Number.isInteger(limit) || limit < 1 || limit > 500))
|
|
268
|
+
throw validation('limit is 1-500.');
|
|
269
|
+
const after = opts.after !== undefined && opts.after !== '' ? requireDocId(opts.after) : undefined;
|
|
270
|
+
const path = `/apps/${requireAppId(appId)}/data/${requireCollection(collection)}`;
|
|
271
|
+
await this.assertDataAccess(appId, caller);
|
|
272
|
+
return this.deps.client.request('GET', path, {
|
|
273
|
+
query: { limit, after },
|
|
274
|
+
agent: caller.agentSession,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* One document (`{ id, data, rev, … }`); a missing one throws 404 not_found.
|
|
279
|
+
*
|
|
280
|
+
* @param appId - App id
|
|
281
|
+
* @param collection - Collection
|
|
282
|
+
* @param docId - Document id
|
|
283
|
+
* @param caller - Agent or owner
|
|
284
|
+
* @returns The document
|
|
285
|
+
*/
|
|
286
|
+
async getDoc(appId, collection, docId, caller) {
|
|
287
|
+
const path = this.docPath(appId, collection, docId);
|
|
288
|
+
await this.assertDataAccess(appId, caller);
|
|
289
|
+
return this.deps.client.request('GET', path, { agent: caller.agentSession });
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Replace (or create) a document.
|
|
293
|
+
*
|
|
294
|
+
* @param appId - App id
|
|
295
|
+
* @param collection - Collection
|
|
296
|
+
* @param docId - Document id
|
|
297
|
+
* @param data - New content
|
|
298
|
+
* @param caller - Agent or owner
|
|
299
|
+
* @returns The stored document
|
|
300
|
+
*/
|
|
301
|
+
async setDoc(appId, collection, docId, data, caller) {
|
|
302
|
+
const path = this.docPath(appId, collection, docId);
|
|
303
|
+
const body = { data: requireData(data) };
|
|
304
|
+
await this.assertDataAccess(appId, caller);
|
|
305
|
+
return this.deps.client.request('PUT', path, { body, agent: caller.agentSession });
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Shallow-merge into a document; `ifRev` makes it conditional (409 conflict).
|
|
309
|
+
*
|
|
310
|
+
* @param appId - App id
|
|
311
|
+
* @param collection - Collection
|
|
312
|
+
* @param docId - Document id
|
|
313
|
+
* @param data - Fields to merge
|
|
314
|
+
* @param ifRev - Expected current rev (optional)
|
|
315
|
+
* @param caller - Agent or owner
|
|
316
|
+
* @returns The stored document
|
|
317
|
+
*/
|
|
318
|
+
async updateDoc(appId, collection, docId, data, ifRev, caller) {
|
|
319
|
+
const rev = ifRev === undefined || ifRev === null || ifRev === '' ? undefined : Number(ifRev);
|
|
320
|
+
if (rev !== undefined && (!Number.isInteger(rev) || rev < 0))
|
|
321
|
+
throw validation('ifRev must be a non-negative integer.');
|
|
322
|
+
const path = this.docPath(appId, collection, docId);
|
|
323
|
+
const body = { data: requireData(data), ...(rev !== undefined ? { ifRev: rev } : {}) };
|
|
324
|
+
await this.assertDataAccess(appId, caller);
|
|
325
|
+
return this.deps.client.request('PATCH', path, {
|
|
326
|
+
body,
|
|
327
|
+
agent: caller.agentSession,
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Add a document with a generated id.
|
|
332
|
+
*
|
|
333
|
+
* @param appId - App id
|
|
334
|
+
* @param collection - Collection
|
|
335
|
+
* @param data - Content
|
|
336
|
+
* @param caller - Agent or owner
|
|
337
|
+
* @returns The stored document
|
|
338
|
+
*/
|
|
339
|
+
async addDoc(appId, collection, data, caller) {
|
|
340
|
+
const path = `/apps/${requireAppId(appId)}/data/${requireCollection(collection)}`;
|
|
341
|
+
const body = { data: requireData(data) };
|
|
342
|
+
await this.assertDataAccess(appId, caller);
|
|
343
|
+
return this.deps.client.request('POST', path, {
|
|
344
|
+
body,
|
|
345
|
+
agent: caller.agentSession,
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Delete a document.
|
|
350
|
+
*
|
|
351
|
+
* @param appId - App id
|
|
352
|
+
* @param collection - Collection
|
|
353
|
+
* @param docId - Document id
|
|
354
|
+
* @param caller - Agent or owner
|
|
355
|
+
* @returns `{ deleted: true }`
|
|
356
|
+
*/
|
|
357
|
+
async deleteDoc(appId, collection, docId, caller) {
|
|
358
|
+
const path = this.docPath(appId, collection, docId);
|
|
359
|
+
await this.assertDataAccess(appId, caller);
|
|
360
|
+
return this.deps.client.request('DELETE', path, { agent: caller.agentSession });
|
|
361
|
+
}
|
|
362
|
+
docPath(appId, collection, docId) {
|
|
363
|
+
return `/apps/${requireAppId(appId)}/data/${requireCollection(collection)}/${encodeURIComponent(requireDocId(docId))}`;
|
|
364
|
+
}
|
|
365
|
+
validateFiles(files) {
|
|
366
|
+
if (!Array.isArray(files) || files.length === 0)
|
|
367
|
+
throw validation('files must be a non-empty array of { path, contentBase64 }.');
|
|
368
|
+
return files.map((f, i) => {
|
|
369
|
+
const o = (f ?? {});
|
|
370
|
+
if (typeof o.path !== 'string' || !o.path || o.path.startsWith('/') || o.path.split('/').includes('..')) {
|
|
371
|
+
throw validation(`files[${i}].path must be a relative path inside the bundle.`);
|
|
372
|
+
}
|
|
373
|
+
if (typeof o.contentBase64 !== 'string')
|
|
374
|
+
throw validation(`files[${i}].contentBase64 is required.`);
|
|
375
|
+
return {
|
|
376
|
+
path: o.path,
|
|
377
|
+
contentBase64: o.contentBase64,
|
|
378
|
+
...(typeof o.contentType === 'string' && o.contentType ? { contentType: o.contentType } : {}),
|
|
379
|
+
};
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
//# sourceMappingURL=apps.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apps.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/apps/apps.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crewly Apps wiring: the shared registry / Cloud client / service the
|
|
3
|
+
* `/api/apps` controller uses, and the change poller started at boot
|
|
4
|
+
* (specs/2026-10-04-crewly-apps-p2.md).
|
|
5
|
+
*
|
|
6
|
+
* @module services/apps/apps.wiring
|
|
7
|
+
*/
|
|
8
|
+
import { AppsCloudClient } from './apps-cloud.client.js';
|
|
9
|
+
import { AppsRegistryService } from './apps-registry.service.js';
|
|
10
|
+
import { AppsService } from './apps.service.js';
|
|
11
|
+
import { AppWakeService } from './app-wake.service.js';
|
|
12
|
+
/** The team shape the apps code reads. */
|
|
13
|
+
export interface AppsTeam {
|
|
14
|
+
members?: Array<{
|
|
15
|
+
sessionName?: string;
|
|
16
|
+
name?: string;
|
|
17
|
+
}>;
|
|
18
|
+
}
|
|
19
|
+
/** Where teams come from. */
|
|
20
|
+
export type AppsTeamsSource = () => Promise<AppsTeam[]>;
|
|
21
|
+
interface AppsParts {
|
|
22
|
+
client: AppsCloudClient;
|
|
23
|
+
registry: AppsRegistryService;
|
|
24
|
+
service: AppsService;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* This instance's Cloud device id (what `X-Crewly-Instance` names).
|
|
28
|
+
*
|
|
29
|
+
* @returns The id, or null before the Slack instance registry resolved it
|
|
30
|
+
*/
|
|
31
|
+
export declare function currentInstanceId(): Promise<string | null>;
|
|
32
|
+
/**
|
|
33
|
+
* Whether two sessions are members of the same team.
|
|
34
|
+
*
|
|
35
|
+
* @param teams - Teams source
|
|
36
|
+
* @returns Predicate
|
|
37
|
+
*/
|
|
38
|
+
export declare function sameTeamFrom(teams: AppsTeamsSource): (a: string, b: string) => Promise<boolean>;
|
|
39
|
+
/**
|
|
40
|
+
* Resolve an `ask` target name to a session — only inside the publisher's
|
|
41
|
+
* own team (by session or display name, case-insensitive).
|
|
42
|
+
*
|
|
43
|
+
* @param teams - Teams source
|
|
44
|
+
* @returns Resolver
|
|
45
|
+
*/
|
|
46
|
+
export declare function teamAgentResolver(teams: AppsTeamsSource): (name: string, publisher: string) => Promise<string | null>;
|
|
47
|
+
/**
|
|
48
|
+
* The shared Apps parts, built on first use.
|
|
49
|
+
*
|
|
50
|
+
* @param teams - Teams source (default: the storage service)
|
|
51
|
+
* @returns Client, registry and service
|
|
52
|
+
*/
|
|
53
|
+
export declare function getAppsParts(teams?: AppsTeamsSource): AppsParts;
|
|
54
|
+
/**
|
|
55
|
+
* Replace the shared parts (tests), or null to rebuild lazily.
|
|
56
|
+
*
|
|
57
|
+
* @param next - Parts or null
|
|
58
|
+
*/
|
|
59
|
+
export declare function setAppsParts(next: AppsParts | null): void;
|
|
60
|
+
/** Inputs of {@link startAppWake}. */
|
|
61
|
+
export interface StartAppWakeInput {
|
|
62
|
+
/** Agent skills root (`config/skills/agent`) */
|
|
63
|
+
skillsPath: string;
|
|
64
|
+
/** Wake an agent with a message; `activate` = start it first when it is down */
|
|
65
|
+
sendToAgent: (session: string, text: string, activate: boolean) => Promise<boolean>;
|
|
66
|
+
/** Hand a message to the orchestrator */
|
|
67
|
+
sendToOrchestrator: (text: string) => Promise<boolean>;
|
|
68
|
+
/** Whether an agent's session is running */
|
|
69
|
+
sessionExists: (session: string) => boolean;
|
|
70
|
+
/** Teams on this instance */
|
|
71
|
+
getTeams: AppsTeamsSource;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Start the app change poller (idempotent).
|
|
75
|
+
*
|
|
76
|
+
* @param input - Delivery callbacks and paths
|
|
77
|
+
* @returns The running service
|
|
78
|
+
*/
|
|
79
|
+
export declare function startAppWake(input: StartAppWakeInput): AppWakeService;
|
|
80
|
+
/** Stop the poller (shutdown; tests). */
|
|
81
|
+
export declare function stopAppWake(): void;
|
|
82
|
+
export {};
|
|
83
|
+
//# sourceMappingURL=apps.wiring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apps.wiring.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/apps/apps.wiring.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAwB,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,0CAA0C;AAC1C,MAAM,WAAW,QAAQ;IACvB,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1D;AAED,6BAA6B;AAC7B,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;AAExD,UAAU,SAAS;IACjB,MAAM,EAAE,eAAe,CAAC;IACxB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,OAAO,EAAE,WAAW,CAAC;CACtB;AAWD;;;;GAIG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIhE;AAaD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,eAAe,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAK/F;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,eAAe,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAWrH;AAYD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,GAAE,eAA8B,GAAG,SAAS,CAO7E;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,CAEzD;AAED,sCAAsC;AACtC,MAAM,WAAW,iBAAiB;IAChC,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACpF,yCAAyC;IACzC,kBAAkB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACvD,4CAA4C;IAC5C,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAC5C,6BAA6B;IAC7B,QAAQ,EAAE,eAAe,CAAC;CAC3B;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,cAAc,CAarE;AAED,yCAAyC;AACzC,wBAAgB,WAAW,IAAI,IAAI,CAGlC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crewly Apps wiring: the shared registry / Cloud client / service the
|
|
3
|
+
* `/api/apps` controller uses, and the change poller started at boot
|
|
4
|
+
* (specs/2026-10-04-crewly-apps-p2.md).
|
|
5
|
+
*
|
|
6
|
+
* @module services/apps/apps.wiring
|
|
7
|
+
*/
|
|
8
|
+
import { getCrewlyHomePath } from '../core/crewly-home.utils.js';
|
|
9
|
+
import { getSlackInstanceRegistryService } from '../slack/slack-instance-registry.service.js';
|
|
10
|
+
import { AppsCloudClient } from './apps-cloud.client.js';
|
|
11
|
+
import { AppsRegistryService } from './apps-registry.service.js';
|
|
12
|
+
import { AppsService } from './apps.service.js';
|
|
13
|
+
import { AppWakeService } from './app-wake.service.js';
|
|
14
|
+
let parts = null;
|
|
15
|
+
let wake = null;
|
|
16
|
+
/** Default teams source: the storage service, loaded lazily. */
|
|
17
|
+
const defaultTeams = async () => {
|
|
18
|
+
const { StorageService } = await import('../core/storage.service.js');
|
|
19
|
+
return StorageService.getInstance().getTeams();
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* This instance's Cloud device id (what `X-Crewly-Instance` names).
|
|
23
|
+
*
|
|
24
|
+
* @returns The id, or null before the Slack instance registry resolved it
|
|
25
|
+
*/
|
|
26
|
+
export async function currentInstanceId() {
|
|
27
|
+
const registry = getSlackInstanceRegistryService();
|
|
28
|
+
if (!registry)
|
|
29
|
+
return null;
|
|
30
|
+
return registry.getInstanceId() ?? (await registry.resolveInstanceId());
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The team that has this session as a member.
|
|
34
|
+
*
|
|
35
|
+
* @param teams - Teams
|
|
36
|
+
* @param session - Agent session
|
|
37
|
+
* @returns The team, or undefined
|
|
38
|
+
*/
|
|
39
|
+
function teamOf(teams, session) {
|
|
40
|
+
return teams.find((t) => (t.members ?? []).some((m) => m.sessionName === session));
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Whether two sessions are members of the same team.
|
|
44
|
+
*
|
|
45
|
+
* @param teams - Teams source
|
|
46
|
+
* @returns Predicate
|
|
47
|
+
*/
|
|
48
|
+
export function sameTeamFrom(teams) {
|
|
49
|
+
return async (a, b) => {
|
|
50
|
+
const team = teamOf(await teams(), a);
|
|
51
|
+
return !!team && (team.members ?? []).some((m) => m.sessionName === b);
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Resolve an `ask` target name to a session — only inside the publisher's
|
|
56
|
+
* own team (by session or display name, case-insensitive).
|
|
57
|
+
*
|
|
58
|
+
* @param teams - Teams source
|
|
59
|
+
* @returns Resolver
|
|
60
|
+
*/
|
|
61
|
+
export function teamAgentResolver(teams) {
|
|
62
|
+
return async (name, publisher) => {
|
|
63
|
+
const team = teamOf(await teams(), publisher);
|
|
64
|
+
if (!team)
|
|
65
|
+
return null;
|
|
66
|
+
const wanted = name.trim().toLowerCase();
|
|
67
|
+
for (const m of team.members ?? []) {
|
|
68
|
+
if (!m.sessionName)
|
|
69
|
+
continue;
|
|
70
|
+
if (m.sessionName.toLowerCase() === wanted || (m.name ?? '').trim().toLowerCase() === wanted)
|
|
71
|
+
return m.sessionName;
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Post the app card where the agent talks with the owner, through the same
|
|
78
|
+
* resolver `reply` uses.
|
|
79
|
+
*/
|
|
80
|
+
const defaultNotifyCard = async (agentSession, text) => {
|
|
81
|
+
const { deliverReply } = await import('../orc/reply-destination.wiring.js');
|
|
82
|
+
const r = await deliverReply({ session: agentSession, content: text, addsNew: true });
|
|
83
|
+
return r.ok ? { ok: true } : { ok: false, error: r.error };
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* The shared Apps parts, built on first use.
|
|
87
|
+
*
|
|
88
|
+
* @param teams - Teams source (default: the storage service)
|
|
89
|
+
* @returns Client, registry and service
|
|
90
|
+
*/
|
|
91
|
+
export function getAppsParts(teams = defaultTeams) {
|
|
92
|
+
if (!parts) {
|
|
93
|
+
const client = new AppsCloudClient({ instanceId: currentInstanceId });
|
|
94
|
+
const registry = new AppsRegistryService(getCrewlyHomePath());
|
|
95
|
+
parts = { client, registry, service: new AppsService({ client, registry, notifyCard: defaultNotifyCard, sameTeam: sameTeamFrom(teams) }) };
|
|
96
|
+
}
|
|
97
|
+
return parts;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Replace the shared parts (tests), or null to rebuild lazily.
|
|
101
|
+
*
|
|
102
|
+
* @param next - Parts or null
|
|
103
|
+
*/
|
|
104
|
+
export function setAppsParts(next) {
|
|
105
|
+
parts = next;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Start the app change poller (idempotent).
|
|
109
|
+
*
|
|
110
|
+
* @param input - Delivery callbacks and paths
|
|
111
|
+
* @returns The running service
|
|
112
|
+
*/
|
|
113
|
+
export function startAppWake(input) {
|
|
114
|
+
if (wake)
|
|
115
|
+
return wake;
|
|
116
|
+
const { client, registry } = getAppsParts(input.getTeams);
|
|
117
|
+
wake = new AppWakeService({
|
|
118
|
+
client,
|
|
119
|
+
registry,
|
|
120
|
+
skillsPath: input.skillsPath,
|
|
121
|
+
deliver: (session, text, opts) => (session ? input.sendToAgent(session, text, opts.activate) : input.sendToOrchestrator(text)),
|
|
122
|
+
resolveAgent: teamAgentResolver(input.getTeams),
|
|
123
|
+
isRunning: input.sessionExists,
|
|
124
|
+
});
|
|
125
|
+
wake.start();
|
|
126
|
+
return wake;
|
|
127
|
+
}
|
|
128
|
+
/** Stop the poller (shutdown; tests). */
|
|
129
|
+
export function stopAppWake() {
|
|
130
|
+
wake?.stop();
|
|
131
|
+
wake = null;
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=apps.wiring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apps.wiring.js","sourceRoot":"","sources":["../../../../../../backend/src/services/apps/apps.wiring.ts"],"names":[],"mappings":"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"}
|