@sema-agent/client-core 0.30.3 → 0.30.4
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 +32 -0
- package/README.md +1 -1
- package/dist/hitl/toolApprovalWire.d.ts +35 -1
- package/dist/hitl/toolApprovalWire.js +24 -0
- package/dist/subagent/engineSubagentTail.d.ts +20 -0
- package/dist/subagent/engineSubagentTail.js +38 -2
- package/docs/INTEGRATION-CLIENTS.md +9 -7
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -16,6 +16,38 @@
|
|
|
16
16
|
> 🔴 **互链**(web [C166]⑦):各版「已知局限」段只记**该版新增**;接入面已知局限的完整台账在
|
|
17
17
|
> `docs/INTEGRATION-CLIENTS.md` §6e/§7 —— **只读其一会漏**,两处都过。
|
|
18
18
|
|
|
19
|
+
## 0.30.4
|
|
20
|
+
|
|
21
|
+
- **#280 移交两件:probeCause 随卡透传 + tail meta 帧发布口(additive,零 BREAKING)**(2026-08-15;
|
|
22
|
+
红先绿后,常驻钉 = durable-card-display-keys ⑧ 段 10 checks + pure B7 probeCause 八钉 / B6
|
|
23
|
+
tail-meta 六钉(含 fail-soft 两钉:sink 同步抛错不撕裂 tail / async 拒绝有界观察零
|
|
24
|
+
unhandledRejection —— codex 复审 [high] 采纳);壳 #280 围栏 T6 现状锁候本批包透传落地
|
|
25
|
+
翻红接线):
|
|
26
|
+
- **件1 `ApprovalCardRequest.probeCause` 透传**(server ≥7.21.0-rc #253 的结构化探针因由,
|
|
27
|
+
`{code, roots:{shown,total}, further?}`):0.30.3 的两处「帧→卡入参」显式挑键把上游键丢弃 ——
|
|
28
|
+
活帧腿(`surfaceToolApprovalFrameAndRespond` 的卡入参)与 durable 行腿
|
|
29
|
+
(`surfaceFsApprovalAndDecide`,载体 = `PendingCheckpoint.riskDescriptor.probeCause`,server 对
|
|
30
|
+
riskDescriptor 整体透传与活帧同值)。本批两腿共用一把**载体形**判(`isProbeCauseCarrier`:
|
|
31
|
+
非 null 非数组对象)+ 原样搬运;🔴 内部结构(code/roots/further)**刻意不校** —— 结构校验归
|
|
32
|
+
呈卡端窄读器(壳 `probeCauseNote.readProbeCauseKey`),包只搬运,unknown 开集类型
|
|
33
|
+
(`ToolApprovalFrame.probeCause` / `ApprovalCardRequest.probeCause` 两位,agent-types 无现成形)。
|
|
34
|
+
帧键镜像 15→16 键;`probeCause` **领先** sdk 6.17.2 运行期锚一代 ⇒ 对账门 AHEAD_OF_ANCHOR
|
|
35
|
+
带退出条件登记(#144 persistedRuleShadowed 同形先例)。超集台账 `docs/type-superset.json`
|
|
36
|
+
补 `cc-counterpart-addition` 一条(CC 近邻 = `CanUseTool` options 的 `decisionReason`/
|
|
37
|
+
`blockedPath` 散文/标量位,差在结构化)。
|
|
38
|
+
- **件2 tail `event: meta` 帧发布口**(`engineSubagentTail.ts`):0.30.3 消费循环
|
|
39
|
+
`ev.event !== 'forward'` continue 把 meta 帧结构性 skip ⇒ `contentFrames` 供给形判别位
|
|
40
|
+
(server e439a6c,闭集 {on, progress_only, unknown} ——「内容永远不会来 vs 还没来」的唯一
|
|
41
|
+
诚实依据)到不了端。本批循环改帧分类闸(switch):meta 经新可装口
|
|
42
|
+
`installSubagentTailMetaSink`(载荷 `SubagentTailMeta = {taskId, meta}`,meta 为帧开集原文,
|
|
43
|
+
判别位窄读归消费端)发布后仍不进内容面;🔴 开闸范围**只放 meta**,heartbeat/未来非 forward
|
|
44
|
+
帧维持 skip。不装 sink = 0.30.3 现状字节不变。公面 +3 名
|
|
45
|
+
(`installSubagentTailMetaSink` 运行期导出 + `SubagentTailMeta`/`SubagentTailMetaSink` 类型),
|
|
46
|
+
baseline 706→707;singleton 台账补 `tailMetaSink`(high,ceiling 89→90 成文理由)。
|
|
47
|
+
- 已知局限(本版新增):meta 判别位的**消费臂在端上**(壳 #280 围栏 T6 翻红后接线);
|
|
48
|
+
`riskDescriptor.probeCause` 与 `shadowedRule` 同样不在 SDK `PendingCheckpoint.riskDescriptor`
|
|
49
|
+
声明里(类型半场候 SDK 班车,durable 腿为结构视图读)。
|
|
50
|
+
|
|
19
51
|
## 0.30.3
|
|
20
52
|
|
|
21
53
|
- **#244 F3 wire/会话判定上收 · 包半场(A-028.9/.10/.11/.12/.13/.15 族E;新三件
|
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ Renamed from **`@sema-agent/wire-cc-adapter`** (0.1.x, deprecated — see *Migra
|
|
|
35
35
|
|
|
36
36
|
## Scope
|
|
37
37
|
|
|
38
|
-
**Version:** 0.30.
|
|
38
|
+
**Version:** 0.30.4
|
|
39
39
|
|
|
40
40
|
- **Today** — the adapter seam, the whole `adapt()` pipeline (all 14 A-layer arms plus the
|
|
41
41
|
B/D/E tool-card layers), the notification/caps/model families, the adapter kernel (stream driver
|
|
@@ -238,6 +238,18 @@ export interface ApprovalCardRequest {
|
|
|
238
238
|
* 压根没有规则命中(缺席),而命中且清掉了的那些根本不会变成卡。
|
|
239
239
|
*/
|
|
240
240
|
persistedRuleShadowed?: string;
|
|
241
|
+
/**
|
|
242
|
+
* 结构化探针因由(#280 件1,0.30.4;server ≥7.21.0-rc #253)——**双源合流**
|
|
243
|
+
* ({@link governanceForced} 同形,两腿在场性可以不一致):
|
|
244
|
+
* · **活卡帧腿**:{@link ToolApprovalFrame.probeCause} 原样;
|
|
245
|
+
* · **durable park 行腿**:`PendingCheckpoint.riskDescriptor.probeCause`(server 对
|
|
246
|
+
* riskDescriptor 整体透传,与活帧同值 —— core `buildRiskDescriptor` 铸)。
|
|
247
|
+
* 🔴 **开集(unknown),包只搬运**:载体形判(非 null 非数组对象)之外零校验零改写 ——
|
|
248
|
+
* 内部结构(code/roots/further)的窄读、消毒与呈现全部归端(壳 `probeCauseNote` 窄读器:
|
|
249
|
+
* 形不合整只按缺席,呈现走 wireNote 车道)。缺席 = 无因由/老引擎/坏载体形(三者同形,不猜),
|
|
250
|
+
* 卡形字节不变。UNTRUSTED-for-display:code/roots 是工具作文面,只渲染绝不回喂模型/工具入参。
|
|
251
|
+
*/
|
|
252
|
+
probeCause?: unknown;
|
|
241
253
|
}
|
|
242
254
|
/**
|
|
243
255
|
* 🔴 **拆缝口** —— 弹「三选卡」并等人的决断。壳 = vendored CC `PermissionRequest`;
|
|
@@ -352,6 +364,28 @@ export interface ToolApprovalFrame {
|
|
|
352
364
|
* 耐久对偶仍未消费——那一路是独立的一件,不在本键的施工面内。
|
|
353
365
|
*/
|
|
354
366
|
persistedRuleShadowed?: string;
|
|
367
|
+
/**
|
|
368
|
+
* server ≥7.21.0-rc(#253 件 G1,core 5.33.0 backlog #239;**ADDITIVE**,`"tool_approval"` only。
|
|
369
|
+
* 真发直证 = engine 7.22.0 fixture `@sema-agent/server/dist/tool-approval.d.ts` 同名键)——
|
|
370
|
+
* 这只 ask **为什么**被收紧的**结构化探针因由**:被拦工具自声明 `reversibilityProbe` 且判不出
|
|
371
|
+
* 可回滚时,引擎在 maybe 档收紧点铸;wire 契约形 = `{ code, roots:{shown,total},
|
|
372
|
+
* further?:{shown,total} }`(server `ProbeCauseSchema` `.strict()`,活卡帧与 durable `card_json`
|
|
373
|
+
* 经同一 `readProbeCause` 单点铸造 ⇒ 两面结构性同值)。
|
|
374
|
+
*
|
|
375
|
+
* 🔴 **本包刻意不拥有这个形**(类型 = unknown 开集;#280 件1,0.30.4):内部结构(code/roots/
|
|
376
|
+
* further)的校验与呈现归呈卡端的窄读器(壳 `probeCauseNote.readProbeCauseKey` 同款「形不合整只
|
|
377
|
+
* 按缺席」纪律),包只做**载体形**判(非 null 非数组对象)+ 原样搬运 —— 两层各校一遍会让
|
|
378
|
+
* 「谁把键窄没的」在排障时说不清,且包侧校严一档就把上游 additive 内键挡在边界外。
|
|
379
|
+
* 🔴 **缺席 ≠「没有原因」**:只有 maybe 档收紧且探针真给了 cause 的 ask 才有它(工具 opt-in
|
|
380
|
+
* 供给,非常驻字段 —— [3980] test 定谳的负控:mandate 路径 ask 帧不带)。
|
|
381
|
+
* 🔴 本键**领先** SDK 运行期锚一代(sdk 6.17.2 的 `TOOL_APPROVAL_FRAME_KEYS` 尚无)⇒ 对账门
|
|
382
|
+
* (run-approval-frame-keys-test.mjs)AHEAD_OF_ANCHOR 带退出条件登记,#144
|
|
383
|
+
* `persistedRuleShadowed` 同形先例:SDK 锚补上当天登记自红逼删。
|
|
384
|
+
* 耐久路对偶 = `PendingCheckpoint.riskDescriptor.probeCause`(同值;server 对 riskDescriptor
|
|
385
|
+
* 整体透传),由 {@link surfaceFsApprovalAndDecide} 的行 → 卡重铸处消费。
|
|
386
|
+
* UNTRUSTED-for-display:code/roots 是工具作文面(server 已 redact),端呈前消毒,只渲染绝不回喂。
|
|
387
|
+
*/
|
|
388
|
+
probeCause?: unknown;
|
|
355
389
|
}
|
|
356
390
|
/** {@link ToolApprovalFrame.delegation} 的形(命名形,不用内联匿名 —— typeshape 门 B4 棘轮口径)。 */
|
|
357
391
|
export interface ToolApprovalDelegation {
|
|
@@ -367,7 +401,7 @@ export interface ToolApprovalDelegation {
|
|
|
367
401
|
* `TOOL_APPROVAL_FRAME_KEYS` 比对——SDK additive 增键时对账当天红,不再人肉追平。
|
|
368
402
|
* 下面两个类型钉保证镜像与 interface 本身不可能漂移(少键/多键都是编译错)。
|
|
369
403
|
*/
|
|
370
|
-
export declare const TOOL_APPROVAL_FRAME_KEYS_MIRROR: readonly ["type", "approvalId", "toolCallId", "toolName", "sourceTaskId", "fromSubagent", "sourceAgentName", "message", "args", "argsOmitted", "governanceForced", "ruleSuggestions", "persistedRuleShadowed", "delegation", "outcome"];
|
|
404
|
+
export declare const TOOL_APPROVAL_FRAME_KEYS_MIRROR: readonly ["type", "approvalId", "toolCallId", "toolName", "sourceTaskId", "fromSubagent", "sourceAgentName", "message", "args", "argsOmitted", "governanceForced", "ruleSuggestions", "persistedRuleShadowed", "probeCause", "delegation", "outcome"];
|
|
371
405
|
/** 子代帧判别:显式键 fromSubagent(core 1.378 RB-39②)优先;缺席退 sourceTaskId 在场性权宜式
|
|
372
406
|
* (server 1.258 [1549]①3,旧代际兼容)。 */
|
|
373
407
|
export declare function isFromSubagent(frame: ToolApprovalFrame): boolean;
|
|
@@ -255,6 +255,11 @@ export async function surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signa
|
|
|
255
255
|
// 合形窄化,落**只读键**(红线见 ApprovalCardRequest.ruleSuggestionsReadOnly 顶注:/decide
|
|
256
256
|
// 无规则位,落可兑付位=假 affordance)。
|
|
257
257
|
const ruleSuggestionsReadOnly = readRuleSuggestions(pending.ruleSuggestions);
|
|
258
|
+
// #280 件1(0.30.4):durable 行腿的探针因由载体 = `riskDescriptor.probeCause`(server 对
|
|
259
|
+
// riskDescriptor 整体透传,与活卡帧同值)。SDK 6.17.2 的 riskDescriptor 声明尚无此键 ⇒ 结构
|
|
260
|
+
// 视图读(与 caps 防御读同款姿势),类型半场候 SDK 班车;载体形不合 ⇒ 不铸键(内部结构不校,
|
|
261
|
+
// 归呈卡端窄读器 —— isProbeCauseCarrier 顶注)。
|
|
262
|
+
const durableProbeCause = pending.riskDescriptor?.probeCause;
|
|
258
263
|
const card = await surfaceApprovalCard({
|
|
259
264
|
toolName,
|
|
260
265
|
args,
|
|
@@ -262,6 +267,7 @@ export async function surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signa
|
|
|
262
267
|
...(signal ? { signal } : {}),
|
|
263
268
|
...(pending.governanceForced === true ? { governanceForced: true } : {}),
|
|
264
269
|
...(ruleSuggestionsReadOnly !== undefined ? { ruleSuggestionsReadOnly } : {}),
|
|
270
|
+
...(isProbeCauseCarrier(durableProbeCause) ? { probeCause: durableProbeCause } : {}),
|
|
265
271
|
});
|
|
266
272
|
switch (card.kind) {
|
|
267
273
|
case 'failed':
|
|
@@ -347,6 +353,11 @@ export const TOOL_APPROVAL_FRAME_KEYS_MIRROR = [
|
|
|
347
353
|
// (sdk 6.14.0/6.15.0 的 TOOL_APPROVAL_FRAME_KEYS 都还没有它)⇒ 对账门里有一条**带退出条件**的
|
|
348
354
|
// 领先登记(AHEAD_OF_ANCHOR):SDK 锚一旦补上,那条登记当场红,逼人删登记而不是让豁免长住。
|
|
349
355
|
'persistedRuleShadowed',
|
|
356
|
+
// #280 件1(client-core 0.30.4):server 7.21.0-rc(#253)起真发 `probeCause`(直证 = engine
|
|
357
|
+
// 7.22.0 fixture 的 `@sema-agent/server/dist/tool-approval.d.ts`)。⚠️ 本键**领先** SDK 运行期锚
|
|
358
|
+
// 一代(sdk 6.17.2 尚无)⇒ 对账门里有一条带退出条件的领先登记(AHEAD_OF_ANCHOR),SDK 锚一旦
|
|
359
|
+
// 补上,那条登记当场红,逼人删登记回到逐元素相等 —— #144 persistedRuleShadowed 同形先例。
|
|
360
|
+
'probeCause',
|
|
350
361
|
'delegation',
|
|
351
362
|
'outcome',
|
|
352
363
|
];
|
|
@@ -458,6 +469,16 @@ function pathFromGateMessage(message) {
|
|
|
458
469
|
* 渲一个按下去必被 server 拒的选项。上限 8 条(server 端候选本就 ≤2,超长=坏形,截不留痕会
|
|
459
470
|
* 掩盖注入,整体降缺席)。
|
|
460
471
|
*/
|
|
472
|
+
/**
|
|
473
|
+
* `probeCause` 的**载体形**判(#280 件1):非 null 非数组对象才搬运(wire 契约的载体就是对象,
|
|
474
|
+
* 串/数/数组/null 是坏载体不是「另一种因由」)。刻意只判到这一层 —— 内部结构(code/roots/further)
|
|
475
|
+
* 校验归呈卡端窄读器(server `readProbeCause` 的消费端对偶,壳 `probeCauseNote.readProbeCauseKey`),
|
|
476
|
+
* 包内校严一档就会把上游 additive 内键挡在边界外,还让「谁把键窄没的」在排障时多一层嫌疑。
|
|
477
|
+
* 两条决断腿(活帧/durable 行)共用这一把,判词绝不各写各的。
|
|
478
|
+
*/
|
|
479
|
+
function isProbeCauseCarrier(v) {
|
|
480
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
481
|
+
}
|
|
461
482
|
function readRuleSuggestions(v) {
|
|
462
483
|
if (!Array.isArray(v))
|
|
463
484
|
return undefined;
|
|
@@ -570,6 +591,9 @@ export async function surfaceToolApprovalFrameAndRespond(frame, respond, streamA
|
|
|
570
591
|
...(typeof frame.persistedRuleShadowed === 'string' && frame.persistedRuleShadowed.trim() !== ''
|
|
571
592
|
? { persistedRuleShadowed: frame.persistedRuleShadowed }
|
|
572
593
|
: {}),
|
|
594
|
+
// #280 件1(0.30.4):探针因由随卡透传 —— 载体形判之外零校验零改写(内部结构归呈卡端窄读器,
|
|
595
|
+
// isProbeCauseCarrier 顶注);缺席/坏载体 ⇒ 键不 stamp,卡形字节不变。
|
|
596
|
+
...(isProbeCauseCarrier(frame.probeCause) ? { probeCause: frame.probeCause } : {}),
|
|
573
597
|
});
|
|
574
598
|
const decision = card.kind === 'allow' ? (card.allowSession ? 'allow_session' : 'allow') : 'deny';
|
|
575
599
|
if (card.kind === 'failed') {
|
|
@@ -20,6 +20,26 @@ export interface SubagentActivity {
|
|
|
20
20
|
export type SubagentActivitySink = (a: SubagentActivity) => void;
|
|
21
21
|
/** 装/卸 Progress 段落点。传 null 卸。返回还原函数。 */
|
|
22
22
|
export declare function installSubagentActivitySink(sink: SubagentActivitySink | null): () => void;
|
|
23
|
+
/**
|
|
24
|
+
* 一帧 tail `event: meta` 的发布载荷(#280 件2,0.30.4)。`meta` 是连接语义帧(server 建连即发:
|
|
25
|
+
* `{version, runId, target, status, seq?, contentFrames?, …}`),**不进内容面** —— 但其中的
|
|
26
|
+
* **供给形判别位 `contentFrames`**(server e439a6c,闭集 {on | progress_only | unknown})是端
|
|
27
|
+
* 区分「内容帧**永远不会来**(forward 缺席宿主,结构性无内容)vs **还没来**」的唯一诚实依据;
|
|
28
|
+
* 0.30.3 及之前它被消费循环的 forward-only 过滤整类 skip,端结构性到不了。
|
|
29
|
+
* 🔴 `meta` 为**开集原文**(SDK subagentStream 产物 `Record<string, unknown>` 原样):判别位的
|
|
30
|
+
* 窄读(闭集判词/缺席处置)归消费端,包只搬运 —— additive 上游往 meta 里加键零施工。
|
|
31
|
+
* ⚠️ 供给形登记随句柄终态在 server 侧撤销(SubagentTailBus.forgetHandleContentMode)⇒ 判别位
|
|
32
|
+
* 要在子代存活窗内消费,终态后重开的 tail 读到 `unknown` 不是回归。
|
|
33
|
+
*/
|
|
34
|
+
export interface SubagentTailMeta {
|
|
35
|
+
taskId: string;
|
|
36
|
+
/** meta 帧原文(开集;`contentFrames` 等判别位的窄读归消费端)。 */
|
|
37
|
+
meta: Record<string, unknown>;
|
|
38
|
+
}
|
|
39
|
+
/** 端装的 meta 帧落点(#280 件2)。不装 ⇒ 判别位不达端(不是错误态,该面不启用;0.30.3 现状字节不变)。 */
|
|
40
|
+
export type SubagentTailMetaSink = (m: SubagentTailMeta) => void;
|
|
41
|
+
/** 装/卸 tail meta 帧落点。传 null 卸。返回还原函数。 */
|
|
42
|
+
export declare function installSubagentTailMetaSink(sink: SubagentTailMetaSink | null): () => void;
|
|
23
43
|
/**
|
|
24
44
|
* tail 是否正对该行开着 —— **两源互斥判别口**(行帧 `currentTool` 臂在 tail 活跃时让位:
|
|
25
45
|
* tail 的 tool_start 带真 args,渲染更细;两源同录 = 每步双行)。
|
|
@@ -84,6 +84,15 @@ export function installSubagentActivitySink(sink) {
|
|
|
84
84
|
activitySink = prev;
|
|
85
85
|
};
|
|
86
86
|
}
|
|
87
|
+
let tailMetaSink = null;
|
|
88
|
+
/** 装/卸 tail meta 帧落点。传 null 卸。返回还原函数。 */
|
|
89
|
+
export function installSubagentTailMetaSink(sink) {
|
|
90
|
+
const prev = tailMetaSink;
|
|
91
|
+
tailMetaSink = sink;
|
|
92
|
+
return () => {
|
|
93
|
+
tailMetaSink = prev;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
87
96
|
/* `coerceOutput`(tool_end.output 的字符串化口)**已搬到 `subagentContentStore.ts`**
|
|
88
97
|
* (#158 移交① / [3674](d) 姊妹病,2026-08-12):喂那个 store 的是两条腿(本 tail 腿 + seam
|
|
89
98
|
* 适配器的 C1 分流臂),字符串化口必须只有一份,故跟着它服务的那个位走。公面导出名不变
|
|
@@ -143,8 +152,35 @@ export function tailEngineSubagent(taskId) {
|
|
|
143
152
|
// 连接分界线:meta 帧即到 = SSE 建连成功(与「子代此刻恰好在跑长工具、没内容可发」区分开)
|
|
144
153
|
hostLog('debug', `[subagent-tail] ${taskId} stream connected +${Date.now() - openedAt}ms`);
|
|
145
154
|
}
|
|
146
|
-
|
|
147
|
-
|
|
155
|
+
// #280 件2(0.30.4):帧分类闸 —— `meta` 经发布口出去(`contentFrames` 判别位在其中,
|
|
156
|
+
// 见 SubagentTailMeta 顶注),`forward` 进内容面,其余(heartbeat / 未来新连接语义帧)
|
|
157
|
+
// 维持 skip。🔴 开闸范围**只放 meta**(最小化):放宽 default 臂 = 把未知帧灌进发布口,
|
|
158
|
+
// 消费端会把连接杂音当判别位读。
|
|
159
|
+
switch (ev.event) {
|
|
160
|
+
case 'meta':
|
|
161
|
+
// 连接语义帧,不进内容面;不装 sink = 现状。🔴 消费端 sink 失败**绝不撕裂 tail**
|
|
162
|
+
//(本文件头注铁律「一切失败 fail-soft…绝不 throw」;runStream onDroppedFrame
|
|
163
|
+
// 「sink 抛错绝不打断流且痕迹落回」同族)——两臂都要:同步 throw 由 try/catch 兜,
|
|
164
|
+
// **异步拒绝**(类型虽 void,宿主传 async 函数合法)也要有界观察 —— 不观察 =
|
|
165
|
+
// unhandledRejection = Node 缺省整进程崩,TUI 宿主最坏形。痕迹留 hostLog,内容帧照常消费。
|
|
166
|
+
try {
|
|
167
|
+
const out = tailMetaSink?.({ taskId, meta: ev.data });
|
|
168
|
+
if (out !== null && typeof out === 'object' && typeof out.then === 'function') {
|
|
169
|
+
;
|
|
170
|
+
out.then(undefined, (e) => {
|
|
171
|
+
hostLog('debug', `[subagent-tail] ${taskId} meta sink rejected: ${String(e).slice(0, 160)}`);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch (e) {
|
|
176
|
+
hostLog('debug', `[subagent-tail] ${taskId} meta sink threw: ${String(e).slice(0, 160)}`);
|
|
177
|
+
}
|
|
178
|
+
continue;
|
|
179
|
+
case 'forward':
|
|
180
|
+
break;
|
|
181
|
+
default:
|
|
182
|
+
continue; // heartbeat 等连接语义帧,不进内容面
|
|
183
|
+
}
|
|
148
184
|
const d = ev.data;
|
|
149
185
|
const t = d.type;
|
|
150
186
|
frames += 1;
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
| peer:wire 契约 | `@sema-agent/sdk` **>=6.17.2**(value-level,非 type-only) | `package.json` `peerDependencies` |
|
|
24
24
|
| peer:会话词汇表 | `@sema-agent/agent-types` **>=0.2.0**(type-only,零运行时) | 同上 |
|
|
25
25
|
| runtime dep | `diff` ^9.0.0(**唯一**一条;portability 门按**等值**钉死) | `package.json` `dependencies` |
|
|
26
|
-
| 公开导出面 | **
|
|
26
|
+
| 公开导出面 | **707** 个运行期符号(+ 33 个测试钩) | `scripts/public-export-baseline.json` 的 `count` / `testHookCount` —— **别手抄进别处,以该文件为准** |
|
|
27
27
|
| 常驻门 | 以 `scripts/gates-manifest.json` 的 `suites` 长度为准(**本档不抄这个数**) | `scripts/gates-manifest.json`;`npm test` 的名单等值门与它逐名对账 |
|
|
28
28
|
| 沿革档 | 0.29.0 起建 `CHANGELOG.md`;更早批次记账在 `src/index.ts` 文件头 + `docs/REFACTOR-LEDGER.md` | — |
|
|
29
29
|
|
|
@@ -99,7 +99,7 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
|
|
|
99
99
|
|
|
100
100
|
## §2 公共导出面地图(按域)
|
|
101
101
|
|
|
102
|
-
> 全集真源 = `scripts/public-export-baseline.json` 的 `names`(**
|
|
102
|
+
> 全集真源 = `scripts/public-export-baseline.json` 的 `names`(**707** 项)。
|
|
103
103
|
> 本节**不逐名抄**,只给「域 → 承重导出 → 用途 → 实现锚」。承重导出 = 一个端为了让这个域干活
|
|
104
104
|
> **必须**直接调到的那几个符号;其余是它们的类型、变体与辅助位。
|
|
105
105
|
> 单一入口:`import { … } from '@sema-agent/client-core'`(`exports` 只有 `.` 一个;
|
|
@@ -109,28 +109,28 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
|
|
|
109
109
|
|
|
110
110
|
`public-export-baseline.json` 由 **`dist/index.js` 的运行期导出**生成(生成口径自述见
|
|
111
111
|
`scripts/run-client-core-typeshape-test.mjs`,双向精确集合门在 `scripts/run-public-surface-test.mjs`)。
|
|
112
|
-
实测:
|
|
112
|
+
实测:707 项 **100% 是运行期导出,零 type-only**。
|
|
113
113
|
|
|
114
114
|
**推论(端必须知道)**:
|
|
115
|
-
- barrel 导出的**类型**面比
|
|
115
|
+
- barrel 导出的**类型**面比 707 大得多,且**不被这道门看守** —— `AdapterContext` / `SeamEvent` /
|
|
116
116
|
`ChromeEvent` / `HostPorts` / `ApprovalCardPort` / `HitlHostSurface` / `ClientSliceLike` /
|
|
117
117
|
`LocalSessionEvent` / `SeatMethodName` / `ModelCatalog` 全在公面上、全**不在**基线里。
|
|
118
118
|
端依赖这些类型是合法的,但**不要**拿基线 diff 当"类型面没变"的证据。
|
|
119
119
|
- `src/agentSession/contract.ts` 对基线贡献 **0** 项(纯类型模块,`export *` 在 dist 里是空转发)。
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
707 项的内部构成(帮助端估读表大小):**210** 项是 `SCREAMING_SNAKE` 常量数据表/词汇表
|
|
122
122
|
(矩阵、键集、env 名、锚串)而非可调用物;**4** 项是 PascalCase 运行期值
|
|
123
123
|
(`ControlRouter` / `ControlSafetyError` / `HitlBridge` / `HitlSafetyError`);
|
|
124
124
|
**39** 项是 `*For(sessionKey, …)` 的 per-session 变体(§6;其中 `engineNamespaceKeyFor` 是命名巧合 —— 参数是 baseUrl 不是 sessionKey,见域 14)。
|
|
125
125
|
|
|
126
|
-
### 2b. 域图(16 域,逐域计数之和 =
|
|
126
|
+
### 2b. 域图(16 域,逐域计数之和 = 707)
|
|
127
127
|
|
|
128
128
|
| # | 域 | 名数 | 承重导出 | 用途 | 实现锚 |
|
|
129
129
|
|---|---|---|---|---|---|
|
|
130
130
|
| 1 | **适配内核(下行主链)** | 29 | `adapt` · `createWireToCcAdapter` · `runStream` · `eventToSdkMessage` · `terminalToSdkResult` · `turnUsageToModelUsage` · `isRunStreamActive` · `ADAPTER_DIVERGENCES` | 引擎 SSE `AgentEvent` → 端要渲的**双面输出**:transcript(`SDKMessage`)+ chrome(瞬态 `ChromeEvent`)。**本包存在的理由** | `src/adapt.ts`、`src/adapt/{arms,wireShapes,panelTasks}.ts`(经 `adapt.ts` 再导出)、`src/adapter/runStream.ts`、`src/adapter/downstream/*`、`src/adapter/types.ts` |
|
|
131
131
|
| 2 | **seam 公共契约** | 2(其余为 type-only) | `CHROME_ARMS` · `deriveTranscriptId` | 公共词汇 + **id 确定性不变量**(同一条流重放 ⇒ 同一串 id)。`CHROME_ARMS` = 端「我要消费哪些 chrome 臂」的对照清单 | `src/seam.ts` |
|
|
132
132
|
| 3 | **HITL 决断卡链**(§4/§5 主战场) | 119 | `makeHitlCanUseTool` · `HitlBridge` · `findPendingForTask` · `HitlSafetyError` · `bridgeAskUserQuestionGates` · `surfaceToolApprovalFrameAndRespond` / `surfaceFsApprovalAndDecide` · `readToolApprovalRespondAck` · `installApprovalCardPort(For)` · `installHitlHostSurface(For)` · `armPlanReviewApproval` · `reopenPlanReviewCard` · `decidePlanReview` · `startApprovalsFeed` · `pendingRowIsOwnedByThisSession` · `approvalCallKey`/`liveFrameCallKey`/`planReviewQuestionId` · `registerArmedGateFor`/`wasGateArmedFor`/`clearArmedGateFor` · `waitForGateArmed(For)`/`onGateArmed(For)`/`gateArmedWaitMs`(#244 F1 呈现回执事件源) · `planReviewArmedKey(For)`/`notePlanReviewAnswered(For)`/`notePlanReviewAnsweredIfDecisive(For)`(A-024.4 plan 呈现分代) · `toolEndOutputText` · `isAskTool` · `waitForParkRowBirth` · `classifyAskParkRows` / `askParkRowArm` / `classifyAskParkChainFailure` · `readDecisionNoteAudit` / `decisionNoteAuditLine` · `resumeRunningOptions` / `resumeChoiceFromLabels` · `persistedRulesLaneAvailable`/`persistedRulesGovernanceAvailable` · `classifyRulesFailure` · `listAllPersistedRules` · `classifySkippedReason` · `readRulePersistOutcome`(#244 F2:persist-ack 读口与 `readToolApprovalRespondAck` 合成一处) · `parseLocalAllowRule`(durable 腿本地落规则窄化骨架,谓词经 `LocalAllowRuleDeps` 注入) | suspended→decide→resume 环。🔴 **D-1 两元组 verbatim 回显**是字节级断言的安全不变量,端**不许重实现它的任何一段**。🔴 键空间边界(web [C1] d3 拦截):`gateIdentity` 四常量两函数只覆盖 HITL questionId/callKey 空间;seat 的 `TOOL_PERMISSION_REQUEST_ID_DOMAINS`(`plan:` 等)是另一键空间,**两者绝不合并**(合并=座位校验器静默拒全部 plan-review 卡) | `src/hitl/hitlBridge.ts`、`toolApprovalWire.ts`、`askGateWire.ts`、`planReviewWire.ts`、`hitlHostSurface.ts`、`gateIdentity.ts`、`armedGateRegistry.ts`、`parkOwnership.ts`、`parkResolver.ts`、`approvalsFeed.ts`、`frameRouter.ts`(**只挑名导出** `toolEndOutputText`/`ENGINE_ABORT_TOOL_RESULT`/`isAskTool`/`HITL_REJECT_MESSAGE`)、`parkRowBirthWait.ts`、`approvalDecisionNoteAudit.ts`、`askParkRowRouting.ts`、`resumeRunningCard.ts`(#265 上收的判定层)、`persistedRulesWire.ts`、`localAllowRule.ts`(#244 F2 规则侧) |
|
|
133
|
-
| 4 | **子代 wire + 面板侧信道台账** |
|
|
133
|
+
| 4 | **子代 wire + 面板侧信道台账** | 69 | `tailEngineSubagent` · `installSubagentActivitySink` · `installSubagentTailMetaSink`(#280 件2:tail meta 帧发布口,`contentFrames` 判别位载体)· `stopEngineTask` + `classifyTaskStopConflict` · `fetchEngineSubagentReport` · `steerEngineSubagent` · `subscribeSubagentContent` · `subscribeEngineAgentPanel` · `publishQuestionFrame` / `respondToQuestion` | 驱动与观测委派子代;经 module 级台账喂活体 agent/task 面板。全部**能力位 gate**(§5b) | `src/subagent/*.ts`、`src/subagentContentStore.ts`、`src/engineAgentPanelStore.ts`、`src/engineInlineTaskStats.ts`、`src/engineToolLabelStore.ts`、`src/liveQuestionStore.ts` |
|
|
134
134
|
| 5 | **fleet 投影** | 43 | `createFleetLedger` · `projectTasks` · `projectWorkflows` · `projectFleetAgentRows` · `readEngineActiveBgTasks` · `FLEET_TASK_VIEW_KEYS` | 老 `fleetClient` 那一刀的成品:**帧体归库、连接归端** —— 端持 SSE 连接,库做行投影 + 保留台账 | `src/fleet/fleetProjection.ts`、`src/fleet/fleetLedger.ts`、`src/fleetAgentPanelProjection.ts`、`src/fleetTaskDesc.ts` |
|
|
135
135
|
| 6 | **请求装配(上行唯一构造口)** | 8 | `buildTaskRequest` · `REQUEST_FIELD_MATRIX` · `unregisteredRequestKeys` · `applyLiveRequestDefaults` · `taskNotificationToPrintFrame` | 两条车道(`interactive`/`print`)出站请求的**唯一**构造器;`unregisteredRequestKeys` 是可执行门 —— 端偷带一个未登记键上 wire 就红 | `src/request/taskRequest.ts`、`src/request/printNotification.ts` |
|
|
136
136
|
| 7 | **通知与 outstanding 台账** | 37 | `installNotificationQueuePort` · `normalizeTaskNotification` · `taskNotificationDedupKeyFromWire` · `registerOutstandingBgTask` / `registerOutstandingWorkflowRun` · `notificationQueuePortMisses` · `subscribeOutstandingWorkflows` · `outstandingDeliverableWorkflowCount` | `task_notification` 归一 + 去重 + 投递进宿主命令队列的**一把闸**;`outstandingDeliverableWorkflowCount()` 是 headless `-p` 的**退出门** | `src/notifications.ts`(11 个 module 台账) |
|
|
@@ -414,6 +414,7 @@ durable park 腿走 `HitlBridge.decideTool(outcome, toolUseID, opts, preResolved
|
|
|
414
414
|
| `installHitlHostSurface(For)` | `src/hitl/hitlHostSurface.ts` | 通知不上屏(与壳原文 `if (!store) return` 同语义) | **是**(`hitlHostSurfaceMisses()` 恒应为 0) | §4a 的两条**安全告知**(remember-not-applied / edit-not-forwarded)+ cancel-by-deny warn + Recent Denials 记账**全丢** |
|
|
415
415
|
| `installEngineWireTarget(For)` | `src/engineWireTarget.ts` | 回落 env 派生 | — | 🔴 **非 Node 宿主(web / desktop 渲染进程)没有 env** ⇒ 根本拿不到引擎目标。对它们这是**唯一**入口(设了就压过 env);不装 ⇒ `engineRowStopGate` 等按 `baseUrl` 查 caps 的门恒判假。⚠️ **凭证面有边界**:`EngineWireTarget.token` 今天是 `string`,**装不进** `{ mode: 'same-origin-relay' }` —— 浏览器同源宿主必读 **§5d** 与缺口 **P-28** |
|
|
416
416
|
| `installSubagentActivitySink` | `src/subagent/engineSubagentTail.ts` | Subagent Progress 段无数据 | 否 | 明确**不是**错误态:那个面就是没启用 |
|
|
417
|
+
| `installSubagentTailMetaSink` | `src/subagent/engineSubagentTail.ts`(#280 件2,0.30.4) | tail `event: meta` 帧不发布(0.30.3 现状) | 否 | `contentFrames` 供给形判别位(闭集 {on, progress_only, unknown})不达端 ⇒ 端把「结构性无内容(forward 缺席宿主)」误读成「还没来」永远空挂。载荷 = `{taskId, meta}`(meta 为帧**开集原文**,判别位窄读归端);⚠️ 判别位要在子代存活窗内消费(server 侧登记随句柄终态撤销,终态后 tail 读到 `unknown` 不是回归) |
|
|
417
418
|
| `installWorkflowStatusProbe` | `src/notifications.ts` | watcher 没有带对 baseUrl/token/principal 的 `workflows.get` | — | **workflow 完成通知永远不落地** |
|
|
418
419
|
| `installBgTaskStatusProbe` | `src/notifications.ts` | bg 状态 watcher 空转 | — | **后台子代完成通知永远不落地**(这个 watcher 存在的理由正是 idle 期推送不可靠) |
|
|
419
420
|
| `CatalogFetchJson`(注入,非 install) | `src/model/catalog.ts` | 线上腿**整条不启用**(`online.reason = 'no-fetch-port'`) | — | 目录只走包内兜底(端可据 `source` + `online.reason` 诚实渲「内置版本(离线)」) |
|
|
@@ -786,6 +787,7 @@ reason 里写明「枚举器盲区形」。已知两形:
|
|
|
786
787
|
- [ ] `kickEngineCapsProbe(baseUrl, probe)`(caps 门的数据源)
|
|
787
788
|
- [ ] `installWorkflowStatusProbe` / `installBgTaskStatusProbe` —— 不装 = **workflow / 后台子代的完成通知永远不落地**
|
|
788
789
|
- [ ] `installSubagentActivitySink`(可选:Subagent Progress 段的数据源;不装不是错误态)
|
|
790
|
+
- [ ] `installSubagentTailMetaSink`(可选,0.30.4 #280 件2:tail meta 帧的 `contentFrames` 判别位数据源;不装不是错误态,但查看态会把「结构性无内容」渲成永远的「还没来」)
|
|
789
791
|
- [ ] **启动校验用存在性读口**(§5a 的 (a) 表,🔴 **哨兵逐口不同,逐个照抄别推广**;多会话宿主用 `*For` 那一支):`hasApprovalCardPort() === true` · `hasApprovalCardPortFor(key) === true` · **`hitlHostSurfaceFor(key) !== null`**(哨兵是 `null`,写 `!== undefined` **恒真** = 假绿) · `hostSettings() !== undefined` · `hostSettingsFor(key) !== undefined` · `hostFs() !== undefined` · `hostFsFor(key) !== undefined` · `hostSession() !== undefined` · `hostSessionFor(key) !== undefined` · `engineWireTarget() !== null` · `engineWireTargetFor(key) !== null`(`hostTimers()` / `hostTimersFor(key)` 同为 `!== undefined`,按你真装的挑)
|
|
790
792
|
- [ ] **miss 计数当回归探针,不当装配自检**(#252 复审 R3/R4,§5a (b) / 缺口 **P-29**):`hostPortMisses()` 空 / `notificationQueuePortMisses() === 0` / `approvalCardPortMisses() === 0` / `hitlHostSurfaceMisses() === 0` / `compensationSplitViolations()` 空 —— 🔴 **这几个数初值就是 0/空**,「完全没装口 + 还没发生任何调用」时它们照样全绿,**启动瞬间的断言证明不了装配**。正确用法 = 跑过**一轮真流量**之后再断言它们仍为 0。⚠️ **通知队列口今天没有存在性读口**(P-29),那一条只能靠你自己记得调过
|
|
791
793
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/client-core",
|
|
3
|
-
"version": "0.30.
|
|
3
|
+
"version": "0.30.4",
|
|
4
4
|
"description": "Client-side session runtime shared by every sema human client (TUI / web / desktop): sema wire frames (AgentEvent) -> CC session vocabulary (SDKMessage) with dual-plane output (transcript/chrome), deterministic transcript ids, lane discipline as a type, and the notification/dedup ledgers. Every CC-skin shape is collected here so the wire itself stays neutral. Blackboard [1832] design axioms; [1651]/[1652]/[1653] signed seam design. Renamed from @sema-agent/wire-cc-adapter (0.1.x).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|