@sema-agent/server 7.16.0 → 7.18.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/USAGE.md +28 -0
- package/dist/boot/reapers.js +29 -0
- package/dist/boot/runner-deps.d.ts +1 -1
- package/dist/boot/runner-deps.js +4 -0
- package/dist/config-types.d.ts +13 -1
- package/dist/config.js +50 -13
- package/dist/http/active-run-conflict.d.ts +10 -0
- package/dist/http/active-run-conflict.js +4 -0
- package/dist/http/routes/approvals-assistant.js +5 -1
- package/dist/http/routes/runs.js +15 -2
- package/dist/http/routes/tasks.js +34 -21
- package/dist/http/routes/trace-usage.js +4 -1
- package/dist/http/server.js +25 -14
- package/dist/http/sse-lifecycle.d.ts +65 -0
- package/dist/http/sse-lifecycle.js +25 -0
- package/dist/http/sse-log.js +8 -3
- package/dist/observability/fail-open.d.ts +4 -0
- package/dist/observability/fail-open.js +4 -0
- package/dist/plugins/e2b-orphan-reclaim.d.ts +74 -0
- package/dist/plugins/e2b-orphan-reclaim.js +135 -0
- package/dist/plugins/remote-env-e2b.js +2 -1
- package/dist/runs.js +2 -1
- package/dist/tool-approval.js +20 -3
- package/dist/trace/core-keyset-guard.d.ts +1 -1
- package/dist/trace/ledger-sink.d.ts +6 -0
- package/dist/trace/ledger-sink.js +11 -0
- package/dist/turn-activity.d.ts +30 -0
- package/dist/turn-activity.js +46 -0
- package/package.json +2 -2
|
@@ -18,7 +18,17 @@ export function createLedgerSink(opts) {
|
|
|
18
18
|
// anchor tracks the same value for its own anchor-put; both latches see the same events in the same order,
|
|
19
19
|
// so the stamps agree byte-for-byte — the anchor's extra `turnHadTool` state never feeds the stamp.)
|
|
20
20
|
let textEventId;
|
|
21
|
+
// #245 S1:活性打点(顶注契约:两打点位之一;抛错吞掉,绝不拖账本/事件循环下水)。
|
|
22
|
+
const beat = () => {
|
|
23
|
+
try {
|
|
24
|
+
opts.onActivity?.();
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
/* 分诊打点失败只丢判别材料 */
|
|
28
|
+
}
|
|
29
|
+
};
|
|
21
30
|
const append = (type, data) => {
|
|
31
|
+
beat(); // 打点位②:不经 onEvent 的直写路径(parked/done/forward)在这里被兜住
|
|
22
32
|
const step = chain.then(() => opts.appendEvent(++seq, type, data));
|
|
23
33
|
chain = step.then(() => undefined, () => undefined);
|
|
24
34
|
return step;
|
|
@@ -36,6 +46,7 @@ export function createLedgerSink(opts) {
|
|
|
36
46
|
}
|
|
37
47
|
};
|
|
38
48
|
const onEvent = async (ev) => {
|
|
49
|
+
beat(); // 打点位①:所有流事件(含只进缓冲的 text/reasoning delta)——「事件到达 sink」= turn 在推进
|
|
39
50
|
switch (ev.type) {
|
|
40
51
|
case "text_delta": {
|
|
41
52
|
const td = ev;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #245 S1([3777] 决策卡死墙攻关):进程内 per-task「turn 最后活性时刻」——running 形 409 与
|
|
3
|
+
* GET /v1/runs/:id 读面的判别材料 `msSinceLastActivity` 的唯一数据源。
|
|
4
|
+
*
|
|
5
|
+
* 【为什么需要它】run 行的 `updatedAt` 由 liveness heartbeat(独立 `setInterval`,runs.ts)推进——
|
|
6
|
+
* 它只证明 **server 进程**活着;turn 卡死在某个 await 上时心跳照走([3771] 推理漏洞的公开更正)。
|
|
7
|
+
* 「turn 真在推进」的证据 = ledger sink 的 durable append(text/tool/status/park/done 全族都过那一条
|
|
8
|
+
* 单写串行链)。cli 的 running 形保守臂([3779] C3)缺的就是这一维:没有它,「真忙的后台 run」与
|
|
9
|
+
* 「断连僵局」在 wire 上不可分辨,只能猜。
|
|
10
|
+
*
|
|
11
|
+
* 【语义边界(与消费端约定,勿漂)】
|
|
12
|
+
* - **同副本 best-effort**:记录只活在本进程。跨副本命中(claim 持有者在别的副本)或本副本重启后
|
|
13
|
+
* ⇒ 读不到 ⇒ wire 键**诚实缺席**——缺席 = 「无法证明」,不是「不活」。绝不铸 0(0 会被读成
|
|
14
|
+
* 「刚刚还活着」,错误方向与 [2255] 「宁缺毋假」纪律同族)。
|
|
15
|
+
* - 不落库、不进 SQL 面:这是分诊提示,不是状态机输入;任何门/CAS/resume 判定都不许读它。
|
|
16
|
+
*
|
|
17
|
+
* 【生命周期】终局**不主动清**——409 只在 `running` 行上消费本记录,终局行不进那个分支,残留无害;
|
|
18
|
+
* 主动清反而制造「done append 已打点、行还没翻终态」窗口里的缺席假象。有界性由插入序近似 LRU 兜底
|
|
19
|
+
* (CAP 条,超限逐最老;每条 ≈ 60B,上限 ≈ 0.5MB,常驻可接受)。
|
|
20
|
+
* 🔴 但**新世代必须清**(codex S1-F2,2026-08-13):session purge 删行后客户端合法复用自带 taskId 重
|
|
21
|
+
* 提交——不清的话新 run 首次打点前会读到旧 run 的时刻 = 假「刚有活性」证据。清点 = 三个 createRun
|
|
22
|
+
* 成功分支(routes/runs.ts + routes/tasks.ts×2,接线锚在 session-active-conflict-materials 测试)。
|
|
23
|
+
*/
|
|
24
|
+
/** ledger sink 每次 durable append 时打点(装配点:runs.ts / routes/tasks.ts 的 createLedgerSink)。 */
|
|
25
|
+
export declare function recordTurnActivity(taskId: string): void;
|
|
26
|
+
/** 最后活性时刻(epoch ms);无记录 ⇒ undefined(缺席语义见顶注)。 */
|
|
27
|
+
export declare function readTurnActivityMs(taskId: string): number | undefined;
|
|
28
|
+
/** 测试隔离用(生产路径不调:终局不清的理由见顶注)。 */
|
|
29
|
+
export declare function clearTurnActivity(taskId: string): void;
|
|
30
|
+
//# sourceMappingURL=turn-activity.d.ts.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #245 S1([3777] 决策卡死墙攻关):进程内 per-task「turn 最后活性时刻」——running 形 409 与
|
|
3
|
+
* GET /v1/runs/:id 读面的判别材料 `msSinceLastActivity` 的唯一数据源。
|
|
4
|
+
*
|
|
5
|
+
* 【为什么需要它】run 行的 `updatedAt` 由 liveness heartbeat(独立 `setInterval`,runs.ts)推进——
|
|
6
|
+
* 它只证明 **server 进程**活着;turn 卡死在某个 await 上时心跳照走([3771] 推理漏洞的公开更正)。
|
|
7
|
+
* 「turn 真在推进」的证据 = ledger sink 的 durable append(text/tool/status/park/done 全族都过那一条
|
|
8
|
+
* 单写串行链)。cli 的 running 形保守臂([3779] C3)缺的就是这一维:没有它,「真忙的后台 run」与
|
|
9
|
+
* 「断连僵局」在 wire 上不可分辨,只能猜。
|
|
10
|
+
*
|
|
11
|
+
* 【语义边界(与消费端约定,勿漂)】
|
|
12
|
+
* - **同副本 best-effort**:记录只活在本进程。跨副本命中(claim 持有者在别的副本)或本副本重启后
|
|
13
|
+
* ⇒ 读不到 ⇒ wire 键**诚实缺席**——缺席 = 「无法证明」,不是「不活」。绝不铸 0(0 会被读成
|
|
14
|
+
* 「刚刚还活着」,错误方向与 [2255] 「宁缺毋假」纪律同族)。
|
|
15
|
+
* - 不落库、不进 SQL 面:这是分诊提示,不是状态机输入;任何门/CAS/resume 判定都不许读它。
|
|
16
|
+
*
|
|
17
|
+
* 【生命周期】终局**不主动清**——409 只在 `running` 行上消费本记录,终局行不进那个分支,残留无害;
|
|
18
|
+
* 主动清反而制造「done append 已打点、行还没翻终态」窗口里的缺席假象。有界性由插入序近似 LRU 兜底
|
|
19
|
+
* (CAP 条,超限逐最老;每条 ≈ 60B,上限 ≈ 0.5MB,常驻可接受)。
|
|
20
|
+
* 🔴 但**新世代必须清**(codex S1-F2,2026-08-13):session purge 删行后客户端合法复用自带 taskId 重
|
|
21
|
+
* 提交——不清的话新 run 首次打点前会读到旧 run 的时刻 = 假「刚有活性」证据。清点 = 三个 createRun
|
|
22
|
+
* 成功分支(routes/runs.ts + routes/tasks.ts×2,接线锚在 session-active-conflict-materials 测试)。
|
|
23
|
+
*/
|
|
24
|
+
const CAP = 8192;
|
|
25
|
+
const lastActivityByTask = new Map();
|
|
26
|
+
/** ledger sink 每次 durable append 时打点(装配点:runs.ts / routes/tasks.ts 的 createLedgerSink)。 */
|
|
27
|
+
export function recordTurnActivity(taskId) {
|
|
28
|
+
if (lastActivityByTask.has(taskId)) {
|
|
29
|
+
lastActivityByTask.delete(taskId); // 重插保持插入序 = 近似 LRU
|
|
30
|
+
}
|
|
31
|
+
else if (lastActivityByTask.size >= CAP) {
|
|
32
|
+
const oldest = lastActivityByTask.keys().next().value;
|
|
33
|
+
if (oldest !== undefined)
|
|
34
|
+
lastActivityByTask.delete(oldest);
|
|
35
|
+
}
|
|
36
|
+
lastActivityByTask.set(taskId, Date.now());
|
|
37
|
+
}
|
|
38
|
+
/** 最后活性时刻(epoch ms);无记录 ⇒ undefined(缺席语义见顶注)。 */
|
|
39
|
+
export function readTurnActivityMs(taskId) {
|
|
40
|
+
return lastActivityByTask.get(taskId);
|
|
41
|
+
}
|
|
42
|
+
/** 测试隔离用(生产路径不调:终局不清的理由见顶注)。 */
|
|
43
|
+
export function clearTurnActivity(taskId) {
|
|
44
|
+
lastActivityByTask.delete(taskId);
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=turn-activity.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/server",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.18.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.30.0",
|
|
58
58
|
"@sema-agent/registry-core": "^0.16.0",
|
|
59
59
|
"e2b": "^2.28.0",
|
|
60
60
|
"libsodium-wrappers": "^0.8.4",
|