@sema-agent/client-core 0.86.0 → 0.88.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 (57) hide show
  1. package/CHANGELOG.md +128 -0
  2. package/README.md +18 -12
  3. package/dist/adapt/arms.js +9 -0
  4. package/dist/adapter/downstream/eventToSdkMessage.js +14 -1
  5. package/dist/adapter/downstream/terminalToSdkResult.js +4 -1
  6. package/dist/adapter/downstream/wiringManifestView.d.ts +2 -0
  7. package/dist/adapter/downstream/wiringManifestView.js +1 -0
  8. package/dist/adapter/runStream.js +75 -2
  9. package/dist/adapter/types.d.ts +3 -0
  10. package/dist/decideReceipt.d.ts +1 -1
  11. package/dist/decideReceipt.js +1 -1
  12. package/dist/detachWire.d.ts +6 -1
  13. package/dist/detachWire.js +22 -1
  14. package/dist/displayUntrusted.d.ts +4 -0
  15. package/dist/displayUntrusted.js +1657 -573
  16. package/dist/engineErrorCodes.d.ts +2 -0
  17. package/dist/engineErrorCodes.js +1 -0
  18. package/dist/engineNoticeCodes.d.ts +20 -0
  19. package/dist/engineNoticeCodes.js +71 -0
  20. package/dist/engineWireFor.d.ts +1 -0
  21. package/dist/engineWireFor.js +1 -1
  22. package/dist/gateOutcome.d.ts +4 -0
  23. package/dist/gateOutcome.js +5 -0
  24. package/dist/generated/engineFactTables.d.ts +1 -0
  25. package/dist/generated/engineFactTables.js +3 -0
  26. package/dist/generated/engineNoticeTables.js +2 -0
  27. package/dist/hitl/crashConverged.d.ts +2 -1
  28. package/dist/hitl/crashConverged.js +23 -3
  29. package/dist/hitl/hitlBridge.d.ts +4 -0
  30. package/dist/hitl/hitlBridge.js +6 -0
  31. package/dist/hitl/parkResolver.js +17 -12
  32. package/dist/hitl/planReviewWire.js +30 -10
  33. package/dist/hitl/suspendedReopen.d.ts +7 -0
  34. package/dist/hitl/suspendedReopen.js +38 -7
  35. package/dist/hitl/toolApprovalWire.js +4 -5
  36. package/dist/index.d.ts +7 -0
  37. package/dist/index.js +4 -0
  38. package/dist/promptDelivery.d.ts +20 -0
  39. package/dist/promptDelivery.js +153 -0
  40. package/dist/registryConflict.d.ts +3 -0
  41. package/dist/registryConflict.js +44 -0
  42. package/dist/request/taskRequest.d.ts +1 -0
  43. package/dist/request/taskRequest.js +25 -1
  44. package/dist/resumeRefusalCopy.d.ts +8 -6
  45. package/dist/resumeRefusalCopy.js +41 -19
  46. package/dist/rewindArchiveCapability.js +5 -0
  47. package/dist/seam.d.ts +12 -1
  48. package/dist/seam.js +7 -0
  49. package/dist/sessionMemoryErase.d.ts +76 -0
  50. package/dist/sessionMemoryErase.js +432 -0
  51. package/dist/subagent/engineSubagentResume.js +2 -1
  52. package/dist/toolHistoryMismatch.d.ts +63 -0
  53. package/dist/toolHistoryMismatch.js +425 -0
  54. package/dist/workflowClient.d.ts +3 -2
  55. package/dist/workflowClient.js +3 -3
  56. package/docs/INTEGRATION-CLIENTS.md +598 -13
  57. package/package.json +2 -2
@@ -10,11 +10,19 @@ import { registerSubagentAlias, registerSubagentContentAlias } from '../subagent
10
10
  import { readAsyncLaunchedAgentReceipt } from '../toolResult.js';
11
11
  import { isWorkflowAgentTaskId, recordWorkflowAgentTaskId } from '../workflow.js';
12
12
  import { isTerminalStatus } from '../runTerminal.js';
13
+ import { readToolHistoryMismatchKey } from '../toolHistoryMismatch.js';
13
14
  import { resolveEnginePanelTaskId } from '../engineAgentPanelStore.js';
