@loomcycle/client 1.124.0 → 1.126.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.
@@ -9,6 +9,7 @@
9
9
  * Method-level code in client.ts stays focused on URL + body shape;
10
10
  * the boring fetch + error-translation machinery lives here.
11
11
  */
12
+ import type { TokenProvider } from "./types.js";
12
13
  /**
13
14
  * @internal — not part of @loomcycle/client's public API surface.
14
15
  *
@@ -28,6 +29,13 @@ export interface _FetchContext {
28
29
  authToken: string | undefined;
29
30
  fetchImpl: typeof fetch;
30
31
  }
32
+ /** authorizedFetch wraps a fetch so every request carries the provider's
33
+ * current bearer (replacing whatever Authorization the caller set), and a
34
+ * 401 is retried once with the token `onUnauthorized` hands back — never
35
+ * twice, so a token the server keeps refusing cannot loop. A request whose
36
+ * body is a stream is not retried: the stream was consumed by the first
37
+ * send. */
38
+ export declare function authorizedFetch(inner: typeof fetch, provider: TokenProvider): typeof fetch;
31
39
  /** authHeaders builds the standard request header set: JSON Accept
32
40
  * + Bearer token when the client was constructed with one. The
33
41
  * caller adds Content-Type when posting a body. */
@@ -10,6 +10,36 @@
10
10
  * the boring fetch + error-translation machinery lives here.
11
11
  */
12
12
  import { AclDeniedError, AgentIDInUseError, AgentNotFoundError, AlreadyPausingError, AuthError, BackpressureError, ChannelCursorRegressionError, InsufficientScopeError, InvalidArgumentError, LoomcycleError, NotFoundError, NotPausedError, PauseNotConfiguredError, PerUserQuotaExhaustedError, PromptTooLargeError, RateLimitedError, RequestTooLargeError, SessionBusyError, SessionNotFoundError, SnapshotNotFoundError, SnapshotTooLargeError, SnapshotVersionError, SubstrateToolRefusedError, TokenLimitExceededError, UnavailableError, } from "./errors.js";
13
+ /** authorizedFetch wraps a fetch so every request carries the provider's
14
+ * current bearer (replacing whatever Authorization the caller set), and a
15
+ * 401 is retried once with the token `onUnauthorized` hands back — never
16
+ * twice, so a token the server keeps refusing cannot loop. A request whose
17
+ * body is a stream is not retried: the stream was consumed by the first
18
+ * send. */
19
+ export function authorizedFetch(inner, provider) {
20
+ return async (input, init) => {
21
+ const token = await provider.getToken();
22
+ const first = await inner(input, withBearer(init, token));
23
+ if (first.status !== 401 || !provider.onUnauthorized || !replayableBody(init?.body))
24
+ return first;
25
+ const fresh = await provider.onUnauthorized(token);
26
+ if (!fresh || fresh === token)
27
+ return first;
28
+ await first.body?.cancel().catch(() => undefined);
29
+ return inner(input, withBearer(init, fresh));
30
+ };
31
+ }
32
+ function withBearer(init, token) {
33
+ const headers = new Headers(init?.headers);
34
+ if (token)
35
+ headers.set("Authorization", `Bearer ${token}`);
36
+ else
37
+ headers.delete("Authorization");
38
+ return { ...init, headers };
39
+ }
40
+ function replayableBody(body) {
41
+ return !(typeof ReadableStream !== "undefined" && body instanceof ReadableStream);
42
+ }
13
43
  /** authHeaders builds the standard request header set: JSON Accept
14
44
  * + Bearer token when the client was constructed with one. The
15
45
  * caller adds Content-Type when posting a body. */
package/dist/index.d.ts CHANGED
@@ -27,6 +27,20 @@
27
27
  * mintUserToken(subject, opts?): Promise<MintedUserToken> // delegated token
28
28
  * listUserTokens(subject, opts?): Promise<ListUserTokensResponse>
29
29
  * revokeUserToken(subject, defId, opts?): Promise<{def_id, retired_at}>
30
+ * approveUser(subject, opts?): Promise<UserRecord> // pending → active (RFC FA)
31
+ * listUserIdentities(subject, opts?): Promise<UserIdentitiesResponse>
32
+ * unlinkUserIdentity(subject, gate, opts?): Promise<void>
33
+ *
34
+ * // Sign-in gates + the password gate's management API (RFC FA)
35
+ * listAuthGates(opts?): Promise<AuthGateListResponse> // admin token only
36
+ * createInvite(gate, body, opts?): Promise<CreatedInvite> // one-time link, shown once
37
+ * listInvites(gate, opts?): Promise<AuthInviteListResponse>
38
+ * revokeInvite(gate, inviteId, opts?): Promise<void>
39
+ * createPasswordReset(gate, subject, opts?): Promise<CreatedPasswordReset>
40
+ * removeGateCredentials(gate, subject, opts?): Promise<void>
41
+ * renameGateLogin(gate, subject, login, opts?): Promise<{subject, login}>
42
+ * listGateIdentities(gate, subject, opts?): Promise<GateIdentitiesResponse>
43
+ * getGateTenantStatus(gate, opts?): Promise<GateTenantStatus>
30
44
  * runnableAgents(opts?): Promise<RunnableAgentsResponse> // RFC BY (v1.51.0) — agents I can run
31
45
  * whoami(): Promise<WhoamiResponse> // RFC L principal (v0.17.0)
32
46
  *
@@ -115,6 +129,19 @@
115
129
  * listVolumes(): Promise<PersistentVolumesResponse>
116
130
  * listEphemeralVolumes(): Promise<EphemeralVolumesResponse>
117
131
  *
