@sema-agent/client-core 0.99.0 → 0.100.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.
Files changed (128) hide show
  1. package/CHANGELOG.md +177 -0
  2. package/README.md +32 -19
  3. package/dist/adapt/arms.js +60 -36
  4. package/dist/adapt/panelTasks.d.ts +2 -1
  5. package/dist/adapt/panelTasks.js +32 -9
  6. package/dist/adapt/textStream.d.ts +1 -1
  7. package/dist/adapt/textStream.js +51 -28
  8. package/dist/adapter/activeRunSelfHeal.d.ts +7 -0
  9. package/dist/adapter/activeRunSelfHeal.js +58 -11
  10. package/dist/adapter/downstream/eventToSdkMessage.d.ts +25 -6
  11. package/dist/adapter/downstream/eventToSdkMessage.js +125 -9
  12. package/dist/adapter/downstream/terminalToSdkResult.js +10 -0
  13. package/dist/adapter/downstream/wiringManifestView.d.ts +3 -1
  14. package/dist/adapter/downstream/wiringManifestView.js +1 -0
  15. package/dist/adapter/runStream.js +32 -5
  16. package/dist/adapter/types.d.ts +2 -0
  17. package/dist/agentsWireCaps.d.ts +7 -0
  18. package/dist/agentsWireCaps.js +100 -15
  19. package/dist/cloudConfigWireCaps.d.ts +10 -1
  20. package/dist/cloudConfigWireCaps.js +156 -62
  21. package/dist/compactionStatus.d.ts +34 -0
  22. package/dist/compactionStatus.js +196 -0
  23. package/dist/decideFailureNote.js +3 -3
  24. package/dist/displayUntrusted.js +150 -5
  25. package/dist/engineAgentPanelStore.d.ts +7 -4
  26. package/dist/engineErrorCodes.d.ts +9 -1
  27. package/dist/engineErrorCodes.js +9 -5
  28. package/dist/engineRowRef.js +1 -0
  29. package/dist/engineToolDirectory.d.ts +3 -0
  30. package/dist/engineToolDirectory.js +4 -2
  31. package/dist/eventLeg.d.ts +1 -7
  32. package/dist/eventLeg.js +7 -8
  33. package/dist/fileHistoryCaptureCapability.d.ts +0 -3
  34. package/dist/fileHistoryCaptureCapability.js +0 -4
  35. package/dist/generated/engineFactTables.d.ts +1 -0
  36. package/dist/generated/engineFactTables.js +27 -0
  37. package/dist/generated/engineNoticeTables.js +3 -0
  38. package/dist/generated/settingsSchemaFns.d.ts +12 -0
  39. package/dist/generated/settingsSchemaFns.js +13 -0
  40. package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -0
  41. package/dist/generated/settingsSchemaMcpRequestEntry.js +162 -0
  42. package/dist/generated/settingsSchemaTables.d.ts +1 -0
  43. package/dist/generated/settingsSchemaTables.js +5 -0
  44. package/dist/generated/settingsSchemaTypes.d.ts +28 -0
  45. package/dist/hitl/allowRuleShadow.js +2 -2
  46. package/dist/hitl/approvalCardReasons.js +2 -2
  47. package/dist/hitl/approvalHolds.d.ts +14 -0
  48. package/dist/hitl/approvalHolds.js +41 -0
  49. package/dist/hitl/askClassPair.d.ts +2 -2
  50. package/dist/hitl/askClassPair.js +2 -2
  51. package/dist/hitl/attributionLadder.d.ts +23 -0
  52. package/dist/hitl/attributionLadder.js +67 -0
  53. package/dist/hitl/decisionLedger.d.ts +55 -0
  54. package/dist/hitl/decisionLedger.js +156 -0
  55. package/dist/hitl/decisionRefusal.d.ts +1 -0
  56. package/dist/hitl/decisionRefusal.js +1 -1
  57. package/dist/hitl/decisionSend.d.ts +113 -0
  58. package/dist/hitl/decisionSend.js +579 -0
  59. package/dist/hitl/hitlBridge.js +18 -6
  60. package/dist/hitl/planReviewWire.js +45 -76
  61. package/dist/hitl/sessionPolicyDeliverable.js +3 -6
  62. package/dist/hitl/toolApprovalWire.js +43 -109
  63. package/dist/hostTurnSettings.d.ts +46 -7
  64. package/dist/hostTurnSettings.js +408 -7
  65. package/dist/humanTurn.d.ts +2 -1
  66. package/dist/humanTurn.js +3 -3
  67. package/dist/i18n/messages.en.d.ts +131 -0
  68. package/dist/i18n/messages.en.js +143 -12
  69. package/dist/i18n/messages.zh.js +148 -12
  70. package/dist/index.d.ts +18 -2
  71. package/dist/index.js +10 -1
  72. package/dist/inheritEnvCapability.d.ts +1 -0
  73. package/dist/inheritEnvCapability.js +9 -2
  74. package/dist/inheritEnvWire.js +2 -2
  75. package/dist/injectionLaneNotice.d.ts +5 -0
  76. package/dist/injectionLaneNotice.js +46 -0
  77. package/dist/mcpPanel.js +2 -0
  78. package/dist/mcpReconnect.js +2 -2
  79. package/dist/mcpToolToggles.d.ts +6 -0
  80. package/dist/mcpToolToggles.js +46 -0
  81. package/dist/mcpWireCaps.d.ts +10 -4
  82. package/dist/mcpWireCaps.js +106 -71
  83. package/dist/mcpWireTransport.d.ts +4 -0
  84. package/dist/mcpWireTransport.js +18 -0
  85. package/dist/modelCapabilityProbe.d.ts +2 -1
  86. package/dist/modelCapabilityProbe.js +10 -9
  87. package/dist/modelIdentityResolvability.d.ts +2 -0
  88. package/dist/modelIdentityResolvability.js +23 -5
  89. package/dist/ownKey.d.ts +26 -0
  90. package/dist/ownKey.js +75 -0
  91. package/dist/panelReduce.d.ts +5 -0
  92. package/dist/panelReduce.js +45 -13
  93. package/dist/panelStateHolder.d.ts +1 -0
  94. package/dist/panelStateHolder.js +10 -1
  95. package/dist/permissionRuleIssue.d.ts +2 -1
  96. package/dist/permissionRuleIssue.js +22 -21
  97. package/dist/pluginHooksWire.js +12 -10
  98. package/dist/prepareRefusal.d.ts +8 -0
  99. package/dist/prepareRefusal.js +72 -0
  100. package/dist/request/taskRequest.d.ts +10 -10
  101. package/dist/request/taskRequest.js +106 -65
  102. package/dist/resumeRefusalCopy.d.ts +3 -1
  103. package/dist/resumeRefusalCopy.js +22 -4
  104. package/dist/retryStatus.d.ts +18 -0
  105. package/dist/retryStatus.js +76 -19
  106. package/dist/ruleRefusalSentence.d.ts +4 -0
  107. package/dist/ruleRefusalSentence.js +58 -0
  108. package/dist/sandboxWire.d.ts +2 -1
  109. package/dist/sandboxWire.js +55 -21
  110. package/dist/scenarioRefusal.d.ts +2 -1
  111. package/dist/scenarioRefusal.js +5 -5
  112. package/dist/seam.d.ts +24 -9
  113. package/dist/seam.js +44 -4
  114. package/dist/seatContract.d.ts +16 -8
  115. package/dist/seatContract.js +21 -6
  116. package/dist/settingsCredentialKeyPaths.d.ts +8 -0
  117. package/dist/settingsCredentialKeyPaths.js +219 -0
  118. package/dist/skillsWireCaps.d.ts +0 -3
  119. package/dist/skillsWireCaps.js +1 -2
  120. package/dist/subagentContentStore.d.ts +1 -0
  121. package/dist/subagentContentStore.js +135 -27
  122. package/dist/toolsFlagNames.d.ts +8 -0
  123. package/dist/toolsFlagNames.js +110 -0
  124. package/dist/turnFailurePresentation.js +15 -7
  125. package/dist/wireRefusalCopy.d.ts +51 -17
  126. package/dist/wireRefusalCopy.js +298 -135
  127. package/docs/INTEGRATION-CLIENTS.md +423 -26
  128. package/package.json +4 -4
