@sema-agent/server 5.2.0 → 5.4.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/boot/resolve-spec.js +2 -4
- package/dist/boot/stores.js +4 -1
- package/dist/capabilities/scenarios.d.ts +2 -3
- package/dist/capabilities/scenarios.js +6 -14
- package/dist/http/routes/sessions.js +13 -5
- package/dist/http/server.js +25 -0
- package/dist/http/wire-types.d.ts +4 -0
- package/dist/run-local.js +1 -1
- package/package.json +3 -3
|
@@ -89,10 +89,8 @@ export function createResolveSpec(ctx) {
|
|
|
89
89
|
// resolving here, skills/mcp would still be filtered by the raw unknown name → any skill/MCP tagged
|
|
90
90
|
// ["default"] silently drops. council finding.)
|
|
91
91
|
const scenarioName = scenarios[requested] ? requested : "default";
|
|
92
|
-
// [891]
|
|
92
|
+
// [891]→[2400]:"autonomous" alias 已退役(clay 裁不留过渡)——body 显式传它走 scenario_unknown 400。
|
|
93
93
|
// 定死 finalVerification:true 保存量行为)。warn 不 400——TB harness/存量部署平滑迁移。
|
|
94
|
-
if (scenarioName === "autonomous")
|
|
95
|
-
logger.warn("scenario_autonomous_deprecated", { alias: "code", note: "renamed by [891]; alias keeps finalVerification pinned — pass scenario:'code' (+ explicit finalVerification if wanted)" });
|
|
96
94
|
const cap = selectScenario(scenarios, scenarioName)(body, auth?.principal);
|
|
97
95
|
// codex R3/R4 (appendSystemPrompt 案): ONE center-pack snapshot per request — the append-less gate below
|
|
98
96
|
// AND the provider pick (promptProvider field) both read THIS capture, never the mutable centerPrompts ref
|
|
@@ -538,7 +536,7 @@ export function createResolveSpec(ctx) {
|
|
|
538
536
|
// design/132 (core 1.249): one-shot end-game verification nudge ("re-run the final artifact through
|
|
539
537
|
// its real entrypoint before finishing"). OPT-IN by core's own judgment (default ON lost the evidence case:
|
|
540
538
|
// +1 turn on every interactive write task) — the AUTONOMY caller declares it (harness/scheduler lanes).
|
|
541
|
-
// [849] scenario-declared leg
|
|
539
|
+
// [849]→[2400] scenario-declared leg 已无生产者(autonomous 退役后无场景定死终验);保留 OR 折入形防回归 —— (cap.finalVerification —
|
|
542
540
|
// picking that scenario IS the autonomy declaration, so this is not "inferring from scenario"); OR-folded
|
|
543
541
|
// with the caller's explicit flag — a scenario can only ADD the closing verification turn, never strip a
|
|
544
542
|
// caller's request. Children do not inherit (core semantics).
|
package/dist/boot/stores.js
CHANGED
|
@@ -253,7 +253,10 @@ export async function openStores(ctx) {
|
|
|
253
253
|
mailboxStore = new TiDBMailboxStore(mysqlPool);
|
|
254
254
|
}
|
|
255
255
|
else if (backend?.kind === "local") {
|
|
256
|
-
|
|
256
|
+
// #113([2399]③→[2408] core 5.2.0 补座):腐读披露——照 roster 同形;torn-tail 静默=core 有意边界。
|
|
257
|
+
mailboxStore = new FileMailboxStore(config.localDataRoot ?? localRoot, {
|
|
258
|
+
onCorruptRead: (info) => logger.warn("mailbox_corrupt_read", { path: info.path, reason: info.reason }),
|
|
259
|
+
});
|
|
257
260
|
}
|
|
258
261
|
if (mailboxStore)
|
|
259
262
|
logger.info("mailbox_store_enabled", { backend: pgPool ? "pg" : mysqlPool ? "tidb" : "file" });
|
|
@@ -19,7 +19,7 @@ export interface ScenarioBundle {
|
|
|
19
19
|
skills: SkillSpec[];
|
|
20
20
|
promptProvider?: PromptProvider;
|
|
21
21
|
/** [849] 场景解释层定死的终验开关(core TaskSpec.finalVerification):bench 实测产品默认请求与
|
|
22
|
-
* bench
|
|
22
|
+
* bench 态差距三件之一。[2400] 起无场景定死(autonomous 退役)——纯 caller 显式旋钮;spec 组装处 OR 折入(场景只会
|
|
23
23
|
* 多加一轮收官验证,绝不收窄 caller 意图),壳/caller 不感知。 */
|
|
24
24
|
finalVerification?: true;
|
|
25
25
|
}
|
|
@@ -130,7 +130,6 @@ export declare function semaIdentityProvider(): PromptProvider;
|
|
|
130
130
|
*/
|
|
131
131
|
export declare function codePromptProvider(brand: boolean): PromptProvider;
|
|
132
132
|
/** @deprecated [891] 改名 code——一版过渡期保留旧符号(与场景名 alias 同窗退役)。 */
|
|
133
|
-
export declare const autonomousPromptProvider: typeof codePromptProvider;
|
|
134
133
|
export declare function buildScenarios(deps: ScenarioDeps): Record<string, Scenario>;
|
|
135
134
|
/** Resolve the scenario for a request (falls back to `default`). */
|
|
136
135
|
export declare function selectScenario(scenarios: Record<string, Scenario>, name: string | undefined): Scenario;
|
|
@@ -148,7 +147,7 @@ export interface ScenarioDetail {
|
|
|
148
147
|
promptSummary: string;
|
|
149
148
|
enabled: boolean;
|
|
150
149
|
}
|
|
151
|
-
/** 内建五场景详情。default/
|
|
150
|
+
/** 内建五场景详情。default/code/team 工厂对良性请求无副作用可真调(拿真实工具名单);code-review/scan 是
|
|
152
151
|
* fail-loud 语义(缺 GIT_API 配置/principal 即 throw)→ 探针失败落静态表兜底(表↔工厂一致性由测试锁:
|
|
153
152
|
* 测试喂 fake deps 真调工厂对账工具名)。enabled 对内建恒 true(约定②)。 */
|
|
154
153
|
export declare function builtinScenarioDetails(scenarios: Record<string, Scenario>, deps: Pick<ScenarioDeps, "brandIdentity">): Record<string, ScenarioDetail>;
|
|
@@ -86,12 +86,12 @@ export function codePromptProvider(brand) {
|
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
88
|
/** @deprecated [891] 改名 code——一版过渡期保留旧符号(与场景名 alias 同窗退役)。 */
|
|
89
|
-
|
|
89
|
+
// [2400] CAPS-OPS-11:autonomousPromptProvider 别名导出已随场景退役删除(真身=codePromptProvider)。
|
|
90
90
|
export function buildScenarios(deps) {
|
|
91
91
|
// The default scenario filters skills by "default" — NOT by req.scenario (which may be an unknown name
|
|
92
92
|
// that fell back here): the bundle must be a coherent "default" set, matching how main.ts resolves an
|
|
93
93
|
// unknown scenario to "default" for tools/prompt/mcp too (council finding — else default-tagged drop).
|
|
94
|
-
// 抽成具名工厂:`
|
|
94
|
+
// 抽成具名工厂:`code` 直接复用它取 bundle(工具/技能面与 default 恒等由构造保证,不靠两处
|
|
95
95
|
// 各写一份 assembleCodeTools 参数再祈祷不漂移)。
|
|
96
96
|
const defaultScenario = (req) => {
|
|
97
97
|
// gap-audit rank-1 BLOCKER: the default agent is the CC agent loop — it MUST have the
|
|
@@ -176,14 +176,9 @@ export function buildScenarios(deps) {
|
|
|
176
176
|
...defaultScenario(req, principal),
|
|
177
177
|
promptProvider: codePromptProvider(deps.brandIdentity === true),
|
|
178
178
|
}),
|
|
179
|
-
// [891]
|
|
180
|
-
//
|
|
181
|
-
//
|
|
182
|
-
autonomous: (req, principal) => ({
|
|
183
|
-
...defaultScenario(req, principal),
|
|
184
|
-
promptProvider: codePromptProvider(deps.brandIdentity === true),
|
|
185
|
-
finalVerification: true,
|
|
186
|
-
}),
|
|
179
|
+
// [891]→[2400] CAPS-OPS-11(clay 裁 2026-08-03,不留任何过渡):`autonomous` 过渡 alias 已退役。
|
|
180
|
+
// body 显式传它 ⇒ 5.1.0 起的 scenario_unknown 400 响亮拒(附现役词表);旧语义迁移形=
|
|
181
|
+
// scenario:"code" + body.finalVerification:true(终验自此=纯 caller 显式旋钮,场景层无定死)。
|
|
187
182
|
"code-review": (req) => codeReview(deps, req),
|
|
188
183
|
// Neutral repo-readonly scenario (OA ask): the SAME clone-free read-only repo tools as code-review
|
|
189
184
|
// (repo_tree / repo_read_file / repo_pull_diff over GIT_API_TOKEN) with NO promptProvider — the
|
|
@@ -228,7 +223,7 @@ export function buildScenarios(deps) {
|
|
|
228
223
|
export function selectScenario(scenarios, name) {
|
|
229
224
|
return (name && scenarios[name]) || scenarios.default;
|
|
230
225
|
}
|
|
231
|
-
/** 内建五场景详情。default/
|
|
226
|
+
/** 内建五场景详情。default/code/team 工厂对良性请求无副作用可真调(拿真实工具名单);code-review/scan 是
|
|
232
227
|
* fail-loud 语义(缺 GIT_API 配置/principal 即 throw)→ 探针失败落静态表兜底(表↔工厂一致性由测试锁:
|
|
233
228
|
* 测试喂 fake deps 真调工厂对账工具名)。enabled 对内建恒 true(约定②)。 */
|
|
234
229
|
export function builtinScenarioDetails(scenarios, deps) {
|
|
@@ -247,9 +242,6 @@ export function builtinScenarioDetails(scenarios, deps) {
|
|
|
247
242
|
? "Sema 产品身份 + core 编码完全体提示词(CODE_AGENT persona+自治自检;CC 血统对表)"
|
|
248
243
|
: "core 编码完全体提示词(CODE_AGENT persona+自治自检;CC 血统对表)"),
|
|
249
244
|
default: mk("default", "通用/助理场景(域中性 persona,CC agent loop 全量工具面;[891] 起非出厂缺省,显式可选)", "full-body", probe("default", {}, undefined, ["Now"]), deps.brandIdentity ? "Sema 产品身份 + core 默认宪法(结构层由引擎合成)" : "core 默认宪法(中性,无场景附加 persona)"),
|
|
250
|
-
autonomous: mk("autonomous", "⚠️ deprecated([891] 改名 code,一版过渡 alias):code persona + finalVerification 固定开(旧语义逐字保留)", "full-body", probe("autonomous", {}, undefined, ["Now"]), deps.brandIdentity
|
|
251
|
-
? "Sema 产品身份 + core 编码完全体提示词(= code 场景;finalVerification 固定开)"
|
|
252
|
-
: "core 编码完全体提示词(= code 场景;finalVerification 固定开)"),
|
|
253
245
|
"code-review": mk("code-review", "代码评审(clone-free 只读仓库工具;council=true 升多镜头评审团)", "repo-readonly", probe("code-review", { repo: "probe/probe" }, undefined, REPO_TOOLS), "评审员/评审团协调提示词(镜头分工+产出契约)"),
|
|
254
246
|
scan: mk("scan", "中性只读仓库扫描(输出契约由 objective+skills 决定)", "repo-readonly", probe("scan", { repo: "probe/probe" }, undefined, REPO_TOOLS), "无场景附加提示词(objective+center skills 拥有输出契约)"),
|
|
255
247
|
team: mk("team", "多智能体团队圆桌(模板成员+synthesizer,模板可由 registry 配置)", "team", probe("team", {}, undefined, ["run_team"]), "团队协调者提示词(圆桌纪律+合成流程)"),
|
|
@@ -718,7 +718,15 @@ async function handleSessionsBody(req, res, url, ctx, miss) {
|
|
|
718
718
|
return;
|
|
719
719
|
}
|
|
720
720
|
const lim = limRaw === null ? 20 : Number(limRaw);
|
|
721
|
-
|
|
721
|
+
// [2400] CAPS-OPS-6(clay 裁 2026-08-03,最优设计不留旧语义):
|
|
722
|
+
// · `?before=<key>`(exclusive)游标——keys 是 uuidv7 字典序 desc(新→旧),before 取更旧段;
|
|
723
|
+
// · `total` = listKeys 口径的**快照总数**(与 tree 腿的 total 同名同义;此前=页内行数,同名反义
|
|
724
|
+
// 且超过 limit 的快照永远取不到)。竞态窗口内正被 reap 的 ghost 键会短暂多计 1,下一拍自愈;
|
|
725
|
+
// · `nextBefore` 仅在还有更旧的 key 时给(=本页最后一个 key);
|
|
726
|
+
// · 复审 A-MED 的保护不变:latest 与**展示行**同源(ghost 不当 latest)、页行掉 ghost 不空报。
|
|
727
|
+
const beforeRaw = q.get("before");
|
|
728
|
+
const scoped = beforeRaw !== null ? keys.filter((k) => k < beforeRaw) : keys;
|
|
729
|
+
const page = scoped.slice(0, lim);
|
|
722
730
|
const snapshots = [];
|
|
723
731
|
for (const k of page) {
|
|
724
732
|
const m = await fs.exportManifest(wsSession, k);
|
|
@@ -733,14 +741,14 @@ async function handleSessionsBody(req, res, url, ctx, miss) {
|
|
|
733
741
|
}
|
|
734
742
|
snapshots.push({ key: k, files: m.size, ...(bytes !== undefined ? { bytes } : {}) });
|
|
735
743
|
}
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
// tree/file/archive 全 404,尽管有有效的次新快照),且 total 计入 ghost 与 snapshots[] 不一致。
|
|
744
|
+
const lastPageKey = page.length > 0 ? page[page.length - 1] : undefined;
|
|
745
|
+
const hasMore = lastPageKey !== undefined && scoped.length > page.length;
|
|
739
746
|
sendJson(res, 200, {
|
|
740
747
|
sessionId: wsSession,
|
|
741
748
|
snapshots,
|
|
742
749
|
...(snapshots.length > 0 ? { latest: snapshots[0].key } : {}),
|
|
743
|
-
total:
|
|
750
|
+
total: keys.length,
|
|
751
|
+
...(hasMore ? { nextBefore: lastPageKey } : {}),
|
|
744
752
|
});
|
|
745
753
|
return;
|
|
746
754
|
}
|
package/dist/http/server.js
CHANGED
|
@@ -51,6 +51,7 @@ export { coarseStatusForState, errorCodeForExit };
|
|
|
51
51
|
// (routes/* 绝不可值 import server.ts:那条边会闭合运行时环,见 test/module-cycle-gate.test.ts)。
|
|
52
52
|
import { sendJson, sendError, httpErrorCode, msg } from "./send.js";
|
|
53
53
|
import { authorized, systemFor, gatedPrincipal, explicitOperatorOk, isOperator } from "./principal-gate.js";
|
|
54
|
+
import { resumeEntryForGate } from "./active-run-conflict.js";
|
|
54
55
|
export { explicitOperatorOk, isOperator };
|
|
55
56
|
/** 分组入参 → 平铺视图(createHttpServer 的第一件事)。一组都没给 ⇒ 原样返回(存量调用零开销、零形变)。 */
|
|
56
57
|
export function flattenServiceDeps(deps) {
|
|
@@ -1194,11 +1195,32 @@ export function createHttpServer(rawDeps) {
|
|
|
1194
1195
|
// D-D SLA deny-sweep 不受影响:它的取行查询本就只选 gate_kind IN ('human','irreversible_ask')。
|
|
1195
1196
|
const decideGateKind = cp.gate?.kind;
|
|
1196
1197
|
if (decideGateKind !== "human" && decideGateKind !== "irreversible_ask") {
|
|
1198
|
+
// [2400] HITL-6(clay 裁 2026-08-03,不做兼容):补机读指路——与 [2255]① 的 409 材料同形
|
|
1199
|
+
// (pendingGate{kind, decidePath},resumeEntryForGate 单源表),客户端凭 decidePath 直达对的
|
|
1200
|
+
// resume 入口,不再解析人话文案。taskId 源=cp.sourceTaskId;缺席 ⇒ 只带 kind,诚实不铸假路径。
|
|
1201
|
+
const gnPath = decideGateKind && cp.sourceTaskId
|
|
1202
|
+
? resumeEntryForGate(decideGateKind, { sessionId, taskId: cp.sourceTaskId })
|
|
1203
|
+
: null;
|
|
1197
1204
|
return {
|
|
1198
1205
|
status: 409,
|
|
1199
1206
|
body: {
|
|
1200
1207
|
error: `task is suspended on a '${decideGateKind ?? "unknown"}' gate, not a tool approval — a plan_review gate is resolved via POST /v1/assistant/tasks/:id/plan_review, a resource_limit suspension via POST /v1/assistant/tasks/:id/resume`,
|
|
1201
1208
|
errorCode: "gate_not_tool_approval",
|
|
1209
|
+
...(decideGateKind ? { pendingGate: { kind: decideGateKind, ...(gnPath ? { decidePath: gnPath } : {}) } } : {}),
|
|
1210
|
+
},
|
|
1211
|
+
};
|
|
1212
|
+
}
|
|
1213
|
+
// [2400] HITL-12(clay 裁 2026-08-03:不兼容老客户端):HTTP 腿强制决策-动作绑定——无 checkpointToken
|
|
1214
|
+
// 且无 boundCallId 的 decide 拒收(此前静默回落 current-pending:并发窗口下 A 想批的门刚被 B 的新门顶掉
|
|
1215
|
+
// 就裁错对象)。内部 D-D SLA deny-sweep(req 缺席)豁免:系统腿 deny 过期行,无并发歧义。位置刻意在
|
|
1216
|
+
// gate-kind 守卫**之后**:错门型先得 409+pendingGate 指路(HITL-6),而不是被本门的 400 遮蔽。
|
|
1217
|
+
if (req !== undefined && !binding?.checkpointToken && !binding?.boundCallId) {
|
|
1218
|
+
return {
|
|
1219
|
+
status: 400,
|
|
1220
|
+
body: {
|
|
1221
|
+
error: "decide requires the decision-action binding — echo checkpointToken and/or boundCallId from the pending approval (GET /v1/approvals)",
|
|
1222
|
+
errorCode: "decide_requires_binding",
|
|
1223
|
+
bindingEnforced: true,
|
|
1202
1224
|
},
|
|
1203
1225
|
};
|
|
1204
1226
|
}
|
|
@@ -1979,6 +2001,9 @@ export function createHttpServer(rawDeps) {
|
|
|
1979
2001
|
status: 200,
|
|
1980
2002
|
body: {
|
|
1981
2003
|
taskId, sessionId, status: result.status,
|
|
2004
|
+
// [2400] HITL-12:世代探测位——本 server 强制决策-动作绑定(无绑定 decide 已在上方 400 拒),
|
|
2005
|
+
// 客户端凭它机器确认「我裁的就是我看到的那个动作」,不再有静默回落窗口。
|
|
2006
|
+
bindingEnforced: true,
|
|
1982
2007
|
...(result.errorCode ? { errorCode: result.errorCode } : {}),
|
|
1983
2008
|
...(result.errorMessage ? { errorMessage: redactSecrets(result.errorMessage) } : {}),
|
|
1984
2009
|
...(checkpointReopened ? { retriable: true } : {}), // the park is still pending — re-fetch + re-decide
|
|
@@ -10,6 +10,10 @@ import type { AgentDefinition, McpServerSpec } from "@sema-agent/core";
|
|
|
10
10
|
export interface TaskRequestBody {
|
|
11
11
|
objective: string;
|
|
12
12
|
sessionId?: string;
|
|
13
|
+
/** dispatch-gateway failover 幂等第二级:caller-minted 任务 id(uuidv7)。同 owner 重放同 id ⇒ 幂等重放;
|
|
14
|
+
* 异 owner ⇒ 409 `conflict.run_exists`;非 uuidv7 ⇒ 400 `request.id_invalid`(routes/runs.ts:192-208 真验收)。
|
|
15
|
+
* [2400] TR-16 连带:此键此前只活在 runs.ts 读点,导出类型漏declared——CAPS-OPS-13 同族第 9 键。 */
|
|
16
|
+
taskId?: string;
|
|
13
17
|
images?: Array<{
|
|
14
18
|
data: string;
|
|
15
19
|
mimeType: string;
|
package/dist/run-local.js
CHANGED
|
@@ -466,7 +466,7 @@ export async function runLocal(argv, deps = {}) {
|
|
|
466
466
|
tools: cap.tools,
|
|
467
467
|
skills: cap.skills,
|
|
468
468
|
...(cap.promptProvider ? { promptProvider: cap.promptProvider } : {}),
|
|
469
|
-
// [849]
|
|
469
|
+
// [849]→[2400] 场景层定死终验已无生产者(autonomous 退役);OR 折入形保留,与 resolveSpec 同语义。
|
|
470
470
|
...(cap.finalVerification === true ? { finalVerification: true } : {}),
|
|
471
471
|
...(mcp ? { mcp } : {}),
|
|
472
472
|
...(timeoutSec !== undefined ? { limits: { timeoutSec } } : {}),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/server",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.4.0",
|
|
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",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"build:binary:run-local:darwin-arm64": "bun build --compile --target=bun-darwin-arm64 src/run-local.ts --outfile dist/run-local-darwin-arm64"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@sema-agent/core": "^5.
|
|
57
|
+
"@sema-agent/core": "^5.2.0",
|
|
58
58
|
"@sema-agent/registry-core": "^0.13.0",
|
|
59
59
|
"e2b": "^2.28.0",
|
|
60
60
|
"libsodium-wrappers": "^0.8.4",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"sharp": "^0.35.3"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
-
"@sema-agent/sdk": "^
|
|
71
|
+
"@sema-agent/sdk": "^5.1.0",
|
|
72
72
|
"@types/libsodium-wrappers": "^0.7.14",
|
|
73
73
|
"@types/node": "22.10.2",
|
|
74
74
|
"@types/pg": "^8.20.0",
|