@appforge-ci/core 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/LICENSE +21 -0
  2. package/dist/agent-readiness.d.ts +163 -0
  3. package/dist/agent-readiness.d.ts.map +1 -0
  4. package/dist/agent-readiness.js +179 -0
  5. package/dist/agent-readiness.js.map +1 -0
  6. package/dist/agent-readiness.test.d.ts +2 -0
  7. package/dist/agent-readiness.test.d.ts.map +1 -0
  8. package/dist/agent-readiness.test.js +177 -0
  9. package/dist/agent-readiness.test.js.map +1 -0
  10. package/dist/api-client.d.ts +529 -0
  11. package/dist/api-client.d.ts.map +1 -0
  12. package/dist/api-client.js +551 -0
  13. package/dist/api-client.js.map +1 -0
  14. package/dist/api-client.test.d.ts +2 -0
  15. package/dist/api-client.test.d.ts.map +1 -0
  16. package/dist/api-client.test.js +305 -0
  17. package/dist/api-client.test.js.map +1 -0
  18. package/dist/build-cost.test.d.ts +2 -0
  19. package/dist/build-cost.test.d.ts.map +1 -0
  20. package/dist/build-cost.test.js +21 -0
  21. package/dist/build-cost.test.js.map +1 -0
  22. package/dist/index.d.ts +8 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +8 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/ota-artifact.d.ts +41 -0
  27. package/dist/ota-artifact.d.ts.map +1 -0
  28. package/dist/ota-artifact.js +43 -0
  29. package/dist/ota-artifact.js.map +1 -0
  30. package/dist/ota-artifact.test.d.ts +2 -0
  31. package/dist/ota-artifact.test.d.ts.map +1 -0
  32. package/dist/ota-artifact.test.js +44 -0
  33. package/dist/ota-artifact.test.js.map +1 -0
  34. package/dist/ota-bundle-hash.d.ts +38 -0
  35. package/dist/ota-bundle-hash.d.ts.map +1 -0
  36. package/dist/ota-bundle-hash.js +40 -0
  37. package/dist/ota-bundle-hash.js.map +1 -0
  38. package/dist/ota-bundle-hash.test.d.ts +2 -0
  39. package/dist/ota-bundle-hash.test.d.ts.map +1 -0
  40. package/dist/ota-bundle-hash.test.js +28 -0
  41. package/dist/ota-bundle-hash.test.js.map +1 -0
  42. package/dist/ota-rollout.d.ts +38 -0
  43. package/dist/ota-rollout.d.ts.map +1 -0
  44. package/dist/ota-rollout.js +53 -0
  45. package/dist/ota-rollout.js.map +1 -0
  46. package/dist/ota-rollout.test.d.ts +2 -0
  47. package/dist/ota-rollout.test.d.ts.map +1 -0
  48. package/dist/ota-rollout.test.js +48 -0
  49. package/dist/ota-rollout.test.js.map +1 -0
  50. package/dist/schemas.d.ts +776 -0
  51. package/dist/schemas.d.ts.map +1 -0
  52. package/dist/schemas.js +538 -0
  53. package/dist/schemas.js.map +1 -0
  54. package/dist/token-packs.test.d.ts +2 -0
  55. package/dist/token-packs.test.d.ts.map +1 -0
  56. package/dist/token-packs.test.js +34 -0
  57. package/dist/token-packs.test.js.map +1 -0
  58. package/dist/types.d.ts +445 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +80 -0
  61. package/dist/types.js.map +1 -0
  62. package/package.json +35 -0
