@migor/agentia 0.9.4 → 0.9.5
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 +688 -4
- package/README.md +1 -1
- package/dist/AGENTS.md +313 -33
- package/dist/container/container.js +15 -0
- package/dist/container/container.js.map +1 -1
- package/dist/core/limits.d.ts +93 -13
- 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/defer.d.ts +49 -0
- package/dist/engine/defer.js +72 -0
- package/dist/engine/defer.js.map +1 -0
- 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 +112 -15
- 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 +3 -1
- package/dist/store/redisStore.js +21 -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/async.d.ts +197 -18
- package/dist/transport/async.js +871 -85
- 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/scheduler.js +9 -23
- package/dist/transport/scheduler.js.map +1 -1
- 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 +86 -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 +6 -4
|
@@ -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,20 @@ 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
|
+
// 超配额就从最旧的别人开始回收 —— **不会**回收刚 push 的这条(它非空且是最后插入的)
|
|
103
|
+
this.#recycleNonTerminal();
|
|
104
|
+
}
|
|
69
105
|
// 广播:先拷订阅者集合(回调里可能退订),单个抛错不影响其它订阅者
|
|
70
106
|
for (const l of [...s.subscribers]) {
|
|
71
107
|
try {
|
|
@@ -120,6 +156,11 @@ export class TaskEventStreams {
|
|
|
120
156
|
const s = this.streams.get(taskId);
|
|
121
157
|
if (!s)
|
|
122
158
|
return;
|
|
159
|
+
// 终态不再计入「非终态缓冲」配额(计数 -1,见 `buffered` 的注释)。
|
|
160
|
+
// 幂等:重复 markDone 不重复减(计数少减一次会让配额**多**留几条,方向是漏不是错,
|
|
161
|
+
// 但那也是漂 —— 判据取在赋值之前)。
|
|
162
|
+
if (!s.done && s.events.length > 0)
|
|
163
|
+
this.buffered -= 1;
|
|
123
164
|
s.done = true;
|
|
124
165
|
// 先广播终态再考虑淘汰:订阅者要能收口(单个抛错不影响其它订阅者)
|
|
125
166
|
for (const l of [...s.doneListeners]) {
|
|
@@ -132,11 +173,51 @@ export class TaskEventStreams {
|
|
|
132
173
|
}
|
|
133
174
|
this.#evictTerminal();
|
|
134
175
|
}
|
|
135
|
-
/**
|
|
136
|
-
|
|
137
|
-
|
|
176
|
+
/**
|
|
177
|
+
* **非终态**流的**缓冲**回收(配额 = `nonTerminalBuffers`)。2026-09-28 外部深评 T4 的收口。
|
|
178
|
+
*
|
|
179
|
+
* 回收的是**缓冲**,不是**表项**:`has()` 仍为真(任务确实在本进程),`nextIndex` 不动
|
|
180
|
+
* (序号接着走),只把回放历史丢掉并用 `firstAvailable = nextIndex` 明示缺口 ——
|
|
181
|
+
* 于是 `replay()` 回空 + `droppedBefore`,HTTP 层据此**先**发一帧 `stream.truncated`
|
|
182
|
+
* 再转实时。连表项一起删是**错的**,理由写在类注释约束 4(恢复段的序号会从 1 重来,
|
|
183
|
+
* 拿 `Last-Event-ID` 续订的读者从此静默收不到东西)。
|
|
184
|
+
*
|
|
185
|
+
* 三条纪律(每条都有代价,别按直觉改):
|
|
186
|
+
*
|
|
187
|
+
* - **有订阅者的不回收**:那是一条正在被读的流,回收等于从读者手里抽走数据。
|
|
188
|
+
* 代价如实:**被实时读的流不受配额约束** ⇒ 同时被读的流很多时,缓冲总量仍会超配额 ——
|
|
189
|
+
* 这是「不抽走正在读的东西」的代价,不是漏洞(与 `#evictTerminal` 同款取舍)。
|
|
190
|
+
* - **终态的不归这里管**:它走 `#evictTerminal()` 的 LRU(那条丢的是**表项**)。
|
|
191
|
+
* - **只在缓冲增长时判**(`push` 让某条流从空变非空 / `open()` 把终态流拉回非终态):
|
|
192
|
+
* 每次 push 都全表扫会把这道内存闸本身变成开销(见 `buffered` 的注释)。
|
|
193
|
+
* 代价如实:判定点之间会**短暂**多出几条 —— 但每条增长都会当场触发一次回收,所以超额是
|
|
194
|
+
* 「本轮一个事件」的量级,不是无界累积。
|
|
195
|
+
*/
|
|
196
|
+
#recycleNonTerminal() {
|
|
197
|
+
if (this.buffered <= this.nonTerminalBuffers)
|
|
198
|
+
return;
|
|
199
|
+
// Map 的插入序即「最旧优先」:挂得最久的任务(等审批 / 等事件 / 等定时器)先被回收 ——
|
|
200
|
+
// 它们正是这条闸要治的那一类(永远不会走到终态,缓冲只增不减)。
|
|
201
|
+
for (const s of this.streams.values()) {
|
|
202
|
+
if (this.buffered <= this.nonTerminalBuffers)
|
|
203
|
+
return;
|
|
204
|
+
if (s.done || s.events.length === 0 || s.subscribers.size > 0)
|
|
205
|
+
continue;
|
|
206
|
+
s.events = [];
|
|
207
|
+
s.firstAvailable = s.nextIndex; // 缺口从「下一条」开始 ⇒ 已缓冲的全不在
|
|
208
|
+
this.buffered -= 1;
|
|
209
|
+
}
|
|
138
210
|
}
|
|
139
|
-
/**
|
|
211
|
+
/**
|
|
212
|
+
* 终态流超过保留条数 ⇒ 从最旧的开始丢(Map 的插入序即 LRU 序;恢复段 `open()` 会把它当新流)。
|
|
213
|
+
*
|
|
214
|
+
* ⚠️ 这里**曾经**还有一个公开方法 `forget(taskId)`(「丢弃某条流」)。2026-09-28 外部深评
|
|
215
|
+
* 复核时确认它**全仓零调用点**(`grep` 命中的 `forget()` 全是 `scheduler.ts` 里那个操作
|
|
216
|
+
* `inFlight` 的同名**局部函数**,与此无关)—— 删掉,不留死承诺。
|
|
217
|
+
* 淘汰这件事**唯一的真实机制就是本方法**:终态流按 LRU 丢、有订阅者的不丢。
|
|
218
|
+
* 将来若真要「外部显式丢弃某条流」,请连同**谁在什么场景会调**一起设计再加回来
|
|
219
|
+
* (报告当初的建议「给 forget 写个测试」是反的:那等于给死代码上锁)。
|
|
220
|
+
*/
|
|
140
221
|
#evictTerminal() {
|
|
141
222
|
const doneIds = [];
|
|
142
223
|
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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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 到期唤醒的**纯判定** + 挂起读数 —— durable timer(2026-09-28 ① 的 timer 侧)。
|
|
3
|
+
*
|
|
4
|
+
* 从 AsyncRunner 里抽出来的第五个协作件(slot-pool → approval-policy → drain-gate →
|
|
5
|
+
* resume-policy → 这里),与 `approval-policy.ts` 是**明确的一对**:挂起的两个原因各有一套闸,
|
|
6
|
+
* 各自一个纯文件。为什么非要分开写:C 之前「挂起」是一个状态兼职两件事
|
|
7
|
+
* (`awaiting_approval` 既等人也等时刻),于是 `approvalTimeoutMs` 会去叫醒一条在等时刻的 run
|
|
8
|
+
* (而且 `#expireAndResume` 紧接着就重派 —— 补不出任何决定也照样开跑)。
|
|
9
|
+
* 两个原因的判据分开成两个具名函数之后,「谁管谁」在调用点一眼可见,也各有单测。
|
|
10
|
+
*
|
|
11
|
+
* 纯的边界:入参不变则结果不变;不碰 store、不改 rec、不派发、不起定时器。
|
|
12
|
+
*/
|
|
13
|
+
import type { SuspendedReason } from '../core/run.js';
|
|
14
|
+
import type { TaskRecord } from '../store/store.js';
|
|
15
|
+
/**
|
|
16
|
+
* 到点了吗(时间挂起)。
|
|
17
|
+
*
|
|
18
|
+
* - 两条判据缺一不可:状态是 `suspended` **且**原因是 `timer`(原因那一半是 C 定的口径 ——
|
|
19
|
+
* 没有它,等审批的挂起会被到期扫描按「`wakeAt` 缺失」判成不到点,看着像对,其实是
|
|
20
|
+
* **恰好**躲过;等时刻的挂起则会被审批那条闸叫醒);
|
|
21
|
+
* - `wakeAt` 缺失 ⇒ 永远不到点:**不**拿 `createdAt` / `startedAt` 之类退化(与
|
|
22
|
+
* `approvalExpired` 的取舍相反)—— 「不知道它什么时候醒」和「现在就该醒」是两件事,
|
|
23
|
+
* 猜错的方向是**提前开跑**,代价是真实副作用;
|
|
24
|
+
* - 边界是**不晚于现在**(`wakeAt <= now`):到点即可唤醒。与 `approvalExpired` 的严格大于
|
|
25
|
+
* 相反,两个闸的语义本来就不同 —— 超时是「等够了没」(恰好等于还没够),
|
|
26
|
+
* 到期是「到点了没」(恰好等于就到了)。
|
|
27
|
+
*/
|
|
28
|
+
export declare function timerDue(rec: TaskRecord, now: number): boolean;
|
|
29
|
+
/** 一条挂起记录的读数 —— AsyncRunner 只留「原因 + 目标时刻」,不持有整条记录 */
|
|
30
|
+
export interface SuspendedEntry {
|
|
31
|
+
reason: SuspendedReason;
|
|
32
|
+
wakeAt: number | undefined;
|
|
33
|
+
}
|
|
34
|
+
/** `/healthz` 的 `suspended` 段 */
|
|
35
|
+
export interface SuspendedSummary {
|
|
36
|
+
/** 等人工决定的条数 */
|
|
37
|
+
approval: number;
|
|
38
|
+
/** 等一个时刻的条数 */
|
|
39
|
+
timer: number;
|
|
40
|
+
/** 最早的目标时刻(epoch ms);一条时间挂起都没有 ⇒ **`null`**(不是 `0`) */
|
|
41
|
+
nextWakeAt: number | null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 把挂起的条目收成读数。口径写在调用方(`AsyncRunner.suspendedSummary`):只数**本进程**
|
|
45
|
+
* 看得见的记录 —— 与 `inFlight` 同一张表,不假装是全局面(跨进程合并看板是聚合方的事)。
|
|
46
|
+
*
|
|
47
|
+
* `nextWakeAt` 给 `null` 而不是 `0`:`0` 在 JSON 里是一个**合法时刻**(1970 年),
|
|
48
|
+
* 监控端拿它算 `nextWakeAt - now` 会得到一个巨大的负数,看着像「早就该醒却没人醒」。
|
|
49
|
+
*/
|
|
50
|
+
export declare function summarizeSuspended(entries: Iterable<SuspendedEntry>): SuspendedSummary;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 到点了吗(时间挂起)。
|
|
3
|
+
*
|
|
4
|
+
* - 两条判据缺一不可:状态是 `suspended` **且**原因是 `timer`(原因那一半是 C 定的口径 ——
|
|
5
|
+
* 没有它,等审批的挂起会被到期扫描按「`wakeAt` 缺失」判成不到点,看着像对,其实是
|
|
6
|
+
* **恰好**躲过;等时刻的挂起则会被审批那条闸叫醒);
|
|
7
|
+
* - `wakeAt` 缺失 ⇒ 永远不到点:**不**拿 `createdAt` / `startedAt` 之类退化(与
|
|
8
|
+
* `approvalExpired` 的取舍相反)—— 「不知道它什么时候醒」和「现在就该醒」是两件事,
|
|
9
|
+
* 猜错的方向是**提前开跑**,代价是真实副作用;
|
|
10
|
+
* - 边界是**不晚于现在**(`wakeAt <= now`):到点即可唤醒。与 `approvalExpired` 的严格大于
|
|
11
|
+
* 相反,两个闸的语义本来就不同 —— 超时是「等够了没」(恰好等于还没够),
|
|
12
|
+
* 到期是「到点了没」(恰好等于就到了)。
|
|
13
|
+
*/
|
|
14
|
+
export function timerDue(rec, now) {
|
|
15
|
+
return (rec.status === 'suspended' &&
|
|
16
|
+
rec.suspendedReason === 'timer' &&
|
|
17
|
+
rec.wakeAt !== undefined &&
|
|
18
|
+
rec.wakeAt <= now);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 把挂起的条目收成读数。口径写在调用方(`AsyncRunner.suspendedSummary`):只数**本进程**
|
|
22
|
+
* 看得见的记录 —— 与 `inFlight` 同一张表,不假装是全局面(跨进程合并看板是聚合方的事)。
|
|
23
|
+
*
|
|
24
|
+
* `nextWakeAt` 给 `null` 而不是 `0`:`0` 在 JSON 里是一个**合法时刻**(1970 年),
|
|
25
|
+
* 监控端拿它算 `nextWakeAt - now` 会得到一个巨大的负数,看着像「早就该醒却没人醒」。
|
|
26
|
+
*/
|
|
27
|
+
export function summarizeSuspended(entries) {
|
|
28
|
+
let approval = 0;
|
|
29
|
+
let timer = 0;
|
|
30
|
+
let nextWakeAt = null;
|
|
31
|
+
for (const e of entries) {
|
|
32
|
+
if (e.reason === 'approval') {
|
|
33
|
+
approval++;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
timer++;
|
|
37
|
+
if (e.wakeAt !== undefined && (nextWakeAt === null || e.wakeAt < nextWakeAt)) {
|
|
38
|
+
nextWakeAt = e.wakeAt;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return { approval, timer, nextWakeAt };
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=wake-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wake-policy.js","sourceRoot":"","sources":["../../src/transport/wake-policy.ts"],"names":[],"mappings":"AAeA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAe,EAAE,GAAW;IACnD,OAAO,CACL,GAAG,CAAC,MAAM,KAAK,WAAW;QAC1B,GAAG,CAAC,eAAe,KAAK,OAAO;QAC/B,GAAG,CAAC,MAAM,KAAK,SAAS;QACxB,GAAG,CAAC,MAAM,IAAI,GAAG,CAClB,CAAC;AACJ,CAAC;AAkBD;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAiC;IAClE,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,UAAU,GAAkB,IAAI,CAAC;IACrC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC5B,QAAQ,EAAE,CAAC;YACX,SAAS;QACX,CAAC;QACD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,UAAU,KAAK,IAAI,IAAI,CAAC,CAAC,MAAM,GAAG,UAAU,CAAC,EAAE,CAAC;YAC7E,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;QACxB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AACzC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@migor/agentia",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.5",
|
|
4
4
|
"description": "面向应用开发的声明式 agent 服务开发框架:装饰器 + DI 声明四类能力,主 agent 编排执行;每次 run 产出结构化结果与可观测调用树(trace、成本、指标),交付可直接上线的服务。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -53,17 +53,19 @@
|
|
|
53
53
|
"e2e:grpc": "npm run build && tsx scripts/e2e-grpc.ts",
|
|
54
54
|
"e2e:live": "tsx scripts/e2e-live.ts",
|
|
55
55
|
"e2e:mcp": "npm run build:cli && tsx scripts/e2e-mcp.ts",
|
|
56
|
+
"e2e:mcp:server": "tsx scripts/e2e-mcp-server.ts",
|
|
56
57
|
"e2e:soak": "tsx scripts/e2e-soak.ts",
|
|
57
58
|
"bench:trace": "tsx scripts/bench-trace-cost.ts",
|
|
58
|
-
"bench:assembly": "tsx scripts/bench-app-assembly.ts"
|
|
59
|
+
"bench:assembly": "tsx scripts/bench-app-assembly.ts",
|
|
60
|
+
"bench:otlp": "tsx scripts/bench-otlp-snapshot.ts"
|
|
59
61
|
},
|
|
60
62
|
"devDependencies": {
|
|
61
|
-
"@anthropic-ai/sdk": "^0.
|
|
63
|
+
"@anthropic-ai/sdk": "^0.128.0",
|
|
62
64
|
"@biomejs/biome": "^2.5.14",
|
|
63
65
|
"@grpc/grpc-js": "^1.14.5",
|
|
64
66
|
"@grpc/proto-loader": "^0.8.1",
|
|
65
67
|
"@types/node": "^26.5.1",
|
|
66
|
-
"c8": "^
|
|
68
|
+
"c8": "^12.0.0",
|
|
67
69
|
"tsx": "^4.19.0",
|
|
68
70
|
"typescript": "^7.0.2",
|
|
69
71
|
"zod": "^4.6.1"
|