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,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AppWakeService — polls the change feed of every app this instance
|
|
3
|
+
* published and wakes the agent that published it when the owner changes
|
|
4
|
+
* something (specs/2026-10-04-crewly-apps-p2.md §5).
|
|
5
|
+
*
|
|
6
|
+
* - Every POLL_INTERVAL_MS, the apps that are due are polled with
|
|
7
|
+
* `GET changes?since=<cursor>&wait=0`, POLL_CONCURRENCY at a time, each
|
|
8
|
+
* request capped at POLL_REQUEST_TIMEOUT_MS. A failing app backs off on
|
|
9
|
+
* its own (×2 up to POLL_MAX_BACKOFF_MS); the others keep their cadence.
|
|
10
|
+
* - Only owner changes wake (data written in the app, `notify` / `ask`);
|
|
11
|
+
* every agent write — the agent's own included — is skipped.
|
|
12
|
+
* - The first change for (app, recipient) opens a BATCH_WINDOW_MS window; a
|
|
13
|
+
* successful wake starts a COOLDOWN_MS quiet period (persisted, so it
|
|
14
|
+
* survives a restart) during which changes keep collecting.
|
|
15
|
+
* - A failed delivery keeps the batch (and the cursor before it) and is
|
|
16
|
+
* retried with backoff; after WAKE_FAILS_BEFORE_ORC_NOTICE failures the
|
|
17
|
+
* orchestrator is told once.
|
|
18
|
+
* - An `ask` reaches a named agent only when it is in the publisher's team
|
|
19
|
+
* and already running; it never starts a stopped agent.
|
|
20
|
+
*
|
|
21
|
+
* @module services/apps/app-wake.service
|
|
22
|
+
*/
|
|
23
|
+
import { CREWLY_APPS_CONSTANTS } from '../../constants.js';
|
|
24
|
+
import { LoggerService } from '../core/logger.service.js';
|
|
25
|
+
import { AppsCloudError } from './apps-cloud.client.js';
|
|
26
|
+
import { buildAppWakeMessage, safeAppName } from './app-wake-message.js';
|
|
27
|
+
const C = CREWLY_APPS_CONSTANTS;
|
|
28
|
+
/** Recipient key for the orchestrator (never a valid session name). */
|
|
29
|
+
export const ORC_RECIPIENT = '\u0000orchestrator';
|
|
30
|
+
/**
|
|
31
|
+
* Change poller and agent waker for Crewly Apps.
|
|
32
|
+
*/
|
|
33
|
+
export class AppWakeService {
|
|
34
|
+
deps;
|
|
35
|
+
now;
|
|
36
|
+
logger;
|
|
37
|
+
timer = null;
|
|
38
|
+
running = false;
|
|
39
|
+
ticking = null;
|
|
40
|
+
batches = new Map();
|
|
41
|
+
lastWakeAt = new Map();
|
|
42
|
+
/** Highest seq read per app (the registry holds what is safe to persist) */
|
|
43
|
+
fetched = new Map();
|
|
44
|
+
/** Seqs above the safe cursor already delivered, per app */
|
|
45
|
+
delivered = new Map();
|
|
46
|
+
backoff = new Map();
|
|
47
|
+
constructor(deps) {
|
|
48
|
+
this.deps = deps;
|
|
49
|
+
this.now = deps.now ?? (() => Date.now());
|
|
50
|
+
this.logger = deps.logger ?? LoggerService.getInstance().createComponentLogger('AppWake');
|
|
51
|
+
}
|
|
52
|
+
/** Start polling (first tick after one interval). */
|
|
53
|
+
start() {
|
|
54
|
+
if (this.running)
|
|
55
|
+
return;
|
|
56
|
+
this.running = true;
|
|
57
|
+
this.schedule();
|
|
58
|
+
}
|
|
59
|
+
/** Stop polling and drop timers. Unsent batches stay behind the persisted cursor and are re-read next start. */
|
|
60
|
+
stop() {
|
|
61
|
+
this.running = false;
|
|
62
|
+
if (this.timer)
|
|
63
|
+
clearTimeout(this.timer);
|
|
64
|
+
this.timer = null;
|
|
65
|
+
for (const b of this.batches.values())
|
|
66
|
+
if (b.timer)
|
|
67
|
+
clearTimeout(b.timer);
|
|
68
|
+
this.batches.clear();
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Per-app backoff state (tests).
|
|
72
|
+
*
|
|
73
|
+
* @param appId - App id
|
|
74
|
+
* @returns Failures in a row and when the app is next due, or null when healthy
|
|
75
|
+
*/
|
|
76
|
+
appBackoff(appId) {
|
|
77
|
+
const b = this.backoff.get(appId);
|
|
78
|
+
return b ? { ...b } : null;
|
|
79
|
+
}
|
|
80
|
+
schedule() {
|
|
81
|
+
if (!this.running)
|
|
82
|
+
return;
|
|
83
|
+
this.timer = setTimeout(() => {
|
|
84
|
+
this.timer = null;
|
|
85
|
+
void this.tick().finally(() => this.schedule());
|
|
86
|
+
}, C.POLL_INTERVAL_MS);
|
|
87
|
+
this.timer.unref?.();
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* One pass over the apps that are due. Exposed for tests and for an immediate poll.
|
|
91
|
+
*/
|
|
92
|
+
async tick() {
|
|
93
|
+
if (this.ticking)
|
|
94
|
+
return this.ticking;
|
|
95
|
+
this.ticking = this.runTick().finally(() => {
|
|
96
|
+
this.ticking = null;
|
|
97
|
+
});
|
|
98
|
+
return this.ticking;
|
|
99
|
+
}
|
|
100
|
+
async runTick() {
|
|
101
|
+
if (!this.deps.client.isAvailable())
|
|
102
|
+
return;
|
|
103
|
+
const now = this.now();
|
|
104
|
+
const due = (await this.deps.registry.list()).filter((e) => !e.deleted && (this.backoff.get(e.appId)?.nextAt ?? 0) <= now);
|
|
105
|
+
let next = 0;
|
|
106
|
+
const worker = async () => {
|
|
107
|
+
while (next < due.length) {
|
|
108
|
+
const app = due[next++];
|
|
109
|
+
await this.pollOne(app);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
await Promise.all(Array.from({ length: Math.min(C.POLL_CONCURRENCY, due.length) }, worker));
|
|
113
|
+
}
|
|
114
|
+
async pollOne(app) {
|
|
115
|
+
try {
|
|
116
|
+
await this.pollApp(app);
|
|
117
|
+
this.backoff.delete(app.appId);
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
if (err instanceof AppsCloudError && err.status === 404) {
|
|
121
|
+
this.logger.info('App no longer exists in Crewly Cloud; stopped polling it', { appId: app.appId });
|
|
122
|
+
await this.deps.registry.markDeleted(app.appId);
|
|
123
|
+
this.backoff.delete(app.appId);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const failures = (this.backoff.get(app.appId)?.failures ?? 0) + 1;
|
|
127
|
+
const wait = Math.min(C.POLL_INTERVAL_MS * 2 ** failures, C.POLL_MAX_BACKOFF_MS);
|
|
128
|
+
this.backoff.set(app.appId, { failures, nextAt: this.now() + wait });
|
|
129
|
+
this.logger.warn('Polling app changes failed', { appId: app.appId, failures, retryInMs: wait, error: err instanceof Error ? err.message : String(err) });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
deliveredSet(app) {
|
|
133
|
+
let set = this.delivered.get(app.appId);
|
|
134
|
+
if (!set) {
|
|
135
|
+
set = new Set(app.delivered ?? []);
|
|
136
|
+
this.delivered.set(app.appId, set);
|
|
137
|
+
}
|
|
138
|
+
return set;
|
|
139
|
+
}
|
|
140
|
+
async pollApp(app) {
|
|
141
|
+
const opts = { timeoutMs: C.POLL_REQUEST_TIMEOUT_MS };
|
|
142
|
+
if (app.cursor === null || app.cursor === undefined) {
|
|
143
|
+
// Never polled: start from now, never replay history.
|
|
144
|
+
const head = await this.deps.client.request('GET', `/apps/${app.appId}/changes`, opts);
|
|
145
|
+
this.fetched.set(app.appId, head.seq);
|
|
146
|
+
await this.deps.registry.setProgress(app.appId, head.seq, []);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const done = this.deliveredSet(app);
|
|
150
|
+
let since = Math.max(app.cursor, this.fetched.get(app.appId) ?? app.cursor);
|
|
151
|
+
for (let page = 0; page < C.POLL_MAX_PAGES; page++) {
|
|
152
|
+
const res = await this.deps.client.request('GET', `/apps/${app.appId}/changes`, { ...opts, query: { since, wait: 0 } });
|
|
153
|
+
const changes = Array.isArray(res.changes) ? res.changes : [];
|
|
154
|
+
for (const change of changes) {
|
|
155
|
+
if (typeof change.seq === 'number' && change.seq > since && !done.has(change.seq))
|
|
156
|
+
await this.handle(app, change);
|
|
157
|
+
}
|
|
158
|
+
since = Math.max(since, typeof res.seq === 'number' ? res.seq : since);
|
|
159
|
+
this.fetched.set(app.appId, since);
|
|
160
|
+
if (changes.length < C.CHANGES_PAGE)
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
await this.persistProgress(app.appId);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Persist the safe cursor — before the first change of any unsent batch
|
|
167
|
+
* for the app — plus the seqs above it that were already delivered, so a
|
|
168
|
+
* restart neither loses a pending batch nor repeats a delivered one.
|
|
169
|
+
*/
|
|
170
|
+
async persistProgress(appId) {
|
|
171
|
+
const fetched = this.fetched.get(appId);
|
|
172
|
+
if (fetched === undefined)
|
|
173
|
+
return;
|
|
174
|
+
let safe = fetched;
|
|
175
|
+
for (const b of this.batches.values()) {
|
|
176
|
+
if (b.appId === appId)
|
|
177
|
+
safe = Math.min(safe, b.firstSeq - 1);
|
|
178
|
+
}
|
|
179
|
+
const set = this.delivered.get(appId) ?? new Set();
|
|
180
|
+
for (const seq of set)
|
|
181
|
+
if (seq <= safe)
|
|
182
|
+
set.delete(seq);
|
|
183
|
+
while (set.size > C.MAX_DELIVERED_SEQS)
|
|
184
|
+
set.delete(Math.min(...set));
|
|
185
|
+
this.delivered.set(appId, set);
|
|
186
|
+
await this.deps.registry.setProgress(appId, safe, [...set]);
|
|
187
|
+
}
|
|
188
|
+
async recipientFor(app, change) {
|
|
189
|
+
const publisher = app.agentSession ?? null;
|
|
190
|
+
const named = change.kind === 'event' && change.event?.type === 'ask' ? change.event.agent : undefined;
|
|
191
|
+
if (publisher && typeof named === 'string' && this.deps.resolveAgent) {
|
|
192
|
+
const target = await this.deps.resolveAgent(named, publisher).catch(() => null);
|
|
193
|
+
// Only a running teammate; an ask never starts a stopped agent.
|
|
194
|
+
if (target && target !== publisher && this.deps.isRunning?.(target))
|
|
195
|
+
return { session: target, activate: false };
|
|
196
|
+
}
|
|
197
|
+
return { session: publisher, activate: true };
|
|
198
|
+
}
|
|
199
|
+
async handle(app, change) {
|
|
200
|
+
// Only the owner's changes wake; any agent write (its own included) does not.
|
|
201
|
+
if (change.actor?.kind !== 'owner')
|
|
202
|
+
return;
|
|
203
|
+
if (change.kind === 'event') {
|
|
204
|
+
if (change.event?.type !== 'notify' && change.event?.type !== 'ask')
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
else if (change.kind !== 'data') {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const { session, activate } = await this.recipientFor(app, change);
|
|
211
|
+
const recipient = session ?? ORC_RECIPIENT;
|
|
212
|
+
const key = `${app.appId}\u0000${recipient}`;
|
|
213
|
+
let batch = this.batches.get(key);
|
|
214
|
+
if (!batch) {
|
|
215
|
+
const last = this.lastWakeAt.get(key) ?? app.wakes?.[recipient] ?? -Infinity;
|
|
216
|
+
const delay = Math.max(C.BATCH_WINDOW_MS, last + C.COOLDOWN_MS - this.now());
|
|
217
|
+
batch = {
|
|
218
|
+
appId: app.appId,
|
|
219
|
+
session,
|
|
220
|
+
activate,
|
|
221
|
+
dataChanges: [],
|
|
222
|
+
events: [],
|
|
223
|
+
dataTotal: 0,
|
|
224
|
+
eventsTotal: 0,
|
|
225
|
+
seqs: [],
|
|
226
|
+
firstSeq: change.seq,
|
|
227
|
+
timer: null,
|
|
228
|
+
failures: 0,
|
|
229
|
+
orcNotified: false,
|
|
230
|
+
};
|
|
231
|
+
this.batches.set(key, batch);
|
|
232
|
+
this.arm(key, batch, delay);
|
|
233
|
+
}
|
|
234
|
+
batch.seqs.push(change.seq);
|
|
235
|
+
if (batch.seqs.length > C.MAX_DELIVERED_SEQS)
|
|
236
|
+
batch.seqs.shift();
|
|
237
|
+
if (change.kind === 'event') {
|
|
238
|
+
batch.eventsTotal++;
|
|
239
|
+
batch.events.push(change);
|
|
240
|
+
if (batch.events.length > C.MAX_EVENTS_PER_WAKE)
|
|
241
|
+
batch.events.shift();
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
batch.dataTotal++;
|
|
245
|
+
batch.dataChanges.push(change);
|
|
246
|
+
if (batch.dataChanges.length > C.MAX_BATCH_DATA_CHANGES)
|
|
247
|
+
batch.dataChanges.shift();
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
arm(key, batch, delay) {
|
|
251
|
+
if (batch.timer)
|
|
252
|
+
clearTimeout(batch.timer);
|
|
253
|
+
batch.timer = setTimeout(() => void this.flush(key), delay);
|
|
254
|
+
batch.timer.unref?.();
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Send one batch now (timer callback; tests). On failure the batch stays
|
|
258
|
+
* pending and is retried with backoff.
|
|
259
|
+
*
|
|
260
|
+
* @param key - Batch key
|
|
261
|
+
* @returns Whether a message was delivered
|
|
262
|
+
*/
|
|
263
|
+
async flush(key) {
|
|
264
|
+
const batch = this.batches.get(key);
|
|
265
|
+
if (!batch)
|
|
266
|
+
return false;
|
|
267
|
+
if (batch.timer)
|
|
268
|
+
clearTimeout(batch.timer);
|
|
269
|
+
batch.timer = null;
|
|
270
|
+
const app = await this.deps.registry.get(batch.appId);
|
|
271
|
+
const recipient = batch.session ?? ORC_RECIPIENT;
|
|
272
|
+
const text = buildAppWakeMessage({
|
|
273
|
+
appId: batch.appId,
|
|
274
|
+
appName: app?.name ?? batch.appId,
|
|
275
|
+
isPublisher: (app?.agentSession ?? null) === batch.session,
|
|
276
|
+
dataChanges: batch.dataChanges,
|
|
277
|
+
events: batch.events,
|
|
278
|
+
dataTotal: batch.dataTotal,
|
|
279
|
+
eventsTotal: batch.eventsTotal,
|
|
280
|
+
skillsPath: this.deps.skillsPath,
|
|
281
|
+
});
|
|
282
|
+
let ok = false;
|
|
283
|
+
try {
|
|
284
|
+
ok = await this.deps.deliver(batch.session, text, { activate: batch.activate });
|
|
285
|
+
}
|
|
286
|
+
catch (err) {
|
|
287
|
+
this.logger.warn('App change wake failed', { appId: batch.appId, session: batch.session, error: err instanceof Error ? err.message : String(err) });
|
|
288
|
+
}
|
|
289
|
+
if (!ok) {
|
|
290
|
+
batch.failures++;
|
|
291
|
+
const retry = Math.min(C.WAKE_RETRY_BASE_MS * 2 ** (batch.failures - 1), C.WAKE_RETRY_MAX_MS);
|
|
292
|
+
this.logger.warn('App change wake was not delivered; will retry', { appId: batch.appId, session: batch.session ?? 'orchestrator', failures: batch.failures, retryInMs: retry });
|
|
293
|
+
if (batch.failures >= C.WAKE_FAILS_BEFORE_ORC_NOTICE && !batch.orcNotified && batch.session !== null) {
|
|
294
|
+
batch.orcNotified = true;
|
|
295
|
+
const notice = `[APP CHANGES] The owner's changes in app "${safeAppName(app?.name ?? batch.appId)}" (${batch.appId}) could not be delivered to ` +
|
|
296
|
+
`${batch.session} after ${batch.failures} tries. Crewly keeps retrying. Check whether that agent is stuck or signed out.`;
|
|
297
|
+
await this.deps.deliver(null, notice, { activate: false }).catch(() => false);
|
|
298
|
+
}
|
|
299
|
+
if (this.batches.get(key) === batch)
|
|
300
|
+
this.arm(key, batch, retry);
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
this.batches.delete(key);
|
|
304
|
+
const at = this.now();
|
|
305
|
+
this.lastWakeAt.set(key, at);
|
|
306
|
+
await this.deps.registry.setLastWake(batch.appId, recipient, at).catch(() => undefined);
|
|
307
|
+
const set = this.delivered.get(batch.appId) ?? new Set();
|
|
308
|
+
for (const seq of batch.seqs)
|
|
309
|
+
set.add(seq);
|
|
310
|
+
this.delivered.set(batch.appId, set);
|
|
311
|
+
this.logger.info('Woke agent for app changes', {
|
|
312
|
+
appId: batch.appId,
|
|
313
|
+
session: batch.session ?? 'orchestrator',
|
|
314
|
+
dataChanges: batch.dataTotal,
|
|
315
|
+
events: batch.eventsTotal,
|
|
316
|
+
});
|
|
317
|
+
await this.persistProgress(batch.appId).catch(() => undefined);
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
320
|
+
/** @returns Keys of batches waiting to be sent (tests) */
|
|
321
|
+
pendingKeys() {
|
|
322
|
+
return [...this.batches.keys()];
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
//# sourceMappingURL=app-wake.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-wake.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/apps/app-wake.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AppsCloudClient — this instance's calls to the Crewly Apps agent API
|
|
3
|
+
* (`<cloudUrl>/api/apps/v1`, crewly-services apps/SPEC.md §3.1).
|
|
4
|
+
*
|
|
5
|
+
* Authenticates with the Cloud access token the {@link CloudClientService}
|
|
6
|
+
* holds and refreshes, bound to this instance (`X-Crewly-Instance`) and
|
|
7
|
+
* attributed to the calling agent (`X-Crewly-Agent`). Agents never see the
|
|
8
|
+
* token: they reach this through `/api/apps` (specs/2026-10-04-crewly-apps-p2.md).
|
|
9
|
+
*
|
|
10
|
+
* @module services/apps/apps-cloud.client
|
|
11
|
+
*/
|
|
12
|
+
/** The slice of the Cloud client used here (injectable for tests). */
|
|
13
|
+
export interface AppsCloudSession {
|
|
14
|
+
isConnected(): boolean;
|
|
15
|
+
getToken(): string | null;
|
|
16
|
+
getCloudUrl(): string | null;
|
|
17
|
+
tryRefreshToken(): Promise<boolean>;
|
|
18
|
+
}
|
|
19
|
+
/** Constructor dependencies. */
|
|
20
|
+
export interface AppsCloudClientDeps {
|
|
21
|
+
cloud?: AppsCloudSession;
|
|
22
|
+
/** This instance's Cloud device id (the Slack instance registry's id) */
|
|
23
|
+
instanceId: () => Promise<string | null>;
|
|
24
|
+
fetchImpl?: typeof fetch;
|
|
25
|
+
}
|
|
26
|
+
/** A failed Apps call: HTTP status and a stable code for the controller and skills. */
|
|
27
|
+
export declare class AppsCloudError extends Error {
|
|
28
|
+
readonly status: number;
|
|
29
|
+
readonly code: string;
|
|
30
|
+
constructor(status: number, code: string, message: string);
|
|
31
|
+
}
|
|
32
|
+
/** Options of one request. */
|
|
33
|
+
export interface AppsRequestOptions {
|
|
34
|
+
/** JSON body */
|
|
35
|
+
body?: unknown;
|
|
36
|
+
/** Query parameters (undefined values are dropped) */
|
|
37
|
+
query?: Record<string, string | number | undefined>;
|
|
38
|
+
/** Agent session to attribute the call to; omitted for the owner */
|
|
39
|
+
agent?: string;
|
|
40
|
+
/** Request timeout (default REQUEST_TIMEOUT_MS) */
|
|
41
|
+
timeoutMs?: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Typed wrapper over the Apps agent API.
|
|
45
|
+
*/
|
|
46
|
+
export declare class AppsCloudClient {
|
|
47
|
+
private readonly deps;
|
|
48
|
+
private readonly cloud;
|
|
49
|
+
private readonly fetchImpl;
|
|
50
|
+
constructor(deps: AppsCloudClientDeps);
|
|
51
|
+
/**
|
|
52
|
+
* Whether a Cloud login is present (a call can be attempted).
|
|
53
|
+
*
|
|
54
|
+
* @returns True when connected with a token and URL
|
|
55
|
+
*/
|
|
56
|
+
isAvailable(): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Call the Apps API and return its `data`.
|
|
59
|
+
*
|
|
60
|
+
* A 401 refreshes the Cloud token once and retries. Cloud's
|
|
61
|
+
* `{ success:false, error, code }` becomes an {@link AppsCloudError} with
|
|
62
|
+
* Cloud's status and code. The token is never part of an error.
|
|
63
|
+
*
|
|
64
|
+
* @param method - HTTP method
|
|
65
|
+
* @param path - Path under `/api/apps/v1` (starts with `/`)
|
|
66
|
+
* @param opts - Body, query, agent attribution
|
|
67
|
+
* @returns The response `data`
|
|
68
|
+
* @throws AppsCloudError not_logged_in / instance_unknown / network / Cloud's code
|
|
69
|
+
*/
|
|
70
|
+
request<T>(method: string, path: string, opts?: AppsRequestOptions): Promise<T>;
|
|
71
|
+
private static readJson;
|
|
72
|
+
private send;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=apps-cloud.client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apps-cloud.client.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/apps/apps-cloud.client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,sEAAsE;AACtE,MAAM,WAAW,gBAAgB;IAC/B,WAAW,IAAI,OAAO,CAAC;IACvB,QAAQ,IAAI,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,IAAI,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CACrC;AAED,gCAAgC;AAChC,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,yEAAyE;IACzE,UAAU,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,uFAAuF;AACvF,qBAAa,cAAe,SAAQ,KAAK;aAErB,MAAM,EAAE,MAAM;aACd,IAAI,EAAE,MAAM;gBADZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM;CAKlB;AAED,8BAA8B;AAC9B,MAAM,WAAW,kBAAkB;IACjC,gBAAgB;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC;IACpD,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,qBAAa,eAAe;IAId,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;gBAEZ,IAAI,EAAE,mBAAmB;IAKtD;;;;OAIG;IACH,WAAW,IAAI,OAAO;IAItB;;;;;;;;;;;;OAYG;IACG,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,kBAAuB,GAAG,OAAO,CAAC,CAAC,CAAC;mBAwBpE,QAAQ;YASf,IAAI;CAwBnB"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AppsCloudClient — this instance's calls to the Crewly Apps agent API
|
|
3
|
+
* (`<cloudUrl>/api/apps/v1`, crewly-services apps/SPEC.md §3.1).
|
|
4
|
+
*
|
|
5
|
+
* Authenticates with the Cloud access token the {@link CloudClientService}
|
|
6
|
+
* holds and refreshes, bound to this instance (`X-Crewly-Instance`) and
|
|
7
|
+
* attributed to the calling agent (`X-Crewly-Agent`). Agents never see the
|
|
8
|
+
* token: they reach this through `/api/apps` (specs/2026-10-04-crewly-apps-p2.md).
|
|
9
|
+
*
|
|
10
|
+
* @module services/apps/apps-cloud.client
|
|
11
|
+
*/
|
|
12
|
+
import { CREWLY_APPS_CONSTANTS } from '../../constants.js';
|
|
13
|
+
import { CloudClientService } from '../cloud/cloud-client.service.js';
|
|
14
|
+
const C = CREWLY_APPS_CONSTANTS;
|
|
15
|
+
/** A failed Apps call: HTTP status and a stable code for the controller and skills. */
|
|
16
|
+
export class AppsCloudError extends Error {
|
|
17
|
+
status;
|
|
18
|
+
code;
|
|
19
|
+
constructor(status, code, message) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.status = status;
|
|
22
|
+
this.code = code;
|
|
23
|
+
this.name = 'AppsCloudError';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Typed wrapper over the Apps agent API.
|
|
28
|
+
*/
|
|
29
|
+
export class AppsCloudClient {
|
|
30
|
+
deps;
|
|
31
|
+
cloud;
|
|
32
|
+
fetchImpl;
|
|
33
|
+
constructor(deps) {
|
|
34
|
+
this.deps = deps;
|
|
35
|
+
this.cloud = deps.cloud ?? CloudClientService.getInstance();
|
|
36
|
+
this.fetchImpl = deps.fetchImpl ?? fetch;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Whether a Cloud login is present (a call can be attempted).
|
|
40
|
+
*
|
|
41
|
+
* @returns True when connected with a token and URL
|
|
42
|
+
*/
|
|
43
|
+
isAvailable() {
|
|
44
|
+
return this.cloud.isConnected() && !!this.cloud.getToken() && !!this.cloud.getCloudUrl();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Call the Apps API and return its `data`.
|
|
48
|
+
*
|
|
49
|
+
* A 401 refreshes the Cloud token once and retries. Cloud's
|
|
50
|
+
* `{ success:false, error, code }` becomes an {@link AppsCloudError} with
|
|
51
|
+
* Cloud's status and code. The token is never part of an error.
|
|
52
|
+
*
|
|
53
|
+
* @param method - HTTP method
|
|
54
|
+
* @param path - Path under `/api/apps/v1` (starts with `/`)
|
|
55
|
+
* @param opts - Body, query, agent attribution
|
|
56
|
+
* @returns The response `data`
|
|
57
|
+
* @throws AppsCloudError not_logged_in / instance_unknown / network / Cloud's code
|
|
58
|
+
*/
|
|
59
|
+
async request(method, path, opts = {}) {
|
|
60
|
+
if (!this.isAvailable()) {
|
|
61
|
+
throw new AppsCloudError(409, C.ERROR_CODES.NOT_LOGGED_IN, 'This machine is not signed in to Crewly Cloud. Run `crewly cloud login`.');
|
|
62
|
+
}
|
|
63
|
+
const instanceId = await this.deps.instanceId();
|
|
64
|
+
if (!instanceId) {
|
|
65
|
+
throw new AppsCloudError(409, C.ERROR_CODES.NO_INSTANCE, 'This machine has no Crewly Cloud instance id yet. Sign in to Crewly Cloud and try again in a minute.');
|
|
66
|
+
}
|
|
67
|
+
let res = await this.send(method, path, opts, instanceId);
|
|
68
|
+
if (res.status === 401 && (await this.cloud.tryRefreshToken().catch(() => false))) {
|
|
69
|
+
res = await this.send(method, path, opts, instanceId);
|
|
70
|
+
}
|
|
71
|
+
const json = await AppsCloudClient.readJson(res);
|
|
72
|
+
if (res.ok && json && json.success !== false)
|
|
73
|
+
return json.data;
|
|
74
|
+
const code = typeof json?.code === 'string' ? json.code : res.status === 401 ? C.ERROR_CODES.NOT_LOGGED_IN : `http_${res.status}`;
|
|
75
|
+
const message = typeof json?.error === 'string'
|
|
76
|
+
? json.error
|
|
77
|
+
: res.status === 401
|
|
78
|
+
? 'Crewly Cloud rejected the session. Run `crewly cloud login` again.'
|
|
79
|
+
: `Crewly Apps request failed (${res.status}).`;
|
|
80
|
+
throw new AppsCloudError(res.status === 401 ? 409 : res.status, code, message);
|
|
81
|
+
}
|
|
82
|
+
static async readJson(res) {
|
|
83
|
+
try {
|
|
84
|
+
const parsed = await res.json();
|
|
85
|
+
return parsed && typeof parsed === 'object' ? parsed : null;
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async send(method, path, opts, instanceId) {
|
|
92
|
+
const base = `${(this.cloud.getCloudUrl() ?? '').replace(/\/+$/, '')}${C.CLOUD_PATH}`;
|
|
93
|
+
const url = new URL(`${base}${path}`);
|
|
94
|
+
for (const [k, v] of Object.entries(opts.query ?? {})) {
|
|
95
|
+
if (v !== undefined && v !== '')
|
|
96
|
+
url.searchParams.set(k, String(v));
|
|
97
|
+
}
|
|
98
|
+
const headers = {
|
|
99
|
+
Authorization: `Bearer ${this.cloud.getToken() ?? ''}`,
|
|
100
|
+
'X-Crewly-Instance': instanceId,
|
|
101
|
+
};
|
|
102
|
+
if (opts.agent)
|
|
103
|
+
headers['X-Crewly-Agent'] = opts.agent;
|
|
104
|
+
if (opts.body !== undefined)
|
|
105
|
+
headers['Content-Type'] = 'application/json';
|
|
106
|
+
try {
|
|
107
|
+
return await this.fetchImpl(url.toString(), {
|
|
108
|
+
method,
|
|
109
|
+
headers,
|
|
110
|
+
...(opts.body !== undefined ? { body: JSON.stringify(opts.body) } : {}),
|
|
111
|
+
signal: AbortSignal.timeout(opts.timeoutMs ?? C.REQUEST_TIMEOUT_MS),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
const why = err instanceof Error ? err.name : 'error';
|
|
116
|
+
throw new AppsCloudError(502, C.ERROR_CODES.NETWORK, `Could not reach Crewly Apps (${why}). Try again shortly.`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=apps-cloud.client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apps-cloud.client.js","sourceRoot":"","sources":["../../../../../../backend/src/services/apps/apps-cloud.client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AppsRegistryService — the apps this instance published, kept in
|
|
3
|
+
* `<CREWLY_HOME>/apps/registry.json`.
|
|
4
|
+
*
|
|
5
|
+
* It answers two questions: which app an agent's publish goes to (so the
|
|
6
|
+
* same agent republishing the same directory lands on the same app), and
|
|
7
|
+
* which agent to wake when an app changes. It also keeps each app's change
|
|
8
|
+
* cursor for the poller (specs/2026-10-04-crewly-apps-p2.md §2, §5).
|
|
9
|
+
*
|
|
10
|
+
* @module services/apps/apps-registry.service
|
|
11
|
+
*/
|
|
12
|
+
/** One app this instance published. */
|
|
13
|
+
export interface AppRegistryEntry {
|
|
14
|
+
appId: string;
|
|
15
|
+
name: string;
|
|
16
|
+
url: string;
|
|
17
|
+
/** The agent woken for this app's changes (the last publisher); null = orchestrator */
|
|
18
|
+
agentSession: string | null;
|
|
19
|
+
/** Absolute source directory or file it was published from */
|
|
20
|
+
source: string | null;
|
|
21
|
+
currentVersion: number | null;
|
|
22
|
+
/** Last change seq handled by the poller; null until it first reads the head */
|
|
23
|
+
cursor: number | null;
|
|
24
|
+
createdAt: string;
|
|
25
|
+
updatedAt: string;
|
|
26
|
+
/** Gone from Cloud (404): no longer polled */
|
|
27
|
+
deleted?: boolean;
|
|
28
|
+
/** Last successful wake per recipient (session, or the orchestrator key), epoch ms: the cooldown survives a restart */
|
|
29
|
+
wakes?: Record<string, number>;
|
|
30
|
+
/** Seqs above `cursor` already delivered (another batch for this app is still pending): skipped when re-read */
|
|
31
|
+
delivered?: number[];
|
|
32
|
+
}
|
|
33
|
+
/** What to look an app up by when publishing. */
|
|
34
|
+
export interface AppLookup {
|
|
35
|
+
appId?: string;
|
|
36
|
+
agentSession?: string | null;
|
|
37
|
+
source?: string | null;
|
|
38
|
+
name?: string | null;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* File-backed registry. All writes are serialised in-process.
|
|
42
|
+
*/
|
|
43
|
+
export declare class AppsRegistryService {
|
|
44
|
+
private readonly file;
|
|
45
|
+
private data;
|
|
46
|
+
private chain;
|
|
47
|
+
/**
|
|
48
|
+
* @param crewlyHome - CREWLY_HOME directory
|
|
49
|
+
*/
|
|
50
|
+
constructor(crewlyHome: string);
|
|
51
|
+
private load;
|
|
52
|
+
private mutate;
|
|
53
|
+
/**
|
|
54
|
+
* Every app, deleted ones included.
|
|
55
|
+
*
|
|
56
|
+
* @returns Copies of the entries
|
|
57
|
+
*/
|
|
58
|
+
list(): Promise<AppRegistryEntry[]>;
|
|
59
|
+
/**
|
|
60
|
+
* One app by id.
|
|
61
|
+
*
|
|
62
|
+
* @param appId - App id
|
|
63
|
+
* @returns A copy, or null
|
|
64
|
+
*/
|
|
65
|
+
get(appId: string): Promise<AppRegistryEntry | null>;
|
|
66
|
+
/**
|
|
67
|
+
* The app a publish should go to: explicit id; else the same agent and
|
|
68
|
+
* source; else the same agent and name (case-insensitive). Deleted apps
|
|
69
|
+
* never match implicitly.
|
|
70
|
+
*
|
|
71
|
+
* @param q - Lookup keys
|
|
72
|
+
* @returns The entry, or null (create a new app)
|
|
73
|
+
*/
|
|
74
|
+
find(q: AppLookup): Promise<AppRegistryEntry | null>;
|
|
75
|
+
/**
|
|
76
|
+
* Insert or update an entry (fields given replace the stored ones).
|
|
77
|
+
*
|
|
78
|
+
* @param appId - App id
|
|
79
|
+
* @param patch - Fields to set
|
|
80
|
+
* @returns The stored entry
|
|
81
|
+
*/
|
|
82
|
+
upsert(appId: string, patch: Partial<Omit<AppRegistryEntry, 'appId'>>): Promise<AppRegistryEntry>;
|
|
83
|
+
/**
|
|
84
|
+
* Store the poller's progress: the cursor and the seqs above it that were
|
|
85
|
+
* already delivered (no-op for an unknown app or no change).
|
|
86
|
+
*
|
|
87
|
+
* @param appId - App id
|
|
88
|
+
* @param cursor - Safe cursor (before every undelivered change)
|
|
89
|
+
* @param delivered - Delivered seqs above the cursor
|
|
90
|
+
*/
|
|
91
|
+
setProgress(appId: string, cursor: number, delivered: number[]): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Record a successful wake for the cooldown.
|
|
94
|
+
*
|
|
95
|
+
* @param appId - App id
|
|
96
|
+
* @param recipient - Session or orchestrator key
|
|
97
|
+
* @param at - Epoch ms
|
|
98
|
+
*/
|
|
99
|
+
setLastWake(appId: string, recipient: string, at: number): Promise<void>;
|
|
100
|
+
/**
|
|
101
|
+
* Mark an app gone from Cloud.
|
|
102
|
+
*
|
|
103
|
+
* @param appId - App id
|
|
104
|
+
*/
|
|
105
|
+
markDeleted(appId: string): Promise<void>;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=apps-registry.service.d.ts.map
|