@alfe.ai/gateway 0.8.3 → 0.9.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.
- package/dist/bin/gateway.js +1 -1
- package/dist/health.js +565 -465
- package/dist/runtime-upgrade.js +22 -6
- package/dist/src/index.d.ts +50 -2
- package/dist/src/index.js +2 -2
- package/package.json +4 -4
package/dist/bin/gateway.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as installService,
|
|
2
|
+
import { a as installService, d as uninstallService, h as SOCKET_PATH, i as checkExistingDaemon, l as stopExistingDaemon, n as queryDaemonHealth, r as startDaemon, t as formatHealthReport } from "../health.js";
|
|
3
3
|
import { t as LOG_FILE } from "../logger.js";
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
5
|
//#region bin/gateway.ts
|
package/dist/health.js
CHANGED
|
@@ -76,6 +76,26 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
76
76
|
*/
|
|
77
77
|
const PINNED_OPENCLAW_VERSION = "2026.6.11";
|
|
78
78
|
//#endregion
|
|
79
|
+
//#region src/claude-code-host-version.ts
|
|
80
|
+
/**
|
|
81
|
+
* The `@alfe.ai/claude-code-host` version Alfe pins the claude-code runtime to —
|
|
82
|
+
* the single source of truth for its install paths:
|
|
83
|
+
* - `@alfe.ai/cli` `installClaudeCodeHost` (fresh `alfe setup`)
|
|
84
|
+
* - the daemon `runtime.update` default (this package)
|
|
85
|
+
*
|
|
86
|
+
* Pinning (rather than floating `npm install -g @alfe.ai/claude-code-host` →
|
|
87
|
+
* `latest`) is deliberate: the host is the claude-code runtime child on every
|
|
88
|
+
* self-hosted claude-code agent, so a bad `latest` publish would auto-reach
|
|
89
|
+
* every new `alfe setup` with no CLI gate. Bump deliberately after validating a
|
|
90
|
+
* new host, then cut a CLI release so the pin travels with the CLI version. The
|
|
91
|
+
* dashboard still surfaces npm-`latest` as an explicit opt-in upgrade.
|
|
92
|
+
*
|
|
93
|
+
* NOTE: claude-code is self-hosted-only (no managed Docker image), so — unlike
|
|
94
|
+
* `PINNED_OPENCLAW_VERSION` — there is no `services/compute/Dockerfile` mirror to
|
|
95
|
+
* keep in sync.
|
|
96
|
+
*/
|
|
97
|
+
const PINNED_CLAUDE_CODE_HOST_VERSION = "0.1.3";
|
|
98
|
+
//#endregion
|
|
79
99
|
//#region ../../packages-internal/ids/dist/prefixes.js
|
|
80
100
|
const ID_PREFIXES = {
|
|
81
101
|
agent: "agt",
|
|
@@ -325,465 +345,72 @@ var AlfeApiClient = class {
|
|
|
325
345
|
error: "Session expired",
|
|
326
346
|
status: 401
|
|
327
347
|
}
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
const body = await res.json();
|
|
331
|
-
if (!res.ok) return {
|
|
332
|
-
ok: false,
|
|
333
|
-
result: {
|
|
334
|
-
ok: false,
|
|
335
|
-
error: body.message || `API error: ${String(res.status)}`,
|
|
336
|
-
status: res.status
|
|
337
|
-
}
|
|
338
|
-
};
|
|
339
|
-
return {
|
|
340
|
-
ok: true,
|
|
341
|
-
res,
|
|
342
|
-
body
|
|
343
|
-
};
|
|
344
|
-
} catch (err) {
|
|
345
|
-
return {
|
|
346
|
-
ok: false,
|
|
347
|
-
result: {
|
|
348
|
-
ok: false,
|
|
349
|
-
error: err instanceof Error ? err.message : "Network error"
|
|
350
|
-
}
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
/**
|
|
355
|
-
* Make an authenticated request to an Alfe API endpoint.
|
|
356
|
-
* Unwraps the @auriclabs/api-core `{ data, timestamp, requestId }` envelope.
|
|
357
|
-
*/
|
|
358
|
-
async request(path, options) {
|
|
359
|
-
const result = await this._fetch(path, options);
|
|
360
|
-
if (!result.ok) return result.result;
|
|
361
|
-
return {
|
|
362
|
-
ok: true,
|
|
363
|
-
data: result.body.data
|
|
364
|
-
};
|
|
365
|
-
}
|
|
366
|
-
/**
|
|
367
|
-
* Make a request to a PUBLIC endpoint that does not require authentication.
|
|
368
|
-
* Skips both the Authorization header injection AND the onAuthFailure
|
|
369
|
-
* callback. Use for endpoints like /auth/device-code that the CLI hits
|
|
370
|
-
* before it has a token.
|
|
371
|
-
*/
|
|
372
|
-
async publicRequest(path, options) {
|
|
373
|
-
const result = await this._fetch(path, options, true);
|
|
374
|
-
if (!result.ok) return result.result;
|
|
375
|
-
return {
|
|
376
|
-
ok: true,
|
|
377
|
-
data: result.body.data
|
|
378
|
-
};
|
|
379
|
-
}
|
|
380
|
-
/**
|
|
381
|
-
* Make an authenticated request that returns the body directly (no envelope unwrap).
|
|
382
|
-
* Use for APIs that don't use the @auriclabs/api-core response format (e.g. gateway).
|
|
383
|
-
*/
|
|
384
|
-
async rawRequest(path, options) {
|
|
385
|
-
const result = await this._fetch(path, options);
|
|
386
|
-
if (!result.ok) return result.result;
|
|
387
|
-
return {
|
|
388
|
-
ok: true,
|
|
389
|
-
data: result.body
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
|
-
getApiBaseUrl() {
|
|
393
|
-
return this.apiBaseUrl;
|
|
394
|
-
}
|
|
395
|
-
};
|
|
396
|
-
//#endregion
|
|
397
|
-
//#region ../../packages-internal/api-client/dist/services/auth.js
|
|
398
|
-
var AuthService = class {
|
|
399
|
-
client;
|
|
400
|
-
constructor(client) {
|
|
401
|
-
this.client = client;
|
|
402
|
-
}
|
|
403
|
-
prefix = "/auth";
|
|
404
|
-
validate(token) {
|
|
405
|
-
return this.client.request(`${this.prefix}/validate`, {
|
|
406
|
-
method: "POST",
|
|
407
|
-
body: JSON.stringify({ token })
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
listTokens() {
|
|
411
|
-
return this.client.request(`${this.prefix}/tokens`);
|
|
412
|
-
}
|
|
413
|
-
createToken(data) {
|
|
414
|
-
return this.client.request(`${this.prefix}/tokens`, {
|
|
415
|
-
method: "POST",
|
|
416
|
-
body: JSON.stringify(data)
|
|
417
|
-
});
|
|
418
|
-
}
|
|
419
|
-
deleteToken(tokenId) {
|
|
420
|
-
return this.client.request(`${this.prefix}/tokens/${tokenId}`, { method: "DELETE" });
|
|
421
|
-
}
|
|
422
|
-
/**
|
|
423
|
-
* Start a device-code flow. Called by the CLI when the user runs
|
|
424
|
-
* `alfe login` and picks the browser path. The returned `device_code`
|
|
425
|
-
* is the CLI's bearer secret for polling /auth/device-token; the
|
|
426
|
-
* `user_code` is what the user types/sees on the dashboard.
|
|
427
|
-
*
|
|
428
|
-
* Uses `publicRequest` because the CLI has no token yet — the standard
|
|
429
|
-
* `request` path would short-circuit with a synthetic 401.
|
|
430
|
-
*/
|
|
431
|
-
startDeviceCode(input) {
|
|
432
|
-
return this.client.publicRequest(`${this.prefix}/device-code`, {
|
|
433
|
-
method: "POST",
|
|
434
|
-
body: JSON.stringify(input)
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
/**
|
|
438
|
-
* Poll for the minted API key. Public endpoint. Returns:
|
|
439
|
-
* 200 → { api_key, tenantId, tokenExpiresAt } (success — write to config)
|
|
440
|
-
* 428 → still pending (caller should sleep `interval` and retry)
|
|
441
|
-
* 429 → polling too fast; caller should back off
|
|
442
|
-
* 410 → device-code expired; user must run `alfe login` again
|
|
443
|
-
* 400 → already redeemed (security: do not retry)
|
|
444
|
-
*
|
|
445
|
-
* Surface the HTTP-status code via the standard ApiResult error shape
|
|
446
|
-
* so callers can branch.
|
|
447
|
-
*/
|
|
448
|
-
pollDeviceToken(deviceCode) {
|
|
449
|
-
return this.client.publicRequest(`${this.prefix}/device-token`, {
|
|
450
|
-
method: "POST",
|
|
451
|
-
body: JSON.stringify({ device_code: deviceCode })
|
|
452
|
-
});
|
|
453
|
-
}
|
|
454
|
-
/** Dashboard-side. Fetch the device fingerprint for an approval card. */
|
|
455
|
-
lookupDeviceCode(userCode) {
|
|
456
|
-
return this.client.request(`${this.prefix}/device-code/lookup`, {
|
|
457
|
-
method: "POST",
|
|
458
|
-
body: JSON.stringify({ user_code: userCode })
|
|
459
|
-
});
|
|
460
|
-
}
|
|
461
|
-
/** Dashboard-side. Approve the pending device-code; CLI's next poll gets the key. */
|
|
462
|
-
approveDeviceCode(input) {
|
|
463
|
-
return this.client.request(`${this.prefix}/device-code/approve`, {
|
|
464
|
-
method: "POST",
|
|
465
|
-
body: JSON.stringify({
|
|
466
|
-
user_code: input.userCode,
|
|
467
|
-
expiresIn: input.expiresIn
|
|
468
|
-
})
|
|
469
|
-
});
|
|
470
|
-
}
|
|
471
|
-
getOnboardingStatus() {
|
|
472
|
-
return this.client.request(`${this.prefix}/onboarding/status`);
|
|
473
|
-
}
|
|
474
|
-
completeOnboarding(input) {
|
|
475
|
-
return this.client.request(`${this.prefix}/onboarding/complete`, {
|
|
476
|
-
method: "POST",
|
|
477
|
-
body: JSON.stringify(input)
|
|
478
|
-
});
|
|
479
|
-
}
|
|
480
|
-
getAccessStatus() {
|
|
481
|
-
return this.client.request(`${this.prefix}/access/status`);
|
|
482
|
-
}
|
|
483
|
-
redeemAccessCode(code) {
|
|
484
|
-
return this.client.request(`${this.prefix}/access/redeem`, {
|
|
485
|
-
method: "POST",
|
|
486
|
-
body: JSON.stringify({ code })
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
|
-
/**
|
|
490
|
-
* Fetch the caller's current permission list as enforced by the gateway.
|
|
491
|
-
* UI permission providers should call this on mount and refetch on
|
|
492
|
-
* Clerk org switch to stay in sync with sub-tenant permission changes.
|
|
493
|
-
*/
|
|
494
|
-
getMyPermissions() {
|
|
495
|
-
return this.client.request(`${this.prefix}/me/permissions`);
|
|
496
|
-
}
|
|
497
|
-
/**
|
|
498
|
-
* Preview what deleting the caller's own account will do. Drives the Danger
|
|
499
|
-
* Zone copy so the user sees an honest, kind-appropriate warning before the
|
|
500
|
-
* irreversible action (a last-admin cascade wipes the whole workspace).
|
|
501
|
-
*/
|
|
502
|
-
getDeletionPreview() {
|
|
503
|
-
return this.client.request(`${this.prefix}/me/deletion-preview`);
|
|
504
|
-
}
|
|
505
|
-
/**
|
|
506
|
-
* Permanently delete the caller's own account. Returns `{ status: "deleting" }`
|
|
507
|
-
* and tears the account down asynchronously — the Clerk user is deleted shortly
|
|
508
|
-
* after, so the caller's session dies. On success, sign out and route the user
|
|
509
|
-
* to a terminal "account is being deleted" state; do NOT retry.
|
|
510
|
-
*
|
|
511
|
-
* Pass `confirmKind` (the accountKind the user actually confirmed, from the
|
|
512
|
-
* deletion preview): if membership changed between preview and execute, the
|
|
513
|
-
* server answers 409 `account_kind_changed` instead of cascading a scope the
|
|
514
|
-
* user never agreed to.
|
|
515
|
-
*/
|
|
516
|
-
deleteAccount(confirmKind) {
|
|
517
|
-
return this.client.request(`${this.prefix}/me`, {
|
|
518
|
-
method: "DELETE",
|
|
519
|
-
...confirmKind ? { body: JSON.stringify({ confirmKind }) } : {}
|
|
520
|
-
});
|
|
521
|
-
}
|
|
522
|
-
getSubscriptionStatus() {
|
|
523
|
-
return this.client.request(`${this.prefix}/subscription`);
|
|
524
|
-
}
|
|
525
|
-
/**
|
|
526
|
-
* Mint a short-lived, single-use Clerk sign-in token for the calling user so
|
|
527
|
-
* a native client can hand its logged-in session to the web dashboard
|
|
528
|
-
* (`${dashboard}/handoff?__clerk_ticket=<token>`). Server mints only for the
|
|
529
|
-
* authenticated user — never a caller-supplied id.
|
|
530
|
-
*/
|
|
531
|
-
createHandoffToken() {
|
|
532
|
-
return this.client.request(`${this.prefix}/handoff-token`, { method: "POST" });
|
|
533
|
-
}
|
|
534
|
-
applyForStartup(input) {
|
|
535
|
-
return this.client.request(`${this.prefix}/subscription/apply-startup`, {
|
|
536
|
-
method: "POST",
|
|
537
|
-
body: JSON.stringify(input)
|
|
538
|
-
});
|
|
539
|
-
}
|
|
540
|
-
/**
|
|
541
|
-
* Accept an approved Startup Program invite. Call after the applicant has a
|
|
542
|
-
* card on file (confirmed or freshly added) — this mints the Professional
|
|
543
|
-
* grant subscription. Idempotent: a repeat call on an already-accepted
|
|
544
|
-
* application returns `{ status: "accepted" }` without re-charging.
|
|
545
|
-
*/
|
|
546
|
-
acceptStartup() {
|
|
547
|
-
return this.client.request(`${this.prefix}/subscription/accept-startup`, { method: "POST" });
|
|
548
|
-
}
|
|
549
|
-
createCheckoutSession(input) {
|
|
550
|
-
return this.client.request(`${this.prefix}/subscription/checkout`, {
|
|
551
|
-
method: "POST",
|
|
552
|
-
body: JSON.stringify(input)
|
|
553
|
-
});
|
|
554
|
-
}
|
|
555
|
-
/**
|
|
556
|
-
* Change a personal (individual-tier) subscriber's platform plan in place on
|
|
557
|
-
* their existing Stripe subscription — no second Checkout, no duplicate sub,
|
|
558
|
-
* no double charge. Upgrades prorate immediately; downgrades apply with no
|
|
559
|
-
* immediate charge/refund. Returns the updated subscription.
|
|
560
|
-
*/
|
|
561
|
-
changePlatformPlan(input) {
|
|
562
|
-
return this.client.request(`${this.prefix}/subscription/change`, {
|
|
563
|
-
method: "POST",
|
|
564
|
-
body: JSON.stringify(input)
|
|
565
|
-
});
|
|
566
|
-
}
|
|
567
|
-
/**
|
|
568
|
-
* Preview the proration cost for changing a personal (individual-tier)
|
|
569
|
-
* subscriber's platform plan — read-only companion to `changePlatformPlan`.
|
|
570
|
-
* Nothing is charged.
|
|
571
|
-
*/
|
|
572
|
-
previewPlatformPlanChange(input) {
|
|
573
|
-
return this.client.request(`${this.prefix}/subscription/change/preview`, {
|
|
574
|
-
method: "POST",
|
|
575
|
-
body: JSON.stringify(input)
|
|
576
|
-
});
|
|
577
|
-
}
|
|
578
|
-
updateSeats(seats) {
|
|
579
|
-
return this.client.request(`${this.prefix}/subscription/seats`, {
|
|
580
|
-
method: "POST",
|
|
581
|
-
body: JSON.stringify({ seats })
|
|
582
|
-
});
|
|
583
|
-
}
|
|
584
|
-
previewSeatChange(seats) {
|
|
585
|
-
return this.client.request(`${this.prefix}/subscription/seats/preview`, {
|
|
586
|
-
method: "POST",
|
|
587
|
-
body: JSON.stringify({ seats })
|
|
588
|
-
});
|
|
589
|
-
}
|
|
590
|
-
listOrgMembers() {
|
|
591
|
-
return this.client.request(`${this.prefix}/org/members`);
|
|
592
|
-
}
|
|
593
|
-
patchOrgMember(userId, body) {
|
|
594
|
-
return this.client.request(`${this.prefix}/org/members/${encodeURIComponent(userId)}`, {
|
|
595
|
-
method: "PATCH",
|
|
596
|
-
body: JSON.stringify(body)
|
|
597
|
-
});
|
|
598
|
-
}
|
|
599
|
-
removeOrgMember(userId) {
|
|
600
|
-
return this.client.request(`${this.prefix}/org/members/${encodeURIComponent(userId)}`, { method: "DELETE" });
|
|
601
|
-
}
|
|
602
|
-
listOrgInvitations() {
|
|
603
|
-
return this.client.request(`${this.prefix}/org/invitations`);
|
|
604
|
-
}
|
|
605
|
-
createOrgInvitation(input) {
|
|
606
|
-
return this.client.request(`${this.prefix}/org/invitations`, {
|
|
607
|
-
method: "POST",
|
|
608
|
-
body: JSON.stringify(input)
|
|
609
|
-
});
|
|
610
|
-
}
|
|
611
|
-
revokeOrgInvitation(invitationId) {
|
|
612
|
-
return this.client.request(`${this.prefix}/org/invitations/${encodeURIComponent(invitationId)}`, { method: "DELETE" });
|
|
613
|
-
}
|
|
614
|
-
listOrgDomains() {
|
|
615
|
-
return this.client.request(`${this.prefix}/org/domains`);
|
|
616
|
-
}
|
|
617
|
-
createOrgDomain(input) {
|
|
618
|
-
return this.client.request(`${this.prefix}/org/domains`, {
|
|
619
|
-
method: "POST",
|
|
620
|
-
body: JSON.stringify(input)
|
|
621
|
-
});
|
|
622
|
-
}
|
|
623
|
-
deleteOrgDomain(domainId) {
|
|
624
|
-
return this.client.request(`${this.prefix}/org/domains/${encodeURIComponent(domainId)}`, { method: "DELETE" });
|
|
625
|
-
}
|
|
626
|
-
updateOrgSettings(input) {
|
|
627
|
-
return this.client.request(`${this.prefix}/org/settings`, {
|
|
628
|
-
method: "PATCH",
|
|
629
|
-
body: JSON.stringify(input)
|
|
630
|
-
});
|
|
631
|
-
}
|
|
632
|
-
};
|
|
633
|
-
//#endregion
|
|
634
|
-
//#region ../../packages-internal/api-client/dist/services/integrations.js
|
|
635
|
-
var IntegrationsService = class {
|
|
636
|
-
client;
|
|
637
|
-
constructor(client) {
|
|
638
|
-
this.client = client;
|
|
639
|
-
}
|
|
640
|
-
listScopedInstalls(scope, scopeId) {
|
|
641
|
-
const params = new URLSearchParams({
|
|
642
|
-
scope,
|
|
643
|
-
scopeId
|
|
644
|
-
});
|
|
645
|
-
return this.client.request(`/integrations/scoped?${params}`);
|
|
646
|
-
}
|
|
647
|
-
installScoped(data) {
|
|
648
|
-
return this.client.request("/integrations/scoped", {
|
|
649
|
-
method: "POST",
|
|
650
|
-
body: JSON.stringify(data)
|
|
651
|
-
});
|
|
652
|
-
}
|
|
653
|
-
getScopedInstall(integrationId, scope, scopeId) {
|
|
654
|
-
const params = new URLSearchParams({
|
|
655
|
-
scope,
|
|
656
|
-
scopeId
|
|
657
|
-
});
|
|
658
|
-
return this.client.request(`/integrations/scoped/${encodeURIComponent(integrationId)}?${params}`);
|
|
659
|
-
}
|
|
660
|
-
updateScopedInstall(integrationId, data) {
|
|
661
|
-
return this.client.request(`/integrations/scoped/${encodeURIComponent(integrationId)}`, {
|
|
662
|
-
method: "PATCH",
|
|
663
|
-
body: JSON.stringify(data)
|
|
664
|
-
});
|
|
665
|
-
}
|
|
666
|
-
removeScopedInstall(integrationId, scope, scopeId) {
|
|
667
|
-
const params = new URLSearchParams({
|
|
668
|
-
scope,
|
|
669
|
-
scopeId
|
|
670
|
-
});
|
|
671
|
-
return this.client.request(`/integrations/scoped/${encodeURIComponent(integrationId)}?${params}`, { method: "DELETE" });
|
|
672
|
-
}
|
|
673
|
-
/**
|
|
674
|
-
* Reinstall (re-apply latest) a scope-level install. Agent scope is rejected
|
|
675
|
-
* by the route — use {@link reinstallIntegration} for agent-scoped reinstall.
|
|
676
|
-
*/
|
|
677
|
-
reinstallScoped(integrationId, scope, scopeId) {
|
|
678
|
-
return this.client.request(`/integrations/scoped/${encodeURIComponent(integrationId)}/reinstall`, {
|
|
679
|
-
method: "POST",
|
|
680
|
-
body: JSON.stringify({
|
|
681
|
-
scope,
|
|
682
|
-
scopeId
|
|
683
|
-
})
|
|
684
|
-
});
|
|
685
|
-
}
|
|
686
|
-
listIntegrations(agentId, options) {
|
|
687
|
-
const params = new URLSearchParams();
|
|
688
|
-
if (options?.includeInherited) params.set("includeInherited", "true");
|
|
689
|
-
if (options?.effective) params.set("effective", "true");
|
|
690
|
-
const qs = params.toString();
|
|
691
|
-
return this.client.request(`/integrations/agents/${agentId}${qs ? `?${qs}` : ""}`);
|
|
692
|
-
}
|
|
693
|
-
installIntegration(agentId, data) {
|
|
694
|
-
return this.client.request(`/integrations/agents/${agentId}`, {
|
|
695
|
-
method: "POST",
|
|
696
|
-
body: JSON.stringify(data)
|
|
697
|
-
});
|
|
698
|
-
}
|
|
699
|
-
getIntegrationConfig(agentId, integrationId) {
|
|
700
|
-
return this.client.request(`/integrations/agents/${agentId}/${integrationId}/config`);
|
|
701
|
-
}
|
|
702
|
-
updateIntegration(agentId, integrationId, data) {
|
|
703
|
-
return this.client.request(`/integrations/agents/${agentId}/${integrationId}`, {
|
|
704
|
-
method: "PATCH",
|
|
705
|
-
body: JSON.stringify(data)
|
|
706
|
-
});
|
|
707
|
-
}
|
|
708
|
-
removeIntegration(agentId, integrationId) {
|
|
709
|
-
return this.client.request(`/integrations/agents/${agentId}/${integrationId}`, { method: "DELETE" });
|
|
710
|
-
}
|
|
711
|
-
reinstallIntegration(agentId, integrationId) {
|
|
712
|
-
return this.client.request(`/integrations/agents/${agentId}/${integrationId}/reinstall`, { method: "POST" });
|
|
713
|
-
}
|
|
714
|
-
/**
|
|
715
|
-
* Upgrade an integration to the registry's latest version via the fast,
|
|
716
|
-
* diff-based daemon path (bumps `version` without `reinstallRequestedAt`).
|
|
717
|
-
* The agent stays online — no destructive teardown. Distinct from
|
|
718
|
-
* {@link reinstallIntegration}, which is the destructive repair path.
|
|
719
|
-
*/
|
|
720
|
-
upgradeIntegration(agentId, integrationId) {
|
|
721
|
-
return this.client.request(`/integrations/agents/${agentId}/${integrationId}/upgrade`, { method: "POST" });
|
|
722
|
-
}
|
|
723
|
-
getRegistry() {
|
|
724
|
-
return this.client.request("/integrations/registry");
|
|
725
|
-
}
|
|
726
|
-
triggerSync(agentId) {
|
|
727
|
-
return this.client.request("/integrations/sync/trigger", {
|
|
728
|
-
method: "POST",
|
|
729
|
-
body: JSON.stringify({ agentId })
|
|
730
|
-
});
|
|
731
|
-
}
|
|
732
|
-
getDiscordGuildChannels(guildId) {
|
|
733
|
-
return this.client.request(`/discord/guilds/${encodeURIComponent(guildId)}/channels`);
|
|
734
|
-
}
|
|
735
|
-
listMobileNumbers() {
|
|
736
|
-
return this.client.request("/mobile/numbers");
|
|
737
|
-
}
|
|
738
|
-
searchMobileNumbers(country, query) {
|
|
739
|
-
const params = new URLSearchParams();
|
|
740
|
-
if (country) params.set("country", country);
|
|
741
|
-
if (query) params.set("query", query);
|
|
742
|
-
return this.client.request(`/mobile/numbers/search?${params}`);
|
|
743
|
-
}
|
|
744
|
-
assignMobileNumber(agentId, phoneNumber, countryCode) {
|
|
745
|
-
return this.client.request("/mobile/numbers/assign", {
|
|
746
|
-
method: "POST",
|
|
747
|
-
body: JSON.stringify({
|
|
748
|
-
agentId,
|
|
749
|
-
phoneNumber,
|
|
750
|
-
countryCode
|
|
751
|
-
})
|
|
752
|
-
});
|
|
753
|
-
}
|
|
754
|
-
releaseMobileNumber(agentId) {
|
|
755
|
-
return this.client.request("/mobile/numbers/release", {
|
|
756
|
-
method: "POST",
|
|
757
|
-
body: JSON.stringify({ agentId })
|
|
758
|
-
});
|
|
759
|
-
}
|
|
760
|
-
getMobileNumber(agentId) {
|
|
761
|
-
return this.client.request(`/mobile/numbers?agentId=${encodeURIComponent(agentId)}`);
|
|
762
|
-
}
|
|
763
|
-
disconnectGoogle(agentId, email) {
|
|
764
|
-
const query = email ? `?email=${encodeURIComponent(email)}` : "";
|
|
765
|
-
return this.client.request(`/google/agents/${encodeURIComponent(agentId)}/account${query}`, { method: "DELETE" });
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
const body = await res.json();
|
|
351
|
+
if (!res.ok) return {
|
|
352
|
+
ok: false,
|
|
353
|
+
result: {
|
|
354
|
+
ok: false,
|
|
355
|
+
error: body.message || `API error: ${String(res.status)}`,
|
|
356
|
+
status: res.status
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
return {
|
|
360
|
+
ok: true,
|
|
361
|
+
res,
|
|
362
|
+
body
|
|
363
|
+
};
|
|
364
|
+
} catch (err) {
|
|
365
|
+
return {
|
|
366
|
+
ok: false,
|
|
367
|
+
result: {
|
|
368
|
+
ok: false,
|
|
369
|
+
error: err instanceof Error ? err.message : "Network error"
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
}
|
|
766
373
|
}
|
|
767
|
-
|
|
768
|
-
|
|
374
|
+
/**
|
|
375
|
+
* Make an authenticated request to an Alfe API endpoint.
|
|
376
|
+
* Unwraps the @auriclabs/api-core `{ data, timestamp, requestId }` envelope.
|
|
377
|
+
*/
|
|
378
|
+
async request(path, options) {
|
|
379
|
+
const result = await this._fetch(path, options);
|
|
380
|
+
if (!result.ok) return result.result;
|
|
381
|
+
return {
|
|
382
|
+
ok: true,
|
|
383
|
+
data: result.body.data
|
|
384
|
+
};
|
|
769
385
|
}
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
386
|
+
/**
|
|
387
|
+
* Make a request to a PUBLIC endpoint that does not require authentication.
|
|
388
|
+
* Skips both the Authorization header injection AND the onAuthFailure
|
|
389
|
+
* callback. Use for endpoints like /auth/device-code that the CLI hits
|
|
390
|
+
* before it has a token.
|
|
391
|
+
*/
|
|
392
|
+
async publicRequest(path, options) {
|
|
393
|
+
const result = await this._fetch(path, options, true);
|
|
394
|
+
if (!result.ok) return result.result;
|
|
395
|
+
return {
|
|
396
|
+
ok: true,
|
|
397
|
+
data: result.body.data
|
|
398
|
+
};
|
|
775
399
|
}
|
|
776
|
-
|
|
777
|
-
|
|
400
|
+
/**
|
|
401
|
+
* Make an authenticated request that returns the body directly (no envelope unwrap).
|
|
402
|
+
* Use for APIs that don't use the @auriclabs/api-core response format (e.g. gateway).
|
|
403
|
+
*/
|
|
404
|
+
async rawRequest(path, options) {
|
|
405
|
+
const result = await this._fetch(path, options);
|
|
406
|
+
if (!result.ok) return result.result;
|
|
407
|
+
return {
|
|
408
|
+
ok: true,
|
|
409
|
+
data: result.body
|
|
410
|
+
};
|
|
778
411
|
}
|
|
779
|
-
|
|
780
|
-
return this.
|
|
781
|
-
method: "POST",
|
|
782
|
-
body: JSON.stringify({
|
|
783
|
-
channel,
|
|
784
|
-
text
|
|
785
|
-
})
|
|
786
|
-
});
|
|
412
|
+
getApiBaseUrl() {
|
|
413
|
+
return this.apiBaseUrl;
|
|
787
414
|
}
|
|
788
415
|
};
|
|
789
416
|
//#endregion
|
|
@@ -4515,6 +4142,7 @@ enumValues({
|
|
|
4515
4142
|
Other: "other"
|
|
4516
4143
|
});
|
|
4517
4144
|
enumValues({
|
|
4145
|
+
IndividualPayg: "individual_payg",
|
|
4518
4146
|
IndividualLite: "individual_lite",
|
|
4519
4147
|
IndividualNormal: "individual_normal",
|
|
4520
4148
|
IndividualPro: "individual_pro",
|
|
@@ -4878,6 +4506,7 @@ const NotificationType = {
|
|
|
4878
4506
|
SubscriptionCreated: "subscription.created",
|
|
4879
4507
|
SubscriptionCancelled: "subscription.cancelled",
|
|
4880
4508
|
StartupGrantEnded: "startup.grant_ended",
|
|
4509
|
+
GrantEnded: "subscription.grant_ended",
|
|
4881
4510
|
SubscriptionPastDue: "subscription.past_due",
|
|
4882
4511
|
BalanceThresholdWarning: "balance.threshold.warning",
|
|
4883
4512
|
PlatformTierPriceIncrease: "platform.tier_price_increase",
|
|
@@ -4898,11 +4527,404 @@ const NotificationChannel = {
|
|
|
4898
4527
|
Push: "push",
|
|
4899
4528
|
Sms: "sms"
|
|
4900
4529
|
};
|
|
4901
|
-
const RecipientStrategy = {
|
|
4902
|
-
TenantAdmins: "tenant_admins",
|
|
4903
|
-
SpecificUser: "specific_user"
|
|
4530
|
+
const RecipientStrategy = {
|
|
4531
|
+
TenantAdmins: "tenant_admins",
|
|
4532
|
+
SpecificUser: "specific_user"
|
|
4533
|
+
};
|
|
4534
|
+
NotificationType.PaymentSucceeded, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.PaymentFailed, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationChannel.Sms, NotificationType.TopUpCompleted, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.AutoRechargeCompleted, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationType.AutoRechargeFailed, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationChannel.Sms, NotificationType.SubscriptionCreated, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationType.SubscriptionCancelled, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.StartupGrantEnded, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.GrantEnded, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.SubscriptionPastDue, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationChannel.Sms, NotificationType.BalanceThresholdWarning, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.PlatformTierPriceIncrease, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationType.AgentCreated, NotificationCategory.Agents, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.AgentProvisionFailed, NotificationCategory.Agents, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.AgentBillingSuspended, NotificationCategory.Agents, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.AgentDisconnectedExtended, NotificationCategory.Agents, RecipientStrategy.TenantAdmins, NotificationChannel.Push, NotificationType.BrowserTakeoverRequested, NotificationCategory.Agents, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.InviteCreated, NotificationCategory.System, RecipientStrategy.SpecificUser, NotificationChannel.Email, NotificationType.OrgClaimed, NotificationCategory.System, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.TeamMemberAdded, NotificationCategory.Team, RecipientStrategy.SpecificUser, NotificationChannel.Email, NotificationChannel.Push, NotificationType.ProjectMemberAdded, NotificationCategory.Team, RecipientStrategy.SpecificUser, NotificationChannel.Email, NotificationChannel.Push, NotificationType.IntegrationInstalled, NotificationCategory.Integrations, RecipientStrategy.TenantAdmins, NotificationChannel.Push, NotificationType.IntegrationRemoved, NotificationCategory.Integrations, RecipientStrategy.TenantAdmins, NotificationChannel.Push;
|
|
4535
|
+
//#endregion
|
|
4536
|
+
//#region ../../packages-internal/api-client/dist/services/auth.js
|
|
4537
|
+
var AuthService = class {
|
|
4538
|
+
client;
|
|
4539
|
+
constructor(client) {
|
|
4540
|
+
this.client = client;
|
|
4541
|
+
}
|
|
4542
|
+
prefix = "/auth";
|
|
4543
|
+
validate(token) {
|
|
4544
|
+
return this.client.request(`${this.prefix}/validate`, {
|
|
4545
|
+
method: "POST",
|
|
4546
|
+
body: JSON.stringify({ token })
|
|
4547
|
+
});
|
|
4548
|
+
}
|
|
4549
|
+
listTokens() {
|
|
4550
|
+
return this.client.request(`${this.prefix}/tokens`);
|
|
4551
|
+
}
|
|
4552
|
+
createToken(data) {
|
|
4553
|
+
return this.client.request(`${this.prefix}/tokens`, {
|
|
4554
|
+
method: "POST",
|
|
4555
|
+
body: JSON.stringify(data)
|
|
4556
|
+
});
|
|
4557
|
+
}
|
|
4558
|
+
deleteToken(tokenId) {
|
|
4559
|
+
return this.client.request(`${this.prefix}/tokens/${tokenId}`, { method: "DELETE" });
|
|
4560
|
+
}
|
|
4561
|
+
/**
|
|
4562
|
+
* Start a device-code flow. Called by the CLI when the user runs
|
|
4563
|
+
* `alfe login` and picks the browser path. The returned `device_code`
|
|
4564
|
+
* is the CLI's bearer secret for polling /auth/device-token; the
|
|
4565
|
+
* `user_code` is what the user types/sees on the dashboard.
|
|
4566
|
+
*
|
|
4567
|
+
* Uses `publicRequest` because the CLI has no token yet — the standard
|
|
4568
|
+
* `request` path would short-circuit with a synthetic 401.
|
|
4569
|
+
*/
|
|
4570
|
+
startDeviceCode(input) {
|
|
4571
|
+
return this.client.publicRequest(`${this.prefix}/device-code`, {
|
|
4572
|
+
method: "POST",
|
|
4573
|
+
body: JSON.stringify(input)
|
|
4574
|
+
});
|
|
4575
|
+
}
|
|
4576
|
+
/**
|
|
4577
|
+
* Poll for the minted API key. Public endpoint. Returns:
|
|
4578
|
+
* 200 → { api_key, tenantId, tokenExpiresAt } (success — write to config)
|
|
4579
|
+
* 428 → still pending (caller should sleep `interval` and retry)
|
|
4580
|
+
* 429 → polling too fast; caller should back off
|
|
4581
|
+
* 410 → device-code expired; user must run `alfe login` again
|
|
4582
|
+
* 400 → already redeemed (security: do not retry)
|
|
4583
|
+
*
|
|
4584
|
+
* Surface the HTTP-status code via the standard ApiResult error shape
|
|
4585
|
+
* so callers can branch.
|
|
4586
|
+
*/
|
|
4587
|
+
pollDeviceToken(deviceCode) {
|
|
4588
|
+
return this.client.publicRequest(`${this.prefix}/device-token`, {
|
|
4589
|
+
method: "POST",
|
|
4590
|
+
body: JSON.stringify({ device_code: deviceCode })
|
|
4591
|
+
});
|
|
4592
|
+
}
|
|
4593
|
+
/** Dashboard-side. Fetch the device fingerprint for an approval card. */
|
|
4594
|
+
lookupDeviceCode(userCode) {
|
|
4595
|
+
return this.client.request(`${this.prefix}/device-code/lookup`, {
|
|
4596
|
+
method: "POST",
|
|
4597
|
+
body: JSON.stringify({ user_code: userCode })
|
|
4598
|
+
});
|
|
4599
|
+
}
|
|
4600
|
+
/** Dashboard-side. Approve the pending device-code; CLI's next poll gets the key. */
|
|
4601
|
+
approveDeviceCode(input) {
|
|
4602
|
+
return this.client.request(`${this.prefix}/device-code/approve`, {
|
|
4603
|
+
method: "POST",
|
|
4604
|
+
body: JSON.stringify({
|
|
4605
|
+
user_code: input.userCode,
|
|
4606
|
+
expiresIn: input.expiresIn
|
|
4607
|
+
})
|
|
4608
|
+
});
|
|
4609
|
+
}
|
|
4610
|
+
getOnboardingStatus() {
|
|
4611
|
+
return this.client.request(`${this.prefix}/onboarding/status`);
|
|
4612
|
+
}
|
|
4613
|
+
completeOnboarding(input) {
|
|
4614
|
+
return this.client.request(`${this.prefix}/onboarding/complete`, {
|
|
4615
|
+
method: "POST",
|
|
4616
|
+
body: JSON.stringify(input)
|
|
4617
|
+
});
|
|
4618
|
+
}
|
|
4619
|
+
getAccessStatus() {
|
|
4620
|
+
return this.client.request(`${this.prefix}/access/status`);
|
|
4621
|
+
}
|
|
4622
|
+
redeemAccessCode(code) {
|
|
4623
|
+
return this.client.request(`${this.prefix}/access/redeem`, {
|
|
4624
|
+
method: "POST",
|
|
4625
|
+
body: JSON.stringify({ code })
|
|
4626
|
+
});
|
|
4627
|
+
}
|
|
4628
|
+
/**
|
|
4629
|
+
* Fetch the caller's current permission list as enforced by the gateway.
|
|
4630
|
+
* UI permission providers should call this on mount and refetch on
|
|
4631
|
+
* Clerk org switch to stay in sync with sub-tenant permission changes.
|
|
4632
|
+
*/
|
|
4633
|
+
getMyPermissions() {
|
|
4634
|
+
return this.client.request(`${this.prefix}/me/permissions`);
|
|
4635
|
+
}
|
|
4636
|
+
/**
|
|
4637
|
+
* Preview what deleting the caller's own account will do. Drives the Danger
|
|
4638
|
+
* Zone copy so the user sees an honest, kind-appropriate warning before the
|
|
4639
|
+
* irreversible action (a last-admin cascade wipes the whole workspace).
|
|
4640
|
+
*/
|
|
4641
|
+
getDeletionPreview() {
|
|
4642
|
+
return this.client.request(`${this.prefix}/me/deletion-preview`);
|
|
4643
|
+
}
|
|
4644
|
+
/**
|
|
4645
|
+
* Permanently delete the caller's own account. Returns `{ status: "deleting" }`
|
|
4646
|
+
* and tears the account down asynchronously — the Clerk user is deleted shortly
|
|
4647
|
+
* after, so the caller's session dies. On success, sign out and route the user
|
|
4648
|
+
* to a terminal "account is being deleted" state; do NOT retry.
|
|
4649
|
+
*
|
|
4650
|
+
* Pass `confirmKind` (the accountKind the user actually confirmed, from the
|
|
4651
|
+
* deletion preview): if membership changed between preview and execute, the
|
|
4652
|
+
* server answers 409 `account_kind_changed` instead of cascading a scope the
|
|
4653
|
+
* user never agreed to.
|
|
4654
|
+
*/
|
|
4655
|
+
deleteAccount(confirmKind) {
|
|
4656
|
+
return this.client.request(`${this.prefix}/me`, {
|
|
4657
|
+
method: "DELETE",
|
|
4658
|
+
...confirmKind ? { body: JSON.stringify({ confirmKind }) } : {}
|
|
4659
|
+
});
|
|
4660
|
+
}
|
|
4661
|
+
getSubscriptionStatus() {
|
|
4662
|
+
return this.client.request(`${this.prefix}/subscription`);
|
|
4663
|
+
}
|
|
4664
|
+
/**
|
|
4665
|
+
* Mint a short-lived, single-use Clerk sign-in token for the calling user so
|
|
4666
|
+
* a native client can hand its logged-in session to the web dashboard
|
|
4667
|
+
* (`${dashboard}/handoff?__clerk_ticket=<token>`). Server mints only for the
|
|
4668
|
+
* authenticated user — never a caller-supplied id.
|
|
4669
|
+
*/
|
|
4670
|
+
createHandoffToken() {
|
|
4671
|
+
return this.client.request(`${this.prefix}/handoff-token`, { method: "POST" });
|
|
4672
|
+
}
|
|
4673
|
+
applyForStartup(input) {
|
|
4674
|
+
return this.client.request(`${this.prefix}/subscription/apply-startup`, {
|
|
4675
|
+
method: "POST",
|
|
4676
|
+
body: JSON.stringify(input)
|
|
4677
|
+
});
|
|
4678
|
+
}
|
|
4679
|
+
/**
|
|
4680
|
+
* Accept an approved Startup Program invite. Call after the applicant has a
|
|
4681
|
+
* card on file (confirmed or freshly added) — this mints the Professional
|
|
4682
|
+
* grant subscription. Idempotent: a repeat call on an already-accepted
|
|
4683
|
+
* application returns `{ status: "accepted" }` without re-charging.
|
|
4684
|
+
*/
|
|
4685
|
+
acceptStartup() {
|
|
4686
|
+
return this.client.request(`${this.prefix}/subscription/accept-startup`, { method: "POST" });
|
|
4687
|
+
}
|
|
4688
|
+
createCheckoutSession(input) {
|
|
4689
|
+
return this.client.request(`${this.prefix}/subscription/checkout`, {
|
|
4690
|
+
method: "POST",
|
|
4691
|
+
body: JSON.stringify(input)
|
|
4692
|
+
});
|
|
4693
|
+
}
|
|
4694
|
+
/**
|
|
4695
|
+
* Change a personal (individual-tier) subscriber's platform plan in place on
|
|
4696
|
+
* their existing Stripe subscription — no second Checkout, no duplicate sub,
|
|
4697
|
+
* no double charge. Upgrades prorate immediately; downgrades apply with no
|
|
4698
|
+
* immediate charge/refund. Returns the updated subscription.
|
|
4699
|
+
*/
|
|
4700
|
+
changePlatformPlan(input) {
|
|
4701
|
+
return this.client.request(`${this.prefix}/subscription/change`, {
|
|
4702
|
+
method: "POST",
|
|
4703
|
+
body: JSON.stringify(input)
|
|
4704
|
+
});
|
|
4705
|
+
}
|
|
4706
|
+
/**
|
|
4707
|
+
* Preview the proration cost for changing a personal (individual-tier)
|
|
4708
|
+
* subscriber's platform plan — read-only companion to `changePlatformPlan`.
|
|
4709
|
+
* Nothing is charged.
|
|
4710
|
+
*/
|
|
4711
|
+
previewPlatformPlanChange(input) {
|
|
4712
|
+
return this.client.request(`${this.prefix}/subscription/change/preview`, {
|
|
4713
|
+
method: "POST",
|
|
4714
|
+
body: JSON.stringify(input)
|
|
4715
|
+
});
|
|
4716
|
+
}
|
|
4717
|
+
updateSeats(seats) {
|
|
4718
|
+
return this.client.request(`${this.prefix}/subscription/seats`, {
|
|
4719
|
+
method: "POST",
|
|
4720
|
+
body: JSON.stringify({ seats })
|
|
4721
|
+
});
|
|
4722
|
+
}
|
|
4723
|
+
previewSeatChange(seats) {
|
|
4724
|
+
return this.client.request(`${this.prefix}/subscription/seats/preview`, {
|
|
4725
|
+
method: "POST",
|
|
4726
|
+
body: JSON.stringify({ seats })
|
|
4727
|
+
});
|
|
4728
|
+
}
|
|
4729
|
+
listOrgMembers() {
|
|
4730
|
+
return this.client.request(`${this.prefix}/org/members`);
|
|
4731
|
+
}
|
|
4732
|
+
patchOrgMember(userId, body) {
|
|
4733
|
+
return this.client.request(`${this.prefix}/org/members/${encodeURIComponent(userId)}`, {
|
|
4734
|
+
method: "PATCH",
|
|
4735
|
+
body: JSON.stringify(body)
|
|
4736
|
+
});
|
|
4737
|
+
}
|
|
4738
|
+
removeOrgMember(userId) {
|
|
4739
|
+
return this.client.request(`${this.prefix}/org/members/${encodeURIComponent(userId)}`, { method: "DELETE" });
|
|
4740
|
+
}
|
|
4741
|
+
listOrgInvitations() {
|
|
4742
|
+
return this.client.request(`${this.prefix}/org/invitations`);
|
|
4743
|
+
}
|
|
4744
|
+
createOrgInvitation(input) {
|
|
4745
|
+
return this.client.request(`${this.prefix}/org/invitations`, {
|
|
4746
|
+
method: "POST",
|
|
4747
|
+
body: JSON.stringify(input)
|
|
4748
|
+
});
|
|
4749
|
+
}
|
|
4750
|
+
revokeOrgInvitation(invitationId) {
|
|
4751
|
+
return this.client.request(`${this.prefix}/org/invitations/${encodeURIComponent(invitationId)}`, { method: "DELETE" });
|
|
4752
|
+
}
|
|
4753
|
+
listOrgDomains() {
|
|
4754
|
+
return this.client.request(`${this.prefix}/org/domains`);
|
|
4755
|
+
}
|
|
4756
|
+
createOrgDomain(input) {
|
|
4757
|
+
return this.client.request(`${this.prefix}/org/domains`, {
|
|
4758
|
+
method: "POST",
|
|
4759
|
+
body: JSON.stringify(input)
|
|
4760
|
+
});
|
|
4761
|
+
}
|
|
4762
|
+
deleteOrgDomain(domainId) {
|
|
4763
|
+
return this.client.request(`${this.prefix}/org/domains/${encodeURIComponent(domainId)}`, { method: "DELETE" });
|
|
4764
|
+
}
|
|
4765
|
+
updateOrgSettings(input) {
|
|
4766
|
+
return this.client.request(`${this.prefix}/org/settings`, {
|
|
4767
|
+
method: "PATCH",
|
|
4768
|
+
body: JSON.stringify(input)
|
|
4769
|
+
});
|
|
4770
|
+
}
|
|
4771
|
+
};
|
|
4772
|
+
//#endregion
|
|
4773
|
+
//#region ../../packages-internal/api-client/dist/services/integrations.js
|
|
4774
|
+
var IntegrationsService = class {
|
|
4775
|
+
client;
|
|
4776
|
+
constructor(client) {
|
|
4777
|
+
this.client = client;
|
|
4778
|
+
}
|
|
4779
|
+
listScopedInstalls(scope, scopeId) {
|
|
4780
|
+
const params = new URLSearchParams({
|
|
4781
|
+
scope,
|
|
4782
|
+
scopeId
|
|
4783
|
+
});
|
|
4784
|
+
return this.client.request(`/integrations/scoped?${params}`);
|
|
4785
|
+
}
|
|
4786
|
+
installScoped(data) {
|
|
4787
|
+
return this.client.request("/integrations/scoped", {
|
|
4788
|
+
method: "POST",
|
|
4789
|
+
body: JSON.stringify(data)
|
|
4790
|
+
});
|
|
4791
|
+
}
|
|
4792
|
+
getScopedInstall(integrationId, scope, scopeId) {
|
|
4793
|
+
const params = new URLSearchParams({
|
|
4794
|
+
scope,
|
|
4795
|
+
scopeId
|
|
4796
|
+
});
|
|
4797
|
+
return this.client.request(`/integrations/scoped/${encodeURIComponent(integrationId)}?${params}`);
|
|
4798
|
+
}
|
|
4799
|
+
updateScopedInstall(integrationId, data) {
|
|
4800
|
+
return this.client.request(`/integrations/scoped/${encodeURIComponent(integrationId)}`, {
|
|
4801
|
+
method: "PATCH",
|
|
4802
|
+
body: JSON.stringify(data)
|
|
4803
|
+
});
|
|
4804
|
+
}
|
|
4805
|
+
removeScopedInstall(integrationId, scope, scopeId) {
|
|
4806
|
+
const params = new URLSearchParams({
|
|
4807
|
+
scope,
|
|
4808
|
+
scopeId
|
|
4809
|
+
});
|
|
4810
|
+
return this.client.request(`/integrations/scoped/${encodeURIComponent(integrationId)}?${params}`, { method: "DELETE" });
|
|
4811
|
+
}
|
|
4812
|
+
/**
|
|
4813
|
+
* Reinstall (re-apply latest) a scope-level install. Agent scope is rejected
|
|
4814
|
+
* by the route — use {@link reinstallIntegration} for agent-scoped reinstall.
|
|
4815
|
+
*/
|
|
4816
|
+
reinstallScoped(integrationId, scope, scopeId) {
|
|
4817
|
+
return this.client.request(`/integrations/scoped/${encodeURIComponent(integrationId)}/reinstall`, {
|
|
4818
|
+
method: "POST",
|
|
4819
|
+
body: JSON.stringify({
|
|
4820
|
+
scope,
|
|
4821
|
+
scopeId
|
|
4822
|
+
})
|
|
4823
|
+
});
|
|
4824
|
+
}
|
|
4825
|
+
listIntegrations(agentId, options) {
|
|
4826
|
+
const params = new URLSearchParams();
|
|
4827
|
+
if (options?.includeInherited) params.set("includeInherited", "true");
|
|
4828
|
+
if (options?.effective) params.set("effective", "true");
|
|
4829
|
+
const qs = params.toString();
|
|
4830
|
+
return this.client.request(`/integrations/agents/${agentId}${qs ? `?${qs}` : ""}`);
|
|
4831
|
+
}
|
|
4832
|
+
installIntegration(agentId, data) {
|
|
4833
|
+
return this.client.request(`/integrations/agents/${agentId}`, {
|
|
4834
|
+
method: "POST",
|
|
4835
|
+
body: JSON.stringify(data)
|
|
4836
|
+
});
|
|
4837
|
+
}
|
|
4838
|
+
getIntegrationConfig(agentId, integrationId) {
|
|
4839
|
+
return this.client.request(`/integrations/agents/${agentId}/${integrationId}/config`);
|
|
4840
|
+
}
|
|
4841
|
+
updateIntegration(agentId, integrationId, data) {
|
|
4842
|
+
return this.client.request(`/integrations/agents/${agentId}/${integrationId}`, {
|
|
4843
|
+
method: "PATCH",
|
|
4844
|
+
body: JSON.stringify(data)
|
|
4845
|
+
});
|
|
4846
|
+
}
|
|
4847
|
+
removeIntegration(agentId, integrationId) {
|
|
4848
|
+
return this.client.request(`/integrations/agents/${agentId}/${integrationId}`, { method: "DELETE" });
|
|
4849
|
+
}
|
|
4850
|
+
reinstallIntegration(agentId, integrationId) {
|
|
4851
|
+
return this.client.request(`/integrations/agents/${agentId}/${integrationId}/reinstall`, { method: "POST" });
|
|
4852
|
+
}
|
|
4853
|
+
/**
|
|
4854
|
+
* Upgrade an integration to the registry's latest version via the fast,
|
|
4855
|
+
* diff-based daemon path (bumps `version` without `reinstallRequestedAt`).
|
|
4856
|
+
* The agent stays online — no destructive teardown. Distinct from
|
|
4857
|
+
* {@link reinstallIntegration}, which is the destructive repair path.
|
|
4858
|
+
*/
|
|
4859
|
+
upgradeIntegration(agentId, integrationId) {
|
|
4860
|
+
return this.client.request(`/integrations/agents/${agentId}/${integrationId}/upgrade`, { method: "POST" });
|
|
4861
|
+
}
|
|
4862
|
+
getRegistry() {
|
|
4863
|
+
return this.client.request("/integrations/registry");
|
|
4864
|
+
}
|
|
4865
|
+
triggerSync(agentId) {
|
|
4866
|
+
return this.client.request("/integrations/sync/trigger", {
|
|
4867
|
+
method: "POST",
|
|
4868
|
+
body: JSON.stringify({ agentId })
|
|
4869
|
+
});
|
|
4870
|
+
}
|
|
4871
|
+
getDiscordGuildChannels(guildId) {
|
|
4872
|
+
return this.client.request(`/discord/guilds/${encodeURIComponent(guildId)}/channels`);
|
|
4873
|
+
}
|
|
4874
|
+
listMobileNumbers() {
|
|
4875
|
+
return this.client.request("/mobile/numbers");
|
|
4876
|
+
}
|
|
4877
|
+
searchMobileNumbers(country, query) {
|
|
4878
|
+
const params = new URLSearchParams();
|
|
4879
|
+
if (country) params.set("country", country);
|
|
4880
|
+
if (query) params.set("query", query);
|
|
4881
|
+
return this.client.request(`/mobile/numbers/search?${params}`);
|
|
4882
|
+
}
|
|
4883
|
+
assignMobileNumber(agentId, phoneNumber, countryCode) {
|
|
4884
|
+
return this.client.request("/mobile/numbers/assign", {
|
|
4885
|
+
method: "POST",
|
|
4886
|
+
body: JSON.stringify({
|
|
4887
|
+
agentId,
|
|
4888
|
+
phoneNumber,
|
|
4889
|
+
countryCode
|
|
4890
|
+
})
|
|
4891
|
+
});
|
|
4892
|
+
}
|
|
4893
|
+
releaseMobileNumber(agentId) {
|
|
4894
|
+
return this.client.request("/mobile/numbers/release", {
|
|
4895
|
+
method: "POST",
|
|
4896
|
+
body: JSON.stringify({ agentId })
|
|
4897
|
+
});
|
|
4898
|
+
}
|
|
4899
|
+
getMobileNumber(agentId) {
|
|
4900
|
+
return this.client.request(`/mobile/numbers?agentId=${encodeURIComponent(agentId)}`);
|
|
4901
|
+
}
|
|
4902
|
+
disconnectGoogle(agentId, email) {
|
|
4903
|
+
const query = email ? `?email=${encodeURIComponent(email)}` : "";
|
|
4904
|
+
return this.client.request(`/google/agents/${encodeURIComponent(agentId)}/account${query}`, { method: "DELETE" });
|
|
4905
|
+
}
|
|
4906
|
+
getAtlassianSites(agentId) {
|
|
4907
|
+
return this.client.request(`/atlassian/agents/${encodeURIComponent(agentId)}/sites`);
|
|
4908
|
+
}
|
|
4909
|
+
selectAtlassianSite(agentId, cloudId) {
|
|
4910
|
+
return this.client.request(`/atlassian/agents/${encodeURIComponent(agentId)}/sites`, {
|
|
4911
|
+
method: "PUT",
|
|
4912
|
+
body: JSON.stringify({ cloudId })
|
|
4913
|
+
});
|
|
4914
|
+
}
|
|
4915
|
+
listSlackChannels(agentId) {
|
|
4916
|
+
return this.client.request(`/slack/agents/${encodeURIComponent(agentId)}/channels`);
|
|
4917
|
+
}
|
|
4918
|
+
sendSlackMessage(agentId, channel, text) {
|
|
4919
|
+
return this.client.request(`/slack/agents/${encodeURIComponent(agentId)}/send`, {
|
|
4920
|
+
method: "POST",
|
|
4921
|
+
body: JSON.stringify({
|
|
4922
|
+
channel,
|
|
4923
|
+
text
|
|
4924
|
+
})
|
|
4925
|
+
});
|
|
4926
|
+
}
|
|
4904
4927
|
};
|
|
4905
|
-
NotificationType.PaymentSucceeded, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.PaymentFailed, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationChannel.Sms, NotificationType.TopUpCompleted, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.AutoRechargeCompleted, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationType.AutoRechargeFailed, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationChannel.Sms, NotificationType.SubscriptionCreated, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationType.SubscriptionCancelled, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.StartupGrantEnded, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.SubscriptionPastDue, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationChannel.Sms, NotificationType.BalanceThresholdWarning, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.PlatformTierPriceIncrease, NotificationCategory.Billing, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationType.AgentCreated, NotificationCategory.Agents, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.AgentProvisionFailed, NotificationCategory.Agents, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.AgentBillingSuspended, NotificationCategory.Agents, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.AgentDisconnectedExtended, NotificationCategory.Agents, RecipientStrategy.TenantAdmins, NotificationChannel.Push, NotificationType.BrowserTakeoverRequested, NotificationCategory.Agents, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.InviteCreated, NotificationCategory.System, RecipientStrategy.SpecificUser, NotificationChannel.Email, NotificationType.OrgClaimed, NotificationCategory.System, RecipientStrategy.TenantAdmins, NotificationChannel.Email, NotificationChannel.Push, NotificationType.TeamMemberAdded, NotificationCategory.Team, RecipientStrategy.SpecificUser, NotificationChannel.Email, NotificationChannel.Push, NotificationType.ProjectMemberAdded, NotificationCategory.Team, RecipientStrategy.SpecificUser, NotificationChannel.Email, NotificationChannel.Push, NotificationType.IntegrationInstalled, NotificationCategory.Integrations, RecipientStrategy.TenantAdmins, NotificationChannel.Push, NotificationType.IntegrationRemoved, NotificationCategory.Integrations, RecipientStrategy.TenantAdmins, NotificationChannel.Push;
|
|
4906
4928
|
//#endregion
|
|
4907
4929
|
//#region src/config.ts
|
|
4908
4930
|
/**
|
|
@@ -5126,6 +5148,17 @@ async function loadDaemonConfig() {
|
|
|
5126
5148
|
const gatewayWsUrl = alfeConfig.gateway_url ?? deriveGatewayWsUrl(apiEndpoint);
|
|
5127
5149
|
const runtimes = await loadRuntimeConfigs();
|
|
5128
5150
|
const runtime = alfeConfig.runtime ?? identity.runtime;
|
|
5151
|
+
let defaultModel;
|
|
5152
|
+
if (runtime === "claude-code") {
|
|
5153
|
+
let timer;
|
|
5154
|
+
const ws = await Promise.race([fetchAgentConfig(alfeConfig.api_key, apiEndpoint), new Promise((resolve) => {
|
|
5155
|
+
timer = setTimeout(() => {
|
|
5156
|
+
resolve(null);
|
|
5157
|
+
}, 5e3);
|
|
5158
|
+
})]);
|
|
5159
|
+
if (timer) clearTimeout(timer);
|
|
5160
|
+
defaultModel = ws?.defaultModel;
|
|
5161
|
+
}
|
|
5129
5162
|
return {
|
|
5130
5163
|
apiKey: alfeConfig.api_key,
|
|
5131
5164
|
apiEndpoint,
|
|
@@ -5136,7 +5169,8 @@ async function loadDaemonConfig() {
|
|
|
5136
5169
|
orgId: identity.orgId,
|
|
5137
5170
|
runtime,
|
|
5138
5171
|
runtimes,
|
|
5139
|
-
autoStartRuntime: alfeConfig.auto_start_runtime ?? true
|
|
5172
|
+
autoStartRuntime: alfeConfig.auto_start_runtime ?? true,
|
|
5173
|
+
...defaultModel ? { defaultModel } : {}
|
|
5140
5174
|
};
|
|
5141
5175
|
}
|
|
5142
5176
|
/**
|
|
@@ -7073,12 +7107,25 @@ async function uninstallSystemd() {
|
|
|
7073
7107
|
return `Uninstalled: ${unitPath}`;
|
|
7074
7108
|
}
|
|
7075
7109
|
/**
|
|
7076
|
-
*
|
|
7110
|
+
* Bootstrap (load) the launchd service from its plist if it isn't already
|
|
7111
|
+
* loaded. Already-loaded is an error we ignore. Needed so `start`/`restart`
|
|
7112
|
+
* work after `stopService()` boots the service OUT.
|
|
7113
|
+
*/
|
|
7114
|
+
function ensureLaunchdLoaded(uid) {
|
|
7115
|
+
try {
|
|
7116
|
+
execSync(`launchctl bootstrap gui/${uid} ${getLaunchdPlistPath()}`, { stdio: "pipe" });
|
|
7117
|
+
} catch {}
|
|
7118
|
+
}
|
|
7119
|
+
/**
|
|
7120
|
+
* Start the installed service via systemctl/launchctl. Bootstraps the launchd
|
|
7121
|
+
* service first so this also works after `stopService()` booted it out.
|
|
7077
7122
|
*/
|
|
7078
7123
|
function startService() {
|
|
7079
7124
|
const platform = process.platform;
|
|
7080
7125
|
if (platform === "darwin") {
|
|
7081
|
-
|
|
7126
|
+
const uid = getLaunchdUid();
|
|
7127
|
+
ensureLaunchdLoaded(uid);
|
|
7128
|
+
execSync(`launchctl kickstart -k gui/${uid}/${LAUNCHD_LABEL}`, { stdio: "pipe" });
|
|
7082
7129
|
logger$1.info("Started launchd service");
|
|
7083
7130
|
return;
|
|
7084
7131
|
}
|
|
@@ -7090,6 +7137,59 @@ function startService() {
|
|
|
7090
7137
|
throw new Error(`Unsupported platform: ${platform}`);
|
|
7091
7138
|
}
|
|
7092
7139
|
/**
|
|
7140
|
+
* Restart the installed service via systemctl/launchctl. This is the
|
|
7141
|
+
* service-manager-native restart (`kickstart -k` / `systemctl restart`) — the
|
|
7142
|
+
* CLI uses it instead of killing the process inline, which would fight launchd
|
|
7143
|
+
* `KeepAlive` / systemd `Restart=always`.
|
|
7144
|
+
*/
|
|
7145
|
+
function restartService() {
|
|
7146
|
+
const platform = process.platform;
|
|
7147
|
+
if (platform === "darwin") {
|
|
7148
|
+
const uid = getLaunchdUid();
|
|
7149
|
+
ensureLaunchdLoaded(uid);
|
|
7150
|
+
execSync(`launchctl kickstart -k gui/${uid}/${LAUNCHD_LABEL}`, { stdio: "pipe" });
|
|
7151
|
+
logger$1.info("Restarted launchd service");
|
|
7152
|
+
return;
|
|
7153
|
+
}
|
|
7154
|
+
if (platform === "linux") {
|
|
7155
|
+
execSync(`${isRootUser() ? "systemctl" : "systemctl --user"} restart ${SYSTEMD_SERVICE}`, { stdio: "pipe" });
|
|
7156
|
+
logger$1.info("Restarted systemd service");
|
|
7157
|
+
return;
|
|
7158
|
+
}
|
|
7159
|
+
throw new Error(`Unsupported platform: ${platform}`);
|
|
7160
|
+
}
|
|
7161
|
+
/**
|
|
7162
|
+
* Stop the installed service via systemctl/launchctl. On macOS this boots the
|
|
7163
|
+
* service OUT (unloads it) so launchd's `KeepAlive` does NOT respawn it;
|
|
7164
|
+
* `startService()` bootstraps it again. On Linux the unit stays enabled (starts
|
|
7165
|
+
* on next boot); `systemctl stop` just halts the current run.
|
|
7166
|
+
*/
|
|
7167
|
+
function stopService() {
|
|
7168
|
+
const platform = process.platform;
|
|
7169
|
+
if (platform === "darwin") {
|
|
7170
|
+
execSync(`launchctl bootout gui/${getLaunchdUid()}/${LAUNCHD_LABEL}`, { stdio: "pipe" });
|
|
7171
|
+
logger$1.info("Stopped launchd service");
|
|
7172
|
+
return;
|
|
7173
|
+
}
|
|
7174
|
+
if (platform === "linux") {
|
|
7175
|
+
execSync(`${isRootUser() ? "systemctl" : "systemctl --user"} stop ${SYSTEMD_SERVICE}`, { stdio: "pipe" });
|
|
7176
|
+
logger$1.info("Stopped systemd service");
|
|
7177
|
+
return;
|
|
7178
|
+
}
|
|
7179
|
+
throw new Error(`Unsupported platform: ${platform}`);
|
|
7180
|
+
}
|
|
7181
|
+
/**
|
|
7182
|
+
* True when the gateway is installed as a system service (launchd plist /
|
|
7183
|
+
* systemd unit present). Lets the CLI restart/stop/start THROUGH the service
|
|
7184
|
+
* manager instead of driving the daemon inline via the PID file.
|
|
7185
|
+
*/
|
|
7186
|
+
function isServiceInstalled() {
|
|
7187
|
+
const platform = process.platform;
|
|
7188
|
+
if (platform === "darwin") return existsSync(getLaunchdPlistPath());
|
|
7189
|
+
if (platform === "linux") return existsSync(isRootUser() ? getSystemdSystemServicePath() : getSystemdServicePath());
|
|
7190
|
+
return false;
|
|
7191
|
+
}
|
|
7192
|
+
/**
|
|
7093
7193
|
* Write the current process PID to the PID file.
|
|
7094
7194
|
*/
|
|
7095
7195
|
async function writePidFile() {
|
|
@@ -23913,7 +24013,7 @@ async function startDaemon() {
|
|
|
23913
24013
|
runtimeProcess = new RuntimeProcess({
|
|
23914
24014
|
runtime: config.runtime,
|
|
23915
24015
|
workspace: runtimeCfg.workspace,
|
|
23916
|
-
env: {}
|
|
24016
|
+
env: config.runtime === "claude-code" && config.defaultModel ? { ALFE_DEFAULT_MODEL: config.defaultModel } : {}
|
|
23917
24017
|
});
|
|
23918
24018
|
runtimeProcess.setTurnActivityProbe(turnActivityProbe);
|
|
23919
24019
|
runtimeProcess.start();
|
|
@@ -24105,7 +24205,7 @@ async function executeCloudCommand(command) {
|
|
|
24105
24205
|
};
|
|
24106
24206
|
const payload = command.payload;
|
|
24107
24207
|
const runtime = config.runtime;
|
|
24108
|
-
const version = payload?.version ?? (runtime === "openclaw" ? "2026.6.11" : void 0);
|
|
24208
|
+
const version = payload?.version ?? (runtime === "openclaw" ? "2026.6.11" : runtime === "claude-code" ? "0.1.3" : void 0);
|
|
24109
24209
|
upgradingRuntime = true;
|
|
24110
24210
|
setTimeout(() => {
|
|
24111
24211
|
(async () => {
|
|
@@ -24805,4 +24905,4 @@ function formatDuration(ms) {
|
|
|
24805
24905
|
return `${String(Math.round(seconds / 3600))}h`;
|
|
24806
24906
|
}
|
|
24807
24907
|
//#endregion
|
|
24808
|
-
export { installService as a,
|
|
24908
|
+
export { loadDaemonConfig as _, installService as a, PINNED_OPENCLAW_VERSION as b, startService as c, uninstallService as d, PROTOCOL_VERSION as f, fetchAgentConfig as g, SOCKET_PATH as h, checkExistingDaemon as i, stopExistingDaemon as l, PID_PATH as m, queryDaemonHealth as n, isServiceInstalled as o, ALFE_DIR as p, startDaemon as r, restartService as s, formatHealthReport as t, stopService as u, resolveAgentIdentity as v, PINNED_CLAUDE_CODE_HOST_VERSION as y };
|
package/dist/runtime-upgrade.js
CHANGED
|
@@ -19,13 +19,19 @@ const execFileAsync = promisify(execFile);
|
|
|
19
19
|
/**
|
|
20
20
|
* Resolve the per-runtime upgrade command.
|
|
21
21
|
*
|
|
22
|
-
* - `openclaw`:
|
|
23
|
-
* - `
|
|
24
|
-
*
|
|
25
|
-
*
|
|
22
|
+
* - `openclaw`: `npm install -g openclaw@<version>` — version-pinned.
|
|
23
|
+
* - `claude-code`: `npm install -g @alfe.ai/claude-code-host@<version>` — the
|
|
24
|
+
* runtime child is the host binary; mirrors openclaw. The
|
|
25
|
+
* caller defaults a missing version to the pin.
|
|
26
|
+
* - `hermes`: `hermes update --yes` — Hermes self-updates from its own
|
|
27
|
+
* channel. A pinned version does not map to a Hermes CLI flag,
|
|
28
|
+
* so the `version` arg is intentionally ignored on this branch.
|
|
26
29
|
*
|
|
27
|
-
* Returns `undefined` for an unknown runtime (or openclaw with no
|
|
28
|
-
* which the caller treats as a failed upgrade (restart on the old
|
|
30
|
+
* Returns `undefined` for an unknown runtime (or openclaw/claude-code with no
|
|
31
|
+
* version), which the caller treats as a failed upgrade (restart on the old
|
|
32
|
+
* version). `upgradeRuntime` restarts the RuntimeProcess child regardless of
|
|
33
|
+
* runtime, so a new branch here is all that's needed to cycle onto the new
|
|
34
|
+
* version.
|
|
29
35
|
*/
|
|
30
36
|
function resolveUpgradeCommand(runtime, version) {
|
|
31
37
|
switch (runtime) {
|
|
@@ -39,6 +45,16 @@ function resolveUpgradeCommand(runtime, version) {
|
|
|
39
45
|
`openclaw@${version}`
|
|
40
46
|
]
|
|
41
47
|
};
|
|
48
|
+
case "claude-code":
|
|
49
|
+
if (!version) return void 0;
|
|
50
|
+
return {
|
|
51
|
+
command: "npm",
|
|
52
|
+
args: [
|
|
53
|
+
"install",
|
|
54
|
+
"-g",
|
|
55
|
+
`@alfe.ai/claude-code-host@${version}`
|
|
56
|
+
]
|
|
57
|
+
};
|
|
42
58
|
case "hermes": return {
|
|
43
59
|
command: "hermes",
|
|
44
60
|
args: ["update", "--yes"]
|
package/dist/src/index.d.ts
CHANGED
|
@@ -59,6 +59,26 @@ declare function startDaemon(): Promise<void>;
|
|
|
59
59
|
*/
|
|
60
60
|
declare const PINNED_OPENCLAW_VERSION = "2026.6.11";
|
|
61
61
|
//#endregion
|
|
62
|
+
//#region src/claude-code-host-version.d.ts
|
|
63
|
+
/**
|
|
64
|
+
* The `@alfe.ai/claude-code-host` version Alfe pins the claude-code runtime to —
|
|
65
|
+
* the single source of truth for its install paths:
|
|
66
|
+
* - `@alfe.ai/cli` `installClaudeCodeHost` (fresh `alfe setup`)
|
|
67
|
+
* - the daemon `runtime.update` default (this package)
|
|
68
|
+
*
|
|
69
|
+
* Pinning (rather than floating `npm install -g @alfe.ai/claude-code-host` →
|
|
70
|
+
* `latest`) is deliberate: the host is the claude-code runtime child on every
|
|
71
|
+
* self-hosted claude-code agent, so a bad `latest` publish would auto-reach
|
|
72
|
+
* every new `alfe setup` with no CLI gate. Bump deliberately after validating a
|
|
73
|
+
* new host, then cut a CLI release so the pin travels with the CLI version. The
|
|
74
|
+
* dashboard still surfaces npm-`latest` as an explicit opt-in upgrade.
|
|
75
|
+
*
|
|
76
|
+
* NOTE: claude-code is self-hosted-only (no managed Docker image), so — unlike
|
|
77
|
+
* `PINNED_OPENCLAW_VERSION` — there is no `services/compute/Dockerfile` mirror to
|
|
78
|
+
* keep in sync.
|
|
79
|
+
*/
|
|
80
|
+
declare const PINNED_CLAUDE_CODE_HOST_VERSION = "0.1.3";
|
|
81
|
+
//#endregion
|
|
62
82
|
//#region src/sentry.d.ts
|
|
63
83
|
/**
|
|
64
84
|
* Agent-side error reporting (Sentry) for the Alfe CLI + gateway daemon.
|
|
@@ -261,6 +281,13 @@ interface DaemonConfig {
|
|
|
261
281
|
runtimes: Record<string, RuntimeConfig>;
|
|
262
282
|
/** Whether to auto-start the agent runtime process (e.g. openclaw) */
|
|
263
283
|
autoStartRuntime: boolean;
|
|
284
|
+
/**
|
|
285
|
+
* The agent's bare `defaultModel`, resolved for claude-code only (other
|
|
286
|
+
* runtimes receive their model via the desired-state reconcile, not here).
|
|
287
|
+
* The daemon injects it into the host env so `claude -p --model` uses the
|
|
288
|
+
* dashboard-selected model. Never provider-qualified.
|
|
289
|
+
*/
|
|
290
|
+
defaultModel?: string;
|
|
264
291
|
}
|
|
265
292
|
interface AgentIdentity {
|
|
266
293
|
agentId: string;
|
|
@@ -349,9 +376,30 @@ declare function installService(): Promise<string>;
|
|
|
349
376
|
*/
|
|
350
377
|
declare function uninstallService(): Promise<string>;
|
|
351
378
|
/**
|
|
352
|
-
* Start the installed service via systemctl/launchctl.
|
|
379
|
+
* Start the installed service via systemctl/launchctl. Bootstraps the launchd
|
|
380
|
+
* service first so this also works after `stopService()` booted it out.
|
|
353
381
|
*/
|
|
354
382
|
declare function startService(): void;
|
|
383
|
+
/**
|
|
384
|
+
* Restart the installed service via systemctl/launchctl. This is the
|
|
385
|
+
* service-manager-native restart (`kickstart -k` / `systemctl restart`) — the
|
|
386
|
+
* CLI uses it instead of killing the process inline, which would fight launchd
|
|
387
|
+
* `KeepAlive` / systemd `Restart=always`.
|
|
388
|
+
*/
|
|
389
|
+
declare function restartService(): void;
|
|
390
|
+
/**
|
|
391
|
+
* Stop the installed service via systemctl/launchctl. On macOS this boots the
|
|
392
|
+
* service OUT (unloads it) so launchd's `KeepAlive` does NOT respawn it;
|
|
393
|
+
* `startService()` bootstraps it again. On Linux the unit stays enabled (starts
|
|
394
|
+
* on next boot); `systemctl stop` just halts the current run.
|
|
395
|
+
*/
|
|
396
|
+
declare function stopService(): void;
|
|
397
|
+
/**
|
|
398
|
+
* True when the gateway is installed as a system service (launchd plist /
|
|
399
|
+
* systemd unit present). Lets the CLI restart/stop/start THROUGH the service
|
|
400
|
+
* manager instead of driving the daemon inline via the PID file.
|
|
401
|
+
*/
|
|
402
|
+
declare function isServiceInstalled(): boolean;
|
|
355
403
|
/**
|
|
356
404
|
* Write the current process PID to the PID file.
|
|
357
405
|
*/
|
|
@@ -366,4 +414,4 @@ declare function checkExistingDaemon(): Promise<number | null>;
|
|
|
366
414
|
*/
|
|
367
415
|
declare function stopExistingDaemon(): Promise<boolean>;
|
|
368
416
|
//#endregion
|
|
369
|
-
export { AGENT_DAEMON_SENTRY_DSN, AGENT_MCP_SENTRY_DSN, AGENT_RUNTIME_SENTRY_DSN, ALFE_DIR, type AgentIdentity, type AgentWorkspaceConfig, type DaemonConfig, type DaemonHealth, type IPCEvent, type IPCRequest, type IPCResponse, type InitAgentSentryOptions, PID_PATH, PINNED_OPENCLAW_VERSION, PROTOCOL_VERSION, type RuntimeOutputLine, SOCKET_PATH, type SentrySurface, captureCliFailure, captureFatal, captureIntegrationFailure, captureMcpFailure, captureRuntimeCrash, captureRuntimeErrorOutput, checkExistingDaemon, fetchAgentConfig, flushSentry, formatHealthReport, initAgentSentry, installService, loadDaemonConfig, logger, queryDaemonHealth, resolveAgentIdentity, setAgentContext, startDaemon, startService, stopExistingDaemon, uninstallService };
|
|
417
|
+
export { AGENT_DAEMON_SENTRY_DSN, AGENT_MCP_SENTRY_DSN, AGENT_RUNTIME_SENTRY_DSN, ALFE_DIR, type AgentIdentity, type AgentWorkspaceConfig, type DaemonConfig, type DaemonHealth, type IPCEvent, type IPCRequest, type IPCResponse, type InitAgentSentryOptions, PID_PATH, PINNED_CLAUDE_CODE_HOST_VERSION, PINNED_OPENCLAW_VERSION, PROTOCOL_VERSION, type RuntimeOutputLine, SOCKET_PATH, type SentrySurface, captureCliFailure, captureFatal, captureIntegrationFailure, captureMcpFailure, captureRuntimeCrash, captureRuntimeErrorOutput, checkExistingDaemon, fetchAgentConfig, flushSentry, formatHealthReport, initAgentSentry, installService, isServiceInstalled, loadDaemonConfig, logger, queryDaemonHealth, resolveAgentIdentity, restartService, setAgentContext, startDaemon, startService, stopExistingDaemon, stopService, uninstallService };
|
package/dist/src/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as installService, c as
|
|
1
|
+
import { _ as loadDaemonConfig, a as installService, b as PINNED_OPENCLAW_VERSION, c as startService, d as uninstallService, f as PROTOCOL_VERSION, g as fetchAgentConfig, h as SOCKET_PATH, i as checkExistingDaemon, l as stopExistingDaemon, m as PID_PATH, n as queryDaemonHealth, o as isServiceInstalled, p as ALFE_DIR, r as startDaemon, s as restartService, t as formatHealthReport, u as stopService, v as resolveAgentIdentity, y as PINNED_CLAUDE_CODE_HOST_VERSION } from "../health.js";
|
|
2
2
|
import { n as logger } from "../logger.js";
|
|
3
3
|
import { a as captureFatal, c as captureRuntimeCrash, d as initAgentSentry, f as setAgentContext, i as captureCliFailure, l as captureRuntimeErrorOutput, n as AGENT_MCP_SENTRY_DSN, o as captureIntegrationFailure, r as AGENT_RUNTIME_SENTRY_DSN, s as captureMcpFailure, t as AGENT_DAEMON_SENTRY_DSN, u as flushSentry } from "../sentry.js";
|
|
4
|
-
export { AGENT_DAEMON_SENTRY_DSN, AGENT_MCP_SENTRY_DSN, AGENT_RUNTIME_SENTRY_DSN, ALFE_DIR, PID_PATH, PINNED_OPENCLAW_VERSION, PROTOCOL_VERSION, SOCKET_PATH, captureCliFailure, captureFatal, captureIntegrationFailure, captureMcpFailure, captureRuntimeCrash, captureRuntimeErrorOutput, checkExistingDaemon, fetchAgentConfig, flushSentry, formatHealthReport, initAgentSentry, installService, loadDaemonConfig, logger, queryDaemonHealth, resolveAgentIdentity, setAgentContext, startDaemon, startService, stopExistingDaemon, uninstallService };
|
|
4
|
+
export { AGENT_DAEMON_SENTRY_DSN, AGENT_MCP_SENTRY_DSN, AGENT_RUNTIME_SENTRY_DSN, ALFE_DIR, PID_PATH, PINNED_CLAUDE_CODE_HOST_VERSION, PINNED_OPENCLAW_VERSION, PROTOCOL_VERSION, SOCKET_PATH, captureCliFailure, captureFatal, captureIntegrationFailure, captureMcpFailure, captureRuntimeCrash, captureRuntimeErrorOutput, checkExistingDaemon, fetchAgentConfig, flushSentry, formatHealthReport, initAgentSentry, installService, isServiceInstalled, loadDaemonConfig, logger, queryDaemonHealth, resolveAgentIdentity, restartService, setAgentContext, startDaemon, startService, stopExistingDaemon, stopService, uninstallService };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alfe.ai/gateway",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"description": "Alfe local gateway daemon — persistent control plane for agent integrations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
"pino-roll": "^1.2.0",
|
|
24
24
|
"smol-toml": ">=1.6.1",
|
|
25
25
|
"ws": "^8.18.0",
|
|
26
|
-
"@alfe.ai/agent-api-client": "^0.11.
|
|
26
|
+
"@alfe.ai/agent-api-client": "^0.11.1",
|
|
27
27
|
"@alfe.ai/ai-proxy-local": "^0.0.13",
|
|
28
28
|
"@alfe.ai/config": "^0.3.0",
|
|
29
|
-
"@alfe.ai/integration-manifest": "^0.3.
|
|
30
|
-
"@alfe.ai/integrations": "^0.5.
|
|
29
|
+
"@alfe.ai/integration-manifest": "^0.3.3",
|
|
30
|
+
"@alfe.ai/integrations": "^0.5.3",
|
|
31
31
|
"@alfe.ai/mcp-bundler": "^0.3.2"
|
|
32
32
|
},
|
|
33
33
|
"license": "UNLICENSED",
|