132
+ * // App clients (RFC FL ClientDef; tenant operator or admin)
133
+ * clientDef(input): Promise<unknown> // POST /v1/_clientdef
134
+ * createClientDef / updateClientDef(name, client, opts?): Promise<ClientDefRecord>
135
+ * getClientDef({name | def_id}): Promise<AppClientEntry>
136
+ * listClientDefs(opts?): Promise<ClientDefListResponse>
137
+ * retireClientDef(name): Promise<ClientDefRetireResult>
138
+ * verifyClientDef(name, {contentSha256}?): Promise<ClientDefVerifyResult>
139
+ * listClientDefNames(opts?): Promise<ClientDefNamesResponse> // GET /v1/_clientdef/names
140
+ *
141
+ * // App sign-in (RFC FL) — also standalone as `new LoomcycleOAuth(...)`
142
+ * oauth: LoomcycleOAuth // beginAuthorize / completeAuthorize / refresh / revoke / discover
143
+ * new LoomcycleClient({ tokenProvider: new OAuthTokenProvider(...) }) // refreshes on its own
144
+ *
118
145
  * // Agent Teams (RFC AP — TeamDef substrate; tenant-confined)
119
146
  * listTeams(): Promise<ListTeamsResponse>
120
147
  * renderTeamDiagram(name, opts?): Promise<TeamDiagram>
@@ -187,5 +214,7 @@ export { verifyLoomcycleSignature, verifyLoomcycleDelivery } from "./signature.j
187
214
  export type { VerifySignatureOptions, VerifiedDelivery } from "./signature.js";
188
215
  export { ClientToolHost, clientToolsURL, CLIENT_TOOL_SUBPROTOCOL } from "./client-tools.js";
189
216
  export type { ClientToolSchema, ClientToolInvocation, ConnectClientToolsOptions, WebSocketLike, WebSocketCtor, } from "./client-tools.js";
