@topolo/sdk 0.20.1 → 0.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1447,7 +1447,7 @@ var TopoloClient = class _TopoloClient {
1447
1447
  timeoutMs;
1448
1448
  fetchImpl;
1449
1449
  credentialProvider;
1450
- credentialLoadInFlight = null;
1450
+ credentialLoadsInFlight = /* @__PURE__ */ new Map();
1451
1451
  refreshCredential;
1452
1452
  refreshInFlight = null;
1453
1453
  debug;
@@ -1504,7 +1504,16 @@ var TopoloClient = class _TopoloClient {
1504
1504
  `Mutating ${method} requests require { confirm: true }. This guardrail prevents agents from issuing writes without an explicit human-in-the-loop acknowledgement.`
1505
1505
  );
1506
1506
  }
1507
- await this.loadCurrentCredential();
1507
+ const actionId = requestActionId(opts.headers);
1508
+ const taskId = opts.actorEnvelope?.delegation?.taskId ?? this.actorContext?.taskId;
1509
+ let requestCredential = await this.loadCurrentCredential({
1510
+ service: normalizeLookupKey(opts.service),
1511
+ method,
1512
+ path: opts.path,
1513
+ ...actionId ? { actionId } : {},
1514
+ ...taskId ? { taskId } : {},
1515
+ ...opts.resource ? { resource: opts.resource } : {}
1516
+ });
1508
1517
  const resolvedService = opts.baseUrl ? { serviceKey: normalizeLookupKey(opts.service), baseUrl: this.validatedServiceOrigin(opts.service, opts.baseUrl) } : await this.resolveRequestService(opts.service);
1509
1518
  const baseUrl = resolvedService.baseUrl;
