@sema-agent/client-core 0.12.1 → 0.13.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/README.md +15 -2
- package/dist/abortableSleep.d.ts +29 -0
- package/dist/abortableSleep.js +43 -0
- package/dist/adapt/arms.d.ts +58 -0
- package/dist/adapt/arms.js +613 -0
- package/dist/adapt/ids.d.ts +22 -0
- package/dist/adapt/ids.js +34 -0
- package/dist/adapt/instanceLedger.d.ts +36 -0
- package/dist/adapt/instanceLedger.js +50 -0
- package/dist/adapt/panelTasks.d.ts +54 -0
- package/dist/adapt/panelTasks.js +193 -0
- package/dist/adapt/textStream.d.ts +49 -0
- package/dist/adapt/textStream.js +141 -0
- package/dist/adapt/toolCards.d.ts +65 -0
- package/dist/adapt/toolCards.js +100 -0
- package/dist/adapt/turnFlags.d.ts +33 -0
- package/dist/adapt/turnFlags.js +55 -0
- package/dist/adapt/wireShapes.d.ts +93 -0
- package/dist/adapt/wireShapes.js +167 -0
- package/dist/adapt.d.ts +32 -59
- package/dist/adapt.js +78 -1206
- package/dist/adapter/downstream/eventToSdkMessage.d.ts +55 -13
- package/dist/adapter/downstream/eventToSdkMessage.js +166 -106
- package/dist/adapter/downstream/terminalToSdkResult.js +149 -160
- package/dist/adapter/downstream/turnUsageToModelUsage.d.ts +36 -0
- package/dist/adapter/downstream/turnUsageToModelUsage.js +34 -6
- package/dist/adapter/runStream.d.ts +29 -4
- package/dist/adapter/runStream.js +129 -13
- package/dist/adapter/types.d.ts +2 -2
- package/dist/agentSession/backgroundView.js +4 -15
- package/dist/agentsWireCaps.d.ts +10 -6
- package/dist/agentsWireCaps.js +21 -7
- package/dist/argvFlagValue.d.ts +41 -0
- package/dist/argvFlagValue.js +69 -0
- package/dist/attachmentsWireCaps.d.ts +3 -2
- package/dist/attachmentsWireCaps.js +5 -3
- package/dist/classifierVerdictWire.d.ts +8 -0
- package/dist/classifierVerdictWire.js +8 -0
- package/dist/cloudConfigWireCaps.d.ts +28 -1
- package/dist/cloudConfigWireCaps.js +51 -11
- package/dist/controlRouter.d.ts +14 -8
- package/dist/controlRouter.js +15 -21
- package/dist/detachWire.d.ts +15 -5
- package/dist/detachWire.js +17 -7
- package/dist/effortWire.d.ts +0 -21
- package/dist/effortWire.js +6 -20
- package/dist/engineInlineTaskStats.d.ts +12 -6
- package/dist/engineWireSdk.d.ts +12 -0
- package/dist/env/localeGeo.js +2 -1
- package/dist/envFlag.d.ts +39 -0
- package/dist/envFlag.js +51 -0
- package/dist/finalVerifyWire.d.ts +7 -5
- package/dist/finalVerifyWire.js +6 -5
- package/dist/fleet/fleetLedger.d.ts +32 -9
- package/dist/fleet/fleetLedger.js +119 -34
- package/dist/fleet/fleetProjection.d.ts +44 -6
- package/dist/fleet/fleetProjection.js +52 -10
- package/dist/fleetAgentPanelProjection.d.ts +18 -1
- package/dist/fleetAgentPanelProjection.js +61 -14
- package/dist/forkWireCaps.d.ts +2 -1
- package/dist/forkWireCaps.js +5 -11
- package/dist/goalStopHook.d.ts +142 -0
- package/dist/goalStopHook.js +258 -0
- package/dist/headlessPermissionModeWire.d.ts +10 -0
- package/dist/headlessPermissionModeWire.js +24 -21
- package/dist/headlessReconnectWire.d.ts +7 -1
- package/dist/headlessReconnectWire.js +20 -2
- package/dist/hitl/approvalsFeed.js +31 -8
- package/dist/hitl/askGateWire.d.ts +27 -96
- package/dist/hitl/askGateWire.js +69 -546
- package/dist/hitl/frameRouter.d.ts +86 -0
- package/dist/hitl/frameRouter.js +342 -0
- package/dist/hitl/gateLedger.d.ts +107 -0
- package/dist/hitl/gateLedger.js +113 -0
- package/dist/hitl/hitlBridge.d.ts +75 -15
- package/dist/hitl/hitlBridge.js +94 -22
- package/dist/hitl/hitlHostSurface.d.ts +49 -0
- package/dist/hitl/hitlHostSurface.js +155 -0
- package/dist/hitl/parkResolver.d.ts +74 -0
- package/dist/hitl/parkResolver.js +241 -0
- package/dist/hitl/planReviewWire.d.ts +60 -2
- package/dist/hitl/planReviewWire.js +152 -74
- package/dist/hitl/toolApprovalWire.d.ts +67 -4
- package/dist/hitl/toolApprovalWire.js +119 -31
- package/dist/hooksWireCaps.d.ts +1 -82
- package/dist/hooksWireCaps.js +34 -235
- package/dist/host.d.ts +16 -5
- package/dist/index.d.ts +2 -0
- package/dist/index.js +15 -1
- package/dist/interactiveToolsWire.d.ts +15 -4
- package/dist/interactiveToolsWire.js +24 -26
- package/dist/limitsWire.js +7 -40
- package/dist/liveInitToolFace.d.ts +51 -6
- package/dist/liveQuestionStore.d.ts +5 -6
- package/dist/model/providerPresets.js +11 -1
- package/dist/notifications.d.ts +48 -2
- package/dist/notifications.js +223 -46
- package/dist/retainBackgroundWireCaps.d.ts +3 -2
- package/dist/retainBackgroundWireCaps.js +5 -9
- package/dist/sandboxWire.d.ts +9 -31
- package/dist/sandboxWire.js +51 -50
- package/dist/scenarioWire.d.ts +1 -1
- package/dist/scenarioWire.js +25 -36
- package/dist/seam.d.ts +23 -6
- package/dist/seam.js +40 -30
- package/dist/seatContract.d.ts +369 -83
- package/dist/seatContract.js +585 -198
- package/dist/selfOrchestrationWireCaps.d.ts +6 -5
- package/dist/selfOrchestrationWireCaps.js +8 -12
- package/dist/sessionSlot.d.ts +8 -0
- package/dist/sessionSlot.js +1 -0
- package/dist/steering.js +2 -2
- package/dist/subagent/engineTaskHandleWire.d.ts +3 -0
- package/dist/subagent/engineTaskHandleWire.js +17 -2
- package/dist/subagentContentStore.d.ts +5 -5
- package/dist/toolResult.d.ts +89 -8
- package/dist/toolResult.js +99 -30
- package/dist/typePins.d.ts +17 -0
- package/dist/typePins.js +1 -0
- package/dist/ultracodeWireCaps.js +5 -6
- package/dist/unrefTimer.d.ts +19 -0
- package/dist/unrefTimer.js +5 -0
- package/dist/workflow.d.ts +3 -2
- package/dist/workflow.js +3 -2
- package/dist/workflowClient.d.ts +7 -0
- package/dist/workflowClient.js +47 -12
- package/package.json +3 -3
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { deriveTranscriptId } from '../seam.js';
|
|
2
|
+
import { degradedToolResultBody, detectEngineBgShellReceipt, reportFindingsToolUseResult, structuredToToolUseResult, todoWriteToolUseResult, wireOutputToBody, } from '../toolResult.js';
|
|
3
|
+
import { chrome, MAIN, transcript } from './ids.js';
|
|
4
|
+
import { flattenWireOutput } from './wireShapes.js';
|
|
5
|
+
export function createToolCardLedger(ctx, idOf) {
|
|
6
|
+
const pending = new Map();
|
|
7
|
+
let assistantResponseId = null;
|
|
8
|
+
/**
|
|
9
|
+
* TodoWrite 划删线 diff 的 `oldTodos`。
|
|
10
|
+
* 🔴 **turn 级**(cli 同:`let lastLiveTodos` 声明在 generator 体内,不是 module 级 ——
|
|
11
|
+
* cli 的注释写着「module-level, per-process」但代码不是,以**代码**为准,差分守卫认代码)。
|
|
12
|
+
*/
|
|
13
|
+
let lastLiveTodos = [];
|
|
14
|
+
/**
|
|
15
|
+
* 一张开卡的收口(cli `buildToolResult` + 它内联的 #117a 桥)。产出顺序与 cli 的
|
|
16
|
+
* 「副作用先于 yield」一致:先 chrome(bg shell 建行),再 transcript(tool_result 卡)。
|
|
17
|
+
*/
|
|
18
|
+
function* buildToolResult(p, end) {
|
|
19
|
+
const isError = end?.isError ?? false;
|
|
20
|
+
// D 层 / T7:wire 带正文 ⇒ 真身投影;没带 ⇒ **诚实缺席**(§8-4,不再 mock 反造)。
|
|
21
|
+
const body = end && end.output !== undefined
|
|
22
|
+
? wireOutputToBody(p.name, end.output, isError, end.truncated === true, flattenWireOutput, end.structured)
|
|
23
|
+
: degradedToolResultBody(isError);
|
|
24
|
+
// ── E 层 ③:#117a 模型发起的后台 Bash 回执 → ctrl+B 面板行(判定在库、执行留宿主)。
|
|
25
|
+
if (p.name === 'Bash' && !isError && end?.output !== undefined) {
|
|
26
|
+
const reg = detectEngineBgShellReceipt(p.rawInput, flattenWireOutput(end.output));
|
|
27
|
+
if (reg) {
|
|
28
|
+
yield chrome({ kind: 'bgshell_register', laneProof: MAIN, taskId: reg.taskId, registration: reg });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// B 层:structured → 逐工具 typed toolUseResult(卡的 outputSchema safeParse 过才渲富卡)。
|
|
32
|
+
let rich = end?.structured !== undefined
|
|
33
|
+
? structuredToToolUseResult(end.structured, end.output !== undefined ? flattenWireOutput(end.output) : undefined)
|
|
34
|
+
: null;
|
|
35
|
+
// E 层 ④/⑤:两条按**工具名**的补位(引擎不发 type 判别位,B 层 switch 认领不了)。
|
|
36
|
+
if (rich === null && p.name === 'TodoWrite') {
|
|
37
|
+
const todo = todoWriteToolUseResult(p.rawInput, lastLiveTodos, isError);
|
|
38
|
+
if (todo !== null) {
|
|
39
|
+
rich = { toolUseResult: todo.toolUseResult, isError: todo.isError };
|
|
40
|
+
lastLiveTodos = todo.newTodos;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (rich === null && !isError && p.name === 'ReportFindings') {
|
|
44
|
+
rich = reportFindingsToolUseResult(end?.structured, p.rawInput);
|
|
45
|
+
}
|
|
46
|
+
const eventId = end?.eventId ?? p.eventId;
|
|
47
|
+
const parentToolCallId = end?.parentToolCallId ?? p.parentToolCallId;
|
|
48
|
+
yield transcript({
|
|
49
|
+
type: 'user',
|
|
50
|
+
message: {
|
|
51
|
+
role: 'user',
|
|
52
|
+
content: [
|
|
53
|
+
{
|
|
54
|
+
type: 'tool_result',
|
|
55
|
+
tool_use_id: p.id,
|
|
56
|
+
content: body.content,
|
|
57
|
+
is_error: rich?.isError === true || body.isError,
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
// DIVERGENCE-2:cli 在缺 eventId 时铸随机 v4,本包一律**稳定键派生**
|
|
62
|
+
// (`wtc_<toolUseId>` —— 一张卡一个结果,天然唯一;同流重放 ⇒ 同 id 序列,[1653])。
|
|
63
|
+
uuid: eventId ?? deriveTranscriptId({ toolCallId: p.id }, ctx),
|
|
64
|
+
session_id: ctx.sessionId,
|
|
65
|
+
...(parentToolCallId !== undefined ? { parent_tool_use_id: parentToolCallId } : {}),
|
|
66
|
+
// CC 结果卡读 sidecar 上的 typed 输出(不是 block content)。
|
|
67
|
+
toolUseResult: rich !== null ? rich.toolUseResult : (body.toolUseResult ?? body.content),
|
|
68
|
+
// T7:wire 没带正文的诚实标记 —— 在场 = 这张卡没有真实执行结果(UI 显示决策留端)。
|
|
69
|
+
...(body.degraded !== undefined ? { _sema_degraded: body.degraded } : {}),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/** 关一张卡的**唯一**实现:出栈 + S1 复位 + 铸卡,前两步恒在第一个 yield 之前。 */
|
|
73
|
+
function* closeCard(p, end) {
|
|
74
|
+
pending.delete(p.id);
|
|
75
|
+
assistantResponseId = null;
|
|
76
|
+
yield* buildToolResult(p, end);
|
|
77
|
+
}
|
|
78
|
+
// 🔴 FIX-05 同族纪律:本模块**零 `this`** —— 全部走闭包变量与具名函数,
|
|
79
|
+
// 所以「同一个台账有两条访问路径」这件事在这里结构上不可能发生。
|
|
80
|
+
return {
|
|
81
|
+
has: (id) => pending.has(id),
|
|
82
|
+
peek: (id) => pending.get(id),
|
|
83
|
+
entries: () => pending.entries(),
|
|
84
|
+
open: (p) => {
|
|
85
|
+
pending.set(p.id, p);
|
|
86
|
+
},
|
|
87
|
+
close: closeCard,
|
|
88
|
+
*sweep() {
|
|
89
|
+
for (const [, p] of pending) {
|
|
90
|
+
// 走同一个 closeCard:出栈 + S1 复位 + 铸卡三步与显式关卡**逐字同一段代码**
|
|
91
|
+
// (拆分前这里把那三步又抄了一遍 —— 抄的那份就是「时序会漂」的第二个构造点)。
|
|
92
|
+
yield* closeCard(p);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
mintResponseId: (frame) => (assistantResponseId ??= `msg_sema_${idOf(frame, 'resp')}`),
|
|
96
|
+
resetResponseId: () => {
|
|
97
|
+
assistantResponseId = null;
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* adapt/turnFlags.ts — M6a **响应度量** + M6b **重试覆盖层**两个小状态机(A 族拆分;矩阵 §1.4)。
|
|
3
|
+
*
|
|
4
|
+
* 🔴 为什么这两件必须在**同一个文件**、而且必须**连驱动壳那一半一起搬**(矩阵 §3.3):
|
|
5
|
+
* 它们各自只有三行代码,但每一件的两半都分居在「驱动壳的帧前置」与「某一条臂」里:
|
|
6
|
+
* · `messageStartEmitted`:D4 的 TTFT 门写它,`turn_usage` 臂(A6)把它复位成 false
|
|
7
|
+
* (下一个 model round 重新压基线);
|
|
8
|
+
* · `endEmitted`:A6 置位,`result` 臂(A7)读它当「别重复发 end」的门;
|
|
9
|
+
* · `retryOverlayActive`:`retry_status` 臂(A15)挂旗,D4 的「恢复即清」判位清旗。
|
|
10
|
+
* 按「臂」切会切出**只有半个状态机**的边 —— 那正是 R1 五报里那条修最容易漂回去的地方。
|
|
11
|
+
* 所以本文件的对外面是**动作**(onFrameBeforeDispatch / noteRetryStatus / …),而不是三个布尔位。
|
|
12
|
+
*
|
|
13
|
+
* 判据留给下一个人:本文件之外的任何地方都不该出现 `messageStartEmitted` / `endEmitted` /
|
|
14
|
+
* `retryOverlayActive` 这三个名字。grep 到了就是有人把状态机又劈开了。
|
|
15
|
+
*/
|
|
16
|
+
import type { AdapterContext, AdapterOutput } from '../seam.js';
|
|
17
|
+
import { type Frame } from './ids.js';
|
|
18
|
+
export interface TurnFlags {
|
|
19
|
+
/**
|
|
20
|
+
* 每帧**分派之前**的两道前置(顺序与拆分前逐字一致:先恢复即清,再 TTFT 起拍):
|
|
21
|
+
* ① R1 重试覆盖层「恢复即清」;② 首个 `stream_event` 的 `response_metrics{phase:'start'}`。
|
|
22
|
+
*/
|
|
23
|
+
onFrameBeforeDispatch(m: Frame): Generator<AdapterOutput>;
|
|
24
|
+
/** A6 `turn_usage`:发 end 度量 + 压下一轮基线。 */
|
|
25
|
+
emitTurnUsageEnd(outputTokens: number): Generator<AdapterOutput>;
|
|
26
|
+
/** A7 `result`:只有还没发过 end 且这帧真带了 outputTokens 时才补发(`!endEmitted` 门)。 */
|
|
27
|
+
/** `readOutputTokens` 惰性:只在真的要发 end 度量时才读 usage(与拆分前「`!endEmitted`
|
|
28
|
+
* 门内才读 `m.usage`」逐字同语义 —— codex 复审 #3 收货修)。 */
|
|
29
|
+
emitResultEndIfNeeded(readOutputTokens: () => number | undefined): Generator<AdapterOutput>;
|
|
30
|
+
/** A15 `retry_status`:挂旗(下一帧主 lane 内容到达即清)。 */
|
|
31
|
+
noteRetryOverlay(): void;
|
|
32
|
+
}
|
|
33
|
+
export declare function createTurnFlags(ctx: AdapterContext, turnStartAt: number): TurnFlags;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { chrome, MAIN } from './ids.js';
|
|
2
|
+
export function createTurnFlags(ctx, turnStartAt) {
|
|
3
|
+
let messageStartEmitted = false;
|
|
4
|
+
let endEmitted = false;
|
|
5
|
+
/**
|
|
6
|
+
* R1(clay 五报 07-31):retry 覆盖层的四个清除点全在 turn 边界,缺「重试成功→清」的转移 ——
|
|
7
|
+
* 引擎重试成功那一刻什么都不发(BrainStatusPhase 无恢复终态,候 core [2163]),所以恢复只能由
|
|
8
|
+
* 「主 lane 又有内容在流」这个事实来证明。挂旗后首个主 lane 内容帧即清,CC 同位 = 重试循环
|
|
9
|
+
* 退出即 onRetryStatus(null)(pretty220 finally 清)。
|
|
10
|
+
*/
|
|
11
|
+
let retryOverlayActive = false;
|
|
12
|
+
return {
|
|
13
|
+
*onFrameBeforeDispatch(m) {
|
|
14
|
+
if (retryOverlayActive &&
|
|
15
|
+
(m.type === 'stream_event' ||
|
|
16
|
+
m.type === 'assistant' ||
|
|
17
|
+
m.type === 'tool_end_result' ||
|
|
18
|
+
m.type === 'turn_usage') &&
|
|
19
|
+
typeof m.parentToolCallId !== 'string' &&
|
|
20
|
+
// stream_event 的子流标记在 event 里(thinking 臂同款判位),帧顶层没有。
|
|
21
|
+
typeof m.event?.parentToolCallId !== 'string') {
|
|
22
|
+
// 恢复即清:主 lane 内容帧到达 = 引擎那次重试已成功;子流帧(parentToolCallId)不算证据
|
|
23
|
+
// (主 brain 仍可能在退避等待,#47 矩阵 #5 同族判别)。
|
|
24
|
+
retryOverlayActive = false;
|
|
25
|
+
yield chrome({ kind: 'retry_status', laneProof: MAIN, status: null });
|
|
26
|
+
}
|
|
27
|
+
if (m.type === 'stream_event' && !messageStartEmitted) {
|
|
28
|
+
messageStartEmitted = true;
|
|
29
|
+
yield chrome({
|
|
30
|
+
kind: 'response_metrics',
|
|
31
|
+
laneProof: MAIN,
|
|
32
|
+
phase: 'start',
|
|
33
|
+
ttftMs: ctx.now() - turnStartAt,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
*emitTurnUsageEnd(outputTokens) {
|
|
38
|
+
yield chrome({ kind: 'response_metrics', laneProof: MAIN, phase: 'end', outputTokens });
|
|
39
|
+
endEmitted = true;
|
|
40
|
+
messageStartEmitted = false; // 下一 model round 重新压基线
|
|
41
|
+
},
|
|
42
|
+
*emitResultEndIfNeeded(readOutputTokens) {
|
|
43
|
+
if (endEmitted)
|
|
44
|
+
return;
|
|
45
|
+
const outputTokens = readOutputTokens();
|
|
46
|
+
if (outputTokens === undefined)
|
|
47
|
+
return;
|
|
48
|
+
yield chrome({ kind: 'response_metrics', laneProof: MAIN, phase: 'end', outputTokens });
|
|
49
|
+
endEmitted = true;
|
|
50
|
+
},
|
|
51
|
+
noteRetryOverlay: () => {
|
|
52
|
+
retryOverlayActive = true;
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* adapt/wireShapes.ts — A 层的**帧形词表 + 纯投影助手**(A 族拆分 REF-CC-SPLIT-01)。
|
|
3
|
+
*
|
|
4
|
+
* 这里全是**纯函数与常量**:零可变量、零 module 台账、零 ctx 依赖。所以它既不出现在
|
|
5
|
+
* 读写矩阵(ADAPT-RW-MATRIX §1)的任何一行里,也不需要任何时序约束 —— 判据锚在
|
|
6
|
+
* 「本文件没有 `let`,也不 import 任何台账」,拆分后的状态归属讨论永远绕开它。
|
|
7
|
+
*
|
|
8
|
+
* 🔴 公面纪律:下面标了「公面」的六件在 0.1.x 起就是 `@sema-agent/client-core` 的导出名,
|
|
9
|
+
* `adapt.ts` 用**具名再导出**把它们原样送出门(不是 `export *` —— 那会把 `TASK_TOOL_NAMES` /
|
|
10
|
+
* `decisionOf` 这两件内部件一起推上公面,public-export-baseline 双向门当场红)。
|
|
11
|
+
*/
|
|
12
|
+
import type { Frame } from './ids.js';
|
|
13
|
+
/**
|
|
14
|
+
* 活体增量攒批节拍的**默认值**(时钟从 ctx.now() 取;宿主可用 `ctx.coalesceIntervalMs` 覆盖)。
|
|
15
|
+
*
|
|
16
|
+
* 取值依据(两个都是实测,别把其中一个当"唯一真相"):
|
|
17
|
+
* · **100ms** = 我们对标的 CC 2.1.207 CLI 口径(187 时代是 16ms,207 提到 100ms 降重绘频率,
|
|
18
|
+
* 长回答滚动更稳)—— 壳是 207 fork,所以库的默认值取它,壳消费本包时行为零变化;
|
|
19
|
+
* · **16ms** = CC **桌面端**宿主 `makeStreamDeltaCoalescer` 的单帧攒批节拍(设计稿 R1 实测)。
|
|
20
|
+
* ⇒ 结论:**节拍是宿主渲染策略,不是 wire 语义** —— CC 自己两个端就是两个值。web/桌面宿主
|
|
21
|
+
* 想要 16ms 就传 `coalesceIntervalMs: 16`,合并**语义**(思考先于文本、段边界重开块、
|
|
22
|
+
* committed 恒随后)在库里,一份。
|
|
23
|
+
*
|
|
24
|
+
* 🔴 顺带钉一句反面事实(R1 证伪,别再写进任何注释/文档):**"UI 从不见裸 token" 是错的** ——
|
|
25
|
+
* CC 攒批后 flush 的载荷仍是 `stream_event` 增量 delta,CC 的 UI 照样消费增量;
|
|
26
|
+
* 完整 assistant 消息是 SDK 另发的一路。我们这里的 `stream_delta` chrome 臂同构。
|
|
27
|
+
*
|
|
28
|
+
* 公面。
|
|
29
|
+
*/
|
|
30
|
+
export declare const FLUSH_INTERVAL_MS = 100;
|
|
31
|
+
/**
|
|
32
|
+
* T40 IDLE-FLUSH 竞速窗(cli upstreamBridge `IDLE_FLUSH_MS` 逐字同值)。
|
|
33
|
+
*
|
|
34
|
+
* 病:模型转入长工具参数生成(大 Write 的 input_json 不经本桥)时 SSE 增量停摆,而 thinking/
|
|
35
|
+
* answerSegment 里**已经生成**的内容还押着陪等(pty 确证:11s 整屏 hash 恒定)。
|
|
36
|
+
* 修:增量停 ≥1.5s 且缓冲非空 ⇒ 先 drainLive()(活体预览语义不变),再提交思考+文本段
|
|
37
|
+
* (段序铁律不破:本来就该在下一张工具卡前 flush,这里只是提前)。
|
|
38
|
+
* 🔴 这是**过渡修**,正解在 core [817](wire 侧给事件);且**需要宿主定时器**:
|
|
39
|
+
* `ctx.setTimer` 缺席 ⇒ 整条竞速不启用(纯等下一帧),与 0.4.0 逐字同行为。
|
|
40
|
+
*
|
|
41
|
+
* 公面。
|
|
42
|
+
*/
|
|
43
|
+
export declare const IDLE_FLUSH_MS = 1500;
|
|
44
|
+
/** cli SUBAGENT_TOOL_NAMES / WORKFLOW_TOOL_NAMES 同源(判别资产,别各自重写)。公面。 */
|
|
45
|
+
export declare const SUBAGENT_TOOL_NAMES: ReadonlySet<string>;
|
|
46
|
+
export declare const WORKFLOW_TOOL_NAMES: ReadonlySet<string>;
|
|
47
|
+
/** 引擎 task 族工具(ctrl+t 面板台账同步的侧信道触发名;cli handleEngineTaskToolUse 受理的三名:
|
|
48
|
+
* TodoWrite 全量表 upsert + TaskCreate/TaskUpdate;其余工具该函数直接 return)。**内部件**。 */
|
|
49
|
+
export declare const TASK_TOOL_NAMES: ReadonlySet<string>;
|
|
50
|
+
/**
|
|
51
|
+
* CC 自己的 reject/cancel 哨兵串(**数据**,非 CC 逻辑;cli src/utils/messages.ts:210-212 逐字)。
|
|
52
|
+
* CC 的 UserToolResultMessage 按 content 串前缀路由到 reject/cancel 卡,不看 is_error 位。
|
|
53
|
+
*
|
|
54
|
+
* 公面。
|
|
55
|
+
*/
|
|
56
|
+
export declare const REJECT_MESSAGE = "The user doesn't want to proceed with this tool use. The tool use was rejected (eg. if it was a file edit, the new_string was NOT written to the file). STOP what you are doing and wait for the user to tell you how to proceed.";
|
|
57
|
+
export declare const CANCEL_MESSAGE = "The user doesn't want to take this action right now. STOP what you are doing and wait for the user to tell you how to proceed.";
|
|
58
|
+
/** CJK 加权 token 估算(cli estimateCjkTokens 逐字:CJK≈0.6,其余≈0.25 tok/char)。公面。 */
|
|
59
|
+
export declare function estimateCjkTokens(s: string): number;
|
|
60
|
+
/**
|
|
61
|
+
* T8 —— 压平 §E1 wire `output`(**非均匀**:`string` | `(TextContent|ImageContent)[]`,events.d.ts:78)
|
|
62
|
+
* 成一条纯文本(cli `flattenWireOutput` 逐字)。text 块贡献 `.text`,image 块贡献中性占位 `[image]`
|
|
63
|
+
* (转录卡是文本粒度),裸字符串直通。
|
|
64
|
+
* 🔴 载荷 UNTRUSTED + 仅供观测(events.d.ts:80-85):渲染可以,**绝不回喂模型**;`truncated` 的更不行。
|
|
65
|
+
* B4 把它从 B 层(`wireOutputToBody`)提到独立导出:A 层的 `settlePanelTasks(report)` 也要用它
|
|
66
|
+
* (关卡时把子代最终报告串到面板行 end 事件上),两处必须同一份实现。
|
|
67
|
+
*
|
|
68
|
+
* 公面。
|
|
69
|
+
*/
|
|
70
|
+
export declare function flattenWireOutput(output: unknown): string;
|
|
71
|
+
/** 引擎 subagent 卡的短标签(cli shortTaskLabel 逐字)。公面。 */
|
|
72
|
+
export declare function shortTaskLabel(task: string): string;
|
|
73
|
+
/**
|
|
74
|
+
* tool_use 块的渲染面消毒(cli assistant 臂逐条搬运,**纯函数**,不改入参):
|
|
75
|
+
* ① 摘 §E2 wire 身份(eventId/parentToolCallId)并从渲染块剥掉;
|
|
76
|
+
* ② 剥所有 `_sema_*` 保留哨兵(CC 的 per-tool 渲染器 safeParse strictObject,多一个键就降级成通用卡);
|
|
77
|
+
* ③ 引擎 subagent 参数名 {agent,task,taskName} → CC 名 {subagent_type,description,prompt}
|
|
78
|
+
* (strict schema 拒绝多余键 ⇒ REPLACE 不 merge;taskName 缺席时从 task 派生短标签);
|
|
79
|
+
* ④ 件8 类型标签诚实化:引擎通道兑现不了的 subagent_type 值一律删(只留 fork/general-purpose/worker),
|
|
80
|
+
* 否则卡头会显示 `Plan(…)` 而实跑 general-purpose。
|
|
81
|
+
*
|
|
82
|
+
* 公面。
|
|
83
|
+
*/
|
|
84
|
+
export declare function sanitizeToolUseBlock(block: Record<string, unknown>): {
|
|
85
|
+
block: Record<string, unknown>;
|
|
86
|
+
rawInput: unknown;
|
|
87
|
+
eventId?: string;
|
|
88
|
+
parentToolCallId?: string;
|
|
89
|
+
label?: string;
|
|
90
|
+
};
|
|
91
|
+
/** seam 的 reserved decision 哨兵(cli decisionOf 逐字)。**内部件**;入参用具名 `Frame` 而不是
|
|
92
|
+
* 再写一遍 `Record<string, unknown>`(同一个 unknown 边界只该有一个名字)。 */
|
|
93
|
+
export declare function decisionOf(block: Frame): 'reject' | 'cancel' | 'error' | undefined;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 活体增量攒批节拍的**默认值**(时钟从 ctx.now() 取;宿主可用 `ctx.coalesceIntervalMs` 覆盖)。
|
|
3
|
+
*
|
|
4
|
+
* 取值依据(两个都是实测,别把其中一个当"唯一真相"):
|
|
5
|
+
* · **100ms** = 我们对标的 CC 2.1.207 CLI 口径(187 时代是 16ms,207 提到 100ms 降重绘频率,
|
|
6
|
+
* 长回答滚动更稳)—— 壳是 207 fork,所以库的默认值取它,壳消费本包时行为零变化;
|
|
7
|
+
* · **16ms** = CC **桌面端**宿主 `makeStreamDeltaCoalescer` 的单帧攒批节拍(设计稿 R1 实测)。
|
|
8
|
+
* ⇒ 结论:**节拍是宿主渲染策略,不是 wire 语义** —— CC 自己两个端就是两个值。web/桌面宿主
|
|
9
|
+
* 想要 16ms 就传 `coalesceIntervalMs: 16`,合并**语义**(思考先于文本、段边界重开块、
|
|
10
|
+
* committed 恒随后)在库里,一份。
|
|
11
|
+
*
|
|
12
|
+
* 🔴 顺带钉一句反面事实(R1 证伪,别再写进任何注释/文档):**"UI 从不见裸 token" 是错的** ——
|
|
13
|
+
* CC 攒批后 flush 的载荷仍是 `stream_event` 增量 delta,CC 的 UI 照样消费增量;
|
|
14
|
+
* 完整 assistant 消息是 SDK 另发的一路。我们这里的 `stream_delta` chrome 臂同构。
|
|
15
|
+
*
|
|
16
|
+
* 公面。
|
|
17
|
+
*/
|
|
18
|
+
export const FLUSH_INTERVAL_MS = 100;
|
|
19
|
+
/**
|
|
20
|
+
* T40 IDLE-FLUSH 竞速窗(cli upstreamBridge `IDLE_FLUSH_MS` 逐字同值)。
|
|
21
|
+
*
|
|
22
|
+
* 病:模型转入长工具参数生成(大 Write 的 input_json 不经本桥)时 SSE 增量停摆,而 thinking/
|
|
23
|
+
* answerSegment 里**已经生成**的内容还押着陪等(pty 确证:11s 整屏 hash 恒定)。
|
|
24
|
+
* 修:增量停 ≥1.5s 且缓冲非空 ⇒ 先 drainLive()(活体预览语义不变),再提交思考+文本段
|
|
25
|
+
* (段序铁律不破:本来就该在下一张工具卡前 flush,这里只是提前)。
|
|
26
|
+
* 🔴 这是**过渡修**,正解在 core [817](wire 侧给事件);且**需要宿主定时器**:
|
|
27
|
+
* `ctx.setTimer` 缺席 ⇒ 整条竞速不启用(纯等下一帧),与 0.4.0 逐字同行为。
|
|
28
|
+
*
|
|
29
|
+
* 公面。
|
|
30
|
+
*/
|
|
31
|
+
export const IDLE_FLUSH_MS = 1500;
|
|
32
|
+
/** cli SUBAGENT_TOOL_NAMES / WORKFLOW_TOOL_NAMES 同源(判别资产,别各自重写)。公面。 */
|
|
33
|
+
export const SUBAGENT_TOOL_NAMES = new Set(['Task', 'Agent', 'Fork']);
|
|
34
|
+
export const WORKFLOW_TOOL_NAMES = new Set(['Workflow', 'RunWorkflow', 'run_workflow']);
|
|
35
|
+
/** 引擎 task 族工具(ctrl+t 面板台账同步的侧信道触发名;cli handleEngineTaskToolUse 受理的三名:
|
|
36
|
+
* TodoWrite 全量表 upsert + TaskCreate/TaskUpdate;其余工具该函数直接 return)。**内部件**。 */
|
|
37
|
+
export const TASK_TOOL_NAMES = new Set(['TodoWrite', 'TaskCreate', 'TaskUpdate']);
|
|
38
|
+
/**
|
|
39
|
+
* CC 自己的 reject/cancel 哨兵串(**数据**,非 CC 逻辑;cli src/utils/messages.ts:210-212 逐字)。
|
|
40
|
+
* CC 的 UserToolResultMessage 按 content 串前缀路由到 reject/cancel 卡,不看 is_error 位。
|
|
41
|
+
*
|
|
42
|
+
* 公面。
|
|
43
|
+
*/
|
|
44
|
+
export const REJECT_MESSAGE = "The user doesn't want to proceed with this tool use. The tool use was rejected (eg. if it was a file edit, the new_string was NOT written to the file). STOP what you are doing and wait for the user to tell you how to proceed.";
|
|
45
|
+
export const CANCEL_MESSAGE = "The user doesn't want to take this action right now. STOP what you are doing and wait for the user to tell you how to proceed.";
|
|
46
|
+
/** CJK 加权 token 估算(cli estimateCjkTokens 逐字:CJK≈0.6,其余≈0.25 tok/char)。公面。 */
|
|
47
|
+
export function estimateCjkTokens(s) {
|
|
48
|
+
let t = 0;
|
|
49
|
+
for (const c of s) {
|
|
50
|
+
const cp = c.codePointAt(0) ?? 0;
|
|
51
|
+
t +=
|
|
52
|
+
(cp >= 0x2e80 && cp <= 0x9fff) ||
|
|
53
|
+
(cp >= 0x3000 && cp <= 0x30ff) ||
|
|
54
|
+
(cp >= 0xac00 && cp <= 0xd7a3) ||
|
|
55
|
+
(cp >= 0xf900 && cp <= 0xfaff) ||
|
|
56
|
+
(cp >= 0xff00 && cp <= 0xffef) ||
|
|
57
|
+
(cp >= 0x20000 && cp <= 0x3ffff)
|
|
58
|
+
? 0.6
|
|
59
|
+
: 0.25;
|
|
60
|
+
}
|
|
61
|
+
return Math.round(t);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* T8 —— 压平 §E1 wire `output`(**非均匀**:`string` | `(TextContent|ImageContent)[]`,events.d.ts:78)
|
|
65
|
+
* 成一条纯文本(cli `flattenWireOutput` 逐字)。text 块贡献 `.text`,image 块贡献中性占位 `[image]`
|
|
66
|
+
* (转录卡是文本粒度),裸字符串直通。
|
|
67
|
+
* 🔴 载荷 UNTRUSTED + 仅供观测(events.d.ts:80-85):渲染可以,**绝不回喂模型**;`truncated` 的更不行。
|
|
68
|
+
* B4 把它从 B 层(`wireOutputToBody`)提到独立导出:A 层的 `settlePanelTasks(report)` 也要用它
|
|
69
|
+
* (关卡时把子代最终报告串到面板行 end 事件上),两处必须同一份实现。
|
|
70
|
+
*
|
|
71
|
+
* 公面。
|
|
72
|
+
*/
|
|
73
|
+
export function flattenWireOutput(output) {
|
|
74
|
+
if (typeof output === 'string')
|
|
75
|
+
return output;
|
|
76
|
+
if (Array.isArray(output)) {
|
|
77
|
+
const parts = [];
|
|
78
|
+
for (const block of output) {
|
|
79
|
+
if (block && typeof block === 'object') {
|
|
80
|
+
const b = block;
|
|
81
|
+
if (b.type === 'text' && typeof b.text === 'string')
|
|
82
|
+
parts.push(b.text);
|
|
83
|
+
else if (b.type === 'image')
|
|
84
|
+
parts.push('[image]');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return parts.join('');
|
|
88
|
+
}
|
|
89
|
+
return '';
|
|
90
|
+
}
|
|
91
|
+
/** 引擎 subagent 卡的短标签(cli shortTaskLabel 逐字)。公面。 */
|
|
92
|
+
export function shortTaskLabel(task) {
|
|
93
|
+
const firstLine = (task.split('\n').find(l => l.trim()) ?? task).trim();
|
|
94
|
+
const words = firstLine.split(/\s+/).slice(0, 6).join(' ');
|
|
95
|
+
const label = words.length > 48 ? words.slice(0, 47) + '…' : words;
|
|
96
|
+
return label || 'subagent';
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* tool_use 块的渲染面消毒(cli assistant 臂逐条搬运,**纯函数**,不改入参):
|
|
100
|
+
* ① 摘 §E2 wire 身份(eventId/parentToolCallId)并从渲染块剥掉;
|
|
101
|
+
* ② 剥所有 `_sema_*` 保留哨兵(CC 的 per-tool 渲染器 safeParse strictObject,多一个键就降级成通用卡);
|
|
102
|
+
* ③ 引擎 subagent 参数名 {agent,task,taskName} → CC 名 {subagent_type,description,prompt}
|
|
103
|
+
* (strict schema 拒绝多余键 ⇒ REPLACE 不 merge;taskName 缺席时从 task 派生短标签);
|
|
104
|
+
* ④ 件8 类型标签诚实化:引擎通道兑现不了的 subagent_type 值一律删(只留 fork/general-purpose/worker),
|
|
105
|
+
* 否则卡头会显示 `Plan(…)` 而实跑 general-purpose。
|
|
106
|
+
*
|
|
107
|
+
* 公面。
|
|
108
|
+
*/
|
|
109
|
+
export function sanitizeToolUseBlock(block) {
|
|
110
|
+
const out = { ...block };
|
|
111
|
+
const rawInput = out.input;
|
|
112
|
+
const eventId = typeof out.eventId === 'string' ? out.eventId : undefined;
|
|
113
|
+
const parentToolCallId = typeof out.parentToolCallId === 'string' ? out.parentToolCallId : undefined;
|
|
114
|
+
// 🔴 B4 补漏(0.5.0 真缺口,差分守卫此前无 fixture 携 label ⇒ 漏得静默):core 的**展示名**
|
|
115
|
+
// `tool_start.label` 同样是侧信道,必须在渲染前摘掉 —— tool_use block 会进壳 transcript,
|
|
116
|
+
// /compact 时原样直发 provider,多一个键 = 400 invalid_request(cli 头注记的「件1 事故同款」)。
|
|
117
|
+
// 摘下来的值由调用方交给 engineToolLabelStore(纯函数不做副作用),unknown-tool 卡按
|
|
118
|
+
// toolCallId 查。今天唯一的真命中族 = MCP 远端工具(name=mcp__srv__tool / label=srv:tool)。
|
|
119
|
+
const label = typeof out.label === 'string' ? out.label : undefined;
|
|
120
|
+
delete out.label;
|
|
121
|
+
delete out.eventId;
|
|
122
|
+
delete out.parentToolCallId;
|
|
123
|
+
if (out.input && typeof out.input === 'object') {
|
|
124
|
+
const cleaned = {};
|
|
125
|
+
for (const [k, val] of Object.entries(out.input)) {
|
|
126
|
+
if (!k.startsWith('_sema_'))
|
|
127
|
+
cleaned[k] = val;
|
|
128
|
+
}
|
|
129
|
+
out.input = cleaned;
|
|
130
|
+
}
|
|
131
|
+
if (out.input && typeof out.input === 'object') {
|
|
132
|
+
const inp = out.input;
|
|
133
|
+
const looksEngineSubagent = typeof inp.task === 'string' && inp.prompt === undefined && inp.description === undefined;
|
|
134
|
+
if (looksEngineSubagent) {
|
|
135
|
+
const task = inp.task;
|
|
136
|
+
const taskName = typeof inp.taskName === 'string' ? inp.taskName.trim() : '';
|
|
137
|
+
const label = taskName || shortTaskLabel(task);
|
|
138
|
+
const remapped = { description: label, prompt: task };
|
|
139
|
+
if (typeof inp.agent === 'string')
|
|
140
|
+
remapped.subagent_type = inp.agent;
|
|
141
|
+
if (typeof inp.model === 'string')
|
|
142
|
+
remapped.model = inp.model;
|
|
143
|
+
out.input = remapped;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (SUBAGENT_TOOL_NAMES.has(out.name) && out.input && typeof out.input === 'object') {
|
|
147
|
+
const inp = out.input;
|
|
148
|
+
if (typeof inp.subagent_type === 'string' &&
|
|
149
|
+
!['fork', 'general-purpose', 'worker'].includes(inp.subagent_type)) {
|
|
150
|
+
delete inp.subagent_type;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
block: out,
|
|
155
|
+
rawInput,
|
|
156
|
+
...(eventId !== undefined ? { eventId } : {}),
|
|
157
|
+
...(parentToolCallId !== undefined ? { parentToolCallId } : {}),
|
|
158
|
+
...(label !== undefined ? { label } : {}),
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
/** seam 的 reserved decision 哨兵(cli decisionOf 逐字)。**内部件**;入参用具名 `Frame` 而不是
|
|
162
|
+
* 再写一遍 `Record<string, unknown>`(同一个 unknown 边界只该有一个名字)。 */
|
|
163
|
+
export function decisionOf(block) {
|
|
164
|
+
const input = block.input;
|
|
165
|
+
const d = input?._sema_decision;
|
|
166
|
+
return d === 'reject' || d === 'cancel' || d === 'error' ? d : undefined;
|
|
167
|
+
}
|
package/dist/adapt.d.ts
CHANGED
|
@@ -1,69 +1,42 @@
|
|
|
1
|
-
import type { AdapterContext, AdapterOutput, WireToCcAdapter } from './seam.js';
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
2
|
+
* adapt.ts — L3 适配管线首批落码(#52a,2026-07-25)。
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
4
|
+
* 真源 = sema-cli `src/sema/upstreamBridge.ts` 的 `sdkMessagesToCcEvents`(~1500 行 generator,
|
|
5
|
+
* 几十批 bug 修的结晶)。本文件把其中**纯投影**的臂搬成与宿主无关的双平面产出:
|
|
6
|
+
* · transcript 平面 = 重启后还该看得见的(committed assistant 文本/思考、tool_use 卡、
|
|
7
|
+
* task-notification user turn、compact 分界),载体 = CC `SDKMessage` 词汇;
|
|
8
|
+
* · chrome 平面 = 纯瞬态 + 宿主副作用(活体增量、spinner 计量、attachment 行、面板/队列/hook
|
|
9
|
+
* 记账),载体 = `ChromeEvent`(每臂的宿主消费义务写在 seam.ts 臂注释里)。
|
|
10
|
+
* 判据成文见 seam.ts 头注([1652]);id 一律走 `deriveTranscriptId`([1653] 不变量:同流重放
|
|
11
|
+
* ⇒ 同 id 序列),**零 Math.random / 零 Date.now**——时钟与铸号全从 `AdapterContext` 注入。
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* 完整 assistant 消息是 SDK 另发的一路。我们这里的 `stream_delta` chrome 臂同构。
|
|
16
|
-
*/
|
|
17
|
-
export declare const FLUSH_INTERVAL_MS = 100;
|
|
18
|
-
/**
|
|
19
|
-
* T40 IDLE-FLUSH 竞速窗(cli upstreamBridge `IDLE_FLUSH_MS` 逐字同值)。
|
|
13
|
+
* ⚠️ 本批**故意只做一半**(cli 迁移消费 = #52b)。未覆盖臂见 `ADAPTER_COVERAGE.todo`,差分守卫
|
|
14
|
+
* (scripts/run-client-core-diff-test.mjs)把「cli 有、adapt 无」的清单钉死,防止悄悄漏臂。
|
|
20
15
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
*
|
|
34
|
-
*
|
|
16
|
+
* ── A 族拆分后的地图(REF-CC-SPLIT-01~05 / FIX-05,2026-08-02;设计=docs/refactor/ADAPT-RW-MATRIX.md)
|
|
17
|
+
* `adapt()` 曾是 1139 行单方法(26 个 turn 级可变量 + 14 个闭包 + 15 个 case)。现在:
|
|
18
|
+
* 本文件 = 公面契约表 + 适配器实例(台账)+ **驱动壳**(迭代器竞速 / abort / finally / 收口三形)
|
|
19
|
+
* adapt/ids.ts 零状态共用件(双平面包装、Frame、MAIN、id 派生工厂)
|
|
20
|
+
* adapt/wireShapes.ts 帧形词表 + 纯投影助手(公面十件由本文件具名再导出)
|
|
21
|
+
* adapt/textStream.ts M1 流合并器(矩阵 §1.1 十二行状态 + 竞速/节拍两处判据)
|
|
22
|
+
* adapt/toolCards.ts M2 工具卡台账(§1.2 三行;S1 复位收进 close() 第一个 yield 前)
|
|
23
|
+
* adapt/panelTasks.ts M3 面板行台账(§1.3 六行;通知臂那半场收成 settleFromNotification)
|
|
24
|
+
* adapt/turnFlags.ts M6a 响应度量 + M6b 重试覆盖层(两个小状态机,两半必须同文件)
|
|
25
|
+
* adapt/instanceLedger.ts 三个实例级 Set(FIX-05:消 self/this 双路径)
|
|
26
|
+
* adapt/arms.ts 15 条帧臂的注册表(Map,不是对象 —— `{type:'__proto__'}` 会污染原型)
|
|
27
|
+
* 🔴 最高不变量(拆分不许动):**段序铁律**(活体增量 → 思考 committed → 文本段 committed → 工具卡)
|
|
28
|
+
* 与**重放确定性**(同流同 id)。收口三形(result 臂 / abort 尾 / T60 尾)**次序不同**,
|
|
29
|
+
* 逐格差异见矩阵 §2.4,pure 门 SPLIT 段钉②/钉③ 把它们钉住了 —— 别归一。
|
|
35
30
|
*/
|
|
36
|
-
|
|
37
|
-
export declare const CANCEL_MESSAGE = "The user doesn't want to take this action right now. STOP what you are doing and wait for the user to tell you how to proceed.";
|
|
38
|
-
/** CJK 加权 token 估算(cli estimateCjkTokens 逐字:CJK≈0.6,其余≈0.25 tok/char)。 */
|
|
39
|
-
export declare function estimateCjkTokens(s: string): number;
|
|
40
|
-
/** 引擎 subagent 卡的短标签(cli shortTaskLabel 逐字)。 */
|
|
41
|
-
/**
|
|
42
|
-
* T8 —— 压平 §E1 wire `output`(**非均匀**:`string` | `(TextContent|ImageContent)[]`,events.d.ts:78)
|
|
43
|
-
* 成一条纯文本(cli `flattenWireOutput` 逐字)。text 块贡献 `.text`,image 块贡献中性占位 `[image]`
|
|
44
|
-
* (转录卡是文本粒度),裸字符串直通。
|
|
45
|
-
* 🔴 载荷 UNTRUSTED + 仅供观测(events.d.ts:80-85):渲染可以,**绝不回喂模型**;`truncated` 的更不行。
|
|
46
|
-
* B4 把它从 B 层(`wireOutputToBody`)提到独立导出:A 层的 `settlePanelTasks(report)` 也要用它
|
|
47
|
-
* (关卡时把子代最终报告串到面板行 end 事件上),两处必须同一份实现。
|
|
48
|
-
*/
|
|
49
|
-
export declare function flattenWireOutput(output: unknown): string;
|
|
50
|
-
export declare function shortTaskLabel(task: string): string;
|
|
31
|
+
import type { AdapterContext, AdapterOutput, WireToCcAdapter } from './seam.js';
|
|
51
32
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* ④ 件8 类型标签诚实化:引擎通道兑现不了的 subagent_type 值一律删(只留 fork/general-purpose/worker),
|
|
58
|
-
* 否则卡头会显示 `Plan(…)` 而实跑 general-purpose。
|
|
33
|
+
* ── A 族拆分(REF-CC-SPLIT-01,2026-08-02)—— 帧形词表与双平面共用件已落 `src/adapt/` ─────────
|
|
34
|
+
* 本文件从此只留:公面契约表(coverage/divergences/ledger 形)+ 适配器实例(台账)+ **驱动壳**。
|
|
35
|
+
* 词表与纯助手在 `adapt/wireShapes.ts`,双平面包装与 id 派生在 `adapt/ids.ts`。
|
|
36
|
+
* 🔴 公面用**具名再导出**(不是 `export *`):`TASK_TOOL_NAMES` / `decisionOf` 是内部件,
|
|
37
|
+
* `export *` 会把它们推上 npm 公面,public-export-baseline 双向门当场红。
|
|
59
38
|
*/
|
|
60
|
-
export
|
|
61
|
-
block: Record<string, unknown>;
|
|
62
|
-
rawInput: unknown;
|
|
63
|
-
eventId?: string;
|
|
64
|
-
parentToolCallId?: string;
|
|
65
|
-
label?: string;
|
|
66
|
-
};
|
|
39
|
+
export { CANCEL_MESSAGE, estimateCjkTokens, flattenWireOutput, FLUSH_INTERVAL_MS, IDLE_FLUSH_MS, REJECT_MESSAGE, sanitizeToolUseBlock, shortTaskLabel, SUBAGENT_TOOL_NAMES, WORKFLOW_TOOL_NAMES, } from './adapt/wireShapes.js';
|
|
67
40
|
/** 台账序列化形(#63 回植:重启恢复 = 台账加载 + 纯重放)。 */
|
|
68
41
|
export interface AdapterLedgerState {
|
|
69
42
|
version: 1;
|