@@ -0,0 +1,551 @@
1
+ /**
2
+ * Every `ApiClient` call is a small JSON request/response — no file
3
+ * upload/download is ever routed through this client (build artifacts and
4
+ * OTA bundles go straight to/from R2 via a presigned URL the caller fetches
5
+ * separately) — but a handful of routes (`explainBuildFailure`,
6
+ * `analyzeSmokeTest`, `askDocsChat`, `generateAppforgeConfig`) proxy to
7
+ * Anthropic server-side and can legitimately take tens of seconds for a
8
+ * real completion, well past what a plain CRUD call needs. 60s is
9
+ * generous enough to cover the slowest of those with room to spare, while
10
+ * still being a real ceiling: without one, a connection that stalls after
11
+ * opening (a network partition, a proxy holding the connection open
12
+ * without sending further bytes, a hung Worker instance) left every
13
+ * caller's `fetch` promise pending forever — same shape as `packages/
14
+ * agent/src/lib/api.ts`'s already-fixed `AgentApi.request`, but for the
15
+ * single shared client every dashboard page, CLI command, and admin-cli
16
+ * command talks to the control plane through. */
17
+ export const DEFAULT_REQUEST_TIMEOUT_MS = 60_000;
18
+ export class ApiError extends Error {
19
+ status;
20
+ body;
21
+ constructor(status, body) {
22
+ super(`API error ${status}: ${JSON.stringify(body)}`);
23
+ this.status = status;
24
+ this.body = body;
25
+ }
26
+ }
27
+ /**
28
+ * Shared "what should the user see" extraction for a caught error from
29
+ * any `ApiClient` call. `ApiError` extends `Error`, so a naive
30
+ * `err instanceof Error ? err.message : fallback` always matches an
31
+ * `ApiError` too and returns *this class's own* constructor string —
32
+ * `API error ${status}: ${JSON.stringify(body)}`, meant for logs/
33
+ * debugging — instead of the server's actual user-facing text at
34
+ * `body.error`. This was independently found and fixed the same way in
35
+ * `Login.tsx`/`Signup.tsx`/`Device.tsx`/`VerifyEmail.tsx` (dashboard)
36
+ * and `VncViewer.tsx`'s own `vncViewerErrorMessage` before this shared
37
+ * helper existed; new callers (both CLIs' top-level handlers first, per
38
+ * ROADMAP.md) should use this instead of repeating the same extraction
39
+ * inline.
40
+ */
41
+ export function apiErrorMessage(err, fallback) {
42
+ if (err instanceof ApiError) {
43
+ const body = err.body;
44
+ return typeof body?.error === "string" ? body.error : err.message;
45
+ }
46
+ return err instanceof Error ? err.message : fallback;
47
+ }
48
+ /**
49
+ * Small typed fetch wrapper shared by the CLI and the dashboard so both
50
+ * talk to the control-plane API through the same request/response shapes.
51
+ */
52
+ export class ApiClient {
53
+ opts;
54
+ constructor(opts) {
55
+ this.opts = opts;
56
+ }
57
+ async request(method, path, body, base = this.opts.baseUrl) {
58
+ const fetchImpl = this.opts.fetchImpl ?? fetch;
59
+ const res = await fetchImpl(`${base}${path}`, {
60
+ method,
61
+ headers: {
62
+ "content-type": "application/json",
63
+ ...(this.opts.token ? { authorization: `Bearer ${this.opts.token}` } : {}),
64
+ },
65
+ body: body === undefined ? undefined : JSON.stringify(body),
66
+ signal: AbortSignal.timeout(this.opts.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS),
67
+ });
68
+ const text = await res.text();
69
+ // `apps/api`'s and `apps/admin-api`'s own `jsonErrorHandler`/
70
+ // `jsonNotFoundHandler` guarantee *those two Workers* always answer
71
+ // with valid JSON, but a real deployment sits behind Cloudflare's
72
+ // edge — a gateway timeout (522/524), a WAF block, or a rate-limit
73
+ // page can all return plain-text/HTML instead, for either a non-ok
74
+ // or (more rarely) an ok response. `JSON.parse`-ing unconditionally
75
+ // used to crash every single caller (every dashboard page, both
76
+ // CLIs) with a raw, uncatchable `SyntaxError` the moment that
77
+ // happened, instead of the `ApiError`/typed rejection they already
78
+ // know how to catch. Mirrors `packages/agent/src/lib/api.ts`'s
79
+ // `AgentApi.request`, which already checks `res.ok` before ever
80
+ // parsing a body.
81
+ if (!res.ok) {
82
+ let json;
83
+ try {
84
+ json = text ? JSON.parse(text) : undefined;
85
+ }
86
+ catch {
87
+ json = text;
88
+ }
89
+ throw new ApiError(res.status, json);
90
+ }
91
+ // `null`, not `undefined` — `getOtaManifest` (the one caller that
92
+ // actually receives a truly empty, `c.body(null, 204)` response body
93
+ // from the server, apps/api/src/routes/ota.ts) is typed
94
+ // `Promise<OtaManifest | null>`, matching this codebase's own
95
+ // convention elsewhere of a real JSON `null` meaning "nothing here"
96
+ // (e.g. `rollbackOtaChannel`'s `{ release: OtaRelease | null }`).
97
+ // This used to resolve to `undefined` instead, silently breaking that
98
+ // type contract: any caller written against the declared type doing
99
+ // the natural `if (manifest === null) return;` would fall through
100
+ // and crash on `undefined.bundleUrl` on the overwhelmingly common
101
+ // "already up to date" response — the exact case this endpoint
102
+ // exists to handle cheaply and often. No other typed `request<T>`
103
+ // call site in this file expects an empty body at all (every other
104
+ // 2xx response from apps/api/apps/admin-api always carries an actual
105
+ // JSON payload), so this only changes behavior for the one caller
106
+ // this type was always meant to describe.
107
+ try {
108
+ return (text ? JSON.parse(text) : null);
109
+ }
110
+ catch {
111
+ throw new Error(`expected a JSON response but got: ${text.slice(0, 200)}`);
112
+ }
113
+ }
114
+ adminRequest(method, path, body) {
115
+ return this.request(method, path, body, this.opts.adminApiUrl ?? this.opts.baseUrl);
116
+ }
117
+ /**
118
+ * `twoFactor` is only needed on a second call, after a first call
119
+ * without it throws `ApiError(401, { requiresTotp: true })` — see
120
+ * apps/api/src/routes/auth.ts's login handler. `recoveryCode` is a
121
+ * lost-authenticator alternate to `totpCode`, never both at once.
122
+ */
123
+ login(email, password, twoFactor) {
124
+ return this.request("POST", "/auth/login", {
125
+ email,
126
+ password,
127
+ totpCode: twoFactor?.totpCode,
128
+ recoveryCode: twoFactor?.recoveryCode,
129
+ });
130
+ }
131
+ signup(email, password, name, orgName) {
132
+ return this.request("POST", "/auth/signup", {
133
+ email,
134
+ password,
135
+ name,
136
+ orgName,
137
+ });
138
+ }
139
+ me() {
140
+ return this.request("GET", "/auth/me");
141
+ }
142
+ /**
143
+ * Redeems the token from the signup verification email's link
144
+ * (`apps/api/src/lib/email-verification.ts`'s `verifyUrl`). No auth of
145
+ * its own — the route this hits (`POST /auth/verify-email`) doesn't
146
+ * require a session, since whoever clicked the link may not be logged
147
+ * in on this browser at all. Was previously unreachable from any
148
+ * client: this method, plus a dashboard route to call it, is the fix.
149
+ */
150
+ verifyEmail(token) {
151
+ return this.request("POST", "/auth/verify-email", { token });
152
+ }
153
+ /** Requires an existing session — unlike `verifyEmail`, this is only
154
+ * ever offered to an already-logged-in user who hasn't verified yet
155
+ * (see `Security.tsx`). Rate-limited server-side. */
156
+ resendVerification() {
157
+ return this.request("POST", "/auth/resend-verification");
158
+ }
159
+ /** Requires re-entering the current password — same reasoning as
160
+ * `disableTwoFactor` below: a stolen session token alone must not be
161
+ * enough to take over the account's own fallback credential.
162
+ * Rate-limited server-side, keyed by user. Also revokes every other
163
+ * live session for the account (a leaked token stops working
164
+ * immediately) — `token` is a freshly-issued replacement for *this*
165
+ * session specifically, so the caller must swap it in (e.g. into
166
+ * `session.token`) or this same request's own session gets logged
167
+ * out by its own success. */
168
+ changePassword(currentPassword, newPassword) {
169
+ return this.request("POST", "/auth/change-password", { currentPassword, newPassword });
170
+ }
171
+ /** No auth of its own — this is the entry point for someone who can't
172
+ * log in at all. Always resolves the same way regardless of whether
173
+ * the email is actually registered (see the route's own doc
174
+ * comment) — never use the response to decide whether to tell the
175
+ * caller "no account with that email". */
176
+ forgotPassword(email) {
177
+ return this.request("POST", "/auth/forgot-password", { email });
178
+ }
179
+ /** Redeems the token from the forgot-password email's link
180
+ * (`apps/api/src/lib/password-reset.ts`'s `resetUrl`). No auth of its
181
+ * own, same reasoning as `verifyEmail` above. Also revokes every
182
+ * other live session for the account and returns a fresh one, same
183
+ * as `changePassword`/`disableTwoFactor` — a reset is at least as
184
+ * strong proof of ownership as re-entering the current password. */
185
+ resetPassword(token, newPassword) {
186
+ return this.request("POST", "/auth/reset-password", { token, newPassword });
187
+ }
188
+ // --- TOTP 2FA (apps/api/src/routes/two-factor.ts) ---
189
+ /** Starts (or restarts) enrollment — the secret is only ever returned
190
+ * here and from confirmTwoFactor's success, never again afterward. */
191
+ enrollTwoFactor() {
192
+ return this.request("POST", "/auth/2fa/enroll");
193
+ }
194
+ /** Redeems the first code from an authenticator app to actually turn
195
+ * 2FA on — `recoveryCodes` is shown exactly once, same as the secret
196
+ * above; the caller is responsible for surfacing it to the user now.
197
+ * Also requires re-entering the account password, same reasoning and
198
+ * requirement as `disableTwoFactor` below: without it, any live
199
+ * session (a stolen JWT, or a CLI/webhook API token, which never
200
+ * expires on its own) was enough to confirm 2FA with an
201
+ * attacker-chosen secret, permanently locking the real account owner
202
+ * out at their next login — see docs/security.md's "2FA (TOTP)" note. */
203
+ confirmTwoFactor(code, password) {
204
+ return this.request("POST", "/auth/2fa/confirm", { code, password });
205
+ }
206
+ /** Requires re-entering the account password — see docs/security.md's
207
+ * "2FA (TOTP)" note on why a session token alone isn't enough here.
208
+ * Also revokes every other live session for the account, same
209
+ * reasoning and `token`-swap requirement as `changePassword` above —
210
+ * the JWT this very request authenticated with might be the leaked
211
+ * one 2FA existed to guard against. */
212
+ disableTwoFactor(password) {
213
+ return this.request("POST", "/auth/2fa/disable", { password });
214
+ }
215
+ /** Invalidates every existing recovery code and returns a fresh set,
216
+ * shown exactly once like the original set from confirmTwoFactor.
217
+ * Also requires re-entering the account password, same reasoning as
218
+ * `disableTwoFactor` above: without it, a stolen session token alone
219
+ * was enough to silently destroy the real owner's recovery path
220
+ * (this codebase has no account-recovery flow) and hand the
221
+ * attacker a fresh set of recovery codes instead — see
222
+ * docs/security.md's "2FA (TOTP)" note. */
223
+ regenerateRecoveryCodes(password) {
224
+ return this.request("POST", "/auth/2fa/recovery-codes/regenerate", { password });
225
+ }
226
+ /** `appforge-admin login --web`'s device-authorization flow (#5) — the CLI calls this first, no auth of its own yet. */
227
+ startDeviceAuth() {
228
+ return this.request("POST", "/auth/device/start");
229
+ }
230
+ /** Poll with the long deviceCode until status stops being "pending" — same shape as gh/OAuth device flow polling. */
231
+ pollDeviceAuth(deviceCode) {
232
+ return this.request("GET", `/auth/device/poll?device_code=${encodeURIComponent(deviceCode)}`);
233
+ }
234
+ /** Called from the dashboard (already has a user session) with the short, human-typed userCode. */
235
+ approveDeviceAuth(userCode) {
236
+ return this.request("POST", "/auth/device/approve", { userCode });
237
+ }
238
+ denyDeviceAuth(userCode) {
239
+ return this.request("POST", "/auth/device/deny", { userCode });
240
+ }
241
+ /** Drafts an appforge.yaml from real project files — see #8. `files` is path -> file contents for whatever the caller found on disk. */
242
+ generateAppforgeConfig(input) {
243
+ return this.request("POST", "/generate-appforge-config", input);
244
+ }
245
+ /** Public, unauthenticated docs Q&A widget (pricing page) — see #10. Resend the whole conversation each call; nothing is kept server-side. */
246
+ askDocsChat(history) {
247
+ return this.request("POST", "/docs-chat", { history });
248
+ }
249
+ createApiToken(orgId, label) {
250
+ return this.request("POST", `/orgs/${orgId}/tokens`, { label });
251
+ }
252
+ /** Never includes the token value itself or its hash — see
253
+ * `ApiTokenInfo`'s own docblock. */
254
+ listApiTokens(orgId, pagination) {
255
+ const params = new URLSearchParams();
256
+ if (pagination?.limit !== undefined)
257
+ params.set("limit", String(pagination.limit));
258
+ if (pagination?.offset !== undefined)
259
+ params.set("offset", String(pagination.offset));
260
+ const qs = params.toString();
261
+ return this.request("GET", `/orgs/${orgId}/tokens${qs ? `?${qs}` : ""}`);
262
+ }
263
+ /** Immediate and permanent — there's no undo once a token is
264
+ * revoked (a fresh one via `createApiToken` is the only way back). */
265
+ revokeApiToken(orgId, tokenId) {
266
+ return this.request("DELETE", `/orgs/${orgId}/tokens/${tokenId}`);
267
+ }
268
+ /** Fixes a typo'd or since-changed org name (e.g. a placeholder used
269
+ * at signup) without any of `updateApp`'s deletion/recreation
270
+ * downsides — there's nothing else to break, since unlike an app's
271
+ * `webhookSecret`, an org's identity has no dependent secret tied to
272
+ * it. `name` is the only updatable field; see `updateOrgSchema`'s own
273
+ * docblock in `packages/core/src/schemas.ts`. */
274
+ updateOrg(orgId, input) {
275
+ return this.request("PATCH", `/orgs/${orgId}`, input);
276
+ }
277
+ listApps(orgId, pagination) {
278
+ const params = new URLSearchParams();
279
+ if (pagination?.limit !== undefined)
280
+ params.set("limit", String(pagination.limit));
281
+ if (pagination?.offset !== undefined)
282
+ params.set("offset", String(pagination.offset));
283
+ const qs = params.toString();
284
+ return this.request("GET", `/orgs/${orgId}/apps${qs ? `?${qs}` : ""}`);
285
+ }
286
+ createApp(orgId, input) {
287
+ return this.request("POST", `/orgs/${orgId}/apps`, input);
288
+ }
289
+ /** A single app's own name/platform/etc. — `listApps` only ever returns a
290
+ * whole org's apps, so a page that already knows just the `appId` (any
291
+ * `/apps/:appId/*` page) needs this rather than fetching every app in
292
+ * the org just to find the one it's showing. */
293
+ getApp(appId) {
294
+ return this.request("GET", `/apps/${appId}`);
295
+ }
296
+ /** The one route that actually returns `webhookSecret` — every other
297
+ * app response (`getApp`/`listApps`/`createApp`/`updateApp`)
298
+ * deliberately omits it. This is the value GitHub's webhook settings
299
+ * "Secret" field needs, per `docs/security.md`'s "GitHub webhooks"
300
+ * note; without it there's no way to ever configure a working
301
+ * webhook at all. */
302
+ getAppWebhookSecret(appId) {
303
+ return this.request("GET", `/apps/${appId}/webhook-secret`);
304
+ }
305
+ /** `platform` isn't updatable — see `updateAppSchema`'s own docblock
306
+ * in `packages/core/src/schemas.ts`. */
307
+ updateApp(appId, input) {
308
+ return this.request("PATCH", `/apps/${appId}`, input);
309
+ }
310
+ /** Permanently removes the app and cascades every `Build`/OTA row for
311
+ * it — 409s (a plain `ApiError`) if a build is still queued/leased/
312
+ * running, so an in-flight build never has its `App` row vanish out
313
+ * from under it. */
314
+ deleteApp(appId) {
315
+ return this.request("DELETE", `/apps/${appId}`);
316
+ }
317
+ /** Build-secrets v1 (ROADMAP.md, split off from #322) — sets or
318
+ * overwrites a named secret for this app, injected as an env var
319
+ * under that name on every build. Never returns the value back;
320
+ * see `getAppSecretNames` for why. */
321
+ setAppSecret(appId, input) {
322
+ return this.request("POST", `/apps/${appId}/secrets`, input);
323
+ }
324
+ /** Names only — this codebase has no route anywhere that returns a
325
+ * secret's decrypted value once it's been set (same discipline
326
+ * `getAppWebhookSecret` deliberately doesn't extend to). */
327
+ getAppSecretNames(appId) {
328
+ return this.request("GET", `/apps/${appId}/secrets`);
329
+ }
330
+ deleteAppSecret(appId, name) {
331
+ return this.request("DELETE", `/apps/${appId}/secrets/${encodeURIComponent(name)}`);
332
+ }
333
+ /** Fleet-secrets v1 (issue #392) — sets or overwrites one of the
334
+ * org's fleet-wide infra secrets (`JWT_SECRET`,
335
+ * `JWT_SECRET_PREVIOUS`, `INTERNAL_SERVICE_TOKEN`; see
336
+ * `FLEET_SECRET_NAMES`). Every Mac mini enrolled in this org picks
337
+ * the new value up on its next heartbeat and re-applies it locally,
338
+ * so this call *is* the rotation — there's no per-machine follow-up
339
+ * step. Never returns the value back, same as `setAppSecret`. */
340
+ setFleetSecret(orgId, input) {
341
+ return this.request("POST", `/orgs/${orgId}/fleet-secrets`, input);
342
+ }
343
+ /** Names only — as with `getAppSecretNames`, no route anywhere returns
344
+ * a fleet secret's decrypted value to a human-facing client; the only
345
+ * decrypt-and-return path in this codebase is apps/admin-api's
346
+ * `GET /agents/fleet-secrets`, which requires an agent bearer token. */
347
+ getFleetSecretNames(orgId) {
348
+ return this.request("GET", `/orgs/${orgId}/fleet-secrets`);
349
+ }
350
+ deleteFleetSecret(orgId, name) {
351
+ return this.request("DELETE", `/orgs/${orgId}/fleet-secrets/${encodeURIComponent(name)}`);
352
+ }
353
+ listBuilds(appId) {
354
+ return this.request("GET", `/apps/${appId}/builds`);
355
+ }
356
+ /** Best-effort suggestions for the trigger-build form's "Workflow"
357
+ * field — see `apps/api/src/lib/appforge-yaml.ts`'s own docblock for
358
+ * why this can legitimately come back empty (private repo, no
359
+ * appforge.yaml on this branch yet, etc.) rather than erroring. */
360
+ listAppWorkflows(appId) {
361
+ return this.request("GET", `/apps/${appId}/workflows`);
362
+ }
363
+ getBuild(buildId) {
364
+ return this.request("GET", `/builds/${buildId}`);
365
+ }
366
+ triggerBuild(input) {
367
+ return this.request("POST", "/builds", input);
368
+ }
369
+ cancelBuild(buildId) {
370
+ return this.request("POST", `/builds/${buildId}/cancel`);
371
+ }
372
+ // --- Fleet management — served by the separately-deployed admin
373
+ // Worker (apps/admin-api), not the customer-facing API. See
374
+ // ApiClientOptions.adminApiUrl. ---
375
+ listAgents(orgId) {
376
+ return this.adminRequest("GET", `/orgs/${orgId}/agents`);
377
+ }
378
+ createEnrollmentToken(orgId) {
379
+ return this.adminRequest("POST", `/orgs/${orgId}/agents/enrollment-token`);
380
+ }
381
+ /** Permanently remove a Mac mini from the fleet. The daemon on the
382
+ * machine itself must be stopped separately — see apps/admin-api's
383
+ * DELETE handler and `appforge-admin agents decommission`. */
384
+ deleteAgent(orgId, agentId) {
385
+ return this.adminRequest("DELETE", `/orgs/${orgId}/agents/${agentId}`);
386
+ }
387
+ /** `scriptName` is only used by RUN_MAINTENANCE_SCRIPT; `targetVersion`
388
+ * only by UPDATE_AGENT (npm version or, for a repo-checkout install, a
389
+ * git ref); `buildId` only by CANCEL_BUILD (which of this agent's
390
+ * possibly-several concurrent builds to kill) — all three are ignored
391
+ * server-side for every other command type. `buildId` was the one
392
+ * missing piece keeping CANCEL_BUILD entirely unreachable from any
393
+ * client despite the rest of the stack (route, schema, DB column,
394
+ * agent handling) already being fully built — see ROADMAP.md. */
395
+ sendAgentCommand(agentId, type, scriptName, targetVersion, buildId) {
396
+ return this.adminRequest("POST", `/agents/${agentId}/commands`, {
397
+ type,
398
+ scriptName,
399
+ targetVersion,
400
+ buildId,
401
+ });
402
+ }
403
+ /** Remote-management history for one agent, newest first — how the
404
+ * Fleet page shows whether a DRAIN/REBOOT/... actually landed
405
+ * (`done`/`failed` + the agent's `result` string) instead of leaving
406
+ * the operator guessing after a click. */
407
+ listAgentCommands(agentId, limit) {
408
+ const qs = limit ? `?limit=${limit}` : "";
409
+ return this.adminRequest("GET", `/agents/${agentId}/commands${qs}`);
410
+ }
411
+ /** VNC "Connect" button, Phase 1c: mints a 5-minute session token plus
412
+ * the `wsUrl` (`apps/device-stream`'s `/vnc` relay, see that Worker's
413
+ * Phase 1b) the dashboard's viewer page dials it against. Called fresh
414
+ * each time the viewer page mounts, same "no pre-fetched token sitting
415
+ * in a URL or router state" shape as `startDeviceTestSession`.
416
+ *
417
+ * `options.requestControl` (Feature 3) asks the server for a session
418
+ * that can also forward mouse/keyboard input, not just watch — sent
419
+ * as `{ mode: "control" }` only when true, so an omitted/false call
420
+ * sends no body at all, unchanged from before this option existed.
421
+ * This is only ever a *request*: the response's own `mode` field
422
+ * ("view" | "control") is what the server actually granted (`403` if
423
+ * control was requested but `Agent.remoteControlEnabled` isn't set —
424
+ * see `apps/admin-api/src/routes/fleet.ts`), and callers must treat
425
+ * that field, never their own request, as authoritative. */
426
+ startVncSession(orgId, agentId, options) {
427
+ return this.adminRequest("POST", `/orgs/${orgId}/agents/${agentId}/vnc-session`, options?.requestControl ? { mode: "control" } : undefined);
428
+ }
429
+ /** Grants or revokes `Agent.remoteControlEnabled` (Feature 3) — the
430
+ * one and only way that flag changes, mirroring `deleteAgent` above's
431
+ * "dedicated route with its own DB write" shape rather than the
432
+ * AgentCommand queue, since this is a persisted authorization bit
433
+ * `startVncSession` needs to read synchronously, not a directive for
434
+ * the agent daemon to act on. See `appforge-admin agents
435
+ * allow-remote-control` (`packages/admin-cli`) for the CLI surface
436
+ * this same route backs. */
437
+ setAgentRemoteControl(orgId, agentId, enabled) {
438
+ return this.adminRequest("PATCH", `/orgs/${orgId}/agents/${agentId}/remote-control`, { enabled });
439
+ }
440
+ /** The audit trail's read side — who's requested a VNC "Connect"
441
+ * session for this agent and when, newest first. How a "Last VNC
442
+ * session" column reads this (`apps/dashboard/src/pages/Fleet.tsx`),
443
+ * same shape `listAgentCommands` above already established. */
444
+ listVncSessions(orgId, agentId) {
445
+ return this.adminRequest("GET", `/orgs/${orgId}/agents/${agentId}/vnc-sessions`);
446
+ }
447
+ getBalance(orgId) {
448
+ return this.request("GET", `/orgs/${orgId}/billing/balance`);
449
+ }
450
+ listTokenPacks() {
451
+ return this.request("GET", "/billing/packs");
452
+ }
453
+ /** Starts an LHV Paytech checkout session for a token top-up — also opportunistically saves a card for MIT monthly billing. */
454
+ createLhvCheckoutSession(orgId, packId) {
455
+ return this.request("POST", `/orgs/${orgId}/billing/checkout/lhv`, { packId });
456
+ }
457
+ isLhvConfigured() {
458
+ return this.request("GET", "/billing/providers/lhv");
459
+ }
460
+ listLedger(orgId) {
461
+ return this.request("GET", `/orgs/${orgId}/billing/ledger`);
462
+ }
463
+ getBillingUsage(orgId) {
464
+ return this.request("GET", `/orgs/${orgId}/billing/usage`);
465
+ }
466
+ setBillingMode(orgId, mode) {
467
+ return this.request("POST", `/orgs/${orgId}/billing/mode`, { mode });
468
+ }
469
+ listMonthlyInvoices(orgId) {
470
+ return this.request("GET", `/orgs/${orgId}/billing/invoices`);
471
+ }
472
+ /** AI triage of a failed build's log — see docs/ai-failure-triage.md.
473
+ * Throws ApiError(501) if ANTHROPIC_API_KEY isn't configured on this
474
+ * deployment; callers should show that as "not available here", not
475
+ * as a generic error. */
476
+ explainBuildFailure(buildId) {
477
+ return this.request("POST", `/builds/${buildId}/explain-failure`);
478
+ }
479
+ /** On-demand re-analysis of every smoke-test screenshot a build produced
480
+ * (#9), one verdict per screenshot in index order — same
481
+ * 501-if-unconfigured contract as explainBuildFailure above. */
482
+ analyzeSmokeTest(buildId) {
483
+ return this.request("POST", `/builds/${buildId}/analyze-smoke-test`);
484
+ }
485
+ startDeviceTestSession(buildId) {
486
+ return this.request("POST", `/builds/${buildId}/device-test/start`);
487
+ }
488
+ // --- OTA (Over-The-Air) updates ---
489
+ /** `appKey` is required — the manifest endpoint has no unauthenticated
490
+ * fallback (see `apps/api/src/routes/ota.ts`'s docblock on it), only
491
+ * `generateOtaAppKey`'s one-time response ever reveals a usable
492
+ * value. This call carries no user session (a mobile app binary has
493
+ * none), so the key travels as a query param rather than the
494
+ * `authorization` header `request()` already reserves for the
495
+ * dashboard/CLI's bearer token. */
496
+ getOtaManifest(appId, channel, appKey, currentHash, installationId) {
497
+ const params = new URLSearchParams({ appKey });
498
+ if (currentHash)
499
+ params.set("currentHash", currentHash);
500
+ // Lets a client SDK participate in staged rollout (apps/api/src/
501
+ // routes/ota.ts's isInStagedRollout) — omit it and the server treats
502
+ // the caller as always-in-rollout, same as every caller before this
503
+ // parameter existed.
504
+ if (installationId)
505
+ params.set("installationId", installationId);
506
+ return this.request("GET", `/apps/${appId}/ota/${encodeURIComponent(channel)}/manifest?${params.toString()}`);
507
+ }
508
+ /** Generates (rotates) this app's OTA manifest key — see
509
+ * `getOtaManifest`. Returned once; the server keeps only its hash. */
510
+ generateOtaAppKey(appId) {
511
+ return this.request("POST", `/apps/${appId}/ota/app-key`);
512
+ }
513
+ listOtaReleases(appId, channel, pagination) {
514
+ const params = new URLSearchParams();
515
+ if (channel)
516
+ params.set("channel", channel);
517
+ if (pagination?.limit !== undefined)
518
+ params.set("limit", String(pagination.limit));
519
+ if (pagination?.offset !== undefined)
520
+ params.set("offset", String(pagination.offset));
521
+ const qs = params.toString();
522
+ return this.request("GET", `/apps/${appId}/ota/releases${qs ? `?${qs}` : ""}`);
523
+ }
524
+ listOtaChannels(appId, pagination) {
525
+ const params = new URLSearchParams();
526
+ if (pagination?.limit !== undefined)
527
+ params.set("limit", String(pagination.limit));
528
+ if (pagination?.offset !== undefined)
529
+ params.set("offset", String(pagination.offset));
530
+ const qs = params.toString();
531
+ return this.request("GET", `/apps/${appId}/ota/channels${qs ? `?${qs}` : ""}`);
532
+ }
533
+ promoteOtaRelease(appId, input) {
534
+ return this.request("POST", `/apps/${appId}/ota/promote`, input);
535
+ }
536
+ /** Progresses an existing release's rollout in place (10% -> 50% ->
537
+ * 100%) instead of re-promoting the same build, which would mint a
538
+ * new release id and reshuffle `isInStagedRollout`'s per-install
539
+ * bucketing — see `updateOtaReleaseRolloutSchema`'s own docblock in
540
+ * `packages/core/src/schemas.ts`. */
541
+ updateOtaReleaseRollout(appId, releaseId, rollout) {
542
+ return this.request("PATCH", `/apps/${appId}/ota/releases/${releaseId}/rollout`, { rollout });
543
+ }
544
+ setActiveOtaRelease(appId, channel, releaseId) {
545
+ return this.request("POST", `/apps/${appId}/ota/channels/${encodeURIComponent(channel)}/active`, { releaseId });
546
+ }
547
+ rollbackOtaChannel(appId, channel) {
548
+ return this.request("POST", `/apps/${appId}/ota/channels/${encodeURIComponent(channel)}/rollback`);
549
+ }
550
+ }
551
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=api-client.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.test.d.ts","sourceRoot":"","sources":["../src/api-client.test.ts"],"names":[],"mappings":""}