@kya-os/cli
Version:
CLI for MCP-I setup and management
149 lines • 4.91 kB
JavaScript
/**
* Know-That-AI (KTA) API utilities
* Handles delegation checking and other KTA API interactions
*/
import { z } from "zod";
import contractsRegistry from "@kya-os/contracts/registry";
const { KTA_BASE_URL, AgentStatusSchema } = contractsRegistry;
/**
* Delegation status response from KTA
* Accept both kid and keyId for backward compatibility
*/
export const DelegationStatusSchema = z.object({
did: z.string(),
// Accept either kid or keyId (server may use either during transition)
kid: z.string().optional(),
keyId: z.string().optional(),
status: z.enum(["active", "revoked", "not_found"]),
delegatedTo: z.string().optional(),
expiresAt: z.number().optional(),
lastUpdated: z.number(),
}).refine((data) => data.kid || data.keyId, {
message: "Either kid or keyId must be provided",
}).transform((data) => ({
...data,
// Normalize: ensure kid is always present (safe due to refine check)
kid: data.kid || data.keyId,
}));
/**
* KTA API client for delegation checking
*/
export class KTAApiClient {
constructor(baseURL = KTA_BASE_URL, apiKey) {
this.baseURL = baseURL;
this.apiKey =
apiKey || process.env.KYA_VOUCHED_API_KEY || process.env.VOUCHED_API_KEY;
}
/**
* Check delegation status for a DID/KeyID pair
* This is the exact KTA lookup API used for delegation confirmation
*/
async checkDelegation(did, kid) {
const url = new URL(`/api/v1/delegations/status`, this.baseURL);
url.searchParams.set("did", did);
// Send both kid and keyId for backward compatibility
// Server may expect either parameter name during transition period
url.searchParams.set("kid", kid);
url.searchParams.set("keyId", kid);
const headers = {
"Content-Type": "application/json",
"User-Agent": "mcpi-cli/1.0.0",
};
if (this.apiKey) {
headers["Authorization"] = `Bearer ${this.apiKey}`;
}
try {
const response = await fetch(url.toString(), {
method: "GET",
headers,
});
if (!response.ok) {
if (response.status === 404) {
return {
did,
kid,
status: "not_found",
lastUpdated: Date.now(),
};
}
throw new Error(`KTA API error: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return DelegationStatusSchema.parse(data);
}
catch (error) {
if (error instanceof Error) {
throw new Error(`Failed to check delegation: ${error.message}`);
}
throw new Error("Failed to check delegation: Unknown error");
}
}
/**
* Check if KTA is reachable
*/
async isReachable() {
try {
const response = await fetch(`${this.baseURL}/api/health`, {
method: "GET",
headers: {
"User-Agent": "mcpi-cli/1.0.0",
},
// Short timeout for health check
signal: AbortSignal.timeout(5000),
});
return response.ok;
}
catch {
return false;
}
}
/**
* Get agent status from KTA
*/
async getAgentStatus(did) {
const url = new URL(`/api/v1/agents/status`, this.baseURL);
url.searchParams.set("did", did);
const headers = {
"Content-Type": "application/json",
"User-Agent": "mcpi-cli/1.0.0",
};
if (this.apiKey) {
headers["Authorization"] = `Bearer ${this.apiKey}`;
}
const response = await fetch(url.toString(), {
method: "GET",
headers,
});
if (!response.ok) {
throw new Error(`KTA API error: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return AgentStatusSchema.parse(data);
}
}
/**
* Default KTA API client instance
*/
export const ktaApi = new KTAApiClient();
/**
* Check if a delegation exists for the given DID/KeyID pair
* Returns true if delegation is active, false otherwise
*/
export async function hasDelegation(did, kid) {
try {
const status = await ktaApi.checkDelegation(did, kid);
return status.status === "active";
}
catch (error) {
// If we can't check delegation, assume false for safety
console.warn(`Warning: Could not check delegation status: ${error}`);
return false;
}
}
/**
* Check if KTA is available
*/
export async function isKTAAvailable() {
return ktaApi.isReachable();
}
//# sourceMappingURL=kta-api.js.map