@sema-agent/client-core 0.90.0 → 0.92.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 (172) hide show
  1. package/CHANGELOG.md +365 -0
  2. package/README.md +48 -32
  3. package/dist/adapt/arms.js +13 -12
  4. package/dist/adapt/panelTasks.d.ts +0 -2
  5. package/dist/adapt/panelTasks.js +6 -26
  6. package/dist/adapt.js +2 -2
  7. package/dist/adapter/activeRunSelfHeal.d.ts +0 -2
  8. package/dist/adapter/activeRunSelfHeal.js +5 -27
  9. package/dist/adapter/downstream/eventToSdkMessage.js +4 -2
  10. package/dist/adapter/downstream/terminalToSdkResult.js +16 -7
  11. package/dist/adapter/downstream/wiringManifestView.d.ts +6 -0
  12. package/dist/adapter/downstream/wiringManifestView.js +16 -0
  13. package/dist/adapter/runStream.js +39 -20
  14. package/dist/askSurvivesStandingAnswer.d.ts +13 -0
  15. package/dist/askSurvivesStandingAnswer.js +53 -0
  16. package/dist/attachmentSeatCapability.d.ts +11 -0
  17. package/dist/attachmentSeatCapability.js +27 -0
  18. package/dist/attachmentsWireCaps.d.ts +9 -0
  19. package/dist/attachmentsWireCaps.js +74 -21
  20. package/dist/autoModeUnavailable.js +3 -2
  21. package/dist/cloudConfigWireCaps.js +5 -4
  22. package/dist/compensations.js +13 -17
  23. package/dist/controlRouter.d.ts +32 -25
  24. package/dist/controlRouter.js +166 -63
  25. package/dist/coreValuePorts.d.ts +4 -2
  26. package/dist/coreValuePorts.js +5 -0
  27. package/dist/decideFailureNote.js +7 -3
  28. package/dist/decideReceipt.d.ts +9 -0
  29. package/dist/decideReceipt.js +62 -1
  30. package/dist/disableSkillsWire.d.ts +1 -0
  31. package/dist/disableSkillsWire.js +8 -1
  32. package/dist/displayUntrusted.js +155 -5
  33. package/dist/effectiveFacts.d.ts +14 -4
  34. package/dist/effectiveFacts.js +45 -5
  35. package/dist/engineAgentAbsence.js +2 -1
  36. package/dist/engineCapReader.js +16 -10
  37. package/dist/engineCapsCache.d.ts +5 -1
  38. package/dist/engineCapsCache.js +69 -8
  39. package/dist/engineClosedSets.d.ts +2 -0
  40. package/dist/engineClosedSets.js +3 -0
  41. package/dist/engineErrorCodes.d.ts +17 -0
  42. package/dist/engineErrorCodes.js +47 -0
  43. package/dist/engineNoticeCodes.d.ts +14 -0
  44. package/dist/engineNoticeCodes.js +71 -0
  45. package/dist/executionLaneCapability.js +2 -0
  46. package/dist/gateOutcome.js +2 -17
  47. package/dist/gateVocabulary.d.ts +2 -4
  48. package/dist/gateVocabulary.js +3 -11
  49. package/dist/generated/engineFactTables.d.ts +27 -0
  50. package/dist/generated/engineFactTables.js +128 -0
  51. package/dist/generated/engineNoticeTables.js +3 -0
  52. package/dist/generated/settingsSchemaTables.d.ts +8 -0
  53. package/dist/generated/settingsSchemaTables.js +40 -0
  54. package/dist/hitl/allowRuleShadow.d.ts +21 -0
  55. package/dist/hitl/allowRuleShadow.js +167 -0
  56. package/dist/hitl/askClassPair.d.ts +14 -0
  57. package/dist/hitl/askClassPair.js +42 -0
  58. package/dist/hitl/askGateWire.d.ts +1 -1
  59. package/dist/hitl/askGateWire.js +2 -1
  60. package/dist/hitl/askSurvivesPosture.d.ts +5 -0
  61. package/dist/hitl/askSurvivesPosture.js +17 -0
  62. package/dist/hitl/automaticAnswerVerdict.d.ts +21 -0
  63. package/dist/hitl/automaticAnswerVerdict.js +143 -0
  64. package/dist/hitl/crashConverged.d.ts +8 -0
  65. package/dist/hitl/crashConverged.js +58 -1
  66. package/dist/hitl/crashConvergedNotice.d.ts +4 -0
  67. package/dist/hitl/crashConvergedNotice.js +57 -0
  68. package/dist/hitl/frameRouter.d.ts +2 -0
  69. package/dist/hitl/frameRouter.js +66 -14
  70. package/dist/hitl/gateLedger.d.ts +6 -0
  71. package/dist/hitl/gateLedger.js +34 -5
  72. package/dist/hitl/hitlBridge.d.ts +7 -4
  73. package/dist/hitl/hitlHostSurface.d.ts +2 -0
  74. package/dist/hitl/hitlHostSurface.js +7 -0
  75. package/dist/hitl/livePendingAsk.js +24 -5
  76. package/dist/hitl/parkResolver.d.ts +7 -2
  77. package/dist/hitl/parkResolver.js +21 -7
  78. package/dist/hitl/persistedRulesWire.d.ts +4 -1
  79. package/dist/hitl/persistedRulesWire.js +9 -2
  80. package/dist/hitl/planReviewWire.d.ts +1 -1
  81. package/dist/hitl/planReviewWire.js +19 -5
  82. package/dist/hitl/replayedApproval.d.ts +21 -0
  83. package/dist/hitl/replayedApproval.js +89 -0
  84. package/dist/hitl/sessionPolicyDeliverable.js +20 -2
  85. package/dist/hitl/sessionPolicyWire.d.ts +13 -0
  86. package/dist/hitl/sessionPolicyWire.js +75 -2
  87. package/dist/hitl/suspendedReopen.js +2 -2
  88. package/dist/hitl/toolApprovalWire.d.ts +9 -1
  89. package/dist/hitl/toolApprovalWire.js +40 -40
  90. package/dist/hookMatcherVerdict.d.ts +29 -0
  91. package/dist/hookMatcherVerdict.js +266 -0
  92. package/dist/humanTurn.d.ts +91 -0
  93. package/dist/humanTurn.js +252 -0
  94. package/dist/humanTurnRead.d.ts +105 -0
  95. package/dist/humanTurnRead.js +331 -0
  96. package/dist/index.d.ts +38 -11
  97. package/dist/index.js +27 -8
  98. package/dist/inheritEnvWire.js +4 -5
  99. package/dist/liveModelCatalog.d.ts +2 -0
  100. package/dist/liveModelCatalog.js +51 -3
  101. package/dist/mcpLiveness.js +2 -1
  102. package/dist/memoryVerbsWire.d.ts +1 -1
  103. package/dist/memoryVerbsWire.js +3 -0
  104. package/dist/model/catalog.js +2 -1
  105. package/dist/model/providerPresets.d.ts +3 -1
  106. package/dist/model/tierVocabulary.d.ts +2 -1
  107. package/dist/model/tierVocabulary.js +3 -8
  108. package/dist/peerFrames.js +2 -2
  109. package/dist/permissionRuleIssue.d.ts +1 -1
  110. package/dist/permissionRuleIssue.js +31 -9
  111. package/dist/permissionsAllowGrantCapability.d.ts +2 -1
  112. package/dist/permissionsAllowGrantCapability.js +11 -2
  113. package/dist/permissionsDeclaration.d.ts +29 -0
  114. package/dist/permissionsDeclaration.js +155 -66
  115. package/dist/pluginHooksWire.js +2 -11
  116. package/dist/promptDelivery.d.ts +11 -3
  117. package/dist/promptDelivery.js +164 -29
  118. package/dist/promptProfileWireCaps.d.ts +2 -1
  119. package/dist/protocolSegment.d.ts +9 -0
  120. package/dist/protocolSegment.js +28 -0
  121. package/dist/providerRejection.d.ts +1 -0
  122. package/dist/providerRejection.js +20 -0
  123. package/dist/readDenyTiers.d.ts +10 -0
  124. package/dist/readDenyTiers.js +29 -0
  125. package/dist/request/taskRequest.js +3 -17
  126. package/dist/resumeRefusalCopy.d.ts +11 -0
  127. package/dist/resumeRefusalCopy.js +61 -4
  128. package/dist/rewindArchiveCapability.js +4 -4
  129. package/dist/rewindWireCaps.d.ts +2 -1
  130. package/dist/rewindWireCaps.js +19 -2
  131. package/dist/ruleCompileVerdict.d.ts +2 -0
  132. package/dist/ruleCompileVerdict.js +13 -0
  133. package/dist/ruleRemovalConsequence.d.ts +2 -1
  134. package/dist/runCancelContext.d.ts +12 -0
  135. package/dist/runCancelContext.js +83 -1
  136. package/dist/seam.d.ts +2 -0
  137. package/dist/seam.js +1 -1
  138. package/dist/seatContract.d.ts +2 -1
  139. package/dist/sessionMemoryStatus.d.ts +2 -4
  140. package/dist/sessionSyncFileHistoryCapability.d.ts +18 -0
  141. package/dist/sessionSyncFileHistoryCapability.js +50 -0
  142. package/dist/skillToolListsCapability.d.ts +18 -0
  143. package/dist/skillToolListsCapability.js +50 -0
  144. package/dist/sqlEngineCapability.js +1 -8
  145. package/dist/steerPriorityCapability.d.ts +18 -0
  146. package/dist/steerPriorityCapability.js +80 -0
  147. package/dist/steerReceipt.d.ts +9 -0
  148. package/dist/steerReceipt.js +25 -0
  149. package/dist/subagent/engineSubagentSteer.js +2 -9
  150. package/dist/supportFloor.js +2 -2
  151. package/dist/taskRequestWords.d.ts +7 -1
  152. package/dist/taskRequestWords.js +18 -8
  153. package/dist/toolHistoryBadTurn.d.ts +1 -0
  154. package/dist/toolHistoryBadTurn.js +89 -0
  155. package/dist/toolHistoryMismatch.d.ts +2 -1
  156. package/dist/toolHistoryMismatch.js +19 -6
  157. package/dist/toolResult.d.ts +8 -0
  158. package/dist/toolResult.js +47 -3
  159. package/dist/types/engineState.d.ts +2 -12
  160. package/dist/userAttachmentEnvelope.d.ts +61 -0
  161. package/dist/userAttachmentEnvelope.js +204 -0
  162. package/dist/userInvokedSkillsCapability.d.ts +18 -0
  163. package/dist/userInvokedSkillsCapability.js +50 -0
  164. package/dist/wireFailureShape.d.ts +3 -0
  165. package/dist/wireFailureShape.js +8 -0
  166. package/dist/wireRefusalCopy.d.ts +6 -0
  167. package/dist/wireRefusalCopy.js +26 -3
  168. package/dist/workflowsJournalCapability.d.ts +18 -0
  169. package/dist/workflowsJournalCapability.js +50 -0
  170. package/dist/writeProtectionCapability.d.ts +2 -4
  171. package/docs/INTEGRATION-CLIENTS.md +1489 -16
  172. package/package.json +3 -3
