@sema-agent/server 1.241.0 → 1.243.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/budget.d.ts +19 -0
- package/dist/budget.d.ts.map +1 -1
- package/dist/budget.js +32 -0
- package/dist/budget.js.map +1 -1
- package/dist/capabilities/center-prompts.d.ts +1 -0
- package/dist/capabilities/center-prompts.d.ts.map +1 -1
- package/dist/capabilities/center-prompts.js +4 -0
- package/dist/capabilities/center-prompts.js.map +1 -1
- package/dist/config-lkg.d.ts.map +1 -1
- package/dist/config-lkg.js +1 -6
- package/dist/config-lkg.js.map +1 -1
- package/dist/env-facts.d.ts +9 -0
- package/dist/env-facts.d.ts.map +1 -1
- package/dist/env-facts.js +22 -0
- package/dist/env-facts.js.map +1 -1
- package/dist/http/server.d.ts +23 -1
- package/dist/http/server.d.ts.map +1 -1
- package/dist/http/server.js +114 -2
- package/dist/http/server.js.map +1 -1
- package/dist/main.js +195 -17
- package/dist/main.js.map +1 -1
- package/dist/plugins/remote-env-e2b.d.ts.map +1 -1
- package/dist/plugins/remote-env-e2b.js +3 -1
- package/dist/plugins/remote-env-e2b.js.map +1 -1
- package/dist/plugins/remote-env-k8s.d.ts.map +1 -1
- package/dist/plugins/remote-env-k8s.js.map +1 -1
- package/dist/sema-registry.d.ts +4 -1
- package/dist/sema-registry.d.ts.map +1 -1
- package/dist/sema-registry.js +48 -21
- package/dist/sema-registry.js.map +1 -1
- package/dist/task-settings.d.ts +4 -1
- package/dist/task-settings.d.ts.map +1 -1
- package/dist/task-settings.js +45 -1
- package/dist/task-settings.js.map +1 -1
- package/package.json +2 -2
package/dist/http/server.js
CHANGED
|
@@ -25,6 +25,7 @@ import { RateLimiter } from "../observability/rate-limit.js";
|
|
|
25
25
|
import { withPrincipal } from "../observability/principal-context.js";
|
|
26
26
|
import { projectEvents, runSummary, mapTraceEvent, toolStartEventData, toolEndEventData, taskProgressEventData, taskNotificationEventData, compactedEventData, diagnosticsEventData, brainStatusEventData, appendModelUsageDelta, appendPromptManifest, attachModelUsage } from "../trace/project.js";
|
|
27
27
|
import { createLedgerSink } from "../trace/ledger-sink.js";
|
|
28
|
+
import { cacheFamilyOfMirror } from "../budget.js";
|
|
28
29
|
import { projectArtifacts } from "../trace/artifacts.js";
|
|
29
30
|
import { composeSupervisorCost, infraCost, infraUsageFromEvents, hasInfraPricing } from "../finance/cost-taxonomy.js";
|
|
30
31
|
import { redactSecrets, redactDeep, redactedPreview } from "../trace/redact.js";
|
|
@@ -329,6 +330,10 @@ export function createHttpServer(deps) {
|
|
|
329
330
|
port: deps.config.port,
|
|
330
331
|
...(deps.config.directDoorActive ? { directDoorActive: true } : {}),
|
|
331
332
|
...(restart ? { restartRequired: true, restart: { reasons: restart.reasons, version: restart.version, since: restart.since } } : {}),
|
|
333
|
+
...(() => {
|
|
334
|
+
const stuck = deps.planeDeferredState?.();
|
|
335
|
+
return stuck ? { modelPlaneDeferred: { version: stuck.version, since: stuck.since, noHandoff: true, ...(stuck.blocked ? { blockedReasons: stuck.blocked } : {}) } } : {};
|
|
336
|
+
})(),
|
|
332
337
|
});
|
|
333
338
|
return;
|
|
334
339
|
}
|
|
@@ -659,6 +664,8 @@ export function createHttpServer(deps) {
|
|
|
659
664
|
subagentSteer: Boolean(deps.subagentSteerRegistry) && Boolean(deps.runStore),
|
|
660
665
|
subagentResume: Boolean(deps.subagentSteerRegistry) && Boolean(deps.runStore),
|
|
661
666
|
taskSettings: { permissions: true, permissionMode: true, model: true, outputStyle: true, env: false, hooks: deps.config.requirePrincipal !== true },
|
|
667
|
+
appendSystemPrompt: true,
|
|
668
|
+
compactionModel: true,
|
|
662
669
|
taskAgents: deps.config.requirePrincipal !== true,
|
|
663
670
|
retainBackgroundProcesses: deps.config.requirePrincipal !== true,
|
|
664
671
|
interactiveTools: true,
|
|
@@ -670,6 +677,7 @@ export function createHttpServer(deps) {
|
|
|
670
677
|
mcpElicitation: Boolean(deps.elicitation),
|
|
671
678
|
askUserQuestion: Boolean(deps.question),
|
|
672
679
|
toolApproval: Boolean(deps.toolApproval),
|
|
680
|
+
sideQuery: true,
|
|
673
681
|
sessionList: Boolean(deps.sessionStorage?.listSessions ?? deps.runStore?.listSessions),
|
|
674
682
|
sessionSearch: Boolean(deps.sessionStorage?.listSessions ?? deps.runStore?.listSessions),
|
|
675
683
|
sessionFork: Boolean(deps.sessionStorage?.fork),
|
|
@@ -708,6 +716,77 @@ export function createHttpServer(deps) {
|
|
|
708
716
|
sendJson(res, 200, { models, default: deps.config.model.id, defaultModel: { id: deps.config.model.id, ...(defaultName ? { name: defaultName } : {}) } });
|
|
709
717
|
return;
|
|
710
718
|
}
|
|
719
|
+
if (req.method === "POST" && url === "/v1/side-query") {
|
|
720
|
+
const ac = new AbortController();
|
|
721
|
+
const onClose = () => ac.abort();
|
|
722
|
+
res.on("close", onClose);
|
|
723
|
+
try {
|
|
724
|
+
if (rateLimited(req, res) || quotaExceeded(req, res) || (await leaseDenied(req, res)))
|
|
725
|
+
return;
|
|
726
|
+
const principal = gatedPrincipal(req, deps.config);
|
|
727
|
+
if (deps.config.requirePrincipal && !principal) {
|
|
728
|
+
sendJson(res, 401, { error: `missing principal header '${deps.config.principalHeader}'` });
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
let body;
|
|
732
|
+
try {
|
|
733
|
+
const raw = await readJson(req);
|
|
734
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw))
|
|
735
|
+
throw new HttpError(400, "body must be a JSON object (SideQuerySpec shape)");
|
|
736
|
+
body = raw;
|
|
737
|
+
}
|
|
738
|
+
catch (e) {
|
|
739
|
+
const he = e instanceof HttpError ? e : new HttpError(400, msg(e));
|
|
740
|
+
sendJson(res, he.status, { error: he.message });
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
if (!Array.isArray(body.messages) || body.messages.length === 0) {
|
|
744
|
+
sendJson(res, 400, { error: "messages must be a non-empty array (SideQueryMessage[])" });
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
if (body.thinking !== undefined && !isThinkingLevel(body.thinking)) {
|
|
748
|
+
sendJson(res, 400, { error: "invalid thinking level" });
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
if (ac.signal.aborted)
|
|
752
|
+
return;
|
|
753
|
+
const spec = {
|
|
754
|
+
messages: body.messages,
|
|
755
|
+
...(typeof body.model === "string" ? { model: body.model } : {}),
|
|
756
|
+
...(typeof body.modelRole === "string" ? { modelRole: body.modelRole } : {}),
|
|
757
|
+
...(isThinkingLevel(body.thinking) ? { thinking: body.thinking } : {}),
|
|
758
|
+
...(typeof body.systemPrompt === "string" ? { systemPrompt: body.systemPrompt } : {}),
|
|
759
|
+
...(Array.isArray(body.tools) ? { tools: body.tools } : {}),
|
|
760
|
+
...(typeof body.maxOutputTokens === "number" && Number.isFinite(body.maxOutputTokens) && body.maxOutputTokens > 0 ? { maxOutputTokens: Math.floor(body.maxOutputTokens) } : {}),
|
|
761
|
+
signal: ac.signal,
|
|
762
|
+
};
|
|
763
|
+
try {
|
|
764
|
+
const catalogSnapshot = Object.values(deps.runner.agentCatalog?.models ?? {}).map((m) => ({ id: m?.id, api: m?.api, params: m?.params?.promptCacheFamily ? { promptCacheFamily: m.params.promptCacheFamily } : undefined }));
|
|
765
|
+
const result = await deps.runner.sideQuery(spec);
|
|
766
|
+
const rr = result;
|
|
767
|
+
const modelId = typeof rr.model === "string" ? rr.model : "unknown";
|
|
768
|
+
const byId = catalogSnapshot.filter((m) => m.id === modelId);
|
|
769
|
+
const families = new Set(byId.map((m) => cacheFamilyOfMirror(m)));
|
|
770
|
+
const family = families.size === 1 ? [...families][0] : undefined;
|
|
771
|
+
deps.sideQueryAccounting?.(principal, { model: modelId, ...(family ? { family } : {}), usage: rr.usage });
|
|
772
|
+
deps.metrics?.inc?.("side_query_total", { result: "ok" });
|
|
773
|
+
if (!res.writableEnded)
|
|
774
|
+
sendJson(res, 200, result);
|
|
775
|
+
}
|
|
776
|
+
catch (e) {
|
|
777
|
+
deps.metrics?.inc?.("side_query_total", { result: "error" });
|
|
778
|
+
if (!res.writableEnded && !ac.signal.aborted) {
|
|
779
|
+
const m = msg(e);
|
|
780
|
+
const isValidation = /^Unknown model ref |^No model for role |requires a non-empty messages array/.test(m);
|
|
781
|
+
sendJson(res, isValidation ? 400 : 500, { error: redactSecrets(m) });
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
finally {
|
|
786
|
+
res.off("close", onClose);
|
|
787
|
+
}
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
711
790
|
if (req.method === "POST" && (url === "/v1/tasks" || url === "/v1/tasks/stream")) {
|
|
712
791
|
const rawIdem = headerStr(req.headers["idempotency-key"]);
|
|
713
792
|
const idemKey = rawIdem ? scopedIdempotencyKey(rawIdem, source, gatedPrincipal(req, deps.config)) : undefined;
|
|
@@ -4090,6 +4169,16 @@ export function createHttpServer(deps) {
|
|
|
4090
4169
|
sendJson(res, 400, { error: `systemPrompt must be at most ${MAX_SYSTEM_PROMPT_CHARS} characters` });
|
|
4091
4170
|
return null;
|
|
4092
4171
|
}
|
|
4172
|
+
if (body.appendSystemPrompt !== undefined) {
|
|
4173
|
+
if (typeof body.appendSystemPrompt !== "string" || body.appendSystemPrompt.length === 0) {
|
|
4174
|
+
sendJson(res, 400, { error: "appendSystemPrompt must be a non-empty string" });
|
|
4175
|
+
return null;
|
|
4176
|
+
}
|
|
4177
|
+
if (body.appendSystemPrompt.length > MAX_SYSTEM_PROMPT_CHARS) {
|
|
4178
|
+
sendJson(res, 400, { error: `appendSystemPrompt must be at most ${MAX_SYSTEM_PROMPT_CHARS} characters` });
|
|
4179
|
+
return null;
|
|
4180
|
+
}
|
|
4181
|
+
}
|
|
4093
4182
|
if (body.cwd !== undefined && !isValidCwd(body.cwd)) {
|
|
4094
4183
|
sendJson(res, 400, { error: "cwd must be a non-empty absolute host path" });
|
|
4095
4184
|
return null;
|
|
@@ -4121,6 +4210,13 @@ export function createHttpServer(deps) {
|
|
|
4121
4210
|
sendJson(res, 400, { error: `settings.outputStyle must be at most ${MAX_SETTINGS_OUTPUT_STYLE_CHARS} characters` });
|
|
4122
4211
|
return null;
|
|
4123
4212
|
}
|
|
4213
|
+
if (typeof st.outputStyle === "string" &&
|
|
4214
|
+
st.outputStyle.length > 0 &&
|
|
4215
|
+
typeof body.appendSystemPrompt === "string" &&
|
|
4216
|
+
body.appendSystemPrompt.length + 2 + st.outputStyle.length > MAX_SYSTEM_PROMPT_CHARS) {
|
|
4217
|
+
sendJson(res, 400, { error: `appendSystemPrompt + settings.outputStyle fold into one system-prompt block — combined they must be at most ${MAX_SYSTEM_PROMPT_CHARS} characters (including the 2-char joiner)` });
|
|
4218
|
+
return null;
|
|
4219
|
+
}
|
|
4124
4220
|
const perms = st.permissions;
|
|
4125
4221
|
if (perms !== null && typeof perms === "object" && !Array.isArray(perms)) {
|
|
4126
4222
|
for (const k of ["allow", "deny", "ask"]) {
|
|
@@ -4352,6 +4448,21 @@ export function createHttpServer(deps) {
|
|
|
4352
4448
|
return null;
|
|
4353
4449
|
}
|
|
4354
4450
|
}
|
|
4451
|
+
if (body.compactionModel !== undefined) {
|
|
4452
|
+
if (typeof body.compactionModel !== "string" || body.compactionModel.length === 0) {
|
|
4453
|
+
sendJson(res, 400, { error: "compactionModel must be a non-empty string (a configured catalog name, tier word, or model id)" });
|
|
4454
|
+
return null;
|
|
4455
|
+
}
|
|
4456
|
+
const bare = deps.config.models ?? {};
|
|
4457
|
+
const catalog = expandTiers(bare, deps.config.tiers ?? {}) ?? bare;
|
|
4458
|
+
if (matchCatalogModel(body.compactionModel, catalog) === undefined) {
|
|
4459
|
+
sendJson(res, 400, {
|
|
4460
|
+
error: `unknown compactionModel "${body.compactionModel.slice(0, 120)}" — not in the configured catalog (name, tier word, or id)`,
|
|
4461
|
+
available: Object.keys(catalog).filter((n) => n !== "default"),
|
|
4462
|
+
});
|
|
4463
|
+
return null;
|
|
4464
|
+
}
|
|
4465
|
+
}
|
|
4355
4466
|
if (body.attachments !== undefined) {
|
|
4356
4467
|
const a = body.attachments;
|
|
4357
4468
|
if (typeof a !== "object" || a === null || Array.isArray(a)) {
|
|
@@ -4394,7 +4505,7 @@ export function createHttpServer(deps) {
|
|
|
4394
4505
|
}
|
|
4395
4506
|
try {
|
|
4396
4507
|
const auth = deps.authorize ? await deps.authorize({ req, body }) : undefined;
|
|
4397
|
-
return { spec: await deps.resolveSpec(body, req, auth), auth, verify, cascade, jobId: body.jobId, body };
|
|
4508
|
+
return { spec: await deps.resolveSpec(body, req, auth, { leg: "fresh" }), auth, verify, cascade, jobId: body.jobId, body };
|
|
4398
4509
|
}
|
|
4399
4510
|
catch (err) {
|
|
4400
4511
|
if (err instanceof HttpError) {
|
|
@@ -5598,7 +5709,8 @@ function headerStr(v) {
|
|
|
5598
5709
|
return Array.isArray(v) ? v[0] : v;
|
|
5599
5710
|
}
|
|
5600
5711
|
function isBillableSubmitPath(url) {
|
|
5601
|
-
return (url === "/v1/
|
|
5712
|
+
return (url === "/v1/side-query" ||
|
|
5713
|
+
url === "/v1/tasks" ||
|
|
5602
5714
|
url === "/v1/tasks/stream" ||
|
|
5603
5715
|
url === "/v1/runs" ||
|
|
5604
5716
|
url === "/v1/leader" ||
|