@agentchainlabsai/sdk 0.0.0-stage → 0.2.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.
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Continue with AgentChain — authorize URL, code exchange, userinfo.
3
+ * PKCE S256 for public clients. No MCP surface.
4
+ */
5
+ /** PKCE S256 pair: keep `codeVerifier` secret until {@link exchangeCode}; send `codeChallenge` in the authorize URL. */
6
+ export declare function createPkcePair(): Promise<{
7
+ codeVerifier: string;
8
+ codeChallenge: string;
9
+ codeChallengeMethod: 'S256';
10
+ }>;
11
+ export type AuthorizeUrlInput = {
12
+ baseUrl: string;
13
+ clientId: string;
14
+ redirectUri: string;
15
+ scope?: string;
16
+ state?: string;
17
+ codeChallenge?: string;
18
+ codeChallengeMethod?: 'S256';
19
+ };
20
+ export declare function buildAuthorizeUrl(input: AuthorizeUrlInput): string;
21
+ export type ExchangeCodeInput = {
22
+ baseUrl: string;
23
+ clientId: string;
24
+ clientSecret?: string;
25
+ code: string;
26
+ redirectUri: string;
27
+ codeVerifier?: string;
28
+ };
29
+ export declare function exchangeCode(input: ExchangeCodeInput): Promise<Record<string, unknown>>;
30
+ export declare function userinfo(baseUrl: string, accessToken: string): Promise<Record<string, unknown>>;
31
+ //# sourceMappingURL=oauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,wHAAwH;AACxH,wBAAsB,cAAc,IAAI,OAAO,CAAC;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAA;CAAE,CAAC,CAM5H;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAalE;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,wBAAsB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAkB7F;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAQrG"}
package/dist/oauth.js ADDED
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Continue with AgentChain — authorize URL, code exchange, userinfo.
3
+ * PKCE S256 for public clients. No MCP surface.
4
+ */
5
+ import { apiErrorFromResponse, fetchJson } from './http.js';
6
+ function base64Url(bytes) {
7
+ let bin = '';
8
+ for (const b of bytes)
9
+ bin += String.fromCharCode(b);
10
+ return btoa(bin).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
11
+ }
12
+ /** PKCE S256 pair: keep `codeVerifier` secret until {@link exchangeCode}; send `codeChallenge` in the authorize URL. */
13
+ export async function createPkcePair() {
14
+ const verifierBytes = new Uint8Array(32);
15
+ crypto.getRandomValues(verifierBytes);
16
+ const codeVerifier = base64Url(verifierBytes);
17
+ const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(codeVerifier));
18
+ return { codeVerifier, codeChallenge: base64Url(new Uint8Array(digest)), codeChallengeMethod: 'S256' };
19
+ }
20
+ export function buildAuthorizeUrl(input) {
21
+ const base = input.baseUrl.replace(/\/$/, '');
22
+ const url = new URL(`${base}/api/oauth/agent/authorize`);
23
+ url.searchParams.set('client_id', input.clientId);
24
+ url.searchParams.set('redirect_uri', input.redirectUri);
25
+ url.searchParams.set('response_type', 'code');
26
+ url.searchParams.set('scope', input.scope ?? 'agent_id profile');
27
+ if (input.state)
28
+ url.searchParams.set('state', input.state);
29
+ if (input.codeChallenge) {
30
+ url.searchParams.set('code_challenge', input.codeChallenge);
31
+ url.searchParams.set('code_challenge_method', input.codeChallengeMethod ?? 'S256');
32
+ }
33
+ return url.toString();
34
+ }
35
+ export async function exchangeCode(input) {
36
+ const base = input.baseUrl.replace(/\/$/, '');
37
+ const body = new URLSearchParams({
38
+ grant_type: 'authorization_code',
39
+ code: input.code,
40
+ redirect_uri: input.redirectUri,
41
+ client_id: input.clientId,
42
+ });
43
+ if (input.clientSecret)
44
+ body.set('client_secret', input.clientSecret);
45
+ if (input.codeVerifier)
46
+ body.set('code_verifier', input.codeVerifier);
47
+ const { res, body: json } = await fetchJson(`${base}/api/oauth/agent/token`, {
48
+ method: 'POST',
49
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded', Accept: 'application/json' },
50
+ body,
51
+ });
52
+ const out = json;
53
+ if (!res.ok)
54
+ throw apiErrorFromResponse(res, out, String(out.error_description || out.error || `HTTP ${res.status}`));
55
+ return out;
56
+ }
57
+ export async function userinfo(baseUrl, accessToken) {
58
+ const base = baseUrl.replace(/\/$/, '');
59
+ const { res, body: json } = await fetchJson(`${base}/api/oauth/agent/userinfo`, {
60
+ headers: { Authorization: `Bearer ${accessToken}`, Accept: 'application/json' },
61
+ });
62
+ const out = json;
63
+ if (!res.ok)
64
+ throw apiErrorFromResponse(res, out, String(out.error_description || out.error || `HTTP ${res.status}`));
65
+ return out;
66
+ }
@@ -0,0 +1,73 @@
1
+ export type RelayBrowserChallenge = {
2
+ method: 'browser';
3
+ challengeToken: string;
4
+ nonce: string;
5
+ difficulty: number;
6
+ /** Unix timestamp in seconds. */
7
+ expiresAt: number;
8
+ };
9
+ export type RelayWalletChallenge = {
10
+ method: 'wallet';
11
+ challengeToken: string;
12
+ message: string;
13
+ /** Unix timestamp in seconds. */
14
+ expiresAt: number;
15
+ ttlSeconds: number;
16
+ };
17
+ export type RelayConnectResponse = {
18
+ product: 'relay';
19
+ productVersion: string;
20
+ agentId: string;
21
+ did: string;
22
+ didAliases: string[];
23
+ apiKey?: string;
24
+ /** ISO-8601 expiry of the issued API key. */
25
+ apiKeyExpiresAt?: string;
26
+ /** False when connect authenticated an existing identity without minting a new key. */
27
+ issuedApiKey?: boolean;
28
+ presentation: {
29
+ token: string;
30
+ expiresAt: number;
31
+ };
32
+ isNewAccount?: boolean;
33
+ [key: string]: unknown;
34
+ };
35
+ /** Deterministic Node.js PoW solver for Relay browser-connect challenges. */
36
+ export declare function solveRelayBrowserChallenge(challenge: RelayBrowserChallenge): string;
37
+ export declare function requestRelayBrowserChallenge(baseUrl?: string): Promise<RelayBrowserChallenge>;
38
+ export declare function connectRelayBrowser(baseUrl: string, params: {
39
+ challengeToken: string;
40
+ solution: string;
41
+ /** Explicit clickwrap/API consent is required for account creation. */
42
+ agreedToTerms: true;
43
+ from?: string;
44
+ cardUrl?: string;
45
+ issueKey?: boolean;
46
+ keyName?: string;
47
+ }): Promise<RelayConnectResponse>;
48
+ export declare function connectRelayWithSolver(solve: (challenge: RelayBrowserChallenge) => Promise<string>, options: {
49
+ baseUrl?: string;
50
+ agreedToTerms: true;
51
+ from?: string;
52
+ cardUrl?: string;
53
+ }): Promise<RelayConnectResponse>;
54
+ /** One-call Node.js Relay Connect flow: challenge, solve and issue credentials. */
55
+ export declare function connectRelay(options: {
56
+ baseUrl?: string;
57
+ agreedToTerms: true;
58
+ from?: string;
59
+ cardUrl?: string;
60
+ }): Promise<RelayConnectResponse>;
61
+ export declare function requestRelayWalletChallenge(walletAddress: string, baseUrl?: string): Promise<RelayWalletChallenge>;
62
+ export declare function connectRelayWallet(baseUrl: string, params: {
63
+ walletAddress: string;
64
+ challengeToken: string;
65
+ signature: string;
66
+ agreedToTerms?: boolean;
67
+ name?: string;
68
+ from?: string;
69
+ cardUrl?: string;
70
+ issueKey?: boolean;
71
+ keyName?: string;
72
+ }): Promise<RelayConnectResponse>;
73
+ //# sourceMappingURL=relay-connect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relay-connect.d.ts","sourceRoot":"","sources":["../src/relay-connect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ import { createHash } from 'node:crypto';
2
+ const MAX_POW_ITERATIONS = 5_000_000;
3
+ /** Deterministic Node.js PoW solver for Relay browser-connect challenges. */
4
+ export function solveRelayBrowserChallenge(challenge) {
5
+ const prefix = '0'.repeat(challenge.difficulty);
6
+ for (let i = 0; i < MAX_POW_ITERATIONS; i += 1) {
7
+ const candidate = String(i);
8
+ const digest = createHash('sha256')
9
+ .update(`${challenge.nonce}:${candidate}`)
10
+ .digest('hex');
11
+ if (digest.startsWith(prefix))
12
+ return candidate;
13
+ }
14
+ throw new Error('Relay proof-of-work solution was not found within the safety limit');
15
+ }
16
+ function normalizeBase(baseUrl) {
17
+ return baseUrl.replace(/\/$/, '');
18
+ }
19
+ async function relayJson(baseUrl, path, body) {
20
+ const response = await fetch(`${normalizeBase(baseUrl)}${path}`, {
21
+ method: 'POST',
22
+ headers: { 'Content-Type': 'application/json' },
23
+ body: JSON.stringify(body),
24
+ });
25
+ const text = await response.text();
26
+ let parsed;
27
+ try {
28
+ parsed = text ? JSON.parse(text) : {};
29
+ }
30
+ catch {
31
+ throw new Error(`Non-JSON response (${response.status}): ${text.slice(0, 200)}`);
32
+ }
33
+ if (!response.ok) {
34
+ const error = parsed;
35
+ throw new Error(error.error || error.code || `HTTP ${response.status}`);
36
+ }
37
+ return parsed;
38
+ }
39
+ export function requestRelayBrowserChallenge(baseUrl = 'https://www.agentchainlabs.com') {
40
+ return relayJson(baseUrl, '/api/v1/identity/connect/challenge', { method: 'browser' });
41
+ }
42
+ export function connectRelayBrowser(baseUrl, params) {
43
+ return relayJson(baseUrl, '/api/v1/identity/connect', {
44
+ method: 'browser',
45
+ ...params,
46
+ });
47
+ }
48
+ export async function connectRelayWithSolver(solve, options) {
49
+ const baseUrl = options.baseUrl ?? 'https://www.agentchainlabs.com';
50
+ const challenge = await requestRelayBrowserChallenge(baseUrl);
51
+ const solution = await solve(challenge);
52
+ return connectRelayBrowser(baseUrl, {
53
+ challengeToken: challenge.challengeToken,
54
+ solution,
55
+ agreedToTerms: options.agreedToTerms,
56
+ from: options.from,
57
+ cardUrl: options.cardUrl,
58
+ });
59
+ }
60
+ /** One-call Node.js Relay Connect flow: challenge, solve and issue credentials. */
61
+ export function connectRelay(options) {
62
+ return connectRelayWithSolver(async (challenge) => solveRelayBrowserChallenge(challenge), options);
63
+ }
64
+ export function requestRelayWalletChallenge(walletAddress, baseUrl = 'https://www.agentchainlabs.com') {
65
+ return relayJson(baseUrl, '/api/v1/identity/connect/challenge', {
66
+ method: 'wallet',
67
+ walletAddress,
68
+ });
69
+ }
70
+ export function connectRelayWallet(baseUrl, params) {
71
+ return relayJson(baseUrl, '/api/v1/identity/connect', {
72
+ method: 'wallet',
73
+ ...params,
74
+ });
75
+ }