@sema-agent/client-core 0.98.0 → 0.100.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/CHANGELOG.md +376 -0
  2. package/README.md +61 -35
  3. package/dist/adapt/arms.js +120 -55
  4. package/dist/adapt/panelTasks.d.ts +3 -2
  5. package/dist/adapt/panelTasks.js +34 -11
  6. package/dist/adapt/textStream.d.ts +1 -1
  7. package/dist/adapt/textStream.js +51 -28
  8. package/dist/adapter/activeRunSelfHeal.d.ts +11 -3
  9. package/dist/adapter/activeRunSelfHeal.js +210 -294
  10. package/dist/adapter/downstream/eventToSdkMessage.d.ts +25 -6
  11. package/dist/adapter/downstream/eventToSdkMessage.js +176 -12
  12. package/dist/adapter/downstream/terminalToSdkResult.js +10 -0
  13. package/dist/adapter/downstream/wiringManifestView.d.ts +3 -1
  14. package/dist/adapter/downstream/wiringManifestView.js +1 -0
  15. package/dist/adapter/runStream.js +82 -40
  16. package/dist/adapter/types.d.ts +2 -0
  17. package/dist/adapter/types.js +2 -1
  18. package/dist/agentSession/engineSessionBackgroundStop.js +16 -8
  19. package/dist/agentsWireCaps.d.ts +7 -3
  20. package/dist/agentsWireCaps.js +133 -39
  21. package/dist/cloudConfigWireCaps.d.ts +10 -1
  22. package/dist/cloudConfigWireCaps.js +181 -65
  23. package/dist/compactionStatus.d.ts +34 -0
  24. package/dist/compactionStatus.js +196 -0
  25. package/dist/controlRouter.d.ts +4 -2
  26. package/dist/controlRouter.js +39 -51
  27. package/dist/coreValuePorts.d.ts +26 -1
  28. package/dist/coreValuePorts.js +10 -0
  29. package/dist/corruptSessionCopy.d.ts +2 -1
  30. package/dist/corruptSessionCopy.js +3 -3
  31. package/dist/decideFailureNote.js +3 -3
  32. package/dist/declared/supportFloorDeclared.js +1 -1
  33. package/dist/detachWire.js +3 -2
  34. package/dist/devicesFace.d.ts +34 -0
  35. package/dist/devicesFace.js +90 -0
  36. package/dist/displayUntrusted.d.ts +1 -0
  37. package/dist/displayUntrusted.js +153 -5
  38. package/dist/engineAgentPanelStore.d.ts +14 -4
  39. package/dist/engineAgentPanelStore.js +14 -0
  40. package/dist/engineCapReader.d.ts +2 -1
  41. package/dist/engineCapReader.js +7 -5
  42. package/dist/engineCapsCache.d.ts +8 -0
  43. package/dist/engineCapsCache.js +59 -6
  44. package/dist/engineCapsChange.d.ts +2 -0
  45. package/dist/engineCapsChange.js +9 -0
  46. package/dist/engineErrorCodes.d.ts +11 -2
  47. package/dist/engineErrorCodes.js +11 -12
  48. package/dist/engineRowRef.js +4 -0
  49. package/dist/engineSessionMessages.d.ts +1 -0
  50. package/dist/engineSessionMessages.js +7 -1
  51. package/dist/engineTargetSeat.d.ts +27 -0
  52. package/dist/engineTargetSeat.js +199 -0
  53. package/dist/engineToolDirectory.d.ts +3 -0
  54. package/dist/engineToolDirectory.js +4 -2
  55. package/dist/engineWireFor.js +3 -8
  56. package/dist/env/uiLanguage.d.ts +2 -1
  57. package/dist/env/uiLanguage.js +3 -2
  58. package/dist/eventLeg.d.ts +7 -5
  59. package/dist/eventLeg.js +68 -49
  60. package/dist/fileHistoryCaptureCapability.d.ts +2 -4
  61. package/dist/fileHistoryCaptureCapability.js +12 -22
  62. package/dist/fileHistoryLegNotice.d.ts +2 -1
  63. package/dist/fileHistoryLegNotice.js +3 -3
  64. package/dist/frameBinding.d.ts +3 -0
  65. package/dist/frameBinding.js +12 -0
  66. package/dist/gateOutcome.js +16 -2
  67. package/dist/gateVocabulary.d.ts +8 -7
  68. package/dist/gateVocabulary.js +71 -73
  69. package/dist/generated/engineFactTables.d.ts +18 -1
  70. package/dist/generated/engineFactTables.js +56 -0
  71. package/dist/generated/engineNoticeTables.js +12 -3
  72. package/dist/generated/settingsSchemaFns.d.ts +18 -0
  73. package/dist/generated/settingsSchemaFns.js +70 -0
  74. package/dist/generated/settingsSchemaHooksClassifier.d.ts +2 -0
  75. package/dist/generated/settingsSchemaHooksClassifier.js +254 -0
  76. package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -0
  77. package/dist/generated/settingsSchemaMcpRequestEntry.js +162 -0
  78. package/dist/generated/settingsSchemaTables.d.ts +2 -0
  79. package/dist/generated/settingsSchemaTables.js +9 -0
  80. package/dist/generated/settingsSchemaTypes.d.ts +133 -0
  81. package/dist/generated/settingsSchemaTypes.js +1 -0
  82. package/dist/hitl/allowRuleShadow.d.ts +2 -1
  83. package/dist/hitl/allowRuleShadow.js +18 -15
  84. package/dist/hitl/approvalCardReasons.d.ts +3 -2
  85. package/dist/hitl/approvalCardReasons.js +29 -30
  86. package/dist/hitl/approvalHolds.d.ts +17 -0
  87. package/dist/hitl/approvalHolds.js +114 -29
  88. package/dist/hitl/askClassPair.d.ts +2 -2
  89. package/dist/hitl/askClassPair.js +16 -0
  90. package/dist/hitl/askGateWire.js +2 -1
  91. package/dist/hitl/askSettlementLine.d.ts +14 -4
  92. package/dist/hitl/askSettlementLine.js +67 -47
  93. package/dist/hitl/attributionLadder.d.ts +23 -0
  94. package/dist/hitl/attributionLadder.js +67 -0
  95. package/dist/hitl/automaticAnswerVerdict.d.ts +2 -1
  96. package/dist/hitl/automaticAnswerVerdict.js +8 -8
  97. package/dist/hitl/crashConvergedNotice.d.ts +5 -4
  98. package/dist/hitl/crashConvergedNotice.js +28 -41
  99. package/dist/hitl/decisionLedger.d.ts +55 -0
  100. package/dist/hitl/decisionLedger.js +156 -0
  101. package/dist/hitl/decisionRefusal.d.ts +1 -0
  102. package/dist/hitl/decisionRefusal.js +1 -1
  103. package/dist/hitl/decisionSend.d.ts +113 -0
  104. package/dist/hitl/decisionSend.js +579 -0
  105. package/dist/hitl/frameRouter.js +7 -8
  106. package/dist/hitl/hitlBridge.d.ts +1 -0
  107. package/dist/hitl/hitlBridge.js +21 -9
  108. package/dist/hitl/persistedRulesWire.d.ts +6 -5
  109. package/dist/hitl/persistedRulesWire.js +55 -73
  110. package/dist/hitl/planReviewWire.d.ts +5 -0
  111. package/dist/hitl/planReviewWire.js +53 -76
  112. package/dist/hitl/sessionPolicyDeliverable.d.ts +2 -0
  113. package/dist/hitl/sessionPolicyDeliverable.js +49 -9
  114. package/dist/hitl/sessionPolicyWire.d.ts +2 -1
  115. package/dist/hitl/sessionPolicyWire.js +23 -24
  116. package/dist/hitl/suspendedReopen.d.ts +2 -1
  117. package/dist/hitl/suspendedReopen.js +7 -10
  118. package/dist/hitl/toolApprovalWire.d.ts +17 -5
  119. package/dist/hitl/toolApprovalWire.js +120 -147
  120. package/dist/hooksWireCaps.js +145 -56
  121. package/dist/host.d.ts +21 -0
  122. package/dist/hostTurnSettings.d.ts +110 -0
  123. package/dist/hostTurnSettings.js +692 -0
  124. package/dist/humanTurn.d.ts +15 -1
  125. package/dist/humanTurn.js +100 -12
  126. package/dist/humanTurnRead.d.ts +2 -0
  127. package/dist/humanTurnRead.js +22 -1
  128. package/dist/i18n/messages.en.d.ts +713 -0
  129. package/dist/i18n/messages.en.js +713 -0
  130. package/dist/i18n/messages.zh.js +854 -1
  131. package/dist/index.d.ts +45 -13
  132. package/dist/index.js +27 -9
  133. package/dist/inheritEnvCapability.d.ts +4 -2
  134. package/dist/inheritEnvCapability.js +12 -5
  135. package/dist/inheritEnvWire.d.ts +3 -2
  136. package/dist/inheritEnvWire.js +14 -16
  137. package/dist/injectionLaneNotice.d.ts +5 -0
  138. package/dist/injectionLaneNotice.js +46 -0
  139. package/dist/interactiveHalt.js +17 -6
  140. package/dist/liveModelCatalog.d.ts +2 -1
  141. package/dist/liveModelCatalog.js +14 -8
  142. package/dist/mcpPanel.d.ts +10 -1
  143. package/dist/mcpPanel.js +42 -13
  144. package/dist/mcpProbeCapability.d.ts +2 -1
  145. package/dist/mcpProbeCapability.js +7 -11
  146. package/dist/mcpProbeWire.d.ts +3 -1
  147. package/dist/mcpProbeWire.js +5 -0
  148. package/dist/mcpReconnect.js +2 -2
  149. package/dist/mcpToolToggles.d.ts +6 -0
  150. package/dist/mcpToolToggles.js +46 -0
  151. package/dist/mcpWireCaps.d.ts +43 -3
  152. package/dist/mcpWireCaps.js +194 -59
  153. package/dist/mcpWireTransport.d.ts +4 -0
  154. package/dist/mcpWireTransport.js +18 -0
  155. package/dist/memoryEntriesWire.js +5 -10
  156. package/dist/model/onboardJudgement.d.ts +93 -0
  157. package/dist/model/onboardJudgement.js +415 -0
  158. package/dist/model/tierVocabulary.d.ts +2 -0
  159. package/dist/model/tierVocabulary.js +17 -5
  160. package/dist/modelCapabilityProbe.d.ts +65 -0
  161. package/dist/modelCapabilityProbe.js +601 -0
  162. package/dist/modelIdentityResolvability.d.ts +5 -0
  163. package/dist/modelIdentityResolvability.js +49 -22
  164. package/dist/ownKey.d.ts +33 -0
  165. package/dist/ownKey.js +109 -0
  166. package/dist/panelReduce.d.ts +11 -1
  167. package/dist/panelReduce.js +95 -16
  168. package/dist/panelStateHolder.d.ts +1 -0
  169. package/dist/panelStateHolder.js +10 -1
  170. package/dist/permissionRuleIssue.d.ts +2 -1
  171. package/dist/permissionRuleIssue.js +23 -20
  172. package/dist/permissionRulesWriteCapability.d.ts +2 -1
  173. package/dist/permissionRulesWriteCapability.js +8 -6
  174. package/dist/pluginHooksWire.d.ts +46 -3
  175. package/dist/pluginHooksWire.js +220 -12
  176. package/dist/prepareRefusal.d.ts +8 -0
  177. package/dist/prepareRefusal.js +72 -0
  178. package/dist/printModelStatus.d.ts +63 -0
  179. package/dist/printModelStatus.js +155 -0
  180. package/dist/request/taskRequest.d.ts +16 -10
  181. package/dist/request/taskRequest.js +195 -58
  182. package/dist/resumeRefusalCopy.d.ts +14 -9
  183. package/dist/resumeRefusalCopy.js +89 -144
  184. package/dist/retryStatus.d.ts +55 -0
  185. package/dist/retryStatus.js +155 -19
  186. package/dist/ruleRefusalSentence.d.ts +4 -0
  187. package/dist/ruleRefusalSentence.js +58 -0
  188. package/dist/sandboxWire.d.ts +2 -1
  189. package/dist/sandboxWire.js +55 -21
  190. package/dist/scenarioRefusal.d.ts +10 -0
  191. package/dist/scenarioRefusal.js +111 -0
  192. package/dist/seam.d.ts +48 -9
  193. package/dist/seam.js +54 -5
  194. package/dist/seatContract.d.ts +272 -14
  195. package/dist/seatContract.js +711 -23
  196. package/dist/selfOrchestrationDenial.js +7 -19
  197. package/dist/sessionIdSegment.d.ts +6 -0
  198. package/dist/sessionIdSegment.js +24 -0
  199. package/dist/sessionMemoryStatus.js +6 -11
  200. package/dist/sessionPolicyCapability.d.ts +2 -1
  201. package/dist/sessionPolicyCapability.js +8 -6
  202. package/dist/settingsCredentialKeyPaths.d.ts +8 -0
  203. package/dist/settingsCredentialKeyPaths.js +219 -0
  204. package/dist/settingsHooksSalvage.d.ts +44 -0
  205. package/dist/settingsHooksSalvage.js +211 -0
  206. package/dist/skillToolListsCapability.d.ts +2 -1
  207. package/dist/skillToolListsCapability.js +8 -6
  208. package/dist/skillsWireCaps.d.ts +0 -3
  209. package/dist/skillsWireCaps.js +1 -2
  210. package/dist/sseIdleTriage.js +3 -2
  211. package/dist/subagent/engineSubagentResume.js +15 -9
  212. package/dist/subagentContentStore.d.ts +4 -0
  213. package/dist/subagentContentStore.js +157 -27
  214. package/dist/toolHistoryMismatch.js +3 -2
  215. package/dist/toolRoster.d.ts +3 -2
  216. package/dist/toolRoster.js +21 -20
  217. package/dist/toolsFlagNames.d.ts +8 -0
  218. package/dist/toolsFlagNames.js +110 -0
  219. package/dist/turnFailurePresentation.d.ts +12 -1
  220. package/dist/turnFailurePresentation.js +220 -15
  221. package/dist/usageAnalytics.js +6 -11
  222. package/dist/userAttachmentEnvelope.d.ts +1 -0
  223. package/dist/userAttachmentEnvelope.js +37 -7
  224. package/dist/userAttachmentSeat.d.ts +21 -0
  225. package/dist/userAttachmentSeat.js +75 -0
  226. package/dist/userInvokedSkillsCapability.d.ts +11 -1
  227. package/dist/userInvokedSkillsCapability.js +31 -7
  228. package/dist/wireErrorTriage.d.ts +7 -0
  229. package/dist/wireErrorTriage.js +23 -1
  230. package/dist/wireFailureShape.js +2 -1
  231. package/dist/wireRefusalCopy.d.ts +62 -16
  232. package/dist/wireRefusalCopy.js +307 -148
  233. package/dist/workflowsJournalCapability.d.ts +2 -1
  234. package/dist/workflowsJournalCapability.js +8 -6
  235. package/docs/INTEGRATION-CLIENTS.md +951 -42
  236. package/package.json +5 -5