1510
1519
  const url = new URL(opts.path, baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`);
@@ -1561,13 +1570,13 @@ var TopoloClient = class _TopoloClient {
1561
1570
  const signal = opts.signal ? mergeSignals(opts.signal, controller.signal) : controller.signal;
1562
1571
  try {
1563
1572
  const requestHeaders = new Headers(headers);
1564
- applyAuthHeaders(requestHeaders, this.credential);
1565
- if (this.credential.kind === "dpop_access_token") {
1573
+ applyAuthHeaders(requestHeaders, requestCredential);
1574
+ if (requestCredential.kind === "dpop_access_token") {
1566
1575
  requestHeaders.set("DPoP", await createDpopProof({
1567
- accessToken: this.credential.accessToken,
1576
+ accessToken: requestCredential.accessToken,
1568
1577
  method,
1569
1578
  targetUrl: urlStr,
1570
- privateJwk: this.credential.privateJwk
1579
+ privateJwk: requestCredential.privateJwk
1571
1580
  }));
1572
1581
  }
1573
1582
  return await this.fetchImpl(urlStr, {
@@ -1603,12 +1612,13 @@ var TopoloClient = class _TopoloClient {
1603
1612
  };
1604
1613
  let res;
1605
1614
  try {
1606
- const attemptedCredential = this.credential;
1615
+ const attemptedCredential = requestCredential;
1607
1616
  res = await fetchWithReadRetry();
1608
1617
  if (res.status === 401 && attemptedCredential.kind === "access_token" && this.refreshCredential) {
1609
1618
  await res.body?.cancel().catch(() => void 0);
1610
1619
  const refreshed = await this.refreshRejectedAccessToken(attemptedCredential.accessToken);
1611
1620
  if (refreshed) {
1621
+ requestCredential = refreshed;
1612
1622
  res = await fetchWithReadRetry();
1613
1623
  }
1614
1624
  }
@@ -1698,18 +1708,23 @@ var TopoloClient = class _TopoloClient {
1698
1708
  });
1699
1709
  return parsed;
1700
1710
  }
1701
- async loadCurrentCredential() {
1702
- if (!this.credentialProvider) return;
1703
- this.credentialLoadInFlight ??= this.credentialProvider().then((credential) => {
1704
- if (!credential) {
1705
- throw new TopoloAuthError("The configured Topolo credential is no longer available.");
1706
- }
1707
- this.credential = credential;
1708
- return credential;
1709
- }).finally(() => {
1710
- this.credentialLoadInFlight = null;
1711
- });
1712
- await this.credentialLoadInFlight;
1711
+ async loadCurrentCredential(context) {
1712
+ if (!this.credentialProvider) return this.credential;
1713
+ const key = JSON.stringify(context);
1714
+ let load = this.credentialLoadsInFlight.get(key);
1715
+ if (!load) {
1716
+ load = this.credentialProvider(context).then((credential) => {
1717
+ if (!credential) {
1718
+ throw new TopoloAuthError("The configured Topolo credential is no longer available.");
1719
+ }
1720
+ this.credential = credential;
1721
+ return credential;
1722
+ }).finally(() => {
1723
+ this.credentialLoadsInFlight.delete(key);
1724
+ });
1725
+ this.credentialLoadsInFlight.set(key, load);
1726
+ }
1727
+ return load;
1713
1728
  }
1714
1729
  async refreshRejectedAccessToken(attemptedAccessToken) {
1715
1730
  if (this.credential.kind === "access_token" && this.credential.accessToken !== attemptedAccessToken) {
@@ -2712,6 +2727,12 @@ function pickString(value) {
2712
2727
  }
2713
2728
  return void 0;
2714
2729
  }
2730
+ function requestActionId(headers) {
2731
+ const value = Object.entries(headers ?? {}).find(
2732
+ ([name]) => name.toLowerCase() === TOPOLO_ACTION_ID_HEADER.toLowerCase()
2733
+ )?.[1];
2734
+ return value?.trim() || void 0;
2735
+ }
2715
2736
  function extractRequired(body) {
2716
2737
  if (body && typeof body === "object") {
2717
2738
  const maybe = body;
package/dist/index.d.cts CHANGED
@@ -176,7 +176,7 @@ interface TopoloClientOptions {
176
176
  * Long-lived hosts use this to adopt context reauthentication and claim
177
177
  * changes without waiting for the previous token to fail with a 401.
178
178
  */
179
- credentialProvider?: () => Promise<TopoloCredential | null>;
179
+ credentialProvider?: (context: TopoloCredentialRequestContext) => Promise<TopoloCredential | null>;
180
180
  /**
181
181
  * Refresh a rejected access-token credential. When supplied, the client
182
182
  * retries one 401 response with the returned credential. Concurrent 401s
@@ -191,6 +191,17 @@ interface TopoloClientOptions {
191
191
  */
192
192
  debug?: (event: TopoloDebugEvent) => void;
193
193
  }
194
+ interface TopoloCredentialRequestContext {
195
+ service: string;
196
+ method: string;
197
+ path: string;
198
+ actionId?: string;
199
+ taskId?: string;
200
+ resource?: {
201
+ resourceType: string;
202
+ resourceId: string;
203
+ };
204
+ }
194
205
  type TopoloDebugEvent = {
195
206
  phase: 'request';
196
207
  method: string;
@@ -439,7 +450,7 @@ declare class TopoloClient {
439
450
  private readonly timeoutMs;
440
451
  private readonly fetchImpl;
441
452
  private readonly credentialProvider?;
442
- private credentialLoadInFlight;
453
+ private readonly credentialLoadsInFlight;
443
454
  private readonly refreshCredential?;
444
455
  private refreshInFlight;
445
456
  private readonly debug?;
@@ -1725,4 +1736,4 @@ declare function createTopolo(options: TopoloClientOptions): {
1725
1736
  };
1726
1737
  type Topolo = ReturnType<typeof createTopolo>;
1727
1738
 
1728
- export { ACTION_CATALOG_DIGEST_ALGORITHM, ACTOR_AUDIT_PROJECTION_VERSION, ACTOR_ENVELOPE_VERSION, type AccountableSubject, type AccountableSubjectType, type ActionContractManifest, type ActionContractSource, type ActorAssurance, type ActorAuditEventRole, type ActorAuditProjection, type ActorChannel, type ActorDelegationHop, type ActorEnvelope, ActorEnvelopeValidationError, type ActorIdentity, type ActorPrincipalType, type AgentIdentity, type AppApiId, type ApplicationCatalogEntry, type ApplicationDeployTarget, type ApplicationDirectory, type ApplicationDirectoryApplication, type ApplicationDirectoryClient, type ApplicationDirectorySource, type ApplicationId, type CredentialIntrospection, type CrmContactSummary, CrmModule, DEFAULT_APP_URLS, type DeviceAuthorizationResponse, type ExternalAgentCredentialIssueInput, type ExternalAgentCredentialIssueResult, IdentityModule, type ListContactsOptions, type ListContactsResult, type OAuthHelperOptions, type P2PActionDetail, type P2PActionRequestInput, type P2PActionRequestResult, type P2PActionRow, type P2PActionRun, type P2PCapability, type P2PConnection, type P2PHold, type P2PLedgerEntry, P2PModule, type P2PPolicy, type P2PPricingModel, type P2PSettlementBatch, type P2PSettlementGroup, type PublishCapabilityInput, type RequestOptions, type ServiceCatalogUrlEntry, TOPOLO_ACTOR_ENVELOPE_HEADER, TOPOLO_ENVIRONMENT_SERVICE_URLS, TOPOLO_RUNTIME_ENVIRONMENTS, TOPOLO_WIDGET_CONTRACT_VERSION, TOPOLO_WIDGET_ENDPOINT, TOPOLO_WIDGET_OUTPUT_SCHEMA, TOPOLO_WIDGET_REFRESH_INTERVAL_MS, type TokenResponse, type Topolo, type TopoloActionAgentContract, type TopoloActionCatalogEntry, type TopoloActionCatalogSummary, type TopoloActionDigestInput, type TopoloActionPlan, type TopoloActionPreparation, type TopoloActionUploadOptions, type TopoloActionValidationIssue, type TopoloActionValidationResult, type TopoloActionsWidget, type TopoloActivityWidget, type TopoloAgentExecutionContext, type TopoloApiKeyResourceMetadata, TopoloAuthError, type TopoloBinaryResponse, type TopoloBindableResource, type TopoloBindableResourceCatalog, type TopoloChartWidget, TopoloClient, type TopoloClientOptions, TopoloConfirmationRequiredError, type TopoloCredential, type TopoloDebugEvent, TopoloHttpError, type TopoloInlineBase64UploadContract, type TopoloJsonSchema, type TopoloNotificationsWidget, TopoloOAuth, TopoloPermissionError, type TopoloRuntimeEnvironment, TopoloSdkError, type TopoloServiceCatalogEntry, type TopoloStatsWidget, type TopoloWidget, type TopoloWidgetAccessibility, type TopoloWidgetActionBinding, type TopoloWidgetActionRecovery, type TopoloWidgetActivityItem, type TopoloWidgetApiError, type TopoloWidgetApiErrorResponse, type TopoloWidgetApiResponse, type TopoloWidgetApiSuccessResponse, type TopoloWidgetBase, type TopoloWidgetConfig, type TopoloWidgetConfiguration, type TopoloWidgetConfigurationField, type TopoloWidgetConfigurationOption, type TopoloWidgetContext, type TopoloWidgetContribution, type TopoloWidgetDatasetDefinition, type TopoloWidgetDimension, type TopoloWidgetDimensionDefinition, type TopoloWidgetDraft, type TopoloWidgetDrilldown, type TopoloWidgetErrorResponseOptions, type TopoloWidgetEventDefinition, type TopoloWidgetLifecycleStage, type TopoloWidgetLocalization, type TopoloWidgetMetric, type TopoloWidgetMetricAggregation, type TopoloWidgetMetricComparison, type TopoloWidgetMetricDefinition, type TopoloWidgetMetricSemantic, type TopoloWidgetNotificationItem, type TopoloWidgetPeriod, type TopoloWidgetPresentation, type TopoloWidgetRefreshPolicy, type TopoloWidgetResourceBinding, type TopoloWidgetResponseOptions, type TopoloWidgetSeries, type TopoloWidgetSeriesDefinition, type TopoloWidgetSeriesPoint, type TopoloWidgetSize, type TopoloWidgetState, type TopoloWidgetStatus, type TopoloWidgetType, type TopoloWidgetValidationResult, type TopoloWidgetVisualizationFamily, type TopoloWidgetWorkspaceSelector, type TopoloWorkspace, type TopoloWorkspaceListResult, type TopoloWorkspaceMutationResult, type TopoloWorkspacePolicy, WorkspacesModule, actionContractCompleteness, applicationEntryFromCatalog, assertTopoloServiceUrlEnvironment, calculateDpopJkt, canonicalJson, canonicalTopoloErrorCode, canonicalTopoloRequestId, canonicalTopoloRequired, canonicalTopoloRetryAfter, canonicalizeActorEnvelope, compactActionCatalogEntry, compactActionPlan, compactActionPreparation, compactActionResult, compactActionValidation, createDpopProof, createTopolo, createTopoloAgentExecutionContext, createTopoloWidgetError, createTopoloWidgetResponse, decodeActorEnvelopeHeader, defineTopoloActionsWidget, defineTopoloActivityWidget, defineTopoloChartWidget, defineTopoloNotificationsWidget, defineTopoloStatsWidget, digestTopoloActionCatalog, encodeActorEnvelopeHeader, encodeTopoloActionBase64, enrichActionContract, extractTopoloServiceErrorCode, extractTopoloServiceErrorDetails, formatDirectoryApplicationIds, friendlyAppId, isTopoloWidgetOutputSchema, listApplicationDirectory, parseActorEnvelope, parseTopoloActionUploadContract, preferExactActionMatches, prepareTopoloActionBase64UploadInput, prepareTopoloActionUploadInput, projectActorAuditEvent, publicTopoloErrorMessage, resolveApplicationDirectoryEntry, resolveCatalogServiceUrl, resolveServiceUrl, sha256CanonicalValue, topoloErrorHint, topoloServiceOrigins, validateTopoloActionInput, validateTopoloWidgetResponse };
1739
+ export { ACTION_CATALOG_DIGEST_ALGORITHM, ACTOR_AUDIT_PROJECTION_VERSION, ACTOR_ENVELOPE_VERSION, type AccountableSubject, type AccountableSubjectType, type ActionContractManifest, type ActionContractSource, type ActorAssurance, type ActorAuditEventRole, type ActorAuditProjection, type ActorChannel, type ActorDelegationHop, type ActorEnvelope, ActorEnvelopeValidationError, type ActorIdentity, type ActorPrincipalType, type AgentIdentity, type AppApiId, type ApplicationCatalogEntry, type ApplicationDeployTarget, type ApplicationDirectory, type ApplicationDirectoryApplication, type ApplicationDirectoryClient, type ApplicationDirectorySource, type ApplicationId, type CredentialIntrospection, type CrmContactSummary, CrmModule, DEFAULT_APP_URLS, type DeviceAuthorizationResponse, type ExternalAgentCredentialIssueInput, type ExternalAgentCredentialIssueResult, IdentityModule, type ListContactsOptions, type ListContactsResult, type OAuthHelperOptions, type P2PActionDetail, type P2PActionRequestInput, type P2PActionRequestResult, type P2PActionRow, type P2PActionRun, type P2PCapability, type P2PConnection, type P2PHold, type P2PLedgerEntry, P2PModule, type P2PPolicy, type P2PPricingModel, type P2PSettlementBatch, type P2PSettlementGroup, type PublishCapabilityInput, type RequestOptions, type ServiceCatalogUrlEntry, TOPOLO_ACTOR_ENVELOPE_HEADER, TOPOLO_ENVIRONMENT_SERVICE_URLS, TOPOLO_RUNTIME_ENVIRONMENTS, TOPOLO_WIDGET_CONTRACT_VERSION, TOPOLO_WIDGET_ENDPOINT, TOPOLO_WIDGET_OUTPUT_SCHEMA, TOPOLO_WIDGET_REFRESH_INTERVAL_MS, type TokenResponse, type Topolo, type TopoloActionAgentContract, type TopoloActionCatalogEntry, type TopoloActionCatalogSummary, type TopoloActionDigestInput, type TopoloActionPlan, type TopoloActionPreparation, type TopoloActionUploadOptions, type TopoloActionValidationIssue, type TopoloActionValidationResult, type TopoloActionsWidget, type TopoloActivityWidget, type TopoloAgentExecutionContext, type TopoloApiKeyResourceMetadata, TopoloAuthError, type TopoloBinaryResponse, type TopoloBindableResource, type TopoloBindableResourceCatalog, type TopoloChartWidget, TopoloClient, type TopoloClientOptions, TopoloConfirmationRequiredError, type TopoloCredential, type TopoloCredentialRequestContext, type TopoloDebugEvent, TopoloHttpError, type TopoloInlineBase64UploadContract, type TopoloJsonSchema, type TopoloNotificationsWidget, TopoloOAuth, TopoloPermissionError, type TopoloRuntimeEnvironment, TopoloSdkError, type TopoloServiceCatalogEntry, type TopoloStatsWidget, type TopoloWidget, type TopoloWidgetAccessibility, type TopoloWidgetActionBinding, type TopoloWidgetActionRecovery, type TopoloWidgetActivityItem, type TopoloWidgetApiError, type TopoloWidgetApiErrorResponse, type TopoloWidgetApiResponse, type TopoloWidgetApiSuccessResponse, type TopoloWidgetBase, type TopoloWidgetConfig, type TopoloWidgetConfiguration, type TopoloWidgetConfigurationField, type TopoloWidgetConfigurationOption, type TopoloWidgetContext, type TopoloWidgetContribution, type TopoloWidgetDatasetDefinition, type TopoloWidgetDimension, type TopoloWidgetDimensionDefinition, type TopoloWidgetDraft, type TopoloWidgetDrilldown, type TopoloWidgetErrorResponseOptions, type TopoloWidgetEventDefinition, type TopoloWidgetLifecycleStage, type TopoloWidgetLocalization, type TopoloWidgetMetric, type TopoloWidgetMetricAggregation, type TopoloWidgetMetricComparison, type TopoloWidgetMetricDefinition, type TopoloWidgetMetricSemantic, type TopoloWidgetNotificationItem, type TopoloWidgetPeriod, type TopoloWidgetPresentation, type TopoloWidgetRefreshPolicy, type TopoloWidgetResourceBinding, type TopoloWidgetResponseOptions, type TopoloWidgetSeries, type TopoloWidgetSeriesDefinition, type TopoloWidgetSeriesPoint, type TopoloWidgetSize, type TopoloWidgetState, type TopoloWidgetStatus, type TopoloWidgetType, type TopoloWidgetValidationResult, type TopoloWidgetVisualizationFamily, type TopoloWidgetWorkspaceSelector, type TopoloWorkspace, type TopoloWorkspaceListResult, type TopoloWorkspaceMutationResult, type TopoloWorkspacePolicy, WorkspacesModule, actionContractCompleteness, applicationEntryFromCatalog, assertTopoloServiceUrlEnvironment, calculateDpopJkt, canonicalJson, canonicalTopoloErrorCode, canonicalTopoloRequestId, canonicalTopoloRequired, canonicalTopoloRetryAfter, canonicalizeActorEnvelope, compactActionCatalogEntry, compactActionPlan, compactActionPreparation, compactActionResult, compactActionValidation, createDpopProof, createTopolo, createTopoloAgentExecutionContext, createTopoloWidgetError, createTopoloWidgetResponse, decodeActorEnvelopeHeader, defineTopoloActionsWidget, defineTopoloActivityWidget, defineTopoloChartWidget, defineTopoloNotificationsWidget, defineTopoloStatsWidget, digestTopoloActionCatalog, encodeActorEnvelopeHeader, encodeTopoloActionBase64, enrichActionContract, extractTopoloServiceErrorCode, extractTopoloServiceErrorDetails, formatDirectoryApplicationIds, friendlyAppId, isTopoloWidgetOutputSchema, listApplicationDirectory, parseActorEnvelope, parseTopoloActionUploadContract, preferExactActionMatches, prepareTopoloActionBase64UploadInput, prepareTopoloActionUploadInput, projectActorAuditEvent, publicTopoloErrorMessage, resolveApplicationDirectoryEntry, resolveCatalogServiceUrl, resolveServiceUrl, sha256CanonicalValue, topoloErrorHint, topoloServiceOrigins, validateTopoloActionInput, validateTopoloWidgetResponse };
package/dist/index.d.ts CHANGED
@@ -176,7 +176,7 @@ interface TopoloClientOptions {
176
176
  * Long-lived hosts use this to adopt context reauthentication and claim
177
177
  * changes without waiting for the previous token to fail with a 401.
178
178
  */
179
- credentialProvider?: () => Promise<TopoloCredential | null>;
179
+ credentialProvider?: (context: TopoloCredentialRequestContext) => Promise<TopoloCredential | null>;
180
180
  /**
181
181
  * Refresh a rejected access-token credential. When supplied, the client
182
182
  * retries one 401 response with the returned credential. Concurrent 401s
@@ -191,6 +191,17 @@ interface TopoloClientOptions {
191
191
  */
192
192
  debug?: (event: TopoloDebugEvent) => void;
193
193
  }
194
+ interface TopoloCredentialRequestContext {
195
+ service: string;
196
+ method: string;
197
+ path: string;
198
+ actionId?: string;
199
+ taskId?: string;
200
+ resource?: {
201
+ resourceType: string;
202
+ resourceId: string;
203
+ };
204
+ }
194
205
  type TopoloDebugEvent = {
195
206
  phase: 'request';
196
207
  method: string;
@@ -439,7 +450,7 @@ declare class TopoloClient {
439
450
  private readonly timeoutMs;
440
451
  private readonly fetchImpl;
441
452
  private readonly credentialProvider?;
442
- private credentialLoadInFlight;
453
+ private readonly credentialLoadsInFlight;
443
454
  private readonly refreshCredential?;
444
455
  private refreshInFlight;
445
456
  private readonly debug?;
@@ -1725,4 +1736,4 @@ declare function createTopolo(options: TopoloClientOptions): {
1725
1736
  };
1726
1737
  type Topolo = ReturnType<typeof createTopolo>;
1727
1738
 
1728
- export { ACTION_CATALOG_DIGEST_ALGORITHM, ACTOR_AUDIT_PROJECTION_VERSION, ACTOR_ENVELOPE_VERSION, type AccountableSubject, type AccountableSubjectType, type ActionContractManifest, type ActionContractSource, type ActorAssurance, type ActorAuditEventRole, type ActorAuditProjection, type ActorChannel, type ActorDelegationHop, type ActorEnvelope, ActorEnvelopeValidationError, type ActorIdentity, type ActorPrincipalType, type AgentIdentity, type AppApiId, type ApplicationCatalogEntry, type ApplicationDeployTarget, type ApplicationDirectory, type ApplicationDirectoryApplication, type ApplicationDirectoryClient, type ApplicationDirectorySource, type ApplicationId, type CredentialIntrospection, type CrmContactSummary, CrmModule, DEFAULT_APP_URLS, type DeviceAuthorizationResponse, type ExternalAgentCredentialIssueInput, type ExternalAgentCredentialIssueResult, IdentityModule, type ListContactsOptions, type ListContactsResult, type OAuthHelperOptions, type P2PActionDetail, type P2PActionRequestInput, type P2PActionRequestResult, type P2PActionRow, type P2PActionRun, type P2PCapability, type P2PConnection, type P2PHold, type P2PLedgerEntry, P2PModule, type P2PPolicy, type P2PPricingModel, type P2PSettlementBatch, type P2PSettlementGroup, type PublishCapabilityInput, type RequestOptions, type ServiceCatalogUrlEntry, TOPOLO_ACTOR_ENVELOPE_HEADER, TOPOLO_ENVIRONMENT_SERVICE_URLS, TOPOLO_RUNTIME_ENVIRONMENTS, TOPOLO_WIDGET_CONTRACT_VERSION, TOPOLO_WIDGET_ENDPOINT, TOPOLO_WIDGET_OUTPUT_SCHEMA, TOPOLO_WIDGET_REFRESH_INTERVAL_MS, type TokenResponse, type Topolo, type TopoloActionAgentContract, type TopoloActionCatalogEntry, type TopoloActionCatalogSummary, type TopoloActionDigestInput, type TopoloActionPlan, type TopoloActionPreparation, type TopoloActionUploadOptions, type TopoloActionValidationIssue, type TopoloActionValidationResult, type TopoloActionsWidget, type TopoloActivityWidget, type TopoloAgentExecutionContext, type TopoloApiKeyResourceMetadata, TopoloAuthError, type TopoloBinaryResponse, type TopoloBindableResource, type TopoloBindableResourceCatalog, type TopoloChartWidget, TopoloClient, type TopoloClientOptions, TopoloConfirmationRequiredError, type TopoloCredential, type TopoloDebugEvent, TopoloHttpError, type TopoloInlineBase64UploadContract, type TopoloJsonSchema, type TopoloNotificationsWidget, TopoloOAuth, TopoloPermissionError, type TopoloRuntimeEnvironment, TopoloSdkError, type TopoloServiceCatalogEntry, type TopoloStatsWidget, type TopoloWidget, type TopoloWidgetAccessibility, type TopoloWidgetActionBinding, type TopoloWidgetActionRecovery, type TopoloWidgetActivityItem, type TopoloWidgetApiError, type TopoloWidgetApiErrorResponse, type TopoloWidgetApiResponse, type TopoloWidgetApiSuccessResponse, type TopoloWidgetBase, type TopoloWidgetConfig, type TopoloWidgetConfiguration, type TopoloWidgetConfigurationField, type TopoloWidgetConfigurationOption, type TopoloWidgetContext, type TopoloWidgetContribution, type TopoloWidgetDatasetDefinition, type TopoloWidgetDimension, type TopoloWidgetDimensionDefinition, type TopoloWidgetDraft, type TopoloWidgetDrilldown, type TopoloWidgetErrorResponseOptions, type TopoloWidgetEventDefinition, type TopoloWidgetLifecycleStage, type TopoloWidgetLocalization, type TopoloWidgetMetric, type TopoloWidgetMetricAggregation, type TopoloWidgetMetricComparison, type TopoloWidgetMetricDefinition, type TopoloWidgetMetricSemantic, type TopoloWidgetNotificationItem, type TopoloWidgetPeriod, type TopoloWidgetPresentation, type TopoloWidgetRefreshPolicy, type TopoloWidgetResourceBinding, type TopoloWidgetResponseOptions, type TopoloWidgetSeries, type TopoloWidgetSeriesDefinition, type TopoloWidgetSeriesPoint, type TopoloWidgetSize, type TopoloWidgetState, type TopoloWidgetStatus, type TopoloWidgetType, type TopoloWidgetValidationResult, type TopoloWidgetVisualizationFamily, type TopoloWidgetWorkspaceSelector, type TopoloWorkspace, type TopoloWorkspaceListResult, type TopoloWorkspaceMutationResult, type TopoloWorkspacePolicy, WorkspacesModule, actionContractCompleteness, applicationEntryFromCatalog, assertTopoloServiceUrlEnvironment, calculateDpopJkt, canonicalJson, canonicalTopoloErrorCode, canonicalTopoloRequestId, canonicalTopoloRequired, canonicalTopoloRetryAfter, canonicalizeActorEnvelope, compactActionCatalogEntry, compactActionPlan, compactActionPreparation, compactActionResult, compactActionValidation, createDpopProof, createTopolo, createTopoloAgentExecutionContext, createTopoloWidgetError, createTopoloWidgetResponse, decodeActorEnvelopeHeader, defineTopoloActionsWidget, defineTopoloActivityWidget, defineTopoloChartWidget, defineTopoloNotificationsWidget, defineTopoloStatsWidget, digestTopoloActionCatalog, encodeActorEnvelopeHeader, encodeTopoloActionBase64, enrichActionContract, extractTopoloServiceErrorCode, extractTopoloServiceErrorDetails, formatDirectoryApplicationIds, friendlyAppId, isTopoloWidgetOutputSchema, listApplicationDirectory, parseActorEnvelope, parseTopoloActionUploadContract, preferExactActionMatches, prepareTopoloActionBase64UploadInput, prepareTopoloActionUploadInput, projectActorAuditEvent, publicTopoloErrorMessage, resolveApplicationDirectoryEntry, resolveCatalogServiceUrl, resolveServiceUrl, sha256CanonicalValue, topoloErrorHint, topoloServiceOrigins, validateTopoloActionInput, validateTopoloWidgetResponse };
1739
+ export { ACTION_CATALOG_DIGEST_ALGORITHM, ACTOR_AUDIT_PROJECTION_VERSION, ACTOR_ENVELOPE_VERSION, type AccountableSubject, type AccountableSubjectType, type ActionContractManifest, type ActionContractSource, type ActorAssurance, type ActorAuditEventRole, type ActorAuditProjection, type ActorChannel, type ActorDelegationHop, type ActorEnvelope, ActorEnvelopeValidationError, type ActorIdentity, type ActorPrincipalType, type AgentIdentity, type AppApiId, type ApplicationCatalogEntry, type ApplicationDeployTarget, type ApplicationDirectory, type ApplicationDirectoryApplication, type ApplicationDirectoryClient, type ApplicationDirectorySource, type ApplicationId, type CredentialIntrospection, type CrmContactSummary, CrmModule, DEFAULT_APP_URLS, type DeviceAuthorizationResponse, type ExternalAgentCredentialIssueInput, type ExternalAgentCredentialIssueResult, IdentityModule, type ListContactsOptions, type ListContactsResult, type OAuthHelperOptions, type P2PActionDetail, type P2PActionRequestInput, type P2PActionRequestResult, type P2PActionRow, type P2PActionRun, type P2PCapability, type P2PConnection, type P2PHold, type P2PLedgerEntry, P2PModule, type P2PPolicy, type P2PPricingModel, type P2PSettlementBatch, type P2PSettlementGroup, type PublishCapabilityInput, type RequestOptions, type ServiceCatalogUrlEntry, TOPOLO_ACTOR_ENVELOPE_HEADER, TOPOLO_ENVIRONMENT_SERVICE_URLS, TOPOLO_RUNTIME_ENVIRONMENTS, TOPOLO_WIDGET_CONTRACT_VERSION, TOPOLO_WIDGET_ENDPOINT, TOPOLO_WIDGET_OUTPUT_SCHEMA, TOPOLO_WIDGET_REFRESH_INTERVAL_MS, type TokenResponse, type Topolo, type TopoloActionAgentContract, type TopoloActionCatalogEntry, type TopoloActionCatalogSummary, type TopoloActionDigestInput, type TopoloActionPlan, type TopoloActionPreparation, type TopoloActionUploadOptions, type TopoloActionValidationIssue, type TopoloActionValidationResult, type TopoloActionsWidget, type TopoloActivityWidget, type TopoloAgentExecutionContext, type TopoloApiKeyResourceMetadata, TopoloAuthError, type TopoloBinaryResponse, type TopoloBindableResource, type TopoloBindableResourceCatalog, type TopoloChartWidget, TopoloClient, type TopoloClientOptions, TopoloConfirmationRequiredError, type TopoloCredential, type TopoloCredentialRequestContext, type TopoloDebugEvent, TopoloHttpError, type TopoloInlineBase64UploadContract, type TopoloJsonSchema, type TopoloNotificationsWidget, TopoloOAuth, TopoloPermissionError, type TopoloRuntimeEnvironment, TopoloSdkError, type TopoloServiceCatalogEntry, type TopoloStatsWidget, type TopoloWidget, type TopoloWidgetAccessibility, type TopoloWidgetActionBinding, type TopoloWidgetActionRecovery, type TopoloWidgetActivityItem, type TopoloWidgetApiError, type TopoloWidgetApiErrorResponse, type TopoloWidgetApiResponse, type TopoloWidgetApiSuccessResponse, type TopoloWidgetBase, type TopoloWidgetConfig, type TopoloWidgetConfiguration, type TopoloWidgetConfigurationField, type TopoloWidgetConfigurationOption, type TopoloWidgetContext, type TopoloWidgetContribution, type TopoloWidgetDatasetDefinition, type TopoloWidgetDimension, type TopoloWidgetDimensionDefinition, type TopoloWidgetDraft, type TopoloWidgetDrilldown, type TopoloWidgetErrorResponseOptions, type TopoloWidgetEventDefinition, type TopoloWidgetLifecycleStage, type TopoloWidgetLocalization, type TopoloWidgetMetric, type TopoloWidgetMetricAggregation, type TopoloWidgetMetricComparison, type TopoloWidgetMetricDefinition, type TopoloWidgetMetricSemantic, type TopoloWidgetNotificationItem, type TopoloWidgetPeriod, type TopoloWidgetPresentation, type TopoloWidgetRefreshPolicy, type TopoloWidgetResourceBinding, type TopoloWidgetResponseOptions, type TopoloWidgetSeries, type TopoloWidgetSeriesDefinition, type TopoloWidgetSeriesPoint, type TopoloWidgetSize, type TopoloWidgetState, type TopoloWidgetStatus, type TopoloWidgetType, type TopoloWidgetValidationResult, type TopoloWidgetVisualizationFamily, type TopoloWidgetWorkspaceSelector, type TopoloWorkspace, type TopoloWorkspaceListResult, type TopoloWorkspaceMutationResult, type TopoloWorkspacePolicy, WorkspacesModule, actionContractCompleteness, applicationEntryFromCatalog, assertTopoloServiceUrlEnvironment, calculateDpopJkt, canonicalJson, canonicalTopoloErrorCode, canonicalTopoloRequestId, canonicalTopoloRequired, canonicalTopoloRetryAfter, canonicalizeActorEnvelope, compactActionCatalogEntry, compactActionPlan, compactActionPreparation, compactActionResult, compactActionValidation, createDpopProof, createTopolo, createTopoloAgentExecutionContext, createTopoloWidgetError, createTopoloWidgetResponse, decodeActorEnvelopeHeader, defineTopoloActionsWidget, defineTopoloActivityWidget, defineTopoloChartWidget, defineTopoloNotificationsWidget, defineTopoloStatsWidget, digestTopoloActionCatalog, encodeActorEnvelopeHeader, encodeTopoloActionBase64, enrichActionContract, extractTopoloServiceErrorCode, extractTopoloServiceErrorDetails, formatDirectoryApplicationIds, friendlyAppId, isTopoloWidgetOutputSchema, listApplicationDirectory, parseActorEnvelope, parseTopoloActionUploadContract, preferExactActionMatches, prepareTopoloActionBase64UploadInput, prepareTopoloActionUploadInput, projectActorAuditEvent, publicTopoloErrorMessage, resolveApplicationDirectoryEntry, resolveCatalogServiceUrl, resolveServiceUrl, sha256CanonicalValue, topoloErrorHint, topoloServiceOrigins, validateTopoloActionInput, validateTopoloWidgetResponse };
package/dist/index.js CHANGED
@@ -1348,7 +1348,7 @@ var TopoloClient = class _TopoloClient {
1348
1348
  timeoutMs;
1349
1349
  fetchImpl;
1350
1350
  credentialProvider;
1351
- credentialLoadInFlight = null;
1351
+ credentialLoadsInFlight = /* @__PURE__ */ new Map();
1352
1352
  refreshCredential;
1353
1353
  refreshInFlight = null;
1354
1354
  debug;
@@ -1405,7 +1405,16 @@ var TopoloClient = class _TopoloClient {
1405
1405
  `Mutating ${method} requests require { confirm: true }. This guardrail prevents agents from issuing writes without an explicit human-in-the-loop acknowledgement.`
1406
1406
  );
1407
1407
  }
1408
- await this.loadCurrentCredential();
1408
+ const actionId = requestActionId(opts.headers);
1409
+ const taskId = opts.actorEnvelope?.delegation?.taskId ?? this.actorContext?.taskId;
1410
+ let requestCredential = await this.loadCurrentCredential({
1411
+ service: normalizeLookupKey(opts.service),
1412
+ method,
1413
+ path: opts.path,
1414
+ ...actionId ? { actionId } : {},
1415
+ ...taskId ? { taskId } : {},
1416
+ ...opts.resource ? { resource: opts.resource } : {}
1417
+ });
1409
1418
  const resolvedService = opts.baseUrl ? { serviceKey: normalizeLookupKey(opts.service), baseUrl: this.validatedServiceOrigin(opts.service, opts.baseUrl) } : await this.resolveRequestService(opts.service);
1410
1419
  const baseUrl = resolvedService.baseUrl;
1411
1420
  const url = new URL(opts.path, baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`);
