feat: add persistent multi-model workers and orchestration budgets
This commit is contained in:
+65
@@ -2248,10 +2248,15 @@ static int h_extensions(cst_http_conn_t *c, void *ud) {
|
||||
cJSON_AddStringToObject(e, "source", ro[i].source);
|
||||
cJSON_AddStringToObject(e, "desc", ro[i].desc);
|
||||
cJSON_AddStringToObject(e, "model", ro[i].model);
|
||||
cJSON_AddStringToObject(e, "profile", ro[i].profile);
|
||||
cJSON_AddBoolToObject(e, "read_only", ro[i].read_only);
|
||||
cJSON_AddItemToArray(a, e);
|
||||
}
|
||||
cst_roles_free(ro, n);
|
||||
char *budget_json = cst_workers_budget_json(cfg);
|
||||
cJSON *budget = budget_json ? cJSON_Parse(budget_json) : NULL;
|
||||
free(budget_json);
|
||||
if (budget) cJSON_AddItemToObject(o, "worker_budget", budget);
|
||||
a = cJSON_AddArrayToObject(o, "runs");
|
||||
n = cst_subagent_list(ws, sid, ru, WUI_RUNS_MAX);
|
||||
for (int i = 0; a && i < n; i++) {
|
||||
@@ -2262,6 +2267,23 @@ static int h_extensions(cst_http_conn_t *c, void *ud) {
|
||||
cJSON_AddStringToObject(e, "role", ru[i].role);
|
||||
cJSON_AddStringToObject(e, "desc", ru[i].desc);
|
||||
cJSON_AddStringToObject(e, "status", ru[i].status);
|
||||
cJSON_AddStringToObject(e, "provider", ru[i].provider);
|
||||
cJSON_AddStringToObject(e, "model", ru[i].model);
|
||||
cJSON_AddNumberToObject(e, "requests", ru[i].requests);
|
||||
cJSON_AddNumberToObject(e, "max_steps", ru[i].max_steps);
|
||||
cJSON_AddNumberToObject(e, "prompt_tokens", ru[i].prompt_tokens);
|
||||
if (ru[i].cache_known) {
|
||||
cJSON_AddNumberToObject(e, "cached_tokens", ru[i].cached_tokens);
|
||||
cJSON_AddNumberToObject(e, "cache_write_tokens", ru[i].cache_write_tokens);
|
||||
} else {
|
||||
cJSON_AddNullToObject(e, "cached_tokens");
|
||||
cJSON_AddNullToObject(e, "cache_write_tokens");
|
||||
}
|
||||
cJSON_AddNumberToObject(e, "output_tokens", ru[i].output_tokens);
|
||||
if (ru[i].priced) {
|
||||
cJSON_AddNumberToObject(e, "cost", ru[i].cost);
|
||||
cJSON_AddStringToObject(e, "currency", ru[i].currency);
|
||||
}
|
||||
cJSON_AddNumberToObject(e, "steps", ru[i].steps);
|
||||
cJSON_AddNumberToObject(e, "tools", ru[i].tools);
|
||||
cJSON_AddNumberToObject(e, "ms", ru[i].ms);
|
||||
@@ -2297,6 +2319,45 @@ static int h_ext_reload_x(cst_http_conn_t *c, void *ud) {
|
||||
return wui_ext_reply(ud, c);
|
||||
}
|
||||
|
||||
static int h_workers_get(cst_http_conn_t *c, void *ud) {
|
||||
wui_t *w = ud;
|
||||
if (wui_claim_read(w) != 0)
|
||||
return cst_http_send_err(c, 409, "another change is running");
|
||||
char *s = cst_workers_config_get(cst_agent_config(w->agent)->workspace_root);
|
||||
cJSON *j = s ? cJSON_Parse(s) : NULL;
|
||||
free(s);
|
||||
wui_release(w);
|
||||
if (!j) return cst_http_send_err(c, 400, "invalid worker configuration");
|
||||
return wui_send_obj(c, 200, j);
|
||||
}
|
||||
static int h_workers_x(cst_http_conn_t *c, void *ud) {
|
||||
wui_t *w = ud;
|
||||
cJSON *j = wui_body(c);
|
||||
char *s = j ? cJSON_PrintUnformatted(j) : NULL;
|
||||
char err[256] = "expected JSON configuration";
|
||||
int rc = s ? cst_workers_config_set(
|
||||
cst_agent_config(w->agent)->workspace_root, s, err, sizeof(err)) : -1;
|
||||
free(s); cJSON_Delete(j);
|
||||
if (rc != 0) return cst_http_send_err(c, 400, err);
|
||||
cst_workers_config_apply(cst_agent_config_mut(w->agent));
|
||||
return cst_http_send_str(c, 200, "application/json", "{\"ok\":true}");
|
||||
}
|
||||
static int h_worker_cancel(cst_http_conn_t *c, void *ud) {
|
||||
wui_t *w = ud;
|
||||
if (wui_claim_read(w) != 0)
|
||||
return cst_http_send_err(c, 409, "another change is running");
|
||||
cJSON *j = wui_body(c);
|
||||
const cJSON *id = cJSON_GetObjectItemCaseSensitive(j, "worker_id");
|
||||
char sid[128];
|
||||
cst_agent_session_id(w->agent, sid, sizeof(sid));
|
||||
int rc = cJSON_IsString(id) ? cst_worker_cancel(
|
||||
cst_agent_config(w->agent)->workspace_root, sid, id->valuestring) : -1;
|
||||
cJSON_Delete(j);
|
||||
wui_release(w);
|
||||
if (rc != 0) return cst_http_send_err(c, 404, "running worker not found");
|
||||
return cst_http_send_str(c, 200, "application/json", "{\"ok\":true}");
|
||||
}
|
||||
|
||||
/* POST /api/extensions/trust {"on": bool}: whether .agent/plugins and
|
||||
* .agent/mcp.json of this workspace load, then reload. */
|
||||
static int h_ext_trust_x(cst_http_conn_t *c, void *ud) {
|
||||
@@ -2321,6 +2382,7 @@ WUI_EXCLUSIVE(h_session_delete)
|
||||
WUI_EXCLUSIVE(h_settings)
|
||||
WUI_EXCLUSIVE(h_perms_reset)
|
||||
WUI_EXCLUSIVE(h_ext_reload)
|
||||
WUI_EXCLUSIVE(h_workers)
|
||||
WUI_EXCLUSIVE(h_ext_trust)
|
||||
WUI_EXCLUSIVE(h_undo)
|
||||
WUI_EXCLUSIVE(h_compact)
|
||||
@@ -2568,6 +2630,9 @@ int cst_webui_run(cst_agent_t *agent, const cst_webui_opts_t *opts) {
|
||||
{"POST", "/api/ask_user", h_ask_user, NULL, 0, 0},
|
||||
{"POST", "/api/config", h_config, NULL, 0, 0},
|
||||
{"GET", "/api/providers", h_providers, NULL, 0, 0},
|
||||
{"GET", "/api/workers/config", h_workers_get, NULL, 0, 0},
|
||||
{"POST", "/api/workers/config", h_workers, NULL, 0, 0},
|
||||
{"POST", "/api/workers/cancel", h_worker_cancel, NULL, 0, 0},
|
||||
{"GET", "/api/models", h_models, NULL, 0, 0},
|
||||
{"POST", "/api/provider", h_provider, NULL, 0, 0},
|
||||
{"POST", "/api/key", h_key, NULL, 0, 0},
|
||||
|
||||
Reference in New Issue
Block a user