14
15
  import { fleetRowAgentType } from '../fleet/fleetRowAgentType.js';
15
16
  import { chrome, mainLane, transcript, messageIdentityOf } from './ids.js';
16
17
  import { wiringManifestViewOf } from '../adapter/downstream/wiringManifestView.js';
17
18
  import { CANCEL_MESSAGE, decisionOf, flattenWireOutput, REJECT_MESSAGE, sanitizeToolUseBlock, shortTaskLabel, TASK_TOOL_NAMES, WORKFLOW_TOOL_NAMES, } from './wireShapes.js';
19
+ function toolHistoryKeyCarry(m) {
20
+ if (m._sema_api_error_message !== true)
21
+ return {};
22
+ const raw = m._sema_tool_history_mismatch;
23
+ const key = readToolHistoryMismatchKey(typeof raw === 'object' && raw !== null ? raw : undefined);
24
+ return key === undefined ? {} : { _sema_tool_history_mismatch: key };
25
+ }
18
26
  const assistantArm = function* (m, { ctx, idOf, text, cards, inst }) {
19
27
  const message = m.message;
20
28
  const blocks = Array.isArray(message?.content)
@@ -120,6 +128,7 @@ const assistantArm = function* (m, { ctx, idOf, text, cards, inst }) {
120
128
  session_id: ctx.sessionId,
121
129
  parent_tool_use_id: null,
122
130
  ...(m._sema_api_error_message === true ? { _sema_api_error_message: true } : {}),
131
+ ...toolHistoryKeyCarry(m),
123
132
  }, ctx.now());
124
133
  text.markEmittedText(textBlock.text);
125
134
  }
@@ -549,7 +549,8 @@ function wiringManifestSupersetBody(ev) {
549
549
  const autoConsolidation = projectAutoConsolidationSection(ev.autoConsolidation);
550
550
  const readDeny = projectReadDenySection(ev.readDeny);
551
551
  const hands = projectHandsSection(ev);
552
- if (modelGate === undefined && autoMode === undefined && mcp === undefined && tools === undefined && hooks === undefined && lsp === undefined && writeProtection === undefined && autoConsolidation === undefined && readDeny === undefined && hands === undefined)
552
+ const fileHistory = projectFileHistorySection(ev);
553
+ if (modelGate === undefined && autoMode === undefined && mcp === undefined && tools === undefined && hooks === undefined && lsp === undefined && writeProtection === undefined && autoConsolidation === undefined && readDeny === undefined && hands === undefined && fileHistory === undefined)
553
554
  return undefined;
554
555
  return {
555
556
  ...(modelGate !== undefined ? { _sema_modelGate: modelGate } : {}),
@@ -562,8 +563,20 @@ function wiringManifestSupersetBody(ev) {
562
563
  ...(autoConsolidation !== undefined ? { _sema_autoConsolidation: autoConsolidation } : {}),
563
564
  ...(readDeny !== undefined ? { _sema_readDeny: readDeny } : {}),
564
565
  ...(hands !== undefined ? { _sema_hands: hands } : {}),
566
+ ...(fileHistory !== undefined ? { _sema_fileHistory: fileHistory } : {}),
565
567
  };
566
568
  }
569
+ function projectFileHistorySection(holder) {
570
+ try {
571
+ if (!Object.hasOwn(holder, 'fileHistory'))
572
+ return undefined;
573
+ const raw = holder.fileHistory;
574
+ return typeof raw === 'string' && raw.length > 0 ? raw : undefined;
575
+ }
576
+ catch {
577
+ return undefined;
578
+ }
579
+ }
567
580
  function projectWriteProtectionSection(raw) {
568
581
  if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
569
582
  return undefined;
@@ -499,6 +499,7 @@ function errorResult(ctx, parts) {
499
499
  ...selectedModelParts(parts.model),
500
500
  ...(parts.salvagedResult !== undefined ? { _sema_salvaged_result: parts.salvagedResult } : {}),
501
501
  ...(parts.outcomeUnknown === true ? { _sema_outcome: 'unknown' } : {}),
502
+ ...(parts.parkFailedReason !== undefined ? { _sema_park_failed_reason: washCredentials(parts.parkFailedReason) } : {}),
502
503
  });
503
504
  }
