@sema-agent/client-core 0.97.1 → 0.98.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 (281) hide show
  1. package/CHANGELOG.md +408 -0
  2. package/README.md +74 -37
  3. package/dist/adapt/arms.d.ts +1 -0
  4. package/dist/adapt/arms.js +128 -34
  5. package/dist/adapt/ids.d.ts +12 -1
  6. package/dist/adapt/ids.js +59 -8
  7. package/dist/adapt/instanceLedger.d.ts +50 -0
  8. package/dist/adapt/instanceLedger.js +147 -0
  9. package/dist/adapt/textStream.d.ts +1 -0
  10. package/dist/adapt/textStream.js +24 -7
  11. package/dist/adapt/toolCards.d.ts +27 -5
  12. package/dist/adapt/toolCards.js +39 -6
  13. package/dist/adapt/wireShapes.js +6 -2
  14. package/dist/adapt.d.ts +2 -0
  15. package/dist/adapt.js +8 -3
  16. package/dist/adapter/activeRunSelfHeal.d.ts +5 -0
  17. package/dist/adapter/activeRunSelfHeal.js +51 -28
  18. package/dist/adapter/downstream/eventToSdkMessage.d.ts +2 -5
  19. package/dist/adapter/downstream/eventToSdkMessage.js +27 -34
  20. package/dist/adapter/downstream/terminalToSdkResult.js +11 -4
  21. package/dist/adapter/downstream/turnUsageToModelUsage.d.ts +5 -2
  22. package/dist/adapter/downstream/turnUsageToModelUsage.js +2 -0
  23. package/dist/adapter/runStream.js +29 -13
  24. package/dist/adapter/types.d.ts +4 -4
  25. package/dist/agentSession/backgroundView.js +2 -1
  26. package/dist/agentSession/engineAgentRegistryRead.d.ts +2 -2
  27. package/dist/agentSession/engineAgentRegistryRead.js +12 -13
  28. package/dist/agentsWireCaps.d.ts +8 -8
  29. package/dist/agentsWireCaps.js +168 -175
  30. package/dist/approvalDecidedByCapability.d.ts +0 -4
  31. package/dist/approvalDecidedByCapability.js +0 -6
  32. package/dist/approvalsStreamLiveCapability.d.ts +0 -4
  33. package/dist/approvalsStreamLiveCapability.js +0 -6
  34. package/dist/assistantInbox.d.ts +34 -0
  35. package/dist/assistantInbox.js +118 -0
  36. package/dist/centerWiringCapability.js +9 -1
  37. package/dist/clientSlice.d.ts +0 -9
  38. package/dist/clientSlice.js +0 -3
  39. package/dist/cloudConfigWireCaps.d.ts +4 -2
  40. package/dist/cloudConfigWireCaps.js +81 -61
  41. package/dist/compensations.js +1 -1
  42. package/dist/connectorStatus.d.ts +21 -0
  43. package/dist/connectorStatus.js +112 -0
  44. package/dist/controlRouter.d.ts +14 -1
  45. package/dist/controlRouter.js +68 -17
  46. package/dist/coreValuePorts.d.ts +3 -3
  47. package/dist/decideReceipt.d.ts +2 -2
  48. package/dist/decideReceipt.js +5 -2
  49. package/dist/declared/supportFloorDeclared.js +3 -3
  50. package/dist/deviceExecutorManagementCapability.d.ts +0 -4
  51. package/dist/deviceExecutorManagementCapability.js +0 -6
  52. package/dist/deviceRebind.d.ts +49 -1
  53. package/dist/deviceRebind.js +221 -3
  54. package/dist/displayUntrusted.d.ts +1 -0
  55. package/dist/displayUntrusted.js +250 -76
  56. package/dist/engineAgentAbsence.d.ts +1 -1
  57. package/dist/engineAgentPanelStore.d.ts +5 -4
  58. package/dist/engineAgentPanelStore.js +3 -12
  59. package/dist/engineCapReader.d.ts +0 -4
  60. package/dist/engineCapReader.js +1 -5
  61. package/dist/engineCapsCache.d.ts +4 -0
  62. package/dist/engineCapsCache.js +17 -12
  63. package/dist/engineClosedSets.d.ts +1 -0
  64. package/dist/engineClosedSets.js +4 -1
  65. package/dist/engineErrorCodes.d.ts +9 -2
  66. package/dist/engineErrorCodes.js +9 -1
  67. package/dist/engineIdentity.d.ts +1 -0
  68. package/dist/engineIdentity.js +8 -0
  69. package/dist/engineRowRef.d.ts +28 -0
  70. package/dist/engineRowRef.js +111 -0
  71. package/dist/engineSessionMessages.d.ts +67 -0
  72. package/dist/engineSessionMessages.js +364 -0
  73. package/dist/engineToolDirectory.d.ts +0 -9
  74. package/dist/engineToolDirectory.js +1 -94
  75. package/dist/engineUrl.d.ts +18 -0
  76. package/dist/engineUrl.js +52 -0
  77. package/dist/env/uiLanguage.d.ts +9 -0
  78. package/dist/env/uiLanguage.js +35 -0
  79. package/dist/eventLeg.d.ts +92 -0
  80. package/dist/eventLeg.js +285 -0
  81. package/dist/executionLaneCapability.d.ts +0 -4
  82. package/dist/executionLaneCapability.js +3 -16
  83. package/dist/fileHistoryCaptureCapability.d.ts +0 -4
  84. package/dist/fileHistoryCaptureCapability.js +5 -7
  85. package/dist/fleet/fleetLedger.d.ts +0 -3
  86. package/dist/fleet/fleetLedger.js +21 -36
  87. package/dist/fleet/fleetProjection.d.ts +2 -2
  88. package/dist/fleet/fleetProjection.js +10 -8
  89. package/dist/frameBinding.d.ts +5 -0
  90. package/dist/frameBinding.js +23 -0
  91. package/dist/gateFailureCodes.d.ts +2 -0
  92. package/dist/gateFailureCodes.js +15 -0
  93. package/dist/gateOutcome.d.ts +3 -1
  94. package/dist/gateOutcome.js +25 -6
  95. package/dist/gateVocabulary.d.ts +5 -0
  96. package/dist/gateVocabulary.js +64 -2
  97. package/dist/generated/engineAskFaceTables.js +2 -2
  98. package/dist/generated/engineFactTables.d.ts +6 -3
  99. package/dist/generated/engineFactTables.js +22 -4
  100. package/dist/generated/engineNoticeTables.js +9 -0
  101. package/dist/generated/toolNameTables.d.ts +1 -0
  102. package/dist/generated/toolNameTables.js +1 -0
  103. package/dist/hitl/allowRuleShadow.d.ts +6 -1
  104. package/dist/hitl/allowRuleShadow.js +21 -17
  105. package/dist/hitl/approvalCardReading.d.ts +15 -0
  106. package/dist/hitl/approvalCardReading.js +154 -0
  107. package/dist/hitl/approvalCardReasons.d.ts +13 -0
  108. package/dist/hitl/approvalCardReasons.js +120 -0
  109. package/dist/hitl/approvalHolds.d.ts +47 -15
  110. package/dist/hitl/approvalHolds.js +134 -28
  111. package/dist/hitl/approvalResolution.d.ts +51 -26
  112. package/dist/hitl/approvalResolution.js +86 -122
  113. package/dist/hitl/approvalsFeed.js +6 -18
  114. package/dist/hitl/askClassPair.d.ts +2 -0
  115. package/dist/hitl/askClassPair.js +1 -0
  116. package/dist/hitl/askGateWire.d.ts +20 -2
  117. package/dist/hitl/askGateWire.js +49 -1
  118. package/dist/hitl/askParkRowRouting.d.ts +5 -0
  119. package/dist/hitl/askParkRowRouting.js +32 -1
  120. package/dist/hitl/askSettlementLine.d.ts +18 -0
  121. package/dist/hitl/askSettlementLine.js +79 -0
  122. package/dist/hitl/automaticAnswerVerdict.d.ts +1 -1
  123. package/dist/hitl/automaticAnswerVerdict.js +21 -5
  124. package/dist/hitl/crashConverged.d.ts +11 -20
  125. package/dist/hitl/crashConverged.js +56 -0
  126. package/dist/hitl/crashConvergedNotice.d.ts +3 -1
  127. package/dist/hitl/crashConvergedNotice.js +48 -11
  128. package/dist/hitl/decisionConflict.js +3 -10
  129. package/dist/hitl/decisionRefusal.d.ts +40 -1
  130. package/dist/hitl/decisionRefusal.js +199 -42
  131. package/dist/hitl/frameRouter.d.ts +5 -2
  132. package/dist/hitl/frameRouter.js +20 -16
  133. package/dist/hitl/gateLedger.d.ts +2 -0
  134. package/dist/hitl/gateLedger.js +50 -13
  135. package/dist/hitl/hitlBridge.d.ts +1 -2
  136. package/dist/hitl/hitlBridge.js +10 -7
  137. package/dist/hitl/livePendingAsk.d.ts +3 -3
  138. package/dist/hitl/livePendingAsk.js +7 -18
  139. package/dist/hitl/parkResolver.d.ts +2 -24
  140. package/dist/hitl/parkResolver.js +61 -97
  141. package/dist/hitl/persistedRulesWire.d.ts +24 -0
  142. package/dist/hitl/persistedRulesWire.js +122 -2
  143. package/dist/hitl/planReviewWire.d.ts +26 -13
  144. package/dist/hitl/planReviewWire.js +112 -78
  145. package/dist/hitl/refusedToolNameProse.d.ts +0 -1
  146. package/dist/hitl/refusedToolNameProse.js +0 -3
  147. package/dist/hitl/replayedApproval.d.ts +4 -3
  148. package/dist/hitl/replayedApproval.js +7 -4
  149. package/dist/hitl/sessionPolicyDeliverable.js +2 -4
  150. package/dist/hitl/sessionPolicyWire.d.ts +32 -20
  151. package/dist/hitl/sessionPolicyWire.js +162 -52
  152. package/dist/hitl/standingRows.d.ts +20 -2
  153. package/dist/hitl/standingRows.js +69 -8
  154. package/dist/hitl/toolApprovalWire.d.ts +87 -152
  155. package/dist/hitl/toolApprovalWire.js +591 -380
  156. package/dist/hookMatcherVerdict.d.ts +6 -1
  157. package/dist/hookMatcherVerdict.js +14 -7
  158. package/dist/hooksWireCaps.d.ts +2 -2
  159. package/dist/hooksWireCaps.js +59 -55
  160. package/dist/i18n/messages.en.d.ts +121 -0
  161. package/dist/i18n/messages.en.js +119 -0
  162. package/dist/i18n/messages.zh.d.ts +3 -0
  163. package/dist/i18n/messages.zh.js +120 -0
  164. package/dist/i18n/translate.d.ts +25 -0
  165. package/dist/i18n/translate.js +127 -0
  166. package/dist/index.d.ts +53 -20
  167. package/dist/index.js +38 -11
  168. package/dist/inheritEnvCapability.d.ts +31 -0
  169. package/dist/inheritEnvCapability.js +104 -0
  170. package/dist/liveModelCatalog.d.ts +1 -2
  171. package/dist/liveModelCatalog.js +2 -6
  172. package/dist/liveQuestionStore.d.ts +2 -21
  173. package/dist/mcpLiveness.d.ts +2 -1
  174. package/dist/mcpProbeWire.d.ts +6 -1
  175. package/dist/mcpProbeWire.js +1 -1
  176. package/dist/mcpWireCaps.d.ts +13 -2
  177. package/dist/mcpWireCaps.js +48 -0
  178. package/dist/memoryEntriesWire.d.ts +4 -9
  179. package/dist/model/modelSupplyRules.d.ts +0 -2
  180. package/dist/model/modelSupplyRules.js +3 -12
  181. package/dist/model/modelsPolicy.d.ts +0 -5
  182. package/dist/model/modelsPolicy.js +6 -36
  183. package/dist/model/subagentModelWord.d.ts +31 -0
  184. package/dist/model/subagentModelWord.js +261 -0
  185. package/dist/notifications.d.ts +6 -0
  186. package/dist/notifications.js +71 -23
  187. package/dist/outputStyleSeatCapability.d.ts +0 -3
  188. package/dist/outputStyleSeatCapability.js +0 -3
  189. package/dist/ownKey.d.ts +15 -0
  190. package/dist/ownKey.js +60 -3
  191. package/dist/panelReduce.d.ts +15 -9
  192. package/dist/panelReduce.js +680 -549
  193. package/dist/panelStateHolder.d.ts +3 -7
  194. package/dist/panelStateHolder.js +14 -130
  195. package/dist/peerLaneCapability.d.ts +0 -4
  196. package/dist/peerLaneCapability.js +0 -6
  197. package/dist/permissionRulesWriteCapability.d.ts +0 -4
  198. package/dist/permissionRulesWriteCapability.js +0 -6
  199. package/dist/permissionWireCaps.d.ts +2 -2
  200. package/dist/permissionWireCaps.js +2 -0
  201. package/dist/permissionsAllowGrantCapability.d.ts +0 -4
  202. package/dist/permissionsAllowGrantCapability.js +0 -6
  203. package/dist/permissionsDeclaration.d.ts +0 -11
  204. package/dist/permissionsDeclaration.js +60 -53
  205. package/dist/pluginHooksWire.d.ts +1 -1
  206. package/dist/pluginHooksWire.js +3 -6
  207. package/dist/preemptWire.d.ts +44 -0
  208. package/dist/preemptWire.js +83 -0
  209. package/dist/printToolResultFrame.js +15 -4
  210. package/dist/replayBody.d.ts +3 -0
  211. package/dist/replayBody.js +14 -0
  212. package/dist/request/taskRequest.d.ts +0 -1
  213. package/dist/request/taskRequest.js +0 -3
  214. package/dist/resumeRefusalCopy.d.ts +2 -1
  215. package/dist/resumeRefusalCopy.js +38 -2
  216. package/dist/retryStatus.d.ts +8 -0
  217. package/dist/retryStatus.js +106 -1
  218. package/dist/rewindArchiveCapability.d.ts +0 -4
  219. package/dist/rewindArchiveCapability.js +2 -10
  220. package/dist/rewindArchiveReading.d.ts +0 -1
  221. package/dist/rewindArchiveReading.js +0 -3
  222. package/dist/runCancelContext.d.ts +2 -1
  223. package/dist/runCancelContext.js +4 -2
  224. package/dist/runReattachPolicy.d.ts +31 -0
  225. package/dist/runReattachPolicy.js +46 -0
  226. package/dist/runTerminal.d.ts +3 -6
  227. package/dist/runTerminal.js +8 -9
  228. package/dist/sandboxWire.d.ts +3 -1
  229. package/dist/sandboxWire.js +76 -27
  230. package/dist/scenarioWire.js +1 -1
  231. package/dist/seam.d.ts +24 -2
  232. package/dist/seam.js +15 -3
  233. package/dist/seatContract.d.ts +53 -10
  234. package/dist/seatContract.js +132 -81
  235. package/dist/sessionPolicyCapability.d.ts +0 -4
  236. package/dist/sessionPolicyCapability.js +0 -6
  237. package/dist/sessionSyncFileHistoryCapability.d.ts +0 -3
  238. package/dist/sessionSyncFileHistoryCapability.js +0 -3
  239. package/dist/skillToolListsCapability.d.ts +0 -3
  240. package/dist/skillToolListsCapability.js +0 -3
  241. package/dist/sqlEngineCapability.d.ts +0 -4
  242. package/dist/sqlEngineCapability.js +0 -6
  243. package/dist/steerPriorityCapability.d.ts +0 -3
  244. package/dist/steerPriorityCapability.js +0 -3
  245. package/dist/streamDrainingLegs.d.ts +4 -0
  246. package/dist/streamDrainingLegs.js +6 -1
  247. package/dist/subagent/engineCompactWire.d.ts +0 -1
  248. package/dist/subagent/engineCompactWire.js +7 -5
  249. package/dist/subagent/engineTaskHandleWire.js +4 -7
  250. package/dist/subagentContentStore.js +1 -11
  251. package/dist/submitReopen.d.ts +24 -0
  252. package/dist/submitReopen.js +75 -0
  253. package/dist/terminalStatuses.d.ts +3 -0
  254. package/dist/terminalStatuses.js +10 -2
  255. package/dist/toolResult.d.ts +10 -1
  256. package/dist/toolResult.js +34 -6
  257. package/dist/toolRoster.d.ts +0 -2
  258. package/dist/toolRoster.js +0 -2
  259. package/dist/turnFailurePresentation.d.ts +28 -0
  260. package/dist/turnFailurePresentation.js +205 -0
  261. package/dist/userInvokedSkillsCapability.d.ts +0 -3
  262. package/dist/userInvokedSkillsCapability.js +0 -3
  263. package/dist/webSearchBackendCapability.d.ts +0 -4
  264. package/dist/webSearchBackendCapability.js +0 -6
  265. package/dist/wireErrorTriage.js +5 -24
  266. package/dist/wireFailureShape.d.ts +62 -5
  267. package/dist/wireFailureShape.js +105 -5
  268. package/dist/wireRefusalCopy.d.ts +12 -2
  269. package/dist/wireRefusalCopy.js +50 -52
  270. package/dist/workflowsJournalCapability.d.ts +0 -4
  271. package/dist/workflowsJournalCapability.js +0 -6
  272. package/dist/writeProtectionCapability.d.ts +0 -4
  273. package/dist/writeProtectionCapability.js +0 -6
  274. package/docs/INTEGRATION-CLIENTS.md +1253 -46
  275. package/package.json +5 -4
  276. package/dist/attachmentSeatCapability.d.ts +0 -12
  277. package/dist/attachmentSeatCapability.js +0 -23
  278. package/dist/hitl/approvalOutcomeNote.d.ts +0 -10
  279. package/dist/hitl/approvalOutcomeNote.js +0 -29
  280. package/dist/sessionReadRedactionCapability.d.ts +0 -13
  281. package/dist/sessionReadRedactionCapability.js +0 -35
