@roamcode.ai/server 1.0.22 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/container/relay.js +1647 -0
- package/dist/health-watchdog.js +87 -0
- package/dist/index.d.ts +1775 -20
- package/dist/index.js +18085 -3812
- package/dist/managed-update-helper.js +4 -1
- package/dist/relay-start.d.ts +118 -0
- package/dist/relay-start.js +1642 -0
- package/dist/start.d.ts +509 -19
- package/dist/start.js +17254 -4741
- package/package.json +6 -5
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as better_sqlite3 from 'better-sqlite3';
|
|
2
2
|
import { FastifyInstance } from 'fastify';
|
|
3
|
+
import WebSocket from 'ws';
|
|
4
|
+
import { z, ZodType } from 'zod';
|
|
3
5
|
import { spawn, ChildProcess, SpawnOptions } from 'node:child_process';
|
|
4
6
|
import { EventEmitter } from 'node:events';
|
|
5
|
-
import { ZodType } from 'zod';
|
|
6
7
|
|
|
7
8
|
interface ServerConfig {
|
|
8
9
|
claudeBin: string;
|
|
@@ -138,6 +139,12 @@ declare function assertConfigAllowsStart(cfg: ServerRuntimeConfig): void;
|
|
|
138
139
|
declare function extractBearerToken(authorizationHeader: string | undefined): string | undefined;
|
|
139
140
|
interface AuthGateOptions {
|
|
140
141
|
token?: string;
|
|
142
|
+
/**
|
|
143
|
+
* Optional verifier for independently revocable credentials (for example per-device tokens). It
|
|
144
|
+
* receives the presented plaintext once; implementations should persist only a digest. A verifier
|
|
145
|
+
* failure is treated as an invalid credential and can never take the server down.
|
|
146
|
+
*/
|
|
147
|
+
verifyCredential?: (token: string) => boolean;
|
|
141
148
|
/** Consecutive failures from one client before it is locked out. Default 10. */
|
|
142
149
|
maxFailures?: number;
|
|
143
150
|
/** Lockout duration in ms. Default 60000. */
|
|
@@ -181,6 +188,7 @@ declare class AuthGate {
|
|
|
181
188
|
private readonly lockoutMs;
|
|
182
189
|
private readonly graceMs;
|
|
183
190
|
private readonly now;
|
|
191
|
+
private readonly verifyCredential?;
|
|
184
192
|
private readonly clients;
|
|
185
193
|
constructor(opts: AuthGateOptions);
|
|
186
194
|
check(presentedToken: string | undefined, clientKey: string): AuthCheckResult;
|
|
@@ -193,6 +201,10 @@ declare class AuthGate {
|
|
|
193
201
|
* slate is correct (and avoids leaving a client locked out against a token that no longer exists).
|
|
194
202
|
*/
|
|
195
203
|
rotateToken(newToken: string): void;
|
|
204
|
+
/** True only for the current host recovery credential (never a device key or grace token). */
|
|
205
|
+
isCurrentHostToken(presentedToken: string | undefined): boolean;
|
|
206
|
+
/** Security reset: replace the host credential immediately, with no previous-token grace window. */
|
|
207
|
+
resetToken(newToken: string): void;
|
|
196
208
|
/** Drop entries whose lockout has expired and whose failure count is 0 — keeps the map bounded. */
|
|
197
209
|
private sweepExpired;
|
|
198
210
|
/** TEST ONLY: number of tracked clients currently locked (lockedUntil in the future). */
|
|
@@ -319,7 +331,58 @@ declare class FsService {
|
|
|
319
331
|
pruneOlderThan(target: string, maxAgeMs: number, now?: number, recursive?: boolean): Promise<number>;
|
|
320
332
|
}
|
|
321
333
|
|
|
322
|
-
|
|
334
|
+
declare const ADAPTER_CONTRACT_VERSION: 1;
|
|
335
|
+
declare const adapterCapabilityNames: readonly ["probe", "launch", "resume", "state", "identity", "metadata", "usage", "login", "attachments", "cleanup"];
|
|
336
|
+
type AdapterCapabilityName = (typeof adapterCapabilityNames)[number];
|
|
337
|
+
type AdapterStateAuthority = "native-events" | "runtime-signals" | "pane-heuristics";
|
|
338
|
+
interface AdapterManifestV1 {
|
|
339
|
+
schemaVersion: typeof ADAPTER_CONTRACT_VERSION;
|
|
340
|
+
id: string;
|
|
341
|
+
version: string;
|
|
342
|
+
displayName: string;
|
|
343
|
+
platforms: Array<"darwin" | "linux">;
|
|
344
|
+
resumeIdentity: "optional" | "required" | "unsupported";
|
|
345
|
+
capabilities: Record<AdapterCapabilityName, boolean>;
|
|
346
|
+
stateAuthority: AdapterStateAuthority[];
|
|
347
|
+
/** JSON Schema for the adapter-owned launch options. */
|
|
348
|
+
optionSchema: Record<string, unknown>;
|
|
349
|
+
}
|
|
350
|
+
declare class AdapterManifestError extends Error {
|
|
351
|
+
constructor(message: string);
|
|
352
|
+
}
|
|
353
|
+
/** The supported, bounded JSON Schema subset shared by the server validator, generated UI, and OpenAPI. */
|
|
354
|
+
declare function validateAdapterOptionSchema(value: unknown): Record<string, unknown>;
|
|
355
|
+
declare function validateAdapterManifest(value: unknown): AdapterManifestV1;
|
|
356
|
+
/** Validate and freeze the public metadata at the adapter boundary before any lifecycle code can run. */
|
|
357
|
+
declare function defineAdapterManifest(value: AdapterManifestV1): Readonly<AdapterManifestV1>;
|
|
358
|
+
declare function publicAdapterDescriptor(manifest: AdapterManifestV1, source: "built-in" | "installed"): {
|
|
359
|
+
id: string;
|
|
360
|
+
displayName: string;
|
|
361
|
+
version: string;
|
|
362
|
+
schemaVersion: 1;
|
|
363
|
+
source: "built-in" | "installed";
|
|
364
|
+
enabled: boolean;
|
|
365
|
+
platforms: ("darwin" | "linux")[];
|
|
366
|
+
resumeIdentity: "optional" | "required" | "unsupported";
|
|
367
|
+
capabilities: {
|
|
368
|
+
state: boolean;
|
|
369
|
+
probe: boolean;
|
|
370
|
+
launch: boolean;
|
|
371
|
+
resume: boolean;
|
|
372
|
+
identity: boolean;
|
|
373
|
+
metadata: boolean;
|
|
374
|
+
usage: boolean;
|
|
375
|
+
login: boolean;
|
|
376
|
+
attachments: boolean;
|
|
377
|
+
cleanup: boolean;
|
|
378
|
+
};
|
|
379
|
+
stateAuthority: AdapterStateAuthority[];
|
|
380
|
+
optionSchema: Record<string, unknown>;
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
/** Public adapter identity. Built-ins are ordinary ids under the same contract; third parties are not
|
|
384
|
+
* forced through a source-code union update. Runtime validation is owned by ProviderRegistry. */
|
|
385
|
+
type ProviderId = string;
|
|
323
386
|
interface ProviderAvailability {
|
|
324
387
|
terminalAvailable: boolean;
|
|
325
388
|
metadataAvailable: boolean;
|
|
@@ -350,7 +413,22 @@ type CodexSessionOptions = {
|
|
|
350
413
|
dangerouslyBypassApprovalsAndSandbox?: boolean;
|
|
351
414
|
addDirs?: string[];
|
|
352
415
|
};
|
|
353
|
-
|
|
416
|
+
interface ProviderSessionOptions {
|
|
417
|
+
provider: ProviderId;
|
|
418
|
+
model?: string;
|
|
419
|
+
effort?: string;
|
|
420
|
+
reasoningEffort?: string;
|
|
421
|
+
permissionMode?: ClaudeSessionOptions["permissionMode"];
|
|
422
|
+
dangerouslySkip?: boolean;
|
|
423
|
+
sandbox?: CodexSessionOptions["sandbox"];
|
|
424
|
+
approvalPolicy?: CodexSessionOptions["approvalPolicy"];
|
|
425
|
+
profile?: string;
|
|
426
|
+
webSearch?: boolean;
|
|
427
|
+
dangerouslyBypassApprovalsAndSandbox?: boolean;
|
|
428
|
+
addDirs?: string[];
|
|
429
|
+
legacyArgs?: string[];
|
|
430
|
+
[key: string]: unknown;
|
|
431
|
+
}
|
|
354
432
|
type LaunchIntent = "fresh" | "resume";
|
|
355
433
|
interface ProcessSpec {
|
|
356
434
|
executable: string;
|
|
@@ -399,9 +477,11 @@ interface ProviderRuntimeMetadata {
|
|
|
399
477
|
effort?: string;
|
|
400
478
|
}
|
|
401
479
|
interface AgentProvider {
|
|
480
|
+
/** Exact public, versioned adapter contract. Optional only for legacy in-process test doubles. */
|
|
481
|
+
readonly manifest?: Readonly<AdapterManifestV1>;
|
|
402
482
|
readonly id: ProviderId;
|
|
403
483
|
readonly displayName: string;
|
|
404
|
-
readonly resumeIdentity: "optional" | "required";
|
|
484
|
+
readonly resumeIdentity: "optional" | "required" | "unsupported";
|
|
405
485
|
probe(): Promise<ProviderAvailability>;
|
|
406
486
|
buildProcess(context: ProviderProcessContext): Promise<ProcessSpec>;
|
|
407
487
|
/** Stateful parsers must be created per spawned process; providers are registry singletons. */
|
|
@@ -413,12 +493,19 @@ interface AgentProvider {
|
|
|
413
493
|
runtimeMetadata?(pane: string): ProviderRuntimeMetadata | undefined;
|
|
414
494
|
cleanup(paths: readonly string[]): void;
|
|
415
495
|
}
|
|
496
|
+
/** Installable and built-in adapters must implement this strict public shape. */
|
|
497
|
+
interface ProviderAdapterV1 extends AgentProvider {
|
|
498
|
+
readonly manifest: Readonly<AdapterManifestV1>;
|
|
499
|
+
}
|
|
416
500
|
|
|
417
501
|
interface SessionDefaults {
|
|
502
|
+
/** The provider used by the most recently created session. Absent only for legacy saved documents. */
|
|
503
|
+
provider?: ProviderId;
|
|
418
504
|
effort: string;
|
|
419
505
|
model?: string;
|
|
420
506
|
dangerouslySkip: boolean;
|
|
421
507
|
permissionMode?: string;
|
|
508
|
+
addDirs?: string[];
|
|
422
509
|
codex?: {
|
|
423
510
|
model?: string;
|
|
424
511
|
reasoningEffort?: string;
|
|
@@ -477,6 +564,7 @@ interface StoredSessionBase {
|
|
|
477
564
|
}
|
|
478
565
|
interface StoredClaudeSession extends StoredSessionBase {
|
|
479
566
|
provider: "claude";
|
|
567
|
+
externalAdapter?: never;
|
|
480
568
|
dangerouslySkip: boolean;
|
|
481
569
|
/** The USER-chosen spawn flags the session was created with (`--model`/`--effort`/`--permission-mode`/
|
|
482
570
|
* `--dangerously-skip-permissions`/`--add-dir …`) — everything EXCEPT the ephemeral per-session
|
|
@@ -494,13 +582,24 @@ interface StoredIntegrationStatus {
|
|
|
494
582
|
}
|
|
495
583
|
interface StoredCodexSession extends StoredSessionBase {
|
|
496
584
|
provider: "codex";
|
|
585
|
+
externalAdapter?: never;
|
|
497
586
|
launchOptions: CodexSessionOptions;
|
|
498
587
|
providerSessionId?: string;
|
|
499
588
|
integrationStatus?: StoredIntegrationStatus;
|
|
500
589
|
dangerouslySkip?: never;
|
|
501
590
|
spawnArgs?: never;
|
|
502
591
|
}
|
|
503
|
-
|
|
592
|
+
interface StoredExternalSession extends StoredSessionBase {
|
|
593
|
+
provider: ProviderId;
|
|
594
|
+
/** Discriminator that keeps additive third-party rows separate from rollback-readable built-in tables. */
|
|
595
|
+
externalAdapter: true;
|
|
596
|
+
launchOptions: ProviderSessionOptions;
|
|
597
|
+
providerSessionId?: string;
|
|
598
|
+
integrationStatus?: StoredIntegrationStatus;
|
|
599
|
+
dangerouslySkip?: never;
|
|
600
|
+
spawnArgs?: never;
|
|
601
|
+
}
|
|
602
|
+
type StoredSession = StoredClaudeSession | StoredCodexSession | StoredExternalSession;
|
|
504
603
|
/** How a store is actually backed: "sqlite" (durable) or "memory-fallback" (the native module failed to
|
|
505
604
|
* load — NOT durable across restarts). Surfaced so start.ts can warn loudly + /diag can report it. */
|
|
506
605
|
type StoreMode = "sqlite" | "memory-fallback";
|
|
@@ -526,6 +625,8 @@ interface SessionStore {
|
|
|
526
625
|
commitProvisionalProviderSessionId(id: string, value: string): void;
|
|
527
626
|
getSessionDefaults(): StoredSessionDefaults | undefined;
|
|
528
627
|
putSessionDefaults(defaults: SessionDefaults, expectedRevision: number, updatedAt: number): StoredSessionDefaults;
|
|
628
|
+
/** Server-owned last-launch write. Replaces the remembered choices and advances the revision atomically. */
|
|
629
|
+
rememberSessionDefaults(defaults: SessionDefaults, updatedAt: number): StoredSessionDefaults;
|
|
529
630
|
putFile(file: StoredSessionFile): void;
|
|
530
631
|
getFile(sessionId: string, id: string): StoredSessionFile | undefined;
|
|
531
632
|
listFiles(sessionId: string, includeHidden?: boolean): StoredSessionFile[];
|
|
@@ -589,6 +690,1514 @@ declare function resolveAccessToken(opts: ResolveAccessTokenOptions): {
|
|
|
589
690
|
generated: boolean;
|
|
590
691
|
};
|
|
591
692
|
|
|
693
|
+
/** A pairing link is deliberately short-lived and can be claimed exactly once. */
|
|
694
|
+
declare const PAIRING_TTL_MS: number;
|
|
695
|
+
type DeviceScope = "direct" | "relay";
|
|
696
|
+
interface DeviceInfo {
|
|
697
|
+
id: string;
|
|
698
|
+
name: string;
|
|
699
|
+
createdAt: number;
|
|
700
|
+
lastSeenAt: number;
|
|
701
|
+
scopes: DeviceScope[];
|
|
702
|
+
/** Pinned E2E relay signing identity. Public material only; the private key never leaves the device. */
|
|
703
|
+
relayIdentityFingerprint?: string;
|
|
704
|
+
}
|
|
705
|
+
interface DeviceRelayIdentity {
|
|
706
|
+
publicKey: string;
|
|
707
|
+
fingerprint: string;
|
|
708
|
+
}
|
|
709
|
+
declare class DevicePairingError extends Error {
|
|
710
|
+
readonly code: "INVALID_RELAY_IDENTITY";
|
|
711
|
+
constructor(code: "INVALID_RELAY_IDENTITY", message: string);
|
|
712
|
+
}
|
|
713
|
+
interface PairingTicket {
|
|
714
|
+
/** One-time capability carried by the pairing URL. Never persisted in plaintext. */
|
|
715
|
+
secret: string;
|
|
716
|
+
expiresAt: number;
|
|
717
|
+
/** Exact product surfaces the resulting device credential can reach. */
|
|
718
|
+
scopes: DeviceScope[];
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Relay bootstrap pre-allocates both durable ids. The token is still inert until the one-use pairing
|
|
722
|
+
* capability is claimed, but carrying it in the URL fragment makes a dropped final response recoverable:
|
|
723
|
+
* the browser can reconnect with the same credential after the host committed the claim.
|
|
724
|
+
*/
|
|
725
|
+
interface RelayPairingTicket extends PairingTicket {
|
|
726
|
+
deviceId: string;
|
|
727
|
+
token: string;
|
|
728
|
+
}
|
|
729
|
+
interface DeviceEnrollment {
|
|
730
|
+
/** The per-device bearer credential. Returned once; only its SHA-256 digest is persisted. */
|
|
731
|
+
token: string;
|
|
732
|
+
device: DeviceInfo;
|
|
733
|
+
}
|
|
734
|
+
interface DeviceStore {
|
|
735
|
+
readonly mode: "sqlite" | "memory-fallback";
|
|
736
|
+
issuePairing(now?: number, scopes?: DeviceScope[]): PairingTicket;
|
|
737
|
+
claimPairing(secret: string, name: string, now?: number, relayIdentityPublicKey?: string): DeviceEnrollment | undefined;
|
|
738
|
+
issueRelayPairing(now?: number): RelayPairingTicket;
|
|
739
|
+
pendingRelayPairing(deviceId: string, now?: number): boolean;
|
|
740
|
+
claimRelayPairing(secret: string, token: string, name: string, relayIdentityPublicKey: string, now?: number): DeviceEnrollment | undefined;
|
|
741
|
+
/** Resolve a per-device bearer credential and best-effort touch its last-seen time. */
|
|
742
|
+
authenticate(token: string, now?: number, requiredScope?: DeviceScope): DeviceInfo | undefined;
|
|
743
|
+
relayIdentity(id: string): DeviceRelayIdentity | undefined;
|
|
744
|
+
list(): DeviceInfo[];
|
|
745
|
+
rename(id: string, name: string): DeviceInfo | undefined;
|
|
746
|
+
revoke(id: string): boolean;
|
|
747
|
+
revokeAll(): number;
|
|
748
|
+
close(): void;
|
|
749
|
+
}
|
|
750
|
+
interface OpenDeviceStoreOptions {
|
|
751
|
+
/** SQLite file path. ":memory:" uses an in-process DB. */
|
|
752
|
+
dbPath: string;
|
|
753
|
+
generateSecret?: () => string;
|
|
754
|
+
generateToken?: () => string;
|
|
755
|
+
generateId?: () => string;
|
|
756
|
+
}
|
|
757
|
+
declare function normalizeDeviceScopes(value: unknown): DeviceScope[] | undefined;
|
|
758
|
+
/** Keep device labels useful in UI while refusing control characters and unbounded payloads. */
|
|
759
|
+
declare function normalizeDeviceName(value: unknown): string | undefined;
|
|
760
|
+
declare function openDeviceStore(opts: OpenDeviceStoreOptions): DeviceStore;
|
|
761
|
+
|
|
762
|
+
declare const INPUT_LEASE_TTL_MS = 30000;
|
|
763
|
+
type InputLeaseActorType = "device" | "host" | "local" | "relay";
|
|
764
|
+
interface InputLeasePrincipal {
|
|
765
|
+
actorType: InputLeaseActorType;
|
|
766
|
+
actorId: string;
|
|
767
|
+
label: string;
|
|
768
|
+
}
|
|
769
|
+
interface InputLease {
|
|
770
|
+
id: string;
|
|
771
|
+
sessionId: string;
|
|
772
|
+
holderId: string;
|
|
773
|
+
actorType: InputLeaseActorType;
|
|
774
|
+
actorId: string;
|
|
775
|
+
label: string;
|
|
776
|
+
acquiredAt: number;
|
|
777
|
+
renewedAt: number;
|
|
778
|
+
expiresAt: number;
|
|
779
|
+
revision: number;
|
|
780
|
+
}
|
|
781
|
+
type InputLeaseEvent = {
|
|
782
|
+
type: "granted";
|
|
783
|
+
lease: InputLease;
|
|
784
|
+
} | {
|
|
785
|
+
type: "renewed";
|
|
786
|
+
lease: InputLease;
|
|
787
|
+
} | {
|
|
788
|
+
type: "released" | "expired" | "revoked";
|
|
789
|
+
lease: InputLease;
|
|
790
|
+
} | {
|
|
791
|
+
type: "taken-over";
|
|
792
|
+
lease: InputLease;
|
|
793
|
+
previous: InputLease;
|
|
794
|
+
};
|
|
795
|
+
type InputLeaseAcquireResult = {
|
|
796
|
+
status: "granted" | "owned";
|
|
797
|
+
lease: InputLease;
|
|
798
|
+
} | {
|
|
799
|
+
status: "denied";
|
|
800
|
+
current: InputLease;
|
|
801
|
+
};
|
|
802
|
+
interface InputLeaseCoordinatorOptions {
|
|
803
|
+
ttlMs?: number;
|
|
804
|
+
now?: () => number;
|
|
805
|
+
generateId?: () => string;
|
|
806
|
+
scheduleExpiry?: boolean;
|
|
807
|
+
onEvent?: (event: InputLeaseEvent) => void;
|
|
808
|
+
}
|
|
809
|
+
/**
|
|
810
|
+
* Coordinates the one mutable terminal input stream shared by many read-only observers.
|
|
811
|
+
*
|
|
812
|
+
* Leases intentionally live in memory: a host restart invalidates every connection and therefore every holder.
|
|
813
|
+
* Durable audit is supplied by the caller through onEvent. Expiry, release, and confirmed takeover are explicit;
|
|
814
|
+
* merely sending input can never acquire or steal ownership.
|
|
815
|
+
*/
|
|
816
|
+
declare class InputLeaseCoordinator {
|
|
817
|
+
private readonly leases;
|
|
818
|
+
private readonly listeners;
|
|
819
|
+
private readonly timers;
|
|
820
|
+
private readonly ttlMs;
|
|
821
|
+
private readonly now;
|
|
822
|
+
private readonly generateId;
|
|
823
|
+
private readonly scheduleExpiry;
|
|
824
|
+
private readonly onEvent?;
|
|
825
|
+
private revision;
|
|
826
|
+
constructor(options?: InputLeaseCoordinatorOptions);
|
|
827
|
+
acquire(sessionId: string, holderId: string, principal: InputLeasePrincipal): InputLeaseAcquireResult;
|
|
828
|
+
takeover(sessionId: string, holderId: string, principal: InputLeasePrincipal, confirmed: boolean, authorized?: boolean): InputLeaseAcquireResult;
|
|
829
|
+
renew(sessionId: string, holderId: string, leaseId: string): InputLease | undefined;
|
|
830
|
+
canWrite(sessionId: string, holderId: string, leaseId?: string): boolean;
|
|
831
|
+
release(sessionId: string, holderId: string, leaseId?: string): boolean;
|
|
832
|
+
releaseHolder(holderId: string): number;
|
|
833
|
+
revoke(sessionId: string): boolean;
|
|
834
|
+
revokeActor(actorType: InputLeaseActorType, actorId: string): number;
|
|
835
|
+
get(sessionId: string): InputLease | undefined;
|
|
836
|
+
subscribe(sessionId: string, listener: (event: InputLeaseEvent) => void): () => void;
|
|
837
|
+
close(): void;
|
|
838
|
+
private validate;
|
|
839
|
+
private current;
|
|
840
|
+
private renewExisting;
|
|
841
|
+
private remove;
|
|
842
|
+
private schedule;
|
|
843
|
+
private emit;
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
type TeamStoreMode = "sqlite" | "memory-fallback";
|
|
847
|
+
type TeamMemberKind = "person" | "service";
|
|
848
|
+
type TeamMemberStatus = "active" | "suspended" | "removed";
|
|
849
|
+
type TeamRole = "viewer" | "operator" | "workspace-manager" | "extension-manager" | "policy-admin" | "organization-admin";
|
|
850
|
+
type TeamScopeType = "team" | "host" | "workspace";
|
|
851
|
+
type TeamPrincipalType = "device" | "host" | "local" | "relay";
|
|
852
|
+
type TeamPermission = "team:read" | "sessions:read" | "sessions:operate" | "attention:read" | "attention:manage" | "presence:read" | "presence:write" | "workspaces:manage" | "extensions:manage" | "policy:manage" | "members:manage" | "audit:read" | "fleet:read";
|
|
853
|
+
interface TeamRecord {
|
|
854
|
+
id: string;
|
|
855
|
+
name: string;
|
|
856
|
+
authorizationEnabled: boolean;
|
|
857
|
+
revision: number;
|
|
858
|
+
createdAt: number;
|
|
859
|
+
updatedAt: number;
|
|
860
|
+
}
|
|
861
|
+
interface TeamMember {
|
|
862
|
+
id: string;
|
|
863
|
+
displayName: string;
|
|
864
|
+
kind: TeamMemberKind;
|
|
865
|
+
status: TeamMemberStatus;
|
|
866
|
+
revision: number;
|
|
867
|
+
createdAt: number;
|
|
868
|
+
updatedAt: number;
|
|
869
|
+
}
|
|
870
|
+
interface TeamRoleBinding {
|
|
871
|
+
id: string;
|
|
872
|
+
memberId: string;
|
|
873
|
+
role: TeamRole;
|
|
874
|
+
scopeType: TeamScopeType;
|
|
875
|
+
scopeId?: string;
|
|
876
|
+
createdAt: number;
|
|
877
|
+
}
|
|
878
|
+
interface TeamPrincipalBinding {
|
|
879
|
+
actorType: TeamPrincipalType;
|
|
880
|
+
actorId: string;
|
|
881
|
+
memberId: string;
|
|
882
|
+
createdAt: number;
|
|
883
|
+
}
|
|
884
|
+
interface TeamAuthorizationResource {
|
|
885
|
+
hostId?: string;
|
|
886
|
+
workspaceId?: string;
|
|
887
|
+
}
|
|
888
|
+
interface TeamAuthorizationDecision {
|
|
889
|
+
allowed: boolean;
|
|
890
|
+
reason: "local-break-glass" | "not-enforced" | "unbound" | "inactive" | "role" | "missing-permission";
|
|
891
|
+
member?: TeamMember;
|
|
892
|
+
roles: TeamRole[];
|
|
893
|
+
}
|
|
894
|
+
interface TeamStore {
|
|
895
|
+
readonly mode: TeamStoreMode;
|
|
896
|
+
getTeam(): TeamRecord | null;
|
|
897
|
+
createTeam(input: {
|
|
898
|
+
name: string;
|
|
899
|
+
ownerName: string;
|
|
900
|
+
ownerPrincipal: {
|
|
901
|
+
actorType: TeamPrincipalType;
|
|
902
|
+
actorId: string;
|
|
903
|
+
};
|
|
904
|
+
}, now?: number): {
|
|
905
|
+
team: TeamRecord;
|
|
906
|
+
owner: TeamMember;
|
|
907
|
+
};
|
|
908
|
+
updateTeam(input: {
|
|
909
|
+
name?: string;
|
|
910
|
+
authorizationEnabled?: boolean;
|
|
911
|
+
}, expectedRevision: number, now?: number): TeamRecord;
|
|
912
|
+
listMembers(opts?: {
|
|
913
|
+
includeRemoved?: boolean;
|
|
914
|
+
}): TeamMember[];
|
|
915
|
+
getMember(id: string): TeamMember | undefined;
|
|
916
|
+
createMember(input: {
|
|
917
|
+
displayName: string;
|
|
918
|
+
kind?: TeamMemberKind;
|
|
919
|
+
}, now?: number): TeamMember;
|
|
920
|
+
updateMember(id: string, input: {
|
|
921
|
+
displayName?: string;
|
|
922
|
+
status?: TeamMemberStatus;
|
|
923
|
+
}, expectedRevision: number, now?: number): TeamMember | undefined;
|
|
924
|
+
listRoleBindings(memberId?: string): TeamRoleBinding[];
|
|
925
|
+
grantRole(input: {
|
|
926
|
+
memberId: string;
|
|
927
|
+
role: TeamRole;
|
|
928
|
+
scopeType?: TeamScopeType;
|
|
929
|
+
scopeId?: string;
|
|
930
|
+
}, now?: number): TeamRoleBinding;
|
|
931
|
+
revokeRole(id: string, now?: number): boolean;
|
|
932
|
+
listPrincipalBindings(memberId?: string): TeamPrincipalBinding[];
|
|
933
|
+
bindPrincipal(input: {
|
|
934
|
+
memberId: string;
|
|
935
|
+
actorType: TeamPrincipalType;
|
|
936
|
+
actorId: string;
|
|
937
|
+
}, now?: number): TeamPrincipalBinding;
|
|
938
|
+
unbindPrincipal(actorType: TeamPrincipalType, actorId: string, now?: number): boolean;
|
|
939
|
+
memberForPrincipal(actorType: TeamPrincipalType, actorId: string): TeamMember | undefined;
|
|
940
|
+
authorize(actorType: TeamPrincipalType, actorId: string, permission: TeamPermission, resource?: TeamAuthorizationResource): TeamAuthorizationDecision;
|
|
941
|
+
close(): void;
|
|
942
|
+
}
|
|
943
|
+
interface OpenTeamStoreOptions {
|
|
944
|
+
dbPath: string;
|
|
945
|
+
generateTeamId?: () => string;
|
|
946
|
+
generateMemberId?: () => string;
|
|
947
|
+
generateRoleId?: () => string;
|
|
948
|
+
loadDatabase?: () => typeof better_sqlite3;
|
|
949
|
+
}
|
|
950
|
+
declare class TeamRevisionConflictError extends Error {
|
|
951
|
+
readonly current: TeamRecord | TeamMember;
|
|
952
|
+
constructor(current: TeamRecord | TeamMember);
|
|
953
|
+
}
|
|
954
|
+
declare function openTeamStore(opts: OpenTeamStoreOptions): TeamStore;
|
|
955
|
+
declare function teamRolePermissions(role: TeamRole): readonly TeamPermission[];
|
|
956
|
+
declare function isTeamRole(value: unknown): value is TeamRole;
|
|
957
|
+
declare function isTeamScopeType(value: unknown): value is TeamScopeType;
|
|
958
|
+
|
|
959
|
+
declare const PRESENCE_TTL_MS = 45000;
|
|
960
|
+
declare const PRESENCE_HEARTBEAT_MS = 15000;
|
|
961
|
+
type PresenceMode = "viewing" | "operating";
|
|
962
|
+
interface PresenceTarget {
|
|
963
|
+
hostId: string;
|
|
964
|
+
workspaceId?: string;
|
|
965
|
+
sessionId?: string;
|
|
966
|
+
agentId?: string;
|
|
967
|
+
}
|
|
968
|
+
interface PresenceRecord extends PresenceTarget {
|
|
969
|
+
id: string;
|
|
970
|
+
memberId?: string;
|
|
971
|
+
label: string;
|
|
972
|
+
mode: PresenceMode;
|
|
973
|
+
connectedAt: number;
|
|
974
|
+
lastSeenAt: number;
|
|
975
|
+
expiresAt: number;
|
|
976
|
+
revision: number;
|
|
977
|
+
}
|
|
978
|
+
type PresenceEvent = {
|
|
979
|
+
type: "joined" | "updated" | "left" | "expired";
|
|
980
|
+
presence: PresenceRecord;
|
|
981
|
+
};
|
|
982
|
+
interface PresenceHeartbeatInput extends PresenceTarget {
|
|
983
|
+
clientId: string;
|
|
984
|
+
mode: PresenceMode;
|
|
985
|
+
memberId?: string;
|
|
986
|
+
}
|
|
987
|
+
interface PresenceCoordinatorOptions {
|
|
988
|
+
ttlMs?: number;
|
|
989
|
+
now?: () => number;
|
|
990
|
+
generateId?: () => string;
|
|
991
|
+
maxRecords?: number;
|
|
992
|
+
maxPerActor?: number;
|
|
993
|
+
scheduleExpiry?: boolean;
|
|
994
|
+
}
|
|
995
|
+
/**
|
|
996
|
+
* Ephemeral, privacy-bounded presence. No IP, bearer credential, path, prompt, or terminal data is retained.
|
|
997
|
+
* Heartbeats expire cleanly after disconnect and are capped both globally and per authenticated actor.
|
|
998
|
+
*/
|
|
999
|
+
declare class PresenceCoordinator {
|
|
1000
|
+
private readonly records;
|
|
1001
|
+
private readonly listeners;
|
|
1002
|
+
private readonly ttlMs;
|
|
1003
|
+
private readonly now;
|
|
1004
|
+
private readonly generateId;
|
|
1005
|
+
private readonly maxRecords;
|
|
1006
|
+
private readonly maxPerActor;
|
|
1007
|
+
private readonly timer?;
|
|
1008
|
+
private revision;
|
|
1009
|
+
constructor(options?: PresenceCoordinatorOptions);
|
|
1010
|
+
heartbeat(principal: InputLeasePrincipal, input: PresenceHeartbeatInput): PresenceRecord;
|
|
1011
|
+
list(filter?: Partial<PresenceTarget>): PresenceRecord[];
|
|
1012
|
+
release(principal: Pick<InputLeasePrincipal, "actorType" | "actorId">, clientId: string): boolean;
|
|
1013
|
+
releaseActor(principal: Pick<InputLeasePrincipal, "actorType" | "actorId">): number;
|
|
1014
|
+
/**
|
|
1015
|
+
* Input ownership is authoritative for the public "operating" label. When a lease ends or moves, keep the
|
|
1016
|
+
* connected observer visible but immediately downgrade stale operating heartbeats instead of waiting for TTL.
|
|
1017
|
+
*/
|
|
1018
|
+
downgradeOperating(principal: Pick<InputLeasePrincipal, "actorType" | "actorId">, sessionId: string): number;
|
|
1019
|
+
subscribe(listener: (event: PresenceEvent) => void): () => void;
|
|
1020
|
+
sweep(): number;
|
|
1021
|
+
close(): void;
|
|
1022
|
+
private enforceBounds;
|
|
1023
|
+
private evict;
|
|
1024
|
+
private publicRecord;
|
|
1025
|
+
private emit;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
declare const RELAY_PROTOCOL_VERSION: 1;
|
|
1029
|
+
declare const RELAY_HANDSHAKE_MAX_SKEW_MS: number;
|
|
1030
|
+
declare const RELAY_CHANNEL_MAX_AGE_MS: number;
|
|
1031
|
+
declare const RELAY_CHANNEL_MAX_FRAMES = 1000000;
|
|
1032
|
+
declare const RELAY_MAX_PLAINTEXT_BYTES: number;
|
|
1033
|
+
type RelayRole = "device" | "host";
|
|
1034
|
+
type RelayDirection = "device-to-host" | "host-to-device";
|
|
1035
|
+
type RelayFrameKind = "auth" | "rpc-request" | "rpc-response" | "stream-open" | "stream-data" | "stream-control" | "close";
|
|
1036
|
+
type RelayCryptoErrorCode = "INVALID_RELAY_IDENTITY" | "INVALID_RELAY_HELLO" | "RELAY_IDENTITY_MISMATCH" | "RELAY_SIGNATURE_INVALID" | "RELAY_HANDSHAKE_EXPIRED" | "RELAY_HANDSHAKE_MISMATCH" | "RELAY_FRAME_INVALID" | "RELAY_FRAME_OUT_OF_ORDER" | "RELAY_FRAME_AUTH_FAILED" | "RELAY_FRAME_TOO_LARGE" | "RELAY_KEY_ROTATION_REQUIRED" | "RELAY_CHANNEL_CLOSED";
|
|
1037
|
+
declare class RelayCryptoError extends Error {
|
|
1038
|
+
readonly code: RelayCryptoErrorCode;
|
|
1039
|
+
constructor(code: RelayCryptoErrorCode, message: string);
|
|
1040
|
+
}
|
|
1041
|
+
interface RelayIdentity {
|
|
1042
|
+
/** Base64url-encoded SPKI DER public key. Safe to pin and exchange. */
|
|
1043
|
+
publicKey: string;
|
|
1044
|
+
/** Base64url-encoded PKCS#8 DER private key. Host persistence must use mode 0600. */
|
|
1045
|
+
privateKey: string;
|
|
1046
|
+
fingerprint: string;
|
|
1047
|
+
}
|
|
1048
|
+
interface RelayEphemeralKeyPair {
|
|
1049
|
+
publicKey: string;
|
|
1050
|
+
privateKey: string;
|
|
1051
|
+
}
|
|
1052
|
+
interface RelayHandshakeHello {
|
|
1053
|
+
v: typeof RELAY_PROTOCOL_VERSION;
|
|
1054
|
+
role: RelayRole;
|
|
1055
|
+
routeId: string;
|
|
1056
|
+
deviceId: string;
|
|
1057
|
+
sessionId: string;
|
|
1058
|
+
issuedAt: number;
|
|
1059
|
+
nonce: string;
|
|
1060
|
+
ephemeralPublicKey: string;
|
|
1061
|
+
identityFingerprint: string;
|
|
1062
|
+
signature: string;
|
|
1063
|
+
}
|
|
1064
|
+
interface RelayEncryptedFrame {
|
|
1065
|
+
v: typeof RELAY_PROTOCOL_VERSION;
|
|
1066
|
+
sessionId: string;
|
|
1067
|
+
seq: string;
|
|
1068
|
+
kind: RelayFrameKind;
|
|
1069
|
+
ciphertext: string;
|
|
1070
|
+
}
|
|
1071
|
+
interface RelayChannelOptions {
|
|
1072
|
+
role: RelayRole;
|
|
1073
|
+
localEphemeral: RelayEphemeralKeyPair;
|
|
1074
|
+
deviceHello: RelayHandshakeHello;
|
|
1075
|
+
hostHello: RelayHandshakeHello;
|
|
1076
|
+
deviceIdentityPublicKey: string;
|
|
1077
|
+
hostIdentityPublicKey: string;
|
|
1078
|
+
now?: () => number;
|
|
1079
|
+
maxAgeMs?: number;
|
|
1080
|
+
maxFrames?: number;
|
|
1081
|
+
}
|
|
1082
|
+
declare function relayIdentityFingerprint(publicKey: string): string;
|
|
1083
|
+
declare function generateRelayIdentity(): RelayIdentity;
|
|
1084
|
+
/** Validates both key encodings and proves that the persisted private key belongs to the advertised identity. */
|
|
1085
|
+
declare function validateRelayIdentity(value: unknown): RelayIdentity;
|
|
1086
|
+
declare function generateRelayEphemeralKeyPair(): RelayEphemeralKeyPair;
|
|
1087
|
+
declare function createRelayHandshakeHello(input: {
|
|
1088
|
+
role: RelayRole;
|
|
1089
|
+
routeId: string;
|
|
1090
|
+
deviceId: string;
|
|
1091
|
+
sessionId?: string;
|
|
1092
|
+
identity: RelayIdentity;
|
|
1093
|
+
ephemeral?: RelayEphemeralKeyPair;
|
|
1094
|
+
nonce?: Uint8Array;
|
|
1095
|
+
issuedAt?: number;
|
|
1096
|
+
}): {
|
|
1097
|
+
hello: RelayHandshakeHello;
|
|
1098
|
+
ephemeral: RelayEphemeralKeyPair;
|
|
1099
|
+
};
|
|
1100
|
+
declare function verifyRelayHandshakeHello(hello: RelayHandshakeHello, expected: {
|
|
1101
|
+
role: RelayRole;
|
|
1102
|
+
routeId: string;
|
|
1103
|
+
deviceId: string;
|
|
1104
|
+
sessionId: string;
|
|
1105
|
+
identityPublicKey: string;
|
|
1106
|
+
now?: number;
|
|
1107
|
+
maxSkewMs?: number;
|
|
1108
|
+
}): void;
|
|
1109
|
+
/** Small exported primitive used to pin RFC 5869 test vectors independently of the handshake. */
|
|
1110
|
+
declare function hkdfSha256(input: Uint8Array, salt: Uint8Array, info: Uint8Array, length: number): Buffer;
|
|
1111
|
+
declare class RelayCipherState {
|
|
1112
|
+
readonly sessionId: string;
|
|
1113
|
+
readonly role: RelayRole;
|
|
1114
|
+
private readonly sendKey;
|
|
1115
|
+
private readonly receiveKey;
|
|
1116
|
+
private readonly sendBaseNonce;
|
|
1117
|
+
private readonly receiveBaseNonce;
|
|
1118
|
+
private readonly now;
|
|
1119
|
+
private readonly maxAgeMs;
|
|
1120
|
+
private readonly maxFrames;
|
|
1121
|
+
private sendSequence;
|
|
1122
|
+
private receiveSequence;
|
|
1123
|
+
private closed;
|
|
1124
|
+
private readonly createdAt;
|
|
1125
|
+
private readonly sendDirection;
|
|
1126
|
+
private readonly receiveDirection;
|
|
1127
|
+
constructor(sessionId: string, role: RelayRole, sendKey: Buffer, receiveKey: Buffer, sendBaseNonce: Buffer, receiveBaseNonce: Buffer, now: () => number, maxAgeMs: number, maxFrames: number);
|
|
1128
|
+
encrypt(kind: RelayFrameKind, plaintext: Uint8Array): RelayEncryptedFrame;
|
|
1129
|
+
decrypt(frame: RelayEncryptedFrame): Buffer;
|
|
1130
|
+
needsRotation(): boolean;
|
|
1131
|
+
sequences(): {
|
|
1132
|
+
send: string;
|
|
1133
|
+
receive: string;
|
|
1134
|
+
};
|
|
1135
|
+
close(): void;
|
|
1136
|
+
private assertOpen;
|
|
1137
|
+
private assertKind;
|
|
1138
|
+
}
|
|
1139
|
+
declare function establishRelayChannel(options: RelayChannelOptions): RelayCipherState;
|
|
1140
|
+
|
|
1141
|
+
interface RelayIdentityStoreOptions {
|
|
1142
|
+
dataDir: string;
|
|
1143
|
+
generate?: () => RelayIdentity;
|
|
1144
|
+
now?: () => number;
|
|
1145
|
+
}
|
|
1146
|
+
interface DurableRelayIdentity {
|
|
1147
|
+
identity: RelayIdentity;
|
|
1148
|
+
createdAt: number;
|
|
1149
|
+
path: string;
|
|
1150
|
+
generated: boolean;
|
|
1151
|
+
}
|
|
1152
|
+
/** Loads one stable host identity or creates it once without allowing concurrent processes to overwrite it. */
|
|
1153
|
+
declare function loadOrCreateRelayIdentity(options: RelayIdentityStoreOptions): DurableRelayIdentity;
|
|
1154
|
+
|
|
1155
|
+
type RelayStoreMode = "sqlite" | "memory";
|
|
1156
|
+
interface RelayRouteRecord {
|
|
1157
|
+
id: string;
|
|
1158
|
+
label: string;
|
|
1159
|
+
hostCredentialHash: string;
|
|
1160
|
+
ownerAccountId?: string;
|
|
1161
|
+
createdAt: number;
|
|
1162
|
+
updatedAt: number;
|
|
1163
|
+
}
|
|
1164
|
+
interface RelayDeviceRouteRecord {
|
|
1165
|
+
routeId: string;
|
|
1166
|
+
deviceId: string;
|
|
1167
|
+
credentialHash: string;
|
|
1168
|
+
createdAt: number;
|
|
1169
|
+
updatedAt: number;
|
|
1170
|
+
/** Bootstrap credentials expire unless the host promotes the device after the E2E pairing claim. */
|
|
1171
|
+
expiresAt?: number;
|
|
1172
|
+
}
|
|
1173
|
+
interface PublicRelayRouteRecord {
|
|
1174
|
+
id: string;
|
|
1175
|
+
label: string;
|
|
1176
|
+
deviceCount: number;
|
|
1177
|
+
createdAt: number;
|
|
1178
|
+
updatedAt: number;
|
|
1179
|
+
}
|
|
1180
|
+
interface RelayRouteStore {
|
|
1181
|
+
readonly mode: RelayStoreMode;
|
|
1182
|
+
createRoute(input: {
|
|
1183
|
+
id?: string;
|
|
1184
|
+
label: string;
|
|
1185
|
+
hostCredentialHash: string;
|
|
1186
|
+
ownerAccountId?: string;
|
|
1187
|
+
}, now?: number): RelayRouteRecord;
|
|
1188
|
+
getRoute(id: string): RelayRouteRecord | undefined;
|
|
1189
|
+
listRoutes(now?: number): PublicRelayRouteRecord[];
|
|
1190
|
+
listRoutesByOwner(ownerAccountId: string, now?: number): PublicRelayRouteRecord[];
|
|
1191
|
+
countDevices(routeId: string, now?: number): number;
|
|
1192
|
+
rotateHostCredential(routeId: string, credentialHash: string, now?: number): boolean;
|
|
1193
|
+
deleteRoute(id: string): boolean;
|
|
1194
|
+
authenticateHost(routeId: string, credential: string): boolean;
|
|
1195
|
+
putDevice(input: {
|
|
1196
|
+
routeId: string;
|
|
1197
|
+
deviceId: string;
|
|
1198
|
+
credentialHash: string;
|
|
1199
|
+
expiresAt?: number;
|
|
1200
|
+
}, now?: number): RelayDeviceRouteRecord;
|
|
1201
|
+
getDevice(routeId: string, deviceId: string, now?: number): RelayDeviceRouteRecord | undefined;
|
|
1202
|
+
authenticateDevice(routeId: string, deviceId: string, credential: string, now?: number): boolean;
|
|
1203
|
+
revokeDevice(routeId: string, deviceId: string): boolean;
|
|
1204
|
+
close(): void;
|
|
1205
|
+
}
|
|
1206
|
+
interface OpenRelayRouteStoreOptions {
|
|
1207
|
+
dbPath: string;
|
|
1208
|
+
generateRouteId?: () => string;
|
|
1209
|
+
loadDatabase?: () => typeof better_sqlite3;
|
|
1210
|
+
}
|
|
1211
|
+
declare function relayCredentialHash(credential: string): string;
|
|
1212
|
+
declare function generateRelayCredential(prefix?: "rrh" | "rrd" | "rrp"): string;
|
|
1213
|
+
declare function openRelayRouteStore(options: OpenRelayRouteStoreOptions): RelayRouteStore;
|
|
1214
|
+
|
|
1215
|
+
type RelayAccountStoreMode = "sqlite" | "memory";
|
|
1216
|
+
type RelayAccountStatus = "active" | "suspended" | "deleted";
|
|
1217
|
+
type RelayAccountPlan = "free" | "team" | "enterprise";
|
|
1218
|
+
interface RelayAccountRecord {
|
|
1219
|
+
id: string;
|
|
1220
|
+
label: string;
|
|
1221
|
+
status: RelayAccountStatus;
|
|
1222
|
+
plan: RelayAccountPlan;
|
|
1223
|
+
maxRoutes: number;
|
|
1224
|
+
maxDevicesPerRoute: number;
|
|
1225
|
+
revision: number;
|
|
1226
|
+
createdAt: number;
|
|
1227
|
+
updatedAt: number;
|
|
1228
|
+
}
|
|
1229
|
+
interface CreateRelayAccountInput {
|
|
1230
|
+
label: string;
|
|
1231
|
+
credential: string;
|
|
1232
|
+
plan?: RelayAccountPlan;
|
|
1233
|
+
maxRoutes?: number;
|
|
1234
|
+
maxDevicesPerRoute?: number;
|
|
1235
|
+
}
|
|
1236
|
+
interface UpdateRelayAccountInput {
|
|
1237
|
+
label?: string;
|
|
1238
|
+
status?: RelayAccountStatus;
|
|
1239
|
+
plan?: RelayAccountPlan;
|
|
1240
|
+
maxRoutes?: number;
|
|
1241
|
+
maxDevicesPerRoute?: number;
|
|
1242
|
+
}
|
|
1243
|
+
interface RelayAccountStore {
|
|
1244
|
+
readonly mode: RelayAccountStoreMode;
|
|
1245
|
+
createAccount(input: CreateRelayAccountInput, now?: number): RelayAccountRecord;
|
|
1246
|
+
getAccount(id: string): RelayAccountRecord | undefined;
|
|
1247
|
+
listAccounts(options?: {
|
|
1248
|
+
includeDeleted?: boolean;
|
|
1249
|
+
}): RelayAccountRecord[];
|
|
1250
|
+
authenticate(credential: string): RelayAccountRecord | undefined;
|
|
1251
|
+
updateAccount(id: string, input: UpdateRelayAccountInput, expectedRevision: number, now?: number): RelayAccountRecord | undefined;
|
|
1252
|
+
rotateCredential(id: string, credential: string, expectedRevision: number, now?: number): RelayAccountRecord | undefined;
|
|
1253
|
+
close(): void;
|
|
1254
|
+
}
|
|
1255
|
+
interface OpenRelayAccountStoreOptions {
|
|
1256
|
+
dbPath: string;
|
|
1257
|
+
generateAccountId?: () => string;
|
|
1258
|
+
loadDatabase?: () => typeof better_sqlite3;
|
|
1259
|
+
}
|
|
1260
|
+
declare class RelayAccountRevisionConflictError extends Error {
|
|
1261
|
+
readonly current: RelayAccountRecord;
|
|
1262
|
+
constructor(current: RelayAccountRecord);
|
|
1263
|
+
}
|
|
1264
|
+
declare function relayAccountCredentialHash(credential: string): string;
|
|
1265
|
+
declare function relayAccountCredentialLookup(credential: string): string;
|
|
1266
|
+
declare function generateRelayAccountCredential(): string;
|
|
1267
|
+
declare function openRelayAccountStore(options: OpenRelayAccountStoreOptions): RelayAccountStore;
|
|
1268
|
+
|
|
1269
|
+
interface RelayDeviceProvisioner {
|
|
1270
|
+
putDevice(deviceId: string, credentialHash: string, expiresAt?: number): Promise<void>;
|
|
1271
|
+
revokeDevice(deviceId: string): Promise<void>;
|
|
1272
|
+
}
|
|
1273
|
+
interface RelayDeviceProvisionerOptions {
|
|
1274
|
+
relayUrl: string;
|
|
1275
|
+
routeId: string;
|
|
1276
|
+
hostCredential: string;
|
|
1277
|
+
request?: typeof globalThis.fetch;
|
|
1278
|
+
timeoutMs?: number;
|
|
1279
|
+
}
|
|
1280
|
+
/** Host-authenticated provisioning uses HTTPS; routing credentials never appear in URLs or logs. */
|
|
1281
|
+
declare function createRelayDeviceProvisioner(options: RelayDeviceProvisionerOptions): RelayDeviceProvisioner;
|
|
1282
|
+
|
|
1283
|
+
interface RelayPairingPackage {
|
|
1284
|
+
v: 1;
|
|
1285
|
+
label: string;
|
|
1286
|
+
relayUrl: string;
|
|
1287
|
+
routeId: string;
|
|
1288
|
+
deviceId: string;
|
|
1289
|
+
deviceCredential: string;
|
|
1290
|
+
deviceToken: string;
|
|
1291
|
+
pairingSecret: string;
|
|
1292
|
+
expiresAt: number;
|
|
1293
|
+
hostIdentityPublicKey: string;
|
|
1294
|
+
hostIdentityFingerprint: string;
|
|
1295
|
+
}
|
|
1296
|
+
interface RelayPairingBootstrap {
|
|
1297
|
+
appUrl: string;
|
|
1298
|
+
label: string;
|
|
1299
|
+
relayUrl: string;
|
|
1300
|
+
routeId: string;
|
|
1301
|
+
hostIdentityPublicKey: string;
|
|
1302
|
+
hostIdentityFingerprint: string;
|
|
1303
|
+
provisioner: RelayDeviceProvisioner;
|
|
1304
|
+
generateDeviceCredential?: () => string;
|
|
1305
|
+
}
|
|
1306
|
+
declare function normalizeRelayAppUrl(value: string): string;
|
|
1307
|
+
declare function buildRelayPairingUrl(appUrl: string, pairing: RelayPairingPackage): string;
|
|
1308
|
+
|
|
1309
|
+
declare const BLIND_RELAY_PROTOCOL_VERSION: 1;
|
|
1310
|
+
declare const BLIND_RELAY_DEFAULT_MAX_FRAME_BYTES = 1500000;
|
|
1311
|
+
declare const BLIND_RELAY_DEFAULT_MAX_QUEUE_BYTES = 4000000;
|
|
1312
|
+
declare const BLIND_RELAY_DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 64;
|
|
1313
|
+
declare const BLIND_RELAY_DEFAULT_MAX_BYTES_PER_MINUTE: number;
|
|
1314
|
+
declare const BLIND_RELAY_DEFAULT_MAX_MESSAGES_PER_MINUTE = 12000;
|
|
1315
|
+
interface CreateBlindRelayOptions {
|
|
1316
|
+
rootToken: string;
|
|
1317
|
+
/** Previous provisioning capabilities accepted only during an explicit, bounded zero-downtime rotation window. */
|
|
1318
|
+
previousRootTokens?: string[];
|
|
1319
|
+
store?: RelayRouteStore;
|
|
1320
|
+
/** Optional hosted control plane. Self-hosted root-only routing remains available without it. */
|
|
1321
|
+
accountStore?: RelayAccountStore;
|
|
1322
|
+
allowedOrigins?: string[];
|
|
1323
|
+
handshakeTimeoutMs?: number;
|
|
1324
|
+
idleTimeoutMs?: number;
|
|
1325
|
+
maxFrameBytes?: number;
|
|
1326
|
+
maxQueueBytes?: number;
|
|
1327
|
+
maxConnectionsPerRoute?: number;
|
|
1328
|
+
maxBytesPerMinute?: number;
|
|
1329
|
+
maxMessagesPerMinute?: number;
|
|
1330
|
+
now?: () => number;
|
|
1331
|
+
generateChannelId?: () => string;
|
|
1332
|
+
}
|
|
1333
|
+
interface BlindRelayMetrics {
|
|
1334
|
+
activeHosts: number;
|
|
1335
|
+
activeDevices: number;
|
|
1336
|
+
acceptedConnections: number;
|
|
1337
|
+
rejectedConnections: number;
|
|
1338
|
+
forwardedFrames: number;
|
|
1339
|
+
forwardedBytes: number;
|
|
1340
|
+
droppedFrames: number;
|
|
1341
|
+
}
|
|
1342
|
+
interface BlindRelayServer {
|
|
1343
|
+
app: FastifyInstance;
|
|
1344
|
+
store: RelayRouteStore;
|
|
1345
|
+
accountStore?: RelayAccountStore;
|
|
1346
|
+
metrics(): BlindRelayMetrics;
|
|
1347
|
+
}
|
|
1348
|
+
declare function createBlindRelayServer(options: CreateBlindRelayOptions): BlindRelayServer;
|
|
1349
|
+
|
|
1350
|
+
interface StartedBlindRelay extends BlindRelayServer {
|
|
1351
|
+
url: string;
|
|
1352
|
+
}
|
|
1353
|
+
declare function startBlindRelay(env?: NodeJS.ProcessEnv): Promise<StartedBlindRelay>;
|
|
1354
|
+
declare function isRelayDirectExecution(moduleUrl: string, argv1: string | undefined, embeddedContainerBuild?: boolean): boolean;
|
|
1355
|
+
|
|
1356
|
+
/** RPC uses JSON inside an encrypted frame inside a base64 relay envelope. Larger data uses chunked streams. */
|
|
1357
|
+
declare const RELAY_RPC_MAX_BODY_BYTES: number;
|
|
1358
|
+
declare const RELAY_RPC_MAX_PATH_BYTES = 4096;
|
|
1359
|
+
type RelayRpcMethod = "GET" | "HEAD" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
1360
|
+
interface RelayRpcRequest {
|
|
1361
|
+
id: string;
|
|
1362
|
+
method: RelayRpcMethod;
|
|
1363
|
+
path: string;
|
|
1364
|
+
headers: Record<string, string>;
|
|
1365
|
+
body?: Buffer;
|
|
1366
|
+
}
|
|
1367
|
+
interface RelayRpcResponse {
|
|
1368
|
+
id: string;
|
|
1369
|
+
status: number;
|
|
1370
|
+
headers: Record<string, string>;
|
|
1371
|
+
body?: string;
|
|
1372
|
+
}
|
|
1373
|
+
declare function parseRelayRpcRequest(value: unknown): RelayRpcRequest;
|
|
1374
|
+
declare function relayRpcResponse(input: {
|
|
1375
|
+
id: string;
|
|
1376
|
+
status: number;
|
|
1377
|
+
headers: Record<string, string | string[] | number | undefined>;
|
|
1378
|
+
body?: Uint8Array;
|
|
1379
|
+
}): RelayRpcResponse;
|
|
1380
|
+
|
|
1381
|
+
type RelayHostStatus = "idle" | "connecting" | "online" | "reconnecting" | "stopped";
|
|
1382
|
+
interface RelayHostMetrics {
|
|
1383
|
+
status: RelayHostStatus;
|
|
1384
|
+
activeChannels: number;
|
|
1385
|
+
acceptedChannels: number;
|
|
1386
|
+
rejectedChannels: number;
|
|
1387
|
+
completedRequests: number;
|
|
1388
|
+
failedRequests: number;
|
|
1389
|
+
reconnects: number;
|
|
1390
|
+
activeTransfers: number;
|
|
1391
|
+
completedTransfers: number;
|
|
1392
|
+
failedTransfers: number;
|
|
1393
|
+
streamedRequestBytes: number;
|
|
1394
|
+
streamedResponseBytes: number;
|
|
1395
|
+
}
|
|
1396
|
+
interface RelayHostConnectorOptions {
|
|
1397
|
+
relayUrl: string;
|
|
1398
|
+
routeId: string;
|
|
1399
|
+
hostCredential: string;
|
|
1400
|
+
hostIdentity: RelayIdentity;
|
|
1401
|
+
devices: DeviceStore;
|
|
1402
|
+
dispatchRequest(token: string, request: RelayRpcRequest): Promise<RelayRpcResponse>;
|
|
1403
|
+
openTerminal?: RelayTerminalOpener;
|
|
1404
|
+
openHttp?: RelayHttpOpener;
|
|
1405
|
+
WebSocketClass?: typeof WebSocket;
|
|
1406
|
+
now?: () => number;
|
|
1407
|
+
random?: () => number;
|
|
1408
|
+
handshakeTimeoutMs?: number;
|
|
1409
|
+
requestTimeoutMs?: number;
|
|
1410
|
+
maxStreamRequestBytes?: number;
|
|
1411
|
+
onStatus?: (status: RelayHostStatus) => void;
|
|
1412
|
+
/** Promotes a five-minute broker bootstrap credential after the E2E pairing claim commits. */
|
|
1413
|
+
promoteDevice?: (deviceId: string, credentialHash: string) => Promise<void>;
|
|
1414
|
+
}
|
|
1415
|
+
interface RelayTerminalOpenRequest {
|
|
1416
|
+
streamId: string;
|
|
1417
|
+
sessionId: string;
|
|
1418
|
+
cols?: number;
|
|
1419
|
+
rows?: number;
|
|
1420
|
+
respawn?: "continue" | "fresh";
|
|
1421
|
+
}
|
|
1422
|
+
interface RelayTerminalHandlers {
|
|
1423
|
+
onBinary(data: Uint8Array): void;
|
|
1424
|
+
onControl(data: string): void;
|
|
1425
|
+
onClose(code: number): void;
|
|
1426
|
+
}
|
|
1427
|
+
interface RelayTerminalBridge {
|
|
1428
|
+
send(data: string): void;
|
|
1429
|
+
close(): void;
|
|
1430
|
+
}
|
|
1431
|
+
type RelayTerminalOpener = (token: string, request: RelayTerminalOpenRequest, handlers: RelayTerminalHandlers) => Promise<RelayTerminalBridge>;
|
|
1432
|
+
interface RelayHttpOpenRequest {
|
|
1433
|
+
streamId: string;
|
|
1434
|
+
method: RelayRpcRequest["method"];
|
|
1435
|
+
path: string;
|
|
1436
|
+
headers: Record<string, string>;
|
|
1437
|
+
}
|
|
1438
|
+
interface RelayHttpResponseHead {
|
|
1439
|
+
status: number;
|
|
1440
|
+
headers: Record<string, string>;
|
|
1441
|
+
}
|
|
1442
|
+
interface RelayHttpHandlers {
|
|
1443
|
+
onResponse(response: RelayHttpResponseHead): void | Promise<void>;
|
|
1444
|
+
onData(data: Uint8Array): void | Promise<void>;
|
|
1445
|
+
onEnd(): void | Promise<void>;
|
|
1446
|
+
onError(error: Error): void;
|
|
1447
|
+
}
|
|
1448
|
+
interface RelayHttpBridge {
|
|
1449
|
+
write(data: Uint8Array): Promise<void>;
|
|
1450
|
+
end(): void;
|
|
1451
|
+
close(): void;
|
|
1452
|
+
}
|
|
1453
|
+
type RelayHttpOpener = (token: string, request: RelayHttpOpenRequest, handlers: RelayHttpHandlers) => Promise<RelayHttpBridge>;
|
|
1454
|
+
interface RelayHostConnector {
|
|
1455
|
+
start(): void;
|
|
1456
|
+
stop(): Promise<void>;
|
|
1457
|
+
waitUntilReady(timeoutMs?: number): Promise<void>;
|
|
1458
|
+
closeDevice(deviceId: string): void;
|
|
1459
|
+
metrics(): RelayHostMetrics;
|
|
1460
|
+
}
|
|
1461
|
+
declare function relayConnectUrl(raw: string): string;
|
|
1462
|
+
declare function createRelayHostConnector(options: RelayHostConnectorOptions): RelayHostConnector;
|
|
1463
|
+
|
|
1464
|
+
interface RelayHostRuntimeConfig {
|
|
1465
|
+
relayUrl: string;
|
|
1466
|
+
routeId: string;
|
|
1467
|
+
hostCredential: string;
|
|
1468
|
+
hostIdentity: RelayIdentity;
|
|
1469
|
+
/** Static PWA origin used only for one-use remote pairing links. */
|
|
1470
|
+
appUrl?: string;
|
|
1471
|
+
hostLabel: string;
|
|
1472
|
+
}
|
|
1473
|
+
interface PersistedRelayHostConfig {
|
|
1474
|
+
version: 1;
|
|
1475
|
+
relayUrl: string;
|
|
1476
|
+
routeId: string;
|
|
1477
|
+
hostCredential: string;
|
|
1478
|
+
appUrl?: string;
|
|
1479
|
+
hostLabel: string;
|
|
1480
|
+
}
|
|
1481
|
+
type RelayHostConfigInput = Omit<PersistedRelayHostConfig, "version">;
|
|
1482
|
+
declare function relayHostConfigPath(dataDir: string): string;
|
|
1483
|
+
declare function readRelayHostConfig(dataDir: string): PersistedRelayHostConfig | undefined;
|
|
1484
|
+
declare function writeRelayHostConfig(dataDir: string, input: RelayHostConfigInput): PersistedRelayHostConfig;
|
|
1485
|
+
declare function removeRelayHostConfig(dataDir: string): boolean;
|
|
1486
|
+
declare function resolveRelayHostConfig(env: NodeJS.ProcessEnv, dataDir: string): RelayHostRuntimeConfig | undefined;
|
|
1487
|
+
|
|
1488
|
+
interface LoopbackRelayTerminalOptions {
|
|
1489
|
+
baseUrl(): string | undefined;
|
|
1490
|
+
issueTicket(token: string): Promise<string>;
|
|
1491
|
+
WebSocketClass?: typeof WebSocket;
|
|
1492
|
+
openTimeoutMs?: number;
|
|
1493
|
+
}
|
|
1494
|
+
declare function createLoopbackRelayTerminalOpener(options: LoopbackRelayTerminalOptions): RelayTerminalOpener;
|
|
1495
|
+
|
|
1496
|
+
interface LoopbackRelayHttpOptions {
|
|
1497
|
+
baseUrl(): string | undefined;
|
|
1498
|
+
headers(token: string, requestHeaders: Record<string, string>): Record<string, string>;
|
|
1499
|
+
idleTimeoutMs?: number;
|
|
1500
|
+
}
|
|
1501
|
+
/**
|
|
1502
|
+
* Streams an authenticated relay request through the real loopback HTTP server. This deliberately traverses
|
|
1503
|
+
* the normal auth, RBAC, rate-limit, idempotency, audit, multipart, and route hooks instead of calling file
|
|
1504
|
+
* services out of band.
|
|
1505
|
+
*/
|
|
1506
|
+
declare function createLoopbackRelayHttpOpener(options: LoopbackRelayHttpOptions): RelayHttpOpener;
|
|
1507
|
+
|
|
1508
|
+
declare const RELAY_WIRE_PROTOCOL_VERSION: 1;
|
|
1509
|
+
declare const RELAY_WIRE_MAX_ENVELOPE_BYTES = 1400000;
|
|
1510
|
+
type RelayWireEnvelope = {
|
|
1511
|
+
v: 1;
|
|
1512
|
+
t: "device-hello";
|
|
1513
|
+
hello: RelayHandshakeHello;
|
|
1514
|
+
identityPublicKey?: string;
|
|
1515
|
+
} | {
|
|
1516
|
+
v: 1;
|
|
1517
|
+
t: "host-hello";
|
|
1518
|
+
hello: RelayHandshakeHello;
|
|
1519
|
+
} | {
|
|
1520
|
+
v: 1;
|
|
1521
|
+
t: "cipher";
|
|
1522
|
+
frame: RelayEncryptedFrame;
|
|
1523
|
+
};
|
|
1524
|
+
declare function encodeRelayWireEnvelope(envelope: RelayWireEnvelope): string;
|
|
1525
|
+
declare function decodeRelayWireEnvelope(payload: unknown): RelayWireEnvelope;
|
|
1526
|
+
|
|
1527
|
+
type PolicyStoreMode = "sqlite" | "memory-fallback";
|
|
1528
|
+
type ExtensionPolicyMode = "allow-integrity" | "signed-only" | "deny";
|
|
1529
|
+
type UpdatePolicyMode = "stable-only" | "deny";
|
|
1530
|
+
interface EnterprisePolicy {
|
|
1531
|
+
enforcementEnabled: boolean;
|
|
1532
|
+
allowedHostIds: string[] | null;
|
|
1533
|
+
allowedWorkspaceIds: string[] | null;
|
|
1534
|
+
allowedProviderIds: string[] | null;
|
|
1535
|
+
allowDangerousProviderModes: boolean;
|
|
1536
|
+
allowFileTransfer: boolean;
|
|
1537
|
+
extensionMode: ExtensionPolicyMode;
|
|
1538
|
+
allowRelay: boolean;
|
|
1539
|
+
updateMode: UpdatePolicyMode;
|
|
1540
|
+
revision: number;
|
|
1541
|
+
createdAt: number;
|
|
1542
|
+
updatedAt: number;
|
|
1543
|
+
}
|
|
1544
|
+
interface EnterprisePolicyUpdate {
|
|
1545
|
+
enforcementEnabled?: boolean;
|
|
1546
|
+
allowedHostIds?: string[] | null;
|
|
1547
|
+
allowedWorkspaceIds?: string[] | null;
|
|
1548
|
+
allowedProviderIds?: string[] | null;
|
|
1549
|
+
allowDangerousProviderModes?: boolean;
|
|
1550
|
+
allowFileTransfer?: boolean;
|
|
1551
|
+
extensionMode?: ExtensionPolicyMode;
|
|
1552
|
+
allowRelay?: boolean;
|
|
1553
|
+
updateMode?: UpdatePolicyMode;
|
|
1554
|
+
}
|
|
1555
|
+
type EnterprisePolicyAction = "access" | "session.launch" | "file.transfer" | "extension.mutate" | "relay.access" | "update.mutate";
|
|
1556
|
+
interface EnterprisePolicyContext {
|
|
1557
|
+
hostId: string;
|
|
1558
|
+
workspaceId?: string;
|
|
1559
|
+
providerId?: string;
|
|
1560
|
+
dangerousProviderMode?: boolean;
|
|
1561
|
+
extensionTrust?: "signed" | "integrity";
|
|
1562
|
+
updateChannel?: "stable" | "beta" | "nightly";
|
|
1563
|
+
}
|
|
1564
|
+
interface EnterprisePolicyDecision {
|
|
1565
|
+
allowed: boolean;
|
|
1566
|
+
reason: "not-enforced" | "allowed" | "host-denied" | "workspace-denied" | "provider-denied" | "dangerous-mode-denied" | "file-transfer-denied" | "extension-denied" | "extension-signature-required" | "relay-denied" | "updates-denied" | "update-channel-denied";
|
|
1567
|
+
}
|
|
1568
|
+
interface PolicyStore {
|
|
1569
|
+
readonly mode: PolicyStoreMode;
|
|
1570
|
+
get(): EnterprisePolicy;
|
|
1571
|
+
update(input: EnterprisePolicyUpdate, expectedRevision: number, now?: number): EnterprisePolicy;
|
|
1572
|
+
close(): void;
|
|
1573
|
+
}
|
|
1574
|
+
interface OpenPolicyStoreOptions {
|
|
1575
|
+
dbPath: string;
|
|
1576
|
+
loadDatabase?: () => typeof better_sqlite3;
|
|
1577
|
+
now?: number;
|
|
1578
|
+
}
|
|
1579
|
+
declare class EnterprisePolicyRevisionConflictError extends Error {
|
|
1580
|
+
readonly current: EnterprisePolicy;
|
|
1581
|
+
constructor(current: EnterprisePolicy);
|
|
1582
|
+
}
|
|
1583
|
+
declare function evaluateEnterprisePolicy(policy: EnterprisePolicy, action: EnterprisePolicyAction, context: EnterprisePolicyContext): EnterprisePolicyDecision;
|
|
1584
|
+
declare function openPolicyStore(options: OpenPolicyStoreOptions): PolicyStore;
|
|
1585
|
+
|
|
1586
|
+
type PeerStoreMode = "sqlite" | "memory-fallback";
|
|
1587
|
+
type PeerAction = "read" | "send" | "wait" | "start" | "focus";
|
|
1588
|
+
type PeerStatus = "active" | "suspended";
|
|
1589
|
+
interface PeerRecord {
|
|
1590
|
+
id: string;
|
|
1591
|
+
label: string;
|
|
1592
|
+
remoteHostId: string;
|
|
1593
|
+
remoteVersion: string;
|
|
1594
|
+
actions: PeerAction[];
|
|
1595
|
+
allowedWorkspaceIds: string[] | null;
|
|
1596
|
+
status: PeerStatus;
|
|
1597
|
+
revision: number;
|
|
1598
|
+
createdAt: number;
|
|
1599
|
+
updatedAt: number;
|
|
1600
|
+
lastVerifiedAt: number;
|
|
1601
|
+
}
|
|
1602
|
+
interface PeerConnection extends PeerRecord {
|
|
1603
|
+
baseUrl: string;
|
|
1604
|
+
credential: string;
|
|
1605
|
+
}
|
|
1606
|
+
interface CreatePeerInput {
|
|
1607
|
+
label: string;
|
|
1608
|
+
baseUrl: string;
|
|
1609
|
+
credential: string;
|
|
1610
|
+
remoteHostId: string;
|
|
1611
|
+
remoteVersion: string;
|
|
1612
|
+
actions?: PeerAction[];
|
|
1613
|
+
allowedWorkspaceIds?: string[] | null;
|
|
1614
|
+
}
|
|
1615
|
+
interface UpdatePeerInput {
|
|
1616
|
+
label?: string;
|
|
1617
|
+
actions?: PeerAction[];
|
|
1618
|
+
allowedWorkspaceIds?: string[] | null;
|
|
1619
|
+
status?: PeerStatus;
|
|
1620
|
+
remoteVersion?: string;
|
|
1621
|
+
lastVerifiedAt?: number;
|
|
1622
|
+
}
|
|
1623
|
+
interface PeerStore {
|
|
1624
|
+
readonly mode: PeerStoreMode;
|
|
1625
|
+
list(): PeerRecord[];
|
|
1626
|
+
get(id: string): PeerRecord | undefined;
|
|
1627
|
+
connection(id: string): PeerConnection | undefined;
|
|
1628
|
+
create(input: CreatePeerInput, now?: number): PeerRecord;
|
|
1629
|
+
update(id: string, input: UpdatePeerInput, expectedRevision: number, now?: number): PeerRecord | undefined;
|
|
1630
|
+
rotateCredential(id: string, input: {
|
|
1631
|
+
credential: string;
|
|
1632
|
+
remoteVersion: string;
|
|
1633
|
+
lastVerifiedAt?: number;
|
|
1634
|
+
}, expectedRevision: number, now?: number): PeerRecord | undefined;
|
|
1635
|
+
remove(id: string): boolean;
|
|
1636
|
+
close(): void;
|
|
1637
|
+
}
|
|
1638
|
+
interface OpenPeerStoreOptions {
|
|
1639
|
+
dbPath: string;
|
|
1640
|
+
generatePeerId?: () => string;
|
|
1641
|
+
loadDatabase?: () => typeof better_sqlite3;
|
|
1642
|
+
}
|
|
1643
|
+
declare class PeerRevisionConflictError extends Error {
|
|
1644
|
+
readonly current: PeerRecord;
|
|
1645
|
+
constructor(current: PeerRecord);
|
|
1646
|
+
}
|
|
1647
|
+
declare function normalizePeerBaseUrl(value: unknown): string;
|
|
1648
|
+
declare function openPeerStore(options: OpenPeerStoreOptions): PeerStore;
|
|
1649
|
+
|
|
1650
|
+
interface VerifiedPeerIdentity {
|
|
1651
|
+
remoteHostId: string;
|
|
1652
|
+
remoteVersion: string;
|
|
1653
|
+
remoteLabel: string;
|
|
1654
|
+
protocolVersion: number;
|
|
1655
|
+
}
|
|
1656
|
+
interface PeerJsonResponse {
|
|
1657
|
+
status: number;
|
|
1658
|
+
body: unknown;
|
|
1659
|
+
}
|
|
1660
|
+
declare class PeerRequestError extends Error {
|
|
1661
|
+
readonly status?: number | undefined;
|
|
1662
|
+
readonly remoteCode?: string | undefined;
|
|
1663
|
+
constructor(message: string, status?: number | undefined, remoteCode?: string | undefined);
|
|
1664
|
+
}
|
|
1665
|
+
declare function requestPeerJson(connection: Pick<PeerConnection, "baseUrl" | "credential">, path: string, init?: {
|
|
1666
|
+
method?: "GET" | "POST";
|
|
1667
|
+
body?: unknown;
|
|
1668
|
+
idempotencyKey?: string;
|
|
1669
|
+
fetch?: typeof globalThis.fetch;
|
|
1670
|
+
timeoutMs?: number;
|
|
1671
|
+
}): Promise<PeerJsonResponse>;
|
|
1672
|
+
declare function verifyPeerConnection(input: {
|
|
1673
|
+
baseUrl: string;
|
|
1674
|
+
credential: string;
|
|
1675
|
+
localHostId: string;
|
|
1676
|
+
fetch?: typeof globalThis.fetch;
|
|
1677
|
+
}): Promise<VerifiedPeerIdentity>;
|
|
1678
|
+
|
|
1679
|
+
type CommandCenterStoreMode = "sqlite" | "memory-fallback";
|
|
1680
|
+
type WorkspaceKind = "directory" | "worktree";
|
|
1681
|
+
type AgentActivity = "blocked" | "working" | "done" | "idle" | "ended" | "unknown";
|
|
1682
|
+
type AttentionKind = "blocked" | "done" | "error" | "file" | "policy";
|
|
1683
|
+
type AttentionState = "open" | "acknowledged" | "snoozed" | "resolved";
|
|
1684
|
+
interface HostRecord {
|
|
1685
|
+
id: string;
|
|
1686
|
+
label: string;
|
|
1687
|
+
createdAt: number;
|
|
1688
|
+
updatedAt: number;
|
|
1689
|
+
}
|
|
1690
|
+
interface WorkspaceRecord {
|
|
1691
|
+
id: string;
|
|
1692
|
+
label: string;
|
|
1693
|
+
cwd: string;
|
|
1694
|
+
kind: WorkspaceKind;
|
|
1695
|
+
sortOrder: number;
|
|
1696
|
+
createdAt: number;
|
|
1697
|
+
updatedAt: number;
|
|
1698
|
+
archivedAt?: number;
|
|
1699
|
+
}
|
|
1700
|
+
interface SessionPlacement {
|
|
1701
|
+
sessionId: string;
|
|
1702
|
+
workspaceId: string;
|
|
1703
|
+
agentId: string;
|
|
1704
|
+
createdAt: number;
|
|
1705
|
+
}
|
|
1706
|
+
interface AgentRecord {
|
|
1707
|
+
id: string;
|
|
1708
|
+
sessionId: string;
|
|
1709
|
+
workspaceId: string;
|
|
1710
|
+
provider: string;
|
|
1711
|
+
activity: AgentActivity;
|
|
1712
|
+
createdAt: number;
|
|
1713
|
+
updatedAt: number;
|
|
1714
|
+
}
|
|
1715
|
+
interface AttentionItem {
|
|
1716
|
+
id: string;
|
|
1717
|
+
workspaceId: string;
|
|
1718
|
+
sessionId: string;
|
|
1719
|
+
agentId: string;
|
|
1720
|
+
kind: AttentionKind;
|
|
1721
|
+
state: AttentionState;
|
|
1722
|
+
title: string;
|
|
1723
|
+
detail?: string;
|
|
1724
|
+
urgency: number;
|
|
1725
|
+
occurrenceCount: number;
|
|
1726
|
+
createdAt: number;
|
|
1727
|
+
updatedAt: number;
|
|
1728
|
+
acknowledgedAt?: number;
|
|
1729
|
+
snoozedUntil?: number;
|
|
1730
|
+
resolvedAt?: number;
|
|
1731
|
+
}
|
|
1732
|
+
interface CommandEvent {
|
|
1733
|
+
id: number;
|
|
1734
|
+
type: string;
|
|
1735
|
+
resourceType: string;
|
|
1736
|
+
resourceId: string;
|
|
1737
|
+
payload: Record<string, unknown>;
|
|
1738
|
+
createdAt: number;
|
|
1739
|
+
}
|
|
1740
|
+
interface CommandLayoutEnvelope {
|
|
1741
|
+
document: Record<string, unknown> | null;
|
|
1742
|
+
revision: number;
|
|
1743
|
+
updatedAt?: number;
|
|
1744
|
+
}
|
|
1745
|
+
declare class CommandCenterRevisionConflictError extends Error {
|
|
1746
|
+
readonly current: CommandLayoutEnvelope;
|
|
1747
|
+
constructor(current: CommandLayoutEnvelope);
|
|
1748
|
+
}
|
|
1749
|
+
interface CreateWorkspaceInput {
|
|
1750
|
+
cwd: string;
|
|
1751
|
+
label?: string;
|
|
1752
|
+
kind?: WorkspaceKind;
|
|
1753
|
+
}
|
|
1754
|
+
interface UpdateWorkspaceInput {
|
|
1755
|
+
label?: string;
|
|
1756
|
+
sortOrder?: number;
|
|
1757
|
+
archived?: boolean;
|
|
1758
|
+
}
|
|
1759
|
+
interface UpsertAgentInput {
|
|
1760
|
+
sessionId: string;
|
|
1761
|
+
workspaceId: string;
|
|
1762
|
+
provider: string;
|
|
1763
|
+
activity: AgentActivity;
|
|
1764
|
+
createdAt: number;
|
|
1765
|
+
}
|
|
1766
|
+
interface RecordAttentionInput {
|
|
1767
|
+
workspaceId: string;
|
|
1768
|
+
sessionId: string;
|
|
1769
|
+
agentId: string;
|
|
1770
|
+
kind: AttentionKind;
|
|
1771
|
+
title: string;
|
|
1772
|
+
detail?: string;
|
|
1773
|
+
urgency?: number;
|
|
1774
|
+
/** Stable transition identity, e.g. `blocked:<sessionId>`. Only one unresolved item exists per key. */
|
|
1775
|
+
dedupeKey: string;
|
|
1776
|
+
}
|
|
1777
|
+
interface CommandCenterStore {
|
|
1778
|
+
readonly mode: CommandCenterStoreMode;
|
|
1779
|
+
getHost(): HostRecord;
|
|
1780
|
+
renameHost(label: string, now?: number): HostRecord;
|
|
1781
|
+
listWorkspaces(opts?: {
|
|
1782
|
+
includeArchived?: boolean;
|
|
1783
|
+
}): WorkspaceRecord[];
|
|
1784
|
+
getWorkspace(id: string): WorkspaceRecord | undefined;
|
|
1785
|
+
createWorkspace(input: CreateWorkspaceInput, now?: number): WorkspaceRecord;
|
|
1786
|
+
updateWorkspace(id: string, input: UpdateWorkspaceInput, now?: number): WorkspaceRecord | undefined;
|
|
1787
|
+
ensureSession(sessionId: string, cwd: string, now?: number): SessionPlacement;
|
|
1788
|
+
placementForSession(sessionId: string): SessionPlacement | undefined;
|
|
1789
|
+
removeSession(sessionId: string, now?: number): void;
|
|
1790
|
+
upsertAgent(input: UpsertAgentInput, now?: number): AgentRecord;
|
|
1791
|
+
getAgent(id: string): AgentRecord | undefined;
|
|
1792
|
+
listAgents(): AgentRecord[];
|
|
1793
|
+
recordAttention(input: RecordAttentionInput, now?: number): AttentionItem;
|
|
1794
|
+
listAttention(opts?: {
|
|
1795
|
+
includeResolved?: boolean;
|
|
1796
|
+
includeSnoozed?: boolean;
|
|
1797
|
+
now?: number;
|
|
1798
|
+
}): AttentionItem[];
|
|
1799
|
+
acknowledgeAttention(id: string, now?: number): AttentionItem | undefined;
|
|
1800
|
+
snoozeAttention(id: string, until: number, now?: number): AttentionItem | undefined;
|
|
1801
|
+
resolveAttention(id: string, now?: number): AttentionItem | undefined;
|
|
1802
|
+
resolveAttentionByDedupeKey(dedupeKey: string, now?: number): number;
|
|
1803
|
+
markSessionViewed(sessionId: string, now?: number): number;
|
|
1804
|
+
appendEvent(type: string, resourceType: string, resourceId: string, payload?: Record<string, unknown>, now?: number): CommandEvent;
|
|
1805
|
+
listEvents(afterId?: number, limit?: number): CommandEvent[];
|
|
1806
|
+
eventBounds(): {
|
|
1807
|
+
earliest: number;
|
|
1808
|
+
latest: number;
|
|
1809
|
+
};
|
|
1810
|
+
subscribeEvents(listener: (event: CommandEvent) => void): () => void;
|
|
1811
|
+
getLayout(): CommandLayoutEnvelope;
|
|
1812
|
+
putLayout(document: Record<string, unknown>, expectedRevision: number, now?: number): CommandLayoutEnvelope;
|
|
1813
|
+
close(): void;
|
|
1814
|
+
}
|
|
1815
|
+
interface OpenCommandCenterStoreOptions {
|
|
1816
|
+
dbPath: string;
|
|
1817
|
+
hostLabel?: string;
|
|
1818
|
+
generateHostId?: () => string;
|
|
1819
|
+
generateWorkspaceId?: () => string;
|
|
1820
|
+
generateAttentionId?: () => string;
|
|
1821
|
+
/** Test/embedding seam; throwing selects the non-durable in-memory fallback. */
|
|
1822
|
+
loadDatabase?: () => typeof better_sqlite3;
|
|
1823
|
+
}
|
|
1824
|
+
declare function normalizeLabel(value: unknown): string | undefined;
|
|
1825
|
+
declare function agentIdForSession(sessionId: string): string;
|
|
1826
|
+
declare function openCommandCenterStore(opts: OpenCommandCenterStoreOptions): CommandCenterStore;
|
|
1827
|
+
/** Exposed for API adapters and tests; one current RoamCode session owns one current agent. */
|
|
1828
|
+
declare const currentAgentIdForSession: typeof agentIdForSession;
|
|
1829
|
+
/** Re-exported validation keeps transport and stores on one label contract. */
|
|
1830
|
+
declare const normalizeCommandCenterLabel: typeof normalizeLabel;
|
|
1831
|
+
|
|
1832
|
+
type WorktreeErrorCode = "WORKTREE_OUTSIDE_ROOT" | "WORKTREE_INVALID_REF" | "WORKTREE_NOT_FOUND" | "WORKTREE_NOT_REGISTERED" | "WORKTREE_MAIN_PROTECTED" | "WORKTREE_DIRTY" | "WORKTREE_EXISTS" | "WORKTREE_GIT_FAILED" | "WORKTREE_TIMEOUT";
|
|
1833
|
+
declare class WorktreeError extends Error {
|
|
1834
|
+
readonly code: WorktreeErrorCode;
|
|
1835
|
+
readonly statusCode: number;
|
|
1836
|
+
constructor(code: WorktreeErrorCode, message: string, statusCode?: number);
|
|
1837
|
+
}
|
|
1838
|
+
interface WorktreeRecord {
|
|
1839
|
+
path: string;
|
|
1840
|
+
repositoryPath: string;
|
|
1841
|
+
branch?: string;
|
|
1842
|
+
head: string;
|
|
1843
|
+
dirty: boolean;
|
|
1844
|
+
changedFiles: number;
|
|
1845
|
+
isMain: boolean;
|
|
1846
|
+
}
|
|
1847
|
+
interface CreateWorktreeInput {
|
|
1848
|
+
repositoryPath: string;
|
|
1849
|
+
path: string;
|
|
1850
|
+
branch?: string;
|
|
1851
|
+
baseRef?: string;
|
|
1852
|
+
}
|
|
1853
|
+
interface CreateWorktreeResult {
|
|
1854
|
+
worktree: WorktreeRecord;
|
|
1855
|
+
created: boolean;
|
|
1856
|
+
}
|
|
1857
|
+
interface WorktreeService {
|
|
1858
|
+
inspect(path: string): Promise<WorktreeRecord>;
|
|
1859
|
+
create(input: CreateWorktreeInput): Promise<CreateWorktreeResult>;
|
|
1860
|
+
remove(path: string, force?: boolean): Promise<WorktreeRecord>;
|
|
1861
|
+
}
|
|
1862
|
+
interface CreateWorktreeServiceOptions {
|
|
1863
|
+
fsRoot: string;
|
|
1864
|
+
gitBin?: string;
|
|
1865
|
+
timeoutMs?: number;
|
|
1866
|
+
maxOutputBytes?: number;
|
|
1867
|
+
}
|
|
1868
|
+
declare function createWorktreeService(options: CreateWorktreeServiceOptions): WorktreeService;
|
|
1869
|
+
|
|
1870
|
+
type ExtensionKind = "adapter" | "plugin";
|
|
1871
|
+
type ExtensionTrust = "signed" | "integrity";
|
|
1872
|
+
declare class ExtensionError extends Error {
|
|
1873
|
+
readonly code: "EXTENSION_INVALID" | "EXTENSION_OUTSIDE_ROOT" | "EXTENSION_INTEGRITY_MISMATCH" | "EXTENSION_SIGNATURE_INVALID" | "EXTENSION_NOT_FOUND" | "EXTENSION_VERSION_NOT_FOUND" | "EXTENSION_ROLLBACK_UNAVAILABLE" | "EXTENSION_IN_USE" | "EXTENSION_PERMISSION_DENIED";
|
|
1874
|
+
readonly statusCode: number;
|
|
1875
|
+
constructor(code: "EXTENSION_INVALID" | "EXTENSION_OUTSIDE_ROOT" | "EXTENSION_INTEGRITY_MISMATCH" | "EXTENSION_SIGNATURE_INVALID" | "EXTENSION_NOT_FOUND" | "EXTENSION_VERSION_NOT_FOUND" | "EXTENSION_ROLLBACK_UNAVAILABLE" | "EXTENSION_IN_USE" | "EXTENSION_PERMISSION_DENIED", message: string, statusCode?: number);
|
|
1876
|
+
}
|
|
1877
|
+
declare const pluginPermissionSchema: z.ZodEnum<{
|
|
1878
|
+
"notifications:write": "notifications:write";
|
|
1879
|
+
"worktrees:write": "worktrees:write";
|
|
1880
|
+
"ci:read": "ci:read";
|
|
1881
|
+
"releases:read": "releases:read";
|
|
1882
|
+
"events:read": "events:read";
|
|
1883
|
+
"events:write": "events:write";
|
|
1884
|
+
}>;
|
|
1885
|
+
declare const pluginManifestSchema: z.ZodObject<{
|
|
1886
|
+
schemaVersion: z.ZodLiteral<1>;
|
|
1887
|
+
kind: z.ZodLiteral<"plugin">;
|
|
1888
|
+
id: z.ZodString;
|
|
1889
|
+
version: z.ZodString;
|
|
1890
|
+
displayName: z.ZodString;
|
|
1891
|
+
description: z.ZodString;
|
|
1892
|
+
platforms: z.ZodArray<z.ZodEnum<{
|
|
1893
|
+
darwin: "darwin";
|
|
1894
|
+
linux: "linux";
|
|
1895
|
+
}>>;
|
|
1896
|
+
minimumRoamCodeVersion: z.ZodOptional<z.ZodString>;
|
|
1897
|
+
permissions: z.ZodArray<z.ZodEnum<{
|
|
1898
|
+
"notifications:write": "notifications:write";
|
|
1899
|
+
"worktrees:write": "worktrees:write";
|
|
1900
|
+
"ci:read": "ci:read";
|
|
1901
|
+
"releases:read": "releases:read";
|
|
1902
|
+
"events:read": "events:read";
|
|
1903
|
+
"events:write": "events:write";
|
|
1904
|
+
}>>;
|
|
1905
|
+
actions: z.ZodArray<z.ZodObject<{
|
|
1906
|
+
id: z.ZodString;
|
|
1907
|
+
title: z.ZodString;
|
|
1908
|
+
description: z.ZodOptional<z.ZodString>;
|
|
1909
|
+
entrypoint: z.ZodString;
|
|
1910
|
+
args: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1911
|
+
cwd: z.ZodDefault<z.ZodEnum<{
|
|
1912
|
+
workspace: "workspace";
|
|
1913
|
+
host: "host";
|
|
1914
|
+
explicit: "explicit";
|
|
1915
|
+
}>>;
|
|
1916
|
+
timeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
1917
|
+
maxOutputBytes: z.ZodDefault<z.ZodNumber>;
|
|
1918
|
+
permissions: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
1919
|
+
"notifications:write": "notifications:write";
|
|
1920
|
+
"worktrees:write": "worktrees:write";
|
|
1921
|
+
"ci:read": "ci:read";
|
|
1922
|
+
"releases:read": "releases:read";
|
|
1923
|
+
"events:read": "events:read";
|
|
1924
|
+
"events:write": "events:write";
|
|
1925
|
+
}>>>;
|
|
1926
|
+
}, z.core.$strict>>;
|
|
1927
|
+
eventHooks: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
1928
|
+
event: z.ZodString;
|
|
1929
|
+
actionId: z.ZodString;
|
|
1930
|
+
}, z.core.$strict>>>;
|
|
1931
|
+
settingsSchema: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1932
|
+
ui: z.ZodOptional<z.ZodObject<{
|
|
1933
|
+
label: z.ZodString;
|
|
1934
|
+
route: z.ZodString;
|
|
1935
|
+
}, z.core.$strict>>;
|
|
1936
|
+
}, z.core.$strict>;
|
|
1937
|
+
declare const adapterRuntimeSchema: z.ZodObject<{
|
|
1938
|
+
executable: z.ZodString;
|
|
1939
|
+
probeArgs: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1940
|
+
probeTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
1941
|
+
launchArgs: z.ZodArray<z.ZodString>;
|
|
1942
|
+
resumeArgs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1943
|
+
env: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
1944
|
+
HOME: "HOME";
|
|
1945
|
+
PATH: "PATH";
|
|
1946
|
+
LANG: "LANG";
|
|
1947
|
+
LC_ALL: "LC_ALL";
|
|
1948
|
+
TMPDIR: "TMPDIR";
|
|
1949
|
+
SHELL: "SHELL";
|
|
1950
|
+
}>>>;
|
|
1951
|
+
workingPatterns: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1952
|
+
blockedPatterns: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1953
|
+
idlePatterns: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1954
|
+
identityPattern: z.ZodOptional<z.ZodString>;
|
|
1955
|
+
}, z.core.$strict>;
|
|
1956
|
+
type PluginPermission = z.infer<typeof pluginPermissionSchema>;
|
|
1957
|
+
type PluginManifestV1 = z.infer<typeof pluginManifestSchema>;
|
|
1958
|
+
type AdapterRuntimeV1 = z.infer<typeof adapterRuntimeSchema>;
|
|
1959
|
+
interface AdapterPackageManifestV1 {
|
|
1960
|
+
schemaVersion: 1;
|
|
1961
|
+
kind: "adapter";
|
|
1962
|
+
adapter: AdapterManifestV1;
|
|
1963
|
+
runtime: AdapterRuntimeV1;
|
|
1964
|
+
}
|
|
1965
|
+
type ExtensionManifestV1 = PluginManifestV1 | AdapterPackageManifestV1;
|
|
1966
|
+
interface ExtensionVersionRecord {
|
|
1967
|
+
kind: ExtensionKind;
|
|
1968
|
+
id: string;
|
|
1969
|
+
version: string;
|
|
1970
|
+
manifest: ExtensionManifestV1;
|
|
1971
|
+
integrity: string;
|
|
1972
|
+
trust: ExtensionTrust;
|
|
1973
|
+
signerFingerprint?: string;
|
|
1974
|
+
source: string;
|
|
1975
|
+
installedAt: number;
|
|
1976
|
+
}
|
|
1977
|
+
interface InstalledExtension {
|
|
1978
|
+
kind: ExtensionKind;
|
|
1979
|
+
id: string;
|
|
1980
|
+
enabled: boolean;
|
|
1981
|
+
currentVersion: string;
|
|
1982
|
+
previousVersion?: string;
|
|
1983
|
+
updatedAt: number;
|
|
1984
|
+
approvedPermissions: string[];
|
|
1985
|
+
current: ExtensionVersionRecord;
|
|
1986
|
+
versions: ExtensionVersionRecord[];
|
|
1987
|
+
}
|
|
1988
|
+
interface InstallExtensionInput {
|
|
1989
|
+
sourceDirectory: string;
|
|
1990
|
+
expectedIntegrity: string;
|
|
1991
|
+
signature?: string;
|
|
1992
|
+
publicKey?: string;
|
|
1993
|
+
source?: string;
|
|
1994
|
+
allowUnsigned?: boolean;
|
|
1995
|
+
}
|
|
1996
|
+
interface ExtensionManager {
|
|
1997
|
+
readonly mode: "sqlite" | "memory-fallback";
|
|
1998
|
+
list(kind?: ExtensionKind): InstalledExtension[];
|
|
1999
|
+
get(kind: ExtensionKind, id: string): InstalledExtension | undefined;
|
|
2000
|
+
packagePath(kind: ExtensionKind, id: string, version?: string): string;
|
|
2001
|
+
verify(kind: ExtensionKind, id: string, version?: string): Promise<boolean>;
|
|
2002
|
+
install(input: InstallExtensionInput): Promise<InstalledExtension>;
|
|
2003
|
+
setEnabled(kind: ExtensionKind, id: string, enabled: boolean, approvedPermissions?: string[]): InstalledExtension;
|
|
2004
|
+
rollback(kind: ExtensionKind, id: string): InstalledExtension;
|
|
2005
|
+
uninstall(kind: ExtensionKind, id: string, options?: {
|
|
2006
|
+
purgeState?: boolean;
|
|
2007
|
+
}): Promise<boolean>;
|
|
2008
|
+
close(): void;
|
|
2009
|
+
}
|
|
2010
|
+
interface OpenExtensionManagerOptions {
|
|
2011
|
+
dbPath: string;
|
|
2012
|
+
packagesDir: string;
|
|
2013
|
+
fsRoot: string;
|
|
2014
|
+
now?: () => number;
|
|
2015
|
+
loadDatabase?: () => typeof better_sqlite3;
|
|
2016
|
+
}
|
|
2017
|
+
declare function inspectExtensionPackage(sourceDirectory: string, fsRoot: string): Promise<{
|
|
2018
|
+
manifest: ExtensionManifestV1;
|
|
2019
|
+
integrity: string;
|
|
2020
|
+
}>;
|
|
2021
|
+
declare function openExtensionManager(options: OpenExtensionManagerOptions): ExtensionManager;
|
|
2022
|
+
interface MarketplaceEntry {
|
|
2023
|
+
kind: ExtensionKind;
|
|
2024
|
+
id: string;
|
|
2025
|
+
version: string;
|
|
2026
|
+
displayName: string;
|
|
2027
|
+
description: string;
|
|
2028
|
+
trust: "verified" | "community" | "local";
|
|
2029
|
+
compatibility: {
|
|
2030
|
+
platforms: Array<"darwin" | "linux">;
|
|
2031
|
+
minimumRoamCodeVersion?: string;
|
|
2032
|
+
};
|
|
2033
|
+
changelog?: string;
|
|
2034
|
+
source: string;
|
|
2035
|
+
integrity: string;
|
|
2036
|
+
signerFingerprint?: string;
|
|
2037
|
+
reportUrl?: string;
|
|
2038
|
+
}
|
|
2039
|
+
declare function parseMarketplaceIndex(value: unknown): MarketplaceEntry[];
|
|
2040
|
+
declare function searchMarketplace(entries: MarketplaceEntry[], query: string, platform?: NodeJS.Platform): MarketplaceEntry[];
|
|
2041
|
+
|
|
2042
|
+
declare class PluginRuntimeError extends Error {
|
|
2043
|
+
readonly code: "PLUGIN_NOT_FOUND" | "PLUGIN_DISABLED" | "PLUGIN_ACTION_NOT_FOUND" | "PLUGIN_PERMISSION_DENIED" | "PLUGIN_PATH_DENIED" | "PLUGIN_OUTPUT_LIMIT" | "PLUGIN_TIMEOUT" | "PLUGIN_FAILED";
|
|
2044
|
+
readonly statusCode: number;
|
|
2045
|
+
constructor(code: "PLUGIN_NOT_FOUND" | "PLUGIN_DISABLED" | "PLUGIN_ACTION_NOT_FOUND" | "PLUGIN_PERMISSION_DENIED" | "PLUGIN_PATH_DENIED" | "PLUGIN_OUTPUT_LIMIT" | "PLUGIN_TIMEOUT" | "PLUGIN_FAILED", message: string, statusCode?: number);
|
|
2046
|
+
}
|
|
2047
|
+
interface PluginRunInput {
|
|
2048
|
+
pluginId: string;
|
|
2049
|
+
actionId: string;
|
|
2050
|
+
workspacePath?: string;
|
|
2051
|
+
explicitCwd?: string;
|
|
2052
|
+
context?: Record<string, unknown>;
|
|
2053
|
+
}
|
|
2054
|
+
interface PluginRunResult {
|
|
2055
|
+
pluginId: string;
|
|
2056
|
+
pluginVersion: string;
|
|
2057
|
+
actionId: string;
|
|
2058
|
+
status: "succeeded" | "failed";
|
|
2059
|
+
exitCode: number;
|
|
2060
|
+
stdout: string;
|
|
2061
|
+
stderr: string;
|
|
2062
|
+
startedAt: number;
|
|
2063
|
+
finishedAt: number;
|
|
2064
|
+
truncated: false;
|
|
2065
|
+
}
|
|
2066
|
+
interface PluginAuditEvent {
|
|
2067
|
+
pluginId: string;
|
|
2068
|
+
pluginVersion: string;
|
|
2069
|
+
actionId: string;
|
|
2070
|
+
phase: "started" | "finished";
|
|
2071
|
+
result?: "succeeded" | "failed";
|
|
2072
|
+
exitCode?: number;
|
|
2073
|
+
durationMs?: number;
|
|
2074
|
+
}
|
|
2075
|
+
interface CreatePluginRuntimeOptions {
|
|
2076
|
+
extensions: ExtensionManager;
|
|
2077
|
+
fsRoot: string;
|
|
2078
|
+
now?: () => number;
|
|
2079
|
+
audit?: (event: PluginAuditEvent) => void;
|
|
2080
|
+
}
|
|
2081
|
+
interface PluginRuntime {
|
|
2082
|
+
run(input: PluginRunInput): Promise<PluginRunResult>;
|
|
2083
|
+
hooksFor(eventType: string): Array<{
|
|
2084
|
+
pluginId: string;
|
|
2085
|
+
actionId: string;
|
|
2086
|
+
}>;
|
|
2087
|
+
}
|
|
2088
|
+
declare function createPluginRuntime(options: CreatePluginRuntimeOptions): PluginRuntime;
|
|
2089
|
+
|
|
2090
|
+
type ControlStoreMode = "sqlite" | "memory-fallback";
|
|
2091
|
+
type AuditActorType = "host" | "device" | "local" | "automation" | "plugin" | "system";
|
|
2092
|
+
type AuditResult = "success" | "denied" | "error";
|
|
2093
|
+
interface IdempotencyRecord {
|
|
2094
|
+
actorId: string;
|
|
2095
|
+
key: string;
|
|
2096
|
+
fingerprint: string;
|
|
2097
|
+
statusCode: number;
|
|
2098
|
+
body: string;
|
|
2099
|
+
createdAt: number;
|
|
2100
|
+
expiresAt: number;
|
|
2101
|
+
}
|
|
2102
|
+
interface AuditRecord {
|
|
2103
|
+
id: number;
|
|
2104
|
+
actorType: AuditActorType;
|
|
2105
|
+
actorId: string;
|
|
2106
|
+
action: string;
|
|
2107
|
+
targetType: string;
|
|
2108
|
+
targetId?: string;
|
|
2109
|
+
result: AuditResult;
|
|
2110
|
+
metadata: Record<string, string | number | boolean | null>;
|
|
2111
|
+
createdAt: number;
|
|
2112
|
+
previousHash: string;
|
|
2113
|
+
hash: string;
|
|
2114
|
+
}
|
|
2115
|
+
type AutomationTrigger = {
|
|
2116
|
+
eventType: string;
|
|
2117
|
+
resourceType?: string;
|
|
2118
|
+
};
|
|
2119
|
+
type AutomationAction = {
|
|
2120
|
+
type: "acknowledge_attention";
|
|
2121
|
+
target: "event-resource" | string;
|
|
2122
|
+
} | {
|
|
2123
|
+
type: "resolve_attention";
|
|
2124
|
+
target: "event-resource" | string;
|
|
2125
|
+
} | {
|
|
2126
|
+
type: "snooze_attention";
|
|
2127
|
+
target: "event-resource" | string;
|
|
2128
|
+
durationMs: number;
|
|
2129
|
+
} | {
|
|
2130
|
+
type: "emit_event";
|
|
2131
|
+
eventType: string;
|
|
2132
|
+
resourceType: string;
|
|
2133
|
+
resourceId: string;
|
|
2134
|
+
};
|
|
2135
|
+
interface AutomationDefinition {
|
|
2136
|
+
id: string;
|
|
2137
|
+
name: string;
|
|
2138
|
+
enabled: boolean;
|
|
2139
|
+
trigger: AutomationTrigger;
|
|
2140
|
+
action: AutomationAction;
|
|
2141
|
+
permissions: string[];
|
|
2142
|
+
createdAt: number;
|
|
2143
|
+
updatedAt: number;
|
|
2144
|
+
}
|
|
2145
|
+
interface AutomationRun {
|
|
2146
|
+
id: number;
|
|
2147
|
+
automationId: string;
|
|
2148
|
+
eventId?: number;
|
|
2149
|
+
status: "succeeded" | "skipped" | "failed";
|
|
2150
|
+
detail?: string;
|
|
2151
|
+
createdAt: number;
|
|
2152
|
+
}
|
|
2153
|
+
interface CreateAutomationInput {
|
|
2154
|
+
name: string;
|
|
2155
|
+
enabled?: boolean;
|
|
2156
|
+
trigger: AutomationTrigger;
|
|
2157
|
+
action: AutomationAction;
|
|
2158
|
+
permissions: string[];
|
|
2159
|
+
}
|
|
2160
|
+
interface UpdateAutomationInput {
|
|
2161
|
+
name?: string;
|
|
2162
|
+
enabled?: boolean;
|
|
2163
|
+
trigger?: AutomationTrigger;
|
|
2164
|
+
action?: AutomationAction;
|
|
2165
|
+
permissions?: string[];
|
|
2166
|
+
}
|
|
2167
|
+
interface ControlStore {
|
|
2168
|
+
readonly mode: ControlStoreMode;
|
|
2169
|
+
getIdempotency(actorId: string, key: string, now?: number): IdempotencyRecord | undefined;
|
|
2170
|
+
putIdempotency(record: IdempotencyRecord): void;
|
|
2171
|
+
appendAudit(input: Omit<AuditRecord, "id" | "previousHash" | "hash">): AuditRecord;
|
|
2172
|
+
listAudit(afterId?: number, limit?: number): AuditRecord[];
|
|
2173
|
+
listAuditLatest(limit?: number): AuditRecord[];
|
|
2174
|
+
verifyAuditChain(): {
|
|
2175
|
+
valid: boolean;
|
|
2176
|
+
count: number;
|
|
2177
|
+
head: string;
|
|
2178
|
+
};
|
|
2179
|
+
listAutomations(): AutomationDefinition[];
|
|
2180
|
+
getAutomation(id: string): AutomationDefinition | undefined;
|
|
2181
|
+
createAutomation(input: CreateAutomationInput, now?: number): AutomationDefinition;
|
|
2182
|
+
updateAutomation(id: string, input: UpdateAutomationInput, now?: number): AutomationDefinition | undefined;
|
|
2183
|
+
removeAutomation(id: string): boolean;
|
|
2184
|
+
recordAutomationRun(input: Omit<AutomationRun, "id">): AutomationRun;
|
|
2185
|
+
listAutomationRuns(automationId?: string, limit?: number): AutomationRun[];
|
|
2186
|
+
close(): void;
|
|
2187
|
+
}
|
|
2188
|
+
interface OpenControlStoreOptions {
|
|
2189
|
+
dbPath: string;
|
|
2190
|
+
generateAutomationId?: () => string;
|
|
2191
|
+
loadDatabase?: () => typeof better_sqlite3;
|
|
2192
|
+
}
|
|
2193
|
+
declare function normalizeAutomationTrigger(value: unknown): AutomationTrigger | undefined;
|
|
2194
|
+
declare function normalizeAutomationAction(value: unknown): AutomationAction | undefined;
|
|
2195
|
+
declare function normalizeAutomationInput(value: unknown): CreateAutomationInput | undefined;
|
|
2196
|
+
/** Retain only coarse, bounded audit metadata; content- or credential-shaped fields are dropped. */
|
|
2197
|
+
declare function privacySafeAuditMetadata(value: Record<string, unknown> | undefined): Record<string, string | number | boolean | null>;
|
|
2198
|
+
declare function openControlStore(opts: OpenControlStoreOptions): ControlStore;
|
|
2199
|
+
declare const CONTROL_IDEMPOTENCY_TTL_MS: number;
|
|
2200
|
+
|
|
592
2201
|
/**
|
|
593
2202
|
* Origin / CSWSH (cross-site WebSocket hijacking) guard for the WS upgrade and state-changing HTTP.
|
|
594
2203
|
*
|
|
@@ -719,6 +2328,11 @@ interface WsTicketStoreOptions {
|
|
|
719
2328
|
/** Injectable ticket generator for tests. Default: 32 CSPRNG bytes, base64url. */
|
|
720
2329
|
generate?: () => string;
|
|
721
2330
|
}
|
|
2331
|
+
interface WsTicketContext {
|
|
2332
|
+
actorType: "device" | "host" | "local" | "relay";
|
|
2333
|
+
actorId: string;
|
|
2334
|
+
label: string;
|
|
2335
|
+
}
|
|
722
2336
|
/**
|
|
723
2337
|
* In-memory single-use ticket store. Deliberately NOT persisted: a ticket outliving a server restart
|
|
724
2338
|
* would defeat its 30s point, and the client just re-POSTs on reconnect. Expired entries are swept
|
|
@@ -726,20 +2340,25 @@ interface WsTicketStoreOptions {
|
|
|
726
2340
|
* a timer.
|
|
727
2341
|
*/
|
|
728
2342
|
declare class WsTicketStore {
|
|
729
|
-
/** ticket → expiry
|
|
2343
|
+
/** ticket → expiry + the authenticated principal that minted it. */
|
|
730
2344
|
private readonly tickets;
|
|
731
2345
|
private readonly ttlMs;
|
|
732
2346
|
private readonly now;
|
|
733
2347
|
private readonly generate;
|
|
734
2348
|
constructor(opts?: WsTicketStoreOptions);
|
|
735
2349
|
/** Mint a fresh single-use ticket. The response shape is exactly what POST /ws-ticket returns. */
|
|
736
|
-
issue(): {
|
|
2350
|
+
issue(context?: WsTicketContext): {
|
|
737
2351
|
ticket: string;
|
|
738
2352
|
expiresInMs: number;
|
|
739
2353
|
};
|
|
740
2354
|
/** Consume a ticket: true exactly ONCE for a live ticket; false for unknown, expired, or already-used
|
|
741
2355
|
* (the entry is deleted on first consume, so a replayed WS URL is rejected). */
|
|
742
2356
|
consume(ticket: string): boolean;
|
|
2357
|
+
/** Consume once and recover the authenticated principal bound at issuance. The wrapper object makes a
|
|
2358
|
+
* context-free legacy/test ticket distinguishable from an invalid ticket. */
|
|
2359
|
+
consumeWithContext(ticket: string): {
|
|
2360
|
+
context?: WsTicketContext;
|
|
2361
|
+
} | undefined;
|
|
743
2362
|
/** Drop expired entries so an unconsumed flood can't grow the map (lazy — no timer to leak). */
|
|
744
2363
|
private sweep;
|
|
745
2364
|
/** TEST ONLY: how many un-consumed tickets are currently held (post-sweep count). */
|
|
@@ -755,6 +2374,8 @@ interface PushSubscriptionRecord {
|
|
|
755
2374
|
auth: string;
|
|
756
2375
|
/** Optional session scope; undefined = subscribed to ALL sessions. */
|
|
757
2376
|
sessionId?: string;
|
|
2377
|
+
/** Per-device credential that created this subscription. Revocation removes its push channel too. */
|
|
2378
|
+
deviceId?: string;
|
|
758
2379
|
createdAt: number;
|
|
759
2380
|
}
|
|
760
2381
|
interface PushStore {
|
|
@@ -764,6 +2385,7 @@ interface PushStore {
|
|
|
764
2385
|
sessionId?: string;
|
|
765
2386
|
}): PushSubscriptionRecord[];
|
|
766
2387
|
remove(endpoint: string): void;
|
|
2388
|
+
removeForDevice(deviceId: string): void;
|
|
767
2389
|
close(): void;
|
|
768
2390
|
}
|
|
769
2391
|
interface OpenPushStoreOptions {
|
|
@@ -1493,10 +3115,45 @@ declare function capturePane(opts: CaptureOptions): Promise<string>;
|
|
|
1493
3115
|
|
|
1494
3116
|
declare class ProviderRegistry {
|
|
1495
3117
|
private readonly byId;
|
|
3118
|
+
private readonly manifests;
|
|
3119
|
+
private readonly sources;
|
|
3120
|
+
private readonly enabled;
|
|
1496
3121
|
constructor(providers: readonly AgentProvider[]);
|
|
3122
|
+
register(provider: AgentProvider, source?: "built-in" | "installed", enabled?: boolean): void;
|
|
3123
|
+
setEnabled(id: ProviderId, enabled: boolean): void;
|
|
3124
|
+
isEnabled(id: ProviderId): boolean;
|
|
3125
|
+
source(id: ProviderId): "built-in" | "installed" | undefined;
|
|
3126
|
+
unregisterInstalled(id: ProviderId): void;
|
|
1497
3127
|
get(id: ProviderId): AgentProvider;
|
|
1498
3128
|
list(): AgentProvider[];
|
|
3129
|
+
listEnabled(): AgentProvider[];
|
|
3130
|
+
manifest(id: ProviderId): Readonly<AdapterManifestV1>;
|
|
3131
|
+
descriptors(): {
|
|
3132
|
+
enabled: boolean;
|
|
3133
|
+
id: string;
|
|
3134
|
+
displayName: string;
|
|
3135
|
+
version: string;
|
|
3136
|
+
schemaVersion: 1;
|
|
3137
|
+
source: "built-in" | "installed";
|
|
3138
|
+
platforms: ("darwin" | "linux")[];
|
|
3139
|
+
resumeIdentity: "optional" | "required" | "unsupported";
|
|
3140
|
+
capabilities: {
|
|
3141
|
+
state: boolean;
|
|
3142
|
+
probe: boolean;
|
|
3143
|
+
launch: boolean;
|
|
3144
|
+
resume: boolean;
|
|
3145
|
+
identity: boolean;
|
|
3146
|
+
metadata: boolean;
|
|
3147
|
+
usage: boolean;
|
|
3148
|
+
login: boolean;
|
|
3149
|
+
attachments: boolean;
|
|
3150
|
+
cleanup: boolean;
|
|
3151
|
+
};
|
|
3152
|
+
stateAuthority: AdapterStateAuthority[];
|
|
3153
|
+
optionSchema: Record<string, unknown>;
|
|
3154
|
+
}[];
|
|
1499
3155
|
}
|
|
3156
|
+
type ReturnTypeOfDescriptors = ReturnType<ProviderRegistry["descriptors"]>;
|
|
1500
3157
|
|
|
1501
3158
|
interface CodexSpawnLease {
|
|
1502
3159
|
readonly started: Promise<void>;
|
|
@@ -1638,6 +3295,11 @@ interface TerminalManagerDeps {
|
|
|
1638
3295
|
* are). Same never-throw contract.
|
|
1639
3296
|
*/
|
|
1640
3297
|
onFinished?: (id: string, wasAttached: boolean) => void;
|
|
3298
|
+
/** Every semantic state transition, including ones observed while a browser is attached. Used by the
|
|
3299
|
+
* command-center event/attention layer; a failure is isolated from terminal state. */
|
|
3300
|
+
onActivityChanged?: (id: string, previous: PaneStatus, current: PaneStatus, attached: boolean) => void;
|
|
3301
|
+
/** A client focused/attached this terminal. Done-unseen attention can become seen; blocked attention stays. */
|
|
3302
|
+
onViewed?: (id: string) => void;
|
|
1641
3303
|
/**
|
|
1642
3304
|
* Capture a tmux session's CURRENT rendered pane as plain text (READ-ONLY). Injected for tests; in
|
|
1643
3305
|
* production it defaults to a real `capture-pane -p` on {@link TMUX_SOCKET}. Drives {@link refreshActivity},
|
|
@@ -1650,15 +3312,8 @@ interface TerminalManagerDeps {
|
|
|
1650
3312
|
type CreateTerminalOptions = {
|
|
1651
3313
|
id: string;
|
|
1652
3314
|
cwd: string;
|
|
1653
|
-
provider:
|
|
1654
|
-
options:
|
|
1655
|
-
cols?: number;
|
|
1656
|
-
rows?: number;
|
|
1657
|
-
} | {
|
|
1658
|
-
id: string;
|
|
1659
|
-
cwd: string;
|
|
1660
|
-
provider: "codex";
|
|
1661
|
-
options: CodexSessionOptions;
|
|
3315
|
+
provider: ProviderId;
|
|
3316
|
+
options: ProviderSessionOptions;
|
|
1662
3317
|
cols?: number;
|
|
1663
3318
|
rows?: number;
|
|
1664
3319
|
};
|
|
@@ -1675,6 +3330,7 @@ declare class TerminalManager {
|
|
|
1675
3330
|
private readonly providers;
|
|
1676
3331
|
private attachConfig?;
|
|
1677
3332
|
constructor(deps: TerminalManagerDeps);
|
|
3333
|
+
private notifyActivityChanged;
|
|
1678
3334
|
/** Late-bound (after listen(), which resolves the loopback port) — same config the chat SessionManager
|
|
1679
3335
|
* gets. When set, each terminal's claude is spawned with `--mcp-config` so send_image/send_file work. */
|
|
1680
3336
|
setAttachConfig(attach: AttachSpawnOptions | undefined): void;
|
|
@@ -2120,8 +3776,24 @@ declare class CodexLatestService {
|
|
|
2120
3776
|
|
|
2121
3777
|
interface CreateServerDeps {
|
|
2122
3778
|
store?: SessionStore;
|
|
3779
|
+
/** Durable per-device credentials + one-time pairing sessions. start.ts supplies a SQLite store. */
|
|
3780
|
+
deviceStore?: DeviceStore;
|
|
3781
|
+
/** Durable host/workspace/agent/attention/event state. start.ts supplies a SQLite store. */
|
|
3782
|
+
commandStore?: CommandCenterStore;
|
|
3783
|
+
/** Durable idempotency, privacy-safe audit, and automation definitions/runs. */
|
|
3784
|
+
controlStore?: ControlStore;
|
|
3785
|
+
/** Guarded git worktree lifecycle, confined to FS_ROOT and injectable for isolated tests. */
|
|
3786
|
+
worktreeService?: WorktreeService;
|
|
3787
|
+
/** Durable verified adapter/plugin package inventory. start.ts supplies a SQLite-backed manager. */
|
|
3788
|
+
extensionManager?: ExtensionManager;
|
|
3789
|
+
/** Bounded, permissioned plugin subprocess boundary. */
|
|
3790
|
+
pluginRuntime?: PluginRuntime;
|
|
3791
|
+
/** Optional immutable marketplace index; local extension installation never depends on it. */
|
|
3792
|
+
marketplaceEntries?: MarketplaceEntry[];
|
|
2123
3793
|
/** Absolute path to the built PWA (packages/web/dist). When set, the server also serves the UI. */
|
|
2124
3794
|
webDir?: string;
|
|
3795
|
+
/** Per-process boot identity returned as a response header for the out-of-process managed watchdog. */
|
|
3796
|
+
healthInstanceId?: string;
|
|
2125
3797
|
pushStore?: PushStore;
|
|
2126
3798
|
/** VAPID public key exposed at GET /push/vapid for the browser subscription. */
|
|
2127
3799
|
vapidPublicKey?: string;
|
|
@@ -2211,13 +3883,49 @@ interface CreateServerDeps {
|
|
|
2211
3883
|
* store is built when omitted.
|
|
2212
3884
|
*/
|
|
2213
3885
|
wsTickets?: WsTicketStore;
|
|
3886
|
+
/** One-writer/many-observer terminal input coordinator. Injectable for deterministic multi-client tests. */
|
|
3887
|
+
inputLeases?: InputLeaseCoordinator;
|
|
3888
|
+
/** Team policy seam: direct local mode permits confirmed takeover; enterprise policy can deny it here. */
|
|
3889
|
+
authorizeInputTakeover?: (principal: InputLeasePrincipal, sessionId: string) => boolean;
|
|
3890
|
+
/** Optional policy seam for acquiring/writing input. Team RBAC is applied in addition when enabled. */
|
|
3891
|
+
authorizeInputWrite?: (principal: InputLeasePrincipal, sessionId: string) => boolean;
|
|
3892
|
+
/** Durable team membership and role assignments. start.ts supplies SQLite; tests may inject memory. */
|
|
3893
|
+
teamStore?: TeamStore;
|
|
3894
|
+
/** Durable organization policy. Disabled by default; enforced uniformly when explicitly enabled. */
|
|
3895
|
+
policyStore?: PolicyStore;
|
|
3896
|
+
/** Durable, explicitly scoped host-to-host API connections. Raw peer credentials never leave this store. */
|
|
3897
|
+
peerStore?: PeerStore;
|
|
3898
|
+
/** Isolated outbound peer transport; injectable so tests never contact developer or production hosts. */
|
|
3899
|
+
peerFetch?: typeof globalThis.fetch;
|
|
3900
|
+
/** Ephemeral, bounded presence heartbeats. */
|
|
3901
|
+
presence?: PresenceCoordinator;
|
|
3902
|
+
/** Advertises and enforces that this host has an outbound blind-relay transport configured. */
|
|
3903
|
+
relayEnabled?: boolean;
|
|
3904
|
+
/** Optional hosted/self-hosted bootstrap; absent means relay works for already-provisioned devices only. */
|
|
3905
|
+
relayPairing?: RelayPairingBootstrap;
|
|
3906
|
+
/** Late-bound host connector hook so device revocation closes relay channels immediately. */
|
|
3907
|
+
onDeviceRevoked?: (deviceId: string) => void;
|
|
2214
3908
|
}
|
|
2215
3909
|
interface CreateServerResult {
|
|
2216
3910
|
app: FastifyInstance;
|
|
2217
3911
|
authGate: AuthGate;
|
|
3912
|
+
/** Issue a five-minute, one-use pairing capability without exposing the host's master token. */
|
|
3913
|
+
issuePairing(): PairingTicket;
|
|
3914
|
+
/** Internal E2E-relay bridge. It authenticates relay-scoped devices through the exact normal route hooks. */
|
|
3915
|
+
dispatchRelayRequest(token: string, request: RelayRpcRequest): Promise<RelayRpcResponse>;
|
|
3916
|
+
/** Issues a relay-principal terminal ticket without exposing the bridge's process-local capability. */
|
|
3917
|
+
issueRelayTerminalTicket(token: string): Promise<string>;
|
|
3918
|
+
/** Process-local loopback headers for streamed relay HTTP. Never expose these outside this server process. */
|
|
3919
|
+
relayLoopbackHeaders(token: string, headers?: Record<string, string>): Record<string, string>;
|
|
2218
3920
|
/** Exposed so startServer can late-bind the MCP attach config (after listen() resolves the port) —
|
|
2219
3921
|
* this is what gives the terminal's claude send_image/send_file. */
|
|
2220
3922
|
terminalManager: TerminalManager;
|
|
3923
|
+
/** Exposed for relay/team composition and isolated ownership tests. */
|
|
3924
|
+
inputLeases: InputLeaseCoordinator;
|
|
3925
|
+
teamStore: TeamStore;
|
|
3926
|
+
policyStore: PolicyStore;
|
|
3927
|
+
peerStore: PeerStore;
|
|
3928
|
+
presence: PresenceCoordinator;
|
|
2221
3929
|
/** False when tmux/node-pty is unavailable → terminal sessions are disabled (startServer warns loudly). */
|
|
2222
3930
|
terminalAvailable: boolean;
|
|
2223
3931
|
}
|
|
@@ -2346,8 +4054,41 @@ declare function startServer(env?: NodeJS.ProcessEnv): Promise<CreateServerResul
|
|
|
2346
4054
|
url: string;
|
|
2347
4055
|
token?: string;
|
|
2348
4056
|
tokenGenerated: boolean;
|
|
4057
|
+
relayHost?: RelayHostConnector;
|
|
2349
4058
|
}>;
|
|
2350
4059
|
|
|
4060
|
+
interface ProcessLifecycleTarget {
|
|
4061
|
+
once(event: string, listener: (...args: unknown[]) => void): unknown;
|
|
4062
|
+
off(event: string, listener: (...args: unknown[]) => void): unknown;
|
|
4063
|
+
exit(code: number): never | void;
|
|
4064
|
+
}
|
|
4065
|
+
interface ProcessLifecycleOptions {
|
|
4066
|
+
/** Close only on an intentional signal. Fatal errors exit immediately because process state is unknown. */
|
|
4067
|
+
close: () => void | Promise<unknown>;
|
|
4068
|
+
target?: ProcessLifecycleTarget;
|
|
4069
|
+
log?: (message: string) => void;
|
|
4070
|
+
shutdownTimeoutMs?: number;
|
|
4071
|
+
setTimer?: typeof setTimeout;
|
|
4072
|
+
clearTimer?: typeof clearTimeout;
|
|
4073
|
+
}
|
|
4074
|
+
interface ProcessLifecycleHandle {
|
|
4075
|
+
dispose(): void;
|
|
4076
|
+
}
|
|
4077
|
+
/**
|
|
4078
|
+
* Keep fatal diagnostics useful without copying bearer credentials, pairing links, or a maintainer's absolute
|
|
4079
|
+
* home path into service logs. The summary deliberately uses Error.message rather than the full stack.
|
|
4080
|
+
*/
|
|
4081
|
+
declare function safeProcessErrorSummary(reason: unknown, home?: string): string;
|
|
4082
|
+
/**
|
|
4083
|
+
* Own the process boundary for the always-on server.
|
|
4084
|
+
*
|
|
4085
|
+
* Intentional SIGTERM/SIGINT gets a bounded graceful close. An uncaught exception or unhandled rejection is
|
|
4086
|
+
* different: Node cannot promise that application state remains valid, so the process exits non-zero immediately
|
|
4087
|
+
* and lets launchd/systemd restart it. Keeping a possibly-corrupt process alive is how a listener can remain bound
|
|
4088
|
+
* while every HTTP request stalls indefinitely.
|
|
4089
|
+
*/
|
|
4090
|
+
declare function installProcessLifecycle(options: ProcessLifecycleOptions): ProcessLifecycleHandle;
|
|
4091
|
+
|
|
2351
4092
|
/** Terminal mode needs BOTH a tmux binary and a loadable node-pty. Injectable for tests. */
|
|
2352
4093
|
declare function detectTerminalSupport(deps?: {
|
|
2353
4094
|
hasTmux?: () => boolean;
|
|
@@ -2430,9 +4171,23 @@ declare function enableService(record: ServiceRecord): {
|
|
|
2430
4171
|
declare class ProviderOptionsError extends ProviderError {
|
|
2431
4172
|
constructor(message: string);
|
|
2432
4173
|
}
|
|
2433
|
-
declare function parseProviderOptions(provider: ProviderId, raw: unknown): ProviderSessionOptions;
|
|
4174
|
+
declare function parseProviderOptions(provider: ProviderId, raw: unknown, optionSchema?: Record<string, unknown>): ProviderSessionOptions;
|
|
2434
4175
|
declare function parseLegacyClaudeArgs(args: readonly string[]): ClaudeSessionOptions;
|
|
2435
4176
|
|
|
4177
|
+
interface CreateInstalledAdapterProviderOptions {
|
|
4178
|
+
extensions: ExtensionManager;
|
|
4179
|
+
adapterId: string;
|
|
4180
|
+
env?: NodeJS.ProcessEnv;
|
|
4181
|
+
}
|
|
4182
|
+
declare function createInstalledAdapterProvider(options: CreateInstalledAdapterProviderOptions): ProviderAdapterV1;
|
|
4183
|
+
|
|
4184
|
+
type JsonObject = Record<string, unknown>;
|
|
4185
|
+
interface OpenApiBuildOptions {
|
|
4186
|
+
serverVersion: string;
|
|
4187
|
+
adapters: ReturnTypeOfDescriptors;
|
|
4188
|
+
}
|
|
4189
|
+
declare function buildOpenApiDocument(options: OpenApiBuildOptions): JsonObject;
|
|
4190
|
+
|
|
2436
4191
|
interface CreateClaudeProviderOptions {
|
|
2437
4192
|
claudeBin: string;
|
|
2438
4193
|
env?: NodeJS.ProcessEnv;
|
|
@@ -2440,7 +4195,7 @@ interface CreateClaudeProviderOptions {
|
|
|
2440
4195
|
getAttach?: () => AttachSpawnOptions | undefined;
|
|
2441
4196
|
probe?: () => Promise<ProviderAvailability>;
|
|
2442
4197
|
}
|
|
2443
|
-
declare function createClaudeProvider(options: CreateClaudeProviderOptions):
|
|
4198
|
+
declare function createClaudeProvider(options: CreateClaudeProviderOptions): ProviderAdapterV1;
|
|
2444
4199
|
|
|
2445
4200
|
interface CreateCodexProviderOptions {
|
|
2446
4201
|
codexBin: string;
|
|
@@ -2453,7 +4208,7 @@ interface CreateCodexProviderOptions {
|
|
|
2453
4208
|
}
|
|
2454
4209
|
type CodexAttachContext = Pick<AttachSpawnOptions, "baseUrl" | "token" | "mcpScriptPath">;
|
|
2455
4210
|
declare function buildCodexArgs(context: ProviderProcessContext, attach?: CodexAttachContext): string[];
|
|
2456
|
-
declare function createCodexProvider(options: CreateCodexProviderOptions):
|
|
4211
|
+
declare function createCodexProvider(options: CreateCodexProviderOptions): ProviderAdapterV1;
|
|
2457
4212
|
|
|
2458
4213
|
declare const CODEX_EXECUTABLE_PROBE_TIMEOUT_MS = 5000;
|
|
2459
4214
|
declare const OPENAI_CODE_SIGNING_TEAM_ID = "2DC432GLL2";
|
|
@@ -2507,4 +4262,4 @@ declare function codexClassifierVersionWarning(codexVersion: string | undefined)
|
|
|
2507
4262
|
|
|
2508
4263
|
declare const SERVER_PACKAGE = "@roamcode.ai/server";
|
|
2509
4264
|
|
|
2510
|
-
export { API_PATH_DENYLIST, type AgentProvider, type AttachSpawnOptions, type AuthCheckResult, AuthGate, type AuthGateOptions, type Bar, CHECK_CACHE_MS, CLASSIFIER_TESTED_UP_TO, CLAUDE_LATEST_CACHE_MS, CLAUDE_VERSION_CACHE_MS, CLAUDE_VERSION_TIMEOUT_MS, CODEX_CLASSIFIER_TESTED_UP_TO, CODEX_EXECUTABLE_PROBE_TIMEOUT_MS, CODEX_OSC_MAX_CARRY, type CaptureOptions, type ChangelogEntry, type ClaudeAuthDeps, ClaudeAuthService, type ClaudeAuthStatus, type ClaudeAvailability, type ClaudeLatestDeps, ClaudeLatestService, type ClaudeMetadataRunner, ClaudeMetadataService, type ClaudeModelCatalogItem, type ClaudeSessionOptions, type ClaudeVersionProbe, type CodexAccount, CodexAppServerClient, type CodexAppServerClientOptions, type CodexDeviceLogin, type CodexExecutableDeps, type CodexExecutableProbe, type CodexExecutableResolution, type CodexInstallProvenance, CodexLatestService, type CodexLoginCompletion, type CodexLoginStatus, type CodexMetadataDiagnostics, type CodexMetadataRpc, CodexMetadataService, type CodexMetadataServiceOptions, type CodexModel, type CodexOscParser, type CodexProfileClientLifecycle, type CodexSessionOptions, type CodexSpawnLease, type CodexThreadInventoryEntry, type CodexThreadPersistence, CodexThreadResolver, type CodexThreadResolverOptions, type CodexUsage, type CodexVersionInfo, type CreateClaudeProviderOptions, type CreateCodexProfileClientLifecycleOptions, type CreateCodexProviderOptions, type CreatePushDispatcherDeps, type CreateServerDeps, type CreateServerResult, type CreateWebPushSendOptions, type DirEntry, type DirListing, type DirSearchResult, FETCH_TIMEOUT_MS, type FetchLatest, type FetchManifest, type FetchReleases, FsError, type FsErrorCode, FsService, type FsServiceOptions, type GitHubRelease, type HooksSettingsDocument, type IPty, type InstallServiceContext, type InstallServiceResult, type InstallationKind, type LaunchIntent, type ManagedInstallOptions, type ManagedInstallResult, type ManagedInstallStatus, type ManagedPaths, type McpConfigDocument, type ModelWeekBar, OPENAI_CODE_SIGNING_TEAM_ID, type OpenPushStoreOptions, type OpenSessionStoreOptions, type OriginCheckOptions, type PaneStatus, type ProcessSpec, type ProviderAvailability, ProviderError, type ProviderId, ProviderOptionsError, type ProviderProcessContext, ProviderRegistry, type ProviderRuntimeSignal, type ProviderRuntimeSignalParser, type ProviderSessionOptions, type PtySpawn, type PushDispatcher, type PushEvent, type PushEventKind, type PushPayload, type PushRecipient, type PushSendFn, type PushStore, type PushSubscriptionRecord, RUNNING_BUILD, RUNNING_VERSION, type RateLimitDecision, RateLimiter, type RateLimiterOptions, type RegisterStaticOptions, type ReleaseRecord, type RenderLaunchdOptions, type RenderSystemdOptions, type ResolveAccessTokenOptions, type ResolveCodexExecutableOptions, type ResolveCodexThreadOptions, type ResolveVapidKeysOptions, type RunClaudeVersion, type RunUsage, SEARCH_MAX_DEPTH, SEARCH_MAX_DIRS, SEARCH_MAX_RESULTS, SERVER_PACKAGE, SHELL_PATH_ALLOWLIST, type ServerConfig, type ServerRuntimeConfig, type ServiceRecord, type SessionDefaults, SessionDefaultsConflictError, type SessionFileDirection, type SessionFileKind, type SessionFileStorage, type SessionStore, type StoreMode, type StoredSession, type StoredSessionDefaults, type StoredSessionFile, type StoredStatus, TerminalManager, type TerminalManagerDeps, type TerminalMeta, TerminalProcess, type TerminalProcessOptions, type TerminalSub, USAGE_CACHE_MS, USAGE_TIMEOUT_MS, type UpdateAction, type UpdateState, type UpdateStatus, Updater, type UpdaterDeps, type UpdaterFs, type UsageInfo, UsageService, type UsageServiceDeps, type VapidKeys, type VersionInfo, WS_TICKET_TTL_MS, WsTicketStore, type WsTicketStoreOptions, assertConfigAllowsStart, buildCodexArgs, buildHooksSettingsDocument, buildMcpConfigDocument, buildPushPayload, buildServicePath, capturePane, classifierVersionWarning, classifyCodexPane, classifyPaneStatus, claudePreflightWarning, codexClassifierVersionWarning, compareVersions, computeBuildDrift, computeInstallDrift, createClaudeAuthService, createClaudeLatestService, createClaudeMetadataRunner, createClaudeProvider, createClaudeVersionProbe, createCodexOscParser, createCodexProfileClientLifecycle, createCodexProvider, createCodexThreadInventory, createCodexThreadPersistence, createPushDispatcher, createServer, createUpdater, createUsageRunner, createUsageService, createWebPushSend, defaultFetchManifest, defaultFetchReleases, defaultProbeCodexExecutable, defaultRunClaudeVersion, defaultUpdaterFs, detectTerminalSupport, enableService, ensureDataDir, extractBearerToken, extractLoginUrl, generateAccessToken, hasEncodedSep, hookAuthFileContent, hookAuthPathFor, hooksSettingsPathFor, installManagedRelease, installService, isCodexProfileClientLifecycle, isLoopbackAddress, isNewerMajorMinor, isOriginAllowed, isPublicForRequest, isPublicPath, isShellPath, isStableVersion, listTmuxSessions, loadConfig, loadServerConfig, looksLikeAssetRequest, managedPaths, mcpConfigPathFor, migrateServiceToLauncher, normalizeOrigin, normalizeProviderAvailability, normalizeRelease, normalizeSessionDefaults, openPushStore, openSessionStore, parseAllowedOrigins, parseAuthStatus, parseClaudeVersion, parseCodexOscNotifications, parseCodexVersion, parseLegacyClaudeArgs, parseNpmLatest, parseProviderOptions, parseReleaseNotes, parseUsage, pathForGate, persistAccessToken, providerPreflightWarning, readActiveVersion, readPreviousVersion, readServiceRecord, registerStatic, relativeWhen, renderLaunchdPlist, renderManagedLauncher, renderSystemdUnit, resetCodexThreadResolutionCoordinatorForTests, resolveAccessToken, resolveCodexExecutable, resolveDataDir, resolveInstallRoot, resolveVapidKeys, restartService, runClaudePreflight, runProviderPreflight, stableReleases, startServer, tmuxSessionName, writeManagedLauncher };
|
|
4265
|
+
export { ADAPTER_CONTRACT_VERSION, API_PATH_DENYLIST, type AdapterCapabilityName, AdapterManifestError, type AdapterManifestV1, type AdapterPackageManifestV1, type AdapterRuntimeV1, type AdapterStateAuthority, type AgentActivity, type AgentProvider, type AgentRecord, type AttachSpawnOptions, type AttentionItem, type AttentionKind, type AttentionState, type AuditActorType, type AuditRecord, type AuditResult, type AuthCheckResult, AuthGate, type AuthGateOptions, type AutomationAction, type AutomationDefinition, type AutomationRun, type AutomationTrigger, BLIND_RELAY_DEFAULT_MAX_BYTES_PER_MINUTE, BLIND_RELAY_DEFAULT_MAX_CONNECTIONS_PER_ROUTE, BLIND_RELAY_DEFAULT_MAX_FRAME_BYTES, BLIND_RELAY_DEFAULT_MAX_MESSAGES_PER_MINUTE, BLIND_RELAY_DEFAULT_MAX_QUEUE_BYTES, BLIND_RELAY_PROTOCOL_VERSION, type Bar, type BlindRelayMetrics, type BlindRelayServer, CHECK_CACHE_MS, CLASSIFIER_TESTED_UP_TO, CLAUDE_LATEST_CACHE_MS, CLAUDE_VERSION_CACHE_MS, CLAUDE_VERSION_TIMEOUT_MS, CODEX_CLASSIFIER_TESTED_UP_TO, CODEX_EXECUTABLE_PROBE_TIMEOUT_MS, CODEX_OSC_MAX_CARRY, CONTROL_IDEMPOTENCY_TTL_MS, type CaptureOptions, type ChangelogEntry, type ClaudeAuthDeps, ClaudeAuthService, type ClaudeAuthStatus, type ClaudeAvailability, type ClaudeLatestDeps, ClaudeLatestService, type ClaudeMetadataRunner, ClaudeMetadataService, type ClaudeModelCatalogItem, type ClaudeSessionOptions, type ClaudeVersionProbe, type CodexAccount, CodexAppServerClient, type CodexAppServerClientOptions, type CodexDeviceLogin, type CodexExecutableDeps, type CodexExecutableProbe, type CodexExecutableResolution, type CodexInstallProvenance, CodexLatestService, type CodexLoginCompletion, type CodexLoginStatus, type CodexMetadataDiagnostics, type CodexMetadataRpc, CodexMetadataService, type CodexMetadataServiceOptions, type CodexModel, type CodexOscParser, type CodexProfileClientLifecycle, type CodexSessionOptions, type CodexSpawnLease, type CodexThreadInventoryEntry, type CodexThreadPersistence, CodexThreadResolver, type CodexThreadResolverOptions, type CodexUsage, type CodexVersionInfo, CommandCenterRevisionConflictError, type CommandCenterStore, type CommandCenterStoreMode, type CommandEvent, type CommandLayoutEnvelope, type ControlStore, type ControlStoreMode, type CreateAutomationInput, type CreateBlindRelayOptions, type CreateClaudeProviderOptions, type CreateCodexProfileClientLifecycleOptions, type CreateCodexProviderOptions, type CreateInstalledAdapterProviderOptions, type CreatePeerInput, type CreatePluginRuntimeOptions, type CreatePushDispatcherDeps, type CreateRelayAccountInput, type CreateServerDeps, type CreateServerResult, type CreateWebPushSendOptions, type CreateWorktreeInput, type CreateWorktreeResult, type CreateWorktreeServiceOptions, type DeviceEnrollment, type DeviceInfo, DevicePairingError, type DeviceRelayIdentity, type DeviceScope, type DeviceStore, type DirEntry, type DirListing, type DirSearchResult, type DurableRelayIdentity, type EnterprisePolicy, type EnterprisePolicyAction, type EnterprisePolicyContext, type EnterprisePolicyDecision, EnterprisePolicyRevisionConflictError, type EnterprisePolicyUpdate, ExtensionError, type ExtensionKind, type ExtensionManager, type ExtensionManifestV1, type ExtensionPolicyMode, type ExtensionTrust, type ExtensionVersionRecord, FETCH_TIMEOUT_MS, type FetchLatest, type FetchManifest, type FetchReleases, FsError, type FsErrorCode, FsService, type FsServiceOptions, type GitHubRelease, type HooksSettingsDocument, type HostRecord, INPUT_LEASE_TTL_MS, type IPty, type IdempotencyRecord, type InputLease, type InputLeaseAcquireResult, type InputLeaseActorType, InputLeaseCoordinator, type InputLeaseCoordinatorOptions, type InputLeaseEvent, type InputLeasePrincipal, type InstallExtensionInput, type InstallServiceContext, type InstallServiceResult, type InstallationKind, type InstalledExtension, type LaunchIntent, type LoopbackRelayHttpOptions, type LoopbackRelayTerminalOptions, type ManagedInstallOptions, type ManagedInstallResult, type ManagedInstallStatus, type ManagedPaths, type MarketplaceEntry, type McpConfigDocument, type ModelWeekBar, OPENAI_CODE_SIGNING_TEAM_ID, type OpenApiBuildOptions, type OpenCommandCenterStoreOptions, type OpenControlStoreOptions, type OpenDeviceStoreOptions, type OpenExtensionManagerOptions, type OpenPeerStoreOptions, type OpenPolicyStoreOptions, type OpenPushStoreOptions, type OpenRelayAccountStoreOptions, type OpenRelayRouteStoreOptions, type OpenSessionStoreOptions, type OpenTeamStoreOptions, type OriginCheckOptions, PAIRING_TTL_MS, PRESENCE_HEARTBEAT_MS, PRESENCE_TTL_MS, type PairingTicket, type PaneStatus, type PeerAction, type PeerConnection, type PeerJsonResponse, type PeerRecord, PeerRequestError, PeerRevisionConflictError, type PeerStatus, type PeerStore, type PeerStoreMode, type PersistedRelayHostConfig, type PluginAuditEvent, type PluginManifestV1, type PluginPermission, type PluginRunInput, type PluginRunResult, type PluginRuntime, PluginRuntimeError, type PolicyStore, type PolicyStoreMode, PresenceCoordinator, type PresenceCoordinatorOptions, type PresenceEvent, type PresenceHeartbeatInput, type PresenceMode, type PresenceRecord, type PresenceTarget, type ProcessLifecycleHandle, type ProcessLifecycleOptions, type ProcessLifecycleTarget, type ProcessSpec, type ProviderAdapterV1, type ProviderAvailability, ProviderError, type ProviderId, ProviderOptionsError, type ProviderProcessContext, ProviderRegistry, type ProviderRuntimeSignal, type ProviderRuntimeSignalParser, type ProviderSessionOptions, type PtySpawn, type PublicRelayRouteRecord, type PushDispatcher, type PushEvent, type PushEventKind, type PushPayload, type PushRecipient, type PushSendFn, type PushStore, type PushSubscriptionRecord, RELAY_CHANNEL_MAX_AGE_MS, RELAY_CHANNEL_MAX_FRAMES, RELAY_HANDSHAKE_MAX_SKEW_MS, RELAY_MAX_PLAINTEXT_BYTES, RELAY_PROTOCOL_VERSION, RELAY_RPC_MAX_BODY_BYTES, RELAY_RPC_MAX_PATH_BYTES, RELAY_WIRE_MAX_ENVELOPE_BYTES, RELAY_WIRE_PROTOCOL_VERSION, RUNNING_BUILD, RUNNING_VERSION, type RateLimitDecision, RateLimiter, type RateLimiterOptions, type RegisterStaticOptions, type RelayAccountPlan, type RelayAccountRecord, RelayAccountRevisionConflictError, type RelayAccountStatus, type RelayAccountStore, type RelayAccountStoreMode, type RelayChannelOptions, RelayCipherState, RelayCryptoError, type RelayCryptoErrorCode, type RelayDeviceProvisioner, type RelayDeviceProvisionerOptions, type RelayDeviceRouteRecord, type RelayDirection, type RelayEncryptedFrame, type RelayEphemeralKeyPair, type RelayFrameKind, type RelayHandshakeHello, type RelayHostConfigInput, type RelayHostConnector, type RelayHostConnectorOptions, type RelayHostMetrics, type RelayHostRuntimeConfig, type RelayHostStatus, type RelayHttpBridge, type RelayHttpHandlers, type RelayHttpOpenRequest, type RelayHttpOpener, type RelayHttpResponseHead, type RelayIdentity, type RelayIdentityStoreOptions, type RelayPairingBootstrap, type RelayPairingPackage, type RelayRole, type RelayRouteRecord, type RelayRouteStore, type RelayRpcMethod, type RelayRpcRequest, type RelayRpcResponse, type RelayStoreMode, type RelayTerminalBridge, type RelayTerminalHandlers, type RelayTerminalOpenRequest, type RelayTerminalOpener, type RelayWireEnvelope, type ReleaseRecord, type RenderLaunchdOptions, type RenderSystemdOptions, type ResolveAccessTokenOptions, type ResolveCodexExecutableOptions, type ResolveCodexThreadOptions, type ResolveVapidKeysOptions, type ReturnTypeOfDescriptors, type RunClaudeVersion, type RunUsage, SEARCH_MAX_DEPTH, SEARCH_MAX_DIRS, SEARCH_MAX_RESULTS, SERVER_PACKAGE, SHELL_PATH_ALLOWLIST, type ServerConfig, type ServerRuntimeConfig, type ServiceRecord, type SessionDefaults, SessionDefaultsConflictError, type SessionFileDirection, type SessionFileKind, type SessionFileStorage, type SessionPlacement, type SessionStore, type StartedBlindRelay, type StoreMode, type StoredExternalSession, type StoredSession, type StoredSessionDefaults, type StoredSessionFile, type StoredStatus, type TeamAuthorizationDecision, type TeamAuthorizationResource, type TeamMember, type TeamMemberKind, type TeamMemberStatus, type TeamPermission, type TeamPrincipalBinding, type TeamPrincipalType, type TeamRecord, TeamRevisionConflictError, type TeamRole, type TeamRoleBinding, type TeamScopeType, type TeamStore, type TeamStoreMode, TerminalManager, type TerminalManagerDeps, type TerminalMeta, TerminalProcess, type TerminalProcessOptions, type TerminalSub, USAGE_CACHE_MS, USAGE_TIMEOUT_MS, type UpdateAction, type UpdateAutomationInput, type UpdatePeerInput, type UpdatePolicyMode, type UpdateRelayAccountInput, type UpdateState, type UpdateStatus, Updater, type UpdaterDeps, type UpdaterFs, type UsageInfo, UsageService, type UsageServiceDeps, type VapidKeys, type VerifiedPeerIdentity, type VersionInfo, WS_TICKET_TTL_MS, type WorkspaceKind, type WorkspaceRecord, WorktreeError, type WorktreeErrorCode, type WorktreeRecord, type WorktreeService, type WsTicketContext, WsTicketStore, type WsTicketStoreOptions, adapterCapabilityNames, assertConfigAllowsStart, buildCodexArgs, buildHooksSettingsDocument, buildMcpConfigDocument, buildOpenApiDocument, buildPushPayload, buildRelayPairingUrl, buildServicePath, capturePane, classifierVersionWarning, classifyCodexPane, classifyPaneStatus, claudePreflightWarning, codexClassifierVersionWarning, compareVersions, computeBuildDrift, computeInstallDrift, createBlindRelayServer, createClaudeAuthService, createClaudeLatestService, createClaudeMetadataRunner, createClaudeProvider, createClaudeVersionProbe, createCodexOscParser, createCodexProfileClientLifecycle, createCodexProvider, createCodexThreadInventory, createCodexThreadPersistence, createInstalledAdapterProvider, createLoopbackRelayHttpOpener, createLoopbackRelayTerminalOpener, createPluginRuntime, createPushDispatcher, createRelayDeviceProvisioner, createRelayHandshakeHello, createRelayHostConnector, createServer, createUpdater, createUsageRunner, createUsageService, createWebPushSend, createWorktreeService, currentAgentIdForSession, decodeRelayWireEnvelope, defaultFetchManifest, defaultFetchReleases, defaultProbeCodexExecutable, defaultRunClaudeVersion, defaultUpdaterFs, defineAdapterManifest, detectTerminalSupport, enableService, encodeRelayWireEnvelope, ensureDataDir, establishRelayChannel, evaluateEnterprisePolicy, extractBearerToken, extractLoginUrl, generateAccessToken, generateRelayAccountCredential, generateRelayCredential, generateRelayEphemeralKeyPair, generateRelayIdentity, hasEncodedSep, hkdfSha256, hookAuthFileContent, hookAuthPathFor, hooksSettingsPathFor, inspectExtensionPackage, installManagedRelease, installProcessLifecycle, installService, isCodexProfileClientLifecycle, isLoopbackAddress, isNewerMajorMinor, isOriginAllowed, isPublicForRequest, isPublicPath, isRelayDirectExecution, isShellPath, isStableVersion, isTeamRole, isTeamScopeType, listTmuxSessions, loadConfig, loadOrCreateRelayIdentity, loadServerConfig, looksLikeAssetRequest, managedPaths, mcpConfigPathFor, migrateServiceToLauncher, normalizeAutomationAction, normalizeAutomationInput, normalizeAutomationTrigger, normalizeCommandCenterLabel, normalizeDeviceName, normalizeDeviceScopes, normalizeOrigin, normalizePeerBaseUrl, normalizeProviderAvailability, normalizeRelayAppUrl, normalizeRelease, normalizeSessionDefaults, openCommandCenterStore, openControlStore, openDeviceStore, openExtensionManager, openPeerStore, openPolicyStore, openPushStore, openRelayAccountStore, openRelayRouteStore, openSessionStore, openTeamStore, parseAllowedOrigins, parseAuthStatus, parseClaudeVersion, parseCodexOscNotifications, parseCodexVersion, parseLegacyClaudeArgs, parseMarketplaceIndex, parseNpmLatest, parseProviderOptions, parseRelayRpcRequest, parseReleaseNotes, parseUsage, pathForGate, persistAccessToken, privacySafeAuditMetadata, providerPreflightWarning, publicAdapterDescriptor, readActiveVersion, readPreviousVersion, readRelayHostConfig, readServiceRecord, registerStatic, relativeWhen, relayAccountCredentialHash, relayAccountCredentialLookup, relayConnectUrl, relayCredentialHash, relayHostConfigPath, relayIdentityFingerprint, relayRpcResponse, removeRelayHostConfig, renderLaunchdPlist, renderManagedLauncher, renderSystemdUnit, requestPeerJson, resetCodexThreadResolutionCoordinatorForTests, resolveAccessToken, resolveCodexExecutable, resolveDataDir, resolveInstallRoot, resolveRelayHostConfig, resolveVapidKeys, restartService, runClaudePreflight, runProviderPreflight, safeProcessErrorSummary, searchMarketplace, stableReleases, startBlindRelay, startServer, teamRolePermissions, tmuxSessionName, validateAdapterManifest, validateAdapterOptionSchema, validateRelayIdentity, verifyPeerConnection, verifyRelayHandshakeHello, writeManagedLauncher, writeRelayHostConfig };
|