@@ -1,7 +1,24 @@
1
- export function rewindSpecForMode(mode, targetEntryId) {
1
+ function restoreFilesKeyMaySend(reading) {
2
+ if (reading === undefined)
3
+ return true;
4
+ try {
5
+ if (reading === null || typeof reading !== 'object')
6
+ return false;
7
+ const kind = reading.kind;
8
+ if (kind === 'unobserved')
9
+ return true;
10
+ return kind === 'present' && reading.restoreFilesEpoch === 'on';
11
+ }
12
+ catch {
13
+ return false;
14
+ }
15
+ }
16
+ export function rewindSpecForMode(mode, targetEntryId, reading) {
2
17
  switch (mode) {
3
18
  case 'both':
4
- return { resumeAt: targetEntryId, resumeAtMode: 'before', restoreFiles: true };
19
+ return restoreFilesKeyMaySend(reading)
20
+ ? { resumeAt: targetEntryId, resumeAtMode: 'before', restoreFiles: true }
21
+ : { resumeAt: targetEntryId, resumeAtMode: 'before' };
5
22
  case 'conversation':
6
23
  return { resumeAt: targetEntryId, resumeAtMode: 'before' };
7
24
  case 'code':
@@ -0,0 +1,2 @@
1
+ export type RuleCompileVerdict = 'compiles' | 'refused' | 'unknown';
2
+ export declare function ruleCompileVerdict(rule: string, behavior: 'deny' | 'ask'): RuleCompileVerdict;
@@ -0,0 +1,13 @@
1
+ import { validatePermissionRules } from './coreValuePorts.js';
2
+ const RULE_COMPILE_ROOT = '/';
3
+ export function ruleCompileVerdict(rule, behavior) {
4
+ try {
5
+ const issues = validatePermissionRules([{ rule, behavior }], { pathBases: { root: RULE_COMPILE_ROOT } });
6
+ if (!Array.isArray(issues))
7
+ return 'unknown';
8
+ return issues.length === 0 ? 'compiles' : 'refused';
9
+ }
10
+ catch {
11
+ return 'unknown';
12
+ }
13
+ }
@@ -1,3 +1,4 @@
1
- export type RuleRemovalBehavior = 'allow' | 'deny' | 'ask' | undefined;
1
+ import type { RuleBehavior } from '@sema-agent/sdk';
2
+ export type RuleRemovalBehavior = RuleBehavior | undefined;
2
3
  export declare function removalConsequenceLineForBehavior(behavior: RuleRemovalBehavior): string;
3
4
  export declare function ruleRemovalBehaviorOf(raw: unknown): RuleRemovalBehavior;
@@ -15,6 +15,7 @@ import { type RunTerminalRead } from './runTerminal.js';
15
15
  export type RunAbortCause = {
16
16
  kind: 'cancelled';
17
17
  context?: RunCancelContextView;
18
+ cause?: AbortCauseReading;
18
19
  } | {
19
20
  kind: 'engine_error';
20
21
  code?: string;
@@ -28,3 +29,14 @@ export type RunAbortCause = {
28
29
  };
29
30
  export declare const RUN_CANCELLED_CODE: "cancelled";
30
31
  export declare function classifyRunAbortCause(record: unknown): RunAbortCause;
32
+ export declare const ABORT_CAUSES: readonly ["client_disconnected", "ask_park_grace_exhausted", "cancel_verb"];
33
+ export type AbortCause = (typeof ABORT_CAUSES)[number];
34
+ export type AbortCauseReading = {
35
+ readonly kind: 'known';
36
+ readonly cause: AbortCause;
37
+ } | {
38
+ readonly kind: 'unrecognized';
39
+ readonly word: string;
40
+ };
41
+ export declare function readAbortCause(frame: unknown): AbortCauseReading | undefined;
42
+ export declare function abortCauseNoteOf(frame: unknown): string | undefined;
@@ -45,7 +45,8 @@ export function classifyRunAbortCause(record) {
45
45
  if (read !== null && read.kind === 'failed') {
46
46
  if (read.code === RUN_CANCELLED_CODE) {
47
47
  const cc = readRunCancelContext(record);
48
- return { kind: 'cancelled', ...(cc?.kind === 'present' ? { context: cc.context } : {}) };
48
+ const cause = readAbortCause(record);
49
+ return { kind: 'cancelled', ...(cc?.kind === 'present' ? { context: cc.context } : {}), ...(cause !== undefined ? { cause } : {}) };
49
50
  }
50
51
  return { kind: 'engine_error', ...(read.code !== undefined ? { code: read.code } : {}), ...(read.message !== undefined ? { message: read.message } : {}) };
51
52
  }
@@ -55,3 +56,84 @@ export function classifyRunAbortCause(record) {
55
56
  return { kind: 'run_still_live', status };
56
57
  return { kind: 'unknown', ...(read !== null ? { terminal: read.kind } : {}) };
57
58
  }
59
+ export const ABORT_CAUSES = Object.freeze(['client_disconnected', 'ask_park_grace_exhausted', 'cancel_verb']);
60
+ function ownDataOf(o, key) {
61
+ const d = Object.getOwnPropertyDescriptor(o, key);
62
+ return d !== undefined && Object.hasOwn(d, 'value') ? d.value : undefined;
63
+ }
64
+ function plainRecordOf(v) {
65
+ return v !== null && typeof v === 'object' && !Array.isArray(v) ? v : undefined;
66
+ }
67
+ function cancelledHolderOf(frame) {
68
+ const f = plainRecordOf(frame);
69
+ if (f === undefined)
70
+ return undefined;
71
+ const type = ownDataOf(f, 'type');
72
+ if (type === 'failed')
73
+ return ownDataOf(f, 'errorCode') === RUN_CANCELLED_CODE ? f : undefined;
74
+ const base = plainRecordOf(type === 'done' ? ownDataOf(f, 'result') : f);
75
+ if (base === undefined)
76
+ return undefined;
77
+ const holder = runResultHolder(base);
78
+ const t = readRunTerminal(holder);
79
+ return t !== null && t.kind === 'failed' && t.code === RUN_CANCELLED_CODE ? holder : undefined;
80
+ }
81
+ function abortCauseIn(holder) {
82
+ const raw = ownDataOf(holder, 'abortCause');
83
+ if (typeof raw !== 'string' || raw.length === 0)
84
+ return undefined;
85
+ return ABORT_CAUSES.includes(raw) ? { kind: 'known', cause: raw } : { kind: 'unrecognized', word: raw };
86
+ }
87
+ export function readAbortCause(frame) {
88
+ try {
89
+ const holder = cancelledHolderOf(frame);
90
+ return holder === undefined ? undefined : abortCauseIn(holder);
91
+ }
92
+ catch {
93
+ return undefined;
94
+ }
95
+ }
96
+ const ABORT_CAUSE_SENTENCES = Object.freeze({
97
+ client_disconnected: 'Aborted: the stream connection to the engine dropped, and the engine stopped the run (cause client_disconnected) — not an engine error.',
98
+ ask_park_grace_exhausted: 'Aborted: the connection dropped while a question or approval was pending, and the run could not be parked for later resumption in time ' +
99
+ '(cause ask_park_grace_exhausted) — not an engine error.',
100
+ cancel_verb: 'Cancelled: a cancel request to the engine stopped this run (cause cancel_verb) — not an engine error.',
101
+ });
102
+ const ABORT_CAUSE_UNRECOGNIZED_SENTENCE = 'Aborted by the engine for a reason this client does not recognize — not an engine error.';
103
+ function secondsText(ms) {
104
+ return `${(ms / 1000).toFixed(1)}s`;
105
+ }
106
+ function cancelContextOf(holder) {
107
+ try {
108
+ const r = readRunCancelContext(holder);
109
+ return r?.kind === 'present' ? r.context : undefined;
110
+ }
111
+ catch {
112
+ return undefined;
113
+ }
114
+ }
115
+ function cancelContextTail(ctx) {
116
+ if (ctx === undefined)
117
+ return '';
118
+ const parts = [];
119
+ if (ctx.elapsedMs !== undefined)
120
+ parts.push(`ran ${secondsText(ctx.elapsedMs)}`);
121
+ if (ctx.lastEventAgeMs !== undefined)
122
+ parts.push(`last engine activity ${secondsText(ctx.lastEventAgeMs)} before the stop`);
123
+ return parts.length > 0 ? ` (${parts.join('; ')})` : '';
124
+ }
125
+ export function abortCauseNoteOf(frame) {
126
+ try {
127
+ const holder = cancelledHolderOf(frame);
128
+ if (holder === undefined)
129
+ return undefined;
130
+ const cause = abortCauseIn(holder);
131
+ if (cause === undefined)
132
+ return undefined;
133
+ const sentence = cause.kind === 'known' ? ABORT_CAUSE_SENTENCES[cause.cause] : ABORT_CAUSE_UNRECOGNIZED_SENTENCE;
134
+ return `${sentence}${cancelContextTail(cancelContextOf(holder))}`;
135
+ }
136
+ catch {
137
+ return undefined;
138
+ }
139
+ }
package/dist/seam.d.ts CHANGED
@@ -3,6 +3,7 @@ import type { EngineTurnUsage } from './adapter/downstream/turnUsageToModelUsage
3
3
  import type { RunCostReconcile } from './adapter/downstream/terminalToSdkResult.js';
4
4
  import type { WiringManifestAutoMode, WiringManifestModelGate, WiringManifestMcpEntryView, WiringManifestHookEntryView, WiringManifestLspSeamView, WiringManifestWriteProtectionView, WiringManifestAutoConsolidationView, WiringManifestReadDenyView, ContextUsageSectionView, PromptManifestSectionView, PromptManifestBlockView, PromptManifestToolView } from './adapter/downstream/eventToSdkMessage.js';
5
5
  import type { ToolRosterView, ToolRosterDeltaView, WiringManifestHandsView } from './toolRoster.js';
6
+ import type { WiringManifestFleetView } from './adapter/downstream/wiringManifestView.js';
6
7
  import type { SuspendedReopenReading } from './hitl/suspendedReopen.js';
7
8
  export interface AbortSignalLike {
8
9
  readonly aborted: boolean;
@@ -177,6 +178,7 @@ export interface WiringManifestChromeEvent {
177
178
  instructions?: {
178
179
  readonly selected: readonly string[];
179
180
  };
181
+ fleet?: WiringManifestFleetView;
180
182
  eventId?: string;
181
183
  }
182
184
  export interface TextSegmentCommittedRow {
package/dist/seam.js CHANGED
@@ -94,7 +94,7 @@ const CHROME_ARM_TABLE = {
94
94
  },
95
95
  tool_progress: {
96
96
  required: false,
97
- duty: 'CC-08(0.71.0,C-R50 一帧两拍):按 `toolCallId` 挂到那张工具卡上;`elapsedSeconds` 缺席不是 0、不等于 tool_end 的 duration;' +
97
+ duty: 'CC-08(0.71.0,一帧两拍):按 `toolCallId` 挂到那张工具卡上;`elapsedSeconds` 缺席不是 0、不等于 tool_end 的 duration;' +
98
98
  '`output` 在场 = 命令尾巴窗口(活面板,不是日志;`totalLines`/`totalBytes` 与它同进同退),🔴 它是 UNTRUSTED RAW,可再封顶展示、**绝不回喂**模型;' +
99
99
  '子代工具的进度不在这条臂上(三键断闸),fleet 面板另有口。不接 = 看不见进度,不属行为丢失。',
100
100
  },
@@ -4,6 +4,7 @@ import type { LaneProof } from "./seam.js";
4
4
  import type { QuestionAnswer } from "./liveQuestionStore.js";
5
5
  import type { ToolApprovalDelegation } from "./hitl/toolApprovalWire.js";
6
6
  import type { ApprovalMandateWord } from "./gateVocabulary.js";
7
+ import type { ModelApiWord } from "./model/providerPresets.js";
7
8
  export interface SeatValidationFailure {
8
9
  reason: string;
9
10
  field?: string;
@@ -240,7 +241,7 @@ export interface SeatCatalogEntry {
240
241
  providerId: string;
241
242
  providerName: string;
242
243
  baseUrl: string;
243
- api: "anthropic-messages" | "openai-completions";
244
+ api: ModelApiWord;
244
245
  apiKey?: string;
245
246
  modelId: string;
246
247
  contextWindow: number;
@@ -1,4 +1,4 @@
1
- import type { SessionMemoryStatus } from '@sema-agent/sdk';
1
+ import type { SessionMemoryStatus, SessionMemoryStatusResponse } from '@sema-agent/sdk';
2
2
  export interface MemoryStatusClientLike {
3
3
  sessions: {
4
4
  memoryStatus(sessionId: string, opts?: {
@@ -8,9 +8,7 @@ export interface MemoryStatusClientLike {
8
8
  } & SessionMemoryStatus>;
9
9
  };
10
10
  }
11
- export type MemoryStatusFacts = SessionMemoryStatus & {
12
- readonly autoConsolidationArmed?: boolean;
13
- };
11
+ export type MemoryStatusFacts = Omit<SessionMemoryStatusResponse, 'sessionId'>;
14
12
  export type MemoryStatusVerdict = {
15
13
  readonly kind: 'ok';
16
14
  readonly sessionId: string;
@@ -0,0 +1,18 @@
1
+ export type SessionSyncFileHistoryReading = {
2
+ kind: 'unobserved';
3
+ } | {
4
+ kind: 'not_reported';
5
+ } | {
6
+ kind: 'absent';
7
+ } | {
8
+ kind: 'present';
9
+ };
10
+ export declare function projectSessionSyncFileHistoryCapability(caps: unknown): SessionSyncFileHistoryReading | undefined;
11
+ export declare function noteEngineCapsForSessionSyncFileHistory(baseUrl: string, caps: unknown, opts?: {
12
+ generation?: number;
13
+ }): void;
14
+ export declare function observedSessionSyncFileHistory(baseUrl?: string | undefined): SessionSyncFileHistoryReading;
15
+ export declare function sessionSyncFileHistoryAvailable(reading: SessionSyncFileHistoryReading): 'yes' | 'no' | 'unknown';
16
+ export declare function sessionSyncFileHistoryDoctorDetail(reading: SessionSyncFileHistoryReading): string;
17
+ export declare function forgetSessionSyncFileHistoryReading(baseUrl: string | undefined): void;
18
+ export declare function __resetSessionSyncFileHistoryReadingsForTests(): void;
@@ -0,0 +1,50 @@
1
+ import { engineWireTarget } from './engineWireTarget.js';
2
+ import { createEngineCapReader } from './engineCapReader.js';
3
+ export function projectSessionSyncFileHistoryCapability(caps) {
4
+ if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
5
+ return undefined;
6
+ if (!Object.hasOwn(caps, 'sessionSyncFileHistory'))
7
+ return { kind: 'not_reported' };
8
+ const v = caps.sessionSyncFileHistory;
9
+ if (v === undefined)
10
+ return { kind: 'not_reported' };
11
+ if (typeof v !== 'boolean')
12
+ return undefined;
13
+ return v ? { kind: 'present' } : { kind: 'absent' };
14
+ }
15
+ const reader = createEngineCapReader({
16
+ name: 'sessionSyncFileHistory',
17
+ project: projectSessionSyncFileHistoryCapability,
18
+ makeUnobserved: () => ({ kind: 'unobserved' }),
19
+ });
20
+ export function noteEngineCapsForSessionSyncFileHistory(baseUrl, caps, opts) {
21
+ reader.note(baseUrl, caps, opts);
22
+ }
23
+ export function observedSessionSyncFileHistory(baseUrl = engineWireTarget()?.baseUrl) {
24
+ return reader.observed(baseUrl);
25
+ }
26
+ export function sessionSyncFileHistoryAvailable(reading) {
27
+ if (reading.kind === 'present')
28
+ return 'yes';
29
+ if (reading.kind === 'absent')
30
+ return 'no';
31
+ return 'unknown';
32
+ }
33
+ export function sessionSyncFileHistoryDoctorDetail(reading) {
34
+ switch (reading.kind) {
35
+ case 'unobserved':
36
+ return 'session-sync file history not observed — the engine reports it on /v1/capabilities (sessionSyncFileHistory); this process has no usable capabilities reading cached for it (none received, or the last one was unreadable)';
37
+ case 'not_reported':
38
+ return 'session-sync file history not reported by this engine — only newer engines advertise it separately; this does not say whether file history can be synced';
39
+ case 'absent':
40
+ return 'no session-sync file history on this deployment — syncing a session moves the conversation only; edited-file history stays behind';
41
+ case 'present':
42
+ return 'session-sync file history on — syncing a session can also move its edited-file history';
43
+ }
44
+ }
45
+ export function forgetSessionSyncFileHistoryReading(baseUrl) {
46
+ reader.forget(baseUrl);
47
+ }
48
+ export function __resetSessionSyncFileHistoryReadingsForTests() {
49
+ reader.__resetForTests();
50
+ }
@@ -0,0 +1,18 @@
1
+ export type SkillToolListsReading = {
2
+ kind: 'unobserved';
3
+ } | {
4
+ kind: 'not_reported';
5
+ } | {
6
+ kind: 'absent';
7
+ } | {
8
+ kind: 'present';
9
+ };
10
+ export declare function projectSkillToolListsCapability(caps: unknown): SkillToolListsReading | undefined;
11
+ export declare function noteEngineCapsForSkillToolLists(baseUrl: string, caps: unknown, opts?: {
12
+ generation?: number;
13
+ }): void;
14
+ export declare function observedSkillToolLists(baseUrl?: string | undefined): SkillToolListsReading;
15
+ export declare function skillToolListsAvailable(reading: SkillToolListsReading): 'yes' | 'no' | 'unknown';
16
+ export declare function skillToolListsDoctorDetail(reading: SkillToolListsReading): string;
17
+ export declare function forgetSkillToolListsReading(baseUrl: string | undefined): void;
18
+ export declare function __resetSkillToolListsReadingsForTests(): void;
@@ -0,0 +1,50 @@
1
+ import { engineWireTarget } from './engineWireTarget.js';
2
+ import { createEngineCapReader } from './engineCapReader.js';
3
+ export function projectSkillToolListsCapability(caps) {
4
+ if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
5
+ return undefined;
6
+ if (!Object.hasOwn(caps, 'skillToolLists'))
7
+ return { kind: 'not_reported' };
8
+ const v = caps.skillToolLists;
9
+ if (v === undefined)
10
+ return { kind: 'not_reported' };
11
+ if (typeof v !== 'boolean')
12
+ return undefined;
13
+ return v ? { kind: 'present' } : { kind: 'absent' };
14
+ }
15
+ const reader = createEngineCapReader({
16
+ name: 'skillToolLists',
17
+ project: projectSkillToolListsCapability,
18
+ makeUnobserved: () => ({ kind: 'unobserved' }),
19
+ });
20
+ export function noteEngineCapsForSkillToolLists(baseUrl, caps, opts) {
21
+ reader.note(baseUrl, caps, opts);
22
+ }
23
+ export function observedSkillToolLists(baseUrl = engineWireTarget()?.baseUrl) {
24
+ return reader.observed(baseUrl);
25
+ }
26
+ export function skillToolListsAvailable(reading) {
27
+ if (reading.kind === 'present')
28
+ return 'yes';
29
+ if (reading.kind === 'absent' || reading.kind === 'not_reported')
30
+ return 'no';
31
+ return 'unknown';
32
+ }
33
+ export function skillToolListsDoctorDetail(reading) {
34
+ switch (reading.kind) {
35
+ case 'unobserved':
36
+ return 'skill tool lists not observed — the engine reports it on /v1/capabilities (skillToolLists); this process has no usable capabilities reading cached for it (none received, or the last one was unreadable)';
37
+ case 'not_reported':
38
+ return 'skill tool lists not reported by this engine — the engine predates them: tool lists on request skills are not read, so they do not limit any tool';
39
+ case 'absent':
40
+ return 'skill tool lists off on this deployment — tool lists on request skills are not read';
41
+ case 'present':
42
+ return 'skill tool lists on — a request skill’s allowed and disallowed tool lists are read as this run’s rules';
43
+ }
44
+ }
45
+ export function forgetSkillToolListsReading(baseUrl) {
46
+ reader.forget(baseUrl);
47
+ }
48
+ export function __resetSkillToolListsReadingsForTests() {
49
+ reader.__resetForTests();
50
+ }
@@ -16,14 +16,7 @@ export function projectSqlEngineCapability(caps) {
16
16
  return { kind: 'none' };
17
17
  return projectSqlEngineView(nested);
18
18
  }
19
- if (!Object.hasOwn(caps, 'sql'))
20
- return { kind: 'not_reported' };
21
- const sql = caps.sql;
22
- if (sql === null)
23
- return { kind: 'none' };
24
- if (sql === undefined)
25
- return { kind: 'not_reported' };
26
- return projectSqlEngineView(sql);
19
+ return { kind: 'not_reported' };
27
20
  }
28
21
  function projectSqlEngineView(sql) {
29
22
  if (sql === null || typeof sql !== 'object')
@@ -0,0 +1,18 @@
1
+ export type SteerPriorityReading = {
2
+ kind: 'unobserved';
3
+ } | {
4
+ kind: 'not_reported';
5
+ } | {
6
+ kind: 'present';
7
+ word: string;
8
+ };
9
+ export type SteerPriorityMode = 'engine' | 'advisory' | 'unknown';
10
+ export declare function projectSteerPriorityCapability(caps: unknown): SteerPriorityReading | undefined;
11
+ export declare function noteEngineCapsForSteerPriority(baseUrl: string, caps: unknown, opts?: {
12
+ generation?: number;
13
+ }): void;
14
+ export declare function observedSteerPriority(baseUrl?: string | undefined): SteerPriorityReading;
15
+ export declare function steerPriorityMode(reading: SteerPriorityReading): SteerPriorityMode;
16
+ export declare function steerPriorityDoctorDetail(reading: SteerPriorityReading): string;
17
+ export declare function forgetSteerPriorityReading(baseUrl: string | undefined): void;
18
+ export declare function __resetSteerPriorityReadingsForTests(): void;
@@ -0,0 +1,80 @@
1
+ import { capForDisplay } from './fleetTaskDesc.js';
2
+ import { engineWireTarget } from './engineWireTarget.js';
3
+ import { createEngineCapReader } from './engineCapReader.js';
4
+ export function projectSteerPriorityCapability(caps) {
5
+ if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
6
+ return undefined;
7
+ if (!Object.hasOwn(caps, 'fleet'))
8
+ return { kind: 'not_reported' };
9
+ const fleet = caps.fleet;
10
+ if (fleet === undefined || fleet === false)
11
+ return { kind: 'not_reported' };
12
+ if (fleet === null || typeof fleet !== 'object' || Array.isArray(fleet))
13
+ return undefined;
14
+ if (!Object.hasOwn(fleet, 'steerPriority'))
15
+ return { kind: 'not_reported' };
16
+ const v = fleet.steerPriority;
17
+ if (v === undefined)
18
+ return { kind: 'not_reported' };
19
+ if (typeof v !== 'string' || v.length === 0)
20
+ return undefined;
21
+ return { kind: 'present', word: v };
22
+ }
23
+ const reader = createEngineCapReader({
24
+ name: 'fleet.steerPriority',
25
+ project: projectSteerPriorityCapability,
26
+ makeUnobserved: () => ({ kind: 'unobserved' }),
27
+ });
28
+ export function noteEngineCapsForSteerPriority(baseUrl, caps, opts) {
29
+ reader.note(baseUrl, caps, opts);
30
+ }
31
+ export function observedSteerPriority(baseUrl = engineWireTarget()?.baseUrl) {
32
+ return reader.observed(baseUrl);
33
+ }
34
+ export function steerPriorityMode(reading) {
35
+ try {
36
+ if (reading === null || typeof reading !== 'object' || Array.isArray(reading))
37
+ return 'unknown';
38
+ if (!Object.hasOwn(reading, 'kind') || reading.kind !== 'present')
39
+ return 'unknown';
40
+ if (!Object.hasOwn(reading, 'word'))
41
+ return 'unknown';
42
+ const word = reading.word;
43
+ return word === 'engine' ? 'engine' : word === 'advisory' ? 'advisory' : 'unknown';
44
+ }
45
+ catch {
46
+ return 'unknown';
47
+ }
48
+ }
49
+ const WORD_DETAIL_MAX = 40;
50
+ export function steerPriorityDoctorDetail(reading) {
51
+ const unobserved = 'steer priority not observed — the engine reports it on /v1/capabilities (fleet.steerPriority); this process has no usable capabilities reading cached for it, so a "now" or "later" steer is not sent';
52
+ let kind;
53
+ let word;
54
+ try {
55
+ if (reading === null || typeof reading !== 'object')
56
+ return unobserved;
57
+ kind = Object.hasOwn(reading, 'kind') ? reading.kind : undefined;
58
+ word = kind === 'present' && Object.hasOwn(reading, 'word') ? reading.word : undefined;
59
+ }
60
+ catch {
61
+ return unobserved;
62
+ }
63
+ if (kind === 'not_reported') {
64
+ return 'steer priority not reported by this engine — it predates the field or has no fleet face, so a "now" or "later" steer is not sent (steers without a priority work as before)';
65
+ }
66
+ if (kind !== 'present' || typeof word !== 'string' || word.length === 0)
67
+ return unobserved;
68
+ if (word === 'engine')
69
+ return 'steer priority applied by the engine — "now" interrupts the running turn, "later" waits until the run would have stopped';
70
+ if (word === 'advisory') {
71
+ return 'steer priority accepted but not applied on this deployment — a "now" or "later" steer is not sent (steers without a priority work as before)';
72
+ }
73
+ return `steer priority reported as "${capForDisplay(word, WORD_DETAIL_MAX)}" — a value this client does not know yet, so whether it is applied is unknown and a "now" or "later" steer is not sent`;
74
+ }
75
+ export function forgetSteerPriorityReading(baseUrl) {
76
+ reader.forget(baseUrl);
77
+ }
78
+ export function __resetSteerPriorityReadingsForTests() {
79
+ reader.__resetForTests();
80
+ }
@@ -0,0 +1,9 @@
1
+ import type { SteerPriority } from '@sema-agent/sdk';
2
+ export interface SteerReceiptReading {
3
+ readonly delivery: string | null;
4
+ readonly status: string | null;
5
+ readonly messageId?: string;
6
+ readonly priority?: SteerPriority;
7
+ }
8
+ export declare function ownNonEmptyStringOf(body: unknown, key: string): string | undefined;
9
+ export declare function readSteerReceipt(receipt: unknown): SteerReceiptReading;
@@ -0,0 +1,25 @@
1
+ export function ownNonEmptyStringOf(body, key) {
2
+ try {
3
+ if (typeof body !== 'object' || body === null || !Object.hasOwn(body, key))
4
+ return undefined;
5
+ const v = body[key];
6
+ return typeof v === 'string' && v.length > 0 ? v : undefined;
7
+ }
8
+ catch {
9
+ return undefined;
10
+ }
11
+ }
12
+ function priorityEchoOf(body) {
13
+ const v = ownNonEmptyStringOf(body, 'priority');
14
+ return v === 'now' || v === 'next' || v === 'later' ? v : undefined;
15
+ }
16
+ export function readSteerReceipt(receipt) {
17
+ const messageId = ownNonEmptyStringOf(receipt, 'messageId');
18
+ const priority = priorityEchoOf(receipt);
19
+ return Object.freeze({
20
+ delivery: ownNonEmptyStringOf(receipt, 'delivery') ?? null,
21
+ status: ownNonEmptyStringOf(receipt, 'status') ?? null,
22
+ ...(messageId !== undefined ? { messageId } : {}),
23
+ ...(priority !== undefined ? { priority } : {}),
24
+ });
25
+ }
@@ -4,19 +4,12 @@ import { engineSessionParamFor } from '../engineSessionParam.js';
4
4
  import { resolveOwnerContext, resolveOwnerRunId } from './engineSubagentResume.js';
5
5
  import { noteBgOwnerAbsence } from './subagentOwnerAbsence.js';
6
6
  import { errCodes, steeringRefusedBeforeEngine } from '../controlRouter.js';
7
+ import { ownNonEmptyStringOf } from '../steerReceipt.js';
7
8
  function usableSteerClient(client) {
8
9
  return clientHasVerbs(client, [['runs', 'steerSubagent']]);
9
10
  }
10
11
  function steerReceiptMessageId(body) {
11
- try {
12
- if (typeof body !== 'object' || body === null || !Object.hasOwn(body, 'messageId'))
13
- return undefined;
14
- const v = body.messageId;
15
- return typeof v === 'string' && v.length > 0 ? v : undefined;
16
- }
17
- catch {
18
- return undefined;
19
- }
12
+ return ownNonEmptyStringOf(body, 'messageId');
20
13
  }
21
14
  export async function steerEngineSubagent(target, text, childTaskId, opts) {
22
15
  const named = typeof childTaskId === 'string' && childTaskId !== '' ? childTaskId : undefined;
@@ -1,6 +1,6 @@
1
1
  export const SUPPORT_FLOOR = Object.freeze({
2
- server: '7.104.0',
3
- core: '7.33.8',
2
+ server: '7.106.0',
3
+ core: '7.35.2',
4
4
  sdk: '12.0.1',
5
5
  });
6
6
  export function supportFloorOf(component) {
@@ -3,4 +3,10 @@ export type TaskRequestReasoningEffort = NonNullable<TaskRequest['reasoningEffor
3
3
  export declare const REASONING_EFFORT_WORDS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
4
4
  export type TaskRequestPermissionMode = NonNullable<TaskRequest['permissionMode']>;
5
5
  export declare const PERMISSION_MODE_WORDS: readonly ["default", "plan", "acceptEdits", "bypassPermissions", "auto"];
6
- export declare function retiredAttachmentsKeyWhy(nameOrToken: string, form?: 'token' | 'key'): string | undefined;
6
+ export interface RetiredAttachmentsKey {
7
+ readonly key: string;
8
+ readonly why: string;
9
+ readonly because: string;
10
+ readonly remedy: string;
11
+ }
12
+ export declare function retiredAttachmentsKeyOf(nameOrToken: string, form?: 'token' | 'key'): RetiredAttachmentsKey | undefined;
@@ -2,17 +2,27 @@ export const REASONING_EFFORT_WORDS = ['off', 'minimal', 'low', 'medium', 'high'
2
2
  export const PERMISSION_MODE_WORDS = ['default', 'plan', 'acceptEdits', 'bypassPermissions', 'auto'];
3
3
  const _taskRequestWordPins = [true, true, true, true];
4
4
  void _taskRequestWordPins;
5
- export function retiredAttachmentsKeyWhy(nameOrToken, form = 'token') {
5
+ export function retiredAttachmentsKeyOf(nameOrToken, form = 'token') {
6
6
  const lower = nameOrToken.trim().toLowerCase();
7
7
  const eq = lower.indexOf('=');
8
8
  const lhs = (eq < 0 ? lower : lower.slice(0, eq)).trim();
9
9
  const bare = lhs.startsWith('+') || lhs.startsWith('-') ? lhs.slice(1).trim() : lhs;
10
- if (bare !== 'planmodereminder')
10
+ const retiredRows = [
11
+ {
12
+ key: 'planModeReminder',
13
+ since: 'core 7.39.0 / server 7.113.0',
14
+ because: 'the engine now states the plan posture itself whenever the permission mode is "plan"',
15
+ remedy: 'send permissionMode "plan" for the plan posture',
16
+ },
17
+ ];
18
+ const row = retiredRows.find((r) => r.key.toLowerCase() === bare);
19
+ if (row === undefined)
11
20
  return undefined;
12
- const head = '"planModeReminder" was retired with core 7.39.0 / server 7.113.0 — the engine now states the plan posture itself whenever the permission mode is "plan"';
13
- if (form === 'token')
14
- return `${head}, and a request carrying the key is answered 400 request.field_invalid; remove the token (send permissionMode "plan" for the plan posture)`;
15
- return nameOrToken === 'planModeReminder'
16
- ? `${head}, and a request carrying this key is answered 400 request.field_invalid; remove the key (send permissionMode "plan" for the plan posture)`
17
- : `${head}; the server ignores this spelling of it, but it is refused here so the retired key is not sent under any spelling; remove the key (send permissionMode "plan" for the plan posture)`;
21
+ const head = `"${row.key}" was retired with ${row.since} — ${row.because}`;
22
+ const why = form === 'token'
23
+ ? `${head}, and a request carrying the key is answered 400 request.field_invalid; remove the token (${row.remedy})`
24
+ : nameOrToken === row.key
25
+ ? `${head}, and a request carrying this key is answered 400 request.field_invalid; remove the key (${row.remedy})`
26
+ : `${head}; the server ignores this spelling of it, but it is refused here so the retired key is not sent under any spelling; remove the key (${row.remedy})`;
27
+ return { key: row.key, why, because: row.because, remedy: row.remedy };
18
28
  }
@@ -0,0 +1 @@
1
+ export declare function toolHistoryBadTurnSentence(promptText: unknown): string;