@@ -0,0 +1,118 @@
1
+ import { errCodes } from './controlRouter.js';
2
+ import { readOwnDataValue } from './ownKey.js';
3
+ import { isReadCredentialRefusal } from './readCredentialRefusal.js';
4
+ import { wireFailureShapeOf } from './wireFailureShape.js';
5
+ export function isAssistantLaneAbsent(err) {
6
+ try {
7
+ return errCodes(err).status === 501;
8
+ }
9
+ catch {
10
+ return false;
11
+ }
12
+ }
13
+ const SEVERITIES = new Set([1, 2, 3, 4, 5]);
14
+ function own(v, key) {
15
+ try {
16
+ return readOwnDataValue(v, key);
17
+ }
18
+ catch {
19
+ return undefined;
20
+ }
21
+ }
22
+ function nonEmptyString(v) {
23
+ return typeof v === 'string' && v !== '' ? v : undefined;
24
+ }
25
+ function finiteNonNeg(v) {
26
+ return typeof v === 'number' && Number.isFinite(v) && v >= 0 ? v : undefined;
27
+ }
28
+ function entryOf(raw) {
29
+ if (raw === null || typeof raw !== 'object')
30
+ return null;
31
+ const sessionId = nonEmptyString(own(raw, 'sessionId'));
32
+ if (sessionId === undefined)
33
+ return null;
34
+ const scope = nonEmptyString(own(raw, 'scope'));
35
+ const gateKind = nonEmptyString(own(raw, 'gateKind'));
36
+ const sev = own(raw, 'severity');
37
+ const severity = typeof sev === 'number' && SEVERITIES.has(sev) ? sev : undefined;
38
+ const spent = finiteNonNeg(own(raw, 'spentMicroUsd'));
39
+ const deadline = finiteNonNeg(own(raw, 'deadline'));
40
+ const created = finiteNonNeg(own(raw, 'createdAt'));
41
+ const objective = nonEmptyString(own(raw, 'objective'));
42
+ const input = own(raw, 'input');
43
+ const inputPreview = typeof input === 'string' && input !== '' ? input : undefined;
44
+ return Object.freeze({
45
+ sessionId,
46
+ ...(scope !== undefined ? { scope } : {}),
47
+ ...(gateKind !== undefined ? { gateKind } : {}),
48
+ ...(severity !== undefined ? { severity } : {}),
49
+ ...(spent !== undefined ? { spentMicroUsd: spent } : {}),
50
+ ...(deadline !== undefined ? { deadlineMs: deadline } : {}),
51
+ ...(created !== undefined ? { createdAtMs: created } : {}),
52
+ ...(objective !== undefined ? { objective } : {}),
53
+ ...(inputPreview !== undefined ? { inputPreview } : {}),
54
+ ...(own(raw, 'requiresRealApproval') === true ? { requiresRealApproval: true } : {}),
55
+ ...(own(raw, 'mandated') === true ? { mandated: true } : {}),
56
+ ...(own(raw, 'hasBidiControls') === true ? { hasBidiControls: true } : {}),
57
+ });
58
+ }
59
+ function isArraySafely(v) {
60
+ try {
61
+ return Array.isArray(v);
62
+ }
63
+ catch {
64
+ return false;
65
+ }
66
+ }
67
+ function unavailable(reason, e) {
68
+ if (e === undefined)
69
+ return Object.freeze({ kind: 'unavailable', reason });
70
+ const { status, errorCode } = wireFailureShapeOf(e);
71
+ return Object.freeze({
72
+ kind: 'unavailable',
73
+ reason,
74
+ ...(status !== undefined ? { status } : {}),
75
+ ...(errorCode !== undefined && errorCode !== '' ? { errorCode } : {}),
76
+ });
77
+ }
78
+ export async function readAssistantInbox(assistant, opts) {
79
+ let verb;
80
+ let signal;
81
+ try {
82
+ verb = assistant === null || assistant === undefined ? undefined : Reflect.get(assistant, 'inbox');
83
+ const s = opts === undefined ? undefined : opts.signal;
84
+ if (s !== undefined && s !== null)
85
+ signal = s;
86
+ }
87
+ catch {
88
+ return Object.freeze({ kind: 'not-reported', via: 'unarmed' });
89
+ }
90
+ if (typeof verb !== 'function')
91
+ return Object.freeze({ kind: 'not-reported', via: 'unarmed' });
92
+ let body;
93
+ try {
94
+ body = await verb.call(assistant, signal !== undefined ? { signal } : undefined);
95
+ }
96
+ catch (e) {
97
+ if (isAssistantLaneAbsent(e))
98
+ return Object.freeze({ kind: 'not-reported', via: 'lane-absent' });
99
+ return unavailable(isReadCredentialRefusal(e) ? 'unauthorized' : 'failed', e);
100
+ }
101
+ const raw = body !== null && typeof body === 'object' ? own(body, 'inbox') : undefined;
102
+ if (!isArraySafely(raw))
103
+ return unavailable('unreadable');
104
+ const entries = [];
105
+ let dropped = 0;
106
+ const lenRaw = own(raw, 'length');
107
+ if (typeof lenRaw !== 'number' || !Number.isInteger(lenRaw) || lenRaw < 0)
108
+ return unavailable('unreadable');
109
+ const len = lenRaw;
110
+ for (let i = 0; i < len; i++) {
111
+ const e = entryOf(own(raw, String(i)));
112
+ if (e === null)
113
+ dropped++;
114
+ else
115
+ entries.push(e);
116
+ }
117
+ return Object.freeze({ kind: 'present', entries: Object.freeze(entries), dropped });
118
+ }
@@ -83,9 +83,17 @@ function projectCenterWiringOf(caps) {
83
83
  },