190
- export type { AgentEvent, ClientOptions, ContinueOptions, EventType, HostWidening, ImageMediaType, ParentContext, PromptContent, PromptSegment, RetryInfo, RunOptions, RunOverrideOptions, SamplingOptions, CompactionOptions, ContextOptions, ToolUse, Usage, CallTiming, Agent, AgentStatus, AwaitedState, AgentUsage, RunResult, RunSpec, RunSpecTeam, ConfiguredRun, ConfiguredRunPatch, ToolChoiceOptions, OutputFormatOptions, CancelAgentResult, ListAgentsResponse, ListUserAgentsOptions, AgentList, WalkRunsPage, RunBatchOptions, RunBatchResult, SpawnRunResult, CompactRunResult, RunTreeDeletion, RunTreeNotReached, DirectoryBudget, DirectoryInspection, DirectoryTenant, DirectoryUser, ErasureAccess, ErasureReport, ErasureResidue, ErasureResult, ErasureTier, ErasureTokenRef, CancelTurnResult, ReviewRunResult, ReplaySessionResult, TranscriptEvent, TranscriptResponse, HealthResponse, ListUsersResponse, UserSummary, UserRecord, CreateUserBody, UpdateUserBody, MintedUserToken, TokenRestrictions, UserTokenMeta, ListUserTokensResponse, RunnableAgent, RunnableAgentsResponse, WhoamiResponse, WhoamiEffective, WhoamiAuth, PauseResult, RetentionOverride, ResumeResult, RuntimeStateResponse, RuntimeStateStatus, ResolverMatrix, ResolverModelStatus, ResolverProviderAvailability, CreateSnapshotOptions, SnapshotCreateResponse, SnapshotDescriptor, SnapshotEnvelope, SnapshotListResponse, SnapshotRestoreResponse, MemoryEntriesResponse, MemoryEntry, MemoryEntryResponse, MemoryScopeIDsResponse, MemoryScopeIDSummary, MemoryScopeKind, MemoryScopesResponse, MemorySearchDocumentFilter, MemorySearchInput, MemorySource, MemoryWhen, MemoryTimeFilter, MemorySearchEntry, MemorySearchResponse, MemoryEmbedModelStats, MemoryEmbedStatsResponse, MemoryReembedConfigured, MemoryReembedResponse, MemoryBackfillResponse, MemoryPurgeResponse, InterruptListResponse, InterruptRow, InterruptStatus, ResolveInterruptOptions, ChannelHookCall, ChannelHookResult, HookFailMode, HookPhase, HookToolCall, HookToolResult, PostHookCall, PostHookResult, PreHookCall, PreHookResult, SubstrateToolInput, SubstrateToolResponse, TeamNameSummary, ListTeamsResponse, TeamDiagram, CreatedTeam, PromotedTeam, RetiredTeam, TeamDefDetail, TeamVerification, TeamDraft, TeamDraftVerification, TeamIssue, TeamIssueKind, TeamVersion, TeamVersionList, TeamBreakpoints, TeamRunDetached, TeamRunResult, TeamRunTarget, CreateTeamOptions, ForkTeamOptions, DefNameSummary, DefNamesResponse, OperatorTokenDefNameSummary, OperatorTokenDefNamesResponse, ScheduleListEntry, ScheduleListResponse, ScheduleActiveRun, ScheduleStateView, ScheduleRunNowResult, SchedulePauseResult, ModelAlias, ModelAliasesResponse, RoutingResponse, RoutingUserTier, RoutingTier, RoutingCandidate, RoutingThroughput, RoutingProvider, SearchRoutingProvider, RoutingEmbedder, RoutingDecision, RoutingDecisionModel, ProviderModelsResponse, TeamRunStep, TeamDecisionHandler, TeamDecisionQuestion, TeamDecisionAnswer, PathToolInput, PathToolResponse, DocumentToolInput, DocumentToolResponse, DocumentSearchFilter, DocumentSearchHit, DocumentSearchResult, DocumentRelatedResult, HistoryToolInput, HistoryToolResponse, EvaluationEmitterRole, EvaluationSubmitInput, EvaluationGetInput, EvaluationListForRunInput, EvaluationListForDefInput, EvaluationAggregateInput, EvaluationInput, EvaluationSubmitResult, EvaluationRecord, EvaluationListForRunResult, EvaluationListForDefResult, EvaluationScoreStats, EvaluationAggregate, VolumeMode, PersistentVolumeEntry, PersistentVolumesResponse, EphemeralVolumeEntry, EphemeralVolumesResponse, SystemPromptPayload, UserInputPayload, ChannelDescriptor, ListChannelsResponse, RunStateEvent, RunStateStreamClose, RunStateStreamItem, RunStateStreamOpen, StreamUserRunStatesOptions, ChangeFeedError, ChangeFeedFrame, ChangeFeedStatus, EmbedderHealth, MemoryChange, MemoryChangeScope, MemoryChangeType, StreamChangesOptions, AckChannelOptions, ChannelAckResult, ChannelMessageItem, ChannelPeekResult, ListTeamChannelsOptions, PeekTeamChannelOptions, ReleaseTeamChannelOptions, TeamChannelReleaseResult, TeamChannelDeclaredIn, TeamChannelDescriptor, TeamChannelPeekResult, TeamChannelsResult, ChannelPublishResult, ChannelPurgeResult, ChannelReleaseResult, ChannelScope, ChannelSubscribeResult, PeekChannelOptions, PublishChannelOptions, SubscribeChannelOptions, AwaitChannelsOptions, BroadcastChannelsOptions, ChannelAwaitEntry, ChannelAwaitMode, ChannelAwaitResult, ChannelBroadcastEntry, ChannelBroadcastResult, CreateChannelOptions, ReleaseChannelOptions, UpdateChannelOptions, SetMemoryEntryOptions, SetMemoryEntryResponse, AgentDefRowResponse, AgentDefVerifyResult, SkillDefVerifyResult, EnsureMcpServerOptions, EnsureMcpServerResult, MCPServerDefRowResponse, MCPServerDefVerifyResult, AgentDefOverlay, AgentRouting, AgentChannelACL, AgentInterruptionACL, AgentDecision, MemoryRerank, AgentSampling, AgentCompaction, AgentTranscription, AgentContext, TierCandidate, CoreBlock, HookEvent, InlineWebhook, HookEntry, EventHooks, ToolEntry, ToolHooksByTool, EnsureCodeAgentOptions, EnsureCodeAgentResult, CreateDefOptions, ForkDefOptions, EnsureHookDefOptions, EnsureHookDefResult, HookDefBody, HookDefForkOverlay, HookDefInput, HookDefMatch, HookDefOverlay, HookDefRowResponse, HookDefVerifyResult, ScheduleDefInput, ScheduleDefOverlay, ScheduleDefRowResponse, ScheduledRunHook, ScheduledRunPromptContent, ScheduledRunPromptSegment, WebhookDefAuth, WebhookDefFilter, WebhookDefInput, WebhookDefOverlay, WebhookDefRateLimit, WebhookDefRowResponse, WebhookDefDeliveries, WebhookDefSyncResponse, LibraryAgentDefinition, LibraryEntry, LibraryListResponse, LibraryMcpServerDefinition, LibrarySkillDefinition, LLMChatContent, LLMChatMessage, LLMChatOptions, LLMChatResponse, LLMChatStreamDelta, LLMChatStreamItem, LLMChatToolCall, LLMChatUsage, LLMTool, LLMEmbeddingItem, LLMEmbeddingsOptions, LLMEmbeddingsResponse, LLMEmbeddingsUsage, UsageDimension, UsageAggregate, UsageReportResponse, CapabilityInertInfo, LimitInfo, FileCapturedInfo, TranscriptionInfo, AdmissionInfo, ErrorInfo, CallFormat, CallRef, HookDecisionInfo, TeamDecisionInfo, OverrideInfo, FallbackInfo, InterruptionEventInfo, SpawnChildInfo, TurnCancelledInfo, ChannelEventInfo, ContextCompactionInfo, ContextRecapInfo, ContextStateInfo, ContextExhaustedInfo, ContextTierVerdict, ContextDistillDeclinedInfo, EffectiveConfigResponse, EffectiveConfigSource, EffectiveValue, InertContextSetting, AgentOverridableResponse, OverridableField, OverrideLockReason, RetuneRunResponse, RunConfigRecord, SubagentHoldInfo, RunConfigResponse, RunPromptResponse, RunPromptSnapshot, PromptBlock, TokenLimit, TokenLimitsResponse, ConfigResponse, ConfigProvider, ConfigModel, ConfigSearch, ConfigInstance, SetTokenLimitRequest, CredentialScope, CredentialMeta, CredentialListResponse, CryptoKeyVersion, CryptoKeyExport, CryptoKeyType, CryptoKeyEncoding, CryptoKeyBackend, CryptoKeyExternal, CryptoOp, CryptoRequestBase, CryptoKeyRef, CryptoEncryptRequest, CryptoDecryptRequest, CryptoRewrapRequest, CryptoMacRequest, CryptoVerifyMacRequest, CryptoSignRequest, CryptoVerifyRequest, CryptoPublicKeyRequest, CryptoTotpRequest, CryptoHashRequest, CryptoRandomRequest, CryptoHashPasswordRequest, CryptoVerifyPasswordRequest, CryptoRequest, CryptoEncryptResult, CryptoDecryptResult, CryptoRewrapResult, CryptoMacResult, CryptoVerifyResult, CryptoSignResult, CryptoPublicJWK, CryptoPublicKeyResult, CryptoTotpResult, CryptoHashResult, CryptoRandomResult, CryptoHashPasswordResult, CryptoVerifyPasswordResult, CryptoResultByOp, CryptoResult, DecideRequest, DecideResponse, DecisionQuestion, DecisionChoiceQuestion, DecisionNoulQuestion, DecisionScoreQuestion, DecisionAnswer, DecisionChoiceAnswer, DecisionNoulAnswer, DecisionScoreAnswer, DecisionModel, DecisionModelsResponse, AclMode, AclSource, AclEffect, AclSubjectKind, AclCondition, AclRule, AclList, AclDefRow, AclDefListResponse, AclDefNamesResponse, AclValidateResult, AclCatalogType, AclCatalog, AclDefOp, AclDefInput, GroupRow, GroupMemberKind, GroupMember, GroupListResponse, GroupDetail, GroupEffective, CreateGroupBody, GroupMemberChange, AclBinding, AclBindingListResponse, CreateAclBindingBody, AuthzReason, AuthzDecision, AuthzRequestContext, AuthzEvaluationRequest, AuthzEvaluationsSemantic, AuthzEvaluationsRequest, AuthzEvaluationsResponse, AuthzTrace, AuthzAppliedBinding, AuthzExplainResponse, AuthzDraftBinding, AuthzSimulateRequest, AuthzSimulateResult, AuthzSimulateResponse, } from "./types.js";
191
- export { AclDeniedError, AgentIDInUseError, AgentNotFoundError, AlreadyPausingError, AuthError, BackpressureError, NotFoundError, InsufficientScopeError, InvalidArgumentError, ChannelCursorRegressionError, LoomcycleError, NotPausedError, PauseNotConfiguredError, PerUserQuotaExhaustedError, PromptTooLargeError, RateLimitedError, RequestTooLargeError, SessionBusyError, SessionNotFoundError, SnapshotNotFoundError, SnapshotTooLargeError, SnapshotVersionError, SubstrateToolRefusedError, TokenLimitExceededError, UnavailableError, } from "./errors.js";
217
+ export { LoomcycleOAuth, OAuthTokenProvider, parseAuthorizeResponse, pkceChallenge } from "./oauth.js";
218
+ export type { LoomcycleOAuthOptions, OAuthTokenProviderOptions } from "./oauth.js";
219
+ export type { AgentEvent, ClientOptions, ContinueOptions, EventType, HostWidening, ImageMediaType, ParentContext, PromptContent, PromptSegment, RetryInfo, RunOptions, RunOverrideOptions, SamplingOptions, CompactionOptions, ContextOptions, ToolUse, Usage, CallTiming, Agent, AgentStatus, AwaitedState, AgentUsage, RunResult, RunSpec, RunSpecTeam, ConfiguredRun, ConfiguredRunPatch, ToolChoiceOptions, OutputFormatOptions, CancelAgentResult, ListAgentsResponse, ListUserAgentsOptions, AgentList, WalkRunsPage, RunBatchOptions, RunBatchResult, SpawnRunResult, CompactRunResult, RunTreeDeletion, RunTreeNotReached, DirectoryBudget, DirectoryInspection, DirectoryTenant, DirectoryUser, ErasureAccess, ErasureReport, ErasureResidue, ErasureResult, ErasureTier, ErasureTokenRef, CancelTurnResult, ReviewRunResult, ReplaySessionResult, TranscriptEvent, TranscriptResponse, HealthResponse, ListUsersResponse, UserSummary, UserStatus, UserRecord, CreateUserBody, UpdateUserBody, MintedUserToken, TokenRestrictions, UserTokenMeta, ListUserTokensResponse, UserIdentity, UserIdentitiesResponse, AuthGateKind, AuthGate, AuthGateKey, AuthGateRemoval, AuthGateProbe, AuthGateListResponse, CreateInviteBody, CreatedInvite, AuthInviteState, AuthInvite, AuthInviteListResponse, CreatedPasswordReset, GateIdentity, GateIdentitiesResponse, GateTenantStatus, RunnableAgent, RunnableAgentsResponse, WhoamiResponse, WhoamiEffective, WhoamiAuth, PauseResult, RetentionOverride, ResumeResult, RuntimeStateResponse, RuntimeStateStatus, ResolverMatrix, ResolverModelStatus, ResolverProviderAvailability, CreateSnapshotOptions, SnapshotCreateResponse, SnapshotDescriptor, SnapshotEnvelope, SnapshotListResponse, SnapshotRestoreResponse, MemoryEntriesResponse, MemoryEntry, MemoryEntryResponse, MemoryScopeIDsResponse, MemoryScopeIDSummary, MemoryScopeKind, MemoryScopesResponse, MemorySearchDocumentFilter, MemorySearchInput, MemorySource, MemoryWhen, MemoryTimeFilter, MemorySearchEntry, MemorySearchResponse, MemoryEmbedModelStats, MemoryEmbedStatsResponse, MemoryReembedConfigured, MemoryReembedResponse, MemoryBackfillResponse, MemoryPurgeResponse, InterruptListResponse, InterruptRow, InterruptStatus, ResolveInterruptOptions, ChannelHookCall, ChannelHookResult, HookFailMode, HookPhase, HookToolCall, HookToolResult, PostHookCall, PostHookResult, PreHookCall, PreHookResult, SubstrateToolInput, SubstrateToolResponse, TeamNameSummary, ListTeamsResponse, TeamDiagram, CreatedTeam, PromotedTeam, RetiredTeam, TeamDefDetail, TeamVerification, TeamDraft, TeamDraftVerification, TeamIssue, TeamIssueKind, TeamVersion, TeamVersionList, TeamBreakpoints, TeamRunDetached, TeamRunResult, TeamRunTarget, CreateTeamOptions, ForkTeamOptions, DefNameSummary, DefNamesResponse, OperatorTokenDefNameSummary, OperatorTokenDefNamesResponse, ScheduleListEntry, ScheduleListResponse, ScheduleActiveRun, ScheduleStateView, ScheduleRunNowResult, SchedulePauseResult, ModelAlias, ModelAliasesResponse, RoutingResponse, RoutingUserTier, RoutingTier, RoutingCandidate, RoutingThroughput, RoutingProvider, SearchRoutingProvider, RoutingEmbedder, RoutingDecision, RoutingDecisionModel, ProviderModelsResponse, TeamRunStep, TeamDecisionHandler, TeamDecisionQuestion, TeamDecisionAnswer, PathToolInput, PathToolResponse, DocumentToolInput, DocumentToolResponse, DocumentSearchFilter, DocumentSearchHit, DocumentSearchResult, DocumentRelatedResult, HistoryToolInput, HistoryToolResponse, EvaluationEmitterRole, EvaluationSubmitInput, EvaluationGetInput, EvaluationListForRunInput, EvaluationListForDefInput, EvaluationAggregateInput, EvaluationInput, EvaluationSubmitResult, EvaluationRecord, EvaluationListForRunResult, EvaluationListForDefResult, EvaluationScoreStats, EvaluationAggregate, VolumeMode, PersistentVolumeEntry, PersistentVolumesResponse, EphemeralVolumeEntry, EphemeralVolumesResponse, SystemPromptPayload, UserInputPayload, ChannelDescriptor, ListChannelsResponse, RunStateEvent, RunStateStreamClose, RunStateStreamItem, RunStateStreamOpen, StreamUserRunStatesOptions, ChangeFeedError, ChangeFeedFrame, ChangeFeedStatus, EmbedderHealth, MemoryChange, MemoryChangeScope, MemoryChangeType, StreamChangesOptions, AckChannelOptions, ChannelAckResult, ChannelMessageItem, ChannelPeekResult, ListTeamChannelsOptions, PeekTeamChannelOptions, ReleaseTeamChannelOptions, TeamChannelReleaseResult, TeamChannelDeclaredIn, TeamChannelDescriptor, TeamChannelPeekResult, TeamChannelsResult, ChannelPublishResult, ChannelPurgeResult, ChannelReleaseResult, ChannelScope, ChannelSubscribeResult, PeekChannelOptions, PublishChannelOptions, SubscribeChannelOptions, AwaitChannelsOptions, BroadcastChannelsOptions, ChannelAwaitEntry, ChannelAwaitMode, ChannelAwaitResult, ChannelBroadcastEntry, ChannelBroadcastResult, CreateChannelOptions, ReleaseChannelOptions, UpdateChannelOptions, SetMemoryEntryOptions, SetMemoryEntryResponse, AgentDefRowResponse, AgentDefVerifyResult, SkillDefVerifyResult, EnsureMcpServerOptions, EnsureMcpServerResult, MCPServerDefRowResponse, MCPServerDefVerifyResult, AgentDefOverlay, AgentRouting, AgentChannelACL, AgentInterruptionACL, AgentDecision, MemoryRerank, AgentSampling, AgentCompaction, AgentTranscription, AgentSpeech, AgentContext, TierCandidate, CoreBlock, HookEvent, InlineWebhook, HookEntry, EventHooks, ToolEntry, ToolHooksByTool, EnsureCodeAgentOptions, EnsureCodeAgentResult, CreateDefOptions, ForkDefOptions, EnsureHookDefOptions, EnsureHookDefResult, HookDefBody, HookDefForkOverlay, HookDefInput, HookDefMatch, HookDefOverlay, HookDefRowResponse, HookDefVerifyResult, ScheduleDefInput, ScheduleDefOverlay, ScheduleDefRowResponse, ScheduledRunHook, ScheduledRunPromptContent, ScheduledRunPromptSegment, WebhookDefAuth, WebhookDefFilter, WebhookDefInput, WebhookDefOverlay, WebhookDefRateLimit, WebhookDefRowResponse, WebhookDefDeliveries, WebhookDefSyncResponse, LibraryAgentDefinition, LibraryEntry, LibraryListResponse, LibraryMcpServerDefinition, LibrarySkillDefinition, LLMChatContent, LLMChatMessage, LLMChatOptions, LLMChatResponse, LLMChatStreamDelta, LLMChatStreamItem, LLMChatToolCall, LLMChatUsage, LLMTool, LLMEmbeddingItem, LLMEmbeddingsOptions, LLMEmbeddingsResponse, LLMEmbeddingsUsage, UsageDimension, UsageBucket, UsageAggregate, UsageReportResponse, CapabilityInertInfo, LimitInfo, FileCapturedInfo, TranscriptionInfo, AdmissionInfo, ErrorInfo, CallFormat, CallRef, HookDecisionInfo, TeamDecisionInfo, OverrideInfo, FallbackInfo, InterruptionEventInfo, SpawnChildInfo, TurnCancelledInfo, ChannelEventInfo, ContextCompactionInfo, ContextRecapInfo, ContextStateInfo, ContextExhaustedInfo, ContextTierVerdict, ContextDistillDeclinedInfo, EffectiveConfigResponse, RunFileInput, RunFileImportSource, RunFileImportHeading, RunInboxDownload, EffectiveConfigSource, EffectiveValue, InertContextSetting, AgentOverridableResponse, OverridableField, OverrideLockReason, RetuneRunResponse, RunConfigRecord, SubagentHoldInfo, RunConfigResponse, RunPromptResponse, RunPromptSnapshot, PromptBlock, TokenLimit, TokenLimitsResponse, ConfigResponse, ConfigProvider, ConfigModel, ConfigSearch, ConfigInstance, SetTokenLimitRequest, CredentialScope, CredentialMeta, CredentialListResponse, CryptoKeyVersion, CryptoKeyExport, CryptoKeyType, CryptoKeyEncoding, CryptoKeyBackend, CryptoKeyExternal, CryptoOp, CryptoRequestBase, CryptoKeyRef, CryptoEncryptRequest, CryptoDecryptRequest, CryptoRewrapRequest, CryptoMacRequest, CryptoVerifyMacRequest, CryptoSignRequest, CryptoVerifyRequest, CryptoPublicKeyRequest, CryptoTotpRequest, CryptoHashRequest, CryptoRandomRequest, CryptoHashPasswordRequest, CryptoVerifyPasswordRequest, CryptoRequest, CryptoEncryptResult, CryptoDecryptResult, CryptoRewrapResult, CryptoMacResult, CryptoVerifyResult, CryptoSignResult, CryptoPublicJWK, CryptoPublicKeyResult, CryptoTotpResult, CryptoHashResult, CryptoRandomResult, CryptoHashPasswordResult, CryptoVerifyPasswordResult, CryptoResultByOp, CryptoResult, DecideRequest, DecideResponse, DecisionQuestion, DecisionChoiceQuestion, DecisionNoulQuestion, DecisionScoreQuestion, DecisionAnswer, DecisionChoiceAnswer, DecisionNoulAnswer, DecisionScoreAnswer, DecisionModel, DecisionModelsResponse, AclMode, AclSource, AclEffect, AclSubjectKind, AclCondition, AclRule, AclList, AclDefRow, AclDefListResponse, AclDefNamesResponse, AclValidateResult, AclCatalogType, AclCatalog, AclDefOp, AclDefInput, GroupRow, GroupMemberKind, GroupMember, GroupListResponse, GroupDetail, GroupEffective, CreateGroupBody, GroupMemberChange, AclBinding, AclBindingListResponse, CreateAclBindingBody, AuthzReason, AuthzDecision, AuthzRequestContext, AuthzEvaluationRequest, AuthzEvaluationsSemantic, AuthzEvaluationsRequest, AuthzEvaluationsResponse, AuthzTrace, AuthzAppliedBinding, AuthzExplainResponse, AuthzDraftBinding, AuthzSimulateRequest, AuthzSimulateResult, AuthzSimulateResponse, OAuthServerMetadata, OAuthTokenResponse, OAuthTokenSet, BeginAuthorizeOptions, AuthorizeRequest, AuthorizeResponseParams, CompleteAuthorizeOptions, RefreshTokenOptions, RevokeTokenOptions, TokenProvider, AppClientRefresh, AppClientConfig, ClientDefInput, ClientDefRecord, ConfigAppClient, AppClientEntry, ClientDefListResponse, ClientDefVerifyResult, ClientDefRetireResult, ClientDefNameSummary, ClientDefNamesResponse, DeviceLoginPrompt, DeviceLoginOptions, DeviceLoginResult, } from "./types.js";
220
+ export { AclDeniedError, AgentIDInUseError, AgentNotFoundError, AlreadyPausingError, AuthError, BackpressureError, DeviceLoginError, NotFoundError, InsufficientScopeError, InvalidArgumentError, ChannelCursorRegressionError, LoomcycleError, NotPausedError, OAuthError, PauseNotConfiguredError, PerUserQuotaExhaustedError, PromptTooLargeError, RateLimitedError, RequestTooLargeError, SessionBusyError, SessionNotFoundError, SnapshotNotFoundError, SnapshotTooLargeError, SnapshotVersionError, SubstrateToolRefusedError, TokenLimitExceededError, UnavailableError, } from "./errors.js";
package/dist/index.js CHANGED
@@ -27,6 +27,20 @@
27
27
  * mintUserToken(subject, opts?): Promise<MintedUserToken> // delegated token