@@ -1,4 +1,7 @@
1
+ import type { UiLanguage } from './env/uiLanguage.js';
1
2
  import { type TurnWireErrorVerdict } from './wireErrorTriage.js';
3
+ import { type LiveModelCatalog } from './liveModelCatalog.js';
4
+ import type { TaskRequestLike } from './request/taskRequest.js';
2
5
  export type TurnFailureCategory = 'auth' | 'billing' | 'rate_limited' | 'invalid_request' | 'capability_unavailable' | 'timeout' | 'server_error' | 'connection_lost' | 'parked' | 'internal';
3
6
  export declare const TURN_FAILURE_CATEGORIES: readonly TurnFailureCategory[];
4
7
  export interface TurnFailureRetry {
@@ -15,11 +18,19 @@ export interface TurnFailurePresentation {
15
18
  readonly name?: string;
16
19
  readonly retry: TurnFailureRetry;
17
20
  readonly waitSec?: number;
21
+ readonly notes: readonly string[];
22
+ readonly waitNote?: string;
23
+ }
24
+ export interface TurnFailureNotesContext {
25
+ readonly requestedScenario?: string;
26
+ readonly sentRequest?: TaskRequestLike;
27
+ readonly modelCatalog?: LiveModelCatalog | null;
28
+ readonly nowMs?: number;
18
29
  }
19
30
  export declare function turnFailurePresentation(err: {} | null | undefined, evidence?: {
20
31
  readonly bound?: boolean;
21
32
  readonly reopened?: boolean;
22
- }): TurnFailurePresentation;
33
+ }, notesCtx?: TurnFailureNotesContext, lang?: UiLanguage): TurnFailurePresentation;
23
34
  export type SeatTurnFailure = Pick<TurnFailurePresentation, 'category' | 'retry' | 'waitSec' | 'headline' | 'errorCode'>;
