UNPKG

@stackmemoryai/stackmemory

Version:

Project-scoped memory for AI coding tools. Durable context across sessions with MCP integration, frames, smart retrieval, Claude Code skills, and automatic hooks.

233 lines (232 loc) 8.49 kB
import { fileURLToPath as __fileURLToPath } from 'url'; import { dirname as __pathDirname } from 'path'; const __filename = __fileURLToPath(import.meta.url); const __dirname = __pathDirname(__filename); import { Command } from "commander"; import { getAPISkill } from "../../skills/api-skill.js"; import { getAPIDiscovery } from "../../skills/api-discovery.js"; function createAPICommand() { const api = new Command("api"); api.description("OpenAPI-based API access via Restish"); api.command("add <name> <url>").description("Register a new API").option("--spec <url>", "OpenAPI spec URL").option( "--auth-type <type>", "Authentication type (none|api-key|oauth2|basic)", "none" ).option("--header-name <name>", "Auth header name", "Authorization").option("--env-var <name>", "Environment variable for auth token").action(async (name, url, options) => { const skill = getAPISkill(); const result = await skill.add(name, url, { spec: options.spec, authType: options.authType, headerName: options.headerName, envVar: options.envVar }); if (result.success) { console.log(`API '${name}' registered`); if (result.data) { console.log(JSON.stringify(result.data, null, 2)); } } else { console.error(`Error: ${result.message}`); process.exit(1); } }); api.command("list").description("List all registered APIs").action(async () => { const skill = getAPISkill(); const result = await skill.list(); if (result.success) { if (Array.isArray(result.data) && result.data.length === 0) { console.log( "No APIs registered. Use: stackmemory api add <name> <url>" ); } else { console.log("Registered APIs:"); for (const api2 of result.data) { console.log(` ${api2.name}`); console.log(` URL: ${api2.baseUrl}`); console.log(` Auth: ${api2.authType}`); console.log(` Operations: ${api2.operations}`); } } } else { console.error(`Error: ${result.message}`); process.exit(1); } }); api.command("describe <name> [operation]").description("Show API details or specific operation").action(async (name, operation) => { const skill = getAPISkill(); const result = await skill.describe(name, operation); if (result.success) { console.log(result.message); if (result.data) { console.log(JSON.stringify(result.data, null, 2)); } } else { console.error(`Error: ${result.message}`); process.exit(1); } }); api.command("exec <name> <operation>").description("Execute an API operation").option("--raw", "Output raw response").option("--filter <query>", "Filter/project response using shorthand query").option("-H, --header <header...>", "Add custom headers (key:value)").allowUnknownOption(true).action(async (name, operation, options, command) => { const skill = getAPISkill(); const params = {}; const args = command.args.slice(2); for (let i = 0; i < args.length; i++) { const arg = args[i]; if (arg.startsWith("--")) { const key = arg.slice(2); const nextArg = args[i + 1]; if (nextArg && !nextArg.startsWith("--")) { params[key] = nextArg; i++; } else { params[key] = true; } } } const headers = {}; if (options.header) { for (const h of options.header) { const [key, ...valueParts] = h.split(":"); headers[key] = valueParts.join(":").trim(); } } const result = await skill.exec(name, operation, params, { raw: options.raw, filter: options.filter, headers }); if (result.success) { if (typeof result.data === "string") { console.log(result.data); } else { console.log(JSON.stringify(result.data, null, 2)); } } else { console.error(`Error: ${result.message}`); process.exit(1); } }); api.command("auth <name>").description("Configure API authentication").option("--token <token>", "API token/key").option("--env-var <name>", "Environment variable name for token").option("--oauth", "Use OAuth2 flow").option("--scopes <scopes>", "OAuth2 scopes (comma-separated)").action(async (name, options) => { const skill = getAPISkill(); const result = await skill.auth(name, { token: options.token, envVar: options.envVar, oauth: options.oauth, scopes: options.scopes?.split(",") }); if (result.success) { console.log(result.message); } else { console.error(`Error: ${result.message}`); process.exit(1); } }); api.command("sync <name>").description("Refresh API operations from spec").action(async (name) => { const skill = getAPISkill(); const result = await skill.sync(name); if (result.success) { console.log(result.message); if (result.data?.operations) { console.log( `Operations: ${result.data.operations.join(", ")}` ); } } else { console.error(`Error: ${result.message}`); process.exit(1); } }); api.command("remove <name>").description("Remove a registered API").action(async (name) => { const skill = getAPISkill(); const result = await skill.remove(name); if (result.success) { console.log(result.message); } else { console.error(`Error: ${result.message}`); process.exit(1); } }); api.command("discover <url>").description("Analyze a URL and discover API endpoints").option("--register", "Auto-register if API is discovered").action(async (url, options) => { const discovery = getAPIDiscovery(); const result = discovery.analyzeUrl(url); if (result) { console.log(`Discovered API: ${result.name}`); console.log(` Base URL: ${result.baseUrl}`); console.log(` Spec URL: ${result.specUrl || "not found"}`); console.log(` Type: ${result.apiType || "rest"}`); console.log(` Source: ${result.source}`); console.log(` Confidence: ${(result.confidence * 100).toFixed(0)}%`); if (result.apiType === "graphql") { console.log( ` Note: This is a GraphQL API. Use a GraphQL client for queries.` ); } else if (result.apiType === "google-discovery") { console.log( ` Note: This uses Google Discovery format. Auth via gcloud CLI.` ); } if (options.register) { await discovery.registerAPI(result); console.log( ` API registered. Use: stackmemory api exec ${result.name} <path>` ); } else { console.log( ` To register: stackmemory api add ${result.name} ${result.baseUrl}` ); } } else { console.log("No API detected in this URL"); } }); api.command("discovered").description("List all auto-discovered APIs").action(() => { const discovery = getAPIDiscovery(); const discovered = discovery.getDiscoveredAPIs(); if (discovered.length === 0) { console.log("No APIs discovered yet."); console.log( "Browse API documentation or use: stackmemory api discover <url>" ); return; } console.log("Discovered APIs:"); for (const api2 of discovered) { console.log(` ${api2.name}`); console.log(` Base: ${api2.baseUrl}`); console.log(` Spec: ${api2.specUrl || "none"}`); console.log(` Confidence: ${(api2.confidence * 100).toFixed(0)}%`); } }); api.command("register-discovered").description("Register all discovered APIs").action(async () => { const discovery = getAPIDiscovery(); const discovered = discovery.getDiscoveredAPIs(); if (discovered.length === 0) { console.log("No APIs to register. Use: stackmemory api discover <url>"); return; } let registered = 0; for (const api2 of discovered) { if (await discovery.registerAPI(api2)) { console.log(`Registered: ${api2.name}`); registered++; } } console.log(` Registered ${registered}/${discovered.length} APIs`); }); api.command("help").description("Show API skill help").action(() => { const skill = getAPISkill(); const discovery = getAPIDiscovery(); console.log(skill.getHelp()); console.log("\n---\n"); console.log(discovery.getHelp()); }); return api; } export { createAPICommand }; //# sourceMappingURL=api.js.map