84
84
  };
85
85
  }
86
+ function projectCenterWiringForCache(caps) {
87
+ const r = projectCenterWiringCapability(caps);
88
+ if (r === undefined || r.kind !== 'present' || r.view.caller === undefined)
89
+ return r;
90
+ const view = { ...r.view };
91
+ delete view.caller;
92
+ return { kind: 'present', view };
93
+ }
86
94
  const reader = createEngineCapReader({
87
95
  name: 'centerWiring',
88
- project: projectCenterWiringCapability,
96
+ project: projectCenterWiringForCache,
89
97
  });
90
98
  export function observedCenterWiring(baseUrl = engineWireTarget()?.baseUrl) {
91
99
  return reader.observed(baseUrl);
@@ -35,10 +35,6 @@ export interface ClientSliceLike {
35
35
  }): Promise<unknown>;
36
36
  readSession(sessionId: string): Promise<unknown>;
37
37
  capabilities(): Promise<unknown>;
38
- probeHealth(): Promise<{
39
- ok: boolean;
40
- version?: string;
41
- }>;
42
38
  }
43
39
  export declare const CLIENT_VERBS: readonly [{
44
40
  readonly verb: "streamTask";
@@ -88,14 +84,9 @@ export declare const CLIENT_VERBS: readonly [{
88
84
  readonly verb: "capabilities";
89
85
  readonly required: true;
90
86
  readonly duty: "引擎 caps(所有能力门的数据源;不实现 = 门全判假)";
91
- }, {
92
- readonly verb: "probeHealth";
93
- readonly required: false;
94
- readonly duty: "健康探测";
95
87
  }];
96
88
  type _MissingFromTable = Exclude<keyof ClientSliceLike, (typeof CLIENT_VERBS)[number]['verb']>;
97
89
  type _ExtraInTable = Exclude<(typeof CLIENT_VERBS)[number]['verb'], keyof ClientSliceLike>;
98
90
  type _MustBeNever<T extends never> = T;
99
91
  export type _VerbTableClosure = [_MustBeNever<_MissingFromTable>, _MustBeNever<_ExtraInTable>];
100
- export declare const PROBE_HEALTH_DIVERGENCE: string;
101
92
  export {};
@@ -11,7 +11,4 @@ export const CLIENT_VERBS = [
11
11
  { verb: 'listSessions', required: false, duty: 'resume 选单' },
12
12
  { verb: 'readSession', required: false, duty: '读历史转录' },
13
13
  { verb: 'capabilities', required: true, duty: '引擎 caps(所有能力门的数据源;不实现 = 门全判假)' },
14
- { verb: 'probeHealth', required: false, duty: '健康探测' },
15
14
  ];
16
- export const PROBE_HEALTH_DIVERGENCE = 'probeHealth: SDK 要求 status==="ok",壳侧 limitsWire:225 / detachWire:82 手拼只要 res.ok。' +
17
- 'B4 保旧行为(res.ok),差异待定 —— 换成 SDK 语义会让"自报 degraded 但可用"的引擎少发 detach 头。';
@@ -20,7 +20,7 @@ export interface CloudModelRefIssue {
20
20
  readonly key: 'models' | 'roles' | 'atMention' | 'tierGroups' | 'activeTierGroup';
21
21
  readonly at?: string;
22
22
  readonly target?: string;
23
- readonly reason: 'dangling' | 'rejected' | 'unreadable' | 'unsupported' | 'duplicate' | 'shadowed' | 'unvouched';
23
+ readonly reason: 'dangling' | 'rejected' | 'unreadable' | 'unsupported' | 'duplicate' | 'unvouched';
24
24
  readonly outcome: 'dropped' | 'kept';
25
25
  }
26
26
  export interface CloudModelsDocOptions {
@@ -123,4 +123,6 @@ export interface CloudEffectiveNotice {
123
123
  readonly level: 'warn' | 'info';
124
124
  readonly text: string;
125
125
  }
126
- export declare function cloudEffectiveNotices(p: Pick<CloudProjection, 'effectiveWarnings' | 'budget' | 'runtimeCaps' | 'modelRefIssues' | 'droppedMcpServers'>): CloudEffectiveNotice[];
126
+ export declare function cloudEffectiveNotices(p: Pick<CloudProjection, 'effectiveWarnings' | 'budget' | 'runtimeCaps' | 'modelRefIssues' | 'droppedMcpServers'> & {
127
+ readonly mcp?: readonly McpServerSpec[];
128
+ }): CloudEffectiveNotice[];
@@ -1,8 +1,9 @@
1
- import { MCP_CAPS } from './mcpWireCaps.js';
1
+ import { MCP_CAPS, mcpAssertionHeaderNotSentNotice, readMcpHttpIdentityHeaders } from './mcpWireCaps.js';
2
2
  import { toCappedSpec } from './skillsWireCaps.js';
3
3
  import { TIER_ORDER } from './model/tierVocabulary.js';
4
4
  import { SETTINGS_NARROW_AT_MENTION } from './generated/settingsSchemaFns.js';
5
5
  import { modelsPolicyOf } from './model/modelsPolicy.js';
6
+ import { normalizeEngineBaseUrl } from './engineUrl.js';
6
7
  import { guardedRead, readOwnDataNonEmptyString, readOwnDataValue } from './ownKey.js';
7
8
  import { SETTINGS_BUDGET_NUMBER_KEYS, SETTINGS_BUDGET_PER_MODEL_NUMBER_KEYS, SETTINGS_BUDGET_STRING_KEYS, SETTINGS_TIER_GROUP_NAME_RE, } from './generated/settingsSchemaTables.js';
8
9
  const asRec = (v) => (typeof v === 'object' && v !== null && !Array.isArray(v) ? v : undefined);
@@ -63,7 +64,8 @@ export function cloudMcpToSpecs(servers, env) {
63
64
  drop(name, 'missing-field');
64
65
  continue;
65
66
  }
66
- if (asStr(t.principalHeader) && asStr(t.assertionHeader)) {
67
+ const identity = readMcpHttpIdentityHeaders(t);
68
+ if (identity.kind === 'both_set') {
67
69
  drop(name, 'principal-and-assertion-header');
68
70
  continue;
69
71
  }
@@ -78,12 +80,12 @@ export function cloudMcpToSpecs(servers, env) {
78
80
  else
79
81
  headers[headerName] = v;
80
82
  }
81
- const principalHeader = asStr(t.principalHeader);
82
83
  transport = {
83
84
  kind: 'http',
84
85
  url,
85
86
  ...(Object.keys(headers).length > 0 ? { headers } : {}),
86
- ...(principalHeader ? { principalHeader } : {}),
87
+ ...(identity.principalHeader !== undefined ? { principalHeader: identity.principalHeader } : {}),
88
+ ...(identity.assertionHeader !== undefined ? { assertionHeader: identity.assertionHeader } : {}),
87
89
  };
88
90
  }
89
91
  else {
@@ -145,17 +147,54 @@ const setOwn = (o, k, v) => {
145
147
  function modelsDocPositionOf(m, key) {
146
148
  return guardedRead(() => (Object.hasOwn(m, key) ? { value: m[key] } : 'absent')) ?? 'unreadable';
147
149
  }
150
+ function writtenCopyOf(v, pinned) {
151
+ try {
152
+ if (pinned === undefined) {
153
+ const enc = JSON.stringify(v);
154
+ return enc === undefined ? undefined : { value: JSON.parse(enc) };
155
+ }
156
+ const src = asRec(v);
157
+ if (src === undefined)
158
+ return undefined;
159
+ const out = {};
160
+ for (const k of Object.keys(src)) {
161
+ const enc = JSON.stringify(k === pinned.key ? pinned.value : src[k]);
162
+ if (enc !== undefined)
163
+ setOwn(out, k, JSON.parse(enc));
164
+ }
165
+ return { value: out };
166
+ }
167
+ catch {
168
+ return undefined;
169
+ }
170
+ }
148
171
  function modelsDocOf(models, opts) {
149
172
  const m = asRec(models);
150
- if (!m || !Array.isArray(m.models))
173
+ const rawModels = m === undefined ? undefined : guarded(() => m.models);
174
+ if (!m || !Array.isArray(rawModels))
151
175
  return { doc: null, issues: [] };
152
- const entries = m.models.filter((e) => {
176
+ const copyFailures = [];
177
+ const copied = [];
178
+ for (const raw of rawModels) {
179
+ const c = writtenCopyOf(raw);
180
+ if (c !== undefined) {
181
+ copied.push(c.value);
182
+ continue;
183
+ }
184
+ const nm = guarded(() => asStr(asRec(raw)?.name));
185
+ if (nm !== undefined)
186
+ copyFailures.push({ key: 'models', target: nm, reason: 'rejected', outcome: 'dropped' });
187
+ }
188
+ if (copied.length === 0 && copyFailures.length > 0) {
189
+ throw new Error('cloud config: no model entry served to you could be read as data, so the models setting cannot be written; the previous one is kept');
190
+ }
191
+ const entries = copied.filter((e) => {
153
192
  const r = asRec(e);
154
193
  return !!r && !!asStr(r.name) && !!asStr(r.id);
155
194
  });
156
195
  const stripped = entries.map(withoutRegistryAnnotations);
157
196
  const allNames = new Set(entries.map((e) => e.name));
158
- const rawNames = new Set(m.models.map((e) => asStr(asRec(e)?.name)).filter((n) => !!n));
197
+ const rawNames = new Set([...copied.map((e) => asStr(asRec(e)?.name)), ...copyFailures.map((i) => i.target)].filter((n) => !!n));
159
198
  const accept = typeof opts?.entryAccepted === 'function' ? opts.entryAccepted : undefined;
160
199
  const acceptedName = (e) => {
161
200
  try {
@@ -168,7 +207,7 @@ function modelsDocOf(models, opts) {
168
207
  };
169
208
  const acceptedFlags = accept ? stripped.map(acceptedName) : undefined;
170
209
  const names = acceptedFlags ? new Set(stripped.filter((_, i) => acceptedFlags[i]).map((e) => e.name)) : allNames;
171
- const issues = [];
210
+ const issues = [...copyFailures];
172
211
  const drop = (i) => {
173
212
  issues.push({ ...i, outcome: 'dropped' });
174
213
  };
@@ -193,49 +232,22 @@ function modelsDocOf(models, opts) {
193
232
  drop({ key: 'roles', at: 'default', reason: 'unreadable' });
194
233
  drop({ key: 'atMention', at: 'models', reason: 'unreadable' });
195
234
  }
196
- if (policy.defaultUnreadable)
197
- drop({ key: 'roles', at: 'default', reason: 'unreadable' });
198
- const dm = policy.defaultModel;
199
- let defaultRole;
200
- let defaultWinner;
201
- if (dm !== undefined && dm.from === 'default') {
202
- const verdict = modelRefVerdict(dm.name);
203
- if (verdict === 'accepted')
204
- defaultRole = { model: dm.name };
205
- else
206
- drop({ key: 'roles', at: 'default', target: dm.name, reason: verdict });
207
- if (verdict === 'accepted' || verdict === 'unvouched')
208
- defaultWinner = dm.name;
209
- }
210
- const roles = asRec(m.roles);
235
+ const rolesRead = guarded(() => ({ value: m.roles }));
236
+ const roleEntries = rolesRead === undefined ? undefined : guarded(() => Object.entries(asRec(rolesRead.value) ?? {}));
237
+ if (roleEntries === undefined)
238
+ drop({ key: 'roles', at: 'models', reason: 'unreadable' });
211
239
  const keptRoles = {};
212
- let sameModelDefaultRole;
213
- for (const [role, t] of Object.entries(roles ?? {})) {
214
- if (role === 'default' && defaultWinner !== undefined) {
215
- const tr = asRec(t);
216
- let model;
217
- let snapshot;
218
- try {
219
- model = tr && Object.hasOwn(tr, 'model') ? tr.model : undefined;
220
- if (tr !== undefined && typeof model === 'string' && model === defaultWinner) {
221
- snapshot = {};
222
- for (const [k, v] of Object.entries(tr))
223
- setOwn(snapshot, k, v);
224
- setOwn(snapshot, 'model', model);
225
- }
226
- }
227
- catch {
228
- model = undefined;
229
- snapshot = undefined;
230
- }
231
- if (snapshot !== undefined)
232
- sameModelDefaultRole = snapshot;
233
- else
234
- drop({ key: 'roles', at: 'default', ...refOf(model), reason: 'shadowed' });
240
+ for (const [role, t] of roleEntries ?? []) {
241
+ const first = guarded(() => {
242
+ const r = asRec(t);
243
+ const has = r !== undefined && Object.hasOwn(r, 'model');
244
+ return { tr: r, has, model: has ? r.model : undefined };
245
+ });
246
+ if (first === undefined) {
247
+ drop({ key: 'roles', at: role, reason: 'unreadable' });
235
248
  continue;
236
249
  }
237
- const tr = asRec(t);
238
- const model = tr && Object.hasOwn(tr, 'model') ? tr.model : undefined;
250
+ const { tr, has, model } = first;
239
251
  if (typeof model === 'string') {
240
252
  const verdict = modelRefVerdict(model);
241
253
  if (verdict !== 'accepted') {
@@ -243,12 +255,15 @@ function modelsDocOf(models, opts) {
243
255
  continue;
244
256
  }
245
257
  }
246
- setOwn(keptRoles, role, t);
258
+ const copy = writtenCopyOf(t, tr !== undefined && has ? { key: 'model', value: model } : undefined);
259
+ if (copy === undefined) {
260
+ drop({ key: 'roles', at: role, ...refOf(model), reason: 'unreadable' });
261
+ continue;
262
+ }
263
+ setOwn(keptRoles, role, copy.value);
247
264
  }
248
265
  const rolesOut = {};
249
- if (defaultRole !== undefined)
250
- setOwn(rolesOut, 'default', sameModelDefaultRole ?? defaultRole);
251
- else if (Object.hasOwn(keptRoles, 'default'))
266
+ if (Object.hasOwn(keptRoles, 'default'))
252
267
  setOwn(rolesOut, 'default', keptRoles.default);
253
268
  for (const [k, v] of Object.entries(keptRoles))
254
269
  if (k !== 'default')
@@ -257,11 +272,9 @@ function modelsDocOf(models, opts) {
257
272
  doc.roles = rolesOut;
258
273
  const am = policy.atMention;
259
274
  if (am?.kind === 'unreadable') {
260
- drop({ key: 'atMention', at: am.from, reason: 'unreadable' });
275
+ drop({ key: 'atMention', at: 'atMention', reason: 'unreadable' });
261
276
  }
262
277
  else if (am !== undefined) {
263
- for (let i = 0; i < am.unreadableEntries; i += 1)
264
- drop({ key: 'atMention', reason: 'unreadable' });
265
278
  const v = am.value;
266
279
  if (v.mode === 'only') {
267
280
  for (const n of v.models)
@@ -341,7 +354,7 @@ function modelsDocOf(models, opts) {
341
354
  drop({ key: 'activeTierGroup', ...refOf(a), reason: typeof a === 'string' && a !== '' ? (rawGroupNames.has(a) ? 'rejected' : 'dangling') : 'unreadable' });
342
355
  }
343
356
  }
344
- return { doc, issues };
357
+ return { doc, issues, entriesRead: copied };
345
358
  }
346
359
  export function cloudModelsToDoc(models, opts) {
347
360
  return modelsDocOf(models, opts).doc;
@@ -385,6 +398,10 @@ export function cloudModelMissingKeyEnv(doc, env) {
385
398
  }
386
399
  return [...out];
387
400
  }
401
+ function mirrorUrlOf(raw) {
402
+ const r = normalizeEngineBaseUrl(raw);
403
+ return r.ok ? r.url : raw;
404
+ }
388
405
  export function cloudExecutionToPolicy(execution) {
389
406
  const e = asRec(execution);
390
407
  const lanes = asArr(e?.allowedLanes).filter((l) => typeof l === 'string' && l.length > 0);
@@ -393,7 +410,7 @@ export function cloudExecutionToPolicy(execution) {
393
410
  return {
394
411
  required: e?.required === true,
395
412
  allowedLanes: lanes.length > 0 ? lanes : ['host'],
396
- sessionMirror: mirrorUrl ? { engineUrl: mirrorUrl.replace(/\/+$/, ''), required: m?.required === true } : null,
413
+ sessionMirror: mirrorUrl ? { engineUrl: mirrorUrlOf(mirrorUrl), required: m?.required === true } : null,
397
414
  };
398
415
  }
399
416
  export function cloudRosterNames(rostersValue) {
@@ -549,7 +566,7 @@ export function projectEffectiveBody(body, skillBodies, env, rostersValue, opts)
549
566
  return name && hash && skillBodies[hash] === undefined ? name : undefined;
550
567
  })
551
568
  .filter((n) => !!n);
552
- const { doc: modelsDoc, issues: modelRefIssues } = modelsDocOf(config.models, opts);
569
+ const { doc: modelsDoc, issues: modelRefIssues, entriesRead } = modelsDocOf(config.models, opts);
553
570
  const view = viewModeOf(b);
554
571
  return {
555
572
  mcp,
@@ -561,7 +578,7 @@ export function projectEffectiveBody(body, skillBodies, env, rostersValue, opts)
561
578
  scope: asStr(b.scope) ?? 'global',
562
579
  skillsMissingBody,
563
580
  droppedMcpServers,
564
- droppedModels: cloudModelsDropped(config.models),
581
+ droppedModels: entriesRead === undefined ? [] : cloudModelsDropped({ models: entriesRead }),
565
582
  execution: cloudExecutionToPolicy(config.execution),
566
583
  effectiveWarnings: effectiveWarningsOf(b),
567
584
  budget: budgetOf(b, view),
@@ -597,12 +614,12 @@ function droppedRefNotice(d) {
597
614
  case 'models':
598
615
  return { level: 'warn', text: `cloud config: ${t === undefined ? 'a model entry' : `model "${t}"`} ${ENTRY_REJECTED} — it was left out of the local catalog` };
599
616
  case 'roles':
617
+ if (d.at === 'models')
618
+ return { level: 'warn', text: 'cloud config: the role settings served to you could not be read by this client — they were left out, so no roles are set on the local engine' };
600
619
  if (d.at === 'default' && d.reason === 'unreadable')
601
620
  return { level: 'warn', text: 'cloud config: the default model setting could not be read, so it was left out — the local engine picks its default from roles and tiers instead' };
602
621
  if (d.reason === 'unvouched')
603
622
  return { level: 'warn', text: `cloud config: role "${d.at ?? ''}" points at model "${t ?? ''}", but this client was given no way to check that the local engine can use that model — the role was left out and falls back along the engine's role chain` };
604
- if (d.reason === 'shadowed')
605
- return { level: 'warn', text: `cloud config: the "${d.at ?? ''}" role${t === undefined ? '' : ` ("${t}")`} is overridden by the default model setting served to you — only one default model can be set, so that role entry was left out` };
606
623
  return { level: 'warn', text: `cloud config: role "${d.at ?? ''}" ${t === undefined ? 'names no readable model' : `points at model "${t}", which ${notServed}`} — the role was left out and falls back along the engine's role chain` };
607
624
  case 'atMention':
608
625
  if (d.at === 'atMention' && d.reason === 'dangling')
@@ -790,6 +807,9 @@ export function cloudEffectiveNotices(p) {
790
807
  });
791
808
  }
792
809
  out.push(...droppedMcpNotices(p));
810
+ const assertionLine = mcpAssertionHeaderNotSentNotice(guarded(() => readOwnDataValue(p, 'mcp')) ?? []);
811
+ if (assertionLine !== undefined)
812
+ out.push({ level: 'warn', text: `cloud config: ${assertionLine}` });
793
813
  out.push(budgetNotice(p.budget));
794
814
  out.push(runtimeCapsNotice(p.runtimeCaps));
795
815
  return out;
@@ -89,7 +89,7 @@ export const MIGRATED_COMPENSATIONS = [
89
89
  what: '从落盘转录的 `<task-notification>` XML 反解回植去重键 —— 去重面纯内存,重启即蒸发,' +
90
90
  '「通知 user-turn 已落盘、ack 未落」的 crash 窗口会二次喂模型(#63)',
91
91
  disposition: 'in-library',
92
- libraryHalf: 'notifications.ts parseTranscriptNotificationSeeds(**唯一一份**解析)+ ' +
92
+ libraryHalf: 'notifications.ts parseTranscriptNotificationSeeds(**唯一一份**解析;0.98.0 起逐块解析归线性块解析器,单条口 readTaskNotificationXml 读同一只)+ ' +
93
93
  'adapt.ts importLedgerFromTranscript(消费口)',
94
94
  chromeArm: null,
95
95
  hostHalf: null,
@@ -0,0 +1,21 @@
1
+ import type { ReaderMintedStatus } from '@sema-agent/connectors-contract';
2
+ import type { McpDeploymentOutcome } from './mcpProbeWire.js';
3
+ export type { ReaderMintedState, ReaderMintedStatus } from '@sema-agent/connectors-contract';
4
+ export declare const CONNECTOR_STATUS_UNKNOWN_WHYS: readonly ["name_unreadable", "mount_face_unreadable", "ambiguous", "unobserved", "probe_face_unreadable", "probe_undecided"];
5
+ export type ConnectorStatusUnknownWhy = (typeof CONNECTOR_STATUS_UNKNOWN_WHYS)[number];
6
+ export interface ConnectorStatusInput {
7
+ name: string;
8
+ mountFace: McpDeploymentOutcome;
9
+ }
10
+ export type ConnectorStatusReading = {
11
+ readonly kind: 'reader';
12
+ readonly status: Readonly<ReaderMintedStatus>;
13
+ } | {
14
+ readonly kind: 'self_reported';
15
+ readonly state: 'unknown';
16
+ } | {
17
+ readonly kind: 'unknown';
18
+ readonly why: ConnectorStatusUnknownWhy;
19
+ };
20
+ export declare function connectorStatusOf(input: ConnectorStatusInput): ConnectorStatusReading;
21
+ export declare function connectorStatusLine(reading: ConnectorStatusReading, lang?: string): string;
@@ -0,0 +1,112 @@
1
+ import { mcpEngineLegLivenessOf } from './mcpEngineLeg.js';
2
+ export const CONNECTOR_STATUS_UNKNOWN_WHYS = Object.freeze([
3
+ 'name_unreadable',
4
+ 'mount_face_unreadable',
5
+ 'ambiguous',
6
+ 'unobserved',
7
+ 'probe_face_unreadable',
8
+ 'probe_undecided',
9
+ ]);
10
+ void true;
11
+ const readerReading = (state) => Object.freeze({ kind: 'reader', status: Object.freeze({ state }) });
12
+ const READER_READINGS = Object.freeze({
13
+ unmounted: readerReading('unmounted'),
14
+ unreachable: readerReading('unreachable'),
15
+ });
16
+ const SELF_REPORTED = Object.freeze({ kind: 'self_reported', state: 'unknown' });
17
+ const UNKNOWN_READINGS = Object.freeze(Object.fromEntries(CONNECTOR_STATUS_UNKNOWN_WHYS.map((why) => [why, Object.freeze({ kind: 'unknown', why })])));
18
+ const BY_LIVENESS = Object.freeze({
19
+ reachable: SELF_REPORTED,
20
+ unreachable: READER_READINGS.unreachable,
21
+ unknown: UNKNOWN_READINGS.probe_undecided,
22
+ });
23
+ const UNREADABLE = Symbol('connectorStatus.unreadable');
24
+ function ownField(o, key) {
25
+ if (o === null || typeof o !== 'object')
26
+ return undefined;
27
+ try {
28
+ if (!Object.hasOwn(o, key))
29
+ return undefined;
30
+ return o[key];
31
+ }
32
+ catch {
33
+ return UNREADABLE;
34
+ }
35
+ }
36
+ function mountRowsOf(outcome) {
37
+ if (ownField(outcome, 'status') !== 'face')
38
+ return undefined;
39
+ if (ownField(outcome, 'declaredBy') !== 'deployment')
40
+ return undefined;
41
+ const faceView = ownField(outcome, 'face');
42
+ const servers = ownField(faceView, 'servers');
43
+ if (servers === UNREADABLE || servers === undefined)
44
+ return undefined;
45
+ return servers;
46
+ }
47
+ function readingOfLiveness(lv) {
48
+ switch (lv.kind) {
49
+ case 'not-listed':
50
+ return READER_READINGS.unmounted;
51
+ case 'unobserved':
52
+ return UNKNOWN_READINGS.mount_face_unreadable;
53
+ case 'ambiguous':
54
+ return UNKNOWN_READINGS.ambiguous;
55
+ case 'absent':
56
+ return UNKNOWN_READINGS.unobserved;
57
+ case 'unreadable':
58
+ return UNKNOWN_READINGS.probe_face_unreadable;
59
+ case 'observed':
60
+ return Object.hasOwn(BY_LIVENESS, lv.state) ? BY_LIVENESS[lv.state] : UNKNOWN_READINGS.probe_face_unreadable;
61
+ default: {
62
+ const exhaustive = lv;
63
+ void exhaustive;
64
+ return UNKNOWN_READINGS.mount_face_unreadable;
65
+ }
66
+ }
67
+ }
68
+ export function connectorStatusOf(input) {
69
+ const name = ownField(input, 'name');
70
+ if (typeof name !== 'string' || name === '')
71
+ return UNKNOWN_READINGS.name_unreadable;
72
+ const rows = mountRowsOf(ownField(input, 'mountFace'));
73
+ if (rows === undefined)
74
+ return UNKNOWN_READINGS.mount_face_unreadable;
75
+ let lv;
76
+ try {
77
+ lv = mcpEngineLegLivenessOf(name, rows);
78
+ }
79
+ catch {
80
+ return UNKNOWN_READINGS.mount_face_unreadable;
81
+ }
82
+ return readingOfLiveness(lv);
83
+ }
84
+ const READER_LINES = Object.freeze({
85
+ unmounted: "This connector is not mounted by default: this deployment's default MCP server list does not include it.",
86
+ unreachable: 'This connector is mounted, but the engine could not reach it when it last tried.',
87
+ });
88
+ const SELF_REPORTED_LINE = 'This connector is mounted and the engine reached it. Whether it is authorized is for the connector itself to report, and this client does not read that report.';
89
+ const UNKNOWN_LINES = Object.freeze({
90
+ name_unreadable: "This client cannot tell this connector's status: it was not given a server name to look up.",
91
+ mount_face_unreadable: "This client could not read this deployment's MCP server list, so it cannot tell whether this connector is mounted.",
92
+ ambiguous: "This deployment lists more than one MCP server under this connector's name, so this client cannot tell which one it is.",
93
+ unobserved: 'This connector is mounted, but the engine has no reachability reading for it.',
94
+ probe_face_unreadable: "This connector is mounted, but this client could not read the engine's reachability reading for it.",
95
+ probe_undecided: 'This connector is mounted; the engine tried to reach it but could not tell whether it is reachable.',
96
+ });
97
+ const FALLBACK_LINE = "This client cannot tell this connector's status.";
98
+ export function connectorStatusLine(reading, lang) {
99
+ void lang;
100
+ const kind = ownField(reading, 'kind');
101
+ if (kind === 'reader') {
102
+ const state = ownField(ownField(reading, 'status'), 'state');
103
+ return typeof state === 'string' && Object.hasOwn(READER_LINES, state) ? READER_LINES[state] : FALLBACK_LINE;
104
+ }
105
+ if (kind === 'self_reported')
106
+ return ownField(reading, 'state') === 'unknown' ? SELF_REPORTED_LINE : FALLBACK_LINE;
107
+ if (kind === 'unknown') {
108
+ const why = ownField(reading, 'why');
109
+ return typeof why === 'string' && Object.hasOwn(UNKNOWN_LINES, why) ? UNKNOWN_LINES[why] : FALLBACK_LINE;
110
+ }
111
+ return FALLBACK_LINE;
112
+ }
@@ -1,5 +1,6 @@
1
- import type { TaskRequest, RunReceipt, CancelAck, Scenario, SteerPriority } from '@sema-agent/sdk';
1
+ import type { TaskRequest, RunReceipt, CancelAck, Scenario, SteerPriority, AssistantTaskStatus } from '@sema-agent/sdk';
2
2
  import { type SteerPriorityReading } from './steerPriorityCapability.js';
3
+ import { type PreemptOutcome } from './preemptWire.js';
3
4
  export interface RunsResourceLike {
4
5
  create(req: TaskRequest, opts?: {
5
6
  idempotencyKey?: string | null;
@@ -12,8 +13,14 @@ export interface RunsResourceLike {
12
13
  signal?: AbortSignal;
13
14
  }): Promise<CancelAck>;
14
15
  }
16
+ export interface AssistantPreemptLike {
17
+ preempt(taskId: string, opts?: {
18
+ signal?: AbortSignal;
19
+ }): Promise<AssistantTaskStatus>;
20
+ }
15
21
  export interface ControlClientLike {
16
22
  runs: RunsResourceLike;
23
+ assistant?: AssistantPreemptLike;
17
24
  }
18
25
  export type ControlSafetyCode = 'not_running' | 'invalid_content' | 'queue_full' | 'duplicate_input_id' | 'ambiguous_target' | 'still_running' | 'blocked_by_hook' | 'ledger_unavailable' | 'steering_other' | 'cancel_lost_race' | 'cancel_run_not_running' | 'not_found' | 'priority_not_applied' | 'steer_input_invalid';
19
26
  export declare class ControlSafetyError extends Error {
@@ -31,6 +38,10 @@ export interface ControlRouterSteerOptions {
31
38
  priority?: SteerPriority;
32
39
  steerPriority?: SteerPriorityReading;
33
40
  }
41
+ export interface PreemptOptions {
42
+ signal?: AbortSignal;
43
+ onUnavailable?: 'cancel' | 'report';
44
+ }
34
45
  export interface ControlRouterOptions {
35
46
  sessionId?: string;
36
47
  jobId?: string;
@@ -55,6 +66,8 @@ export declare class ControlRouter {
55
66
  cancel(opts?: {
56
67
  signal?: AbortSignal;
57
68
  }): Promise<CancelAck>;
69
+ private cancelRun;
70
+ preempt(opts?: PreemptOptions): Promise<PreemptOutcome>;
58
71
  }
59
72
  export interface ErrCodes {
60
73
  code?: string | undefined;