@@ -1,4 +1,5 @@
1
1
  import { ccToolDenialKindForToolEnd, gateOutcomeOf } from '../gateOutcome.js';
2
+ import { terminalOwnerOf } from '../seam.js';
2
3
  import { isSubFlowSegmentEnd, SEGMENT_END_IDENTITY_KEYS, snapshotSegmentIdentity, snapshotIsSubFlow } from '../adapter/types.js';
3
4
  import { classifyPeerNotification, renderPeerFrameTranscriptText } from '../peerFrames.js';
4
5
  import { dropQueuedNotificationsForRun, isEngineWorkflowNotified, isWorkflowCompletionCardEnqueued, markEngineWorkflowNotified, noteOwnWorkflowRun, normalizeTaskNotification, noteWorkflowCompletionCardEnqueued, renderTaskNotificationXml, taskNotificationDedupKey } from '../notifications.js';
@@ -12,10 +13,11 @@ import { recordWorkflowAgentTaskId } from '../workflow.js';
12
13
  import { isCoreTaskNotificationTerminal, isCoreTaskNotificationTerminalNotSuccess, isCoreTaskProgressTerminal, isCoreTaskProgressTerminalNotSuccess } from '../terminalStatuses.js';
13
14
  import { readToolHistoryMismatchKey } from '../toolHistoryMismatch.js';
