UNPKG

@nuwa-ai/cap-kit

Version:
731 lines (725 loc) 23.1 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { CapArtifactSchema: () => CapArtifactSchema, CapAuthorDIDSchema: () => CapAuthorDIDSchema, CapCoreSchema: () => CapCoreSchema, CapIDNameSchema: () => CapIDNameSchema, CapIDSchema: () => CapIDSchema, CapKitMcp: () => CapKitMcp, CapKitRestful: () => CapKitRestful, CapMcpServerSchema: () => CapMcpServerSchema, CapMetadataSchema: () => CapMetadataSchema, CapModelSchema: () => CapModelSchema, CapPromptSchema: () => CapPromptSchema, CapPromptSuggestionSchema: () => CapPromptSuggestionSchema, CapSchema: () => CapSchema, CapStatsSchema: () => CapStatsSchema, CapThumbnailSchema: () => CapThumbnailSchema, RatingDistribution: () => RatingDistribution, ResultCapMetadataSchema: () => ResultCapMetadataSchema }); module.exports = __toCommonJS(index_exports); // src/type.ts var import_v3 = require("zod/v3"); var CapAuthorDIDSchema = import_v3.z.string().startsWith("did:"); var CapIDNameSchema = import_v3.z.string().regex(/^[a-z0-9_]+$/, "Name must contain only lowercase letters, numbers, and underscores").min(6, "Name must be at least 6 characters").max(20, "Name must be at most 20 characters"); var CapArtifactSchema = import_v3.z.object({ srcUrl: import_v3.z.string().url("Must be a valid URL") }); var CapIDSchema = import_v3.z.object({ authorDID: CapAuthorDIDSchema, idName: CapIDNameSchema }).transform((data) => ({ ...data, id: `${data.authorDID}:${data.idName}` })); var CapModelSchema = import_v3.z.object({ customGatewayUrl: import_v3.z.string().url("Must be a valid URL").optional(), providerId: import_v3.z.enum([ "openai_chat_completion", "openai_responses", "anthropic", "google", "openrouter", "xai", "groq", "togetherai", "azure", "deepseek", "mistral" ]), modelId: import_v3.z.string().max(50, "Model ID must be at most 50 characters").refine((id) => id.length > 0, "Model ID is required"), parameters: import_v3.z.record(import_v3.z.string(), import_v3.z.any()).optional(), supportedInputs: import_v3.z.array(import_v3.z.enum(["text", "image", "file", "audio"])).min(1).refine((inputs) => inputs.includes("text"), "text input is required"), contextLength: import_v3.z.number().min(1e3, "Please enter a valid context length") }); var CapPromptSuggestionSchema = import_v3.z.string().max(100, "Each suggestion must be at most 50 characters"); var CapPromptSchema = import_v3.z.object({ value: import_v3.z.string(), suggestions: import_v3.z.array(CapPromptSuggestionSchema).optional() }); var CapMcpServerSchema = import_v3.z.string().url("Must be a valid URL"); var CapCoreSchema = import_v3.z.object({ prompt: CapPromptSchema, model: CapModelSchema, mcpServers: import_v3.z.record(import_v3.z.string(), CapMcpServerSchema), artifact: CapArtifactSchema.optional() }); var CapThumbnailSchema = import_v3.z.string().url("Must be a valid URL").optional(); var CapMetadataSchema = import_v3.z.object({ displayName: import_v3.z.string().min(1, "Display name is required").max(50, "Display name too long"), description: import_v3.z.string().min(10, "Description must be at least 10 characters").max(150, "Description too long"), introduction: import_v3.z.string().min(10, "Introduction must be at least 10 characters").max(5e3, "Introduction too long"), tags: import_v3.z.array(import_v3.z.string()).min(1, "At least one tag is required"), homepage: import_v3.z.string().url("Must be a valid URL").optional(), repository: import_v3.z.string().url("Must be a valid URL").optional(), thumbnail: CapThumbnailSchema }); var CapSchema = CapIDSchema.and( import_v3.z.object({ core: CapCoreSchema, metadata: CapMetadataSchema }) ); var CapStatsSchema = import_v3.z.object({ capId: import_v3.z.string(), downloads: import_v3.z.number(), ratingCount: import_v3.z.number(), averageRating: import_v3.z.number(), favorites: import_v3.z.number(), userRating: import_v3.z.number().optional() }); var ResultCapMetadataSchema = import_v3.z.object({ id: import_v3.z.string(), cid: import_v3.z.string(), name: import_v3.z.string(), version: import_v3.z.string(), displayName: import_v3.z.string(), description: import_v3.z.string(), introduction: import_v3.z.string(), timestamp: import_v3.z.string(), tags: import_v3.z.array(import_v3.z.string()), homepage: import_v3.z.string().optional(), repository: import_v3.z.string().optional(), thumbnail: CapThumbnailSchema, stats: CapStatsSchema }); var RatingDistribution = import_v3.z.object({ rating: import_v3.z.number(), count: import_v3.z.number() }); // src/mcp.ts var import_rooch_sdk = require("@roochnetwork/rooch-sdk"); var yaml = __toESM(require("js-yaml"), 1); // src/client.ts var import_payment_kit = require("@nuwa-ai/payment-kit"); var buildClient = async (mcpUrl, env) => { return (0, import_payment_kit.createMcpClient)({ baseUrl: mcpUrl, env, maxAmount: BigInt(1e7), debug: false, forceMode: "payment" }); }; // src/mcp.ts var CapKitMcp = class { constructor(option) { this.isInitializing = false; this.roochClient = new import_rooch_sdk.RoochClient({ url: option.roochUrl }); this.contractAddress = option.contractAddress; this.mcpUrl = option.mcpUrl; this.env = option.env; } async getTools() { if (!this.mcpTools) { const client = await this.getMcpClient(); this.mcpTools = await client.tools(); } return this.mcpTools; } async getMcpClient() { if (this.mcpClient) { return this.mcpClient; } while (this.isInitializing) { await new Promise((resolve) => setTimeout(resolve, 50)); if (this.mcpClient) { return this.mcpClient; } } this.isInitializing = true; try { const client = await buildClient(this.mcpUrl, this.env); await client.listTools(); this.mcpClient = client; return client; } catch (error) { console.error("Failed to initialize MCP client:", error); throw error; } finally { this.isInitializing = false; } } async mcpClose() { this.mcpClient?.close(); } async queryByID(id) { try { const tools = await this.getTools(); const queryCapByID = tools.queryCapByID; if (!queryCapByID) { throw new Error("Query Cap by id tool not available on MCP server"); } const result = await queryCapByID.execute(id, { toolCallId: "queryCapByID", messages: [] }); if (result.isError) { throw new Error(result.content?.[0]?.text || "Unknown error"); } const queryResult = JSON.parse(result.content[0].text); if (queryResult.code !== 200 && queryResult.code !== 404) { throw new Error(`Query with id failed: ${queryResult.error || "Unknown error"}`); } return queryResult; } catch (e) { throw e; } } async queryByName(name, opt) { try { const tools = await this.getTools(); const queryCapByName = tools.queryCapByName; if (!queryCapByName) { throw new Error("query tool not available on MCP server"); } const result = await queryCapByName.execute( { name, tags: opt?.tags, page: opt?.page, pageSize: opt?.size, sortBy: opt?.sortBy, sortOrder: opt?.sortOrder }, { toolCallId: "query-cap-by-name", messages: [] } ); if (result.isError) { throw new Error(result.content?.[0]?.text || "Unknown error"); } const queryResult = JSON.parse(result.content[0].text); if (queryResult.code === 404) { return { code: 200, data: { totalItems: 0, page: opt?.page || 0, pageSize: opt?.size || 50, items: [] } }; } if (queryResult.code !== 200) { throw new Error(`query failed: ${queryResult.error || "Unknown error"}`); } return { code: queryResult.code, data: { totalItems: queryResult.data.totalItems, page: queryResult.data.page, pageSize: queryResult.data.pageSize, items: queryResult.data.items } }; } catch (e) { throw e; } } async queryMyFavorite(page, size) { try { const tools = await this.getTools(); const queryMyFavoriteCaps = tools.queryMyFavoriteCap; if (!queryMyFavoriteCaps) { throw new Error("queryMyFavoriteCaps tool not available on MCP server"); } const result = await queryMyFavoriteCaps.execute( { page, pageSize: size }, { toolCallId: "queryMyFavoriteCaps", messages: [] } ); if (result.isError) { throw new Error(result.content?.[0]?.text || "Unknown error"); } const queryResult = JSON.parse(result.content[0].text); if (queryResult.code !== 200) { throw new Error(`queryMyFavoriteCaps failed: ${queryResult.error || "Unknown error"}`); } return { code: queryResult.code, data: { totalItems: queryResult.data.totalItems, page: queryResult.data.page, pageSize: queryResult.data.pageSize, items: queryResult.data.items } }; } catch (e) { throw e; } } async queryCapStats(capId) { try { const tools = await this.getTools(); const queryCapStats = tools.queryCapStats; if (!queryCapStats) { throw new Error("queryCapStats tool not available on MCP server"); } const result = await queryCapStats.execute( { capId }, { toolCallId: "queryCapStats", messages: [] } ); if (result.isError) { throw new Error(result.content?.[0]?.text || "Unknown error"); } const queryResult = JSON.parse(result.content[0].text); if (queryResult.code !== 200) { throw new Error(`query cap stats failed: ${queryResult.error || "Unknown error"}`); } return queryResult; } catch (e) { throw e; } } async rateCap(capId, rating) { if (rating < 1 || rating > 5 || !Number.isInteger(rating)) { throw new Error("Rating must be an integer between 1 and 5"); } try { const tools = await this.getTools(); const rateCap = tools.rateCap; if (!rateCap) { throw new Error("rateCap tool not available on MCP server"); } const result = await rateCap.execute( { capId, rating }, { toolCallId: "rateCap", messages: [] } ); if (result.isError) { throw new Error(result.content?.[0]?.text || "Unknown error"); } return { code: 200, data: true }; } catch (e) { throw e; } } async queryCapRatingDistribution(capId) { try { const tools = await this.getTools(); const queryCapRatingDistribution = tools.queryCapRatingDistribution; if (!queryCapRatingDistribution) { throw new Error("queryCapRatingDistribution tool not available on MCP server"); } const result = await queryCapRatingDistribution.execute( { capId }, { toolCallId: "queryCapRatingDistribution", messages: [] } ); if (result.isError) { throw new Error(result.content?.[0]?.text || "Unknown error"); } const content = result.content?.[0]?.text; if (content) { try { const resut = JSON.parse(content); return { code: 200, data: resut.data.distribution }; } catch (parseError) { throw new Error("Failed to parse rating distribution response"); } } throw new Error("No data received"); } catch (e) { throw e; } } async install(capId, action) { try { const tools = await this.getTools(); const favoriteCap = tools.favoriteCap; if (!favoriteCap) { throw new Error("favoriteCap tool not available on MCP server"); } const result = await favoriteCap.execute( { capId, action: action === "isInstall" ? "isFavorite" : action }, { toolCallId: "favoriteCap", messages: [] } ); if (result.isError) { throw new Error(result.content?.[0]?.text || "Unknown error"); } if (action === "isInstall") { const data = JSON.parse(result.content[0].text); return { code: 200, data: data.isFavorite }; } else { return { code: 200, data: true }; } } catch (e) { throw e; } } async updateEnableCap(capId, action) { try { const tools = await this.getTools(); const updateEnableCap = tools.updateEnableCap; if (!updateEnableCap) { throw new Error("updateEnableCap tool not available on MCP server"); } const result = await updateEnableCap.execute( { capId, action }, { toolCallId: "updateEnableCap", messages: [] } ); if (result.isError) { throw new Error(result.content?.[0]?.text || "Unknown error"); } return { code: 200, data: true }; } catch (e) { throw e; } } // async downloadByID(id: string, format?: "base64" | "utf8"): Promise<Cap> { // const result = await this.queryByID({ id: id }); // // if (result.code === 200) { // return this.downloadByCID(result.data!.cid, format); // } else { // throw new Error("Invalid Cap ID"); // } // } async downloadByID(id) { try { const tools = await this.getTools(); const downloadCap = tools.downloadCap; if (!downloadCap) { throw new Error("downloadCap tool not available on MCP server"); } const result = await downloadCap.execute( { id }, { toolCallId: "download-cap", messages: [] } ); if (result.isError) { throw new Error(result.content?.[0]?.text || "Unknown error"); } const downloadResult = JSON.parse(result.content[0].text); if (downloadResult.code !== 200) { throw new Error(`Download failed: ${downloadResult.error || "Unknown error"}`); } const data = downloadResult.data.rawData; const utf8 = new TextDecoder().decode(Uint8Array.from(atob(data), (c) => c.charCodeAt(0))); return yaml.load(utf8); } catch (e) { throw e; } } // async registerCap(cap: Cap) { // // len > 6 && len < 20, only contain a-z, A-Z, 0-9, _ // if (!/^[a-zA-Z0-9_]{6,20}$/.test(cap.idName)) { // throw new Error( // "Name must be between 6 and 20 characters and only contain a-z, A-Z, 0-9, _", // ); // } // // // 1. Create ACP (Agent Capability Package) file // const acpContent = yaml.dump(cap); // // // 2. Upload ACP file to IPFS using nuwa-cap-store MCP // const cid = await this.uploadToIPFS(cap.id, acpContent); // // // 3. Call Move contract to register the capability // const result = await this.registerOnChain(cap.idName, cid, this.env.keyManager); // // if (result.execution_info.status.type !== "executed") { // throw new Error("unknown error"); // } // // return cid; // } async registerCap(cap) { if (!/^[a-zA-Z0-9_]{6,20}$/.test(cap.idName)) { throw new Error("Name must be between 6 and 20 characters and only contain a-z, A-Z, 0-9, _"); } const acpContent = yaml.dump(cap); const encoder = new TextEncoder(); const bytes = encoder.encode(acpContent); const rawData = btoa(String.fromCharCode(...bytes)); const tools = await this.getTools(); const uploadCap = tools.uploadCap; const result = await uploadCap.execute( { cap: rawData }, { toolCallId: "upload-cap", messages: [] } ); if (result.isError) { throw new Error(result.content?.[0]?.text || "Unknown error"); } const uploadResult = JSON.parse(result.content[0].text); const uploadData = uploadResult.data; if (uploadResult.code !== 200) { throw new Error(`Upload cap failed: ${uploadResult.error || "Unknown error"}`); } return cap.id; } // private async uploadToIPFS( // name: string, // content: string, // ): Promise<string> { // // try { // // Get tools from MCP server // const tools = await this.getTools() // const uploadCap = tools.uploadCap; // // if (!uploadCap) { // throw new Error("uploadCap tool not available on MCP server"); // } // // // Convert content to base64 (UTF-8 safe) // const encoder = new TextEncoder(); // const bytes = encoder.encode(content); // const fileData = btoa(String.fromCharCode(...bytes)); // const fileName = `${name}.cap.yaml`; // // // Upload file to IPFS // const result = await uploadCap.execute( // { // fileName, // fileData, // }, // { // toolCallId: "upload-cap", // messages: [], // }, // ); // // if (result.isError) { // throw new Error((result.content as any)?.[0]?.text || "Unknown error"); // } // // const uploadResult = JSON.parse((result.content as any)[0].text); // const uploadData = uploadResult.data; // // if (uploadResult.code !== 200 || !uploadData.ipfsCid) { // throw new Error( // `Upload cap failed: ${uploadResult.error || "Unknown error"}`, // ); // } // // return uploadData.ipfsCid; // } catch (e) { // throw e // } // } // // private async registerOnChain( // name: string, // cid: string, // signer: SignerInterface, // ) { // const chainSigner = await DidAccountSigner.create(signer); // const transaction = new Transaction(); // transaction.callFunction({ // target: `${this.contractAddress}::acp_registry::register`, // typeArgs: [], // args: [Args.string(name), Args.string(cid)], // maxGas: 500000000, // }); // // return await this.roochClient.signAndExecuteTransaction({ // transaction, // signer: chainSigner, // }); // } }; // src/restful.ts var yaml2 = __toESM(require("js-yaml"), 1); var CapKitRestful = class { constructor(apiUrl) { this.apiUrl = apiUrl; } async queryCap(capId) { const response = await fetch(`${this.apiUrl}/cap/${capId}`); return await response.json(); } async queryCaps(name, tags, page, pageSize, sortBy, sortOrder) { const params = new URLSearchParams(); if (name) params.append("name", name); if (tags && tags.length > 0) { tags.forEach((tag) => params.append("tags", tag)); } if (page !== void 0) params.append("page", page.toString()); if (pageSize !== void 0) params.append("pageSize", pageSize.toString()); if (sortBy) params.append("sortBy", sortBy); if (sortOrder) params.append("sortOrder", sortOrder); const url = params.toString() ? `${this.apiUrl}/caps?${params.toString()}` : `${this.apiUrl}/caps`; const response = await fetch(url); return await response.json(); } async queryUserInstalledCaps(did, page, pageSize) { const params = new URLSearchParams(); if (did) params.append("did", did); if (page !== void 0) params.append("page", page.toString()); if (pageSize !== void 0) params.append("pageSize", pageSize.toString()); const url = `${this.apiUrl}/caps/installed?${params.toString()}`; const response = await fetch(url); return await response.json(); } async downloadCap(capId) { const response = await fetch(`${this.apiUrl}/cap/download/${capId}`); const result = await response.json(); const utf8 = new TextDecoder().decode( Uint8Array.from(atob(result.data.raw_data), (c) => c.charCodeAt(0)) ); return yaml2.load(utf8); } async downloadCaps(capIDs) { if (capIDs.length === 0) { return { successful: {}, failed: {}, summary: { successful: 0, failed: 0, total: 0 } }; } const response = await fetch(`${this.apiUrl}/caps/download`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ ids: capIDs }) }); const result = await response.json(); const successful = result.data.successful; const formatSuccessful = {}; for (const [id, value] of Object.entries(successful)) { const utf8 = new TextDecoder().decode( Uint8Array.from(atob(value), (c) => c.charCodeAt(0)) ); const cap = yaml2.load(utf8); formatSuccessful[id] = cap; } return { ...result.data, successful: formatSuccessful }; } }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { CapArtifactSchema, CapAuthorDIDSchema, CapCoreSchema, CapIDNameSchema, CapIDSchema, CapKitMcp, CapKitRestful, CapMcpServerSchema, CapMetadataSchema, CapModelSchema, CapPromptSchema, CapPromptSuggestionSchema, CapSchema, CapStatsSchema, CapThumbnailSchema, RatingDistribution, ResultCapMetadataSchema }); //# sourceMappingURL=index.cjs.map