@acosmi/sdk-ts 1.3.2 → 1.4.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/index.mjs CHANGED
@@ -1056,7 +1056,7 @@ init_adapters();
1056
1056
 
1057
1057
  // src/auth.ts
1058
1058
  var authTimeoutMs = 3e4;
1059
- async function discover(serverURL, signal) {
1059
+ async function discoverWithProfile(serverURL, profile, signal) {
1060
1060
  let parsed;
1061
1061
  try {
1062
1062
  parsed = new URL(serverURL.replace(/\/+$/, ""));
@@ -1064,7 +1064,7 @@ async function discover(serverURL, signal) {
1064
1064
  throw new Error(`discover: invalid server URL: ${e instanceof Error ? e.message : String(e)}`);
1065
1065
  }
1066
1066
  const origin = `${parsed.protocol}//${parsed.host}`;
1067
- const endpoint = `${origin}/.well-known/oauth-authorization-server/desktop`;
1067
+ const endpoint = `${origin}/.well-known/oauth-authorization-server/${profile}`;
1068
1068
  const ctl = withTimeout(authTimeoutMs, signal);
1069
1069
  let resp;
1070
1070
  try {
@@ -1090,6 +1090,12 @@ async function discover(serverURL, signal) {
1090
1090
  }
1091
1091
  return meta;
1092
1092
  }
1093
+ async function discover(serverURL, signal) {
1094
+ return discoverWithProfile(serverURL, "desktop", signal);
1095
+ }
1096
+ async function discoverWebOAuthMetadata(serverURL, signal) {
1097
+ return discoverWithProfile(serverURL, "web", signal);
1098
+ }
1093
1099
  async function register(meta, appName, signal) {
1094
1100
  const regReq = {
1095
1101
  client_name: appName,
@@ -1121,12 +1127,50 @@ async function register(meta, appName, signal) {
1121
1127
  throw new Error(`register: decode: ${e instanceof Error ? e.message : String(e)}`);
1122
1128
  }
1123
1129
  }
1124
- async function generateCodeVerifier() {
1130
+ async function registerWebOAuthClient(meta, opts, signal) {
1131
+ const regReq = {
1132
+ client_name: opts.clientName,
1133
+ token_endpoint_auth_method: "none",
1134
+ grant_types: ["authorization_code", "refresh_token"],
1135
+ redirect_uris: opts.redirectURIs,
1136
+ response_types: ["code"],
1137
+ ...opts.scopes ? { scope: opts.scopes.join(" ") } : {}
1138
+ };
1139
+ const ctl = withTimeout(authTimeoutMs, signal);
1140
+ let resp;
1141
+ try {
1142
+ resp = await fetch(meta.registration_endpoint, {
1143
+ method: "POST",
1144
+ headers: { "Content-Type": "application/json" },
1145
+ body: JSON.stringify(regReq),
1146
+ signal: ctl.signal
1147
+ });
1148
+ } catch (e) {
1149
+ throw new Error(`register: ${e instanceof Error ? e.message : String(e)}`);
1150
+ } finally {
1151
+ ctl.dispose();
1152
+ }
1153
+ if (resp.status !== 200 && resp.status !== 201) {
1154
+ throw new Error(`register: HTTP ${resp.status}`);
1155
+ }
1156
+ try {
1157
+ return await resp.json();
1158
+ } catch (e) {
1159
+ throw new Error(`register: decode: ${e instanceof Error ? e.message : String(e)}`);
1160
+ }
1161
+ }
1162
+ async function randomBase64Url32() {
1125
1163
  const c = await getCrypto();
1126
1164
  const b = new Uint8Array(32);
1127
1165
  c.getRandomValues(b);
1128
1166
  return base64urlNoPad(b);
1129
1167
  }
1168
+ async function generateCodeVerifier() {
1169
+ return randomBase64Url32();
1170
+ }
1171
+ async function generateState() {
1172
+ return randomBase64Url32();
1173
+ }
1130
1174
  async function codeChallenge(verifier) {
1131
1175
  const c = await getCrypto();
1132
1176
  const buf = await c.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
@@ -1160,6 +1204,7 @@ var ErrAuthDenied = "auth_denied";
1160
1204
  var ErrTimeout = "auth_timeout";
1161
1205
  var ErrTokenExchange = "token_exchange_failed";
1162
1206
  var ErrSSLProxy = "ssl_proxy_detected";
1207
+ var ErrStateMismatch = "state_mismatch";
1163
1208
  function isSSLError(err) {
1164
1209
  const msg = err instanceof Error ? err.message : String(err);
1165
1210
  return msg.includes("tls:") || msg.includes("x509:") || msg.includes("certificate");
@@ -1273,6 +1318,51 @@ async function authorize(meta, clientID, scopes, opts = {}) {
1273
1318
  function htmlEscape(s) {
1274
1319
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
1275
1320
  }
1321
+ async function createWebAuthorizationRequest(meta, opts) {
1322
+ const verifier = await generateCodeVerifier();
1323
+ const challenge = await codeChallenge(verifier);
1324
+ const state = await generateState();
1325
+ const authURL = new URL(meta.authorization_endpoint);
1326
+ authURL.searchParams.set("response_type", "code");
1327
+ authURL.searchParams.set("client_id", opts.clientID);
1328
+ authURL.searchParams.set("redirect_uri", opts.redirectURI);
1329
+ authURL.searchParams.set("code_challenge", challenge);
1330
+ authURL.searchParams.set("code_challenge_method", "S256");
1331
+ authURL.searchParams.set("state", state);
1332
+ authURL.searchParams.set("scope", opts.scopes.join(" "));
1333
+ if (opts.loginHint) {
1334
+ authURL.searchParams.set("login_hint", opts.loginHint);
1335
+ }
1336
+ return {
1337
+ authUrl: authURL.toString(),
1338
+ state,
1339
+ verifier,
1340
+ clientID: opts.clientID,
1341
+ redirectURI: opts.redirectURI,
1342
+ serverURL: opts.serverURL,
1343
+ createdAt: Date.now()
1344
+ };
1345
+ }
1346
+ async function completeWebAuthorizationRequest(pending, params, signal) {
1347
+ if (!params.code) {
1348
+ throw new Error("completeWebAuthorizationRequest: missing authorization code");
1349
+ }
1350
+ if (params.state !== pending.state) {
1351
+ throw new Error(
1352
+ `completeWebAuthorizationRequest: ${ErrStateMismatch}: callback state does not match pending state (possible CSRF)`
1353
+ );
1354
+ }
1355
+ const meta = await discoverWebOAuthMetadata(pending.serverURL, signal);
1356
+ const resp = await exchangeCode(
1357
+ meta,
1358
+ pending.clientID,
1359
+ params.code,
1360
+ pending.redirectURI,
1361
+ pending.verifier,
1362
+ signal
1363
+ );
1364
+ return newTokenSet(resp, pending.clientID, pending.serverURL);
1365
+ }
1276
1366
  async function exchangeCode(meta, clientID, code, redirectURI, codeVerifier, signal) {
1277
1367
  const data = new URLSearchParams({
1278
1368
  grant_type: "authorization_code",
@@ -2165,6 +2255,8 @@ var Client = class _Client {
2165
2255
  serverURL;
2166
2256
  /** Compliance API 根地址 (已 trim 尾随 /); null = 走默认 ${serverURL}/admin-api */
2167
2257
  complianceBaseURL;
2258
+ /** OAuth metadata profile — 刷新 token 时发现 metadata 用 (默认 'desktop') */
2259
+ oauthMetadataProfile;
2168
2260
  /** OAuth metadata (lazy loaded) */
2169
2261
  meta = null;
2170
2262
  /** 当前 token (内存) */
@@ -2199,6 +2291,7 @@ var Client = class _Client {
2199
2291
  constructor(cfg = {}) {
2200
2292
  this.serverURL = (cfg.serverURL ?? "https://acosmi.com").replace(/\/+$/, "");
2201
2293
  this.complianceBaseURL = cfg.complianceBaseURL ? cfg.complianceBaseURL.replace(/\/+$/, "") : null;
2294
+ this.oauthMetadataProfile = cfg.oauthMetadataProfile ?? "desktop";
2202
2295
  this.store = cfg.store ?? defaultTokenStore();
2203
2296
  this.fetchImpl = cfg.fetchImpl ?? globalThis.fetch.bind(globalThis);
2204
2297
  this.retryPolicy = effectivePolicy(cfg.retryPolicy ?? null);
@@ -2373,7 +2466,7 @@ var Client = class _Client {
2373
2466
  if (tokens) {
2374
2467
  if (!meta) {
2375
2468
  try {
2376
- meta = await discover(this.serverURL, signal);
2469
+ meta = await discoverWithProfile(this.serverURL, this.oauthMetadataProfile, signal);
2377
2470
  } catch (e) {
2378
2471
  console.warn(`[acosmi-sdk] warning: discover for revocation failed: ${e instanceof Error ? e.message : String(e)}`);
2379
2472
  }
@@ -2444,7 +2537,7 @@ var Client = class _Client {
2444
2537
  }
2445
2538
  if (this.meta == null) {
2446
2539
  try {
2447
- this.meta = await discover(this.serverURL, signal);
2540
+ this.meta = await discoverWithProfile(this.serverURL, this.oauthMetadataProfile, signal);
2448
2541
  } catch (e) {
2449
2542
  throw new Error(
2450
2543
  `discover for refresh: ${e instanceof Error ? e.message : String(e)}`
@@ -2476,7 +2569,7 @@ var Client = class _Client {
2476
2569
  throw new Error("no tokens to refresh");
2477
2570
  }
2478
2571
  if (this.meta == null) {
2479
- this.meta = await discover(this.serverURL, signal);
2572
+ this.meta = await discoverWithProfile(this.serverURL, this.oauthMetadataProfile, signal);
2480
2573
  }
2481
2574
  const tokenResp = await refreshToken(
2482
2575
  this.meta,
@@ -5369,6 +5462,6 @@ Client.prototype.getBugReport = async function(bugID, signal) {
5369
5462
  return resp.data;
5370
5463
  };
5371
5464
 
5372
- export { AgentRunStreamError, AgentRunsClient, AnthropicAdapter, BucketClassCommercial, BucketClassGeneric, BusinessError, Client, ComplianceClient, CompliancePollError, DefaultRetryPolicy, ErrAuthDenied, ErrBillingCallbackCannotCommit, ErrBillingCommitRequiresLocalVerify, ErrBillingS2sForbidden, ErrBrowserOpen, ErrComplianceStepUpRequired, ErrDiscovery, ErrEnvelopeGateClosed, ErrProviderNotConfigured, ErrProviderUnknownNoRetry, ErrRegistration, ErrSSLProxy, ErrSealApprovalContractHashMismatch, ErrSealApprovalExpired, ErrSealApprovalLocationMismatch, ErrSealApprovalNonceUsed, ErrSealApprovalNotApproved, ErrSealApprovalSealMismatch, ErrSealApprovalTransactorMismatch, ErrSealUseAlreadyConsumed, ErrTimeout, ErrTokenExchange, EventAuthURL, EventComplete, EventError, FileTokenStore, FilterStatusAdminBypass, FilterStatusDisabledByFlag, FilterStatusFallbackMissingUser, FilterStatusFallbackNoBuckets, FilterStatusFallbackTkdistError, FilterStatusFallbackTkdistSkew, FilterStatusInternalBypass, FilterStatusOK, FilterStatusUnknown, HTTPError, InMemoryTokenStore, LocalStorageTokenStore, ModelNotFoundError, NetworkError, OpenAIAdapter, OrderTerminalError, ProviderFormat, RateLimitError, ScopeAI, ScopeAccount, ScopeComplianceContractSigningRead, ScopeComplianceContractSigningWrite, ScopeComplianceEvidenceRead, ScopeComplianceEvidenceWrite, ScopeComplianceReportsPublish, ScopeComplianceReportsRead, ScopeComplianceReportsWrite, ScopeComplianceSealApprovalApprove, ScopeComplianceSealApprovalRequest, ScopeComplianceSealManage, ScopeComplianceSealUseExecute, ScopeComplianceTimestampIssue, ScopeComplianceTimestampVerify, ScopeEntitlements, ScopeModels, ScopeModelsChat, ScopeProfile, ScopeSkillStore, ScopeSkills, ScopeTokenPackages, ScopeTools, ScopeToolsExecute, ScopeWallet, ScopeWalletReadonly, ServerToolTypeWebSearch, StreamError, ThinkingHigh, ThinkingHighMinMaxTokens, ThinkingMax, ThinkingMaxFallbackMaxTokens, ThinkingOff, allScopes, anthropicResponseTextContent, anthropicResponseThinkingContent, anthropicResponseToolUseBlocks, apiResponseBusinessError, apiResponseGetMessage, authorize, bucketInfoIsCommercial, bucketRowIsCommercial, buildBetas, classifyComplianceError, commerceScopes, complianceScopes, computeBackoff, defaultRetryable, defaultSafeToRetry, discover, effectivePolicy, exchangeCode, extractAnthropicBlockMeta, fileLockDefaults, findDesktopVisualUnderstandingModel, findFirstModelByInputModality, getAdapter, getAdapterForModel, isBillingConfirmable, isComplianceBusinessError, isComplianceTerminalError, isSSLError, modelScopes, modelSupportsImageInput, modelSupportsInputModality, newFileTokenStore, newThinkingConfig, newTokenSet, newWebSearchTool, parseNotificationEvent, parseSettlement, parseSourcesEvent, refreshToken, register, revokeToken, sanitize_exports as sanitize, skillScopes, tokenSetIsExpired, uniqueMerge };
5465
+ export { AgentRunStreamError, AgentRunsClient, AnthropicAdapter, BucketClassCommercial, BucketClassGeneric, BusinessError, Client, ComplianceClient, CompliancePollError, DefaultRetryPolicy, ErrAuthDenied, ErrBillingCallbackCannotCommit, ErrBillingCommitRequiresLocalVerify, ErrBillingS2sForbidden, ErrBrowserOpen, ErrComplianceStepUpRequired, ErrDiscovery, ErrEnvelopeGateClosed, ErrProviderNotConfigured, ErrProviderUnknownNoRetry, ErrRegistration, ErrSSLProxy, ErrSealApprovalContractHashMismatch, ErrSealApprovalExpired, ErrSealApprovalLocationMismatch, ErrSealApprovalNonceUsed, ErrSealApprovalNotApproved, ErrSealApprovalSealMismatch, ErrSealApprovalTransactorMismatch, ErrSealUseAlreadyConsumed, ErrStateMismatch, ErrTimeout, ErrTokenExchange, EventAuthURL, EventComplete, EventError, FileTokenStore, FilterStatusAdminBypass, FilterStatusDisabledByFlag, FilterStatusFallbackMissingUser, FilterStatusFallbackNoBuckets, FilterStatusFallbackTkdistError, FilterStatusFallbackTkdistSkew, FilterStatusInternalBypass, FilterStatusOK, FilterStatusUnknown, HTTPError, InMemoryTokenStore, LocalStorageTokenStore, ModelNotFoundError, NetworkError, OpenAIAdapter, OrderTerminalError, ProviderFormat, RateLimitError, ScopeAI, ScopeAccount, ScopeComplianceContractSigningRead, ScopeComplianceContractSigningWrite, ScopeComplianceEvidenceRead, ScopeComplianceEvidenceWrite, ScopeComplianceReportsPublish, ScopeComplianceReportsRead, ScopeComplianceReportsWrite, ScopeComplianceSealApprovalApprove, ScopeComplianceSealApprovalRequest, ScopeComplianceSealManage, ScopeComplianceSealUseExecute, ScopeComplianceTimestampIssue, ScopeComplianceTimestampVerify, ScopeEntitlements, ScopeModels, ScopeModelsChat, ScopeProfile, ScopeSkillStore, ScopeSkills, ScopeTokenPackages, ScopeTools, ScopeToolsExecute, ScopeWallet, ScopeWalletReadonly, ServerToolTypeWebSearch, StreamError, ThinkingHigh, ThinkingHighMinMaxTokens, ThinkingMax, ThinkingMaxFallbackMaxTokens, ThinkingOff, allScopes, anthropicResponseTextContent, anthropicResponseThinkingContent, anthropicResponseToolUseBlocks, apiResponseBusinessError, apiResponseGetMessage, authorize, bucketInfoIsCommercial, bucketRowIsCommercial, buildBetas, classifyComplianceError, commerceScopes, completeWebAuthorizationRequest, complianceScopes, computeBackoff, createWebAuthorizationRequest, defaultRetryable, defaultSafeToRetry, discover, discoverWebOAuthMetadata, discoverWithProfile, effectivePolicy, exchangeCode, extractAnthropicBlockMeta, fileLockDefaults, findDesktopVisualUnderstandingModel, findFirstModelByInputModality, generateState, getAdapter, getAdapterForModel, isBillingConfirmable, isComplianceBusinessError, isComplianceTerminalError, isSSLError, modelScopes, modelSupportsImageInput, modelSupportsInputModality, newFileTokenStore, newThinkingConfig, newTokenSet, newWebSearchTool, parseNotificationEvent, parseSettlement, parseSourcesEvent, refreshToken, register, registerWebOAuthClient, revokeToken, sanitize_exports as sanitize, skillScopes, tokenSetIsExpired, uniqueMerge };
5373
5466
  //# sourceMappingURL=index.mjs.map
5374
5467
  //# sourceMappingURL=index.mjs.map