UNPKG

@astrasyncai/sdk

Version:

Official Node.js SDK for the AstraSync KYA Platform — register and manage AI agents with verified identities

168 lines (167 loc) 5.69 kB
// src/errors.ts var AstraSyncError = class extends Error { constructor(message, statusCode, code) { super(message); this.name = "AstraSyncError"; this.statusCode = statusCode; this.code = code; } }; var KYDRequiredError = class extends AstraSyncError { constructor(response) { const kydUrl = response.kydUrl || "https://app.kya.astrasync.ai/developer-profile"; super( `KYD verification required before registering agents. Complete your KYD profile at: ${kydUrl}`, 403, "KYD_REQUIRED" ); this.name = "KYDRequiredError"; this.kydUrl = kydUrl; this.ownerNotified = response.ownerNotified || false; } }; var AuthenticationError = class extends AstraSyncError { constructor(message) { super(message, 401, "AUTH_FAILED"); this.name = "AuthenticationError"; } }; // src/api.ts var DEFAULT_BASE_URL = "https://api.kya.astrasync.ai"; var AstraSync = class { constructor(config = {}) { this.baseUrl = (config.baseUrl || process.env.ASTRASYNC_API_URL || DEFAULT_BASE_URL).replace(/\/+$/, ""); this.apiKey = config.apiKey || process.env.ASTRASYNC_API_KEY; this.email = config.email; this.password = config.password; this.privateKey = config.privateKey; if (!this.apiKey && !this.email) { throw new AuthenticationError( "Authentication required. Provide apiKey, or email+password. Set ASTRASYNC_API_KEY env var or pass config to constructor." ); } if (this.email && !this.password) { throw new AuthenticationError("Password is required when using email authentication."); } } /** * Register a new AI agent on the AstraSync KYA Platform. * Sends full payload including model, framework, PDLSS, and metadata. */ async register(options) { const body = { name: options.name, ...options.description && { description: options.description }, ...options.agentType && { agentType: options.agentType }, ...options.apiEndpoint && { apiEndpoint: options.apiEndpoint }, ...options.model && { model: options.model }, ...options.framework && { framework: options.framework }, ...options.metadata && { metadata: options.metadata }, ...options.pdlss && { pdlss: options.pdlss } }; return this.request("POST", "/api/agents/register", body); } /** * Look up an agent's public profile by ASTRA ID or UUID. */ async verify(agentId) { return this.request("GET", `/api/agents/verify/${agentId}`); } /** * Check API health. */ async health() { const res = await fetch(`${this.baseUrl}/api/health/`); if (!res.ok) { throw new AstraSyncError(`Health check failed: ${res.status}`, res.status); } return res.json(); } // ── Private helpers ────────────────────────────────────────────── async request(method, endpoint, body) { const url = `${this.baseUrl}${endpoint}`; const headers = { "Content-Type": "application/json" }; const token = await this.getAuthToken(); headers["Authorization"] = `Bearer ${token}`; if (this.privateKey) { const signature = await this.signRequest(method, endpoint, body || {}); headers["X-AstraSync-Signature"] = signature; } const res = await fetch(url, { method, headers, ...body ? { body: JSON.stringify(body) } : {} }); if (!res.ok) { const errorBody = await res.json().catch(() => ({ error: res.statusText })); if (res.status === 403 && errorBody.code === "KYD_REQUIRED") { throw new KYDRequiredError(errorBody); } throw new AstraSyncError( errorBody.error || `Request failed: ${res.status}`, res.status, errorBody.code ); } return res.json(); } async getAuthToken() { if (this.apiKey) { return this.apiKey; } if (this.cachedJwt && this.jwtExpiresAt && Date.now() < this.jwtExpiresAt) { return this.cachedJwt; } const res = await fetch(`${this.baseUrl}/api/auth/login`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email: this.email, password: this.password }) }); if (!res.ok) { const errorBody = await res.json().catch(() => ({})); throw new AuthenticationError( errorBody.message || errorBody.error || "Login failed" ); } const data = await res.json(); this.cachedJwt = data.data.token; this.jwtExpiresAt = Date.now() + 6 * 24 * 60 * 60 * 1e3; return this.cachedJwt; } /** * Sign a request using secp256k1 (ethers.js). * Canonical message format: METHOD:ENDPOINT:SORTED_JSON_BODY * Must match apps/backend/src/services/signature-verify.service.ts exactly. */ async signRequest(method, endpoint, body) { const { Wallet } = await import("ethers"); const sorted = this.sortObjectKeys(body); const canonical = `${method}:${endpoint}:${JSON.stringify(sorted)}`; const wallet = new Wallet(this.privateKey); return wallet.signMessage(canonical); } /** Recursively sort object keys for canonical JSON representation. */ sortObjectKeys(obj) { if (obj === null || typeof obj !== "object") { return obj; } if (Array.isArray(obj)) { return obj.map((item) => this.sortObjectKeys(item)); } const sorted = {}; for (const key of Object.keys(obj).sort()) { sorted[key] = this.sortObjectKeys(obj[key]); } return sorted; } }; export { AstraSync, AstraSyncError, AuthenticationError, KYDRequiredError }; //# sourceMappingURL=index.mjs.map