14
15
  import { readProviderRejectionResendKey } from '../providerRejection.js';
15
- import { contextUsageReadingOf, guardedRead, humanInputAttachmentsOf, readFrameStringKey, readFrameTrueMark } from '../ownKey.js';
16
+ import { contextUsageReadingOf, guardedRead, humanInputAttachmentsOf, promptManifestIdentityOfFrame, promptManifestSectionViewOf, readFrameStringKey, readFrameTrueMark } from '../ownKey.js';
16
17
  import { CORE_USER_ATTACHMENT_LABEL_MAX } from '../generated/engineFactTables.js';
17
18
  import { ESCAPE_FACE, paintAndCap, washCredentials } from '../displayUntrusted.js';
18
19
  import { resolveEnginePanelTaskId } from '../engineAgentPanelStore.js';
20
+ import { cycleSeqValue } from '../cycleOrder.js';
19
21
  import { fleetRowAgentType } from '../fleet/fleetRowAgentType.js';
20
22
  import { chrome, mainLane, transcript, messageIdentityOf } from './ids.js';
21
23
  import { engineRefOf } from '../engineRowRef.js';
@@ -23,27 +25,6 @@ import { isReplayMarked, RESULT_REPLAYED_TEXT } from '../replayBody.js';
23
25
  import { wiringManifestViewOf } from '../adapter/downstream/wiringManifestView.js';
24
26
  import { isUnsettledHeldToolEnd } from '../engineRowRef.js';
25
27
  import { CANCEL_MESSAGE, decisionOf, flattenWireOutput, REJECT_MESSAGE, sanitizeToolUseBlock, shortTaskLabel, TASK_TOOL_NAMES, WORKFLOW_TOOL_NAMES, } from './wireShapes.js';
