tether-name 2.0.0 → 2.0.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/README.md +24 -3
- package/dist/index.d.mts +23 -2
- package/dist/index.d.ts +23 -2
- package/dist/index.js +37 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +37 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -147,7 +147,7 @@ Create and manage agents programmatically with an API key:
|
|
|
147
147
|
const client = new TetherClient({ apiKey: 'sk-tether-name-...' });
|
|
148
148
|
|
|
149
149
|
// Create an agent
|
|
150
|
-
const agent = await client.createAgent('my-bot', 'Does helpful things');
|
|
150
|
+
const agent = await client.createAgent('my-bot', 'Does helpful things', 'verified-domain-id');
|
|
151
151
|
console.log(agent.id); // "abc123"
|
|
152
152
|
console.log(agent.agentName); // "my-bot"
|
|
153
153
|
console.log(agent.registrationToken); // Use to register the agent
|
|
@@ -155,6 +155,9 @@ console.log(agent.registrationToken); // Use to register the agent
|
|
|
155
155
|
// List all agents
|
|
156
156
|
const agents = await client.listAgents();
|
|
157
157
|
|
|
158
|
+
// List registered domains
|
|
159
|
+
const domains = await client.listDomains();
|
|
160
|
+
|
|
158
161
|
// Delete an agent
|
|
159
162
|
await client.deleteAgent(agent.id);
|
|
160
163
|
```
|
|
@@ -205,14 +208,18 @@ Signs a challenge using the configured private key.
|
|
|
205
208
|
|
|
206
209
|
Submits signed proof to verify the challenge.
|
|
207
210
|
|
|
208
|
-
#### `async createAgent(agentName: string, description?: string): Promise<Agent>`
|
|
211
|
+
#### `async createAgent(agentName: string, description?: string, domainId?: string): Promise<Agent>`
|
|
209
212
|
|
|
210
|
-
Creates a new agent. Requires API key authentication.
|
|
213
|
+
Creates a new agent. Requires API key authentication. `domainId` is optional and links this agent to a verified domain.
|
|
211
214
|
|
|
212
215
|
#### `async listAgents(): Promise<Agent[]>`
|
|
213
216
|
|
|
214
217
|
Lists all agents for the authenticated account. Requires API key authentication.
|
|
215
218
|
|
|
219
|
+
#### `async listDomains(): Promise<Domain[]>`
|
|
220
|
+
|
|
221
|
+
Lists all registered domains for the authenticated account. Requires API key authentication.
|
|
222
|
+
|
|
216
223
|
#### `async deleteAgent(agentId: string): Promise<boolean>`
|
|
217
224
|
|
|
218
225
|
Deletes an agent by ID. Requires API key authentication. Returns `true` on success.
|
|
@@ -225,6 +232,7 @@ interface VerificationResult {
|
|
|
225
232
|
agentName?: string; // Registered agent name
|
|
226
233
|
verifyUrl?: string; // Public verification URL
|
|
227
234
|
email?: string; // Registered email
|
|
235
|
+
domain?: string; // Verified domain (if assigned)
|
|
228
236
|
registeredSince?: string; // ISO date of registration
|
|
229
237
|
error?: string; // Error message if failed
|
|
230
238
|
challenge?: string; // The verified challenge
|
|
@@ -236,12 +244,25 @@ interface Agent {
|
|
|
236
244
|
id: string; // Unique agent ID
|
|
237
245
|
agentName: string; // Agent display name
|
|
238
246
|
description: string; // Agent description
|
|
247
|
+
domainId?: string; // Optional assigned domain ID
|
|
248
|
+
domain?: string | null; // Resolved assigned domain name
|
|
239
249
|
createdAt: number; // Creation time (epoch ms)
|
|
240
250
|
registrationToken?: string; // Token for key registration (returned on create)
|
|
241
251
|
lastVerifiedAt?: number; // Last verification time (epoch ms)
|
|
242
252
|
}
|
|
243
253
|
```
|
|
244
254
|
|
|
255
|
+
```typescript
|
|
256
|
+
interface Domain {
|
|
257
|
+
id: string;
|
|
258
|
+
domain: string;
|
|
259
|
+
verified: boolean;
|
|
260
|
+
verifiedAt: number;
|
|
261
|
+
lastCheckedAt: number;
|
|
262
|
+
createdAt: number;
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
245
266
|
### Errors
|
|
246
267
|
|
|
247
268
|
- `TetherError` - Base error class
|
package/dist/index.d.mts
CHANGED
|
@@ -37,6 +37,7 @@ interface VerificationResponse {
|
|
|
37
37
|
verifyUrl?: string;
|
|
38
38
|
agentName?: string;
|
|
39
39
|
email?: string;
|
|
40
|
+
domain?: string;
|
|
40
41
|
/** Raw API value (epoch ms from service; older services may return ISO strings) */
|
|
41
42
|
registeredSince?: number | string;
|
|
42
43
|
error?: string;
|
|
@@ -53,6 +54,8 @@ interface VerificationResult {
|
|
|
53
54
|
verifyUrl?: string;
|
|
54
55
|
/** The agent's registered email */
|
|
55
56
|
email?: string;
|
|
57
|
+
/** Verified domain (if this agent has a domain assigned) */
|
|
58
|
+
domain?: string;
|
|
56
59
|
/** ISO date string of when the agent was registered */
|
|
57
60
|
registeredSince?: string;
|
|
58
61
|
/** Error message if verification failed */
|
|
@@ -71,10 +74,23 @@ interface Agent {
|
|
|
71
74
|
id: string;
|
|
72
75
|
agentName: string;
|
|
73
76
|
description: string;
|
|
77
|
+
domainId?: string;
|
|
78
|
+
domain?: string | null;
|
|
74
79
|
createdAt: number;
|
|
75
80
|
registrationToken?: string;
|
|
76
81
|
lastVerifiedAt?: number;
|
|
77
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* A domain registered to the authenticated account
|
|
85
|
+
*/
|
|
86
|
+
interface Domain {
|
|
87
|
+
id: string;
|
|
88
|
+
domain: string;
|
|
89
|
+
verified: boolean;
|
|
90
|
+
verifiedAt: number;
|
|
91
|
+
lastCheckedAt: number;
|
|
92
|
+
createdAt: number;
|
|
93
|
+
}
|
|
78
94
|
/**
|
|
79
95
|
* Response from the issue agent endpoint
|
|
80
96
|
*/
|
|
@@ -82,6 +98,7 @@ interface IssueAgentResponse {
|
|
|
82
98
|
id: string;
|
|
83
99
|
agentName: string;
|
|
84
100
|
description: string;
|
|
101
|
+
domainId?: string;
|
|
85
102
|
createdAt: number;
|
|
86
103
|
registrationToken: string;
|
|
87
104
|
}
|
|
@@ -130,11 +147,15 @@ declare class TetherClient {
|
|
|
130
147
|
/**
|
|
131
148
|
* Create a new agent
|
|
132
149
|
*/
|
|
133
|
-
createAgent(agentName: string, description?: string): Promise<Agent>;
|
|
150
|
+
createAgent(agentName: string, description?: string, domainId?: string): Promise<Agent>;
|
|
134
151
|
/**
|
|
135
152
|
* List all agents
|
|
136
153
|
*/
|
|
137
154
|
listAgents(): Promise<Agent[]>;
|
|
155
|
+
/**
|
|
156
|
+
* List all registered domains
|
|
157
|
+
*/
|
|
158
|
+
listDomains(): Promise<Domain[]>;
|
|
138
159
|
/**
|
|
139
160
|
* Delete an agent by ID
|
|
140
161
|
*/
|
|
@@ -181,4 +202,4 @@ declare function signChallenge(privateKey: KeyObject, challenge: string): string
|
|
|
181
202
|
*/
|
|
182
203
|
declare function detectKeyFormat(keyPath: string): KeyFormat;
|
|
183
204
|
|
|
184
|
-
export { type Agent, type ChallengeResponse, type IssueAgentResponse, type KeyFormat, TetherAPIError, TetherClient, type TetherClientConfig, TetherError, TetherVerificationError, type VerificationRequest, type VerificationResponse, type VerificationResult, detectKeyFormat, loadPrivateKey, signChallenge };
|
|
205
|
+
export { type Agent, type ChallengeResponse, type Domain, type IssueAgentResponse, type KeyFormat, TetherAPIError, TetherClient, type TetherClientConfig, TetherError, TetherVerificationError, type VerificationRequest, type VerificationResponse, type VerificationResult, detectKeyFormat, loadPrivateKey, signChallenge };
|
package/dist/index.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ interface VerificationResponse {
|
|
|
37
37
|
verifyUrl?: string;
|
|
38
38
|
agentName?: string;
|
|
39
39
|
email?: string;
|
|
40
|
+
domain?: string;
|
|
40
41
|
/** Raw API value (epoch ms from service; older services may return ISO strings) */
|
|
41
42
|
registeredSince?: number | string;
|
|
42
43
|
error?: string;
|
|
@@ -53,6 +54,8 @@ interface VerificationResult {
|
|
|
53
54
|
verifyUrl?: string;
|
|
54
55
|
/** The agent's registered email */
|
|
55
56
|
email?: string;
|
|
57
|
+
/** Verified domain (if this agent has a domain assigned) */
|
|
58
|
+
domain?: string;
|
|
56
59
|
/** ISO date string of when the agent was registered */
|
|
57
60
|
registeredSince?: string;
|
|
58
61
|
/** Error message if verification failed */
|
|
@@ -71,10 +74,23 @@ interface Agent {
|
|
|
71
74
|
id: string;
|
|
72
75
|
agentName: string;
|
|
73
76
|
description: string;
|
|
77
|
+
domainId?: string;
|
|
78
|
+
domain?: string | null;
|
|
74
79
|
createdAt: number;
|
|
75
80
|
registrationToken?: string;
|
|
76
81
|
lastVerifiedAt?: number;
|
|
77
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* A domain registered to the authenticated account
|
|
85
|
+
*/
|
|
86
|
+
interface Domain {
|
|
87
|
+
id: string;
|
|
88
|
+
domain: string;
|
|
89
|
+
verified: boolean;
|
|
90
|
+
verifiedAt: number;
|
|
91
|
+
lastCheckedAt: number;
|
|
92
|
+
createdAt: number;
|
|
93
|
+
}
|
|
78
94
|
/**
|
|
79
95
|
* Response from the issue agent endpoint
|
|
80
96
|
*/
|
|
@@ -82,6 +98,7 @@ interface IssueAgentResponse {
|
|
|
82
98
|
id: string;
|
|
83
99
|
agentName: string;
|
|
84
100
|
description: string;
|
|
101
|
+
domainId?: string;
|
|
85
102
|
createdAt: number;
|
|
86
103
|
registrationToken: string;
|
|
87
104
|
}
|
|
@@ -130,11 +147,15 @@ declare class TetherClient {
|
|
|
130
147
|
/**
|
|
131
148
|
* Create a new agent
|
|
132
149
|
*/
|
|
133
|
-
createAgent(agentName: string, description?: string): Promise<Agent>;
|
|
150
|
+
createAgent(agentName: string, description?: string, domainId?: string): Promise<Agent>;
|
|
134
151
|
/**
|
|
135
152
|
* List all agents
|
|
136
153
|
*/
|
|
137
154
|
listAgents(): Promise<Agent[]>;
|
|
155
|
+
/**
|
|
156
|
+
* List all registered domains
|
|
157
|
+
*/
|
|
158
|
+
listDomains(): Promise<Domain[]>;
|
|
138
159
|
/**
|
|
139
160
|
* Delete an agent by ID
|
|
140
161
|
*/
|
|
@@ -181,4 +202,4 @@ declare function signChallenge(privateKey: KeyObject, challenge: string): string
|
|
|
181
202
|
*/
|
|
182
203
|
declare function detectKeyFormat(keyPath: string): KeyFormat;
|
|
183
204
|
|
|
184
|
-
export { type Agent, type ChallengeResponse, type IssueAgentResponse, type KeyFormat, TetherAPIError, TetherClient, type TetherClientConfig, TetherError, TetherVerificationError, type VerificationRequest, type VerificationResponse, type VerificationResult, detectKeyFormat, loadPrivateKey, signChallenge };
|
|
205
|
+
export { type Agent, type ChallengeResponse, type Domain, type IssueAgentResponse, type KeyFormat, TetherAPIError, TetherClient, type TetherClientConfig, TetherError, TetherVerificationError, type VerificationRequest, type VerificationResponse, type VerificationResult, detectKeyFormat, loadPrivateKey, signChallenge };
|
package/dist/index.js
CHANGED
|
@@ -274,6 +274,7 @@ var TetherClient = class {
|
|
|
274
274
|
agentName: data.agentName,
|
|
275
275
|
verifyUrl: data.verifyUrl,
|
|
276
276
|
email: data.email,
|
|
277
|
+
domain: data.domain,
|
|
277
278
|
registeredSince,
|
|
278
279
|
error: data.error,
|
|
279
280
|
challenge
|
|
@@ -317,7 +318,7 @@ var TetherClient = class {
|
|
|
317
318
|
/**
|
|
318
319
|
* Create a new agent
|
|
319
320
|
*/
|
|
320
|
-
async createAgent(agentName, description = "") {
|
|
321
|
+
async createAgent(agentName, description = "", domainId) {
|
|
321
322
|
this._requireApiKey();
|
|
322
323
|
try {
|
|
323
324
|
const response = await fetch(`${this.baseUrl}/agents/issue`, {
|
|
@@ -326,7 +327,7 @@ var TetherClient = class {
|
|
|
326
327
|
"Content-Type": "application/json",
|
|
327
328
|
...this._authHeaders()
|
|
328
329
|
},
|
|
329
|
-
body: JSON.stringify({ agentName, description })
|
|
330
|
+
body: JSON.stringify({ agentName, description, ...domainId ? { domainId } : {} })
|
|
330
331
|
});
|
|
331
332
|
if (!response.ok) {
|
|
332
333
|
const errorText = await response.text().catch(() => "Unknown error");
|
|
@@ -384,6 +385,40 @@ var TetherClient = class {
|
|
|
384
385
|
);
|
|
385
386
|
}
|
|
386
387
|
}
|
|
388
|
+
/**
|
|
389
|
+
* List all registered domains
|
|
390
|
+
*/
|
|
391
|
+
async listDomains() {
|
|
392
|
+
this._requireApiKey();
|
|
393
|
+
try {
|
|
394
|
+
const response = await fetch(`${this.baseUrl}/domains`, {
|
|
395
|
+
method: "GET",
|
|
396
|
+
headers: {
|
|
397
|
+
...this._authHeaders()
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
if (!response.ok) {
|
|
401
|
+
const errorText = await response.text().catch(() => "Unknown error");
|
|
402
|
+
throw new TetherAPIError(
|
|
403
|
+
`List domains failed: ${response.status} ${response.statusText}`,
|
|
404
|
+
response.status,
|
|
405
|
+
errorText
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
const data = await response.json();
|
|
409
|
+
return data;
|
|
410
|
+
} catch (error) {
|
|
411
|
+
if (error instanceof TetherError) {
|
|
412
|
+
throw error;
|
|
413
|
+
}
|
|
414
|
+
throw new TetherAPIError(
|
|
415
|
+
`Failed to list domains: ${error instanceof Error ? error.message : String(error)}`,
|
|
416
|
+
void 0,
|
|
417
|
+
void 0,
|
|
418
|
+
error instanceof Error ? error : void 0
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
387
422
|
/**
|
|
388
423
|
* Delete an agent by ID
|
|
389
424
|
*/
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/crypto.ts","../src/client.ts"],"sourcesContent":["/**\n * Tether Name SDK - Official Node.js library for tether.name agent identity verification\n * \n * @example\n * ```typescript\n * import { TetherClient } from 'tether-name';\n * \n * const client = new TetherClient({\n * agentId: 'your-agent-id',\n * privateKeyPath: '/path/to/key.pem'\n * });\n * \n * const result = await client.verify();\n * console.log(result.verified, result.agentName);\n * ```\n */\n\n// Main exports\nexport { TetherClient } from './client.js';\n\n// Types\nexport type {\n TetherClientConfig,\n ChallengeResponse,\n Agent,\n IssueAgentResponse,\n VerificationRequest,\n VerificationResponse,\n VerificationResult,\n KeyFormat\n} from './types.js';\n\n// Errors\nexport {\n TetherError,\n TetherAPIError,\n TetherVerificationError\n} from './errors.js';\n\n// Crypto utilities (for advanced use cases)\nexport {\n loadPrivateKey,\n signChallenge,\n detectKeyFormat\n} from './crypto.js';","/**\n * Base error class for all Tether-related errors\n */\nexport class TetherError extends Error {\n constructor(message: string, public readonly cause?: Error) {\n super(message);\n this.name = 'TetherError';\n \n // Maintain proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, TetherError);\n }\n }\n}\n\n/**\n * Error thrown when verification fails\n */\nexport class TetherVerificationError extends TetherError {\n constructor(message: string, cause?: Error) {\n super(message, cause);\n this.name = 'TetherVerificationError';\n }\n}\n\n/**\n * Error thrown when API requests fail\n */\nexport class TetherAPIError extends TetherError {\n constructor(\n message: string,\n public readonly status?: number,\n public readonly response?: string,\n cause?: Error\n ) {\n super(message, cause);\n this.name = 'TetherAPIError';\n }\n}","import { createSign, createPrivateKey, KeyObject } from 'crypto';\nimport { readFileSync } from 'fs';\nimport { TetherError } from './errors.js';\nimport type { KeyFormat } from './types.js';\n\n/**\n * Imports a DER-encoded private key, trying PKCS#8 first then PKCS#1.\n */\nfunction importDerKey(derData: Buffer): KeyObject {\n try {\n return createPrivateKey({ key: derData, format: 'der', type: 'pkcs8' });\n } catch {\n // PKCS#8 failed — try PKCS#1\n }\n try {\n return createPrivateKey({ key: derData, format: 'der', type: 'pkcs1' });\n } catch {\n // PKCS#1 also failed\n }\n throw new TetherError(\n 'Failed to load DER private key: data is not valid PKCS#8 or PKCS#1. ' +\n 'Ensure the file is an RSA private key in DER format.'\n );\n}\n\n/**\n * Loads a private key from various sources\n */\nexport function loadPrivateKey(options: {\n keyPath?: string;\n keyPem?: string;\n keyBuffer?: Buffer;\n}): KeyObject {\n const { keyPath, keyPem, keyBuffer } = options;\n\n try {\n if (keyPem) {\n // PEM string provided directly\n return createPrivateKey(keyPem);\n }\n\n if (keyBuffer) {\n // DER buffer provided directly\n return importDerKey(keyBuffer);\n }\n\n if (keyPath) {\n // Read from file - detect format by extension or content\n const keyData = readFileSync(keyPath);\n\n // Try to detect format\n if (keyPath.endsWith('.pem') || keyData.toString().includes('-----BEGIN')) {\n // PEM format\n return createPrivateKey(keyData);\n } else {\n // Assume DER format\n return importDerKey(keyData);\n }\n }\n\n throw new TetherError('No private key provided');\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherError(\n `Failed to load private key: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Signs a challenge string using RSA-SHA256\n * Returns URL-safe base64 encoded signature (no padding)\n */\nexport function signChallenge(privateKey: KeyObject, challenge: string): string {\n try {\n const sign = createSign('SHA256');\n sign.update(challenge);\n sign.end();\n \n const signature = sign.sign(privateKey);\n \n // Convert to URL-safe base64 without padding\n return signature\n .toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=/g, '');\n } catch (error) {\n throw new TetherError(\n `Failed to sign challenge: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Utility function to detect key format from file extension or content\n */\nexport function detectKeyFormat(keyPath: string): KeyFormat {\n if (keyPath.endsWith('.pem')) {\n return 'pem';\n }\n if (keyPath.endsWith('.der')) {\n return 'der';\n }\n \n // Try to read a small portion to detect format\n try {\n const keyData = readFileSync(keyPath, { encoding: 'utf8', flag: 'r' });\n if (keyData.includes('-----BEGIN')) {\n return 'pem';\n }\n } catch {\n // If we can't read as text, it's probably DER\n }\n \n return 'der';\n}","import { KeyObject } from 'crypto';\nimport { TetherError, TetherAPIError, TetherVerificationError } from './errors.js';\nimport { loadPrivateKey, signChallenge } from './crypto.js';\nimport type {\n TetherClientConfig,\n ChallengeResponse,\n Agent,\n IssueAgentResponse,\n VerificationRequest,\n VerificationResponse,\n VerificationResult\n} from './types.js';\n\n/**\n * TetherClient - Official SDK for tether.name agent identity verification\n */\nexport class TetherClient {\n private readonly agentId: string;\n private readonly privateKey: KeyObject | null;\n private readonly baseUrl: string;\n private readonly apiKey?: string;\n\n constructor(config: TetherClientConfig) {\n // Set base URL\n this.baseUrl = 'https://api.tether.name';\n\n // Get API key from config or environment\n this.apiKey = config.apiKey || process.env.TETHER_API_KEY;\n\n // Get agent ID from config or environment\n this.agentId = config.agentId || process.env.TETHER_AGENT_ID || '';\n\n // Load private key if key material is provided\n const keyPath = config.privateKeyPath || process.env.TETHER_PRIVATE_KEY_PATH;\n const hasKeyMaterial = keyPath || config.privateKeyPem || config.privateKeyBuffer;\n\n if (hasKeyMaterial) {\n this.privateKey = loadPrivateKey({\n keyPath,\n keyPem: config.privateKeyPem,\n keyBuffer: config.privateKeyBuffer\n });\n } else {\n this.privateKey = null;\n }\n\n // If no API key and no private key, agent ID and key are still needed for verify/sign\n // but we defer the error to when those methods are called\n if (!this.apiKey && !this.privateKey) {\n // Allow construction — errors thrown at method call time\n }\n\n if (!this.apiKey && !this.agentId) {\n // Allow construction — errors thrown at method call time\n }\n }\n\n /**\n * Returns authorization headers when an API key is configured\n */\n private _authHeaders(): Record<string, string> {\n if (this.apiKey) {\n return { 'Authorization': `Bearer ${this.apiKey}` };\n }\n return {};\n }\n\n /**\n * Ensures a private key is available, throwing if not\n */\n private _requirePrivateKey(): KeyObject {\n if (!this.privateKey) {\n throw new TetherError(\n 'Private key is required for this operation. Provide privateKeyPath, privateKeyPem, or privateKeyBuffer in config, or set TETHER_PRIVATE_KEY_PATH environment variable.'\n );\n }\n return this.privateKey;\n }\n\n /**\n * Ensures an API key is available, throwing if not\n */\n private _requireApiKey(): void {\n if (!this.apiKey) {\n throw new TetherError(\n 'API key is required for agent management operations. Provide apiKey in config or set TETHER_API_KEY environment variable.'\n );\n }\n }\n\n /**\n * Ensures an agent ID is available, throwing if not\n */\n private _requireAgentId(): string {\n if (!this.agentId) {\n throw new TetherError(\n 'Agent ID is required for this operation. Provide it in config or set TETHER_AGENT_ID environment variable.'\n );\n }\n return this.agentId;\n }\n\n /**\n * Request a challenge from the Tether API\n */\n async requestChallenge(): Promise<string> {\n try {\n const response = await fetch(`${this.baseUrl}/challenge`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Challenge request failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as ChallengeResponse;\n\n if (!data.code) {\n throw new TetherAPIError('Invalid challenge response: missing code');\n }\n\n return data.code;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to request challenge: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Sign a challenge string\n */\n sign(challenge: string): string {\n const key = this._requirePrivateKey();\n return signChallenge(key, challenge);\n }\n\n /**\n * Submit proof for a challenge\n */\n async submitProof(challenge: string, proof: string): Promise<VerificationResult> {\n const agentId = this._requireAgentId();\n\n try {\n const payload: VerificationRequest = {\n challenge,\n proof,\n agentId\n };\n\n const response = await fetch(`${this.baseUrl}/challenge/verify`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(payload)\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Verification failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as VerificationResponse;\n\n // Convert API response to our result format\n const registeredSince = typeof data.registeredSince === 'number'\n ? new Date(data.registeredSince).toISOString()\n : data.registeredSince;\n\n return {\n verified: data.valid,\n agentName: data.agentName,\n verifyUrl: data.verifyUrl,\n email: data.email,\n registeredSince,\n error: data.error,\n challenge\n };\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to submit proof: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Perform complete verification in one call\n */\n async verify(): Promise<VerificationResult> {\n try {\n const challenge = await this.requestChallenge();\n const proof = this.sign(challenge);\n const result = await this.submitProof(challenge, proof);\n\n if (!result.verified) {\n throw new TetherVerificationError(\n result.error || 'Verification failed for unknown reason'\n );\n }\n\n return result;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherVerificationError(\n `Verification failed: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Create a new agent\n */\n async createAgent(agentName: string, description: string = ''): Promise<Agent> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/agents/issue`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...this._authHeaders()\n },\n body: JSON.stringify({ agentName, description })\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Create agent failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as IssueAgentResponse;\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to create agent: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * List all agents\n */\n async listAgents(): Promise<Agent[]> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/agents`, {\n method: 'GET',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `List agents failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as Agent[];\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to list agents: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Delete an agent by ID\n */\n async deleteAgent(agentId: string): Promise<boolean> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/agents/${agentId}`, {\n method: 'DELETE',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Delete agent failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n return true;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to delete agent: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/crypto.ts","../src/client.ts"],"sourcesContent":["/**\n * Tether Name SDK - Official Node.js library for tether.name agent identity verification\n * \n * @example\n * ```typescript\n * import { TetherClient } from 'tether-name';\n * \n * const client = new TetherClient({\n * agentId: 'your-agent-id',\n * privateKeyPath: '/path/to/key.pem'\n * });\n * \n * const result = await client.verify();\n * console.log(result.verified, result.agentName);\n * ```\n */\n\n// Main exports\nexport { TetherClient } from './client.js';\n\n// Types\nexport type {\n TetherClientConfig,\n ChallengeResponse,\n Agent,\n Domain,\n IssueAgentResponse,\n VerificationRequest,\n VerificationResponse,\n VerificationResult,\n KeyFormat\n} from './types.js';\n\n// Errors\nexport {\n TetherError,\n TetherAPIError,\n TetherVerificationError\n} from './errors.js';\n\n// Crypto utilities (for advanced use cases)\nexport {\n loadPrivateKey,\n signChallenge,\n detectKeyFormat\n} from './crypto.js';","/**\n * Base error class for all Tether-related errors\n */\nexport class TetherError extends Error {\n constructor(message: string, public readonly cause?: Error) {\n super(message);\n this.name = 'TetherError';\n \n // Maintain proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, TetherError);\n }\n }\n}\n\n/**\n * Error thrown when verification fails\n */\nexport class TetherVerificationError extends TetherError {\n constructor(message: string, cause?: Error) {\n super(message, cause);\n this.name = 'TetherVerificationError';\n }\n}\n\n/**\n * Error thrown when API requests fail\n */\nexport class TetherAPIError extends TetherError {\n constructor(\n message: string,\n public readonly status?: number,\n public readonly response?: string,\n cause?: Error\n ) {\n super(message, cause);\n this.name = 'TetherAPIError';\n }\n}","import { createSign, createPrivateKey, KeyObject } from 'crypto';\nimport { readFileSync } from 'fs';\nimport { TetherError } from './errors.js';\nimport type { KeyFormat } from './types.js';\n\n/**\n * Imports a DER-encoded private key, trying PKCS#8 first then PKCS#1.\n */\nfunction importDerKey(derData: Buffer): KeyObject {\n try {\n return createPrivateKey({ key: derData, format: 'der', type: 'pkcs8' });\n } catch {\n // PKCS#8 failed — try PKCS#1\n }\n try {\n return createPrivateKey({ key: derData, format: 'der', type: 'pkcs1' });\n } catch {\n // PKCS#1 also failed\n }\n throw new TetherError(\n 'Failed to load DER private key: data is not valid PKCS#8 or PKCS#1. ' +\n 'Ensure the file is an RSA private key in DER format.'\n );\n}\n\n/**\n * Loads a private key from various sources\n */\nexport function loadPrivateKey(options: {\n keyPath?: string;\n keyPem?: string;\n keyBuffer?: Buffer;\n}): KeyObject {\n const { keyPath, keyPem, keyBuffer } = options;\n\n try {\n if (keyPem) {\n // PEM string provided directly\n return createPrivateKey(keyPem);\n }\n\n if (keyBuffer) {\n // DER buffer provided directly\n return importDerKey(keyBuffer);\n }\n\n if (keyPath) {\n // Read from file - detect format by extension or content\n const keyData = readFileSync(keyPath);\n\n // Try to detect format\n if (keyPath.endsWith('.pem') || keyData.toString().includes('-----BEGIN')) {\n // PEM format\n return createPrivateKey(keyData);\n } else {\n // Assume DER format\n return importDerKey(keyData);\n }\n }\n\n throw new TetherError('No private key provided');\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherError(\n `Failed to load private key: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Signs a challenge string using RSA-SHA256\n * Returns URL-safe base64 encoded signature (no padding)\n */\nexport function signChallenge(privateKey: KeyObject, challenge: string): string {\n try {\n const sign = createSign('SHA256');\n sign.update(challenge);\n sign.end();\n \n const signature = sign.sign(privateKey);\n \n // Convert to URL-safe base64 without padding\n return signature\n .toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=/g, '');\n } catch (error) {\n throw new TetherError(\n `Failed to sign challenge: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Utility function to detect key format from file extension or content\n */\nexport function detectKeyFormat(keyPath: string): KeyFormat {\n if (keyPath.endsWith('.pem')) {\n return 'pem';\n }\n if (keyPath.endsWith('.der')) {\n return 'der';\n }\n \n // Try to read a small portion to detect format\n try {\n const keyData = readFileSync(keyPath, { encoding: 'utf8', flag: 'r' });\n if (keyData.includes('-----BEGIN')) {\n return 'pem';\n }\n } catch {\n // If we can't read as text, it's probably DER\n }\n \n return 'der';\n}","import { KeyObject } from 'crypto';\nimport { TetherError, TetherAPIError, TetherVerificationError } from './errors.js';\nimport { loadPrivateKey, signChallenge } from './crypto.js';\nimport type {\n TetherClientConfig,\n ChallengeResponse,\n Agent,\n Domain,\n IssueAgentResponse,\n VerificationRequest,\n VerificationResponse,\n VerificationResult\n} from './types.js';\n\n/**\n * TetherClient - Official SDK for tether.name agent identity verification\n */\nexport class TetherClient {\n private readonly agentId: string;\n private readonly privateKey: KeyObject | null;\n private readonly baseUrl: string;\n private readonly apiKey?: string;\n\n constructor(config: TetherClientConfig) {\n // Set base URL\n this.baseUrl = 'https://api.tether.name';\n\n // Get API key from config or environment\n this.apiKey = config.apiKey || process.env.TETHER_API_KEY;\n\n // Get agent ID from config or environment\n this.agentId = config.agentId || process.env.TETHER_AGENT_ID || '';\n\n // Load private key if key material is provided\n const keyPath = config.privateKeyPath || process.env.TETHER_PRIVATE_KEY_PATH;\n const hasKeyMaterial = keyPath || config.privateKeyPem || config.privateKeyBuffer;\n\n if (hasKeyMaterial) {\n this.privateKey = loadPrivateKey({\n keyPath,\n keyPem: config.privateKeyPem,\n keyBuffer: config.privateKeyBuffer\n });\n } else {\n this.privateKey = null;\n }\n\n // If no API key and no private key, agent ID and key are still needed for verify/sign\n // but we defer the error to when those methods are called\n if (!this.apiKey && !this.privateKey) {\n // Allow construction — errors thrown at method call time\n }\n\n if (!this.apiKey && !this.agentId) {\n // Allow construction — errors thrown at method call time\n }\n }\n\n /**\n * Returns authorization headers when an API key is configured\n */\n private _authHeaders(): Record<string, string> {\n if (this.apiKey) {\n return { 'Authorization': `Bearer ${this.apiKey}` };\n }\n return {};\n }\n\n /**\n * Ensures a private key is available, throwing if not\n */\n private _requirePrivateKey(): KeyObject {\n if (!this.privateKey) {\n throw new TetherError(\n 'Private key is required for this operation. Provide privateKeyPath, privateKeyPem, or privateKeyBuffer in config, or set TETHER_PRIVATE_KEY_PATH environment variable.'\n );\n }\n return this.privateKey;\n }\n\n /**\n * Ensures an API key is available, throwing if not\n */\n private _requireApiKey(): void {\n if (!this.apiKey) {\n throw new TetherError(\n 'API key is required for agent management operations. Provide apiKey in config or set TETHER_API_KEY environment variable.'\n );\n }\n }\n\n /**\n * Ensures an agent ID is available, throwing if not\n */\n private _requireAgentId(): string {\n if (!this.agentId) {\n throw new TetherError(\n 'Agent ID is required for this operation. Provide it in config or set TETHER_AGENT_ID environment variable.'\n );\n }\n return this.agentId;\n }\n\n /**\n * Request a challenge from the Tether API\n */\n async requestChallenge(): Promise<string> {\n try {\n const response = await fetch(`${this.baseUrl}/challenge`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Challenge request failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as ChallengeResponse;\n\n if (!data.code) {\n throw new TetherAPIError('Invalid challenge response: missing code');\n }\n\n return data.code;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to request challenge: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Sign a challenge string\n */\n sign(challenge: string): string {\n const key = this._requirePrivateKey();\n return signChallenge(key, challenge);\n }\n\n /**\n * Submit proof for a challenge\n */\n async submitProof(challenge: string, proof: string): Promise<VerificationResult> {\n const agentId = this._requireAgentId();\n\n try {\n const payload: VerificationRequest = {\n challenge,\n proof,\n agentId\n };\n\n const response = await fetch(`${this.baseUrl}/challenge/verify`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(payload)\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Verification failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as VerificationResponse;\n\n // Convert API response to our result format\n const registeredSince = typeof data.registeredSince === 'number'\n ? new Date(data.registeredSince).toISOString()\n : data.registeredSince;\n\n return {\n verified: data.valid,\n agentName: data.agentName,\n verifyUrl: data.verifyUrl,\n email: data.email,\n domain: data.domain,\n registeredSince,\n error: data.error,\n challenge\n };\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to submit proof: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Perform complete verification in one call\n */\n async verify(): Promise<VerificationResult> {\n try {\n const challenge = await this.requestChallenge();\n const proof = this.sign(challenge);\n const result = await this.submitProof(challenge, proof);\n\n if (!result.verified) {\n throw new TetherVerificationError(\n result.error || 'Verification failed for unknown reason'\n );\n }\n\n return result;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherVerificationError(\n `Verification failed: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Create a new agent\n */\n async createAgent(agentName: string, description: string = '', domainId?: string): Promise<Agent> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/agents/issue`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...this._authHeaders()\n },\n body: JSON.stringify({ agentName, description, ...(domainId ? { domainId } : {}) })\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Create agent failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as IssueAgentResponse;\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to create agent: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * List all agents\n */\n async listAgents(): Promise<Agent[]> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/agents`, {\n method: 'GET',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `List agents failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as Agent[];\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to list agents: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * List all registered domains\n */\n async listDomains(): Promise<Domain[]> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/domains`, {\n method: 'GET',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `List domains failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as Domain[];\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to list domains: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Delete an agent by ID\n */\n async deleteAgent(agentId: string): Promise<boolean> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/agents/${agentId}`, {\n method: 'DELETE',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Delete agent failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n return true;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to delete agent: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -242,6 +242,7 @@ var TetherClient = class {
|
|
|
242
242
|
agentName: data.agentName,
|
|
243
243
|
verifyUrl: data.verifyUrl,
|
|
244
244
|
email: data.email,
|
|
245
|
+
domain: data.domain,
|
|
245
246
|
registeredSince,
|
|
246
247
|
error: data.error,
|
|
247
248
|
challenge
|
|
@@ -285,7 +286,7 @@ var TetherClient = class {
|
|
|
285
286
|
/**
|
|
286
287
|
* Create a new agent
|
|
287
288
|
*/
|
|
288
|
-
async createAgent(agentName, description = "") {
|
|
289
|
+
async createAgent(agentName, description = "", domainId) {
|
|
289
290
|
this._requireApiKey();
|
|
290
291
|
try {
|
|
291
292
|
const response = await fetch(`${this.baseUrl}/agents/issue`, {
|
|
@@ -294,7 +295,7 @@ var TetherClient = class {
|
|
|
294
295
|
"Content-Type": "application/json",
|
|
295
296
|
...this._authHeaders()
|
|
296
297
|
},
|
|
297
|
-
body: JSON.stringify({ agentName, description })
|
|
298
|
+
body: JSON.stringify({ agentName, description, ...domainId ? { domainId } : {} })
|
|
298
299
|
});
|
|
299
300
|
if (!response.ok) {
|
|
300
301
|
const errorText = await response.text().catch(() => "Unknown error");
|
|
@@ -352,6 +353,40 @@ var TetherClient = class {
|
|
|
352
353
|
);
|
|
353
354
|
}
|
|
354
355
|
}
|
|
356
|
+
/**
|
|
357
|
+
* List all registered domains
|
|
358
|
+
*/
|
|
359
|
+
async listDomains() {
|
|
360
|
+
this._requireApiKey();
|
|
361
|
+
try {
|
|
362
|
+
const response = await fetch(`${this.baseUrl}/domains`, {
|
|
363
|
+
method: "GET",
|
|
364
|
+
headers: {
|
|
365
|
+
...this._authHeaders()
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
if (!response.ok) {
|
|
369
|
+
const errorText = await response.text().catch(() => "Unknown error");
|
|
370
|
+
throw new TetherAPIError(
|
|
371
|
+
`List domains failed: ${response.status} ${response.statusText}`,
|
|
372
|
+
response.status,
|
|
373
|
+
errorText
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
const data = await response.json();
|
|
377
|
+
return data;
|
|
378
|
+
} catch (error) {
|
|
379
|
+
if (error instanceof TetherError) {
|
|
380
|
+
throw error;
|
|
381
|
+
}
|
|
382
|
+
throw new TetherAPIError(
|
|
383
|
+
`Failed to list domains: ${error instanceof Error ? error.message : String(error)}`,
|
|
384
|
+
void 0,
|
|
385
|
+
void 0,
|
|
386
|
+
error instanceof Error ? error : void 0
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
355
390
|
/**
|
|
356
391
|
* Delete an agent by ID
|
|
357
392
|
*/
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/crypto.ts","../src/client.ts"],"sourcesContent":["/**\n * Base error class for all Tether-related errors\n */\nexport class TetherError extends Error {\n constructor(message: string, public readonly cause?: Error) {\n super(message);\n this.name = 'TetherError';\n \n // Maintain proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, TetherError);\n }\n }\n}\n\n/**\n * Error thrown when verification fails\n */\nexport class TetherVerificationError extends TetherError {\n constructor(message: string, cause?: Error) {\n super(message, cause);\n this.name = 'TetherVerificationError';\n }\n}\n\n/**\n * Error thrown when API requests fail\n */\nexport class TetherAPIError extends TetherError {\n constructor(\n message: string,\n public readonly status?: number,\n public readonly response?: string,\n cause?: Error\n ) {\n super(message, cause);\n this.name = 'TetherAPIError';\n }\n}","import { createSign, createPrivateKey, KeyObject } from 'crypto';\nimport { readFileSync } from 'fs';\nimport { TetherError } from './errors.js';\nimport type { KeyFormat } from './types.js';\n\n/**\n * Imports a DER-encoded private key, trying PKCS#8 first then PKCS#1.\n */\nfunction importDerKey(derData: Buffer): KeyObject {\n try {\n return createPrivateKey({ key: derData, format: 'der', type: 'pkcs8' });\n } catch {\n // PKCS#8 failed — try PKCS#1\n }\n try {\n return createPrivateKey({ key: derData, format: 'der', type: 'pkcs1' });\n } catch {\n // PKCS#1 also failed\n }\n throw new TetherError(\n 'Failed to load DER private key: data is not valid PKCS#8 or PKCS#1. ' +\n 'Ensure the file is an RSA private key in DER format.'\n );\n}\n\n/**\n * Loads a private key from various sources\n */\nexport function loadPrivateKey(options: {\n keyPath?: string;\n keyPem?: string;\n keyBuffer?: Buffer;\n}): KeyObject {\n const { keyPath, keyPem, keyBuffer } = options;\n\n try {\n if (keyPem) {\n // PEM string provided directly\n return createPrivateKey(keyPem);\n }\n\n if (keyBuffer) {\n // DER buffer provided directly\n return importDerKey(keyBuffer);\n }\n\n if (keyPath) {\n // Read from file - detect format by extension or content\n const keyData = readFileSync(keyPath);\n\n // Try to detect format\n if (keyPath.endsWith('.pem') || keyData.toString().includes('-----BEGIN')) {\n // PEM format\n return createPrivateKey(keyData);\n } else {\n // Assume DER format\n return importDerKey(keyData);\n }\n }\n\n throw new TetherError('No private key provided');\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherError(\n `Failed to load private key: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Signs a challenge string using RSA-SHA256\n * Returns URL-safe base64 encoded signature (no padding)\n */\nexport function signChallenge(privateKey: KeyObject, challenge: string): string {\n try {\n const sign = createSign('SHA256');\n sign.update(challenge);\n sign.end();\n \n const signature = sign.sign(privateKey);\n \n // Convert to URL-safe base64 without padding\n return signature\n .toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=/g, '');\n } catch (error) {\n throw new TetherError(\n `Failed to sign challenge: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Utility function to detect key format from file extension or content\n */\nexport function detectKeyFormat(keyPath: string): KeyFormat {\n if (keyPath.endsWith('.pem')) {\n return 'pem';\n }\n if (keyPath.endsWith('.der')) {\n return 'der';\n }\n \n // Try to read a small portion to detect format\n try {\n const keyData = readFileSync(keyPath, { encoding: 'utf8', flag: 'r' });\n if (keyData.includes('-----BEGIN')) {\n return 'pem';\n }\n } catch {\n // If we can't read as text, it's probably DER\n }\n \n return 'der';\n}","import { KeyObject } from 'crypto';\nimport { TetherError, TetherAPIError, TetherVerificationError } from './errors.js';\nimport { loadPrivateKey, signChallenge } from './crypto.js';\nimport type {\n TetherClientConfig,\n ChallengeResponse,\n Agent,\n IssueAgentResponse,\n VerificationRequest,\n VerificationResponse,\n VerificationResult\n} from './types.js';\n\n/**\n * TetherClient - Official SDK for tether.name agent identity verification\n */\nexport class TetherClient {\n private readonly agentId: string;\n private readonly privateKey: KeyObject | null;\n private readonly baseUrl: string;\n private readonly apiKey?: string;\n\n constructor(config: TetherClientConfig) {\n // Set base URL\n this.baseUrl = 'https://api.tether.name';\n\n // Get API key from config or environment\n this.apiKey = config.apiKey || process.env.TETHER_API_KEY;\n\n // Get agent ID from config or environment\n this.agentId = config.agentId || process.env.TETHER_AGENT_ID || '';\n\n // Load private key if key material is provided\n const keyPath = config.privateKeyPath || process.env.TETHER_PRIVATE_KEY_PATH;\n const hasKeyMaterial = keyPath || config.privateKeyPem || config.privateKeyBuffer;\n\n if (hasKeyMaterial) {\n this.privateKey = loadPrivateKey({\n keyPath,\n keyPem: config.privateKeyPem,\n keyBuffer: config.privateKeyBuffer\n });\n } else {\n this.privateKey = null;\n }\n\n // If no API key and no private key, agent ID and key are still needed for verify/sign\n // but we defer the error to when those methods are called\n if (!this.apiKey && !this.privateKey) {\n // Allow construction — errors thrown at method call time\n }\n\n if (!this.apiKey && !this.agentId) {\n // Allow construction — errors thrown at method call time\n }\n }\n\n /**\n * Returns authorization headers when an API key is configured\n */\n private _authHeaders(): Record<string, string> {\n if (this.apiKey) {\n return { 'Authorization': `Bearer ${this.apiKey}` };\n }\n return {};\n }\n\n /**\n * Ensures a private key is available, throwing if not\n */\n private _requirePrivateKey(): KeyObject {\n if (!this.privateKey) {\n throw new TetherError(\n 'Private key is required for this operation. Provide privateKeyPath, privateKeyPem, or privateKeyBuffer in config, or set TETHER_PRIVATE_KEY_PATH environment variable.'\n );\n }\n return this.privateKey;\n }\n\n /**\n * Ensures an API key is available, throwing if not\n */\n private _requireApiKey(): void {\n if (!this.apiKey) {\n throw new TetherError(\n 'API key is required for agent management operations. Provide apiKey in config or set TETHER_API_KEY environment variable.'\n );\n }\n }\n\n /**\n * Ensures an agent ID is available, throwing if not\n */\n private _requireAgentId(): string {\n if (!this.agentId) {\n throw new TetherError(\n 'Agent ID is required for this operation. Provide it in config or set TETHER_AGENT_ID environment variable.'\n );\n }\n return this.agentId;\n }\n\n /**\n * Request a challenge from the Tether API\n */\n async requestChallenge(): Promise<string> {\n try {\n const response = await fetch(`${this.baseUrl}/challenge`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Challenge request failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as ChallengeResponse;\n\n if (!data.code) {\n throw new TetherAPIError('Invalid challenge response: missing code');\n }\n\n return data.code;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to request challenge: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Sign a challenge string\n */\n sign(challenge: string): string {\n const key = this._requirePrivateKey();\n return signChallenge(key, challenge);\n }\n\n /**\n * Submit proof for a challenge\n */\n async submitProof(challenge: string, proof: string): Promise<VerificationResult> {\n const agentId = this._requireAgentId();\n\n try {\n const payload: VerificationRequest = {\n challenge,\n proof,\n agentId\n };\n\n const response = await fetch(`${this.baseUrl}/challenge/verify`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(payload)\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Verification failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as VerificationResponse;\n\n // Convert API response to our result format\n const registeredSince = typeof data.registeredSince === 'number'\n ? new Date(data.registeredSince).toISOString()\n : data.registeredSince;\n\n return {\n verified: data.valid,\n agentName: data.agentName,\n verifyUrl: data.verifyUrl,\n email: data.email,\n registeredSince,\n error: data.error,\n challenge\n };\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to submit proof: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Perform complete verification in one call\n */\n async verify(): Promise<VerificationResult> {\n try {\n const challenge = await this.requestChallenge();\n const proof = this.sign(challenge);\n const result = await this.submitProof(challenge, proof);\n\n if (!result.verified) {\n throw new TetherVerificationError(\n result.error || 'Verification failed for unknown reason'\n );\n }\n\n return result;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherVerificationError(\n `Verification failed: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Create a new agent\n */\n async createAgent(agentName: string, description: string = ''): Promise<Agent> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/agents/issue`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...this._authHeaders()\n },\n body: JSON.stringify({ agentName, description })\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Create agent failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as IssueAgentResponse;\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to create agent: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * List all agents\n */\n async listAgents(): Promise<Agent[]> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/agents`, {\n method: 'GET',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `List agents failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as Agent[];\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to list agents: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Delete an agent by ID\n */\n async deleteAgent(agentId: string): Promise<boolean> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/agents/${agentId}`, {\n method: 'DELETE',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Delete agent failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n return true;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to delete agent: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/crypto.ts","../src/client.ts"],"sourcesContent":["/**\n * Base error class for all Tether-related errors\n */\nexport class TetherError extends Error {\n constructor(message: string, public readonly cause?: Error) {\n super(message);\n this.name = 'TetherError';\n \n // Maintain proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, TetherError);\n }\n }\n}\n\n/**\n * Error thrown when verification fails\n */\nexport class TetherVerificationError extends TetherError {\n constructor(message: string, cause?: Error) {\n super(message, cause);\n this.name = 'TetherVerificationError';\n }\n}\n\n/**\n * Error thrown when API requests fail\n */\nexport class TetherAPIError extends TetherError {\n constructor(\n message: string,\n public readonly status?: number,\n public readonly response?: string,\n cause?: Error\n ) {\n super(message, cause);\n this.name = 'TetherAPIError';\n }\n}","import { createSign, createPrivateKey, KeyObject } from 'crypto';\nimport { readFileSync } from 'fs';\nimport { TetherError } from './errors.js';\nimport type { KeyFormat } from './types.js';\n\n/**\n * Imports a DER-encoded private key, trying PKCS#8 first then PKCS#1.\n */\nfunction importDerKey(derData: Buffer): KeyObject {\n try {\n return createPrivateKey({ key: derData, format: 'der', type: 'pkcs8' });\n } catch {\n // PKCS#8 failed — try PKCS#1\n }\n try {\n return createPrivateKey({ key: derData, format: 'der', type: 'pkcs1' });\n } catch {\n // PKCS#1 also failed\n }\n throw new TetherError(\n 'Failed to load DER private key: data is not valid PKCS#8 or PKCS#1. ' +\n 'Ensure the file is an RSA private key in DER format.'\n );\n}\n\n/**\n * Loads a private key from various sources\n */\nexport function loadPrivateKey(options: {\n keyPath?: string;\n keyPem?: string;\n keyBuffer?: Buffer;\n}): KeyObject {\n const { keyPath, keyPem, keyBuffer } = options;\n\n try {\n if (keyPem) {\n // PEM string provided directly\n return createPrivateKey(keyPem);\n }\n\n if (keyBuffer) {\n // DER buffer provided directly\n return importDerKey(keyBuffer);\n }\n\n if (keyPath) {\n // Read from file - detect format by extension or content\n const keyData = readFileSync(keyPath);\n\n // Try to detect format\n if (keyPath.endsWith('.pem') || keyData.toString().includes('-----BEGIN')) {\n // PEM format\n return createPrivateKey(keyData);\n } else {\n // Assume DER format\n return importDerKey(keyData);\n }\n }\n\n throw new TetherError('No private key provided');\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherError(\n `Failed to load private key: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Signs a challenge string using RSA-SHA256\n * Returns URL-safe base64 encoded signature (no padding)\n */\nexport function signChallenge(privateKey: KeyObject, challenge: string): string {\n try {\n const sign = createSign('SHA256');\n sign.update(challenge);\n sign.end();\n \n const signature = sign.sign(privateKey);\n \n // Convert to URL-safe base64 without padding\n return signature\n .toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=/g, '');\n } catch (error) {\n throw new TetherError(\n `Failed to sign challenge: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Utility function to detect key format from file extension or content\n */\nexport function detectKeyFormat(keyPath: string): KeyFormat {\n if (keyPath.endsWith('.pem')) {\n return 'pem';\n }\n if (keyPath.endsWith('.der')) {\n return 'der';\n }\n \n // Try to read a small portion to detect format\n try {\n const keyData = readFileSync(keyPath, { encoding: 'utf8', flag: 'r' });\n if (keyData.includes('-----BEGIN')) {\n return 'pem';\n }\n } catch {\n // If we can't read as text, it's probably DER\n }\n \n return 'der';\n}","import { KeyObject } from 'crypto';\nimport { TetherError, TetherAPIError, TetherVerificationError } from './errors.js';\nimport { loadPrivateKey, signChallenge } from './crypto.js';\nimport type {\n TetherClientConfig,\n ChallengeResponse,\n Agent,\n Domain,\n IssueAgentResponse,\n VerificationRequest,\n VerificationResponse,\n VerificationResult\n} from './types.js';\n\n/**\n * TetherClient - Official SDK for tether.name agent identity verification\n */\nexport class TetherClient {\n private readonly agentId: string;\n private readonly privateKey: KeyObject | null;\n private readonly baseUrl: string;\n private readonly apiKey?: string;\n\n constructor(config: TetherClientConfig) {\n // Set base URL\n this.baseUrl = 'https://api.tether.name';\n\n // Get API key from config or environment\n this.apiKey = config.apiKey || process.env.TETHER_API_KEY;\n\n // Get agent ID from config or environment\n this.agentId = config.agentId || process.env.TETHER_AGENT_ID || '';\n\n // Load private key if key material is provided\n const keyPath = config.privateKeyPath || process.env.TETHER_PRIVATE_KEY_PATH;\n const hasKeyMaterial = keyPath || config.privateKeyPem || config.privateKeyBuffer;\n\n if (hasKeyMaterial) {\n this.privateKey = loadPrivateKey({\n keyPath,\n keyPem: config.privateKeyPem,\n keyBuffer: config.privateKeyBuffer\n });\n } else {\n this.privateKey = null;\n }\n\n // If no API key and no private key, agent ID and key are still needed for verify/sign\n // but we defer the error to when those methods are called\n if (!this.apiKey && !this.privateKey) {\n // Allow construction — errors thrown at method call time\n }\n\n if (!this.apiKey && !this.agentId) {\n // Allow construction — errors thrown at method call time\n }\n }\n\n /**\n * Returns authorization headers when an API key is configured\n */\n private _authHeaders(): Record<string, string> {\n if (this.apiKey) {\n return { 'Authorization': `Bearer ${this.apiKey}` };\n }\n return {};\n }\n\n /**\n * Ensures a private key is available, throwing if not\n */\n private _requirePrivateKey(): KeyObject {\n if (!this.privateKey) {\n throw new TetherError(\n 'Private key is required for this operation. Provide privateKeyPath, privateKeyPem, or privateKeyBuffer in config, or set TETHER_PRIVATE_KEY_PATH environment variable.'\n );\n }\n return this.privateKey;\n }\n\n /**\n * Ensures an API key is available, throwing if not\n */\n private _requireApiKey(): void {\n if (!this.apiKey) {\n throw new TetherError(\n 'API key is required for agent management operations. Provide apiKey in config or set TETHER_API_KEY environment variable.'\n );\n }\n }\n\n /**\n * Ensures an agent ID is available, throwing if not\n */\n private _requireAgentId(): string {\n if (!this.agentId) {\n throw new TetherError(\n 'Agent ID is required for this operation. Provide it in config or set TETHER_AGENT_ID environment variable.'\n );\n }\n return this.agentId;\n }\n\n /**\n * Request a challenge from the Tether API\n */\n async requestChallenge(): Promise<string> {\n try {\n const response = await fetch(`${this.baseUrl}/challenge`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Challenge request failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as ChallengeResponse;\n\n if (!data.code) {\n throw new TetherAPIError('Invalid challenge response: missing code');\n }\n\n return data.code;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to request challenge: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Sign a challenge string\n */\n sign(challenge: string): string {\n const key = this._requirePrivateKey();\n return signChallenge(key, challenge);\n }\n\n /**\n * Submit proof for a challenge\n */\n async submitProof(challenge: string, proof: string): Promise<VerificationResult> {\n const agentId = this._requireAgentId();\n\n try {\n const payload: VerificationRequest = {\n challenge,\n proof,\n agentId\n };\n\n const response = await fetch(`${this.baseUrl}/challenge/verify`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(payload)\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Verification failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as VerificationResponse;\n\n // Convert API response to our result format\n const registeredSince = typeof data.registeredSince === 'number'\n ? new Date(data.registeredSince).toISOString()\n : data.registeredSince;\n\n return {\n verified: data.valid,\n agentName: data.agentName,\n verifyUrl: data.verifyUrl,\n email: data.email,\n domain: data.domain,\n registeredSince,\n error: data.error,\n challenge\n };\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to submit proof: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Perform complete verification in one call\n */\n async verify(): Promise<VerificationResult> {\n try {\n const challenge = await this.requestChallenge();\n const proof = this.sign(challenge);\n const result = await this.submitProof(challenge, proof);\n\n if (!result.verified) {\n throw new TetherVerificationError(\n result.error || 'Verification failed for unknown reason'\n );\n }\n\n return result;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherVerificationError(\n `Verification failed: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Create a new agent\n */\n async createAgent(agentName: string, description: string = '', domainId?: string): Promise<Agent> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/agents/issue`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...this._authHeaders()\n },\n body: JSON.stringify({ agentName, description, ...(domainId ? { domainId } : {}) })\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Create agent failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as IssueAgentResponse;\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to create agent: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * List all agents\n */\n async listAgents(): Promise<Agent[]> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/agents`, {\n method: 'GET',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `List agents failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as Agent[];\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to list agents: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * List all registered domains\n */\n async listDomains(): Promise<Domain[]> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/domains`, {\n method: 'GET',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `List domains failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n const data = await response.json() as Domain[];\n return data;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to list domains: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Delete an agent by ID\n */\n async deleteAgent(agentId: string): Promise<boolean> {\n this._requireApiKey();\n try {\n const response = await fetch(`${this.baseUrl}/agents/${agentId}`, {\n method: 'DELETE',\n headers: {\n ...this._authHeaders()\n }\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new TetherAPIError(\n `Delete agent failed: ${response.status} ${response.statusText}`,\n response.status,\n errorText\n );\n }\n\n return true;\n } catch (error) {\n if (error instanceof TetherError) {\n throw error;\n }\n throw new TetherAPIError(\n `Failed to delete agent: ${error instanceof Error ? error.message : String(error)}`,\n undefined,\n undefined,\n error instanceof Error ? error : undefined\n );\n }\n }\n}\n"],"mappings":"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","names":[]}
|