import { RelayFileClient, type AccessTokenProvider } from "./client.js"; import { type RelayfileCloudTokenSet, type RelayfileCloudTokenSetupOptions } from "./cloud-token-provider.js"; import type { RelayfileCloudLoginOptions } from "./cloud-login.js"; import { type EnsureMountedWorkspaceInput, type AgentWorkspaceInvite, type AgentWorkspaceInviteOptions, type AgentWorkspaceScopedInviteOptions, type ConnectIntegrationOptions, type ConnectIntegrationResult, type CreateWorkspaceOptions, type JoinWorkspaceOptions, type MountLauncher, type MountedWorkspaceHandle, type MountedWorkspaceStatus, type MountWorkspaceInput, type ReadMountedWorkspaceStatusInput, type RelayfileSetupOptions, type WaitForConnectionOptions, type WorkspaceMountEnv, type WorkspaceMountEnvOptions, type WorkspaceInfo, type WorkspaceIntegrationProvider, type WorkspacePermissions } from "./setup-types.js"; export { RELAYFILE_SDK_VERSION } from "./version.js"; interface JoinWorkspaceResponse { workspaceId?: string; token?: string; relayfileUrl?: string; wsUrl?: string; relaycastApiKey?: string; relaycastBaseUrl?: string; } type ValidatedJoinWorkspaceResponse = Required> & Pick; interface NormalizedJoinWorkspaceOptions { agentName: string; scopes: string[]; permissions?: WorkspacePermissions; } interface ValidatedIntegrationStatusResponse { ready: boolean; state?: string; initialSyncState?: string; } interface CloudRequestOptions { operation: string; method: string; path: string; body?: unknown; signal?: AbortSignal; timeoutMs?: number; tokenProvider?: AccessTokenProvider; } interface WorkspaceHandleOptions { setup: RelayfileSetup; info: WorkspaceInfo; token: string; joinOptions: NormalizedJoinWorkspaceOptions; } export declare class RelayfileSetup { private readonly cloudApiUrl; private readonly accessToken?; private readonly requestTimeoutMs; private readonly retryOptions; static login(options?: RelayfileCloudLoginOptions): Promise; static fromCloudTokens(tokens: RelayfileCloudTokenSet, options?: RelayfileCloudTokenSetupOptions): RelayfileSetup; constructor(options?: RelayfileSetupOptions); createWorkspace(options?: CreateWorkspaceOptions): Promise; joinWorkspace(workspaceId: string, options?: JoinWorkspaceOptions): Promise; mountWorkspace(input: MountWorkspaceInput): Promise; ensureMountedWorkspace(input: EnsureMountedWorkspaceInput): Promise; joinWorkspaceResponse(workspaceId: string, options: NormalizedJoinWorkspaceOptions, overrides?: { tokenProvider?: AccessTokenProvider; }): Promise; requestJson(options: CloudRequestOptions): Promise; getCloudApiUrl(): string; protected getDefaultMountLauncher(): MountLauncher; protected readMountedWorkspaceStatus(input: ReadMountedWorkspaceStatusInput): Promise; private resolveWorkspaceForMount; private createMountSession; } export declare class WorkspaceHandle { readonly info: WorkspaceInfo; readonly workspaceId: string; private readonly _setup; private readonly _joinOptions; private readonly _pendingConnections; private _token; private _tokenIssuedAt; private _client?; private _refreshPromise?; constructor(options: WorkspaceHandleOptions); client(): RelayFileClient; connectIntegration(provider: WorkspaceIntegrationProvider, options?: ConnectIntegrationOptions): Promise; connectNotion(options?: Omit): Promise; waitForConnection(provider: WorkspaceIntegrationProvider, options?: WaitForConnectionOptions): Promise; waitForNotion(options?: WaitForConnectionOptions): Promise; isConnected(provider: WorkspaceIntegrationProvider, connectionId: string): Promise; disconnectIntegration(provider: WorkspaceIntegrationProvider, _connectionId?: string): Promise; /** * Bind an existing Nango connection to this workspace + provider slot * without going through the OAuth re-mint flow. Use this when an operator * has already minted the connection out-of-band (Nango UI, third-party * setup) and just wants Cloud to start routing sync webhooks for it. * * The Cloud-side adopt route validates that the Nango connection exists * upstream and that its end-user/workspace tag matches this workspace. * On success returns the bound `connectionId` and, when a stale prior * row was atomically replaced, a `replacedConnectionId` so callers can * surface that a migration happened. * * Failure modes (HTTP body carries `code`): * - `connection_not_found` (404): Nango doesn't know this connectionId * - `workspace_mismatch` (409): connection belongs to a different * workspace; the body includes `pathWorkspaceId` and * `connectionWorkspaceId` * - `existing_connection_live_or_unknown` (409): a different * connection is already bound here and is either still live * upstream or has indeterminate state; operator must disconnect * first */ adoptIntegration(provider: WorkspaceIntegrationProvider, connectionId: string, options?: { providerConfigKey?: string; }): Promise<{ connectionId: string; replacedConnectionId?: string; }>; /** * List the upstream resources the current connection's OAuth grant * covers. Today only Atlassian-family providers (`jira`, `confluence`) * have meaningful entries here — every Atlassian OAuth grant can cover * multiple sites (cloudIds), and the operator needs to bind one of them * to this workspace via {@link setIntegrationMetadata} before sync can * run. * * Cloud returns 400 `provider_has_no_accessible_resources` for providers * that don't model this concept (currently everything non-Atlassian); * that error surfaces here as a `CloudApiError` so callers can handle * it explicitly rather than treating an empty list as ambiguous. * * @example * ```ts * const sites = await workspace.listAccessibleResources("jira") * if (sites.length > 1) { * const choice = await promptOperator(sites) * await workspace.setIntegrationMetadata("jira", { * cloudId: choice.id, * baseUrl: choice.url * }) * } * ``` */ listAccessibleResources(provider: WorkspaceIntegrationProvider | string): Promise>; /** * Set the operator-controlled metadata namespace on the workspace's * connection for `provider`. The cloud route forwards the payload to * Nango's `setMetadata` (full-replacement, not merge), so the value * passed here becomes the connection's metadata wholesale. Callers that * want merge semantics should read existing metadata first. * * This is the second half of the post-OAuth picker flow for Jira / * Confluence (see {@link listAccessibleResources}), but is intentionally * general-purpose — any provider whose sync requires operator-supplied * connection-level config (e.g. a non-default API host) can use this. * * The cloud side rejects top-level keys that look like Nango plumbing * (`_*`, `connection_*`, `auth_*`, `provider_config_key`, `connection_id`) * with `code: "invalid_metadata"` so a typo can't clobber the connection. * * @example * ```ts * await workspace.setIntegrationMetadata("jira", { * cloudId: "abc-123", * baseUrl: "https://foo.atlassian.net" * }) * ``` */ setIntegrationMetadata(provider: WorkspaceIntegrationProvider | string, metadata: Record): Promise>; getToken(): string; requestJson(options: Omit): Promise; mountEnv(options?: WorkspaceMountEnvOptions): WorkspaceMountEnv; /** * Build an invite that hands a peer agent the calling workspace's existing * JWT and metadata. The invite carries the SAME token this handle holds, * with the SAME scopes — there is no per-invite downscoping. Use * {@link agentInviteScoped} when the receiver should have a strictly * narrower set of scopes than this workspace. */ agentInvite(options?: AgentWorkspaceInviteOptions): AgentWorkspaceInvite; /** * Mint a fresh, downscoped relayfile JWT for a peer agent and return an * invite carrying that token. Round-trips through the cloud join endpoint * (`POST /api/v1/workspaces/{id}/join`), which signs a new JWT whose * `scopes` claim is the requested subset of this workspace's grant. The * cloud API rejects requests that exceed the calling workspace's scopes. * * Prefer this over {@link agentInvite} whenever the receiver should not * inherit the full workspace token's reach (e.g. one agent that only needs * `relayfile:fs:read:/notion/pages/*`). The caller's token is unaffected; * a separate JWT is issued for the invitee. * * @example * const invite = await workspace.agentInviteScoped({ * agentName: 'notion-summarizer', * scopes: ['relayfile:fs:read:/notion/pages/*'], * }) * // invite.relayfileToken is a JWT with scopes=['relayfile:fs:read:/notion/pages/*'] */ agentInviteScoped(options?: AgentWorkspaceScopedInviteOptions): Promise; refreshToken(): Promise; private performRefreshToken; private getOrRefreshToken; private resolveConnectionId; getConnectionStatus(provider: WorkspaceIntegrationProvider, connectionId: string, options?: { signal?: AbortSignal; timeoutMs?: number; }): Promise; private resolveRelaycastBaseUrl; }