504
505
  export function doneToSdkResult(ev, ctx, observed) {
@@ -513,7 +514,9 @@ export function doneToSdkResult(ev, ctx, observed) {
513
514
  const durationMs = elapsedMs(ctx);
514
515
  const errorCode = runTerminalCode(terminal);
515
516
  const degraded = degradedOf(r);
516
- const errorBase = { durationMs, stats, model: r.model, errorCode, degraded, observed, facts: effectiveFactParts(rec) };
517
+ const parkFailedRaw = ev._sema_park_failed_reason;
518
+ const parkFailedReason = typeof parkFailedRaw === 'string' && parkFailedRaw.length > 0 ? parkFailedRaw : undefined;
519
+ const errorBase = { durationMs, stats, model: r.model, errorCode, degraded, observed, facts: effectiveFactParts(rec), parkFailedReason };
517
520
  if (terminal?.kind === 'failed') {
518
521
  const failedCode = terminal.code;
519
522
  const failedMessage = terminal.message;
@@ -11,6 +11,7 @@ export type WiringManifestSections = {
11
11
  _sema_autoConsolidation?: WiringManifestAutoConsolidationView;
12
12
  _sema_readDeny?: WiringManifestReadDenyView;
13
13
  _sema_hands?: WiringManifestHandsView;
14
+ _sema_fileHistory?: string;
14
15
  eventId?: string;
15
16
  };
16
17
  export interface WiringManifestView {
@@ -24,6 +25,7 @@ export interface WiringManifestView {
24
25
  autoConsolidation?: WiringManifestAutoConsolidationView;
25
26
  readDeny?: WiringManifestReadDenyView;
26
27
  hands?: WiringManifestHandsView;
28
+ fileHistory?: string;
27
29
  eventId?: string;
28
30
  }
29
31
  export declare function wiringManifestViewOf(s: WiringManifestSections): WiringManifestView | undefined;
@@ -15,6 +15,7 @@ export function wiringManifestViewOf(s) {
15
15
  ...(isObj(s._sema_autoConsolidation) ? { autoConsolidation: s._sema_autoConsolidation } : {}),
16
16
  ...(isObj(s._sema_readDeny) ? { readDeny: s._sema_readDeny } : {}),
17
17
  ...(isObj(s._sema_hands) && typeof s._sema_hands.mounted === 'boolean' ? { hands: s._sema_hands } : {}),
18
+ ...(typeof s._sema_fileHistory === 'string' && s._sema_fileHistory.length > 0 ? { fileHistory: s._sema_fileHistory } : {}),
18
19
  };
19
20
  if (Object.keys(view).length === 0)
20
21
  return undefined;
@@ -5,9 +5,11 @@ import { readRunCostFacts, terminalToSdkResult, TOOL_INPUT_JOIN_MAX_CALLS } from
5
5
  import { coerceOutput, publishSubagentContentEvent } from '../subagentContentStore.js';
6
6
  import { ACTIVE_RUN_BUSY_ERROR_CODE, OUTPUT_INVALID, isCorruptSessionCode, isLimitsExceededCode } from '../engineErrorCodes.js';
7
7
  import { corruptSessionContent } from '../corruptSessionCopy.js';
8
+ import { classifyToolHistoryMismatch, noteToolHistoryTerminal, openToolHistoryGeneration, TOOL_HISTORY_REWIND_SENTENCE, toolHistoryMismatchRowKey, toolHistoryRepeatSentence, toolHistoryRewindOffered, } from '../toolHistoryMismatch.js';
8
9
  import { isReviewPark, readRunTerminal, runTerminalCode } from '../runTerminal.js';
9
10
  import { washCredentials } from '../displayUntrusted.js';
10
11
  import { ccToolDenialKindForToolEnd, gateDeniedBy, gateOutcomeOf } from '../gateOutcome.js';
12
+ import { resumeReopenContent, resumeReopenFromError, suspendedReopenOf } from '../hitl/suspendedReopen.js';
11
13
  import { isCcToolDenialKind, isCcToolDenialKindADenial, isGateDeniedByWord } from '../gateVocabulary.js';
12
14
  const mainLane = () => ({ lane: 'main' });
13
15
  function emitChromeFireAndForget(ctx, event) {
@@ -19,6 +21,27 @@ function emitChromeFireAndForget(ctx, event) {
19
21
  }
20
22
  catch { }
21
23
  }
24
+ function suspendedReopenedNotice(ev) {
25
+ try {
26
+ const reopen = suspendedReopenOf(ev);
27
+ if (reopen.kind !== 'reopened')
28
+ return undefined;
29
+ const detail = resumeReopenFromError({ errorCode: reopen.code, retriable: true });
30
+ const rawTaskId = ev.taskId;
31
+ const eventId = eventSeq(ev);
32
+ return {
33
+ kind: 'suspended_reopened',
34
+ laneProof: mainLane(),
35
+ reopen,
36
+ ...(detail !== null ? { content: resumeReopenContent(detail) } : {}),
37
+ ...(typeof eventId === 'string' && eventId.length > 0 ? { eventId } : {}),
38
+ ...(typeof rawTaskId === 'string' && rawTaskId.length > 0 ? { taskId: rawTaskId } : {}),
39
+ };
40
+ }
41
+ catch {
42
+ return undefined;
43
+ }
44
+ }
22
45
  export function pendingGateIsProvablyDifferent(prev, next) {
23
46
  const a = prev?.checkpointId;
24
47
  const b = next?.checkpointId;
@@ -98,7 +121,7 @@ export function isModelOutputErrorRowText(text) {
98
121
  return text.trimStart().startsWith(`${MODEL_OUTPUT_ERROR_PREFIX}:`);
99
122
  }
100
123
  export const OUTCOME_UNKNOWN_ROW_PREFIX = 'Outcome unknown';
101
- function syntheticTerminalRow(ctx, text) {
124
+ function syntheticTerminalRow(ctx, text, historyKey) {
102
125
  return stamp(ctx, {
103
126
  uuid: undefined,
104
127
  session_id: undefined,
@@ -106,8 +129,22 @@ function syntheticTerminalRow(ctx, text) {
106
129
  message: { role: 'assistant', model: '<synthetic>', content: [{ type: 'text', text: washCredentials(text) }] },
107
130
  parent_tool_use_id: null,
108
131
  _sema_api_error_message: true,
132
+ ...(historyKey !== undefined ? { _sema_tool_history_mismatch: historyKey } : {}),
109
133
  });
110
134
  }
135
+ function engineRunIdOf(result) {
136
+ const v = result?.runId;
137
+ return typeof v === 'string' && v.length > 0 ? v : undefined;
138
+ }
139
+ function engineSessionIdOf(result) {
140
+ const v = result?.sessionId;
141
+ return typeof v === 'string' && v.length > 0 ? v : undefined;
142
+ }
143
+ function providerFailureStatusOf(result) {
144
+ const af = result?.apiFailure;
145
+ const status = typeof af === 'object' && af !== null ? af.status : undefined;
146
+ return typeof status === 'number' && Number.isFinite(status) ? status : undefined;
147
+ }
111
148
  export function isOutcomeUnknownRowText(text) {
112
149
  return text.trimStart().startsWith(`${OUTCOME_UNKNOWN_ROW_PREFIX}:`);
113
150
  }
@@ -192,6 +229,7 @@ async function* runStreamInner(events, ctx, handle = {}) {
192
229
  const seen = new Set();
193
230
  if (ctx.startedAtMs === undefined)
194
231
  ctx.startedAtMs = Date.now();
232
+ const historyGeneration = openToolHistoryGeneration();
195
233
  const nestedUsageByTask = new Map();
196
234
  let usageMissingObserved = false;
197
235
  const toolInputByCallId = new Map();
@@ -478,7 +516,37 @@ async function* runStreamInner(events, ctx, handle = {}) {
478
516
  const sessionUnreadable = ev.type === 'failed'
479
517
  ? isCorruptSessionCode(ev.errorCode)
480
518
  : doneTerminal?.kind === 'failed' && isCorruptSessionCode(doneTerminal.code);
481
- yield syntheticTerminalRow(ctx, sessionUnreadable ? `${rowText}\n${corruptSessionContent()}` : rowText);
519
+ const historyMismatch = !busy.busy && !governance && !isModelOutputErrorText(errText)
520
+ ? classifyToolHistoryMismatch({
521
+ code: ev.type === 'failed' ? ev.errorCode : runTerminalCode(doneTerminal),
522
+ status: ev.type === 'done' ? providerFailureStatusOf(ev.result) : undefined,
523
+ message: errText,
524
+ })
525
+ : null;
526
+ const historyEchoedSid = ev.type === 'done' ? engineSessionIdOf(ev.result) : undefined;
527
+ const historyRepeat = noteToolHistoryTerminal({
528
+ sessionId: historyEchoedSid ?? ctx.sessionId,
529
+ sessionEchoed: historyEchoedSid !== undefined,
530
+ generation: historyGeneration,
531
+ runId: ev.type === 'done' ? engineRunIdOf(ev.result) : undefined,
532
+ replay: ev.type === 'done' && ev.replay === true,
533
+ mismatch: historyMismatch,
534
+ });
535
+ const rewindLine = historyMismatch !== null && ctx.lane !== 'print' && ctx.lane !== 'utility' && toolHistoryRewindOffered(ctx.offersRewind)
536
+ ? `\n${TOOL_HISTORY_REWIND_SENTENCE}${historyRepeat !== undefined && historyRepeat >= 2 ? ` ${toolHistoryRepeatSentence(historyRepeat)}` : ''}`
537
+ : '';
538
+ yield syntheticTerminalRow(ctx, `${sessionUnreadable ? `${rowText}\n${corruptSessionContent()}` : rowText}${rewindLine}`, historyMismatch === null ? undefined : toolHistoryMismatchRowKey(historyMismatch, historyRepeat));
539
+ }
540
+ else {
541
+ const echoedSid = ev.type === 'done' ? engineSessionIdOf(ev.result) : undefined;
542
+ noteToolHistoryTerminal({
543
+ sessionId: echoedSid ?? ctx.sessionId,
544
+ sessionEchoed: echoedSid !== undefined,
545
+ generation: historyGeneration,
546
+ runId: ev.type === 'done' ? engineRunIdOf(ev.result) : undefined,
547
+ replay: ev.type === 'done' && ev.replay === true,
548
+ mismatch: null,
549
+ });
482
550
  }
483
551
  if (ev.type === 'done' && isReviewPark(doneTerminal) && ctx.emitChrome) {
484
552
  try {
@@ -514,6 +582,11 @@ async function* runStreamInner(events, ctx, handle = {}) {
514
582
  yield resultFrame;
515
583
  return;
516
584
  }
585
+ if (ev.type === 'suspended') {
586
+ const notice = suspendedReopenedNotice(ev);
587
+ if (notice !== undefined)
588
+ emitChromeFireAndForget(ctx, notice);
589
+ }
517
590
  const projection = eventToSdkMessage(ev, ctx);
518
591
  if (projection.kind === 'message') {
519
592
  yield projection.message;
@@ -18,6 +18,9 @@ export interface EmitContext {
18
18
  startedAtMs?: number;
19
19
  model?: string;
20
20
  lane?: RequestLane;
21
+ offersRewind?: boolean | {
22
+ readonly engineBaseUrl: string;
23
+ };
21
24
  emitChrome?(event: ChromeEvent): void | Promise<void>;
22
25
  onDroppedFrame?(info: DroppedFrameInfo): void;
23
26
  }
@@ -1,5 +1,5 @@
1
1
  import { type GateOutcomeView } from './gateOutcome.js';
2
- import { type ResumeReopenDetail } from './resumeRefusalCopy.js';
2
+ import { type ResumeReopenDetail } from './hitl/suspendedReopen.js';
3
3
  export interface DecideReceiptView {
4
4
  status?: string;
5
5
  taskId?: string;
@@ -1,5 +1,5 @@
1
1
  import { gateOutcomeOf } from './gateOutcome.js';
2
- import { resumeReopenFromError } from './resumeRefusalCopy.js';
2
+ import { resumeReopenFromError } from './hitl/suspendedReopen.js';
3
3
  import { DECIDE_CLAIM_LOST, DECIDE_GATE_MOVED, DECIDE_NOT_PARKED, DECIDE_WORKFLOW_HOST_UNKNOWN, DECIDE_WORKFLOW_LANE_CODES, DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED, isDecideParkMovedCode, } from './engineErrorCodes.js';
4
4
  import { effectiveWireErrorCode } from './wireErrorTriage.js';
5
5
  import { readErrorString } from './wireFailureShape.js';
@@ -1,4 +1,5 @@
1
1
  import { type EnvLike } from './hostEnv.js';
2
+ import { type WireAuthTokenSource } from './engineWireSdk.js';
2
3
  export declare const DETACH_HEADER = "x-detach-on-disconnect";
3
4
  export declare const HEADLESS_DETACH_ENV = "SEMA_HEADLESS_DETACH";
4
5
  export declare const DETACH_WIRE_MIN_ENGINE: readonly [number, number, number];
@@ -36,7 +37,11 @@ export interface DetachCancelArm {
36
37
  principal: string | undefined;
37
38
  getTaskId: () => string | null;
38
39
  }
39
- export declare function armDetachCancel(arm: DetachCancelArm): void;
40
+ export declare function armDetachCancel(arm: Omit<DetachCancelArm, 'authToken'> & {
41
+ authToken: WireAuthTokenSource | {
42
+ mode: 'loopback-unauthed';
43
+ };
44
+ }): void;
40
45
  export declare function isDetachArmed(): boolean;
41
46
  export declare function detachedTaskId(): string | null;
42
47
  export declare function detachCancelArm(): DetachCancelArm | null;
@@ -1,6 +1,7 @@
1
1
  import { hostEnv } from './hostEnv.js';
2
2
  import { envFlagOff } from './envFlag.js';
3
3
  import { versionSupportsLimits } from './limitsWire.js';
4
+ import { resolveWireAuth } from './engineWireSdk.js';
4
5
  export const DETACH_HEADER = 'x-detach-on-disconnect';
5
6
  export const HEADLESS_DETACH_ENV = 'SEMA_HEADLESS_DETACH';
6
7
  export const DETACH_WIRE_MIN_ENGINE = [1, 196, 0];
@@ -80,6 +81,17 @@ let cancelArm = null;
80
81
  export function armDetachCancel(arm) {
81
82
  cancelArm = arm;
82
83
  }
84
+ function armAuthNow(baseUrl, source) {
85
+ let token;
86
+ try {
87
+ const v = source();
88
+ token = typeof v === 'string' ? v : undefined;
89
+ }
90
+ catch {
91
+ token = undefined;
92
+ }
93
+ return resolveWireAuth(baseUrl, token);
94
+ }
83
95
  export function isDetachArmed() {
84
96
  return cancelArm !== null;
85
97
  }
@@ -87,7 +99,16 @@ export function detachedTaskId() {
87
99
  return cancelArm?.getTaskId() ?? null;
88
100
  }
89
101
  export function detachCancelArm() {
90
- return cancelArm;
102
+ const arm = cancelArm;
103
+ if (arm === null)
104
+ return null;
105
+ const source = arm.authToken;
106
+ if (typeof source === 'function') {
107
+ const view = Object.defineProperties(Object.create(Object.getPrototypeOf(arm)), Object.getOwnPropertyDescriptors(arm));
108
+ Object.defineProperty(view, 'authToken', { value: armAuthNow(arm.baseUrl, source), enumerable: true, writable: true, configurable: true });
109
+ return view;
110
+ }
111
+ return arm;
91
112
  }
92
113
  export function _resetDetachWireForTest() {
93
114
  cancelArm = null;
@@ -33,5 +33,9 @@ export interface DisplayUntrustedMarked {
33
33
  readonly text: string;
34
34
  readonly marks: readonly DisplayMarkSpan[];
35
35
  }
36
+ export declare function credentialWashPasses(text: string, opts?: DisplayUntrustedOptions | null): {
37
+ passes: number;
38
+ capped: boolean;
39
+ };
36
40
  export declare function displayUntrusted(text: string, opts?: DisplayUntrustedOptions): string;
37
41
  export declare function displayUntrustedMarks(text: string, opts?: DisplayUntrustedOptions): DisplayUntrustedMarked;