24
35
  export declare function seatTurnFailureOf(err: {} | null | undefined, evidence?: {
25
36
  readonly bound?: boolean;
@@ -1,10 +1,19 @@
1
+ import { msg, renderMessage } from './i18n/translate.js';
1
2
  import { classifyTurnWireError, effectiveWireErrorCode, isPreStreamDrainingReject } from './wireErrorTriage.js';
2
3
  import { isSseIdleError } from './sseIdleTriage.js';
3
4
  import { isCodeClassifiedGateFailure } from './gateFailureCodes.js';
4
5
  import { CORRUPT_ROW_ERROR_CODE, CORRUPT_SESSION_ERROR_CODE, MEMORY_CONTROL_PLANE_CORRUPT, SCENARIO_ASSIGNMENT_UNKNOWN_ERROR_CODE } from './engineErrorCodes.js';
5
- import { toolDeclarationRefusalFromError } from './wireRefusalCopy.js';
6
+ import { admissionWallRefusalContent, admissionWallRefusalFromError, bodyShapeRefusalFromError, bodyShapeRefusalTouchesSettings, fleetLeaseUnavailableContent, fleetLeaseUnavailableFromError, hostPostureRefusalContent, hostPostureRefusalFromError, fieldLimitRefusalContent, fieldLimitRefusalFromError, toolDeclarationRefusalContent, toolDeclarationRefusalFromError, usageWindowExhaustedContent, usageWindowExhaustedFromError, userAttachmentRefusalFromError, } from './wireRefusalCopy.js';
6
7
  import { THROWN_SLOT_UNREADABLE, readErrorNumber, readThrownSlot, wireFailureTextsOf } from './wireFailureShape.js';
7
8
  import { provablyNotSent } from './engineWireFor.js';
9
+ import { corruptStoredRowContent, scenarioDenyFromError, scenarioNotAllowedContent } from './wireErrorTriage.js';
10
+ import { checkpointUnsupportedVersionContent, checkpointUnsupportedVersionFromError, requireExistingSessionRefusalContent, requireExistingSessionRefusalFromError, resumeContextUnavailableContent, resumeContextUnavailableFromError, resumePolicyBlockContent, resumePolicyBlockFromError, resumeRefusalContent, resumeRefusalFromError, } from './resumeRefusalCopy.js';
11
+ import { resumeReopenContent, resumeReopenFromError } from './hitl/suspendedReopen.js';
12
+ import { prepareRefusalCodeOf, prepareRefusalNoteOf } from './prepareRefusal.js';
13
+ import { isCorruptSessionError } from './corruptSession.js';
14
+ import { corruptSessionContent } from './corruptSessionCopy.js';
15
+ import { inheritEnvRefusalContent, inheritEnvRefusalFromError } from './inheritEnvWire.js';
16
+ import { modelCandidateRejectedContent, modelCandidateRejectedOf } from './liveModelCatalog.js';
8
17
  const CATEGORY_TABLE = Object.freeze({
9
18
  auth: true,
10
19
  billing: true,
@@ -18,12 +27,12 @@ const CATEGORY_TABLE = Object.freeze({
18
27
  internal: true,
19
28
  });
20
29
  export const TURN_FAILURE_CATEGORIES = Object.freeze(Object.keys(CATEGORY_TABLE));
21
- const TURN_FAILURE_HEADLINES = Object.freeze({
22
- connection_lost_not_sent: 'The engine is unreachable — your message did not run. Check that the engine is up, then send it again.',
23
- connection_lost: 'The connection to the engine was lost — it is not known whether your message ran. Check the run’s status, or reattach to it, before sending it again.',
24
- timeout: 'The event stream went silent — the run may still be going on the engine. Check its status before sending again.',
25
- parked: 'The event stream ended while the run had not reached a terminal state — the run is likely parked waiting for a decision, not crashed. Check its status and decide anything pending; the turn did not complete here.',
26
- internal: 'This client hit an internal error — it is a bug in the client, not an engine outage, and the turn did not complete.',
30
+ const TURN_FAILURE_HEADLINE_KEYS = Object.freeze({
31
+ connection_lost_not_sent: 'notice.failure.headline.connectionLostNotSent',
32
+ connection_lost: 'notice.failure.headline.connectionLost',
33
+ timeout: 'notice.failure.headline.timeout',
34
+ parked: 'notice.failure.headline.parked',
35
+ internal: 'notice.failure.headline.internal',
27
36
  });
28
37
  function waitSecOf(err) {
29
38
  const ms = readThrownSlot(err, 'retryAfterMs', 'data');
@@ -88,43 +97,43 @@ function connectionLostBeforeSend(err, evidence) {
88
97
  return false;
89
98
  return typeof err === 'object' && err !== null && provablyNotSent(err);
90
99
  }
91
- export function turnFailurePresentation(err, evidence) {
100
+ export function turnFailurePresentation(err, evidence, notesCtx, lang) {
92
101
  const verdict = classifyTurnWireError(err);
93
102
  let shape;
94
- let headline;
103
+ let headlineKey;
95
104
  let detail;
96
105
  let name;
97
106
  if (verdict.kind === 'http') {
98
107
  shape = httpShapeOf(err, verdict);
99
108
  detail = verdict.message;
100
109
  if (shape.category === 'internal')
101
- headline = TURN_FAILURE_HEADLINES.internal;
110
+ headlineKey = TURN_FAILURE_HEADLINE_KEYS.internal;
102
111
  }
103
112
  else if (verdict.kind === 'stream-ended-without-terminal') {
104
113
  shape = { category: 'parked', offer: false };
105
- headline = TURN_FAILURE_HEADLINES.parked;
114
+ headlineKey = TURN_FAILURE_HEADLINE_KEYS.parked;
106
115
  detail = wireFailureTextsOf(err).reason;
107
116
  }
108
117
  else if (verdict.kind === 'transport') {
109
118
  const notSent = connectionLostBeforeSend(err, evidence);
110
119
  shape = { category: 'connection_lost', offer: notSent };
111
- headline = notSent ? TURN_FAILURE_HEADLINES.connection_lost_not_sent : TURN_FAILURE_HEADLINES.connection_lost;
120
+ headlineKey = notSent ? TURN_FAILURE_HEADLINE_KEYS.connection_lost_not_sent : TURN_FAILURE_HEADLINE_KEYS.connection_lost;
112
121
  detail = verdict.detail;
113
122
  }
114
123
  else if (isIdleWatchdog(err)) {
115
124
  shape = { category: 'timeout', offer: true };
116
- headline = TURN_FAILURE_HEADLINES.timeout;
125
+ headlineKey = TURN_FAILURE_HEADLINE_KEYS.timeout;
117
126
  detail = verdict.detail;
118
127
  }
119
128
  else if (BROWSER_FETCH_FAILURE.test(verdict.detail)) {
120
129
  const notSent = connectionLostBeforeSend(err, evidence);
121
130
  shape = { category: 'connection_lost', offer: notSent };
122
- headline = notSent ? TURN_FAILURE_HEADLINES.connection_lost_not_sent : TURN_FAILURE_HEADLINES.connection_lost;
131
+ headlineKey = notSent ? TURN_FAILURE_HEADLINE_KEYS.connection_lost_not_sent : TURN_FAILURE_HEADLINE_KEYS.connection_lost;
123
132
  detail = verdict.detail;
124
133
  }
125
134
  else {
126
135
  shape = { category: 'internal', offer: false };
127
- headline = TURN_FAILURE_HEADLINES.internal;
136
+ headlineKey = TURN_FAILURE_HEADLINE_KEYS.internal;
128
137
  detail = verdict.detail;
129
138
  name = verdict.name;
130
139
  }
@@ -133,6 +142,8 @@ export function turnFailurePresentation(err, evidence) {
133
142
  const wireRetriable = readThrownSlot(err, 'retriable', 'data') === true && !isCodeClassifiedGateFailure(errorCode, true);
134
143
  const retry = wireRetriable && shape.category !== 'parked' ? { offer: true, basis: 'wire' } : { offer: shape.offer, basis: 'category' };
135
144
  const waitSec = waitSecOf(err);
145
+ const chain = turnFailureNotesOf(err, verdict, notesCtx, waitSec, lang);
146
+ const headline = headlineKey !== undefined ? renderMessage(msg(headlineKey), lang) : undefined;
136
147
  return Object.freeze({
137
148
  category: shape.category,
138
149
  kind: verdict.kind,
@@ -143,8 +154,202 @@ export function turnFailurePresentation(err, evidence) {
143
154
  ...(name !== undefined ? { name } : {}),
144
155
  retry: Object.freeze(retry),
145
156
  ...(waitSec !== undefined ? { waitSec } : {}),
157
+ notes: chain.notes,
158
+ ...(chain.waitNote !== undefined ? { waitNote: chain.waitNote } : {}),
146
159
  });
147
160
  }
161
+ function quotaDetailOf(err) {
162
+ if (readThrownSlot(err, 'status', 'data') !== 429 || readThrownSlot(err, 'errorCode', 'data') !== 'quota_exhausted')
163
+ return null;
164
+ const detail = readThrownSlot(err, 'detail', 'data');
165
+ const slot = (key) => (typeof detail === 'object' && detail !== null ? readThrownSlot(detail, key, 'data') : undefined);
166
+ const windowType = slot('windowType');
167
+ const remaining = slot('remaining');
168
+ const resetAt = slot('resetAt');
169
+ const isEstimate = slot('isEstimate');
170
+ const pool = slot('pool');
171
+ return {
172
+ ...(windowType === 'fiveHour' || windowType === 'weekly' || windowType === 'budget' ? { windowType } : {}),
173
+ ...(typeof remaining === 'number' && Number.isFinite(remaining) ? { remaining } : {}),
174
+ ...(typeof resetAt === 'string' || resetAt === null ? { resetAt } : {}),
175
+ ...(typeof isEstimate === 'boolean' ? { isEstimate } : {}),
176
+ ...(typeof pool === 'string' && pool.length > 0 ? { pool } : {}),
177
+ };
178
+ }
179
+ const MONTH_KEYS = [
180
+ 'notice.failure.month.jan',
181
+ 'notice.failure.month.feb',
182
+ 'notice.failure.month.mar',
183
+ 'notice.failure.month.apr',
184
+ 'notice.failure.month.may',
185
+ 'notice.failure.month.jun',
186
+ 'notice.failure.month.jul',
187
+ 'notice.failure.month.aug',
188
+ 'notice.failure.month.sep',
189
+ 'notice.failure.month.oct',
190
+ 'notice.failure.month.nov',
191
+ 'notice.failure.month.dec',
192
+ ];
193
+ function quotaResetInstant(resetAtIso, nowMs, lang) {
194
+ const t = Date.parse(resetAtIso);
195
+ if (!Number.isFinite(t))
196
+ return undefined;
197
+ const d = new Date(t);
198
+ const now = new Date(nowMs);
199
+ const hm = `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
200
+ const sameDay = d.getFullYear() === now.getFullYear() && d.getMonth() === now.getMonth() && d.getDate() === now.getDate();
201
+ if (sameDay)
202
+ return hm;
203
+ const monthKey = MONTH_KEYS[d.getMonth()];
204
+ return renderMessage(msg('notice.failure.quota.instantOtherDay', { month: monthKey === undefined ? '' : msg(monthKey), day: d.getDate(), time: hm }), lang);
205
+ }
206
+ function quotaExhaustedLine(detail, nowMs, lang) {
207
+ const part = (key, params) => renderMessage(msg(key, params), lang);
208
+ const parts = [];
209
+ if (detail.windowType === 'fiveHour')
210
+ parts.push(part('notice.failure.quota.fiveHour'));
211
+ else if (detail.windowType === 'weekly')
212
+ parts.push(part('notice.failure.quota.weekly'));
213
+ else if (detail.windowType === 'budget') {
214
+ if (detail.pool === 'personal')
215
+ parts.push(part('notice.failure.quota.budgetPersonal'));
216
+ else if (detail.pool)
217
+ parts.push(part('notice.failure.quota.budgetPool', { pool: detail.pool }));
218
+ else
219
+ parts.push(part('notice.failure.quota.budget'));
220
+ }
221
+ else
222
+ parts.push(part('notice.failure.quota.usage'));
223
+ if (typeof detail.remaining === 'number' && Number.isFinite(detail.remaining)) {
224
+ parts.push(detail.windowType === 'budget'
225
+ ? part('notice.failure.quota.remainingBudget', { amount: `$${(detail.remaining / 1_000_000).toFixed(2)}` })
226
+ : part('notice.failure.quota.remainingTokens', { count: detail.remaining.toLocaleString('en-US') }));
227
+ }
228
+ const resetText = typeof detail.resetAt === 'string' ? quotaResetInstant(detail.resetAt, nowMs, lang) : undefined;
229
+ if (resetText)
230
+ parts.push(detail.isEstimate === false ? part('notice.failure.quota.resetAt', { time: resetText }) : part('notice.failure.quota.resetAround', { time: resetText }));
231
+ parts.push(part('notice.failure.quota.refresh'));
232
+ parts.push(part('notice.failure.quota.noBypass'));
233
+ return parts.join(part('notice.failure.quota.join'));
234
+ }
235
+ function protectiveSettingsAtRisk(sent, lang) {
236
+ const out = [];
237
+ const permsRaw = sent.permissions;
238
+ const perms = typeof permsRaw === 'object' && permsRaw !== null ? permsRaw : {};
239
+ const deny = Array.isArray(perms.deny) ? perms.deny.length : 0;
240
+ const ask = Array.isArray(perms.ask) ? perms.ask.length : 0;
241
+ if (deny > 0)
242
+ out.push(renderMessage(msg(deny === 1 ? 'notice.failure.settings.denyRules.one' : 'notice.failure.settings.denyRules.other', { count: deny }), lang));
243
+ if (ask > 0)
244
+ out.push(renderMessage(msg(ask === 1 ? 'notice.failure.settings.askRules.one' : 'notice.failure.settings.askRules.other', { count: ask }), lang));
245
+ if (perms.disableBypassPermissionsMode !== undefined)
246
+ out.push('permissions.disableBypassPermissionsMode');
247
+ if (perms.disableAutoMode !== undefined)
248
+ out.push('permissions.disableAutoMode');
249
+ if (typeof perms.defaultMode === 'string')
250
+ out.push('permissions.defaultMode');
251
+ return out;
252
+ }
253
+ function settingsBodyShapeNote(err, sentRequest, lang) {
254
+ if (readThrownSlot(err, 'status', 'data') !== 400 || readThrownSlot(err, 'errorCode', 'data') !== 'request.body_shape')
255
+ return undefined;
256
+ const touches = bodyShapeRefusalTouchesSettings(bodyShapeRefusalFromError(err), sentRequest);
257
+ if (touches === false)
258
+ return undefined;
259
+ const rawSettings = sentRequest === undefined ? undefined : readThrownSlot(sentRequest, 'settings', 'data');
260
+ if (typeof rawSettings !== 'object' || rawSettings === null || Array.isArray(rawSettings))
261
+ return undefined;
262
+ const sentSettings = rawSettings;
263
+ if (Object.keys(sentSettings).length === 0)
264
+ return undefined;
265
+ const lines = [renderMessage(msg('notice.failure.settings.lead'), lang)];
266
+ const atRisk = protectiveSettingsAtRisk(sentSettings, lang);
267
+ if (atRisk.length > 0) {
268
+ lines.push(renderMessage(msg('notice.failure.settings.safety', { risks: atRisk.join(renderMessage(msg('notice.failure.settings.riskJoin'), lang)) }), lang));
269
+ lines.push(renderMessage(msg('notice.failure.settings.stillLocal'), lang));
270
+ }
271
+ return lines.join('\n');
272
+ }
273
+ function isRefusedRequest(err) {
274
+ const status = readThrownSlot(err, 'status', 'data');
275
+ return typeof status === 'number' && status >= 400 && status < 500;
276
+ }
277
+ function waitSentence(sec, lang) {
278
+ return renderMessage(sec === 1 ? msg('notice.failure.wait.one') : msg('notice.failure.wait.other', { seconds: sec }), lang);
279
+ }
280
+ function turnFailureNotesOf(err, verdict, ctx, waitSec, lang) {
281
+ const lines = [];
282
+ try {
283
+ const sentRequest = ctx === undefined ? undefined : ctx.sentRequest;
284
+ const nowMs = ctx !== undefined && typeof ctx.nowMs === 'number' && Number.isFinite(ctx.nowMs) ? ctx.nowMs : Date.now();
285
+ const quota = quotaDetailOf(err);
286
+ if (quota)
287
+ lines.push(quotaExhaustedLine(quota, nowMs, lang));
288
+ const scenarioDeny = quota ? null : scenarioDenyFromError(err);
289
+ if (scenarioDeny)
290
+ lines.push(scenarioNotAllowedContent(scenarioDeny, ctx?.requestedScenario));
291
+ const resumeRefusal = quota || scenarioDeny ? null : resumeRefusalFromError(err);
292
+ if (resumeRefusal)
293
+ lines.push(resumeRefusalContent(resumeRefusal, lang));
294
+ const requireExisting = quota || scenarioDeny || resumeRefusal ? null : requireExistingSessionRefusalFromError(err);
295
+ if (requireExisting)
296
+ lines.push(requireExistingSessionRefusalContent(requireExisting, lang));
297
+ const resumeReopen = quota || scenarioDeny || resumeRefusal || requireExisting ? null : resumeReopenFromError(err);
298
+ if (resumeReopen)
299
+ lines.push(resumeReopenContent(resumeReopen, lang));
300
+ const resumeGone = quota || scenarioDeny || resumeRefusal || requireExisting || resumeReopen ? null : resumeContextUnavailableFromError(err);
301
+ if (resumeGone)
302
+ lines.push(resumeContextUnavailableContent(resumeGone, lang));
303
+ const checkpointUnsupported = quota || scenarioDeny || resumeRefusal || requireExisting || resumeReopen || resumeGone ? null : checkpointUnsupportedVersionFromError(err);
304
+ if (checkpointUnsupported)
305
+ lines.push(checkpointUnsupportedVersionContent(checkpointUnsupported, undefined, lang));
306
+ const storedRowWhere = quota || scenarioDeny || resumeRefusal || resumeReopen || resumeGone ? undefined : verdict.kind === 'http' ? verdict.storedRowWhere : undefined;
307
+ if (storedRowWhere !== undefined)
308
+ lines.push(corruptStoredRowContent(storedRowWhere));
309
+ if (storedRowWhere === undefined && isCorruptSessionError(err))
310
+ lines.push(corruptSessionContent(lang));
311
+ const usageWindow = quota || scenarioDeny || resumeRefusal || resumeReopen || resumeGone ? null : usageWindowExhaustedFromError(err);
312
+ if (usageWindow)
313
+ lines.push(usageWindowExhaustedContent(usageWindow, lang));
314
+ const hostPosture = quota || scenarioDeny || resumeRefusal || resumeReopen || resumeGone || storedRowWhere !== undefined ? null : hostPostureRefusalFromError(err, sentRequest);
315
+ if (hostPosture)
316
+ lines.push(hostPostureRefusalContent(hostPosture, lang));
317
+ const inheritEnv = hostPosture ? null : inheritEnvRefusalFromError(err, sentRequest);
318
+ if (inheritEnv)
319
+ lines.push(inheritEnvRefusalContent(inheritEnv, lang));
320
+ const bucket = inheritEnv ? null : fieldLimitRefusalFromError(err);
321
+ const toolDecl = toolDeclarationRefusalFromError(err);
322
+ if (toolDecl)
323
+ lines.push(toolDeclarationRefusalContent(toolDecl, lang));
324
+ const prepareCode = toolDecl ? undefined : prepareRefusalCodeOf(err);
325
+ const prepareNote = prepareCode === undefined ? undefined : prepareRefusalNoteOf(prepareCode, userAttachmentRefusalFromError(err) ?? undefined);
326
+ if (prepareNote !== undefined)
327
+ lines.push(prepareNote);
328
+ const wall = admissionWallRefusalFromError(err);
329
+ if (wall)
330
+ lines.push(admissionWallRefusalContent(wall));
331
+ const lease = fleetLeaseUnavailableFromError(err);
332
+ if (lease)
333
+ lines.push(fleetLeaseUnavailableContent(lease, lang));
334
+ const policyBlock = quota || scenarioDeny || resumeRefusal || resumeReopen || resumeGone || usageWindow || hostPosture ? null : resumePolicyBlockFromError(err);
335
+ if (policyBlock)
336
+ lines.push(resumePolicyBlockContent(policyBlock, lang));
337
+ if (bucket)
338
+ lines.push(fieldLimitRefusalContent(bucket, lang));
339
+ const settingsRefusal = settingsBodyShapeNote(err, sentRequest, lang);
340
+ if (settingsRefusal !== undefined)
341
+ lines.push(settingsRefusal);
342
+ if (isRefusedRequest(err) && ctx !== undefined && ctx.modelCatalog !== undefined) {
343
+ const rejected = modelCandidateRejectedContent(modelCandidateRejectedOf(ctx.modelCatalog), lang);
344
+ if (rejected !== undefined)
345
+ lines.push(rejected);
346
+ }
347
+ return Object.freeze({ notes: Object.freeze(lines), ...(waitSec !== undefined && !lease && !usageWindow ? { waitNote: waitSentence(waitSec, lang) } : {}) });
348
+ }
349
+ catch {
350
+ return Object.freeze({ notes: Object.freeze(lines) });
351
+ }
352
+ }
148
353
  export function seatTurnFailureOf(err, evidence) {
149
354
  const p = turnFailurePresentation(err, evidence);
150
355
  return {
@@ -1,3 +1,4 @@
1
+ import { readThrownSlot, THROWN_SLOT_UNREADABLE } from './wireFailureShape.js';
1
2
  export const USAGE_SENTENCES = Object.freeze({
2
3
  analyticsUnavailable: 'Usage analytics aren’t available on this backend.',
3
4
  analyticsUnread: 'Usage analytics couldn’t be read just now.',
@@ -10,18 +11,12 @@ const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v)
10
11
  const nonNeg = (v) => typeof v === 'number' && Number.isFinite(v) && v >= 0;
11
12
  const nonEmpty = (v) => typeof v === 'string' && v.length > 0;
12
13
  export function classifyUsageFailure(e) {
13
- let code;
14
- let status;
15
- try {
16
- const o = e;
17
- const rawCode = o?.errorCode;
18
- const rawStatus = o?.status;
19
- code = typeof rawCode === 'string' ? rawCode : undefined;
20
- status = typeof rawStatus === 'number' ? rawStatus : undefined;
21
- }
22
- catch {
14
+ const rawCode = readThrownSlot(e, 'errorCode', 'data');
15
+ const rawStatus = readThrownSlot(e, 'status', 'data');
16
+ if (rawCode === THROWN_SLOT_UNREADABLE || rawStatus === THROWN_SLOT_UNREADABLE)
23
17
  return { kind: 'failed', error: e };
24
- }
18
+ const code = typeof rawCode === 'string' ? rawCode : undefined;
19
+ const status = typeof rawStatus === 'number' ? rawStatus : undefined;
25
20
  if (code !== undefined) {
26
21
  if (code.startsWith('capability.'))
27
22
  return { kind: 'unavailable', why: 'capability' };
@@ -78,5 +78,6 @@ export type UserAttachmentDescriptor = {
78
78
  };
79
79
  export declare function showAttachmentName(s: string): string;
80
80
  export declare function mintEnvelopeOf(d: DescriptorView, imageDelivery: 'attached' | 'not-attached'): string;
81
+ export declare function seatTextOf(d: DescriptorView): string | undefined;
81
82
  export declare function mintReferenceOf(d: DescriptorView): string;
82
83
  export declare function mintUserAttachmentEnvelope(descriptor: UserAttachmentDescriptor): string;
@@ -83,11 +83,7 @@ function mintText(d) {
83
83
  : `Full path: ${path} (lines ${d.startLine}–${d.startLine + n - 1} of ${d.totalLines}; the other lines are not included). The client read it from disk and copied those lines between the two fence lines below. ${dataNote(d.source, "the file's contents")}`;
84
84
  return fenced(anyEscaped ? [l1, l2, ESCAPE_NOTE] : [l1, l2], body);
85
85
  }
86
- function mintNotebook(d) {
87
- const path = showAttachmentName(d.path);
88
- const l1 = firstLine(d.source, 'a Jupyter notebook', d.name);
89
- if (d.cells.length === 0)
90
- return `${l1}\nFull path: ${path} (0 cells). The client read it from disk; it has no cells.`;
86
+ function notebookBody(d) {
91
87
  let cellsWithImages = 0;
92
88
  let cellsWithOversized = 0;
93
89
  const parts = [];
@@ -113,9 +109,16 @@ function mintNotebook(d) {
113
109
  if (hasImage)
114
110
  cellsWithImages++;
115
111
  }
112
+ return { text: parts.join('\n'), cellsWithImages, cellsWithOversized };
113
+ }
114
+ function mintNotebook(d) {
115
+ const path = showAttachmentName(d.path);
116
+ const l1 = firstLine(d.source, 'a Jupyter notebook', d.name);
117
+ if (d.cells.length === 0)
118
+ return `${l1}\nFull path: ${path} (0 cells). The client read it from disk; it has no cells.`;
119
+ const { text, cellsWithImages, cellsWithOversized } = notebookBody(d);
116
120
  let anyEscaped = false;
117
- const body = parts
118
- .join('\n')
121
+ const body = text
119
122
  .split('\n')
120
123
  .map((line, i) => {
121
124
  const shown = showBodyLine(line);
@@ -281,6 +284,33 @@ function referenceSentence(d) {
281
284
  }
282
285
  return `The user mentioned the ${what} ${name} (${path}) in this message; its contents are not included here.`;
283
286
  }
287
+ export function seatTextOf(d) {
288
+ let text;
289
+ switch (d.kind) {
290
+ case 'text':
291
+ if (d.source !== 'at-mention' || !d.complete || d.lines.length === 0)
292
+ return undefined;
293
+ text = d.lines.join('\n');
294
+ break;
295
+ case 'notebook': {
296
+ if (d.source !== 'at-mention' || d.cells.length === 0)
297
+ return undefined;
298
+ const body = notebookBody(d);
299
+ if (body.cellsWithImages > 0 || body.cellsWithOversized > 0)
300
+ return undefined;
301
+ text = body.text;
302
+ break;
303
+ }
304
+ case 'directory':
305
+ if (d.entries.length === 0 || d.totalEntries > d.entries.length)
306
+ return undefined;
307
+ text = d.entries.map(showAttachmentName).join('\n');
308
+ break;
309
+ default:
310
+ return undefined;
311
+ }
312
+ return text.length > 0 ? text : undefined;
313
+ }
284
314
  export function mintReferenceOf(d) {
285
315
  return `${TAG_OPEN}${tagAttributes(d)} />\n${referenceSentence(d)}`;
286
316
  }
@@ -0,0 +1,21 @@
1
+ export interface UserAttachmentSeatLimits {
2
+ readonly maxEntries: number;
3
+ readonly maxRenderedTextChars: number;
4
+ }
5
+ export interface UserAttachmentSeatPresent {
6
+ readonly kind: 'present';
7
+ readonly entries: readonly string[];
8
+ readonly kinds: readonly string[];
9
+ readonly supplies: readonly string[];
10
+ readonly limits: UserAttachmentSeatLimits;
11
+ }
12
+ export type UserAttachmentSeatReading = {
13
+ kind: 'unobserved';
14
+ } | {
15
+ kind: 'unreadable';
16
+ } | {
17
+ kind: 'not_reported';
18
+ } | UserAttachmentSeatPresent;
19
+ export declare function projectUserAttachmentSeatCapability(caps: {} | null | undefined): UserAttachmentSeatReading | undefined;
20
+ export declare function observedUserAttachmentSeat(baseUrl?: string | undefined): UserAttachmentSeatReading;
21
+ export declare function userAttachmentSeatAdmits(reading: UserAttachmentSeatReading | undefined): 'yes' | 'no' | 'unknown';
@@ -0,0 +1,75 @@
1
+ import { engineWireTarget } from './engineWireTarget.js';
2
+ import { createEngineCapReader } from './engineCapReader.js';
3
+ import { ownDataField, readOwnDataValue } from './ownKey.js';
4
+ const _seatPin = [true, true];
5
+ void _seatPin;
6
+ function stringList(v) {
7
+ if (!Array.isArray(v))
8
+ return undefined;
9
+ const n = ownDataField(v, 'length');
10
+ if (typeof n !== 'number' || !Number.isSafeInteger(n) || n < 0)
11
+ return undefined;
12
+ const out = [];
13
+ for (let i = 0; i < n; i += 1) {
14
+ const d = Object.getOwnPropertyDescriptor(v, i);
15
+ if (d === undefined || !('value' in d) || typeof d.value !== 'string')
16
+ return undefined;
17
+ out.push(d.value);
18
+ }
19
+ return out;
20
+ }
21
+ const positiveInt = (v) => (typeof v === 'number' && Number.isSafeInteger(v) && v >= 1 ? v : undefined);
22
+ const isPlainRecord = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);
23
+ export function projectUserAttachmentSeatCapability(caps) {
24
+ try {
25
+ if (!isPlainRecord(caps))
26
+ return undefined;
27
+ const seat = ownDataField(caps, 'userAttachments');
28
+ if (seat === undefined)
29
+ return { kind: 'not_reported' };
30
+ if (!isPlainRecord(seat))
31
+ return undefined;
32
+ const entries = stringList(ownDataField(seat, 'entries'));
33
+ const kinds = stringList(ownDataField(seat, 'kinds'));
34
+ const supplies = stringList(ownDataField(seat, 'supplies'));
35
+ const limits = ownDataField(seat, 'limits');
36
+ if (entries === undefined || kinds === undefined || supplies === undefined || !isPlainRecord(limits))
37
+ return undefined;
38
+ const maxEntries = positiveInt(ownDataField(limits, 'maxEntries'));
39
+ const maxRenderedTextChars = positiveInt(ownDataField(limits, 'maxRenderedTextChars'));
40
+ if (maxEntries === undefined || maxRenderedTextChars === undefined)
41
+ return undefined;
42
+ return { kind: 'present', entries, kinds, supplies, limits: { maxEntries, maxRenderedTextChars } };
43
+ }
44
+ catch {
45
+ return undefined;
46
+ }
47
+ }
48
+ const reader = createEngineCapReader({ name: 'userAttachments', project: projectUserAttachmentSeatCapability });
49
+ export function observedUserAttachmentSeat(baseUrl = engineWireTarget()?.baseUrl) {
50
+ return reader.observed(baseUrl);
51
+ }
52
+ export function userAttachmentSeatAdmits(reading) {
53
+ try {
54
+ if (!isPlainRecord(reading))
55
+ return 'unknown';
56
+ const kind = readOwnDataValue(reading, 'kind');
57
+ if (kind === 'not_reported')
58
+ return 'no';
59
+ if (kind !== 'present')
60
+ return 'unknown';
61
+ const has = (key, word) => {
62
+ const list = stringList(readOwnDataValue(reading, key));
63
+ return list === undefined ? undefined : list.includes(word);
64
+ };
65
+ const objective = has('entries', 'objective');
66
+ const text = has('supplies', 'content_text');
67
+ const client = has('kinds', 'client_text');
68
+ if (objective === undefined || text === undefined || client === undefined)
69
+ return 'unknown';
70
+ return objective && text && client ? 'yes' : 'no';
71
+ }
72
+ catch {
73
+ return 'unknown';
74
+ }
75
+ }
@@ -1,3 +1,4 @@
1
+ import type { UiLanguage } from './env/uiLanguage.js';
1
2
  export type UserInvokedSkillsReading = {
2
3
  kind: 'unobserved';
3
4
  } | {
@@ -12,4 +13,13 @@ export type UserInvokedSkillsReading = {
12
13
  export declare function projectUserInvokedSkillsCapability(caps: unknown): UserInvokedSkillsReading | undefined;
13
14
  export declare function observedUserInvokedSkills(baseUrl?: string | undefined): UserInvokedSkillsReading;
14
15
  export declare function userInvokedSkillsAvailable(reading: UserInvokedSkillsReading): 'yes' | 'no' | 'unknown';
15
- export declare function userInvokedSkillsDoctorDetail(reading: UserInvokedSkillsReading): string;
16
+ export declare function userInvokedSkillsDoctorDetail(reading: UserInvokedSkillsReading, lang?: UiLanguage): string;
17
+ export interface UserInvokedSkillsDeclaration {
18
+ readonly field: {
19
+ readonly userInvokedSkills?: readonly string[];
20
+ };
21
+ readonly withheld?: {
22
+ readonly cause: Exclude<UserInvokedSkillsReading['kind'], 'present'>;
23
+ };
24
+ }
25
+ export declare function userInvokedSkillsDeclaration(names: readonly string[] | null | undefined, reading: UserInvokedSkillsReading): UserInvokedSkillsDeclaration;
@@ -1,6 +1,7 @@
1
1
  import { engineWireTarget } from './engineWireTarget.js';
2
2
  import { createEngineCapReader, unreadableReadingDetail } from './engineCapReader.js';
3
- import { ownDataField } from './ownKey.js';
3
+ import { msg, renderMessage } from './i18n/translate.js';
4
+ import { ownDataField, readOwnDataValue } from './ownKey.js';
4
5
  export function projectUserInvokedSkillsCapability(caps) {
5
6
  try {
6
7
  if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
@@ -30,17 +31,40 @@ export function userInvokedSkillsAvailable(reading) {
30
31
  return 'no';
31
32
  return 'unknown';
32
33
  }
33
- export function userInvokedSkillsDoctorDetail(reading) {
34
+ export function userInvokedSkillsDoctorDetail(reading, lang) {
35
+ const subject = msg('notice.capability.subject.userInvokedSkills');
34
36
  switch (reading.kind) {
35
37
  case 'unreadable':
36
- return unreadableReadingDetail('user-invoked skills');
38
+ return unreadableReadingDetail(renderMessage(subject, lang), lang);
37
39
  case 'unobserved':
38
- return 'user-invoked skills not observed — the engine reports it on /v1/capabilities (userInvokedSkills); this process has no usable capabilities reading cached for it (none received, the last one was unreadable, or the last one was discarded when the engine connection was reset; this process cannot tell which)';
40
+ return renderMessage(msg('notice.capability.unobserved', { subject, key: 'userInvokedSkills' }), lang);
39
41
  case 'not_reported':
40
- return 'user-invoked skills not reported by this engine — the engine predates it, so naming skills on a request is refused (do not send the key)';
42
+ return renderMessage(msg('notice.capability.userInvokedSkills.notReported'), lang);
41
43
  case 'absent':
42
- return 'user-invoked skills off on this deployment — naming skills on a request is not accepted';
44
+ return renderMessage(msg('notice.capability.userInvokedSkills.absent'), lang);
43
45
  case 'present':
44
- return 'user-invoked skills on — skills the user names on a request take effect when the run starts';
46
+ return renderMessage(msg('notice.capability.userInvokedSkills.present'), lang);
45
47
  }
46
48
  }
49
+ export function userInvokedSkillsDeclaration(names, reading) {
50
+ let named = false;
51
+ try {
52
+ named = Array.isArray(names) && names.length > 0;
53
+ }
54
+ catch {
55
+ named = false;
56
+ }
57
+ if (!named)
58
+ return { field: {} };
59
+ let kind;
60
+ try {
61
+ kind = reading !== null && typeof reading === 'object' ? readOwnDataValue(reading, 'kind') : undefined;
62
+ }
63
+ catch {
64
+ kind = undefined;
65
+ }
66
+ if (kind === 'present')
67
+ return { field: { userInvokedSkills: names } };
68
+ const cause = kind === 'absent' || kind === 'not_reported' || kind === 'unobserved' ? kind : 'unreadable';
69
+ return { field: {}, withheld: { cause } };
70
+ }
@@ -21,6 +21,13 @@ export declare function classifyTurnWireError(err: unknown): TurnWireErrorVerdic
21
21
  export declare function isWireTransportError(err: unknown): boolean;
22
22
  export declare function isPreStreamDrainingReject(err: unknown): boolean;
23
23
  export declare function effectiveWireErrorCode(err: unknown): string | undefined;
24
+ export type NotFoundFailure = {
25
+ readonly kind: 'not_found';
26
+ readonly code: string;
27
+ } | {
28
+ readonly kind: 'unknown_404';
29
+ };
30
+ export declare function isNotFoundFailure(e: {} | null | undefined): NotFoundFailure | false;
24
31
  export declare function corruptStoredRowWhere(err: unknown): string | undefined;
25
32
  export declare function corruptStoredRowContent(where: string): string;
26
33
  export declare function isResumeAtRejection(err: unknown): boolean;