Files
CST-agent/src/extensions.c
T
WHCandCursor ea38247161
ci / tcc-check (push) Failing after 40s
ci / linux (aarch64, 0) (push) Skipped
ci / linux (x86, 1) (push) Skipped
ci / linux (x86_64, 1) (push) Skipped
ci / windows (push) Skipped
feat: Hermit 1.1.0 — HERMIT_* env, Tauri desktop shell
Wire hermit_getenv across the engine, rebrand WebUI/systemd/docs, and
add apps/desktop (Tauri 2 + React) with a DeepSeek-Harness-like UI.
Qt app/ is frozen; full libcstcore FFI is scaffolded behind --features engine.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-30 13:15:47 +08:00

96 lines
3.0 KiB
C

#include "cst_ext.h"
#include "cst_hermit_glyph.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cst_mcp.h"
#include "cst_plugins.h"
#include "cst_skills.h"
#include "cst_subagent.h"
#include "cst_tools.h"
#include "cst_util.h"
static char g_report[256];
const char *cst_extensions_report(void) { return g_report; }
void cst_extensions_wait(FILE *log) {
int ready = 0, total = 0;
cst_mcp_counts(&ready, &total);
if (total == 0)
return;
/* Default 8s (was 30s); override with CST_MCP_WAIT_MS. */
const char *e = hermit_getenv("MCP_WAIT_MS");
int ms = e && atoi(e) >= 0 ? atoi(e) : 8000;
if (ms > 60000)
ms = 60000;
cst_mcp_wait_ready(ms);
cst_mcp_info_t info[CST_MCP_MAX];
int n = cst_mcp_info(info, CST_MCP_MAX);
for (int i = 0; log && i < n; i++) {
if (info[i].state == CST_MCP_READY)
fprintf(log, "mcp %s: %d tool%s\n", info[i].name, info[i].ntools,
info[i].ntools == 1 ? "" : "s");
else if (info[i].state != CST_MCP_OFF)
fprintf(log, "mcp %s: %s\n", info[i].name,
info[i].error[0] ? info[i].error : "not ready");
}
}
void cst_extensions_load(const cst_agent_config_t *cfg, char *report,
size_t report_sz) {
if (report && report_sz)
report[0] = 0;
g_report[0] = 0;
if (!cfg || cfg->tool_profile == CST_TOOLS_MINIMAL)
return;
const char *ws = cfg->workspace_root;
int trusted = cst_settings_trusted(ws);
int mcp_untrusted = 0, plugin_untrusted = 0;
/* workspace and user mcp.json come before plugin servers: first name wins */
cst_mcp_load_configs(ws, trusted, &mcp_untrusted);
int np = cst_plugins_load(ws, trusted, &plugin_untrusted);
cst_skill_t *v = calloc(CST_SKILLS_MAX, sizeof(*v));
int ns = v ? cst_skills_list(ws, v, CST_SKILLS_MAX) : 0;
free(v);
if (ns > 0)
cst_skills_register_tool();
if (cfg->depth == 0)
cst_subagent_register_tool(ws);
cst_mcp_start_all(ws);
cst_buf_t b = {0};
if (ns > 0)
cst_buf_printf(&b, "%d skill%s", ns, ns == 1 ? "" : "s");
if (np > 0) {
cst_plugin_info_t info[CST_PLUGINS_MAX];
int n = cst_plugins_info(info, CST_PLUGINS_MAX), nt = 0;
for (int i = 0; i < n; i++)
nt += info[i].ntools;
cst_buf_printf(&b, "%s%d plugin%s (%d tool%s)", b.len ? " · " : "", np,
np == 1 ? "" : "s", nt, nt == 1 ? "" : "s");
}
int ready = 0, total = 0;
cst_mcp_counts(&ready, &total);
if (total > 0)
cst_buf_printf(&b, "%s%d MCP server%s", b.len ? " · " : "", total,
total == 1 ? "" : "s");
if (mcp_untrusted + plugin_untrusted > 0)
cst_buf_printf(&b, "%suntrusted workspace: /plugins trust",
b.len ? " · " : "");
if (report && report_sz)
snprintf(report, report_sz, "%s", b.buf ? b.buf : "");
snprintf(g_report, sizeof(g_report), "%s", b.buf ? b.buf : "");
cst_buf_free(&b);
}
void cst_extensions_unload(void) {
cst_mcp_stop_all();
cst_plugins_unload();
cst_tool_unregister_owner("builtin:skills");
cst_tool_unregister_owner("builtin:task");
}