temp
This commit is contained in:
118
dist/tools/coolify-api.js
vendored
Normal file
118
dist/tools/coolify-api.js
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
"use strict";
|
||||
// =============================================================================
|
||||
// Pure Coolify API — no ToolContext coupling, no registry coupling.
|
||||
//
|
||||
// Everything in here takes a plain { apiUrl, apiToken } config and calls
|
||||
// the Coolify v1 API directly. Security guardrails (PROTECTED_COOLIFY_PROJECT,
|
||||
// PROTECTED_COOLIFY_APPS, assertCoolifyDeployable) are enforced inside each
|
||||
// function so every caller — in-process tool handler, MCP server, or future
|
||||
// direct SDK user — gets the same protection.
|
||||
//
|
||||
// This is the shared core consumed by:
|
||||
// - tools/coolify.ts (in-process registry used by agent-runner loop)
|
||||
// - mcp/coolify-server.ts (stdio MCP server exposed to Goose/Claude/Cursor)
|
||||
// =============================================================================
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.listProjects = listProjects;
|
||||
exports.listApplications = listApplications;
|
||||
exports.deploy = deploy;
|
||||
exports.getLogs = getLogs;
|
||||
exports.listAllApps = listAllApps;
|
||||
exports.getAppStatus = getAppStatus;
|
||||
exports.deployApp = deployApp;
|
||||
const security_1 = require("./security");
|
||||
async function coolifyFetch(cfg, path, method = 'GET', body) {
|
||||
const res = await fetch(`${cfg.apiUrl}/api/v1${path}`, {
|
||||
method,
|
||||
headers: {
|
||||
'Authorization': `Bearer ${cfg.apiToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
body: body ? JSON.stringify(body) : undefined
|
||||
});
|
||||
if (!res.ok) {
|
||||
return { error: `Coolify API error: ${res.status} ${res.statusText}` };
|
||||
}
|
||||
return res.json();
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
// Public API — each function corresponds 1:1 with a registered tool today
|
||||
// ---------------------------------------------------------------------------
|
||||
async function listProjects(cfg) {
|
||||
const projects = await coolifyFetch(cfg, '/projects');
|
||||
if (!Array.isArray(projects))
|
||||
return projects;
|
||||
return projects.filter((p) => p.uuid !== security_1.PROTECTED_COOLIFY_PROJECT);
|
||||
}
|
||||
async function listApplications(cfg, projectUuid) {
|
||||
const all = await coolifyFetch(cfg, '/applications');
|
||||
if (!Array.isArray(all))
|
||||
return all;
|
||||
return all.filter((a) => a.project_uuid === projectUuid);
|
||||
}
|
||||
async function deploy(cfg, applicationUuid) {
|
||||
(0, security_1.assertCoolifyDeployable)(applicationUuid);
|
||||
const apps = await coolifyFetch(cfg, '/applications');
|
||||
if (Array.isArray(apps)) {
|
||||
const app = apps.find((a) => a.uuid === applicationUuid);
|
||||
if (app?.project_uuid === security_1.PROTECTED_COOLIFY_PROJECT) {
|
||||
return {
|
||||
error: `SECURITY: App "${applicationUuid}" belongs to the protected Vibn project. Agents cannot deploy platform apps.`
|
||||
};
|
||||
}
|
||||
}
|
||||
return coolifyFetch(cfg, `/applications/${applicationUuid}/deploy`, 'POST');
|
||||
}
|
||||
async function getLogs(cfg, applicationUuid, limit = 50) {
|
||||
return coolifyFetch(cfg, `/applications/${applicationUuid}/logs?limit=${limit}`);
|
||||
}
|
||||
async function listAllApps(cfg) {
|
||||
const apps = await coolifyFetch(cfg, '/applications');
|
||||
if (!Array.isArray(apps))
|
||||
return apps;
|
||||
return apps
|
||||
.filter((a) => a.project_uuid !== security_1.PROTECTED_COOLIFY_PROJECT && !security_1.PROTECTED_COOLIFY_APPS.has(a.uuid))
|
||||
.map((a) => ({
|
||||
uuid: a.uuid,
|
||||
name: a.name,
|
||||
fqdn: a.fqdn,
|
||||
status: a.status,
|
||||
repo: a.git_repository,
|
||||
branch: a.git_branch
|
||||
}));
|
||||
}
|
||||
async function getAppStatus(cfg, appName) {
|
||||
const apps = await coolifyFetch(cfg, '/applications');
|
||||
if (!Array.isArray(apps))
|
||||
return apps;
|
||||
const app = apps.find((a) => a.name?.toLowerCase() === appName.toLowerCase() || a.uuid === appName);
|
||||
if (!app)
|
||||
return { error: `App "${appName}" not found` };
|
||||
if (security_1.PROTECTED_COOLIFY_APPS.has(app.uuid) || app.project_uuid === security_1.PROTECTED_COOLIFY_PROJECT) {
|
||||
return {
|
||||
error: `SECURITY: "${appName}" is a protected Vibn platform app. Status is not exposed to agents.`
|
||||
};
|
||||
}
|
||||
const logs = await coolifyFetch(cfg, `/applications/${app.uuid}/logs?limit=20`);
|
||||
return { name: app.name, uuid: app.uuid, status: app.status, fqdn: app.fqdn, logs };
|
||||
}
|
||||
async function deployApp(cfg, appName) {
|
||||
const apps = await coolifyFetch(cfg, '/applications');
|
||||
if (!Array.isArray(apps))
|
||||
return apps;
|
||||
const app = apps.find((a) => a.name?.toLowerCase() === appName.toLowerCase() || a.uuid === appName);
|
||||
if (!app)
|
||||
return { error: `App "${appName}" not found` };
|
||||
if (security_1.PROTECTED_COOLIFY_APPS.has(app.uuid) || app.project_uuid === security_1.PROTECTED_COOLIFY_PROJECT) {
|
||||
return {
|
||||
error: `SECURITY: "${appName}" is a protected Vibn platform application. ` +
|
||||
`Agents can only deploy user project apps, not platform infrastructure.`
|
||||
};
|
||||
}
|
||||
// Non-project-prefixed deploy endpoint — older Coolify entry point still in use
|
||||
const result = await fetch(`${cfg.apiUrl}/api/v1/deploy?uuid=${app.uuid}&force=false`, {
|
||||
headers: { 'Authorization': `Bearer ${cfg.apiToken}` }
|
||||
});
|
||||
return result.json();
|
||||
}
|
||||
Reference in New Issue
Block a user