Extensions: skills, plugins, MCP, sub-agents; configurable keys
- Skills (SKILL.md discovery, skill tool, /skills /skill) - plugin.json exec tools with permission prompts, timeouts and workspace trust (/plugins) - MCP stdio client: JSON-RPC initialize/tools/list/tools/call, mcp__server__tool, /mcp and sidebar status - task tool with general/explore/plan and .agent/agents/*.md roles, parallel read-only runs, cancel propagation, /agents - Keymap with Ctrl+X leader, keybinds.json overrides and /keys panel - Collapsed thinking, throttled streaming Markdown, leaner tool output, parallel read-only tools - Spawn: close-on-exec pipes and a process-wide fork lock - Tests for keymap, skills, plugins, MCP, sub-agents, shell compaction; docs/plugins.md
This commit is contained in:
+69
-1
@@ -27,7 +27,7 @@ int cst_settings_load(cst_settings_t *s) {
|
||||
FILE *fp = fopen(path, "rb");
|
||||
if (!fp)
|
||||
return -1;
|
||||
char buf[16384];
|
||||
static _Thread_local char buf[65536];
|
||||
size_t n = fread(buf, 1, sizeof(buf) - 1, fp);
|
||||
fclose(fp);
|
||||
buf[n] = 0;
|
||||
@@ -42,6 +42,14 @@ int cst_settings_load(cst_settings_t *s) {
|
||||
cJSON_GetObjectItemCaseSensitive(root, "effort"));
|
||||
copy_str(s->approval, sizeof(s->approval),
|
||||
cJSON_GetObjectItemCaseSensitive(root, "approval"));
|
||||
s->show_thinking =
|
||||
cJSON_IsTrue(cJSON_GetObjectItemCaseSensitive(root, "show_thinking"));
|
||||
const cJSON *tr = cJSON_GetObjectItemCaseSensitive(root, "trusted_workspaces");
|
||||
const cJSON *w;
|
||||
cJSON_ArrayForEach(w, tr) {
|
||||
if (s->ntrusted < CST_SETTINGS_MAX_TRUSTED && cJSON_IsString(w))
|
||||
copy_str(s->trusted[s->ntrusted++], sizeof(s->trusted[0]), w);
|
||||
}
|
||||
const cJSON *models = cJSON_GetObjectItemCaseSensitive(root, "models");
|
||||
const cJSON *m;
|
||||
cJSON_ArrayForEach(m, models) {
|
||||
@@ -73,6 +81,13 @@ int cst_settings_save(const cst_settings_t *s) {
|
||||
cJSON_AddStringToObject(root, "effort", s->effort);
|
||||
if (s->approval[0])
|
||||
cJSON_AddStringToObject(root, "approval", s->approval);
|
||||
if (s->show_thinking)
|
||||
cJSON_AddTrueToObject(root, "show_thinking");
|
||||
if (s->ntrusted) {
|
||||
cJSON *tr = cJSON_AddArrayToObject(root, "trusted_workspaces");
|
||||
for (int i = 0; i < s->ntrusted; i++)
|
||||
cJSON_AddItemToArray(tr, cJSON_CreateString(s->trusted[i]));
|
||||
}
|
||||
cJSON *models = cJSON_AddObjectToObject(root, "models");
|
||||
for (int i = 0; i < s->nmodels; i++)
|
||||
cJSON_AddStringToObject(models, s->models[i].provider, s->models[i].model);
|
||||
@@ -146,3 +161,56 @@ int cst_settings_remember_approval(int approval) {
|
||||
snprintf(s.approval, sizeof(s.approval), "%s", cst_approval_name(approval));
|
||||
return cst_settings_save(&s);
|
||||
}
|
||||
|
||||
int cst_settings_remember_thinking(int show_thinking) {
|
||||
cst_settings_t s;
|
||||
cst_settings_load(&s);
|
||||
s.show_thinking = show_thinking != 0;
|
||||
return cst_settings_save(&s);
|
||||
}
|
||||
|
||||
static void real_ws(const char *ws, char *out, size_t n) {
|
||||
if (!ws || os_realpath(ws, out, n) != 0)
|
||||
snprintf(out, n, "%s", ws ? ws : "");
|
||||
}
|
||||
|
||||
int cst_settings_trusted(const char *workspace) {
|
||||
char real[OS_PATH_MAX];
|
||||
real_ws(workspace, real, sizeof(real));
|
||||
cst_settings_t s;
|
||||
cst_settings_load(&s);
|
||||
for (int i = 0; i < s.ntrusted; i++)
|
||||
if (strcmp(s.trusted[i], real) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cst_settings_trust(const char *workspace, int on) {
|
||||
char real[OS_PATH_MAX];
|
||||
real_ws(workspace, real, sizeof(real));
|
||||
if (!real[0] || strlen(real) >= sizeof(((cst_settings_t *)0)->trusted[0]))
|
||||
return -1;
|
||||
cst_settings_t s;
|
||||
cst_settings_load(&s);
|
||||
int k = 0, found = 0;
|
||||
for (int i = 0; i < s.ntrusted; i++) {
|
||||
if (strcmp(s.trusted[i], real) == 0) {
|
||||
found = 1;
|
||||
if (!on)
|
||||
continue;
|
||||
}
|
||||
if (k != i)
|
||||
memcpy(s.trusted[k], s.trusted[i], sizeof(s.trusted[0]));
|
||||
k++;
|
||||
}
|
||||
s.ntrusted = k;
|
||||
if (on && !found) {
|
||||
if (s.ntrusted >= CST_SETTINGS_MAX_TRUSTED) {
|
||||
memmove(s.trusted[0], s.trusted[1],
|
||||
sizeof(s.trusted[0]) * (CST_SETTINGS_MAX_TRUSTED - 1));
|
||||
s.ntrusted--;
|
||||
}
|
||||
snprintf(s.trusted[s.ntrusted++], sizeof(s.trusted[0]), "%.511s", real);
|
||||
}
|
||||
return cst_settings_save(&s);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user