@sema-agent/client-core 0.75.1 → 0.76.1
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 +53 -0
- package/README.md +11 -1
- package/dist/adapt/arms.js +137 -35
- package/dist/adapt/ids.d.ts +29 -2
- package/dist/adapt/ids.js +29 -2
- package/dist/adapt/panelTasks.d.ts +4 -3
- package/dist/adapt/panelTasks.js +29 -11
- package/dist/adapt/textStream.js +5 -5
- package/dist/adapt/toolCards.js +2 -2
- package/dist/adapt/turnFlags.js +5 -5
- package/dist/adapt.d.ts +1 -1
- package/dist/adapt.js +8 -8
- package/dist/adapter/downstream/eventToSdkMessage.d.ts +57 -0
- package/dist/adapter/downstream/eventToSdkMessage.js +125 -17
- package/dist/adapter/runStream.js +14 -5
- package/dist/adapter/types.d.ts +12 -0
- package/dist/adapter/types.js +30 -0
- package/dist/agentsWireCaps.d.ts +15 -2
- package/dist/approvalsStreamLiveCapability.js +15 -35
- package/dist/deviceExecutorManagementCapability.js +15 -35
- package/dist/engineAgentPanelStore.js +13 -1
- package/dist/engineCapReader.d.ts +77 -0
- package/dist/engineCapReader.js +87 -0
- package/dist/engineErrorCodes.d.ts +4 -0
- package/dist/engineErrorCodes.js +14 -0
- package/dist/executionLaneCapability.js +15 -38
- package/dist/fleet/fleetRowAgentType.js +1 -1
- package/dist/hitl/approvalOutcomeNote.d.ts +0 -10
- package/dist/hitl/approvalOutcomeNote.js +35 -8
- package/dist/hitl/approvalResolution.d.ts +148 -0
- package/dist/hitl/approvalResolution.js +199 -0
- package/dist/hitl/approvalsFeed.d.ts +100 -2
- package/dist/hitl/approvalsFeed.js +234 -18
- package/dist/hitl/livePendingAsk.d.ts +26 -6
- package/dist/hitl/livePendingAsk.js +52 -12
- package/dist/hitl/persistedRulesWire.d.ts +20 -0
- package/dist/hitl/persistedRulesWire.js +23 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +25 -1
- package/dist/mcpLiveness.d.ts +179 -0
- package/dist/mcpLiveness.js +218 -0
- package/dist/mcpPanel.d.ts +17 -0
- package/dist/mcpPanel.js +21 -0
- package/dist/mcpProbeCapability.d.ts +84 -0
- package/dist/mcpProbeCapability.js +124 -0
- package/dist/memoryComplianceCapability.d.ts +73 -0
- package/dist/memoryComplianceCapability.js +109 -0
- package/dist/memoryEntriesWire.d.ts +302 -0
- package/dist/memoryEntriesWire.js +595 -0
- package/dist/memoryOriginCapability.d.ts +68 -0
- package/dist/memoryOriginCapability.js +102 -0
- package/dist/memorySpecWire.d.ts +175 -0
- package/dist/memorySpecWire.js +320 -0
- package/dist/peerLaneCapability.d.ts +62 -0
- package/dist/peerLaneCapability.js +100 -0
- package/dist/permissionRulesWriteCapability.d.ts +64 -0
- package/dist/permissionRulesWriteCapability.js +98 -0
- package/dist/seam.d.ts +53 -5
- package/dist/seam.js +10 -1
- package/dist/selfOrchestrationDenial.js +7 -2
- package/dist/sqlEngineCapability.js +15 -35
- package/dist/webSearchBackendCapability.js +15 -35
- package/dist/writeProtectionCapability.js +15 -35
- package/docs/INTEGRATION-CLIENTS.md +148 -15
- package/package.json +1 -1
package/dist/adapt/arms.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isSubFlowSegmentEnd } from '../adapter/types.js';
|
|
1
|
+
import { isSubFlowSegmentEnd, SEGMENT_END_IDENTITY_KEYS, snapshotSegmentIdentity, snapshotIsSubFlow } from '../adapter/types.js';
|
|
2
2
|
import { classifyPeerNotification, renderPeerFrameTranscriptText } from '../peerFrames.js';
|
|
3
3
|
import { dropQueuedNotificationsForRun, isEngineWorkflowNotified, isWorkflowCompletionCardEnqueued, markEngineWorkflowNotified, noteOwnWorkflowRun, normalizeTaskNotification, noteWorkflowCompletionCardEnqueued, renderTaskNotificationXml, taskNotificationDedupKey } from '../notifications.js';
|
|
4
4
|
import { mapBrainStatusToRetry } from '../retryStatus.js';
|
|
@@ -13,7 +13,7 @@ import { isTerminalStatus } from '../runTerminal.js';
|
|
|
13
13
|
import { resolveEnginePanelTaskId } from '../engineAgentPanelStore.js';
|
|
14
14
|
// 0.75.1 CC-95(b):子代类型的诚实来源台账(fleet 行帧折进 name 之前留的那一份;包内叶)。
|
|
15
15
|
import { fleetRowAgentType } from '../fleet/fleetRowAgentType.js';
|
|
16
|
-
import { chrome,
|
|
16
|
+
import { chrome, mainLane, transcript, messageIdentityOf } from './ids.js';
|
|
17
17
|
import { CANCEL_MESSAGE, decisionOf, flattenWireOutput, REJECT_MESSAGE, sanitizeToolUseBlock, shortTaskLabel, TASK_TOOL_NAMES, WORKFLOW_TOOL_NAMES, } from './wireShapes.js';
|
|
18
18
|
// ══ M2/M1 —— assistant(tool_use 半场 + durable 文本/思考半场)══════════════════════════════════
|
|
19
19
|
const assistantArm = function* (m, { ctx, idOf, text, cards, inst }) {
|
|
@@ -53,7 +53,7 @@ const assistantArm = function* (m, { ctx, idOf, text, cards, inst }) {
|
|
|
53
53
|
if (TASK_TOOL_NAMES.has(toolName)) {
|
|
54
54
|
yield chrome({
|
|
55
55
|
kind: 'task_ledger_sync',
|
|
56
|
-
laneProof:
|
|
56
|
+
laneProof: mainLane(),
|
|
57
57
|
source: 'tool_use',
|
|
58
58
|
toolName,
|
|
59
59
|
toolUseId,
|
|
@@ -190,7 +190,7 @@ const systemArm = function* (m, { ctx, idOf }) {
|
|
|
190
190
|
continue;
|
|
191
191
|
yield chrome({
|
|
192
192
|
kind: 'attachment',
|
|
193
|
-
laneProof:
|
|
193
|
+
laneProof: mainLane(),
|
|
194
194
|
id: idOf(m, `attached-file-${i++}`),
|
|
195
195
|
attachment: {
|
|
196
196
|
type: 'compact_file_reference',
|
|
@@ -207,7 +207,7 @@ const diagnosticsArm = function* (m, { idOf }) {
|
|
|
207
207
|
const att = projectDiagnosticsFrame(m);
|
|
208
208
|
if (att === null)
|
|
209
209
|
return;
|
|
210
|
-
yield chrome({ kind: 'attachment', laneProof:
|
|
210
|
+
yield chrome({ kind: 'attachment', laneProof: mainLane(), id: idOf(m), attachment: att });
|
|
211
211
|
};
|
|
212
212
|
const steeringInjectedArm = function* (m, { idOf }) {
|
|
213
213
|
if (typeof m.parentToolCallId === 'string')
|
|
@@ -220,7 +220,7 @@ const steeringInjectedArm = function* (m, { idOf }) {
|
|
|
220
220
|
for (const att of steeringInjectedToAttachments(source, preview)) {
|
|
221
221
|
yield chrome({
|
|
222
222
|
kind: 'attachment',
|
|
223
|
-
laneProof:
|
|
223
|
+
laneProof: mainLane(),
|
|
224
224
|
id: idOf(m, `steering-${i++}`),
|
|
225
225
|
attachment: att,
|
|
226
226
|
});
|
|
@@ -234,7 +234,7 @@ const workspaceChangedArm = function* (m, { idOf }) {
|
|
|
234
234
|
return;
|
|
235
235
|
yield chrome({
|
|
236
236
|
kind: 'attachment',
|
|
237
|
-
laneProof:
|
|
237
|
+
laneProof: mainLane(),
|
|
238
238
|
id: idOf(m),
|
|
239
239
|
attachment: { type: 'workspace_changed', cwd },
|
|
240
240
|
});
|
|
@@ -267,7 +267,7 @@ const humanInputArm = function* (m) {
|
|
|
267
267
|
};
|
|
268
268
|
yield chrome({
|
|
269
269
|
kind: 'human_input',
|
|
270
|
-
laneProof:
|
|
270
|
+
laneProof: mainLane(),
|
|
271
271
|
carrier,
|
|
272
272
|
...(str(m.inputId) !== undefined ? { inputId: str(m.inputId) } : {}),
|
|
273
273
|
...(typeof m.sessionSeq === 'number' && Number.isFinite(m.sessionSeq) ? { sessionSeq: m.sessionSeq } : {}),
|
|
@@ -301,7 +301,7 @@ const messageCommittedArm = function* (m) {
|
|
|
301
301
|
return;
|
|
302
302
|
yield chrome({
|
|
303
303
|
kind: 'message_committed',
|
|
304
|
-
laneProof:
|
|
304
|
+
laneProof: mainLane(),
|
|
305
305
|
entryId,
|
|
306
306
|
role,
|
|
307
307
|
...(typeof m.toolCallId === 'string' && m.toolCallId.length > 0 ? { toolCallId: m.toolCallId } : {}),
|
|
@@ -336,7 +336,7 @@ const engineNoticeArm = function* (m) {
|
|
|
336
336
|
: {};
|
|
337
337
|
yield chrome({
|
|
338
338
|
kind: 'engine_notice',
|
|
339
|
-
laneProof:
|
|
339
|
+
laneProof: mainLane(),
|
|
340
340
|
code,
|
|
341
341
|
message: typeof m.message === 'string' ? m.message : '',
|
|
342
342
|
detail,
|
|
@@ -392,7 +392,7 @@ const wiringManifestArm = function* (m) {
|
|
|
392
392
|
return;
|
|
393
393
|
yield chrome({
|
|
394
394
|
kind: 'wiring_manifest',
|
|
395
|
-
laneProof:
|
|
395
|
+
laneProof: mainLane(),
|
|
396
396
|
...(hasGate ? { modelGate: modelGate } : {}),
|
|
397
397
|
...(hasAuto ? { autoMode: autoMode } : {}),
|
|
398
398
|
...(hasMcp ? { mcp: mcp } : {}),
|
|
@@ -428,7 +428,7 @@ const approvalFrameArm = (kind) => function* (m) {
|
|
|
428
428
|
const frame = m.frame;
|
|
429
429
|
if (typeof frame !== 'object' || frame === null)
|
|
430
430
|
return;
|
|
431
|
-
yield chrome({ kind, laneProof:
|
|
431
|
+
yield chrome({ kind, laneProof: mainLane(), frame, schemaVersion });
|
|
432
432
|
};
|
|
433
433
|
/**
|
|
434
434
|
* `text_end` 内部臂 → **权威段替换** + chrome `text_segment_end`(#323 / core #447;L-310,
|
|
@@ -485,7 +485,7 @@ const toolDisclosureArm = function* (m) {
|
|
|
485
485
|
return; // 二道判:非投影口喂进来的帧
|
|
486
486
|
yield chrome({
|
|
487
487
|
kind: 'tool_disclosure',
|
|
488
|
-
laneProof:
|
|
488
|
+
laneProof: mainLane(),
|
|
489
489
|
policy,
|
|
490
490
|
...(typeof m.thresholdPercent === 'number' ? { thresholdPercent: m.thresholdPercent } : {}),
|
|
491
491
|
deferred,
|
|
@@ -508,7 +508,7 @@ const toolProgressArm = function* (m) {
|
|
|
508
508
|
const output = typeof m.output === 'string' ? m.output : undefined;
|
|
509
509
|
yield chrome({
|
|
510
510
|
kind: 'tool_progress',
|
|
511
|
-
laneProof:
|
|
511
|
+
laneProof: mainLane(),
|
|
512
512
|
toolCallId,
|
|
513
513
|
toolName,
|
|
514
514
|
...(typeof m.elapsedTimeSeconds === 'number' ? { elapsedSeconds: m.elapsedTimeSeconds } : {}),
|
|
@@ -530,7 +530,7 @@ const toolRosterDeltaArm = function* (m) {
|
|
|
530
530
|
return;
|
|
531
531
|
yield chrome({
|
|
532
532
|
kind: 'tool_roster_delta',
|
|
533
|
-
laneProof:
|
|
533
|
+
laneProof: mainLane(),
|
|
534
534
|
delta: delta,
|
|
535
535
|
...(typeof m.eventId === 'string' && m.eventId.length > 0 ? { eventId: m.eventId } : {}),
|
|
536
536
|
});
|
|
@@ -551,7 +551,7 @@ const contextUsageArm = function* (m) {
|
|
|
551
551
|
return;
|
|
552
552
|
yield chrome({
|
|
553
553
|
kind: 'context_usage',
|
|
554
|
-
laneProof:
|
|
554
|
+
laneProof: mainLane(),
|
|
555
555
|
...(usedTokens !== undefined ? { usedTokens } : {}),
|
|
556
556
|
...(windowTokens !== undefined ? { windowTokens } : {}),
|
|
557
557
|
...(compactAtTokens !== undefined ? { compactAtTokens } : {}),
|
|
@@ -569,16 +569,21 @@ const compactionOutcomeArm = function* (m) {
|
|
|
569
569
|
const outcome = str(m.outcome);
|
|
570
570
|
if (outcome === undefined)
|
|
571
571
|
return;
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
572
|
+
// 🔴 身份四键一次性快照(0.76.1;外部验收方对 0.76.0 的 F1):修前先 isSubFlowSegmentEnd(m) 再 str(m.parentToolCallId),
|
|
573
|
+
// parentToolCallId 读了两次 ⇒ 值随读变的帧让直喂入口丢事件、经投影却出 subagent chrome —— 两入口分叉。
|
|
574
|
+
const idSnap = snapshotSegmentIdentity(m);
|
|
575
|
+
if (idSnap === null)
|
|
576
|
+
return; // 读身份就抛 ⇒ 整帧拒(与投影口判 malformed 同一处置,不发 chrome)
|
|
577
|
+
let laneProof = mainLane();
|
|
578
|
+
if (snapshotIsSubFlow(idSnap)) {
|
|
579
|
+
const parent = str(idSnap.parentToolCallId);
|
|
575
580
|
if (parent === undefined)
|
|
576
581
|
return;
|
|
577
582
|
laneProof = { lane: 'subagent', parentToolCallId: parent };
|
|
578
583
|
}
|
|
579
584
|
const trigger = str(m.trigger);
|
|
580
585
|
const reason = str(m.reason);
|
|
581
|
-
const eventId = str(
|
|
586
|
+
const eventId = str(idSnap.eventId);
|
|
582
587
|
yield chrome({
|
|
583
588
|
kind: 'compaction_outcome',
|
|
584
589
|
laneProof,
|
|
@@ -588,6 +593,94 @@ const compactionOutcomeArm = function* (m) {
|
|
|
588
593
|
...(eventId !== undefined ? { eventId } : {}),
|
|
589
594
|
});
|
|
590
595
|
};
|
|
596
|
+
/**
|
|
597
|
+
* CC-91(0.76.0):逐行**重建**白名单行(不是 `Array.isArray` 就整只透传)——
|
|
598
|
+
* 🔴 本臂与投影口是**两个入口**:宿主自建管线 / 重放存量转录可以绕过投影口直接把 wire 帧喂进 `adapt()`,
|
|
599
|
+
* 那条路上未校验的行会把本臂对外承诺的四条(零 `tokens`、零 digest 过境、`chars` 有限非负、全坏即缺席)
|
|
600
|
+
* 一起破掉,还可能把违反公开型的行(`null` / `chars: -1`)递到消费端手里
|
|
601
|
+
* (异源对抗复审 R1 [medium] 实测可复现:`sections:[{id:'x',chars:-1,tokens:123,contentHash:'…'}]` 原样进 chrome)。
|
|
602
|
+
* ⇒ 与投影口**同律同形**:好行留、坏行逐条丢、全丢光或非数组 ⇒ 键缺席(不铸 `[]`)。
|
|
603
|
+
* 两处实现由门逐字对拍(同一帧走投影口 vs 直喂 adapt,chrome 行必须一模一样),drift 即红。
|
|
604
|
+
*/
|
|
605
|
+
const promptManifestRows = (v, pick) => {
|
|
606
|
+
if (!Array.isArray(v))
|
|
607
|
+
return undefined;
|
|
608
|
+
const rows = [];
|
|
609
|
+
for (const r of v) {
|
|
610
|
+
if (typeof r !== 'object' || r === null || Array.isArray(r))
|
|
611
|
+
continue;
|
|
612
|
+
const row = pick(r);
|
|
613
|
+
if (row !== undefined)
|
|
614
|
+
rows.push(row);
|
|
615
|
+
}
|
|
616
|
+
return rows.length > 0 ? rows : undefined;
|
|
617
|
+
};
|
|
618
|
+
/**
|
|
619
|
+
* CC-91(0.76.0):`prompt_assembled` 内部臂 → chrome `prompt_assembled`。每帧一条;转录面零行。
|
|
620
|
+
* 🔴 **包不去重**:一次任务的每一次 prepare(cascade / verify 的每一 rung、resume 腿)各自一条,server 逐条保序落账 ⇒
|
|
621
|
+
* 每条都交出去,「只要最后一次」是**宿主**的动作(与 `context_usage` 同律;在包内按最后一条折会把先前已计费 rung 的组成面抹掉)。
|
|
622
|
+
* ⚠️ 上游那条流的**重放去重**是另一件事,按 `eventSeq` 在 `adapter/runStream.ts` 做;本臂只说「同一条流上的多条 prepare 都算真事实」。
|
|
623
|
+
* 🔴 lane 如实:`parentToolCallId` 非空串 ⇒ subagent;只有 `sourceTaskId` / `bgAgentId`(或父键空串)的帧没有诚实的 lane 可挂 ⇒ 不发,
|
|
624
|
+
* 绝不落到主会话名下。一条组成面的键都读不出的帧不发(非投影口喂进来的坏帧兜底)。
|
|
625
|
+
* 🔴 **零 tokens 铸点**:本臂只搬 `chars`(上游真字节无 token 位),不在这一层编任何 token 数。
|
|
626
|
+
*/
|
|
627
|
+
const promptAssembledArm = function* (m) {
|
|
628
|
+
const str = (v) => (typeof v === 'string' && v.length > 0 ? v : undefined);
|
|
629
|
+
const size = (v) => (typeof v === 'number' && Number.isFinite(v) && v >= 0 ? v : undefined);
|
|
630
|
+
// ⚠️ 帧上的 `constitution` 刻意不过境(投影口头注写明理由:今天零消费场景,键即契约)。
|
|
631
|
+
const totalChars = size(m.totalChars);
|
|
632
|
+
const blocks = promptManifestRows(m.blocks, (o) => {
|
|
633
|
+
const id = str(o.id);
|
|
634
|
+
const chars = size(o.chars);
|
|
635
|
+
return id === undefined || chars === undefined ? undefined : { id, chars };
|
|
636
|
+
});
|
|
637
|
+
const sections = promptManifestRows(m.sections, (o) => {
|
|
638
|
+
const id = str(o.id);
|
|
639
|
+
const chars = size(o.chars);
|
|
640
|
+
if (id === undefined || chars === undefined)
|
|
641
|
+
return undefined;
|
|
642
|
+
// 🔴 语义槽在**两个入口上都只认一个键名** `slot`(上游的名字,本层不改名):投影口产物与 wire 原形同名,
|
|
643
|
+
// 所以两条路读的是同一个位。曾经的写法是「`kind` 优先、回退 `slot`」—— 那会让一条**同时**带
|
|
644
|
+
// `kind` 与 `slot`(或只带 `kind`)的帧在两条路上读出不同的槽,而这种帧是合法的(上游行是开集)。
|
|
645
|
+
const slot = str(o.slot);
|
|
646
|
+
return { id, chars, ...(slot !== undefined ? { slot } : {}) };
|
|
647
|
+
});
|
|
648
|
+
const tools = promptManifestRows(m.tools, (o) => {
|
|
649
|
+
const wireName = str(o.wireName);
|
|
650
|
+
return wireName === undefined ? undefined : { wireName };
|
|
651
|
+
});
|
|
652
|
+
if (totalChars === undefined && blocks === undefined && sections === undefined && tools === undefined)
|
|
653
|
+
return;
|
|
654
|
+
// 🔴 身份四键**一次性快照**,与投影口的 `identitySnapshot` / `identityOrMalformed` 同律(每键只读一次、抛错整帧拒):
|
|
655
|
+
// ① 三个子流键**逐个**过形门(在场即必须是串)—— 只守 `parentToolCallId` 的话,一条
|
|
656
|
+
// `{parentToolCallId:'tc-9', sourceTaskId: 7}` 会在投影口被整帧判坏、在直喂这条路上照发一条 subagent chrome;
|
|
657
|
+
// ② **不能就地多读**:进程内帧可以带 accessor,同一个键读两次拿到两个值时,「形门读一次、子流判定再读一次、
|
|
658
|
+
// 取 parent 又读一次」会让同一帧在两条路上归属不同 lane —— 子代的组成信息被洗成主会话的
|
|
659
|
+
// (第三轮复审 [medium] 实测可复现)。所以这里**不**用 `isSubFlowSegmentEnd(m)`(它会再读一遍),
|
|
660
|
+
// 子流判定直接看快照里「三键有没有在场」,语义与它逐字同(键在场 = 子代帧,空串也算在场)。
|
|
661
|
+
const idSnap = snapshotSegmentIdentity(m);
|
|
662
|
+
if (idSnap === null)
|
|
663
|
+
return; // 读身份就抛 ⇒ 整帧拒(理由见 snapshotSegmentIdentity 头注与本臂上方的说明)
|
|
664
|
+
if (SEGMENT_END_IDENTITY_KEYS.some((k) => idSnap[k] !== undefined && typeof idSnap[k] !== 'string'))
|
|
665
|
+
return;
|
|
666
|
+
let laneProof = mainLane();
|
|
667
|
+
if (SEGMENT_END_IDENTITY_KEYS.some((k) => idSnap[k] !== undefined)) {
|
|
668
|
+
const parent = str(idSnap.parentToolCallId);
|
|
669
|
+
if (parent === undefined)
|
|
670
|
+
return;
|
|
671
|
+
laneProof = { lane: 'subagent', parentToolCallId: parent };
|
|
672
|
+
}
|
|
673
|
+
const eventId = str(idSnap.eventId);
|
|
674
|
+
yield chrome({
|
|
675
|
+
kind: 'prompt_assembled',
|
|
676
|
+
laneProof,
|
|
677
|
+
...(totalChars !== undefined ? { totalChars } : {}),
|
|
678
|
+
...(blocks !== undefined ? { blocks } : {}),
|
|
679
|
+
...(sections !== undefined ? { sections } : {}),
|
|
680
|
+
...(tools !== undefined ? { tools } : {}),
|
|
681
|
+
...(eventId !== undefined ? { eventId } : {}),
|
|
682
|
+
});
|
|
683
|
+
};
|
|
591
684
|
const textSegmentEndArm = function* (m, { text }) {
|
|
592
685
|
// 🔴 断闸按「**键在不在**」判,不按「是不是串」判(异源对抗复审第三轮 [medium] 采纳)。
|
|
593
686
|
// 投影层已对坏 lane 位整帧 fail-closed;这一道是给**非投影口**喂进来的帧(宿主自建管线 /
|
|
@@ -606,7 +699,7 @@ const textSegmentEndArm = function* (m, { text }) {
|
|
|
606
699
|
const r = text.replaceAnswerSegment(content, m);
|
|
607
700
|
yield chrome({
|
|
608
701
|
kind: 'text_segment_end',
|
|
609
|
-
laneProof:
|
|
702
|
+
laneProof: mainLane(),
|
|
610
703
|
content,
|
|
611
704
|
// CC-01:帧上带的是**轮换前**的段身份 —— 与本段已过境的 committed 行同值(归属的第二把钥匙)。
|
|
612
705
|
segmentId: text.segmentId(),
|
|
@@ -638,7 +731,7 @@ const thinkingSegmentEndArm = function* (m, { text }) {
|
|
|
638
731
|
const r = text.replaceThinkingSegment(content, m);
|
|
639
732
|
yield chrome({
|
|
640
733
|
kind: 'thinking_segment_end',
|
|
641
|
-
laneProof:
|
|
734
|
+
laneProof: mainLane(),
|
|
642
735
|
content,
|
|
643
736
|
...(r.diverged ? { diverged: true } : {}),
|
|
644
737
|
...(r.committedPrefixDiverged ? { committedPrefixDiverged: true } : {}),
|
|
@@ -659,7 +752,7 @@ const promptSuggestionsArm = function* (m) {
|
|
|
659
752
|
// 空批不发(cli 同门:`if (list.length > 0)`)—— 作废由 turn 开场那一发负责,
|
|
660
753
|
// 这里再发一次 null 会把本轮真产出的建议在极端交错下擦掉。
|
|
661
754
|
if (list.length > 0) {
|
|
662
|
-
yield chrome({ kind: 'prompt_suggestions', laneProof:
|
|
755
|
+
yield chrome({ kind: 'prompt_suggestions', laneProof: mainLane(), suggestions: list });
|
|
663
756
|
}
|
|
664
757
|
};
|
|
665
758
|
// ══ M2 —— tool_end_result(关卡 + B/D/E 层卡本体 + 两个侧产物)══════════════════════════════════
|
|
@@ -705,14 +798,19 @@ const toolEndResultArm = function* (m, { ctx, idOf, cards, panel }) {
|
|
|
705
798
|
if (p === undefined || callId === undefined)
|
|
706
799
|
return;
|
|
707
800
|
const structured = m.structured;
|
|
801
|
+
// 身份键各读一次(0.76.1:此前 typeof 再取值 = 读两次;值随读变的帧会让判形与取值各看一份)。
|
|
802
|
+
const closeEventIdRaw = m.eventId;
|
|
803
|
+
const closeParentRaw = m.parentToolCallId;
|
|
804
|
+
const closeEventId = typeof closeEventIdRaw === 'string' ? closeEventIdRaw : undefined;
|
|
805
|
+
const closeParent = typeof closeParentRaw === 'string' ? closeParentRaw : undefined;
|
|
708
806
|
// 出栈 + S1 复位(**yield 之前**)已收进 close() —— 见 toolCards.ts 的拆分硬约束。
|
|
709
807
|
yield* cards.close(p, {
|
|
710
808
|
output: m.output,
|
|
711
809
|
structured,
|
|
712
810
|
truncated: m.truncated === true,
|
|
713
811
|
isError: m.isError === true,
|
|
714
|
-
eventId:
|
|
715
|
-
parentToolCallId:
|
|
812
|
+
eventId: closeEventId,
|
|
813
|
+
parentToolCallId: closeParent,
|
|
716
814
|
});
|
|
717
815
|
const s = structured !== undefined && structured !== null && typeof structured === 'object'
|
|
718
816
|
? structured
|
|
@@ -740,7 +838,7 @@ const toolEndResultArm = function* (m, { ctx, idOf, cards, panel }) {
|
|
|
740
838
|
if (s && (s.type === 'task' || s.type === 'task-list')) {
|
|
741
839
|
yield chrome({
|
|
742
840
|
kind: 'task_ledger_sync',
|
|
743
|
-
laneProof:
|
|
841
|
+
laneProof: mainLane(),
|
|
744
842
|
source: 'structured',
|
|
745
843
|
structuredType: s.type,
|
|
746
844
|
structured: s,
|
|
@@ -763,10 +861,12 @@ const taskProgressArm = function* (m, { ctx, cards, panel, inst }) {
|
|
|
763
861
|
// 只带 rollup 数字 = CC `AgentProgress` 同形 ⇒ 忠实的 CC-187 面是 footer 面板行
|
|
764
862
|
// (CC 自己对进程外 agent 的先例:面板行 + task-notification,从不合成 inline 消息轨)。
|
|
765
863
|
// **不产任何 transcript 消息**:全是 chrome。
|
|
766
|
-
const
|
|
864
|
+
const taskIdRaw = m.taskId;
|
|
865
|
+
const taskId = typeof taskIdRaw === 'string' ? taskIdRaw : undefined;
|
|
767
866
|
if (taskId === undefined)
|
|
768
867
|
return;
|
|
769
|
-
const
|
|
868
|
+
const explicitParentRaw = m.parentToolCallId; // 读一次(0.76.1:typeof 再取值 = 读两次)
|
|
869
|
+
const explicitParent = typeof explicitParentRaw === 'string' ? explicitParentRaw : undefined;
|
|
770
870
|
// ── W1 段2([1617]②,frame-lane-matrix #2/#8)workflow lane 门:workflow 子代的 tick 属
|
|
771
871
|
// fleet lane 自描述行(footer 只渲 workflow 聚合行),**绝不**进前台 subagent lane
|
|
772
872
|
// (不登 alias、不 bind、不 livePanelTasks、不发 panel tick —— 修前每个 workflow agent
|
|
@@ -982,7 +1082,7 @@ function prefixOf(whole, part) {
|
|
|
982
1082
|
return null;
|
|
983
1083
|
}
|
|
984
1084
|
const resultArm = function* (m, { ctx, idOf, text, cards, panel, flags }) {
|
|
985
|
-
yield chrome({ kind: 'retry_status', laneProof:
|
|
1085
|
+
yield chrome({ kind: 'retry_status', laneProof: mainLane(), status: null });
|
|
986
1086
|
// MF-10 防御 sweep(sweep 点 2/4):结掉那些卡从没关过的行(流被截断)。
|
|
987
1087
|
// cli 同位:setRetryStatus(null) 之后、开卡兜底关闭之前。
|
|
988
1088
|
yield* panel.settle(null, false);
|
|
@@ -1073,7 +1173,7 @@ const resultArm = function* (m, { ctx, idOf, text, cards, panel, flags }) {
|
|
|
1073
1173
|
// 改口。两个位是**长度**不是内容 —— 不复述任何一份正文。
|
|
1074
1174
|
yield chrome({
|
|
1075
1175
|
kind: 'result_text_diverged',
|
|
1076
|
-
laneProof:
|
|
1176
|
+
laneProof: mainLane(),
|
|
1077
1177
|
committedLength: committed.length,
|
|
1078
1178
|
resultLength: terminalText.length,
|
|
1079
1179
|
});
|
|
@@ -1098,7 +1198,7 @@ const taskNotificationArm = function* (m, { ctx, idOf, panel, inst }) {
|
|
|
1098
1198
|
if (settleAllowed && terminal) {
|
|
1099
1199
|
yield chrome({
|
|
1100
1200
|
kind: 'bgshell_settle',
|
|
1101
|
-
laneProof:
|
|
1201
|
+
laneProof: mainLane(),
|
|
1102
1202
|
taskId,
|
|
1103
1203
|
status: rawStatus,
|
|
1104
1204
|
...(typeof n.output_file === 'string' && n.output_file.length > 0
|
|
@@ -1121,7 +1221,7 @@ const taskNotificationArm = function* (m, { ctx, idOf, panel, inst }) {
|
|
|
1121
1221
|
if (n.task_type !== 'external' && terminal) {
|
|
1122
1222
|
yield chrome({
|
|
1123
1223
|
kind: 'notification_terminal',
|
|
1124
|
-
laneProof:
|
|
1224
|
+
laneProof: mainLane(),
|
|
1125
1225
|
taskId,
|
|
1126
1226
|
status: rawStatus,
|
|
1127
1227
|
...(typeof n.task_type === 'string' ? { taskType: n.task_type } : {}),
|
|
@@ -1225,7 +1325,7 @@ const workflowCompleteArm = function* (m) {
|
|
|
1225
1325
|
noteWorkflowCompletionCardEnqueued(runId);
|
|
1226
1326
|
yield chrome({
|
|
1227
1327
|
kind: 'workflow_notification_enqueue',
|
|
1228
|
-
laneProof:
|
|
1328
|
+
laneProof: mainLane(),
|
|
1229
1329
|
runId,
|
|
1230
1330
|
status: wfStatus,
|
|
1231
1331
|
summary: wfSummary,
|
|
@@ -1278,10 +1378,10 @@ const retryStatusArm = function* (m, { ctx, flags }) {
|
|
|
1278
1378
|
// 首版写成「无条件发 + clearRetryOverlay」,在常态顺序上双清(对抗复审命中)。
|
|
1279
1379
|
if (status === null) {
|
|
1280
1380
|
if (flags.takeRetryOverlay())
|
|
1281
|
-
yield chrome({ kind: 'retry_status', laneProof:
|
|
1381
|
+
yield chrome({ kind: 'retry_status', laneProof: mainLane(), status: null });
|
|
1282
1382
|
return;
|
|
1283
1383
|
}
|
|
1284
|
-
yield chrome({ kind: 'retry_status', laneProof:
|
|
1384
|
+
yield chrome({ kind: 'retry_status', laneProof: mainLane(), status });
|
|
1285
1385
|
// ⟨帧序耦合 6/7⟩ 挂旗;下一个主 lane 内容帧到达时由 TurnFlags 的帧前置清掉(恢复即清)。
|
|
1286
1386
|
flags.noteRetryOverlay();
|
|
1287
1387
|
};
|
|
@@ -1315,6 +1415,8 @@ export const ARMS = new Map([
|
|
|
1315
1415
|
['context_usage', contextUsageArm],
|
|
1316
1416
|
// CC-89(0.75.0):压缩的非 compacted 结局(additive;不接 = 压缩失败对用户不可见)。
|
|
1317
1417
|
['compaction_outcome', compactionOutcomeArm],
|
|
1418
|
+
// CC-91(0.76.0):这一次 prepare 的提示词装配清单(additive;不接 = 端只能按本地镜像自己估)。
|
|
1419
|
+
['prompt_assembled', promptAssembledArm],
|
|
1318
1420
|
['wiring_manifest', wiringManifestArm],
|
|
1319
1421
|
// B-078 / L-208(0.65.0):design/172 流内审批两帧 —— 修前它们在投影层就 `dropped`,
|
|
1320
1422
|
// 壳自己另接一份 ⇒ desktop/web 拿不到卡集与撤卡(归层违例)。
|
package/dist/adapt/ids.d.ts
CHANGED
|
@@ -1,8 +1,35 @@
|
|
|
1
1
|
import type { AdapterContext, AdapterOutput, ChromeEvent, LaneProof } from '../seam.js';
|
|
2
2
|
/** 帧 = wire 投影出来的中性 arm(cli seam/adapter downstream 的 SDKMessage 形),结构化读取。 */
|
|
3
3
|
export type Frame = Record<string, unknown>;
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* 主车道证明的**出厂口** —— 每次调用交出一只**新的** `{lane:'main'}`(本批实现的臂全在 leader
|
|
6
|
+
* lane;子代/workflow lane 的 tick 面留 #52b)。
|
|
7
|
+
*
|
|
8
|
+
* 🔴 **为什么是函数不是常量**(0.76.1)。此前这里是一只模块级常量对象,`laneOf(未登记 id)` 与本包
|
|
9
|
+
* 约五十个 `laneProof:` 主车道发点交出去的是**同一只**对象 —— 跨适配器实例、跨流、跨 turn 全是
|
|
10
|
+
* 它。实测(修前,本门 L1/L5 段的同一条路径):两个互不相干的消费者各取一次未登记行的证明,
|
|
11
|
+
* `===` 为真;给第一只补上卡号之后,第二只当场读出 `{lane:'subagent', parentToolCallId:'…'}`,
|
|
12
|
+
* 开流序幕那四条主车道事件也一起变 —— **一次写打穿整个进程**,而且静默。
|
|
13
|
+
*
|
|
14
|
+
* 🔴 **判据如实**:这是**别名风险**,不是「已经在串味的现场」。修前逐站点穷举(语法树扫写表达式)
|
|
15
|
+
* 的结论是:本包内对车道证明**零就地写**(两处看起来像写的是给局部变量**换绑**新对象,不改旧的);
|
|
16
|
+
* 三个消费端的证明用法全是只读(读 `lane` 位 / 解构丢弃)。⇒ 本批修的是「交出去的可变引用被
|
|
17
|
+
* 当成缺省值别名」这一形,不是在修一条已经在错归因的行。发布文案不许把它写成用户可见的回归。
|
|
18
|
+
* 这条形本身仍然要修:`laneProof` 是**公开输出面**上的一位,拿它做 WeakMap 键 / 身份去重 /
|
|
19
|
+
* 视图层身份记忆的消费者,在两条无关行共享一只对象时会把它们认成同一条 —— **一个字都不写也照错**。
|
|
20
|
+
* 这也正是冻结那条修法救不了的一半。
|
|
21
|
+
*
|
|
22
|
+
* 🔴 **为什么不是冻结**(两条都摆过,这条落选):
|
|
23
|
+
* ① 冻结只挡「写」,不解「别名」——上一段那三种按身份认物的消费面照错;每次新建两件一起解决。
|
|
24
|
+
* ② 子代臂 `{lane:'subagent', parentToolCallId}` 与 workflow 臂本来就**逐次新建**且可写,只冻主
|
|
25
|
+
* 车道这一半 ⇒ 同一处写操作会因为「这条行恰好绑没绑卡」而一边抛一边收,失败随行漂成间歇形;
|
|
26
|
+
* 要对称就得连十几处内联字面量一起冻,比每次新建更大的改动换更小的收益。
|
|
27
|
+
* ③ 证明是在宿主手里被写的:冻结把一条本包的别名缺陷变成宿主侧的抛错,而宿主的抛会顺着
|
|
28
|
+
* `for await` 打断整条 adapt 流。适配层不该给主链添这种反噬。
|
|
29
|
+
* ⚠️ 代价如实:每条主车道事件多一只小对象(≈ 一个键的字面量)。别为了省它把出厂口缓存成模块级
|
|
30
|
+
* 单例(`const M = mainLane()` 就是把这一形原样种回来)—— 结构反钉门盯着这一形。
|
|
31
|
+
*/
|
|
32
|
+
export declare const mainLane: () => LaneProof;
|
|
6
33
|
/** 帧 → 稳定转录 id(`suffix` = 同一帧派生多条消息时的去撞位)。 */
|
|
7
34
|
export type IdOf = (frame: Frame, suffix?: string) => string;
|
|
8
35
|
/**
|
package/dist/adapt/ids.js
CHANGED
|
@@ -1,6 +1,33 @@
|
|
|
1
1
|
import { deriveTranscriptId } from '../seam.js';
|
|
2
|
-
/**
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* 主车道证明的**出厂口** —— 每次调用交出一只**新的** `{lane:'main'}`(本批实现的臂全在 leader
|
|
4
|
+
* lane;子代/workflow lane 的 tick 面留 #52b)。
|
|
5
|
+
*
|
|
6
|
+
* 🔴 **为什么是函数不是常量**(0.76.1)。此前这里是一只模块级常量对象,`laneOf(未登记 id)` 与本包
|
|
7
|
+
* 约五十个 `laneProof:` 主车道发点交出去的是**同一只**对象 —— 跨适配器实例、跨流、跨 turn 全是
|
|
8
|
+
* 它。实测(修前,本门 L1/L5 段的同一条路径):两个互不相干的消费者各取一次未登记行的证明,
|
|
9
|
+
* `===` 为真;给第一只补上卡号之后,第二只当场读出 `{lane:'subagent', parentToolCallId:'…'}`,
|
|
10
|
+
* 开流序幕那四条主车道事件也一起变 —— **一次写打穿整个进程**,而且静默。
|
|
11
|
+
*
|
|
12
|
+
* 🔴 **判据如实**:这是**别名风险**,不是「已经在串味的现场」。修前逐站点穷举(语法树扫写表达式)
|
|
13
|
+
* 的结论是:本包内对车道证明**零就地写**(两处看起来像写的是给局部变量**换绑**新对象,不改旧的);
|
|
14
|
+
* 三个消费端的证明用法全是只读(读 `lane` 位 / 解构丢弃)。⇒ 本批修的是「交出去的可变引用被
|
|
15
|
+
* 当成缺省值别名」这一形,不是在修一条已经在错归因的行。发布文案不许把它写成用户可见的回归。
|
|
16
|
+
* 这条形本身仍然要修:`laneProof` 是**公开输出面**上的一位,拿它做 WeakMap 键 / 身份去重 /
|
|
17
|
+
* 视图层身份记忆的消费者,在两条无关行共享一只对象时会把它们认成同一条 —— **一个字都不写也照错**。
|
|
18
|
+
* 这也正是冻结那条修法救不了的一半。
|
|
19
|
+
*
|
|
20
|
+
* 🔴 **为什么不是冻结**(两条都摆过,这条落选):
|
|
21
|
+
* ① 冻结只挡「写」,不解「别名」——上一段那三种按身份认物的消费面照错;每次新建两件一起解决。
|
|
22
|
+
* ② 子代臂 `{lane:'subagent', parentToolCallId}` 与 workflow 臂本来就**逐次新建**且可写,只冻主
|
|
23
|
+
* 车道这一半 ⇒ 同一处写操作会因为「这条行恰好绑没绑卡」而一边抛一边收,失败随行漂成间歇形;
|
|
24
|
+
* 要对称就得连十几处内联字面量一起冻,比每次新建更大的改动换更小的收益。
|
|
25
|
+
* ③ 证明是在宿主手里被写的:冻结把一条本包的别名缺陷变成宿主侧的抛错,而宿主的抛会顺着
|
|
26
|
+
* `for await` 打断整条 adapt 流。适配层不该给主链添这种反噬。
|
|
27
|
+
* ⚠️ 代价如实:每条主车道事件多一只小对象(≈ 一个键的字面量)。别为了省它把出厂口缓存成模块级
|
|
28
|
+
* 单例(`const M = mainLane()` 就是把这一形原样种回来)—— 结构反钉门盯着这一形。
|
|
29
|
+
*/
|
|
30
|
+
export const mainLane = () => ({ lane: 'main' });
|
|
4
31
|
/**
|
|
5
32
|
* L-215③(0.65.0)—— 一条 assistant 转录消息的**身份键**(`message.id` / `message.model`)。
|
|
6
33
|
*
|
|
@@ -40,8 +40,9 @@ export interface PanelTaskLedger {
|
|
|
40
40
|
unboundCandidates(): number;
|
|
41
41
|
/** 行的车道证明:绑到卡的 = subagent lane(带父卡 id),未绑的 = 主 lane。 */
|
|
42
42
|
laneOf(taskId: string): LaneProof;
|
|
43
|
-
/** 这条行已经绑过卡了吗(
|
|
44
|
-
*
|
|
43
|
+
/** 这条行已经绑过卡了吗(含糊回落的前置判位;别拿「`laneOf(...)` 是不是那只主车道常量」代替 ——
|
|
44
|
+
* 那是按引用相等在推断,判据锚在会决定结果的量上才对。0.76.1 起主车道证明**逐次新建**,
|
|
45
|
+
* 那种写法连偶然成立都做不到了)。 */
|
|
45
46
|
isBound(taskId: string): boolean;
|
|
46
47
|
/**
|
|
47
48
|
* B-074 —— 这条行绑在一张**本 turn 还开着**的卡上吗(`liveBound`,#6 的 live/inert 判位)。
|
|
@@ -75,7 +76,7 @@ export interface PanelTaskLedger {
|
|
|
75
76
|
* B-074(0.65.0)**终态 tick 边** —— core 明写的那一拍(`task_progress.status` = `completed`/
|
|
76
77
|
* `failed`)按 taskId 直接落行。
|
|
77
78
|
*
|
|
78
|
-
* 为什么不复用 {@link settleFromNotification}
|
|
79
|
+
* 为什么不复用 {@link settleFromNotification}:那一条是**通知帧**那半场,它按**主车道**发
|
|
79
80
|
* end(bg 子代行本来就是 unbound 的),而终态 tick 的行**可能绑着一张前台委派卡** ⇒ 车道证明
|
|
80
81
|
* 必须走 {@link laneOf},否则一条 subagent lane 的行会拿 main lane 的证明去落终态(帧×lane
|
|
81
82
|
* 矩阵那一族的病)。也不复用 {@link settle}:那一条按**卡 id** 收(关卡/防御 sweep 的语义),
|
package/dist/adapt/panelTasks.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { clearEnginePanelTaskResident, clearEnginePanelTaskResidentByWire, markEnginePanelTaskResident } from '../engineAgentPanelStore.js';
|
|
2
|
-
import { chrome,
|
|
2
|
+
import { chrome, mainLane } from './ids.js';
|
|
3
3
|
import { SUBAGENT_TOOL_NAMES } from './wireShapes.js';
|
|
4
4
|
export function createPanelTaskLedger(ctx, cards, inst) {
|
|
5
5
|
/** taskId → 绑定的 open tool_use id。 */
|
|
@@ -22,7 +22,25 @@ export function createPanelTaskLedger(ctx, cards, inst) {
|
|
|
22
22
|
const subagentTypeById = new Map();
|
|
23
23
|
const laneOf = (taskId) => {
|
|
24
24
|
const card = taskCardBinding.get(taskId);
|
|
25
|
-
return card !== undefined ? { lane: 'subagent', parentToolCallId: card } :
|
|
25
|
+
return card !== undefined ? { lane: 'subagent', parentToolCallId: card } : mainLane();
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* 一条行要发**多条**事件时的车道证明来源(0.76.1,异源对抗复审 R1 [medium] 实测逼出)。
|
|
29
|
+
*
|
|
30
|
+
* 病形:终态那两处(关卡 / 终态 tick)此前 `const lane = laneOf(taskId)` 取一次,然后 stop 与
|
|
31
|
+
* end **两条事件共用那一只** —— 消费者拿到 stop 后改它的归属,同一条行的 end 跟着变;逐条消费
|
|
32
|
+
* 的宿主甚至能在 end 那一次 `yield` **之前**就把它污染掉(生成器在两条之间是挂起的)。
|
|
33
|
+
*
|
|
34
|
+
* 修法**不是**在每条事件那里各调一次 `laneOf`:两次调用之间生成器会挂起,消费者若在这中间绑了卡,
|
|
35
|
+
* 同一条行的两条事件就会**分流到两个归属**上(一条算主车道、一条算子代)——那比别名更坏。
|
|
36
|
+
* ⇒ **归属判一次、证明铸多只**:这里把归属(绑到哪张卡 / 没绑)先定死,返回的铸口每次交出一只
|
|
37
|
+
* 新对象、值恒相同。
|
|
38
|
+
*/
|
|
39
|
+
const laneMinterFor = (taskId) => {
|
|
40
|
+
const card = taskCardBinding.get(taskId);
|
|
41
|
+
return card !== undefined
|
|
42
|
+
? () => ({ lane: 'subagent', parentToolCallId: card })
|
|
43
|
+
: mainLane;
|
|
26
44
|
};
|
|
27
45
|
return {
|
|
28
46
|
laneOf,
|
|
@@ -131,7 +149,7 @@ export function createPanelTaskLedger(ctx, cards, inst) {
|
|
|
131
149
|
yield chrome({ kind: 'inline_task_stats', laneProof: { lane: 'subagent', parentToolCallId: cardId }, op: 'settle', cardId, isError });
|
|
132
150
|
}
|
|
133
151
|
else {
|
|
134
|
-
yield chrome({ kind: 'inline_task_stats', laneProof:
|
|
152
|
+
yield chrome({ kind: 'inline_task_stats', laneProof: mainLane(), op: 'settle_all' });
|
|
135
153
|
}
|
|
136
154
|
for (const taskId of livePanelTasks) {
|
|
137
155
|
if (cardId !== null && taskCardBinding.get(taskId) !== cardId)
|
|
@@ -144,18 +162,18 @@ export function createPanelTaskLedger(ctx, cards, inst) {
|
|
|
144
162
|
if (endedPanelTasks.has(taskId))
|
|
145
163
|
continue;
|
|
146
164
|
endedPanelTasks.add(taskId);
|
|
147
|
-
const
|
|
165
|
+
const mintLane = laneMinterFor(taskId);
|
|
148
166
|
const agentType = subagentTypeById.get(taskId);
|
|
149
167
|
yield chrome({
|
|
150
168
|
kind: 'subagent_lifecycle',
|
|
151
|
-
laneProof:
|
|
169
|
+
laneProof: mintLane(),
|
|
152
170
|
phase: 'stop',
|
|
153
171
|
taskId,
|
|
154
172
|
...(agentType !== undefined ? { agentType } : {}),
|
|
155
173
|
});
|
|
156
174
|
yield chrome({
|
|
157
175
|
kind: 'panel_task',
|
|
158
|
-
laneProof:
|
|
176
|
+
laneProof: mintLane(),
|
|
159
177
|
event: {
|
|
160
178
|
kind: 'end',
|
|
161
179
|
taskId,
|
|
@@ -184,7 +202,7 @@ export function createPanelTaskLedger(ctx, cards, inst) {
|
|
|
184
202
|
endedPanelTasks.add(taskId);
|
|
185
203
|
yield chrome({
|
|
186
204
|
kind: 'panel_task',
|
|
187
|
-
laneProof:
|
|
205
|
+
laneProof: mainLane(),
|
|
188
206
|
event: { kind: 'end', taskId, isError },
|
|
189
207
|
});
|
|
190
208
|
// SubagentStop 只对**真 fire 过 Start** 的子代(workflow runId / 外来 id 不配对乱 fire)。
|
|
@@ -193,7 +211,7 @@ export function createPanelTaskLedger(ctx, cards, inst) {
|
|
|
193
211
|
if (inst.hasFiredSubagentStart(taskId)) {
|
|
194
212
|
yield chrome({
|
|
195
213
|
kind: 'subagent_lifecycle',
|
|
196
|
-
laneProof:
|
|
214
|
+
laneProof: mainLane(),
|
|
197
215
|
phase: 'stop',
|
|
198
216
|
taskId,
|
|
199
217
|
guard: 'if-started',
|
|
@@ -215,7 +233,7 @@ export function createPanelTaskLedger(ctx, cards, inst) {
|
|
|
215
233
|
return;
|
|
216
234
|
endedPanelTasks.add(taskId);
|
|
217
235
|
clearResidencyBothKeys(taskId);
|
|
218
|
-
const
|
|
236
|
+
const mintLane = laneMinterFor(taskId);
|
|
219
237
|
const card = taskCardBinding.get(taskId);
|
|
220
238
|
if (card !== undefined) {
|
|
221
239
|
yield chrome({
|
|
@@ -231,7 +249,7 @@ export function createPanelTaskLedger(ctx, cards, inst) {
|
|
|
231
249
|
const agentType = subagentTypeById.get(taskId);
|
|
232
250
|
yield chrome({
|
|
233
251
|
kind: 'subagent_lifecycle',
|
|
234
|
-
laneProof:
|
|
252
|
+
laneProof: mintLane(),
|
|
235
253
|
phase: 'stop',
|
|
236
254
|
taskId,
|
|
237
255
|
...(agentType !== undefined ? { agentType } : {}),
|
|
@@ -240,7 +258,7 @@ export function createPanelTaskLedger(ctx, cards, inst) {
|
|
|
240
258
|
}
|
|
241
259
|
yield chrome({
|
|
242
260
|
kind: 'panel_task',
|
|
243
|
-
laneProof:
|
|
261
|
+
laneProof: mintLane(),
|
|
244
262
|
event: { kind: 'end', taskId, isError },
|
|
245
263
|
});
|
|
246
264
|
},
|
package/dist/adapt/textStream.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { chrome,
|
|
1
|
+
import { chrome, mainLane, transcript, messageIdentityOf } from './ids.js';
|
|
2
2
|
import { estimateCjkTokens, FLUSH_INTERVAL_MS } from './wireShapes.js';
|
|
3
3
|
// L-318:六形判决单源(两条车道同吃;落账各归各层,见 textSegmentAuthority.ts 头注)。
|
|
4
4
|
import { resolveTextSegmentAuthority } from './textSegmentAuthority.js';
|
|
@@ -196,7 +196,7 @@ export function createTextStream(ctx, idOf) {
|
|
|
196
196
|
thinkingAnchor = null;
|
|
197
197
|
thinkingBlockOpen = false;
|
|
198
198
|
// P2d:活体 "∴ Thinking…" 行在 committed 块落地的**同一刻**收掉(先收行再上消息,cli 同序)
|
|
199
|
-
yield chrome({ kind: 'thinking_activity', laneProof:
|
|
199
|
+
yield chrome({ kind: 'thinking_activity', laneProof: mainLane(), active: false });
|
|
200
200
|
yield transcript(msg, ctx.now());
|
|
201
201
|
}
|
|
202
202
|
/** 段提交的**唯一本体**(两个入口 `takeAnswerSegment` / `takeAnswerSegmentOnIdle` 共用;
|
|
@@ -266,7 +266,7 @@ export function createTextStream(ctx, idOf) {
|
|
|
266
266
|
thinkingBlockOpen = true;
|
|
267
267
|
yield chrome({
|
|
268
268
|
kind: 'stream_delta',
|
|
269
|
-
laneProof:
|
|
269
|
+
laneProof: mainLane(),
|
|
270
270
|
channel: 'thinking',
|
|
271
271
|
text: thinkingPending,
|
|
272
272
|
estimatedTokens: estimateCjkTokens(thinkingPending),
|
|
@@ -283,7 +283,7 @@ export function createTextStream(ctx, idOf) {
|
|
|
283
283
|
ctx.probe?.('stream', `${ctx.now()} text_flush len=${textPending.length}`);
|
|
284
284
|
yield chrome({
|
|
285
285
|
kind: 'stream_delta',
|
|
286
|
-
laneProof:
|
|
286
|
+
laneProof: mainLane(),
|
|
287
287
|
channel: 'text',
|
|
288
288
|
text: textPending,
|
|
289
289
|
estimatedTokens: estimateCjkTokens(textPending),
|
|
@@ -328,7 +328,7 @@ export function createTextStream(ctx, idOf) {
|
|
|
328
328
|
// 对照物只在 `reasoning_end` 用过之后清(段界由引擎说了算),turn 结束整只丢,天然有界。
|
|
329
329
|
// P2d:elapsed 锚在**首条** leader 推理增量(token 累计由 stream_delta.estimatedTokens
|
|
330
330
|
// 承载,宿主自加;>30s 无增量的 stall 提示同样由宿主按增量时间戳判)。
|
|
331
|
-
yield chrome({ kind: 'thinking_activity', laneProof:
|
|
331
|
+
yield chrome({ kind: 'thinking_activity', laneProof: mainLane(), active: true });
|
|
332
332
|
}
|
|
333
333
|
thinking += delta;
|
|
334
334
|
thinkingPending += delta;
|