28
28
  * listUserTokens(subject, opts?): Promise<ListUserTokensResponse>
29
29
  * revokeUserToken(subject, defId, opts?): Promise<{def_id, retired_at}>
30
+ * approveUser(subject, opts?): Promise<UserRecord> // pending → active (RFC FA)
31
+ * listUserIdentities(subject, opts?): Promise<UserIdentitiesResponse>
32
+ * unlinkUserIdentity(subject, gate, opts?): Promise<void>
33
+ *
34
+ * // Sign-in gates + the password gate's management API (RFC FA)
35
+ * listAuthGates(opts?): Promise<AuthGateListResponse> // admin token only
36
+ * createInvite(gate, body, opts?): Promise<CreatedInvite> // one-time link, shown once
37
+ * listInvites(gate, opts?): Promise<AuthInviteListResponse>
38
+ * revokeInvite(gate, inviteId, opts?): Promise<void>
39
+ * createPasswordReset(gate, subject, opts?): Promise<CreatedPasswordReset>
40
+ * removeGateCredentials(gate, subject, opts?): Promise<void>
41
+ * renameGateLogin(gate, subject, login, opts?): Promise<{subject, login}>
42
+ * listGateIdentities(gate, subject, opts?): Promise<GateIdentitiesResponse>
43
+ * getGateTenantStatus(gate, opts?): Promise<GateTenantStatus>
30
44
  * runnableAgents(opts?): Promise<RunnableAgentsResponse> // RFC BY (v1.51.0) — agents I can run
