@migor/agentia 0.9.4 → 0.10.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/CHANGELOG.md +1280 -4
- package/README.en.md +61 -3
- package/README.md +66 -4
- package/dist/AGENTS.md +330 -45
- package/dist/container/container.js +21 -0
- package/dist/container/container.js.map +1 -1
- package/dist/core/limits.d.ts +101 -14
- package/dist/core/limits.js +103 -13
- package/dist/core/limits.js.map +1 -1
- package/dist/core/line-framing.d.ts +36 -0
- package/dist/core/line-framing.js +39 -0
- package/dist/core/line-framing.js.map +1 -0
- package/dist/core/message.d.ts +11 -0
- package/dist/core/run.d.ts +68 -4
- package/dist/core/run.js +27 -1
- package/dist/core/run.js.map +1 -1
- package/dist/core/schema.js +59 -8
- package/dist/core/schema.js.map +1 -1
- package/dist/core/timeout.d.ts +43 -1
- package/dist/core/timeout.js +76 -3
- package/dist/core/timeout.js.map +1 -1
- package/dist/core/tool.d.ts +25 -1
- package/dist/core/trace.d.ts +40 -1
- package/dist/core/trace.js +26 -0
- package/dist/core/trace.js.map +1 -1
- package/dist/engine/budget.js +14 -0
- package/dist/engine/budget.js.map +1 -1
- package/dist/engine/defer.d.ts +49 -0
- package/dist/engine/defer.js +72 -0
- package/dist/engine/defer.js.map +1 -0
- package/dist/engine/errors.d.ts +23 -1
- package/dist/engine/errors.js +24 -0
- package/dist/engine/errors.js.map +1 -1
- package/dist/engine/forwarded.d.ts +14 -5
- package/dist/engine/forwarded.js +4 -1
- package/dist/engine/forwarded.js.map +1 -1
- package/dist/engine/loop-result.d.ts +65 -7
- package/dist/engine/loop-result.js +24 -5
- package/dist/engine/loop-result.js.map +1 -1
- package/dist/engine/loop.d.ts +2 -0
- package/dist/engine/loop.js +157 -17
- package/dist/engine/loop.js.map +1 -1
- package/dist/engine/mcp-server-http.d.ts +2 -0
- package/dist/engine/mcp-server-http.js +215 -0
- package/dist/engine/mcp-server-http.js.map +1 -0
- package/dist/engine/mcp-server-stdio.d.ts +15 -0
- package/dist/engine/mcp-server-stdio.js +106 -0
- package/dist/engine/mcp-server-stdio.js.map +1 -0
- package/dist/engine/mcp-server.d.ts +134 -0
- package/dist/engine/mcp-server.js +232 -0
- package/dist/engine/mcp-server.js.map +1 -0
- package/dist/engine/menu-drift.d.ts +34 -0
- package/dist/engine/menu-drift.js +81 -0
- package/dist/engine/menu-drift.js.map +1 -0
- package/dist/engine/policy.d.ts +2 -1
- package/dist/engine/policy.js +7 -1
- package/dist/engine/policy.js.map +1 -1
- package/dist/engine/replay.d.ts +2 -1
- package/dist/engine/replay.js +3 -2
- package/dist/engine/replay.js.map +1 -1
- package/dist/engine/resume-input.d.ts +10 -0
- package/dist/engine/resume-input.js +11 -0
- package/dist/engine/resume-input.js.map +1 -1
- package/dist/engine/run-config.d.ts +26 -2
- package/dist/engine/run-config.js +60 -0
- package/dist/engine/run-config.js.map +1 -1
- package/dist/engine/spec.d.ts +33 -4
- package/dist/engine/spec.js.map +1 -1
- package/dist/engine/tool-context.d.ts +10 -5
- package/dist/engine/tool-context.js +5 -1
- package/dist/engine/tool-context.js.map +1 -1
- package/dist/engine/tracer.d.ts +43 -5
- package/dist/engine/tracer.js +73 -10
- package/dist/engine/tracer.js.map +1 -1
- package/dist/engine/trimming.js +28 -2
- package/dist/engine/trimming.js.map +1 -1
- package/dist/engine/turn.d.ts +60 -3
- package/dist/engine/turn.js +180 -71
- package/dist/engine/turn.js.map +1 -1
- package/dist/engine/types.d.ts +89 -3
- package/dist/engine/types.js +38 -2
- package/dist/engine/types.js.map +1 -1
- package/dist/eval/export.d.ts +48 -0
- package/dist/eval/export.js +146 -0
- package/dist/eval/export.js.map +1 -0
- package/dist/eval/harvest.js +7 -2
- package/dist/eval/harvest.js.map +1 -1
- package/dist/index.d.ts +8 -5
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/adapter-options.d.ts +22 -0
- package/dist/integrations/adapter-options.js +51 -0
- package/dist/integrations/adapter-options.js.map +1 -1
- package/dist/integrations/anthropic.d.ts +4 -2
- package/dist/integrations/anthropic.js +27 -27
- package/dist/integrations/anthropic.js.map +1 -1
- package/dist/integrations/file-sink.d.ts +20 -0
- package/dist/integrations/file-sink.js +27 -0
- package/dist/integrations/file-sink.js.map +1 -0
- package/dist/integrations/mcp-http.d.ts +3 -3
- package/dist/integrations/mcp-http.js +1 -1
- package/dist/integrations/mcp-http.js.map +1 -1
- package/dist/integrations/mcp-protocol.d.ts +115 -0
- package/dist/integrations/mcp-protocol.js +69 -0
- package/dist/integrations/mcp-protocol.js.map +1 -0
- package/dist/integrations/mcp-stdio.d.ts +3 -3
- package/dist/integrations/mcp-stdio.js +17 -3
- package/dist/integrations/mcp-stdio.js.map +1 -1
- package/dist/integrations/mcp.d.ts +6 -95
- package/dist/integrations/mcp.js +24 -66
- package/dist/integrations/mcp.js.map +1 -1
- package/dist/integrations/metrics-otlp.js +52 -7
- package/dist/integrations/metrics-otlp.js.map +1 -1
- package/dist/integrations/metrics-render.d.ts +15 -0
- package/dist/integrations/metrics-render.js +79 -2
- package/dist/integrations/metrics-render.js.map +1 -1
- package/dist/integrations/metrics-state.d.ts +99 -1
- package/dist/integrations/metrics-state.js +128 -4
- package/dist/integrations/metrics-state.js.map +1 -1
- package/dist/integrations/metrics.d.ts +62 -6
- package/dist/integrations/metrics.js +49 -8
- package/dist/integrations/metrics.js.map +1 -1
- package/dist/integrations/openai.js +9 -31
- package/dist/integrations/openai.js.map +1 -1
- package/dist/integrations/otlp.d.ts +3 -3
- package/dist/integrations/report.d.ts +7 -0
- package/dist/integrations/report.js +20 -1
- package/dist/integrations/report.js.map +1 -1
- package/dist/runtime/memory.d.ts +61 -1
- package/dist/runtime/memory.js +47 -7
- package/dist/runtime/memory.js.map +1 -1
- package/dist/runtime/run.d.ts +12 -2
- package/dist/runtime/run.js +126 -17
- package/dist/runtime/run.js.map +1 -1
- package/dist/store/fsStore.js +10 -4
- package/dist/store/fsStore.js.map +1 -1
- package/dist/store/record.d.ts +41 -0
- package/dist/store/record.js +54 -0
- package/dist/store/record.js.map +1 -0
- package/dist/store/redisStore.d.ts +24 -1
- package/dist/store/redisStore.js +42 -7
- package/dist/store/redisStore.js.map +1 -1
- package/dist/store/sqliteStore.d.ts +23 -0
- package/dist/store/sqliteStore.js +103 -8
- package/dist/store/sqliteStore.js.map +1 -1
- package/dist/store/store.d.ts +65 -2
- package/dist/store/store.js +5 -2
- package/dist/store/store.js.map +1 -1
- package/dist/toolkit/capability-cycles.d.ts +50 -0
- package/dist/toolkit/capability-cycles.js +88 -0
- package/dist/toolkit/capability-cycles.js.map +1 -0
- package/dist/toolkit/capability-slice.d.ts +86 -0
- package/dist/toolkit/capability-slice.js +98 -0
- package/dist/toolkit/capability-slice.js.map +1 -0
- package/dist/toolkit/module.d.ts +7 -1
- package/dist/toolkit/module.js +65 -32
- package/dist/toolkit/module.js.map +1 -1
- package/dist/transport/approval-policy.d.ts +1 -1
- package/dist/transport/approval-policy.js +8 -4
- package/dist/transport/approval-policy.js.map +1 -1
- package/dist/transport/approval-supervisor.d.ts +73 -0
- package/dist/transport/approval-supervisor.js +252 -0
- package/dist/transport/approval-supervisor.js.map +1 -0
- package/dist/transport/async.d.ts +159 -56
- package/dist/transport/async.js +627 -269
- package/dist/transport/async.js.map +1 -1
- package/dist/transport/drain-gate.d.ts +6 -2
- package/dist/transport/drain-gate.js +14 -2
- package/dist/transport/drain-gate.js.map +1 -1
- package/dist/transport/http-endpoints.d.ts +151 -0
- package/dist/transport/http-endpoints.js +480 -0
- package/dist/transport/http-endpoints.js.map +1 -0
- package/dist/transport/http-io.d.ts +66 -0
- package/dist/transport/http-io.js +145 -0
- package/dist/transport/http-io.js.map +1 -0
- package/dist/transport/http-route.d.ts +10 -3
- package/dist/transport/http-route.js +18 -3
- package/dist/transport/http-route.js.map +1 -1
- package/dist/transport/http-shapes.d.ts +11 -0
- package/dist/transport/http-shapes.js +31 -1
- package/dist/transport/http-shapes.js.map +1 -1
- package/dist/transport/http.d.ts +22 -35
- package/dist/transport/http.js +98 -476
- package/dist/transport/http.js.map +1 -1
- package/dist/transport/owner-id.d.ts +29 -0
- package/dist/transport/owner-id.js +46 -0
- package/dist/transport/owner-id.js.map +1 -0
- package/dist/transport/owner-liveness.d.ts +8 -0
- package/dist/transport/owner-liveness.js +56 -0
- package/dist/transport/owner-liveness.js.map +1 -0
- package/dist/transport/resume-policy.d.ts +48 -10
- package/dist/transport/resume-policy.js +25 -10
- package/dist/transport/resume-policy.js.map +1 -1
- package/dist/transport/resume-scanner.d.ts +55 -0
- package/dist/transport/resume-scanner.js +219 -0
- package/dist/transport/resume-scanner.js.map +1 -0
- package/dist/transport/scheduler.js +9 -23
- package/dist/transport/scheduler.js.map +1 -1
- package/dist/transport/signal-supervisor.d.ts +80 -0
- package/dist/transport/signal-supervisor.js +129 -0
- package/dist/transport/signal-supervisor.js.map +1 -0
- package/dist/transport/slot-pool.d.ts +9 -1
- package/dist/transport/slot-pool.js +9 -1
- package/dist/transport/slot-pool.js.map +1 -1
- package/dist/transport/task-events.d.ts +34 -3
- package/dist/transport/task-events.js +93 -5
- package/dist/transport/task-events.js.map +1 -1
- package/dist/transport/wake-policy.d.ts +50 -0
- package/dist/transport/wake-policy.js +43 -0
- package/dist/transport/wake-policy.js.map +1 -0
- package/package.json +14 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume-scanner.js","sourceRoot":"","sources":["../../src/transport/resume-scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,24 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { isThenable } from '../store/store.js';
|
|
3
3
|
import { zeroClauseOf } from '../core/limits.js';
|
|
4
|
-
|
|
5
|
-
* Agentia —— 定时触发(spec §6.3 定时事件)。
|
|
6
|
-
* 依赖 AsyncRunner:每次触发 = submit 一次异步任务。
|
|
7
|
-
*
|
|
8
|
-
* 周期任务去重:幂等键按 interval 窗口分片(同一片只算一次);
|
|
9
|
-
* 即便上一片还没跑完,下一片仍会重新 submit —— 同步 store 下若上一任务的同窗口键
|
|
10
|
-
* 还在 queued/running/succeeded,AsyncRunner 的 at-least-once 去重会直接返回既有记录,
|
|
11
|
-
* 同窗口不并发跑两遍;**异步 store 下该保证减弱**:submit 即时去重让位于执行前去重
|
|
12
|
-
* (只采纳 succeeded),上一片仍 running 时新片可能并发执行 —— at-least-once 语义允许,
|
|
13
|
-
* 窗口推进后新键正常执行。
|
|
14
|
-
*
|
|
15
|
-
* v1 提供 everyMs / at;cron 表达式解析后置(宿主可用队列 cron 替换语义)。
|
|
16
|
-
*/
|
|
17
|
-
/**
|
|
18
|
-
* Node 定时器延迟的上限:2^31-1ms(约 24.86 天)。超过会被**静默**钳到 1ms
|
|
19
|
-
* (只打一条 TimeoutOverflowWarning)—— every/at 都在注册前挡掉(2026-09-19 复审发现)。
|
|
20
|
-
*/
|
|
21
|
-
const MAX_TIMER_DELAY_MS = 2_147_483_647;
|
|
4
|
+
import { MAX_TIMER_DELAY_MS } from '../core/timeout.js';
|
|
22
5
|
export class Scheduler {
|
|
23
6
|
runner;
|
|
24
7
|
jobs = new Map();
|
|
@@ -34,9 +17,11 @@ export class Scheduler {
|
|
|
34
17
|
throw new Error(`Scheduler.every 的 intervalMs 必须为正有限数(${zeroClauseOf('Scheduler.every.intervalMs')}),收到 ${intervalMs}`);
|
|
35
18
|
}
|
|
36
19
|
if (intervalMs > MAX_TIMER_DELAY_MS) {
|
|
37
|
-
// Node 的定时器延迟是 32 位有符号整数:超过 2^31-1ms(约 24.86
|
|
38
|
-
//
|
|
39
|
-
//
|
|
20
|
+
// Node 的定时器延迟是 32 位有符号整数:超过 2^31-1ms(约 24.86 天)**不会被遵守** ——
|
|
21
|
+
// Node 只在 stderr 留一行 TimeoutOverflowWarning,随后把延迟钳到 1ms,周期任务退化成
|
|
22
|
+
// 每毫秒空转(每个 tick 都对 store 打一轮)。这是配置错误,与上面的 0 同款处理。
|
|
23
|
+
// (此前的注释写「runTimeoutMs 在 async.ts 有同款防线」—— 与当时的实现不符;
|
|
24
|
+
// 2026-09-28 把那道防线真的补上了,五处站点现在都走 assertTimerDelay。)
|
|
40
25
|
throw new Error(`Scheduler.every 的 intervalMs 超过定时器上限(约 24.86 天),收到 ${intervalMs}`);
|
|
41
26
|
}
|
|
42
27
|
if (opts.maxInFlight !== undefined) {
|
|
@@ -81,7 +66,8 @@ export class Scheduler {
|
|
|
81
66
|
const id = randomUUID();
|
|
82
67
|
const delay = Math.max(0, when.getTime() - Date.now());
|
|
83
68
|
if (delay > MAX_TIMER_DELAY_MS) {
|
|
84
|
-
// 与 every() 同款防线:超 2^31-1ms
|
|
69
|
+
// 与 every() 同款防线:超 2^31-1ms 的延迟**不会被遵守**(Node 只在 stderr 留一行
|
|
70
|
+
// TimeoutOverflowWarning,然后把延迟钳到 1ms)⇒「30 天后」变成「立即触发」,
|
|
85
71
|
// 定时语义直接作废。远期单发请拆成多次自检(或落库后由宿主自己的 cron 驱动)。
|
|
86
72
|
throw new Error(`Scheduler.at 的目标时刻超过定时器上限(约 24.86 天后),收到 ${when.toISOString()}`);
|
|
87
73
|
}
|
|
@@ -139,7 +125,7 @@ export class Scheduler {
|
|
|
139
125
|
if (isThenable(rec)) {
|
|
140
126
|
void rec
|
|
141
127
|
.then((r) => {
|
|
142
|
-
//
|
|
128
|
+
// suspended 也算「不再占执行资源」(在等人,不在跑)——
|
|
143
129
|
// 不放手会让 maxInFlight 闸门永久自闭(人可能几小时后才批)
|
|
144
130
|
if (!r || (r.status !== 'queued' && r.status !== 'running'))
|
|
145
131
|
forget(taskId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/transport/scheduler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/transport/scheduler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentia —— 信号监督:挂起任务的**事件投递**入口(`signalTask`)。
|
|
3
|
+
*
|
|
4
|
+
* 从 `async.ts` 的 `AsyncRunner` 抽出的**方向正交**的一块(外部深评结构体检的建议④
|
|
5
|
+
* 「恢复重投」那一族里、与原「审批监督」同形的另一半)。
|
|
6
|
+
*
|
|
7
|
+
* ⚠️ 它与 {@link ApprovalSupervisor} 的 `approve` 是**同一族** —— 都是「挂起任务的外部
|
|
8
|
+
* 唤醒入口」,形状逐条对应:
|
|
9
|
+
* 读记录 → 校验挂起 → 改状态 → **先落库再派发** → `unmarkSuspended` → `dispatch`
|
|
10
|
+
* 两处不同,且都是真实的语义差别(不是待收拾的重复):
|
|
11
|
+
* ① **并发闸不同款**:`approve` 共享在飞那次(决定是幂等合并,重入返回同一个 Promise);
|
|
12
|
+
* 事件**串行成链** —— 两条并发事件是两条不同的输入,共享就是静默丢掉一条。
|
|
13
|
+
* ② **多一道容量闸**:事件要进 `rec.pendingEvents`(有界),审批决定直接合并进 `rec.approvals`。
|
|
14
|
+
*
|
|
15
|
+
* 分成两个文件而不是合成一个「挂起中心」:两者的领域词不同(决定 / 事件),文件名要能说准。
|
|
16
|
+
* 若将来长出**第三个**唤醒通路,那些公共形状就该抽出来 —— 现在抽是过早。
|
|
17
|
+
*
|
|
18
|
+
* **零行为变化**:逐字搬迁 + 依赖改为构造注入。判据次序(状态 ⇒ 幂等 ⇒ 容量)、错误类型、
|
|
19
|
+
* 副作用次序一字未改。
|
|
20
|
+
*
|
|
21
|
+
* 为什么 `dispatch` 用**回调注入**而不是 import `async.ts`:见 `approval-supervisor.ts` 头注
|
|
22
|
+
* (同一条理由 —— `#dispatch` 归 `AsyncRunner`,本件只消费它)。
|
|
23
|
+
*
|
|
24
|
+
* ⚠️ `TaskEventError` 随本簇迁到这里;`async.ts` 仍 **re-export** 它 ⇒
|
|
25
|
+
* `http-endpoints.ts` 与既有用例的 `from './async.js'` 导入路径不变。
|
|
26
|
+
*/
|
|
27
|
+
import type { TaskEvent } from '../core/run.js';
|
|
28
|
+
import type { TaskRecord, TaskStore } from '../store/store.js';
|
|
29
|
+
import type { ApprovalSupervisor } from './approval-supervisor.js';
|
|
30
|
+
/**
|
|
31
|
+
* `signalTask` 的失败:带 HTTP 语义的状态码(404 = 任务不存在,409 = 任务当前不在
|
|
32
|
+
* `suspended` 状态 / 同 eventId 已投递)。形状与 `async.ts` 的 `TaskCancelError` 同款
|
|
33
|
+
* (module 级 export,不进公共导出面)。
|
|
34
|
+
*/
|
|
35
|
+
export declare class TaskEventError extends Error {
|
|
36
|
+
readonly status: 404 | 409;
|
|
37
|
+
constructor(status: 404 | 409, message: string);
|
|
38
|
+
}
|
|
39
|
+
/** `SignalSupervisor` 的注入依赖(全部由 `AsyncRunner` 构造时提供) */
|
|
40
|
+
export interface SignalSupervisorDeps {
|
|
41
|
+
store: TaskStore;
|
|
42
|
+
/** 恢复执行时写进记录的宿主标识(投递成功要 `rec.ownerId = ownerId`) */
|
|
43
|
+
ownerId: string;
|
|
44
|
+
/** 挂起读数的除名口(投递成功 = 「醒来」那一刻,读数纪律②) */
|
|
45
|
+
approvals: ApprovalSupervisor;
|
|
46
|
+
/** 派发入口(`AsyncRunner.#dispatch`:停机闸 + 唯一派发点 + 停机窗口里的一次告警) */
|
|
47
|
+
dispatch(rec: TaskRecord): void;
|
|
48
|
+
}
|
|
49
|
+
export declare class SignalSupervisor {
|
|
50
|
+
#private;
|
|
51
|
+
constructor(deps: SignalSupervisorDeps);
|
|
52
|
+
/**
|
|
53
|
+
* 投递一个事件给**挂起**的任务(2026-09-28 ⑥,run 事件投入口;
|
|
54
|
+
* `POST /tasks/:id/events` 的宿主方法侧,与 approve/cancel 对称)。
|
|
55
|
+
*
|
|
56
|
+
* 语义(设计稿 §3 逐条的落点):
|
|
57
|
+
* - **只对 `suspended` 生效**:不存在 ⇒ 404;其余状态(含已终态)⇒ 409
|
|
58
|
+
* (「不唤醒已终态」是这条状态闸的推论,与 approve 同款「状态不对要说出来」);
|
|
59
|
+
* - **幂等**:`eventId` 给定时按 `rec.deliveredEventIds` 去重,重复 ⇒ 409
|
|
60
|
+
* (簿记随记录落库,重启不丢;有界 FIFO,见 MAX_DELIVERED_EVENT_IDS)。
|
|
61
|
+
* 不给 `eventId` 就**没有恰好一次**:重复投递 = 重复进历史(如实,不假装);
|
|
62
|
+
* - **投完即续跑**(两种挂起原因都算 —— 对 timer 挂起这就是「提前醒」):
|
|
63
|
+
* 事件进 `rec.pendingEvents`、状态回 `running`,**先落库再派发**
|
|
64
|
+
* (与 approve / 到期唤醒同一条纪律:崩在窗口里不能丢事件)。
|
|
65
|
+
* 事件**不**直接追加进 `rec.spec.messages` —— 续跑判定只认历史末尾一条
|
|
66
|
+
* (`tailToolUses`),追加 user 消息会把续跑判成新对话;注入由引擎在
|
|
67
|
+
* 未决 tool_use 解决之后做(见 engine/loop.ts 的 deliverTaskEvents);
|
|
68
|
+
* - **不沿旧 wakeAt**:记录上的旧目标时刻不动(闸都 gate 在 suspended 上,
|
|
69
|
+
* 状态一翻它就失效);醒来重跑那一批时工具若再次 `deferUntil`,
|
|
70
|
+
* `wakeAt` 由新回合重新落定;
|
|
71
|
+
* - drain 期间**仍允许**(与 approve 同理由:挂起的任务只有外部输入能推进)。
|
|
72
|
+
*
|
|
73
|
+
* 并发闸与 approve **不同款**:approve 共享在飞那次(决定是幂等合并),事件**串行成链**
|
|
74
|
+
* (两条并发事件是两条不同的输入,共享 = 静默丢一条)。与其它恢复路径
|
|
75
|
+
* (approve / 到期唤醒,各有自己的闸)的竞速:进闸后重读再判挡住绝大多数;
|
|
76
|
+
* 剩下的窄窗口与既有「approve × wakeDue 分闸」同类(那两条按挂起原因天然互斥,
|
|
77
|
+
* 事件两种原因都适用,是这个闸新盖的缝 —— 已记在 spec §10 2026-09-28 ⑥)。
|
|
78
|
+
*/
|
|
79
|
+
signalTask(taskId: string, event: TaskEvent): Promise<TaskRecord>;
|
|
80
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `signalTask` 的失败:带 HTTP 语义的状态码(404 = 任务不存在,409 = 任务当前不在
|
|
3
|
+
* `suspended` 状态 / 同 eventId 已投递)。形状与 `async.ts` 的 `TaskCancelError` 同款
|
|
4
|
+
* (module 级 export,不进公共导出面)。
|
|
5
|
+
*/
|
|
6
|
+
export class TaskEventError extends Error {
|
|
7
|
+
status;
|
|
8
|
+
constructor(status, message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = 'TaskEventError';
|
|
11
|
+
this.status = status;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* `deliveredEventIds` 簿记的条数上限(FIFO 裁最旧)。它是**去重簿记**不是审计日志:
|
|
16
|
+
* 256 条对「webhook 重试窗口」绰绰有余,而无界增长会让每条 TaskRecord 随事件量膨胀
|
|
17
|
+
* (记录随 trace 一起落库,每次 save 全文重写)。「数量有界」不是用户旋钮,不进
|
|
18
|
+
* `core/limits.ts` 的 0 语义表。
|
|
19
|
+
*/
|
|
20
|
+
const MAX_DELIVERED_EVENT_IDS = 256;
|
|
21
|
+
/**
|
|
22
|
+
* `pendingEvents`(待注入事件缓冲)的**条数上限**(2026-09-28 复审第三轮,定案 **B**)。
|
|
23
|
+
*
|
|
24
|
+
* 为什么要有:`deliveredEventIds` 那侧是有界的(256),缓冲这侧原先没有 —— 而它不需要攻击者
|
|
25
|
+
* 就能长:投方每次投一条、这条 run 每次都在恢复段**再次挂起**(再挂起出口刻意不注入事件,
|
|
26
|
+
* 见 spec §10 ⑥ 第 4 条)⇒ 每条都留在记录上,而记录随 trace 一起落库、每次 save 全文重写。
|
|
27
|
+
*
|
|
28
|
+
* 为什么是「满了拒绝」而不是「丢最旧」(A 的反面):缓冲**在下次跑通时就注入并清空**,所以
|
|
29
|
+
* 上限只管「一个挂起窗口里能攒多少」。丢最旧必须**同时**把该 id 从 `deliveredEventIds` 摘掉,
|
|
30
|
+
* 否则发件方重投会拿到「已投递」的 409 而事件其实已经没了 —— 那是最坏的一种谎。宁可不收下
|
|
31
|
+
* 并说出来(调用方拿到 409 就能改主意:先让这条 run 真走起来)。
|
|
32
|
+
*
|
|
33
|
+
* 为什么是 64:一个挂起窗口里等到的输入,量级与 `deliveredEventIds` 的重试窗口(256)同类,
|
|
34
|
+
* 取它的 1/4 —— 容得下真实的 webhook 突发(一次重试窗口里几十条),又不足以把挂起任务当队列灌。
|
|
35
|
+
* **数量有界不是用户旋钮**(与 MAX_DELIVERED_EVENT_IDS 同档),不进 `core/limits.ts` 的 0 语义表。
|
|
36
|
+
*/
|
|
37
|
+
const MAX_PENDING_EVENTS = 64;
|
|
38
|
+
export class SignalSupervisor {
|
|
39
|
+
/** 同一任务的在飞事件投递(`signalTask` 的重入闸,见下) */
|
|
40
|
+
#inflight = new Map();
|
|
41
|
+
#deps;
|
|
42
|
+
constructor(deps) {
|
|
43
|
+
this.#deps = deps;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 投递一个事件给**挂起**的任务(2026-09-28 ⑥,run 事件投入口;
|
|
47
|
+
* `POST /tasks/:id/events` 的宿主方法侧,与 approve/cancel 对称)。
|
|
48
|
+
*
|
|
49
|
+
* 语义(设计稿 §3 逐条的落点):
|
|
50
|
+
* - **只对 `suspended` 生效**:不存在 ⇒ 404;其余状态(含已终态)⇒ 409
|
|
51
|
+
* (「不唤醒已终态」是这条状态闸的推论,与 approve 同款「状态不对要说出来」);
|
|
52
|
+
* - **幂等**:`eventId` 给定时按 `rec.deliveredEventIds` 去重,重复 ⇒ 409
|
|
53
|
+
* (簿记随记录落库,重启不丢;有界 FIFO,见 MAX_DELIVERED_EVENT_IDS)。
|
|
54
|
+
* 不给 `eventId` 就**没有恰好一次**:重复投递 = 重复进历史(如实,不假装);
|
|
55
|
+
* - **投完即续跑**(两种挂起原因都算 —— 对 timer 挂起这就是「提前醒」):
|
|
56
|
+
* 事件进 `rec.pendingEvents`、状态回 `running`,**先落库再派发**
|
|
57
|
+
* (与 approve / 到期唤醒同一条纪律:崩在窗口里不能丢事件)。
|
|
58
|
+
* 事件**不**直接追加进 `rec.spec.messages` —— 续跑判定只认历史末尾一条
|
|
59
|
+
* (`tailToolUses`),追加 user 消息会把续跑判成新对话;注入由引擎在
|
|
60
|
+
* 未决 tool_use 解决之后做(见 engine/loop.ts 的 deliverTaskEvents);
|
|
61
|
+
* - **不沿旧 wakeAt**:记录上的旧目标时刻不动(闸都 gate 在 suspended 上,
|
|
62
|
+
* 状态一翻它就失效);醒来重跑那一批时工具若再次 `deferUntil`,
|
|
63
|
+
* `wakeAt` 由新回合重新落定;
|
|
64
|
+
* - drain 期间**仍允许**(与 approve 同理由:挂起的任务只有外部输入能推进)。
|
|
65
|
+
*
|
|
66
|
+
* 并发闸与 approve **不同款**:approve 共享在飞那次(决定是幂等合并),事件**串行成链**
|
|
67
|
+
* (两条并发事件是两条不同的输入,共享 = 静默丢一条)。与其它恢复路径
|
|
68
|
+
* (approve / 到期唤醒,各有自己的闸)的竞速:进闸后重读再判挡住绝大多数;
|
|
69
|
+
* 剩下的窄窗口与既有「approve × wakeDue 分闸」同类(那两条按挂起原因天然互斥,
|
|
70
|
+
* 事件两种原因都适用,是这个闸新盖的缝 —— 已记在 spec §10 2026-09-28 ⑥)。
|
|
71
|
+
*/
|
|
72
|
+
signalTask(taskId, event) {
|
|
73
|
+
// 串行化(**不是** approve 那种「共享在飞那次」):两个并发事件是**两条不同的输入**,
|
|
74
|
+
// 共享在飞那次 = 后一条被静默丢掉;各自读-改-写而不互斥 = 双派发(与 resumePending
|
|
75
|
+
// 的重入闸同一个 bug 类)。排成链:前一次落库完,这一次进闸后重读再判
|
|
76
|
+
// (那时若已派发则状态是 running ⇒ 409 如实说出来,调用方可重试)。
|
|
77
|
+
const prev = this.#inflight.get(taskId);
|
|
78
|
+
const run = Promise.resolve(prev)
|
|
79
|
+
.catch(() => undefined) // 前一次的 reject 已由它自己的调用方接走,这里只排队
|
|
80
|
+
.then(() => this.#signalInner(taskId, event))
|
|
81
|
+
.finally(() => {
|
|
82
|
+
// 只摘自己:链上可能已有更新的节点(无条件 delete 会摘掉别人的)
|
|
83
|
+
if (this.#inflight.get(taskId) === run)
|
|
84
|
+
this.#inflight.delete(taskId);
|
|
85
|
+
});
|
|
86
|
+
this.#inflight.set(taskId, run);
|
|
87
|
+
return run;
|
|
88
|
+
}
|
|
89
|
+
async #signalInner(taskId, event) {
|
|
90
|
+
const rec = await this.#deps.store.get(taskId);
|
|
91
|
+
if (!rec)
|
|
92
|
+
throw new TaskEventError(404, `task 不存在: ${taskId}`);
|
|
93
|
+
if (rec.status !== 'suspended') {
|
|
94
|
+
throw new TaskEventError(409, `task ${taskId} 当前状态为 ${rec.status},只有挂起的任务能接收事件`);
|
|
95
|
+
}
|
|
96
|
+
// 幂等去重(先判再改):重复 ⇒ 409,记录一个字节不动(与 cancel 的「已终态」同款)
|
|
97
|
+
if (event.eventId !== undefined && rec.deliveredEventIds?.includes(event.eventId)) {
|
|
98
|
+
throw new TaskEventError(409, `事件 ${event.eventId} 已投递给 task ${taskId}(重复投递)`);
|
|
99
|
+
}
|
|
100
|
+
// 缓冲上限(2026-09-28 复审第三轮,定案 B:满了**说出来**,不静默丢)。
|
|
101
|
+
// 判据次序 状态 ⇒ 幂等 ⇒ 容量:重复投递的那条本来就在缓冲里,报「重复投递」比报「满了」有用;
|
|
102
|
+
// 两种 409 的**区别必须让调用方看得见** —— 重复投递是「已经在里面了」,满了是「没收下」。
|
|
103
|
+
if ((rec.pendingEvents?.length ?? 0) >= MAX_PENDING_EVENTS) {
|
|
104
|
+
throw new TaskEventError(409, `task ${taskId} 的待注入事件已达上限(${MAX_PENDING_EVENTS} 条)—— ${rec.suspendedReason === 'approval'
|
|
105
|
+
? '这条在等人工审批,而让它跑起来的唯一触发源是 approve(不在投递方手里)⇒ 要么等人批,要么 cancel 后重新提交'
|
|
106
|
+
: '这条在等定时到点(approve 对它不适用)—— 到点它会自己醒来,缓冲里的事件在醒来那段注入;等不了就 cancel 后重新提交'};本次事件**没有**被记录。`);
|
|
107
|
+
}
|
|
108
|
+
rec.pendingEvents = [...(rec.pendingEvents ?? []), event];
|
|
109
|
+
if (event.eventId !== undefined) {
|
|
110
|
+
const ids = [...(rec.deliveredEventIds ?? []), event.eventId];
|
|
111
|
+
rec.deliveredEventIds =
|
|
112
|
+
ids.length > MAX_DELIVERED_EVENT_IDS
|
|
113
|
+
? ids.slice(ids.length - MAX_DELIVERED_EVENT_IDS)
|
|
114
|
+
: ids;
|
|
115
|
+
}
|
|
116
|
+
rec.status = 'running'; // 由 #executeInner 接管(acquireSlot → 恢复执行)
|
|
117
|
+
rec.ownerId = this.#deps.ownerId;
|
|
118
|
+
// 先落库再派发 —— 与 approve 同一条真纪律:save 失败就绝不恢复执行
|
|
119
|
+
// (落不了库的事件不算投递:崩在窗口里会丢事件)。调用方拿到 reject,重试即可。
|
|
120
|
+
await this.#deps.store.save(rec);
|
|
121
|
+
// 离开挂起态(读数纪律②):事件到了这就是「醒来」那一刻 —— 与 approve 的决定齐了同形
|
|
122
|
+
this.#deps.approvals.unmarkSuspended(taskId);
|
|
123
|
+
// 派发走唯一入口(闸在 #dispatch 里):停机窗口里不派发,事件留在 pendingEvents 上,
|
|
124
|
+
// 下次启动的 resumePending 认领时注入。
|
|
125
|
+
this.#deps.dispatch(rec);
|
|
126
|
+
return { ...rec };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=signal-supervisor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signal-supervisor.js","sourceRoot":"","sources":["../../src/transport/signal-supervisor.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,6 +19,14 @@ export declare class SlotPool {
|
|
|
19
19
|
acquire(): Promise<void>;
|
|
20
20
|
/** 还槽位:有等待者则移交(计数不变),否则归还 */
|
|
21
21
|
release(): void;
|
|
22
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* 当前占用数。
|
|
24
|
+
*
|
|
25
|
+
* ⚠️ 2026-09-28 起它**不再是「测试用」**:`AsyncRunner` 的排队段闸(`maxQueued`)
|
|
26
|
+
* 用它算「此刻还有几个空槽位」—— 判据是「**真正在排队的深度** = 已受理未持槽的任务数
|
|
27
|
+
* − 当前空槽位数」(见 async.ts 的 `#queueDepth`)。先前那句「测试用;对外暴露的是
|
|
28
|
+
* active」是一句**会误导人**的自述:它让读代码的人以为改这个读数不影响行为。
|
|
29
|
+
* 读到它想改语义时,请连着 `#queueDepth` 一起看 —— 那里写着为什么不能只看等待队列长度。
|
|
30
|
+
*/
|
|
23
31
|
get inUse(): number;
|
|
24
32
|
}
|
|
@@ -35,7 +35,15 @@ export class SlotPool {
|
|
|
35
35
|
this.running--;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* 当前占用数。
|
|
40
|
+
*
|
|
41
|
+
* ⚠️ 2026-09-28 起它**不再是「测试用」**:`AsyncRunner` 的排队段闸(`maxQueued`)
|
|
42
|
+
* 用它算「此刻还有几个空槽位」—— 判据是「**真正在排队的深度** = 已受理未持槽的任务数
|
|
43
|
+
* − 当前空槽位数」(见 async.ts 的 `#queueDepth`)。先前那句「测试用;对外暴露的是
|
|
44
|
+
* active」是一句**会误导人**的自述:它让读代码的人以为改这个读数不影响行为。
|
|
45
|
+
* 读到它想改语义时,请连着 `#queueDepth` 一起看 —— 那里写着为什么不能只看等待队列长度。
|
|
46
|
+
*/
|
|
39
47
|
get inUse() {
|
|
40
48
|
return this.running;
|
|
41
49
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slot-pool.js","sourceRoot":"","sources":["../../src/transport/slot-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,QAAQ;IAIU,KAAK;IAH1B,OAAO,GAAG,CAAC,CAAC;IACH,SAAS,GAAsB,EAAE,CAAC;IAEnD,YAA6B,KAAa;qBAAb,KAAK;IAAW,CAAC;IAE9C,wBAAwB;IACxB,OAAO;QACL,IAAI,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC3B,CAAC;QACD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAChE,CAAC;IAED,6BAA6B;IAC7B,OAAO;QACL,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACpC,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,EAAE,CAAC;QACT,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC;IACH,CAAC;IAED
|
|
1
|
+
{"version":3,"file":"slot-pool.js","sourceRoot":"","sources":["../../src/transport/slot-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,QAAQ;IAIU,KAAK;IAH1B,OAAO,GAAG,CAAC,CAAC;IACH,SAAS,GAAsB,EAAE,CAAC;IAEnD,YAA6B,KAAa;qBAAb,KAAK;IAAW,CAAC;IAE9C,wBAAwB;IACxB,OAAO;QACL,IAAI,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC3B,CAAC;QACD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAChE,CAAC;IAED,6BAA6B;IAC7B,OAAO;QACL,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACpC,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,EAAE,CAAC;QACT,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACH,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF"}
|
|
@@ -17,9 +17,19 @@ import type { TraceRecordEvent } from '../core/trace.js';
|
|
|
17
17
|
* 告诉订阅者(`replay()` 的返回值 / `stream.truncated` 帧)—— **不静默**。
|
|
18
18
|
* 3. **终态缓冲区只保留最近 `retainTerminal` 条。** 留下的意义是「刚跑完就连上来也能重放」;
|
|
19
19
|
* 更早的任务连接上来只能拿到终态(不假装还能重放)。留多了等于把内存换成没人看的历史。
|
|
20
|
+
* 4. **非终态流的缓冲也回收(配额 `nonTerminalBuffers`)。** 终态那条闸只管**跑完的**任务,
|
|
21
|
+
* 而「挂着不动的任务」才是真常态:等审批的、等事件的、等定时器的每条都占一份 ≤`maxEvents` 条
|
|
22
|
+
* 的缓冲(约 1 MB),**且永远不会走到终态** ⇒ 表项只增不减(2026-09-28 外部深评 T4)。
|
|
23
|
+
* 回收的是**缓冲**,不是**表项**:表项留着当**桩**(`has()` 仍为真、`nextIndex` 接着走),
|
|
24
|
+
* 只把回放历史丢掉并用 `firstAvailable` 明示缺口 —— 详见 `#recycleNonTerminal()` 的三条纪律。
|
|
25
|
+
* ⚠️ 反过来做(连表项一起删)会**静默破坏约束 1**:恢复段的 `open()` 会给一个不存在的任务
|
|
26
|
+
* 新建 `nextIndex = 1` 的流,于是拿 `Last-Event-ID` 续订的读者的 `replay(from=N)` 永远筛不出
|
|
27
|
+
* 东西(`index > N` 恒假)—— 读者从此只等到收口帧,中间一片空白。
|
|
20
28
|
*
|
|
21
29
|
* ⚠️ 内存量级(文档里要给使用者一个数):单条事件正文受 `maxEventChars` 约束(入参/成功出参
|
|
22
|
-
* 缺省 2000 字符),所以 500 条 × 2 KB ≈ 1 MB
|
|
30
|
+
* 缺省 2000 字符),所以 500 条 × 2 KB ≈ 1 MB/任务。**缓冲**总量 ≈
|
|
31
|
+
* (`nonTerminalBuffers` 32 + `retainTerminal` 16)× 1 MB ≈ 48 MB 上限(有订阅者的流不受配额约束,
|
|
32
|
+
* 见约束 4);此外每条非终态任务留一个**桩**(约百字节),桩本身不设上限,理由同约束 4。
|
|
23
33
|
*/
|
|
24
34
|
export interface TaskEventStreamsOptions {
|
|
25
35
|
/**
|
|
@@ -33,6 +43,18 @@ export interface TaskEventStreamsOptions {
|
|
|
33
43
|
maxEvents?: number;
|
|
34
44
|
/** 终态流的保留条数(LRU,超出即丢最旧的终态流);缺省 16 */
|
|
35
45
|
retainTerminal?: number;
|
|
46
|
+
/**
|
|
47
|
+
* **非终态**流的**缓冲**配额(条数,不是事件数):本进程最多为多少条非终态流保留
|
|
48
|
+
* 「可回放的事件缓冲」;缺省 32。超出即从**最旧**的、**无订阅者**的非终态流开始回收缓冲
|
|
49
|
+
* (表项与序号都留着,见类注释约束 4)。`0` 读作 disabled = **没人读的**非终态流一律不留
|
|
50
|
+
* 回放缓冲(只有实时转发;有订阅者的流照旧留着 —— 见 `#recycleNonTerminal` 的纪律)。
|
|
51
|
+
*
|
|
52
|
+
* 为什么是**条数**而不是字节数:真正的量纲是「任务数 × 每任务 ≤`maxEvents` 条」,
|
|
53
|
+
* 每任务那半已经被 `maxEvents` 钉住了,剩下的变量就是**多少条流**在占缓冲 —— 按字节设限
|
|
54
|
+
* 还要去估正文长度(`maxEventChars` 只是缺省、用户可改),反而不准。
|
|
55
|
+
* 0 语义归类见 `core/limits.ts` 的 `TaskEventStreams.nonTerminalBuffers` 行。
|
|
56
|
+
*/
|
|
57
|
+
nonTerminalBuffers?: number;
|
|
36
58
|
}
|
|
37
59
|
/** 一条事件在**流**里的位置(`index` 是流自己的序号,不是 recorder 的 seq) */
|
|
38
60
|
export interface TaskStreamEvent {
|
|
@@ -50,11 +72,22 @@ export interface TaskReplay {
|
|
|
50
72
|
/** 缺省上限 —— 与文档里写的数字必须一致(`usage-guide` §7) */
|
|
51
73
|
export declare const TASK_STREAM_DEFAULT_MAX_EVENTS = 500;
|
|
52
74
|
export declare const TASK_STREAM_DEFAULT_RETAIN_TERMINAL = 16;
|
|
75
|
+
export declare const TASK_STREAM_DEFAULT_NON_TERMINAL_BUFFERS = 32;
|
|
53
76
|
export declare class TaskEventStreams {
|
|
54
77
|
#private;
|
|
55
78
|
private readonly streams;
|
|
56
79
|
private readonly maxEvents;
|
|
57
80
|
private readonly retainTerminal;
|
|
81
|
+
private readonly nonTerminalBuffers;
|
|
82
|
+
/**
|
|
83
|
+
* 「非终态**且**缓冲非空」的流数 —— 配额判据的**增量**计数。
|
|
84
|
+
*
|
|
85
|
+
* 为什么不每次现数:判定点在 `push` 上(每条事件都可能让一条流从空变非空),
|
|
86
|
+
* 每次全表扫一遍会把这道内存闸本身变成 O(流数 × 事件数) 的开销。
|
|
87
|
+
* 增量的代价是必须有**唯二**的增减点(`#recycleNonTerminal` 减、`push`/`open` 增),
|
|
88
|
+
* 所以三处各有一句注释钉着 —— 谁新开一条改缓冲的路径,得同时改这里。
|
|
89
|
+
*/
|
|
90
|
+
private buffered;
|
|
58
91
|
constructor(opts?: TaskEventStreamsOptions);
|
|
59
92
|
/** 这条流在场吗(在场 = 本进程见过它的记账) */
|
|
60
93
|
has(taskId: string): boolean;
|
|
@@ -85,6 +118,4 @@ export declare class TaskEventStreams {
|
|
|
85
118
|
replay(taskId: string, from?: number): TaskReplay;
|
|
86
119
|
/** 标记终态:此后不再有事件(`task.end` 由调用方发),并按 LRU 丢掉最旧的终态流 */
|
|
87
120
|
markDone(taskId: string): void;
|
|
88
|
-
/** 丢弃某条流(终态 LRU 用) */
|
|
89
|
-
forget(taskId: string): void;
|
|
90
121
|
}
|
|
@@ -2,10 +2,21 @@ import { zeroClauseOf } from '../core/limits.js';
|
|
|
2
2
|
/** 缺省上限 —— 与文档里写的数字必须一致(`usage-guide` §7) */
|
|
3
3
|
export const TASK_STREAM_DEFAULT_MAX_EVENTS = 500;
|
|
4
4
|
export const TASK_STREAM_DEFAULT_RETAIN_TERMINAL = 16;
|
|
5
|
+
export const TASK_STREAM_DEFAULT_NON_TERMINAL_BUFFERS = 32;
|
|
5
6
|
export class TaskEventStreams {
|
|
6
7
|
streams = new Map();
|
|
7
8
|
maxEvents;
|
|
8
9
|
retainTerminal;
|
|
10
|
+
nonTerminalBuffers;
|
|
11
|
+
/**
|
|
12
|
+
* 「非终态**且**缓冲非空」的流数 —— 配额判据的**增量**计数。
|
|
13
|
+
*
|
|
14
|
+
* 为什么不每次现数:判定点在 `push` 上(每条事件都可能让一条流从空变非空),
|
|
15
|
+
* 每次全表扫一遍会把这道内存闸本身变成 O(流数 × 事件数) 的开销。
|
|
16
|
+
* 增量的代价是必须有**唯二**的增减点(`#recycleNonTerminal` 减、`push`/`open` 增),
|
|
17
|
+
* 所以三处各有一句注释钉着 —— 谁新开一条改缓冲的路径,得同时改这里。
|
|
18
|
+
*/
|
|
19
|
+
buffered = 0;
|
|
9
20
|
constructor(opts = {}) {
|
|
10
21
|
// 坏值响亮失败(口径与 resolveTraceLimits / resolveMaxRetries 同款):
|
|
11
22
|
// 判定是 `length > maxEvents` ⇒ NaN 恒假(上限根本不生效)、Infinity 永不触发、
|
|
@@ -26,6 +37,17 @@ export class TaskEventStreams {
|
|
|
26
37
|
'NaN 会让「超出保留条数」的判定恒假(终态流被静默清空),负数 / 小数没有「留几条」的读法');
|
|
27
38
|
}
|
|
28
39
|
this.retainTerminal = retainTerminal;
|
|
40
|
+
// nonTerminalBuffers 同款校验:判定是 `buffered <= quota 提前返回` ⇒ NaN 恒假
|
|
41
|
+
// ⇒ **每条**非终态流的缓冲都被立刻回收(回放历史静默全没,与 retainTerminal 的
|
|
42
|
+
// 「保留机制失效」同族、方向相反)。0 有读法:非终态流不留回放缓冲(只做实时转发)。
|
|
43
|
+
const nonTerminalBuffers = opts.nonTerminalBuffers ?? TASK_STREAM_DEFAULT_NON_TERMINAL_BUFFERS;
|
|
44
|
+
if (typeof nonTerminalBuffers !== 'number' ||
|
|
45
|
+
!Number.isSafeInteger(nonTerminalBuffers) ||
|
|
46
|
+
nonTerminalBuffers < 0) {
|
|
47
|
+
throw new TypeError(`nonTerminalBuffers 必须是非负安全整数(${zeroClauseOf('TaskEventStreams.nonTerminalBuffers')}),收到 ${String(opts.nonTerminalBuffers)} —— ` +
|
|
48
|
+
'NaN 会让「超出配额」的判定恒假(没人读的非终态流的回放缓冲被静默回收),负数 / 小数没有「留几条」的读法');
|
|
49
|
+
}
|
|
50
|
+
this.nonTerminalBuffers = nonTerminalBuffers;
|
|
29
51
|
}
|
|
30
52
|
/** 这条流在场吗(在场 = 本进程见过它的记账) */
|
|
31
53
|
has(taskId) {
|
|
@@ -45,8 +67,14 @@ export class TaskEventStreams {
|
|
|
45
67
|
});
|
|
46
68
|
return;
|
|
47
69
|
}
|
|
48
|
-
// 复用:只把「已完成」摘掉 ——
|
|
70
|
+
// 复用:只把「已完成」摘掉 —— 恢复段是同一个任务的续篇,缓冲与序号都接着用。
|
|
71
|
+
// 从终态回到非终态且缓冲非空 ⇒ 它重新计入配额(计数 +1,见 `buffered` 的注释)并当场对账。
|
|
72
|
+
const backInQuota = existing.done && existing.events.length > 0;
|
|
49
73
|
existing.done = false;
|
|
74
|
+
if (backInQuota) {
|
|
75
|
+
this.buffered += 1;
|
|
76
|
+
this.#recycleNonTerminal();
|
|
77
|
+
}
|
|
50
78
|
}
|
|
51
79
|
/**
|
|
52
80
|
* 记一条事件:入缓冲 + 广播给订阅者。
|
|
@@ -60,12 +88,23 @@ export class TaskEventStreams {
|
|
|
60
88
|
const s = this.streams.get(taskId);
|
|
61
89
|
if (!s || s.done)
|
|
62
90
|
return;
|
|
91
|
+
// 从「空」变「非空」⇒ 这条流开始占配额(计数 +1,见 `buffered` 的注释)。
|
|
92
|
+
// 判据取在 push 之前:push 之后一定非空(`maxEvents ≥ 1` 由构造期保证)。
|
|
93
|
+
const wasEmpty = s.events.length === 0;
|
|
63
94
|
const item = { index: s.nextIndex++, event };
|
|
64
95
|
s.events.push(item);
|
|
65
96
|
if (s.events.length > this.maxEvents) {
|
|
66
97
|
const dropped = s.events.shift();
|
|
67
98
|
s.firstAvailable = dropped.index + 1;
|
|
68
99
|
}
|
|
100
|
+
if (wasEmpty) {
|
|
101
|
+
this.buffered += 1;
|
|
102
|
+
// 超配额就从 Map 中最旧的非空、**无订阅者**候选开始回收(遍历的是 `open()` 的插入序,
|
|
103
|
+
// 不是 push 序)。⚠️ 若更早 open 的流都空着、或已被回收成桩,**被回收的可能就是刚 push 的
|
|
104
|
+
// 这条**(缺口由 `droppedBefore` 明示,见 `#recycleNonTerminal`)—— 那句「不会回收刚 push 的
|
|
105
|
+
// 这条」是**假的**(2026-09-29 外部深评 B1 实证:这条流非空正是它被选中的理由,不是豁免)。
|
|
106
|
+
this.#recycleNonTerminal();
|
|
107
|
+
}
|
|
69
108
|
// 广播:先拷订阅者集合(回调里可能退订),单个抛错不影响其它订阅者
|
|
70
109
|
for (const l of [...s.subscribers]) {
|
|
71
110
|
try {
|
|
@@ -120,6 +159,11 @@ export class TaskEventStreams {
|
|
|
120
159
|
const s = this.streams.get(taskId);
|
|
121
160
|
if (!s)
|
|
122
161
|
return;
|
|
162
|
+
// 终态不再计入「非终态缓冲」配额(计数 -1,见 `buffered` 的注释)。
|
|
163
|
+
// 幂等:重复 markDone 不重复减(计数少减一次会让配额**多**留几条,方向是漏不是错,
|
|
164
|
+
// 但那也是漂 —— 判据取在赋值之前)。
|
|
165
|
+
if (!s.done && s.events.length > 0)
|
|
166
|
+
this.buffered -= 1;
|
|
123
167
|
s.done = true;
|
|
124
168
|
// 先广播终态再考虑淘汰:订阅者要能收口(单个抛错不影响其它订阅者)
|
|
125
169
|
for (const l of [...s.doneListeners]) {
|
|
@@ -132,11 +176,55 @@ export class TaskEventStreams {
|
|
|
132
176
|
}
|
|
133
177
|
this.#evictTerminal();
|
|
134
178
|
}
|
|
135
|
-
/**
|
|
136
|
-
|
|
137
|
-
|
|
179
|
+
/**
|
|
180
|
+
* **非终态**流的**缓冲**回收(配额 = `nonTerminalBuffers`)。2026-09-28 外部深评 T4 的收口。
|
|
181
|
+
*
|
|
182
|
+
* 回收的是**缓冲**,不是**表项**:`has()` 仍为真(任务确实在本进程),`nextIndex` 不动
|
|
183
|
+
* (序号接着走),只把回放历史丢掉并用 `firstAvailable = nextIndex` 明示缺口 ——
|
|
184
|
+
* 于是 `replay()` 回空 + `droppedBefore`,HTTP 层据此**先**发一帧 `stream.truncated`
|
|
185
|
+
* 再转实时。连表项一起删是**错的**,理由写在类注释约束 4(恢复段的序号会从 1 重来,
|
|
186
|
+
* 拿 `Last-Event-ID` 续订的读者从此静默收不到东西)。
|
|
187
|
+
*
|
|
188
|
+
* 三条纪律(每条都有代价,别按直觉改):
|
|
189
|
+
*
|
|
190
|
+
* - **有订阅者的不回收**:那是一条正在被读的流,回收等于从读者手里抽走数据。
|
|
191
|
+
* 代价如实:**被实时读的流不受配额约束** ⇒ 同时被读的流很多时,缓冲总量仍会超配额 ——
|
|
192
|
+
* 这是「不抽走正在读的东西」的代价,不是漏洞(与 `#evictTerminal` 同款取舍)。
|
|
193
|
+
* ⚠️ 另一条代价(2026-09-29 外部深评 B1):**退订不触发回收**(回收只在「某条流从空变非空」
|
|
194
|
+
* 这个判定点跑)⇒ 一条「曾被实时读过、之后退订」的非空流会**一直占着配额**,直到下一次判定点。
|
|
195
|
+
* 所以配额的真实上界是 `nonTerminalBuffers + 曾有订阅者的流数`(仍有界,但别把它当
|
|
196
|
+
* 「缓冲总量 ≤ nonTerminalBuffers」来承诺)。
|
|
197
|
+
* - **终态的不归这里管**:它走 `#evictTerminal()` 的 LRU(那条丢的是**表项**)。
|
|
198
|
+
* - **只在缓冲增长时判**(`push` 让某条流从空变非空 / `open()` 把终态流拉回非终态):
|
|
199
|
+
* 每次 push 都全表扫会把这道内存闸本身变成开销(见 `buffered` 的注释)。
|
|
200
|
+
* 代价如实:判定点之间会**短暂**多出几条 —— 但每条增长都会当场触发一次回收,所以超额是
|
|
201
|
+
* 「本轮一个事件」的量级,不是无界累积。
|
|
202
|
+
*/
|
|
203
|
+
#recycleNonTerminal() {
|
|
204
|
+
if (this.buffered <= this.nonTerminalBuffers)
|
|
205
|
+
return;
|
|
206
|
+
// Map 的插入序即「最旧优先」:挂得最久的任务(等审批 / 等事件 / 等定时器)先被回收 ——
|
|
207
|
+
// 它们正是这条闸要治的那一类(永远不会走到终态,缓冲只增不减)。
|
|
208
|
+
for (const s of this.streams.values()) {
|
|
209
|
+
if (this.buffered <= this.nonTerminalBuffers)
|
|
210
|
+
return;
|
|
211
|
+
if (s.done || s.events.length === 0 || s.subscribers.size > 0)
|
|
212
|
+
continue;
|
|
213
|
+
s.events = [];
|
|
214
|
+
s.firstAvailable = s.nextIndex; // 缺口从「下一条」开始 ⇒ 已缓冲的全不在
|
|
215
|
+
this.buffered -= 1;
|
|
216
|
+
}
|
|
138
217
|
}
|
|
139
|
-
/**
|
|
218
|
+
/**
|
|
219
|
+
* 终态流超过保留条数 ⇒ 从最旧的开始丢(Map 的插入序即 LRU 序;恢复段 `open()` 会把它当新流)。
|
|
220
|
+
*
|
|
221
|
+
* ⚠️ 这里**曾经**还有一个公开方法 `forget(taskId)`(「丢弃某条流」)。2026-09-28 外部深评
|
|
222
|
+
* 复核时确认它**全仓零调用点**(`grep` 命中的 `forget()` 全是 `scheduler.ts` 里那个操作
|
|
223
|
+
* `inFlight` 的同名**局部函数**,与此无关)—— 删掉,不留死承诺。
|
|
224
|
+
* 淘汰这件事**唯一的真实机制就是本方法**:终态流按 LRU 丢、有订阅者的不丢。
|
|
225
|
+
* 将来若真要「外部显式丢弃某条流」,请连同**谁在什么场景会调**一起设计再加回来
|
|
226
|
+
* (报告当初的建议「给 forget 写个测试」是反的:那等于给死代码上锁)。
|
|
227
|
+
*/
|
|
140
228
|
#evictTerminal() {
|
|
141
229
|
const doneIds = [];
|
|
142
230
|
for (const [taskId, s] of this.streams) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-events.js","sourceRoot":"","sources":["../../src/transport/task-events.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"task-events.js","sourceRoot":"","sources":["../../src/transport/task-events.ts"],"names":[],"mappings":"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"}
|