@sema-agent/server 3.3.0 → 3.4.1
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.
|
@@ -3,7 +3,7 @@ import { principalFrom, verifyDirectDoorProof, MAX_APPROVAL_REASON_CHARS } from
|
|
|
3
3
|
import { redactedPreview } from "../../trace/redact.js";
|
|
4
4
|
import { sleep } from "../sse-log.js";
|
|
5
5
|
import { sendJson, sendError, sseHeaders } from "../send.js";
|
|
6
|
-
import { gatedPrincipal, explicitOperatorOk, isOperator
|
|
6
|
+
import { gatedPrincipal, explicitOperatorOk, isOperator } from "../principal-gate.js";
|
|
7
7
|
// design/80 seam #2 (assistant-scheduler): graceful preempt (durable yield) + resource_limit resume of one task.
|
|
8
8
|
export const ASSISTANT_PREEMPT_RE = /^\/v1\/assistant\/tasks\/([^/]+)\/preempt$/;
|
|
9
9
|
export const ASSISTANT_RESUME_RE = /^\/v1\/assistant\/tasks\/([^/]+)\/resume$/;
|
|
@@ -155,13 +155,35 @@ async function handleApprovalsAssistantBody(req, res, url, ctx, miss) {
|
|
|
155
155
|
// 🔴 STRIP the resume `token` (the unexposed secret capability — resume is by sessionId, never the
|
|
156
156
|
// token) AND the RAW `toolInput` (core bounds but does NOT redact it — redaction is
|
|
157
157
|
// the consumer's job). Re-emit the REDACTED `input` instead.
|
|
158
|
-
|
|
159
|
-
//
|
|
160
|
-
//
|
|
161
|
-
//
|
|
158
|
+
// 🔴 EXPLICIT projection([2029] cli 批准的收窄,辖域=仅本 inbox 面)—— 此前是「剥 token/toolInput、
|
|
159
|
+
// 其余整行展开」,于是 core summarizeCheckpoint 在 tool_approval 门上填的 toolName/toolCallId/preview/
|
|
160
|
+
// principal/sourceTaskId/contentKind 全部漏上 wire(其中 preview 还没过脱敏,而它同源的 toolInput 是
|
|
161
|
+
// 显式脱敏的)。四客户端仓结构性零消费(inbox verb 无调用点,[2029] 取证),按 §2 原意收成显式白名单:
|
|
162
|
+
// §1 镜像键(OMIT-when-absent)+ 两个显式 nullable 的 enrichment(objective/input)。富行
|
|
163
|
+
// (toolName/toolCallId/decide 绑定)只住 /v1/approvals —— 那面有具名消费者(desktop session-host
|
|
164
|
+
// 冷恢复),不在本刀辖域。`input` = REDACTED preview,只有 tool_approval 门携带(其余 ⇒ null)。
|
|
162
165
|
const input = s.toolInput != null ? redactedPreview(s.toolInput) : null;
|
|
163
|
-
return {
|
|
164
|
-
|
|
166
|
+
return {
|
|
167
|
+
sessionId: s.sessionId,
|
|
168
|
+
scope: s.scope,
|
|
169
|
+
createdAt: s.createdAt,
|
|
170
|
+
...(s.gateKind !== undefined ? { gateKind: s.gateKind } : {}),
|
|
171
|
+
...(s.severity !== undefined ? { severity: s.severity } : {}),
|
|
172
|
+
...(s.spentMicroUsd !== undefined ? { spentMicroUsd: s.spentMicroUsd } : {}),
|
|
173
|
+
...(s.deadline !== undefined ? { deadline: s.deadline } : {}),
|
|
174
|
+
objective: ctx?.body?.objective ?? null,
|
|
175
|
+
input,
|
|
176
|
+
};
|
|
177
|
+
}))
|
|
178
|
+
// severity DESC, then **explicitly** oldest-first within a tier ([2027] 第五节欠单②,红先绿后:
|
|
179
|
+
// test/assistant-triage-ordering.test.ts)。旧姿势只比 severity,靠「listByScope 是 created_at ASC
|
|
180
|
+
// + Array#sort 稳定」来兑现 §2 那句 oldest-first —— 而那个前提**只在本仓的 SQL 后端成立**
|
|
181
|
+
// (checkpoint-store-sql.ts 的 `ORDER BY created_at ASC`):core 的 `CheckpointStore.listByScope` 接口
|
|
182
|
+
// 零顺序声明,InMemory/File 两个实现直接遍历 Map(LOCAL 车道包的正是 File store)⇒ 那句承诺过去是
|
|
183
|
+
// **后端相关**的。比较器自带兜底后它与 store 顺序无关。形与 listPending 的同族 sort 逐字一致
|
|
184
|
+
// (checkpoint-store-sql.ts `|| a.createdAt - b.createdAt`)。createdAt 缺席(pre-1.116 投影的老行)
|
|
185
|
+
// 计 0 = 档内最老:确定性优于「看它恰好落在哪」。
|
|
186
|
+
).sort((a, b) => (b.severity ?? 0) - (a.severity ?? 0) || (a.createdAt ?? 0) - (b.createdAt ?? 0));
|
|
165
187
|
sendJson(res, 200, { inbox }); // CheckpointSummary (token-stripped) + objective, severity-prioritized — the assistant single inbox
|
|
166
188
|
return;
|
|
167
189
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/server",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.1",
|
|
4
4
|
"description": "Sema Server — the server/API implementation layer for Sema, wiring core, registry, model providers, and cloud agent execution. Built on @sema-agent/core.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "BUSL-1.1",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"build:binary:run-local:darwin-arm64": "bun build --compile --target=bun-darwin-arm64 src/run-local.ts --outfile dist/run-local-darwin-arm64"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@sema-agent/core": "^2.
|
|
56
|
+
"@sema-agent/core": "^2.2.0",
|
|
57
57
|
"@sema-agent/registry-core": "^0.10.24",
|
|
58
58
|
"e2b": "^2.28.0",
|
|
59
59
|
"libsodium-wrappers": "^0.8.4",
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
export interface InfraCostRates {
|
|
2
|
-
toolCallMicroUsd: number;
|
|
3
|
-
sandboxSecMicroUsd: number;
|
|
4
|
-
egressGbMicroUsd: number;
|
|
5
|
-
}
|
|
6
|
-
export interface InfraUsage {
|
|
7
|
-
toolCalls: number;
|
|
8
|
-
sandboxWalltimeMs: number;
|
|
9
|
-
egressBytes: number;
|
|
10
|
-
}
|
|
11
|
-
export interface InfraCostBreakdown {
|
|
12
|
-
toolCallMicroUsd: number;
|
|
13
|
-
sandboxWalltimeMicroUsd: number;
|
|
14
|
-
egressMicroUsd: number;
|
|
15
|
-
totalMicroUsd: number;
|
|
16
|
-
}
|
|
17
|
-
export interface LlmCostBreakdown {
|
|
18
|
-
llmRootMicroUsd: number;
|
|
19
|
-
nestedSubagentMicroUsd: number;
|
|
20
|
-
memoryConsolidationMicroUsd: number;
|
|
21
|
-
compactionMicroUsd: number;
|
|
22
|
-
}
|
|
23
|
-
export interface SupervisorCostBreakdown {
|
|
24
|
-
llm: LlmCostBreakdown | null;
|
|
25
|
-
infra: InfraCostBreakdown;
|
|
26
|
-
totalMicroUsd: number;
|
|
27
|
-
}
|
|
28
|
-
export declare function infraCost(usage: InfraUsage, rates: InfraCostRates): InfraCostBreakdown;
|
|
29
|
-
export declare function composeSupervisorCost(llm: LlmCostBreakdown | null, llmTotalMicroUsd: number, infra: InfraCostBreakdown): SupervisorCostBreakdown;
|
|
30
|
-
export declare function hasInfraPricing(r: InfraCostRates): boolean;
|
|
31
|
-
export declare function infraUsageFromEvents(events: ReadonlyArray<{
|
|
32
|
-
type?: string;
|
|
33
|
-
}>, runDurationMs: number): InfraUsage;
|
|
34
|
-
//# sourceMappingURL=cost-taxonomy.d.ts.map
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
const nonNeg = (n) => (Number.isFinite(n) && n > 0 ? n : 0);
|
|
2
|
-
export function infraCost(usage, rates) {
|
|
3
|
-
const toolCallMicroUsd = nonNeg(usage.toolCalls) * nonNeg(rates.toolCallMicroUsd);
|
|
4
|
-
const sandboxWalltimeMicroUsd = (nonNeg(usage.sandboxWalltimeMs) / 1000) * nonNeg(rates.sandboxSecMicroUsd);
|
|
5
|
-
const egressMicroUsd = (nonNeg(usage.egressBytes) / 1_000_000_000) * nonNeg(rates.egressGbMicroUsd);
|
|
6
|
-
return {
|
|
7
|
-
toolCallMicroUsd,
|
|
8
|
-
sandboxWalltimeMicroUsd,
|
|
9
|
-
egressMicroUsd,
|
|
10
|
-
totalMicroUsd: toolCallMicroUsd + sandboxWalltimeMicroUsd + egressMicroUsd,
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
export function composeSupervisorCost(llm, llmTotalMicroUsd, infra) {
|
|
14
|
-
return { llm, infra, totalMicroUsd: nonNeg(llmTotalMicroUsd) + infra.totalMicroUsd };
|
|
15
|
-
}
|
|
16
|
-
export function hasInfraPricing(r) {
|
|
17
|
-
return r.toolCallMicroUsd > 0 || r.sandboxSecMicroUsd > 0 || r.egressGbMicroUsd > 0;
|
|
18
|
-
}
|
|
19
|
-
export function infraUsageFromEvents(events, runDurationMs) {
|
|
20
|
-
return {
|
|
21
|
-
toolCalls: events.reduce((n, e) => (e.type === "tool_start" ? n + 1 : n), 0),
|
|
22
|
-
sandboxWalltimeMs: nonNeg(runDurationMs),
|
|
23
|
-
egressBytes: 0,
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
//# sourceMappingURL=cost-taxonomy.js.map
|
package/dist/sema-registry.d.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sema-registry adapter — pull the effective config from sema-registry and apply it OVER the
|
|
3
|
-
* env-derived defaults (env = fallback, center = override). Follows the "universal internal
|
|
4
|
-
* schema → translate at the boundary" pattern, with our security boundary kept:
|
|
5
|
-
*
|
|
6
|
-
* - the CENTER owns the LOGICAL config: the model roster (names/capabilities/tier), the role map,
|
|
7
|
-
* and team templates;
|
|
8
|
-
* - the SERVICE env still owns the SECRETS: API keys stay in env (the center never stores a secret);
|
|
9
|
-
* keys are per-model via `apiKeyEnv` → `config.modelApiKeyEnv` → the spec's `getApiKeyAndHeaders`
|
|
10
|
-
* (core 1.45), so each model/cascade-rung authenticates with its own upstream key.
|
|
11
|
-
*
|
|
12
|
-
* Per-model `baseUrl` IS transported (a catalog model may live on a different gateway;
|
|
13
|
-
* core brain honors model.baseUrl, absent = "" = boot-env endpoint).
|
|
14
|
-
*
|
|
15
|
-
* Hot-reload status (复审 2026-07-29 P1-11 — 亲读判定,取代此处旧的 "models/roles are restart-to-apply"
|
|
16
|
-
* TODO, which went stale when `mutateInPlace` landed):
|
|
17
|
-
* - models/roles/roster/teams/projects/autonomy — **HOT**. `applyEffective` mutates `config.models`/
|
|
18
|
-
* `config.roles` IN PLACE, and core's Runner reads `this.deps.models/roles` per task off that very
|
|
19
|
-
* reference. Both brains re-resolve `model.baseUrl || config.baseUrl` inside `buildRequest()` on every
|
|
20
|
-
* call (core 2.1.0 `brain/openai.js` + `brain/anthropic.js`), so a moved gateway takes effect on the
|
|
21
|
-
* next task with no restart.
|
|
22
|
-
* - the same plane under a **tier-frozen** Runner — deferred, not hot: core expands a PRIVATE catalog copy
|
|
23
|
-
* at construction, so `main` defers the whole plane and the `models-tiers` restart slice signals.
|
|
24
|
-
* - **`degrade-route`** — the one genuinely boot-frozen catalog consumer left: reactive degrade
|
|
25
|
-
* (`MODEL_DEGRADE_REACTIVE`) bakes the target Model + its gateway + its key into the brain composition
|
|
26
|
-
* at boot. It cannot be hot-applied without rebuilding the brain, so it is registered on the existing
|
|
27
|
-
* restartRequired /health contract instead (see `restart-signal.ts`). Fail-loud beats serving a stale
|
|
28
|
-
* gateway silently on the rate-limit path.
|
|
29
|
-
* - skills/mcp/scenarios/runtime-gates — restart-to-apply by construction (baked into the boot wiring).
|
|
30
|
-
*
|
|
31
|
-
* (design/158 A13, internal-lossless) This module is now a FACADE: the implementation lives in
|
|
32
|
-
* `src/config-center/` split by responsibility group (HTTP client / EffectiveConfig application /
|
|
33
|
-
* restart-signal detection / skills+MCP consumption). Every symbol below is re-exported UNCHANGED —
|
|
34
|
-
* existing `from "./sema-registry.js"` / `from "../sema-registry.js"` imports need zero changes.
|
|
35
|
-
*/
|
|
36
|
-
export { fetchEffective, fetchPrincipalCaps, ConfigCenterHttpError, fetchSkillContent, fetchPromptArtifact, fetchPromptBlob, } from "./config-center/http-client.js";
|
|
37
|
-
export { mutateInPlace, applyEffective, applyRuntimeGates, applyRuntimeHot, resolveDefaultModelName, logEffectiveDiff, runtimeHasActiveGate, } from "./config-center/apply-effective.js";
|
|
38
|
-
export { restartReasons, planeHasActiveTiers, modelPlaneChanged, type RestartSlice, type RestartSliceCtx, type RestartSignal, } from "./config-center/restart-signal.js";
|
|
39
|
-
export { applyCenterSkills, resolveMcpServers, mcpForScenario } from "./config-center/skills-mcp.js";
|
|
40
|
-
export type { CenterSkillManifest, CenterMcpServer, EffectiveConfig, ExecutionRuling, SessionMirrorRuling, } from "./config-center/types.js";
|
|
41
|
-
//# sourceMappingURL=sema-registry.d.ts.map
|
package/dist/sema-registry.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sema-registry adapter — pull the effective config from sema-registry and apply it OVER the
|
|
3
|
-
* env-derived defaults (env = fallback, center = override). Follows the "universal internal
|
|
4
|
-
* schema → translate at the boundary" pattern, with our security boundary kept:
|
|
5
|
-
*
|
|
6
|
-
* - the CENTER owns the LOGICAL config: the model roster (names/capabilities/tier), the role map,
|
|
7
|
-
* and team templates;
|
|
8
|
-
* - the SERVICE env still owns the SECRETS: API keys stay in env (the center never stores a secret);
|
|
9
|
-
* keys are per-model via `apiKeyEnv` → `config.modelApiKeyEnv` → the spec's `getApiKeyAndHeaders`
|
|
10
|
-
* (core 1.45), so each model/cascade-rung authenticates with its own upstream key.
|
|
11
|
-
*
|
|
12
|
-
* Per-model `baseUrl` IS transported (a catalog model may live on a different gateway;
|
|
13
|
-
* core brain honors model.baseUrl, absent = "" = boot-env endpoint).
|
|
14
|
-
*
|
|
15
|
-
* Hot-reload status (复审 2026-07-29 P1-11 — 亲读判定,取代此处旧的 "models/roles are restart-to-apply"
|
|
16
|
-
* TODO, which went stale when `mutateInPlace` landed):
|
|
17
|
-
* - models/roles/roster/teams/projects/autonomy — **HOT**. `applyEffective` mutates `config.models`/
|
|
18
|
-
* `config.roles` IN PLACE, and core's Runner reads `this.deps.models/roles` per task off that very
|
|
19
|
-
* reference. Both brains re-resolve `model.baseUrl || config.baseUrl` inside `buildRequest()` on every
|
|
20
|
-
* call (core 2.1.0 `brain/openai.js` + `brain/anthropic.js`), so a moved gateway takes effect on the
|
|
21
|
-
* next task with no restart.
|
|
22
|
-
* - the same plane under a **tier-frozen** Runner — deferred, not hot: core expands a PRIVATE catalog copy
|
|
23
|
-
* at construction, so `main` defers the whole plane and the `models-tiers` restart slice signals.
|
|
24
|
-
* - **`degrade-route`** — the one genuinely boot-frozen catalog consumer left: reactive degrade
|
|
25
|
-
* (`MODEL_DEGRADE_REACTIVE`) bakes the target Model + its gateway + its key into the brain composition
|
|
26
|
-
* at boot. It cannot be hot-applied without rebuilding the brain, so it is registered on the existing
|
|
27
|
-
* restartRequired /health contract instead (see `restart-signal.ts`). Fail-loud beats serving a stale
|
|
28
|
-
* gateway silently on the rate-limit path.
|
|
29
|
-
* - skills/mcp/scenarios/runtime-gates — restart-to-apply by construction (baked into the boot wiring).
|
|
30
|
-
*
|
|
31
|
-
* (design/158 A13, internal-lossless) This module is now a FACADE: the implementation lives in
|
|
32
|
-
* `src/config-center/` split by responsibility group (HTTP client / EffectiveConfig application /
|
|
33
|
-
* restart-signal detection / skills+MCP consumption). Every symbol below is re-exported UNCHANGED —
|
|
34
|
-
* existing `from "./sema-registry.js"` / `from "../sema-registry.js"` imports need zero changes.
|
|
35
|
-
*/
|
|
36
|
-
export { fetchEffective, fetchPrincipalCaps, ConfigCenterHttpError, fetchSkillContent, fetchPromptArtifact, fetchPromptBlob, } from "./config-center/http-client.js";
|
|
37
|
-
export { mutateInPlace, applyEffective, applyRuntimeGates, applyRuntimeHot, resolveDefaultModelName, logEffectiveDiff, runtimeHasActiveGate, } from "./config-center/apply-effective.js";
|
|
38
|
-
export { restartReasons, planeHasActiveTiers, modelPlaneChanged, } from "./config-center/restart-signal.js";
|
|
39
|
-
export { applyCenterSkills, resolveMcpServers, mcpForScenario } from "./config-center/skills-mcp.js";
|
|
40
|
-
//# sourceMappingURL=sema-registry.js.map
|