26
- function hostOwnString(o, key) {
27
- return readFrameStringKey(o, key);
28
- }
29
- function continuesParkDeclarationOf(ctx) {
30
- const decl = guardedRead(() => ctx.continuesPark);
31
- return typeof decl === 'object' && decl !== null ? decl : undefined;
32
- }
33
- function continuesParkWitness(ctx, row) {
34
- const decl = continuesParkDeclarationOf(ctx);
35
- if (decl === undefined)
36
- return false;
37
- if (hostOwnString(decl, 'toolCallId') !== row.toolCallId)
38
- return false;
39
- const cp = hostOwnString(decl, 'checkpointId');
40
- if (cp !== undefined && row.checkpointId !== undefined && cp !== row.checkpointId)
41
- return false;
42
- const parkedTaskId = hostOwnString(decl, 'parkedTaskId');
43
- if (parkedTaskId !== undefined && row.parkedRun !== undefined && parkedTaskId !== row.parkedRun)
44
- return false;
45
- return true;
46
- }
47
28
  function claimParkedCard(m, callId, toolName, deps) {
48
29
  const { ctx, cards, inst, pass } = deps;
49
30
  if (cards.has(callId))
@@ -57,12 +38,11 @@ function claimParkedCard(m, callId, toolName, deps) {
57
38
  return undefined;
58
39
  const frameRun = engineRefOf(m)?.taskId;
59
40
  if (frameRun !== undefined) {
60
- const decl = continuesParkDeclarationOf(ctx);
61
- const allowed = [row.parkedRun, row.card.engineRef?.taskId, readFrameStringKey(decl, 'parkedTaskId'), readFrameStringKey(decl, 'continuationTaskId')].filter((x) => x !== undefined);
41
+ const allowed = [row.parkedRun, row.card.engineRef?.taskId].filter((x) => x !== undefined);
62
42
  if (allowed.length > 0 && !allowed.includes(frameRun))
63
43
  return undefined;
64
44
  }
65
- if (row.pass !== pass && !continuesParkWitness(ctx, row))
45
+ if (row.pass !== pass)
66
46
  return undefined;
67
47
  inst.dropParkedToolRow(row.key);
68
48
  return row.card;
@@ -70,6 +50,12 @@ function claimParkedCard(m, callId, toolName, deps) {
70
50
  function laneOfCard(p) {
71
51
  return p.parentToolCallId !== undefined && p.parentToolCallId !== '' ? { lane: 'subagent', parentToolCallId: p.parentToolCallId } : mainLane();
72
52
  }
53
+ function terminalOwnerCarry(m) {
54
+ if (m._sema_api_error_message !== true)
55
+ return {};
56
+ const owner = terminalOwnerOf(m);
57
+ return owner === undefined ? {} : { _sema_terminal_owner: owner };
58
+ }
73
59
  function toolHistoryKeyCarry(m) {
74
60
  if (m._sema_api_error_message !== true)
75
61
  return {};
@@ -189,7 +175,7 @@ const assistantArm = function* (m, deps) {
189
175
  }
190
176
  const textBlock = blocks.find(b => b?.type === 'text');
191
177
  const thinkingBlock = blocks.find(b => b?.type === 'thinking');
192
- if ((textBlock && typeof textBlock.text === 'string' && textBlock.text.length > 0) || (thinkingBlock && typeof thinkingBlock.thinking === 'string'))
178
+ if (textBlock && typeof textBlock.text === 'string' && textBlock.text.length > 0)
193
179
  text.anchorWindow(m);
194
180
  if (textBlock && typeof textBlock.text === 'string' && textBlock.text.length > 0) {
195
181
  const rowText = m._sema_api_error_message === true ? washCredentials(textBlock.text) : textBlock.text;
@@ -205,6 +191,7 @@ const assistantArm = function* (m, deps) {
205
191
  ...(m._sema_api_error_message === true ? { _sema_api_error_message: true } : {}),
206
192
  ...toolHistoryKeyCarry(m),
207
193
  ...providerResendKeyCarry(m),
194
+ ...terminalOwnerCarry(m),
208
195
  }, ctx.now());
209
196
  text.markEmittedText(rowText);
210
197
  }
@@ -457,12 +444,41 @@ const compactionOutcomeArm = function* (m) {
457
444
  const trigger = str(m.trigger);
458
445
  const reason = str(m.reason);
459
446
  const eventId = str(idSnap.eventId);
447
+ const pass = str(m.pass);
460
448
  yield chrome({
461
449
  kind: 'compaction_outcome',
462
450
  laneProof,
463
451
  outcome,
464
452
  ...(trigger !== undefined ? { trigger } : {}),
465
453
  ...(reason !== undefined ? { reason } : {}),
454
+ ...(pass !== undefined ? { pass } : {}),
455
+ ...(eventId !== undefined ? { eventId } : {}),
456
+ });
457
+ };
458
+ const compactionStartedArm = function* (m) {
459
+ const str = (v) => (typeof v === 'string' && v.length > 0 ? v : undefined);
460
+ const pass = str(m.pass);
461
+ const trigger = str(m.trigger);
462
+ if (pass === undefined || trigger === undefined)
463
+ return;
464
+ const idSnap = snapshotSegmentIdentity(m);
465
+ if (idSnap === null)
466
+ return;
467
+ let laneProof = mainLane();
468
+ if (snapshotIsSubFlow(idSnap)) {
469
+ const parent = str(idSnap.parentToolCallId);
470
+ if (parent === undefined)
471
+ return;
472
+ laneProof = { lane: 'subagent', parentToolCallId: parent };
473
+ }
474
+ const startedAt = typeof m.startedAt === 'number' && Number.isFinite(m.startedAt) ? m.startedAt : undefined;
475
+ const eventId = str(idSnap.eventId);
476
+ yield chrome({
477
+ kind: 'compaction_started',
478
+ laneProof,
479
+ pass,
480
+ trigger,
481
+ ...(startedAt !== undefined ? { startedAt } : {}),
466
482
  ...(eventId !== undefined ? { eventId } : {}),
467
483
  });
468
484
  };
@@ -533,14 +549,8 @@ const promptAssembledArm = function* (m) {
533
549
  const chars = size(o.chars);
534
550
  return id === undefined || chars === undefined ? undefined : { id, chars };
535
551
  });
536
- const sections = promptManifestRows(m.sections, (o) => {
537
- const id = str(o.id);
538
- const chars = size(o.chars);
539
- if (id === undefined || chars === undefined)
540
- return undefined;
541
- const slot = str(o.slot);
542
- return { id, chars, ...(slot !== undefined ? { slot } : {}) };
543
- });
552
+ const sections = promptManifestRows(m.sections, (o) => promptManifestSectionViewOf(o));
553
+ const promptIdentity = promptManifestIdentityOfFrame(m);
544
554
  const tools = promptManifestRows(m.tools, (o) => {
545
555
  const wireName = str(o.wireName);
546
556
  return wireName === undefined ? undefined : { wireName };
@@ -567,6 +577,7 @@ const promptAssembledArm = function* (m) {
567
577
  ...(blocks !== undefined ? { blocks } : {}),
568
578
  ...(sections !== undefined ? { sections } : {}),
569
579
  ...(tools !== undefined ? { tools } : {}),
580
+ ...(promptIdentity !== undefined ? { identity: promptIdentity } : {}),
570
581
  ...(eventId !== undefined ? { eventId } : {}),
571
582
  });
572
583
  };
@@ -576,6 +587,7 @@ const textSegmentEndArm = function* (m, { text }) {
576
587
  const content = typeof m.content === 'string' ? m.content : '';
577
588
  if (content.length === 0)
578
589
  return;
590
+ text.anchorWindow(m);
579
591
  const r = text.replaceAnswerSegment(content, m);
580
592
  yield* text.drainLive();
581
593
  yield chrome({
@@ -591,7 +603,7 @@ const textSegmentEndArm = function* (m, { text }) {
591
603
  ...(r.committedRows !== undefined ? { committedRows: r.committedRows } : {}),
592
604
  ...(typeof m.eventId === 'string' && m.eventId.length > 0 ? { eventId: m.eventId } : {}),
593
605
  });
594
- text.rotateSegmentIdentity(m);
606
+ yield* text.endSegment();
595
607
  };
596
608
  const thinkingSegmentEndArm = function* (m, { text }) {
597
609
  if (isSubFlowSegmentEnd(m))
@@ -773,6 +785,15 @@ const taskProgressArm = function* (m, { ctx, cards, panel, inst }) {
773
785
  }
774
786
  panel.noteResidency(taskId, identity.taskId);
775
787
  panel.markLive(taskId);
788
+ const cycleSeq = cycleSeqValue(m.seq);
789
+ panel.noteCycle(taskId, cycleSeq);
790
+ const finalUsage = {};
791
+ if (isCoreTaskProgressTerminal(m.status)) {
792
+ if (typeof usage.totalTokens === 'number' && Number.isFinite(usage.totalTokens))
793
+ finalUsage.totalTokens = true;
794
+ if (typeof usage.toolUses === 'number' && Number.isFinite(usage.toolUses))
795
+ finalUsage.toolUses = true;
796
+ }
776
797
  yield chrome({
777
798
  kind: 'panel_task',
778
799
  laneProof: panel.laneOf(taskId),
@@ -788,11 +809,13 @@ const taskProgressArm = function* (m, { ctx, cards, panel, inst }) {
788
809
  ...(panel.isLiveBound(taskId) ? { cardBound: true } : {}),
789
810
  toolUses: typeof usage.toolUses === 'number' ? usage.toolUses : 0,
790
811
  totalTokens: typeof usage.totalTokens === 'number' ? usage.totalTokens : 0,
812
+ ...(cycleSeq !== undefined ? { cycleSeq } : {}),
813
+ ...(finalUsage.totalTokens === true || finalUsage.toolUses === true ? { final: finalUsage } : {}),
791
814
  },
792
815
  });
793
816
  if (isCoreTaskProgressTerminal(m.status) && !panel.isLiveBound(taskId)) {
794
817
  ctx.probe?.('tick', JSON.stringify({ t: ctx.now(), taskId, lane: 'foreground', settle: m.status }));
795
- yield* panel.settleFromTerminalTick(taskId, isCoreTaskProgressTerminalNotSuccess(m.status));
818
+ yield* panel.settleFromTerminalTick(taskId, isCoreTaskProgressTerminalNotSuccess(m.status), cycleSeq);
796
819
  }
797
820
  };
798
821
  const streamEventArm = function* (m, { text }) {
@@ -1028,6 +1051,7 @@ export const ARMS = new Map([
1028
1051
  ['tool_roster_delta', toolRosterDeltaArm],
1029
1052
  ['context_usage', contextUsageArm],
1030
1053
  ['compaction_outcome', compactionOutcomeArm],
1054
+ ['compaction_started', compactionStartedArm],
1031
1055
  ['prompt_assembled', promptAssembledArm],
1032
1056
  ['wiring_manifest', wiringManifestArm],
1033
1057
  ['approval_request', approvalFrameArm('approval_request')],
@@ -7,10 +7,11 @@ export interface PanelTaskLedger {
7
7
  isLiveBound(taskId: string): boolean;
8
8
  isLive(taskId: string): boolean;
9
9
  markLive(taskId: string): void;
10
+ noteCycle(taskId: string, cycleSeq: number | undefined): void;
10
11
  noteResidency(taskId: string, residentKey?: string): void;
11
12
  start(taskId: string, agentType?: string): Generator<AdapterOutput>;
12
13
  settle(cardId: string | null, isError: boolean, report?: string): Generator<AdapterOutput>;
13
14
  settleFromNotification(taskId: string, isError: boolean, sessionId?: string): Generator<AdapterOutput>;
14
- settleFromTerminalTick(taskId: string, isError: boolean): Generator<AdapterOutput>;
15
+ settleFromTerminalTick(taskId: string, isError: boolean, cycleSeq?: number): Generator<AdapterOutput>;
15
16
  }
16
17
  export declare function createPanelTaskLedger(ctx: AdapterContext, cards: OpenCardView, inst: AdapterInstanceLedger): PanelTaskLedger;
@@ -5,7 +5,15 @@ import { SUBAGENT_TOOL_NAMES } from './wireShapes.js';
5
5
  export function createPanelTaskLedger(ctx, cards, inst) {
6
6
  const taskCardBinding = new Map();
7
7
  const livePanelTasks = new Set();
8
- const endedPanelTasks = new Set();
8
+ const endedPanelTasks = new Map();
9
+ const seenCycle = new Map();
10
+ const currentGenerationEnded = (taskId) => {
11
+ if (!endedPanelTasks.has(taskId))
12
+ return false;
13
+ const prior = endedPanelTasks.get(taskId);
14
+ const seen = seenCycle.get(taskId);
15
+ return !(prior !== undefined && seen !== undefined && prior < seen);
16
+ };
9
17
  const liveBoundPanelTasks = new Set();
10
18
  const clearResidencyBothKeys = (taskId) => clearEnginePanelTaskResidentByWire(taskId);
11
19
  const subagentTypeById = new Map();
@@ -42,6 +50,13 @@ export function createPanelTaskLedger(ctx, cards, inst) {
42
50
  markLive: (taskId) => {
43
51
  livePanelTasks.add(taskId);
44
52
  },
53
+ noteCycle: (taskId, cycleSeq) => {
54
+ if (cycleSeq === undefined)
55
+ return;
56
+ const seen = seenCycle.get(taskId);
57
+ if (seen === undefined || cycleSeq > seen)
58
+ seenCycle.set(taskId, cycleSeq);
59
+ },
45
60
  noteResidency: (taskId, residentKey = taskId) => {
46
61
  if (liveBoundPanelTasks.has(taskId))
47
62
  clearEnginePanelTaskResident(residentKey);
@@ -69,9 +84,9 @@ export function createPanelTaskLedger(ctx, cards, inst) {
69
84
  continue;
70
85
  if (cardId === null && !liveBoundPanelTasks.has(taskId))
71
86
  continue;
72
- if (endedPanelTasks.has(taskId))
87
+ if (currentGenerationEnded(taskId))
73
88
  continue;
74
- endedPanelTasks.add(taskId);
89
+ endedPanelTasks.set(taskId, undefined);
75
90
  const mintLane = laneMinterFor(taskId);
76
91
  const agentType = subagentTypeById.get(taskId);
77
92
  yield chrome({
@@ -90,9 +105,9 @@ export function createPanelTaskLedger(ctx, cards, inst) {
90
105
  },
91
106
  *settleFromNotification(taskId, isError, sessionId) {
92
107
  clearResidencyBothKeys(taskId);
93
- if (endedPanelTasks.has(taskId))
108
+ if (currentGenerationEnded(taskId))
94
109
  return;
95
- endedPanelTasks.add(taskId);
110
+ endedPanelTasks.set(taskId, undefined);
96
111
  yield chrome({
97
112
  kind: 'panel_task',
98
113
  laneProof: mainLane(),
@@ -108,10 +123,18 @@ export function createPanelTaskLedger(ctx, cards, inst) {
108
123
  });
109
124
  }
110
125
  },
111
- *settleFromTerminalTick(taskId, isError) {
112
- if (endedPanelTasks.has(taskId))
126
+ *settleFromTerminalTick(taskId, isError, cycleSeq) {
127
+ if (endedPanelTasks.has(taskId)) {
128
+ const prior = endedPanelTasks.get(taskId);
129
+ if (cycleSeq === undefined || prior === undefined || cycleSeq <= prior)
130
+ return;
131
+ }
132
+ const seen = seenCycle.get(taskId);
133
+ if (cycleSeq !== undefined && seen !== undefined && cycleSeq < seen) {
134
+ yield chrome({ kind: 'panel_task', laneProof: laneMinterFor(taskId)(), event: panelEndFact(taskId, isError, { cycleSeq }) });
113
135
  return;
114
- endedPanelTasks.add(taskId);
136
+ }
137
+ endedPanelTasks.set(taskId, cycleSeq);
115
138
  clearResidencyBothKeys(taskId);
116
139
  const mintLane = laneMinterFor(taskId);
117
140
  const card = taskCardBinding.get(taskId);
@@ -138,7 +161,7 @@ export function createPanelTaskLedger(ctx, cards, inst) {
138
161
  yield chrome({
139
162
  kind: 'panel_task',
140
163
  laneProof: mintLane(),
141
- event: panelEndFact(taskId, isError),
164
+ event: panelEndFact(taskId, isError, cycleSeq !== undefined ? { cycleSeq } : undefined),
142
165
  });
143
166
  },
144
167
  };
@@ -36,7 +36,7 @@ export interface TextStream {
36
36
  replaceThinkingSegment(content: string, anchor?: Frame): ThinkingSegmentReplacement;
37
37
  segmentId(): string;
38
38
  anchorWindow(frame: Frame): void;
39
- rotateSegmentIdentity(anchor: Frame): void;
39
+ endSegment(): Generator<AdapterOutput>;
40
40
  stampSegmentIdentity(out: AdapterOutput): AdapterOutput;
41
41
  readonly answerLength: number;
42
42
  }
@@ -38,7 +38,6 @@ export function createTextStream(ctx, idOf) {
38
38
  let segmentCommitted = '';
39
39
  let previousSegmentCommitted = '';
40
40
  let segmentWindowCloseArmed = false;
41
- let segmentSealed = '';
42
41
  const flushEveryMs = typeof ctx.coalesceIntervalMs === 'number' && ctx.coalesceIntervalMs >= 0
43
42
  ? ctx.coalesceIntervalMs
44
43
  : FLUSH_INTERVAL_MS;
@@ -55,6 +54,25 @@ export function createTextStream(ctx, idOf) {
55
54
  segmentIdCache = idOf(segmentWindowAnchor ?? {}, 'segment');
56
55
  return segmentIdCache;
57
56
  };
57
+ const openSegmentWindow = (frame) => {
58
+ if (segmentWindowAnchor !== null)
59
+ return;
60
+ segmentWindowAnchor = frame;
61
+ segmentIdCache = null;
62
+ };
63
+ const closeSegmentWindow = () => {
64
+ committedTextRows = [];
65
+ segmentWindowAnchor = null;
66
+ segmentIdCache = null;
67
+ };
68
+ const consumeArmedClose = () => {
69
+ if (!segmentWindowCloseArmed)
70
+ return;
71
+ segmentWindowCloseArmed = false;
72
+ previousSegmentCommitted = '';
73
+ segmentCommitted = '';
74
+ closeSegmentWindow();
75
+ };
58
76
  function* takeThinking() {
59
77
  if (thinking.length === 0)
60
78
  return;
@@ -77,9 +95,11 @@ export function createTextStream(ctx, idOf) {
77
95
  yield transcript(msg, ctx.now());
78
96
  }
79
97
  function* emitAnswerSegment() {
80
- const body = segmentSealed + answerSegment;
98
+ const body = answerSegment;
81
99
  if (body.length === 0)
82
100
  return;
101
+ if (segmentAnchor !== null)
102
+ openSegmentWindow(segmentAnchor);
83
103
  const anchor = segmentAnchor ?? {};
84
104
  const msg = {
85
105
  type: 'assistant',
@@ -90,10 +110,8 @@ export function createTextStream(ctx, idOf) {
90
110
  };
91
111
  const committedTextBeforeRow = committedText;
92
112
  committedText += body;
93
- segmentCommitted += answerSegment;
94
- if (answerSegment.length > 0)
95
- committedTextRows.push({ text: body, uuid: msg.uuid, sealedPrefix: segmentSealed, msgSerial: messageSerial, msgTextBefore: committedTextBeforeRow });
96
- segmentSealed = '';
113
+ segmentCommitted += body;
114
+ committedTextRows.push({ text: body, uuid: msg.uuid, msgSerial: messageSerial, msgTextBefore: committedTextBeforeRow });
97
115
  answerSegment = '';
98
116
  segmentAnchor = null;
99
117
  segmentLast = null;
@@ -108,7 +126,7 @@ export function createTextStream(ctx, idOf) {
108
126
  segmentCommitted = '';
109
127
  }
110
128
  function* takeAnswerSegmentOnIdle() {
111
- const body = segmentSealed + answerSegment;
129
+ const body = answerSegment;
112
130
  if (body.length === 0)
113
131
  return;
114
132
  if (idleFlushUsedInSegment)
@@ -149,28 +167,20 @@ export function createTextStream(ctx, idOf) {
149
167
  }
150
168
  return {
151
169
  *feedText(delta, frame) {
152
- if (segmentWindowCloseArmed) {
153
- segmentWindowCloseArmed = false;
154
- previousSegmentCommitted = '';
155
- segmentCommitted = '';
156
- committedTextRows = [];
157
- }
170
+ consumeArmedClose();
158
171
  if (thinking.length > 0 || thinkingPending.length > 0) {
159
172
  yield* drainLive();
160
173
  yield* takeThinking();
161
174
  }
162
- if (answerSegment.length === 0 && segmentSealed.length === 0)
175
+ if (answerSegment.length === 0)
163
176
  segmentAnchor = frame;
164
177
  segmentLast = frame;
165
- if (segmentWindowAnchor === null)
166
- segmentWindowAnchor = frame;
178
+ openSegmentWindow(frame);
167
179
  answer += delta;
168
180
  answerSegment += delta;
169
181
  textPending += delta;
170
182
  },
171
183
  *feedThinking(delta, frame) {
172
- if (segmentWindowAnchor === null)
173
- segmentWindowAnchor = frame;
174
184
  if (thinkingSettled) {
175
185
  if (thinking.length > 0) {
176
186
  yield* drainLive();
@@ -212,7 +222,7 @@ export function createTextStream(ctx, idOf) {
212
222
  const rows = uuidsUnique ? rowsAll : [];
213
223
  const rowUuids = rows.map((r) => r.uuid);
214
224
  const committedRowsOut = committedPrefixDiverged && rows.length > 0
215
- ? rows.map((r, i) => ({ uuid: r.uuid, text: i === 0 ? r.sealedPrefix + content : r.sealedPrefix }))
225
+ ? rows.map((r, i) => ({ uuid: r.uuid, text: i === 0 ? content : '' }))
216
226
  : undefined;
217
227
  const attribution = uuidsUnique
218
228
  ? {
@@ -287,11 +297,12 @@ export function createTextStream(ctx, idOf) {
287
297
  }
288
298
  }
289
299
  else {
290
- segmentSealed += verdict.tail;
300
+ answerSegment = verdict.tail;
291
301
  if (diverged && anchor !== undefined)
292
302
  segmentLast = anchor;
293
303
  }
294
- answerSegment = '';
304
+ if (committedPrefixDiverged)
305
+ answerSegment = '';
295
306
  if (answer.endsWith(liveSegment)) {
296
307
  answer = answer.slice(0, answer.length - liveSegment.length) + content;
297
308
  }
@@ -305,7 +316,6 @@ export function createTextStream(ctx, idOf) {
305
316
  return { diverged, committedPrefixLen, committedPrefixDiverged, ...attribution };
306
317
  },
307
318
  hasPendingContent: () => thinking.length > 0 ||
308
- segmentSealed.length > 0 ||
309
319
  answerSegment.length > 0 ||
310
320
  thinkingPending.length > 0 ||
311
321
  textPending.length > 0,
@@ -365,13 +375,21 @@ export function createTextStream(ctx, idOf) {
365
375
  },
366
376
  segmentId: segmentIdNow,
367
377
  anchorWindow: (frame) => {
368
- if (segmentWindowAnchor === null)
369
- segmentWindowAnchor = frame;
378
+ openSegmentWindow(frame);
370
379
  },
371
- rotateSegmentIdentity: (anchor) => {
372
- committedTextRows = [];
373
- segmentWindowAnchor = anchor;
374
- segmentIdCache = null;
380
+ *endSegment() {
381
+ try {
382
+ yield* emitAnswerSegment();
383
+ }
384
+ finally {
385
+ segmentAnchor = null;
386
+ segmentLast = null;
387
+ segmentCommitted = '';
388
+ previousSegmentCommitted = '';
389
+ idleFlushUsedInSegment = false;
390
+ textBlockOpen = false;
391
+ closeSegmentWindow();
392
+ }
375
393
  },
376
394
  stampSegmentIdentity: (out) => {
377
395
  if (out.plane !== 'transcript')
@@ -385,6 +403,11 @@ export function createTextStream(ctx, idOf) {
385
403
  const last = blocks[blocks.length - 1];
386
404
  if (last === undefined || last.type !== 'text' || typeof last.text !== 'string')
387
405
  return out;
406
+ if (segmentWindowAnchor === null) {
407
+ const rowUuid = out.message.uuid;
408
+ openSegmentWindow(typeof rowUuid === 'string' ? { uuid: rowUuid } : {});
409
+ }
410
+ ;
388
411
  out.message[SEMA_SEGMENT_ID_KEY] = segmentIdNow();
389
412
  return out;
390
413
  },
@@ -40,11 +40,14 @@ export type ReopenCardVerdict = {
40
40
  dismissedByUser?: true;
41
41
  _sema_noPresentationSurface?: true;
42
42
  _sema_errorCode?: string;
43
+ _sema_reopenRefusal?: PlanReviewReopenRefusal;
43
44
  } | {
44
45
  reopened: true;
45
46
  firstSight: boolean;
46
47
  presented?: boolean;
47
48
  };
49
+ export declare const PLAN_REVIEW_REOPEN_REFUSALS: readonly ["invalid_call", "no_delivery_path", "not_presented", "gate_record_gone", "internal_error"];
50
+ export type PlanReviewReopenRefusal = (typeof PLAN_REVIEW_REOPEN_REFUSALS)[number];
48
51
  export interface RunningChoiceRequest {
49
52
  taskId: string;
50
53
  status: string;
@@ -140,6 +143,8 @@ export type SelfHealOutcome = {
140
143
  taskId: string;
141
144
  detail: string;
142
145
  delivery: 'rejected' | 'unknown';
146
+ errorCode?: string;
147
+ runStatus?: string;
143
148
  } | {
144
149
  kind: 'running-attach';
145
150
  taskId: string;
@@ -229,6 +234,8 @@ export interface ActiveRunSelfHealCopy {
229
234
  freshSession?: string;
230
235
  keepSessionWayOut?: () => string | null;
231
236
  engineDecidePath?: boolean;
237
+ endRun?: string;
238
+ wakeSession?: string | null;
232
239
  rowFor?: (outcome: SelfHealOutcome, signal: ActiveRunBusySignal | null | undefined) => string | undefined;
233
240
  headlessRowFor?: (signal: ActiveRunBusySignal) => string | undefined;
234
241
  }