@@ -1462,13 +1471,13 @@ var TopoloClient = class _TopoloClient {
1462
1471
  const signal = opts.signal ? mergeSignals(opts.signal, controller.signal) : controller.signal;
1463
1472
  try {
1464
1473
  const requestHeaders = new Headers(headers);
1465
- applyAuthHeaders(requestHeaders, this.credential);
1466
- if (this.credential.kind === "dpop_access_token") {
1474
+ applyAuthHeaders(requestHeaders, requestCredential);
1475
+ if (requestCredential.kind === "dpop_access_token") {
1467
1476
  requestHeaders.set("DPoP", await createDpopProof({
1468
- accessToken: this.credential.accessToken,
1477
+ accessToken: requestCredential.accessToken,
1469
1478
  method,
1470
1479
  targetUrl: urlStr,
1471
- privateJwk: this.credential.privateJwk
1480
+ privateJwk: requestCredential.privateJwk
1472
1481
  }));
1473
1482
  }
1474
1483
  return await this.fetchImpl(urlStr, {
@@ -1504,12 +1513,13 @@ var TopoloClient = class _TopoloClient {
1504
1513
  };
1505
1514
  let res;
1506
1515
  try {
1507
- const attemptedCredential = this.credential;
1516
+ const attemptedCredential = requestCredential;
1508
1517
  res = await fetchWithReadRetry();
1509
1518
  if (res.status === 401 && attemptedCredential.kind === "access_token" && this.refreshCredential) {
1510
1519
  await res.body?.cancel().catch(() => void 0);
1511
1520
  const refreshed = await this.refreshRejectedAccessToken(attemptedCredential.accessToken);
1512
1521
  if (refreshed) {
1522
+ requestCredential = refreshed;
1513
1523
  res = await fetchWithReadRetry();
1514
1524
  }
1515
1525
  }
@@ -1599,18 +1609,23 @@ var TopoloClient = class _TopoloClient {
1599
1609
  });
1600
1610
  return parsed;
1601
1611
  }
1602
- async loadCurrentCredential() {
1603
- if (!this.credentialProvider) return;
1604
- this.credentialLoadInFlight ??= this.credentialProvider().then((credential) => {
1605
- if (!credential) {
1606
- throw new TopoloAuthError("The configured Topolo credential is no longer available.");
1607
- }
1608
- this.credential = credential;
1609
- return credential;
1610
- }).finally(() => {
1611
- this.credentialLoadInFlight = null;
1612
- });
1613
- await this.credentialLoadInFlight;
1612
+ async loadCurrentCredential(context) {
1613
+ if (!this.credentialProvider) return this.credential;
1614
+ const key = JSON.stringify(context);
1615
+ let load = this.credentialLoadsInFlight.get(key);
1616
+ if (!load) {
1617
+ load = this.credentialProvider(context).then((credential) => {
1618
+ if (!credential) {
1619
+ throw new TopoloAuthError("The configured Topolo credential is no longer available.");
1620
+ }
1621
+ this.credential = credential;
1622
+ return credential;
1623
+ }).finally(() => {
1624
+ this.credentialLoadsInFlight.delete(key);
1625
+ });
1626
+ this.credentialLoadsInFlight.set(key, load);
1627
+ }
1628
+ return load;
1614
1629
  }
1615
1630
  async refreshRejectedAccessToken(attemptedAccessToken) {
1616
1631
  if (this.credential.kind === "access_token" && this.credential.accessToken !== attemptedAccessToken) {
@@ -2613,6 +2628,12 @@ function pickString(value) {
2613
2628
  }
2614
2629
  return void 0;
2615
2630
  }
2631
+ function requestActionId(headers) {
2632
+ const value = Object.entries(headers ?? {}).find(
2633
+ ([name]) => name.toLowerCase() === TOPOLO_ACTION_ID_HEADER.toLowerCase()
2634
+ )?.[1];
2635
+ return value?.trim() || void 0;
2636
+ }
2616
2637
  function extractRequired(body) {
2617
2638
  if (body && typeof body === "object") {
2618
2639
  const maybe = body;
@@ -481,6 +481,22 @@ var import_node_fs = require("fs");
481
481
  var import_node_os = require("os");
482
482
  var import_node_path = require("path");
483
483
  var KEYCHAIN_SERVICE = "topolo-external-agent-installation";
484
+ var MACOS_KEYCHAIN_WRITE_SCRIPT = [
485
+ "log_user 0",
486
+ "set timeout 10",
487
+ "set secret [gets stdin]",
488
+ "spawn -noecho /usr/bin/security add-generic-password -U -a $env(TOPOLO_KEYCHAIN_ACCOUNT) -s $env(TOPOLO_KEYCHAIN_SERVICE) -w",
489
+ "for {set prompt 0} {$prompt < 2} {incr prompt} {",
490
+ " expect {",
491
+ ' -re {(?i)password} { send -- "$secret\\r" }',
492
+ " timeout { exit 70 }",
493
+ " eof { exit 71 }",
494
+ " }",
495
+ "}",
496
+ "expect eof",
497
+ "set result [wait]",
498
+ "exit [lindex $result 3]"
499
+ ].join("\n");
484
500
  function installationStorePath() {
485
501
  const override = process.env.TOPOLO_INSTALLATIONS_PATH?.trim();
486
502
  if (override) return override;
@@ -507,16 +523,16 @@ function createPlatformInstallationSecretBackend(options = {}) {
507
523
  if (platform2 === "darwin") {
508
524
  return {
509
525
  async set(account, value) {
510
- runOrThrow(spawn("security", [
511
- "add-generic-password",
512
- "-U",
513
- "-a",
514
- account,
515
- "-s",
516
- KEYCHAIN_SERVICE,
517
- "-w"
518
- ], { input: `${value}
519
- `, encoding: "utf8" }), "macOS Keychain write");
526
+ runOrThrow(spawn("/usr/bin/expect", ["-c", MACOS_KEYCHAIN_WRITE_SCRIPT], {
527
+ input: `${value}
528
+ `,
529
+ encoding: "utf8",
530
+ env: {
531
+ ...process.env,
532
+ TOPOLO_KEYCHAIN_ACCOUNT: account,
533
+ TOPOLO_KEYCHAIN_SERVICE: KEYCHAIN_SERVICE
534
+ }
535
+ }), "macOS Keychain write");
520
536
  },
521
537
  async get(account) {
522
538
  const result = spawn("security", [
@@ -428,6 +428,22 @@ import { existsSync } from "fs";
428
428
  import { homedir, platform as hostPlatform } from "os";
429
429
  import { dirname, join } from "path";
430
430
  var KEYCHAIN_SERVICE = "topolo-external-agent-installation";
431
+ var MACOS_KEYCHAIN_WRITE_SCRIPT = [
432
+ "log_user 0",
433
+ "set timeout 10",
434
+ "set secret [gets stdin]",
435
+ "spawn -noecho /usr/bin/security add-generic-password -U -a $env(TOPOLO_KEYCHAIN_ACCOUNT) -s $env(TOPOLO_KEYCHAIN_SERVICE) -w",
436
+ "for {set prompt 0} {$prompt < 2} {incr prompt} {",
437
+ " expect {",
438
+ ' -re {(?i)password} { send -- "$secret\\r" }',
439
+ " timeout { exit 70 }",
440
+ " eof { exit 71 }",
441
+ " }",
442
+ "}",
443
+ "expect eof",
444
+ "set result [wait]",
445
+ "exit [lindex $result 3]"
446
+ ].join("\n");
431
447
  function installationStorePath() {
432
448
  const override = process.env.TOPOLO_INSTALLATIONS_PATH?.trim();
433
449
  if (override) return override;
@@ -454,16 +470,16 @@ function createPlatformInstallationSecretBackend(options = {}) {
454
470
  if (platform2 === "darwin") {
455
471
  return {
456
472
  async set(account, value) {
457
- runOrThrow(spawn("security", [
458
- "add-generic-password",
459
- "-U",
460
- "-a",
461
- account,
462
- "-s",
463
- KEYCHAIN_SERVICE,
464
- "-w"
465
- ], { input: `${value}
466
- `, encoding: "utf8" }), "macOS Keychain write");
473
+ runOrThrow(spawn("/usr/bin/expect", ["-c", MACOS_KEYCHAIN_WRITE_SCRIPT], {
474
+ input: `${value}
475
+ `,
476
+ encoding: "utf8",
477
+ env: {
478
+ ...process.env,
479
+ TOPOLO_KEYCHAIN_ACCOUNT: account,
480
+ TOPOLO_KEYCHAIN_SERVICE: KEYCHAIN_SERVICE
481
+ }
482
+ }), "macOS Keychain write");
467
483
  },
468
484
  async get(account) {
469
485
  const result = spawn("security", [
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@topolo/sdk",
3
3
  "packageManager": "pnpm@10.17.1",
4
- "version": "0.20.1",
5
- "topoloPublishedVersion": "0.20.1",
4
+ "version": "0.21.1",
5
+ "topoloPublishedVersion": "0.21.1",
6
6
  "description": "Typed client SDK for the Topolo platform. Used by TopoloCli, TopoloMCP, and third-party agents.",
7
7
  "license": "UNLICENSED",
8
8
  "author": "Topolo",