31
45
  * whoami(): Promise<WhoamiResponse> // RFC L principal (v0.17.0)
32
46
  *
@@ -115,6 +129,19 @@
115
129
  * listVolumes(): Promise<PersistentVolumesResponse>
116
130
  * listEphemeralVolumes(): Promise<EphemeralVolumesResponse>
117
131
  *
132
+ * // App clients (RFC FL ClientDef; tenant operator or admin)
133
+ * clientDef(input): Promise<unknown> // POST /v1/_clientdef
134
+ * createClientDef / updateClientDef(name, client, opts?): Promise<ClientDefRecord>
135
+ * getClientDef({name | def_id}): Promise<AppClientEntry>
136
+ * listClientDefs(opts?): Promise<ClientDefListResponse>
137
+ * retireClientDef(name): Promise<ClientDefRetireResult>
138
+ * verifyClientDef(name, {contentSha256}?): Promise<ClientDefVerifyResult>
139
+ * listClientDefNames(opts?): Promise<ClientDefNamesResponse> // GET /v1/_clientdef/names
140
+ *
141
+ * // App sign-in (RFC FL) — also standalone as `new LoomcycleOAuth(...)`
142
+ * oauth: LoomcycleOAuth // beginAuthorize / completeAuthorize / refresh / revoke / discover
143
+ * new LoomcycleClient({ tokenProvider: new OAuthTokenProvider(...) }) // refreshes on its own
144
+ *
118
145
  * // Agent Teams (RFC AP — TeamDef substrate; tenant-confined)
