@sema-agent/server 1.240.0 → 1.242.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/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.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 +13 -0
- package/dist/http/server.d.ts.map +1 -1
- package/dist/http/server.js +118 -22
- package/dist/http/server.js.map +1 -1
- package/dist/main.js +6 -2
- package/dist/main.js.map +1 -1
- package/dist/plugins/memory-engine-pg.d.ts.map +1 -1
- package/dist/plugins/memory-engine-pg.js +22 -10
- package/dist/plugins/memory-engine-pg.js.map +1 -1
- package/dist/plugins/memory-sync-store-pg.d.ts.map +1 -1
- package/dist/plugins/memory-sync-store-pg.js +4 -3
- package/dist/plugins/memory-sync-store-pg.js.map +1 -1
- package/dist/plugins/pg-approval-store.d.ts.map +1 -1
- package/dist/plugins/pg-approval-store.js +2 -1
- package/dist/plugins/pg-approval-store.js.map +1 -1
- package/dist/plugins/pg-checkpoint-store.d.ts.map +1 -1
- package/dist/plugins/pg-checkpoint-store.js +7 -6
- package/dist/plugins/pg-checkpoint-store.js.map +1 -1
- package/dist/plugins/pg-image-bake.d.ts +1 -1
- package/dist/plugins/pg-image-bake.d.ts.map +1 -1
- package/dist/plugins/pg-image-bake.js +17 -15
- package/dist/plugins/pg-image-bake.js.map +1 -1
- package/dist/plugins/pg-image-index.d.ts.map +1 -1
- package/dist/plugins/pg-image-index.js +18 -9
- package/dist/plugins/pg-image-index.js.map +1 -1
- package/dist/plugins/pg-outcome-ledger.d.ts.map +1 -1
- package/dist/plugins/pg-outcome-ledger.js +5 -4
- package/dist/plugins/pg-outcome-ledger.js.map +1 -1
- package/dist/plugins/pg-run-store.d.ts.map +1 -1
- package/dist/plugins/pg-run-store.js +6 -5
- package/dist/plugins/pg-run-store.js.map +1 -1
- package/dist/plugins/pg-safe-json.d.ts +9 -0
- package/dist/plugins/pg-safe-json.d.ts.map +1 -0
- package/dist/plugins/pg-safe-json.js +90 -0
- package/dist/plugins/pg-safe-json.js.map +1 -0
- package/dist/plugins/pg-session-policy-store.d.ts.map +1 -1
- package/dist/plugins/pg-session-policy-store.js +4 -0
- package/dist/plugins/pg-session-policy-store.js.map +1 -1
- package/dist/plugins/pg-session-storage.d.ts.map +1 -1
- package/dist/plugins/pg-session-storage.js +5 -4
- package/dist/plugins/pg-session-storage.js.map +1 -1
- package/dist/plugins/pg-tool-result-store.d.ts.map +1 -1
- package/dist/plugins/pg-tool-result-store.js +2 -1
- package/dist/plugins/pg-tool-result-store.js.map +1 -1
- package/dist/plugins/pg-workflow-journal-store.d.ts.map +1 -1
- package/dist/plugins/pg-workflow-journal-store.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/plugins/tidb-image-bake.d.ts +1 -1
- package/dist/plugins/tidb-image-bake.d.ts.map +1 -1
- package/dist/plugins/tidb-image-bake.js +3 -2
- package/dist/plugins/tidb-image-bake.js.map +1 -1
- package/dist/plugins/tidb-workflow-journal-store.d.ts.map +1 -1
- package/dist/plugins/tidb-workflow-journal-store.js.map +1 -1
- package/dist/tool-approval.d.ts +1 -0
- package/dist/tool-approval.d.ts.map +1 -1
- package/dist/tool-approval.js +13 -8
- package/dist/tool-approval.js.map +1 -1
- package/package.json +2 -2
package/dist/http/server.js
CHANGED
|
@@ -25,11 +25,13 @@ 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";
|
|
31
32
|
import { usageSummary, usageSeries, usageBreakdown } from "../usage-analytics.js";
|
|
32
33
|
import { IdempotencyCache } from "./idempotency.js";
|
|
34
|
+
import { pgHasUnstorable } from "../plugins/pg-safe-json.js";
|
|
33
35
|
export const MAX_USER_SKILLS = 10;
|
|
34
36
|
export const MAX_SKILL_CONTENT_CHARS = 1_048_576;
|
|
35
37
|
export const MAX_SYSTEM_PROMPT_CHARS = 16_384;
|
|
@@ -669,6 +671,7 @@ export function createHttpServer(deps) {
|
|
|
669
671
|
mcpElicitation: Boolean(deps.elicitation),
|
|
670
672
|
askUserQuestion: Boolean(deps.question),
|
|
671
673
|
toolApproval: Boolean(deps.toolApproval),
|
|
674
|
+
sideQuery: true,
|
|
672
675
|
sessionList: Boolean(deps.sessionStorage?.listSessions ?? deps.runStore?.listSessions),
|
|
673
676
|
sessionSearch: Boolean(deps.sessionStorage?.listSessions ?? deps.runStore?.listSessions),
|
|
674
677
|
sessionFork: Boolean(deps.sessionStorage?.fork),
|
|
@@ -707,6 +710,77 @@ export function createHttpServer(deps) {
|
|
|
707
710
|
sendJson(res, 200, { models, default: deps.config.model.id, defaultModel: { id: deps.config.model.id, ...(defaultName ? { name: defaultName } : {}) } });
|
|
708
711
|
return;
|
|
709
712
|
}
|
|
713
|
+
if (req.method === "POST" && url === "/v1/side-query") {
|
|
714
|
+
const ac = new AbortController();
|
|
715
|
+
const onClose = () => ac.abort();
|
|
716
|
+
res.on("close", onClose);
|
|
717
|
+
try {
|
|
718
|
+
if (rateLimited(req, res) || quotaExceeded(req, res) || (await leaseDenied(req, res)))
|
|
719
|
+
return;
|
|
720
|
+
const principal = gatedPrincipal(req, deps.config);
|
|
721
|
+
if (deps.config.requirePrincipal && !principal) {
|
|
722
|
+
sendJson(res, 401, { error: `missing principal header '${deps.config.principalHeader}'` });
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
let body;
|
|
726
|
+
try {
|
|
727
|
+
const raw = await readJson(req);
|
|
728
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw))
|
|
729
|
+
throw new HttpError(400, "body must be a JSON object (SideQuerySpec shape)");
|
|
730
|
+
body = raw;
|
|
731
|
+
}
|
|
732
|
+
catch (e) {
|
|
733
|
+
const he = e instanceof HttpError ? e : new HttpError(400, msg(e));
|
|
734
|
+
sendJson(res, he.status, { error: he.message });
|
|
735
|
+
return;
|
|
736
|
+
}
|
|
737
|
+
if (!Array.isArray(body.messages) || body.messages.length === 0) {
|
|
738
|
+
sendJson(res, 400, { error: "messages must be a non-empty array (SideQueryMessage[])" });
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
741
|
+
if (body.thinking !== undefined && !isThinkingLevel(body.thinking)) {
|
|
742
|
+
sendJson(res, 400, { error: "invalid thinking level" });
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
if (ac.signal.aborted)
|
|
746
|
+
return;
|
|
747
|
+
const spec = {
|
|
748
|
+
messages: body.messages,
|
|
749
|
+
...(typeof body.model === "string" ? { model: body.model } : {}),
|
|
750
|
+
...(typeof body.modelRole === "string" ? { modelRole: body.modelRole } : {}),
|
|
751
|
+
...(isThinkingLevel(body.thinking) ? { thinking: body.thinking } : {}),
|
|
752
|
+
...(typeof body.systemPrompt === "string" ? { systemPrompt: body.systemPrompt } : {}),
|
|
753
|
+
...(Array.isArray(body.tools) ? { tools: body.tools } : {}),
|
|
754
|
+
...(typeof body.maxOutputTokens === "number" && Number.isFinite(body.maxOutputTokens) && body.maxOutputTokens > 0 ? { maxOutputTokens: Math.floor(body.maxOutputTokens) } : {}),
|
|
755
|
+
signal: ac.signal,
|
|
756
|
+
};
|
|
757
|
+
try {
|
|
758
|
+
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 }));
|
|
759
|
+
const result = await deps.runner.sideQuery(spec);
|
|
760
|
+
const rr = result;
|
|
761
|
+
const modelId = typeof rr.model === "string" ? rr.model : "unknown";
|
|
762
|
+
const byId = catalogSnapshot.filter((m) => m.id === modelId);
|
|
763
|
+
const families = new Set(byId.map((m) => cacheFamilyOfMirror(m)));
|
|
764
|
+
const family = families.size === 1 ? [...families][0] : undefined;
|
|
765
|
+
deps.sideQueryAccounting?.(principal, { model: modelId, ...(family ? { family } : {}), usage: rr.usage });
|
|
766
|
+
deps.metrics?.inc?.("side_query_total", { result: "ok" });
|
|
767
|
+
if (!res.writableEnded)
|
|
768
|
+
sendJson(res, 200, result);
|
|
769
|
+
}
|
|
770
|
+
catch (e) {
|
|
771
|
+
deps.metrics?.inc?.("side_query_total", { result: "error" });
|
|
772
|
+
if (!res.writableEnded && !ac.signal.aborted) {
|
|
773
|
+
const m = msg(e);
|
|
774
|
+
const isValidation = /^Unknown model ref |^No model for role |requires a non-empty messages array/.test(m);
|
|
775
|
+
sendJson(res, isValidation ? 400 : 500, { error: redactSecrets(m) });
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
finally {
|
|
780
|
+
res.off("close", onClose);
|
|
781
|
+
}
|
|
782
|
+
return;
|
|
783
|
+
}
|
|
710
784
|
if (req.method === "POST" && (url === "/v1/tasks" || url === "/v1/tasks/stream")) {
|
|
711
785
|
const rawIdem = headerStr(req.headers["idempotency-key"]);
|
|
712
786
|
const idemKey = rawIdem ? scopedIdempotencyKey(rawIdem, source, gatedPrincipal(req, deps.config)) : undefined;
|
|
@@ -5469,7 +5543,7 @@ async function ingestBakeLine(bakes, idx, bake, line, registry) {
|
|
|
5469
5543
|
const cancelled = doneStatus === "CANCELLED";
|
|
5470
5544
|
const errorText = typeof line.error === "string" ? redactSecrets(line.error) : null;
|
|
5471
5545
|
const tag = typeof line.tag === "string" ? line.tag : bake.tag;
|
|
5472
|
-
|
|
5546
|
+
let digest = typeof line.digest === "string" && line.digest.length > 0 ? line.digest : null;
|
|
5473
5547
|
let indexId = bake.indexId;
|
|
5474
5548
|
let repo = bake.repo;
|
|
5475
5549
|
let ref = bake.ref;
|
|
@@ -5484,27 +5558,35 @@ async function ingestBakeLine(bakes, idx, bake, line, registry) {
|
|
|
5484
5558
|
const fresh = await bakes.getBake(bakeId);
|
|
5485
5559
|
const nonTerminal = !!fresh && (fresh.status === "queued" || fresh.status === "running");
|
|
5486
5560
|
if (manifestBody && typeof manifestBody === "object" && nonTerminal) {
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
manifestSha = typeof line.manifestSha === "string" ? line.manifestSha : (typeof line.manifest?.sha256 === "string" ? String(line.manifest.sha256) : bake.manifestSha);
|
|
5492
|
-
const entry = manifestToIndexEntry(manifestBody, { repo, digest, status: "building", manifestSha, sizeBytes: manifestBody.sizeBytes ?? null, signed: false });
|
|
5493
|
-
entry.visibility = "public";
|
|
5494
|
-
entry.tenantId = null;
|
|
5495
|
-
indexId = await idx.registerBuilding(entry);
|
|
5496
|
-
ref = `${repo}@${digest}`;
|
|
5497
|
-
await bakes.setIndexId(bakeId, indexId);
|
|
5498
|
-
registerSteps.push({ step: "register", status: "ok" });
|
|
5499
|
-
}
|
|
5500
|
-
catch (err) {
|
|
5561
|
+
const profile = bake.profile && bake.profile !== "custom" ? bake.profile : (manifestBody.profile && manifestBody.profile !== "custom" ? manifestBody.profile : "custom");
|
|
5562
|
+
repo = registry ? `${registry}/${profile}` : `sema-images/${profile}`;
|
|
5563
|
+
manifestSha = typeof line.manifestSha === "string" ? line.manifestSha : (typeof line.manifest?.sha256 === "string" ? String(line.manifest.sha256) : bake.manifestSha);
|
|
5564
|
+
if (pgHasUnstorable(digest) || pgHasUnstorable(repo) || pgHasUnstorable(manifestSha)) {
|
|
5501
5565
|
indexId = null;
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5566
|
+
registerSteps.push({ step: "register", status: "skipped", reason: "identity fields contained unstorable bytes" });
|
|
5567
|
+
}
|
|
5568
|
+
else {
|
|
5569
|
+
registerSteps.push({ step: "register", status: "running" });
|
|
5570
|
+
try {
|
|
5571
|
+
const entry = manifestToIndexEntry(manifestBody, { repo, digest, status: "building", manifestSha, sizeBytes: manifestBody.sizeBytes ?? null, signed: false });
|
|
5572
|
+
entry.visibility = "public";
|
|
5573
|
+
entry.tenantId = null;
|
|
5574
|
+
indexId = await idx.registerBuilding(entry);
|
|
5575
|
+
ref = `${repo}@${digest}`;
|
|
5576
|
+
const bound = await bakes.setIndexId(bakeId, indexId);
|
|
5577
|
+
if (!bound)
|
|
5578
|
+
indexId = null;
|
|
5579
|
+
registerSteps.push({ step: "register", status: "ok" });
|
|
5580
|
+
}
|
|
5581
|
+
catch (err) {
|
|
5582
|
+
indexId = null;
|
|
5583
|
+
ref = `${repo}@${digest}`;
|
|
5584
|
+
finalStatus = "FAILED";
|
|
5585
|
+
registerDowngraded = true;
|
|
5586
|
+
finalExit = exitCode ?? 0;
|
|
5587
|
+
finalError = redactSecrets(`index register failed after a COMPLETE build (built-but-unregistered partial): ${String(err?.message ?? err)}`);
|
|
5588
|
+
registerSteps.push({ step: "register", status: "fail", reason: "index register failed (TiDB?)" });
|
|
5589
|
+
}
|
|
5508
5590
|
}
|
|
5509
5591
|
}
|
|
5510
5592
|
}
|
|
@@ -5519,6 +5601,19 @@ async function ingestBakeLine(bakes, idx, bake, line, registry) {
|
|
|
5519
5601
|
const conflictBands = errorCode === "band-conflict" && Array.isArray(line.conflictBands)
|
|
5520
5602
|
? line.conflictBands.filter((b) => typeof b === "string")
|
|
5521
5603
|
: null;
|
|
5604
|
+
const identityInvalid = (typeof digest === "string" && pgHasUnstorable(digest)) ||
|
|
5605
|
+
(typeof repo === "string" && pgHasUnstorable(repo)) ||
|
|
5606
|
+
(typeof ref === "string" && pgHasUnstorable(ref)) ||
|
|
5607
|
+
(typeof manifestSha === "string" && pgHasUnstorable(manifestSha));
|
|
5608
|
+
if (identityInvalid) {
|
|
5609
|
+
finalStatus = "FAILED";
|
|
5610
|
+
digest = null;
|
|
5611
|
+
repo = null;
|
|
5612
|
+
ref = null;
|
|
5613
|
+
manifestSha = null;
|
|
5614
|
+
indexId = null;
|
|
5615
|
+
finalError = finalError ? `${finalError}; identity fields contained unstorable bytes` : "terminal frame identity fields contained unstorable bytes";
|
|
5616
|
+
}
|
|
5522
5617
|
const finalState = (finalStatus === "COMPLETE" ? "COMPLETE" : finalStatus === "CANCELLED" ? "CANCELLED" : "FAILED");
|
|
5523
5618
|
const coarse = coarseStatusForState(finalState);
|
|
5524
5619
|
let affectedRows = 0;
|
|
@@ -5576,7 +5671,8 @@ function headerStr(v) {
|
|
|
5576
5671
|
return Array.isArray(v) ? v[0] : v;
|
|
5577
5672
|
}
|
|
5578
5673
|
function isBillableSubmitPath(url) {
|
|
5579
|
-
return (url === "/v1/
|
|
5674
|
+
return (url === "/v1/side-query" ||
|
|
5675
|
+
url === "/v1/tasks" ||
|
|
5580
5676
|
url === "/v1/tasks/stream" ||
|
|
5581
5677
|
url === "/v1/runs" ||
|
|
5582
5678
|
url === "/v1/leader" ||
|