119
146
  * listTeams(): Promise<ListTeamsResponse>
120
147
  * renderTeamDiagram(name, opts?): Promise<TeamDiagram>
@@ -184,4 +211,5 @@ export { LoomcycleClient } from "./client.js";
184
211
  export { InteractiveSession } from "./interactive.js";
185
212
  export { verifyLoomcycleSignature, verifyLoomcycleDelivery } from "./signature.js";
186
213
  export { ClientToolHost, clientToolsURL, CLIENT_TOOL_SUBPROTOCOL } from "./client-tools.js";
187
- export { AclDeniedError, AgentIDInUseError, AgentNotFoundError, AlreadyPausingError, AuthError, BackpressureError, NotFoundError, InsufficientScopeError, InvalidArgumentError, ChannelCursorRegressionError, LoomcycleError, NotPausedError, PauseNotConfiguredError, PerUserQuotaExhaustedError, PromptTooLargeError, RateLimitedError, RequestTooLargeError, SessionBusyError, SessionNotFoundError, SnapshotNotFoundError, SnapshotTooLargeError, SnapshotVersionError, SubstrateToolRefusedError, TokenLimitExceededError, UnavailableError, } from "./errors.js";
214
+ export { LoomcycleOAuth, OAuthTokenProvider, parseAuthorizeResponse, pkceChallenge } from "./oauth.js";
215
+ export { AclDeniedError, AgentIDInUseError, AgentNotFoundError, AlreadyPausingError, AuthError, BackpressureError, DeviceLoginError, NotFoundError, InsufficientScopeError, InvalidArgumentError, ChannelCursorRegressionError, LoomcycleError, NotPausedError, OAuthError, PauseNotConfiguredError, PerUserQuotaExhaustedError, PromptTooLargeError, RateLimitedError, RequestTooLargeError, SessionBusyError, SessionNotFoundError, SnapshotNotFoundError, SnapshotTooLargeError, SnapshotVersionError, SubstrateToolRefusedError, TokenLimitExceededError, UnavailableError, } from "./errors.js";
@@ -0,0 +1,131 @@
1
+ import { OAuthError } from "./errors.js";
2
+ import type { AuthorizeRequest, AuthorizeResponseParams, BeginAuthorizeOptions, CompleteAuthorizeOptions, OAuthServerMetadata, OAuthTokenSet, RefreshTokenOptions, RevokeTokenOptions, TokenProvider } from "./types.js";
3
+ /** Options for {@link LoomcycleOAuth}. */
4
+ export interface LoomcycleOAuthOptions {
5
+ /** loomcycle's address as the person's browser reaches it, e.g.
6
+ * `https://loom.example.com`. Defaults to http://127.0.0.1:8787. */
7
+ baseUrl?: string;
8
+ /** Custom fetch (tests, Tauri's HTTP plugin); defaults to global `fetch`. */
9
+ fetch?: typeof fetch;
10
+ /** Web Crypto; defaults to `globalThis.crypto` (browsers, Node 19+). On
11
+ * Node 18 pass `require("node:crypto").webcrypto`. */
12
+ crypto?: Crypto;
13
+ /** The server's issuer identifier, when the app knows it. A redirect's
14
+ * `iss` is compared with it; without it, the issuer is discovered from
15
+ * the server's metadata the first time a redirect carries `iss`. */
16
+ issuer?: string;
17
+ }
18
+ /**
19
+ * The app sign-in helper. Construct one per loomcycle server.
20
+ *
21
+ * ```ts
22
+ * const oauth = new LoomcycleOAuth({ baseUrl: "https://loom.example.com" });
23
+ * // 1. Start: keep verifier + state in session storage, then navigate.
24
+ * const req = await oauth.beginAuthorize({ clientId: "loomboard", redirectUri });
25
+ * sessionStorage.setItem("lc_pkce", JSON.stringify({ verifier: req.verifier, state: req.state }));
26
+ * location.assign(req.url);
27
+ * // 2. Back on redirectUri:
28
+ * const saved = JSON.parse(sessionStorage.getItem("lc_pkce")!);
29
+ * const tokens = await oauth.completeAuthorize({
30
+ * ...parseAuthorizeResponse(location.href),
31
+ * expectedState: saved.state, verifier: saved.verifier, clientId: "loomboard", redirectUri,
32
+ * });
33
+ * ```
34
+ */
35
+ export declare class LoomcycleOAuth {
36
+ private readonly baseUrl;
37
+ private readonly fetchImpl;
38
+ private readonly cryptoImpl?;
39
+ private readonly issuer?;
40
+ private metadata?;
41
+ constructor(opts?: LoomcycleOAuthOptions);
42
+ /** Start a sign-in: a fresh PKCE verifier, its S256 challenge, a state,
43
+ * and the authorize URL to send the person to. Nothing is sent to the
44
+ * server. */
45
+ beginAuthorize(opts: BeginAuthorizeOptions): Promise<AuthorizeRequest>;
46
+ /** Finish a sign-in from the redirect's parameters (see
47
+ * {@link parseAuthorizeResponse}). In order: the `state` must be the one
48
+ * this sign-in sent, an `iss` must name this server (RFC 9207), an
49
+ * `error` is thrown as an {@link OAuthError}, and only then is the code
50
+ * exchanged. */
51
+ completeAuthorize(opts: CompleteAuthorizeOptions): Promise<OAuthTokenSet>;
52
+ /** Trade a refresh token for a new token set. The refresh token is spent:
53
+ * persist the returned one before anything else uses the old. A spent
54
+ * token presented again ends the whole sign-in. */
55
+ refresh(opts: RefreshTokenOptions): Promise<OAuthTokenSet>;
56
+ /** Sign out (RFC 7009): a refresh token ends the whole sign-in, an access
57
+ * token ends that token. The server answers the same for a token it does
58
+ * not know, so this resolves unless the request itself failed. */
59
+ revoke(opts: RevokeTokenOptions): Promise<void>;
60
+ /** The server's authorization server metadata (RFC 8414). Cached after the
61
+ * first success. Fails with a 404 when the server does not know its public
62
+ * address (`LOOMCYCLE_PUBLIC_URL` unset). */
63
+ discover(opts?: {
64
+ signal?: AbortSignal;
65
+ }): Promise<OAuthServerMetadata>;
66
+ private fetchMetadata;
67
+ private tokenRequest;
68
+ /** POST a form: parameters in the body, never the URL; no bearer and no
69
+ * cookie (the code or the refresh token is the credential); only
70
+ * CORS-safelisted headers, so a browser sends it without a preflight. */
71
+ private postForm;
72
+ private webCrypto;
73
+ }
74
+ /** Read the authorization response parameters from the redirect URL (its
75
+ * query). Pass the result to {@link LoomcycleOAuth.completeAuthorize}. */
76
+ export declare function parseAuthorizeResponse(url: string | URL): AuthorizeResponseParams;
77
+ /** The PKCE S256 code challenge of a verifier (RFC 7636 §4.2):
78
+ * BASE64URL(SHA-256(ASCII(verifier))). */
79
+ export declare function pkceChallenge(verifier: string, cryptoImpl?: Crypto): Promise<string>;
80
+ /** Options for {@link OAuthTokenProvider}. */
81
+ export interface OAuthTokenProviderOptions {
82
+ /** The helper for the server that issued the tokens. */
83
+ oauth: LoomcycleOAuth;
84
+ clientId: string;
85
+ /** The current token set (from completeAuthorize, or persisted). */
86
+ tokens: OAuthTokenSet;
87
+ /** Called with every new token set, before the token is used. Persist it:
88
+ * the refresh token it replaced is spent. A throw fails the request that
89
+ * caused the refresh; the new set is kept in memory regardless. */
90
+ onTokens?: (tokens: OAuthTokenSet) => void | Promise<void>;
91
+ /** Called once when the sign-in ends: the server refused the refresh token
92
+ * (revoked, expired, reused) or {@link OAuthTokenProvider.signOut} ran.
93
+ * Clear what you persisted and send the person to sign in again. */
94
+ onSignedOut?: (reason: OAuthError) => void;
95
+ /** Refresh this long before the access token expires (default 60 s). */
96
+ refreshSkewMs?: number;
97
+ }
98
+ /**
99
+ * A {@link TokenProvider} over an app sign-in: hands out the access token,
100
+ * refreshes it before it expires and once after a 401, and shares one
101
+ * refresh between concurrent requests (two refreshes of the same refresh
102
+ * token would end the sign-in, since the server takes the second as a
103
+ * replay).
104
+ *
105
+ * One provider per sign-in: two providers — or two browser tabs — refreshing
106
+ * the same refresh token end it the same way.
107
+ */
108
+ export declare class OAuthTokenProvider implements TokenProvider {
109
+ private readonly opts;
110
+ private current?;
111
+ private inflight?;
112
+ private ended?;
113
+ private readonly skew;
114
+ constructor(opts: OAuthTokenProviderOptions);
115
+ /** The current token set; undefined once signed out. */
116
+ get tokens(): OAuthTokenSet | undefined;
117
+ getToken(): Promise<string | undefined>;
118
+ onUnauthorized(rejected: string | undefined): Promise<string | undefined>;
119
+ /** Refresh now, sharing a refresh already under way. */
120
+ refresh(): Promise<OAuthTokenSet>;
121
+ /** End the sign-in: revoke the refresh token on the server (which also
122
+ * ends the access tokens it issued) and forget the tokens. Resolves even
123
+ * if the server could not be reached; the tokens are forgotten either
124
+ * way. */
125
+ signOut(opts?: {
126
+ signal?: AbortSignal;
127
+ }): Promise<void>;
128
+ private refreshOnce;
129
+ private doRefresh;
130
+ private end;
131
+ }