@sema-agent/client-core 0.99.0 → 0.101.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 (374) hide show
  1. package/CHANGELOG.md +572 -0
  2. package/README.md +174 -114
  3. package/dist/adapt/arms.js +109 -50
  4. package/dist/adapt/panelTasks.d.ts +2 -1
  5. package/dist/adapt/panelTasks.js +32 -9
  6. package/dist/adapt/textStream.d.ts +1 -1
  7. package/dist/adapt/textStream.js +58 -32
  8. package/dist/adapt/toolCards.js +9 -8
  9. package/dist/adapt.js +7 -1
  10. package/dist/adapter/activeRunSelfHeal.d.ts +31 -2
  11. package/dist/adapter/activeRunSelfHeal.js +162 -13
  12. package/dist/adapter/downstream/eventToSdkMessage.d.ts +25 -6
  13. package/dist/adapter/downstream/eventToSdkMessage.js +157 -20
  14. package/dist/adapter/downstream/terminalToSdkResult.d.ts +60 -1
  15. package/dist/adapter/downstream/terminalToSdkResult.js +219 -39
  16. package/dist/adapter/downstream/wiringManifestView.d.ts +3 -1
  17. package/dist/adapter/downstream/wiringManifestView.js +1 -0
  18. package/dist/adapter/runStream.d.ts +4 -4
  19. package/dist/adapter/runStream.js +184 -42
  20. package/dist/adapter/types.d.ts +2 -0
  21. package/dist/agentsWireCaps.d.ts +9 -7
  22. package/dist/agentsWireCaps.js +101 -17
  23. package/dist/approvalDecidedByCapability.js +2 -2
  24. package/dist/approvalFrameFamilies.d.ts +33 -0
  25. package/dist/approvalFrameFamilies.js +120 -0
  26. package/dist/approvalsStreamLiveCapability.js +2 -2
  27. package/dist/attachmentsWireCaps.js +41 -13
  28. package/dist/callerCwdCapability.js +2 -2
  29. package/dist/centerWiringCapability.js +2 -2
  30. package/dist/clockReading.d.ts +2 -0
  31. package/dist/clockReading.js +4 -0
  32. package/dist/cloudConfigWireCaps.d.ts +28 -5
  33. package/dist/cloudConfigWireCaps.js +334 -103
  34. package/dist/compactionStatus.d.ts +34 -0
  35. package/dist/compactionStatus.js +196 -0
  36. package/dist/coreValuePorts.d.ts +12 -2
  37. package/dist/coreValuePorts.js +9 -0
  38. package/dist/decideFailureNote.js +8 -6
  39. package/dist/decideReceipt.js +2 -2
  40. package/dist/deviceExecutorManagementCapability.js +2 -2
  41. package/dist/deviceFlowPolling.js +1 -1
  42. package/dist/disableSkillsWire.d.ts +1 -1
  43. package/dist/disableSkillsWire.js +4 -3
  44. package/dist/displayUntrusted.d.ts +1 -0
  45. package/dist/displayUntrusted.js +215 -13
  46. package/dist/engineAgentPanelStore.d.ts +7 -4
  47. package/dist/engineCapReader.js +1 -1
  48. package/dist/engineConfigDrift.js +1 -1
  49. package/dist/engineErrorCodes.d.ts +23 -6
  50. package/dist/engineErrorCodes.js +36 -11
  51. package/dist/engineGenerationConvergence.d.ts +39 -0
  52. package/dist/engineGenerationConvergence.js +95 -0
  53. package/dist/engineGenerationPort.d.ts +61 -0
  54. package/dist/engineGenerationPort.js +144 -0
  55. package/dist/engineHealthFacts.d.ts +23 -0
  56. package/dist/engineHealthFacts.js +92 -0
  57. package/dist/engineIdentity.d.ts +4 -0
  58. package/dist/engineIdentity.js +11 -0
  59. package/dist/engineNoticeCodes.d.ts +2 -5
  60. package/dist/engineRowRef.js +4 -0
  61. package/dist/engineSessionMessages.js +2 -2
  62. package/dist/engineToolDirectory.d.ts +3 -0
  63. package/dist/engineToolDirectory.js +6 -4
  64. package/dist/engineWireFor.d.ts +99 -0
  65. package/dist/engineWireFor.js +248 -6
  66. package/dist/engineWireTarget.d.ts +1 -0
  67. package/dist/engineWireTarget.js +8 -0
  68. package/dist/env/uiLanguage.js +1 -1
  69. package/dist/errorSupplementRoles.d.ts +3 -0
  70. package/dist/errorSupplementRoles.js +37 -0
  71. package/dist/eventLeg.d.ts +1 -7
  72. package/dist/eventLeg.js +7 -8
  73. package/dist/executionLaneCapability.js +2 -2
  74. package/dist/fileHistoryCaptureCapability.d.ts +0 -3
  75. package/dist/fileHistoryCaptureCapability.js +3 -7
  76. package/dist/finalVerifyWire.d.ts +6 -3
  77. package/dist/finalVerifyWire.js +6 -23
  78. package/dist/flagInput.d.ts +4 -0
  79. package/dist/flagInput.js +24 -0
  80. package/dist/fleet/fleetLedger.js +5 -2
  81. package/dist/fleet/fleetProjection.d.ts +1 -0
  82. package/dist/fleet/fleetProjection.js +15 -2
  83. package/dist/gateVocabulary.js +3 -0
  84. package/dist/generated/engineFactTables.d.ts +7 -2
  85. package/dist/generated/engineFactTables.js +79 -0
  86. package/dist/generated/engineNoticeTables.js +15 -0
  87. package/dist/generated/settingsSchemaActiveTiers.d.ts +1 -0
  88. package/dist/generated/settingsSchemaActiveTiers.js +14 -0
  89. package/dist/generated/settingsSchemaCallerTextEcho.d.ts +1 -0
  90. package/dist/generated/settingsSchemaCallerTextEcho.js +8 -0
  91. package/dist/generated/settingsSchemaControlAndBidi.d.ts +1 -0
  92. package/dist/generated/settingsSchemaControlAndBidi.js +8 -0
  93. package/dist/generated/settingsSchemaDefaultModel.d.ts +11 -0
  94. package/dist/generated/settingsSchemaDefaultModel.js +25 -0
  95. package/dist/generated/settingsSchemaFns.d.ts +66 -0
  96. package/dist/generated/settingsSchemaFns.js +38 -0
  97. package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -0
  98. package/dist/generated/settingsSchemaMcpRequestEntry.js +156 -0
  99. package/dist/generated/settingsSchemaSafetyMergeSpec.d.ts +1 -0
  100. package/dist/generated/settingsSchemaSafetyMergeSpec.js +95 -0
  101. package/dist/generated/settingsSchemaSettingsSources.d.ts +1 -0
  102. package/dist/generated/settingsSchemaSettingsSources.js +58 -0
  103. package/dist/generated/settingsSchemaTables.d.ts +3 -0
  104. package/dist/generated/settingsSchemaTables.js +18 -0
  105. package/dist/generated/settingsSchemaTypes.d.ts +28 -0
  106. package/dist/generated/settingsSchemaUrlPattern.d.ts +1 -0
  107. package/dist/generated/settingsSchemaUrlPattern.js +183 -0
  108. package/dist/headlessPermissionModeWire.d.ts +18 -2
  109. package/dist/headlessPermissionModeWire.js +30 -19
  110. package/dist/hitl/allowRuleShadow.js +9 -7
  111. package/dist/hitl/approvalCardReading.d.ts +3 -0
  112. package/dist/hitl/approvalCardReading.js +17 -0
  113. package/dist/hitl/approvalCardReasons.js +2 -2
  114. package/dist/hitl/approvalCompleteParked.js +1 -1
  115. package/dist/hitl/approvalDelivery.d.ts +87 -0
  116. package/dist/hitl/approvalDelivery.js +193 -0
  117. package/dist/hitl/approvalHolds.d.ts +14 -0
  118. package/dist/hitl/approvalHolds.js +41 -0
  119. package/dist/hitl/approvalResolution.d.ts +11 -0
  120. package/dist/hitl/approvalResolution.js +50 -11
  121. package/dist/hitl/askClassPair.d.ts +8 -2
  122. package/dist/hitl/askClassPair.js +31 -4
  123. package/dist/hitl/askParkAutoReopenBlock.d.ts +30 -0
  124. package/dist/hitl/askParkAutoReopenBlock.js +117 -0
  125. package/dist/hitl/askParkRowRouting.js +4 -1
  126. package/dist/hitl/attributionLadder.d.ts +62 -0
  127. package/dist/hitl/attributionLadder.js +138 -0
  128. package/dist/hitl/automaticAnswerVerdict.d.ts +6 -1
  129. package/dist/hitl/automaticAnswerVerdict.js +46 -11
  130. package/dist/hitl/crashConverged.js +2 -2
  131. package/dist/hitl/decisionConflict.d.ts +6 -2
  132. package/dist/hitl/decisionConflict.js +24 -9
  133. package/dist/hitl/decisionLedger.d.ts +55 -0
  134. package/dist/hitl/decisionLedger.js +156 -0
  135. package/dist/hitl/decisionRefusal.d.ts +21 -10
  136. package/dist/hitl/decisionRefusal.js +100 -55
  137. package/dist/hitl/decisionSend.d.ts +116 -0
  138. package/dist/hitl/decisionSend.js +563 -0
  139. package/dist/hitl/frameRouter.d.ts +1 -0
  140. package/dist/hitl/frameRouter.js +9 -2
  141. package/dist/hitl/hitlBridge.d.ts +18 -6
  142. package/dist/hitl/hitlBridge.js +59 -43
  143. package/dist/hitl/livePendingAsk.js +4 -3
  144. package/dist/hitl/noAllowCause.js +1 -1
  145. package/dist/hitl/parkResolver.js +3 -2
  146. package/dist/hitl/persistedRulesWire.js +1 -0
  147. package/dist/hitl/planReviewWire.d.ts +4 -0
  148. package/dist/hitl/planReviewWire.js +104 -106
  149. package/dist/hitl/resumeRunningCard.d.ts +3 -2
  150. package/dist/hitl/resumeRunningCard.js +17 -11
  151. package/dist/hitl/sessionPolicyDeliverable.d.ts +5 -2
  152. package/dist/hitl/sessionPolicyDeliverable.js +65 -35
  153. package/dist/hitl/sessionPolicyWire.d.ts +13 -3
  154. package/dist/hitl/sessionPolicyWire.js +81 -16
  155. package/dist/hitl/standingRows.js +1 -1
  156. package/dist/hitl/toolApprovalWire.d.ts +9 -10
  157. package/dist/hitl/toolApprovalWire.js +103 -151
  158. package/dist/hookMatcherVerdict.d.ts +2 -0
  159. package/dist/hookMatcherVerdict.js +12 -0
  160. package/dist/hooksCompactTransition.d.ts +19 -0
  161. package/dist/hooksCompactTransition.js +41 -0
  162. package/dist/hooksWireCaps.d.ts +1 -1
  163. package/dist/hooksWireCaps.js +202 -203
  164. package/dist/host.d.ts +1 -14
  165. package/dist/host.js +0 -8
  166. package/dist/hostCallbackGuard.d.ts +1 -0
  167. package/dist/hostCallbackGuard.js +1 -1
  168. package/dist/hostSettingsSource.d.ts +172 -0
  169. package/dist/hostSettingsSource.js +675 -0
  170. package/dist/hostTurnSettings.d.ts +114 -19
  171. package/dist/hostTurnSettings.js +966 -68
  172. package/dist/httpHookPolicy.d.ts +37 -0
  173. package/dist/httpHookPolicy.js +176 -0
  174. package/dist/humanTurn.d.ts +4 -2
  175. package/dist/humanTurn.js +40 -10
  176. package/dist/humanTurnRead.js +4 -3
  177. package/dist/humanTurnSentences.d.ts +10 -0
  178. package/dist/humanTurnSentences.js +74 -0
  179. package/dist/i18n/messages.en.d.ts +313 -0
  180. package/dist/i18n/messages.en.js +326 -13
  181. package/dist/i18n/messages.zh.js +341 -13
  182. package/dist/i18n/translate.js +3 -3
  183. package/dist/index.d.ts +85 -15
  184. package/dist/index.js +53 -12
  185. package/dist/inheritEnvCapability.d.ts +4 -1
  186. package/dist/inheritEnvCapability.js +38 -17
  187. package/dist/inheritEnvWire.d.ts +2 -1
  188. package/dist/inheritEnvWire.js +11 -5
  189. package/dist/injectionLaneNotice.d.ts +5 -0
  190. package/dist/injectionLaneNotice.js +46 -0
  191. package/dist/interactiveToolsWire.d.ts +4 -2
  192. package/dist/interactiveToolsWire.js +5 -5
  193. package/dist/jsonFaithful.d.ts +20 -0
  194. package/dist/jsonFaithful.js +152 -0
  195. package/dist/limitsWire.d.ts +7 -2
  196. package/dist/limitsWire.js +19 -13
  197. package/dist/liveInitToolFace.d.ts +6 -1
  198. package/dist/liveInitToolFace.js +5 -3
  199. package/dist/liveModelCatalog.d.ts +22 -0
  200. package/dist/liveModelCatalog.js +132 -18
  201. package/dist/mcpPanel.js +3 -1
  202. package/dist/mcpProbeCapability.js +2 -2
  203. package/dist/mcpReconnect.js +2 -2
  204. package/dist/mcpStatusSupersetKeys.d.ts +24 -0
  205. package/dist/mcpStatusSupersetKeys.js +45 -0
  206. package/dist/mcpToolToggles.d.ts +6 -0
  207. package/dist/mcpToolToggles.js +47 -0
  208. package/dist/mcpWireCaps.d.ts +48 -4
  209. package/dist/mcpWireCaps.js +338 -99
  210. package/dist/mcpWireTransport.d.ts +4 -0
  211. package/dist/mcpWireTransport.js +18 -0
  212. package/dist/memoryComplianceCapability.js +2 -2
  213. package/dist/memoryOriginCapability.js +2 -2
  214. package/dist/model/catalogDefault.d.ts +24 -0
  215. package/dist/model/catalogDefault.js +4 -0
  216. package/dist/model/liveCatalogShape.js +5 -4
  217. package/dist/model/modelsPolicy.js +4 -3
  218. package/dist/model/onboardJudgement.d.ts +1 -0
  219. package/dist/model/onboardJudgement.js +1 -1
  220. package/dist/model/subagentModelWord.js +2 -2
  221. package/dist/modelCapabilityProbe.d.ts +2 -1
  222. package/dist/modelCapabilityProbe.js +16 -15
  223. package/dist/modelIdentityResolvability.d.ts +12 -1
  224. package/dist/modelIdentityResolvability.js +69 -28
  225. package/dist/modsKernelIdentity.d.ts +10 -0
  226. package/dist/modsKernelIdentity.js +103 -0
  227. package/dist/modsKernelTransit.d.ts +8 -0
  228. package/dist/modsKernelTransit.js +6 -0
  229. package/dist/notifications.d.ts +30 -12
  230. package/dist/notifications.js +241 -53
  231. package/dist/outputStyleSeatCapability.js +2 -2
  232. package/dist/ownKey.d.ts +37 -0
  233. package/dist/ownKey.js +238 -2
  234. package/dist/panelReduce.d.ts +5 -0
  235. package/dist/panelReduce.js +45 -13
  236. package/dist/panelStateHolder.d.ts +1 -0
  237. package/dist/panelStateHolder.js +10 -1
  238. package/dist/peerFrames.d.ts +1 -1
  239. package/dist/peerFrames.js +6 -2
  240. package/dist/peerLaneCapability.js +2 -2
  241. package/dist/permissionModesCapability.js +4 -4
  242. package/dist/permissionRuleIssue.d.ts +2 -1
  243. package/dist/permissionRuleIssue.js +24 -21
  244. package/dist/permissionRulesWriteCapability.js +2 -2
  245. package/dist/permissionsAllowGrantCapability.js +2 -2
  246. package/dist/permissionsDeclaration.d.ts +43 -4
  247. package/dist/permissionsDeclaration.js +102 -35
  248. package/dist/pluginHooksWire.d.ts +20 -4
  249. package/dist/pluginHooksWire.js +101 -60
  250. package/dist/prepareRefusal.d.ts +9 -0
  251. package/dist/prepareRefusal.js +90 -0
  252. package/dist/printInitToolFace.js +2 -2
  253. package/dist/printModelStatus.js +1 -1
  254. package/dist/projectMemory.d.ts +32 -0
  255. package/dist/projectMemory.js +70 -0
  256. package/dist/promptBlockedCopy.d.ts +2 -1
  257. package/dist/promptBlockedCopy.js +2 -1
  258. package/dist/promptDelivery.d.ts +23 -3
  259. package/dist/promptDelivery.js +169 -30
  260. package/dist/providerRejection.d.ts +19 -1
  261. package/dist/providerRejection.js +75 -4
  262. package/dist/queuedDelivery.d.ts +48 -0
  263. package/dist/queuedDelivery.js +233 -0
  264. package/dist/reattachWindow.d.ts +94 -0
  265. package/dist/reattachWindow.js +127 -0
  266. package/dist/request/printNotification.d.ts +1 -1
  267. package/dist/request/printNotification.js +5 -1
  268. package/dist/request/submissionIdentity.d.ts +37 -0
  269. package/dist/request/submissionIdentity.js +65 -0
  270. package/dist/request/taskRequest.d.ts +22 -14
  271. package/dist/request/taskRequest.js +312 -202
  272. package/dist/resultFrameKeys.d.ts +1 -0
  273. package/dist/resultFrameKeys.js +4 -1
  274. package/dist/resumeRefusalCopy.d.ts +3 -1
  275. package/dist/resumeRefusalCopy.js +22 -4
  276. package/dist/retryStatus.d.ts +26 -0
  277. package/dist/retryStatus.js +133 -28
  278. package/dist/rewindArchiveCapability.js +2 -2
  279. package/dist/rewindEngineAction.d.ts +2 -0
  280. package/dist/rewindEngineAction.js +23 -1
  281. package/dist/rowKind.d.ts +36 -0
  282. package/dist/rowKind.js +97 -0
  283. package/dist/ruleCompileVerdict.d.ts +18 -0
  284. package/dist/ruleCompileVerdict.js +67 -2
  285. package/dist/ruleReadings.d.ts +58 -0
  286. package/dist/ruleReadings.js +132 -0
  287. package/dist/ruleRefusalSentence.d.ts +8 -0
  288. package/dist/ruleRefusalSentence.js +64 -0
  289. package/dist/runCancelContext.d.ts +0 -1
  290. package/dist/runCancelContext.js +1 -2
  291. package/dist/runTerminal.d.ts +5 -0
  292. package/dist/runTerminal.js +52 -17
  293. package/dist/sandboxWire.d.ts +3 -2
  294. package/dist/sandboxWire.js +59 -27
  295. package/dist/scenarioRefusal.d.ts +2 -1
  296. package/dist/scenarioRefusal.js +6 -6
  297. package/dist/scenarioSkills.d.ts +20 -0
  298. package/dist/scenarioSkills.js +72 -0
  299. package/dist/scenarioWire.d.ts +5 -2
  300. package/dist/scenarioWire.js +9 -9
  301. package/dist/sealedKeyCapability.js +2 -2
  302. package/dist/seam.d.ts +26 -9
  303. package/dist/seam.js +44 -4
  304. package/dist/seatContract.d.ts +62 -9
  305. package/dist/seatContract.js +70 -25
  306. package/dist/selfOrchestrationDenial.js +1 -1
  307. package/dist/sessionPolicyCapability.js +2 -2
  308. package/dist/sessionRulesChildrenReadLive.d.ts +6 -0
  309. package/dist/sessionRulesChildrenReadLive.js +5 -0
  310. package/dist/sessionRulesNamespaceFormsCapability.d.ts +12 -0
  311. package/dist/sessionRulesNamespaceFormsCapability.js +29 -0
  312. package/dist/sessionSyncFileHistoryCapability.js +2 -2
  313. package/dist/settingsCredentialKeyPaths.d.ts +8 -0
  314. package/dist/settingsCredentialKeyPaths.js +274 -0
  315. package/dist/settingsHooksSalvage.d.ts +1 -0
  316. package/dist/settingsHooksSalvage.js +7 -1
  317. package/dist/settingsLayerAdmission.d.ts +4 -0
  318. package/dist/settingsLayerAdmission.js +16 -0
  319. package/dist/skillToolListsCapability.js +6 -5
  320. package/dist/skillsWireCaps.d.ts +14 -3
  321. package/dist/skillsWireCaps.js +48 -18
  322. package/dist/slashCommandGate.d.ts +24 -0
  323. package/dist/slashCommandGate.js +74 -0
  324. package/dist/slashCommandTable.d.ts +14 -0
  325. package/dist/slashCommandTable.js +99 -0
  326. package/dist/sqlEngineCapability.js +2 -2
  327. package/dist/steerPriorityCapability.js +2 -2
  328. package/dist/storePostureCapability.js +2 -2
  329. package/dist/subagent/agentStateDetail.js +1 -1
  330. package/dist/subagent/engineDelegatedPrompt.d.ts +9 -0
  331. package/dist/subagent/engineDelegatedPrompt.js +38 -7
  332. package/dist/subagent/engineRowStopGate.js +2 -2
  333. package/dist/subagent/engineSubagentResume.js +3 -3
  334. package/dist/subagent/engineTaskHandleWire.d.ts +1 -0
  335. package/dist/subagent/engineTaskHandleWire.js +10 -0
  336. package/dist/subagentContentStore.d.ts +1 -0
  337. package/dist/subagentContentStore.js +135 -27
  338. package/dist/submitFailure.d.ts +8 -0
  339. package/dist/submitFailure.js +17 -0
  340. package/dist/supportFloor.d.ts +1 -0
  341. package/dist/supportFloor.js +7 -0
  342. package/dist/terminationIntent.d.ts +55 -0
  343. package/dist/terminationIntent.js +352 -0
  344. package/dist/toolHistoryMismatch.d.ts +8 -0
  345. package/dist/toolHistoryMismatch.js +37 -6
  346. package/dist/toolResult.d.ts +13 -3
  347. package/dist/toolResult.js +158 -9
  348. package/dist/toolResultContent.d.ts +13 -0
  349. package/dist/toolResultContent.js +82 -7
  350. package/dist/toolRoster.d.ts +18 -0
  351. package/dist/toolRoster.js +64 -0
  352. package/dist/toolsFlagNames.d.ts +8 -0
  353. package/dist/toolsFlagNames.js +110 -0
  354. package/dist/turnFailurePresentation.js +41 -96
  355. package/dist/usageLimitAutoResume.d.ts +74 -0
  356. package/dist/usageLimitAutoResume.js +227 -0
  357. package/dist/userAttachmentEnvelope.js +1 -1
  358. package/dist/userAttachmentSeat.js +5 -5
  359. package/dist/userInvokedSkillsCapability.js +2 -2
  360. package/dist/webSearchBackendCapability.js +2 -2
  361. package/dist/wireErrorTriage.js +99 -50
  362. package/dist/wireFailureShape.d.ts +25 -1
  363. package/dist/wireFailureShape.js +92 -5
  364. package/dist/wireRefusalCopy.d.ts +75 -18
  365. package/dist/wireRefusalCopy.js +532 -148
  366. package/dist/wiringFleetDoctor.d.ts +3 -0
  367. package/dist/wiringFleetDoctor.js +21 -0
  368. package/dist/workflow.d.ts +2 -1
  369. package/dist/workflow.js +38 -1
  370. package/dist/workflowClient.d.ts +2 -7
  371. package/dist/workflowsJournalCapability.js +2 -2
  372. package/dist/writeProtectionCapability.js +2 -2
  373. package/docs/INTEGRATION-CLIENTS.md +1013 -190
  374. package/package.json +15 -4
@@ -1,10 +1,13 @@
1
- import { PROTOCOL_ERROR_NAME, THROWN_SLOT_UNREADABLE, protocolErrorNameOf, readErrorNumber, readErrorRecord, readErrorStrictStringList, readErrorString, readErrorStringList, readRefusalField, readThrownSlot, readThrownStatusSlot } from './wireFailureShape.js';
2
- import { readOwnDataValue, readOwnNonEmptyString } from './ownKey.js';
3
- import { ACTIVE_RUN_BUSY_ERROR_CODE, FLEET_LEASE_UNAVAILABLE, REQUEST_AUTONOMY_LANE_REFUSED, REQUEST_FIELD_CONFLICT, RESUME_OUTCOME_INVALID, RESUME_POLICY_FOLD_CODE, SCENARIO_ASSIGNMENT_UNKNOWN_ERROR_CODE, USAGE_WINDOW_EXHAUSTED, USER_ATTACHMENT_INVALID_ERROR_CODE, USER_INVOKED_SKILL_UNKNOWN_ERROR_CODE } from './engineErrorCodes.js';
1
+ import { PROTOCOL_ERROR_NAME, REFUSAL_PROBLEMS_READ_MAX, THROWN_SLOT_UNREADABLE, effectiveWireCodeReading, isSlotCarrier, protocolErrorNameOf, readErrorNumber, readErrorRecord, readErrorStrictStringList, readErrorString, readErrorStringList, readRefusalField, readThrownSlot, readThrownStatusSlot } from './wireFailureShape.js';
2
+ import { appendOwnElement, guardedRead, readOwnDataValue, readOwnNonEmptyString } from './ownKey.js';
3
+ import { ACTIVE_RUN_BUSY_ERROR_CODE, FLEET_LEASE_UNAVAILABLE, REQUEST_AUTONOMY_LANE_REFUSED, REQUEST_FIELD_CONFLICT, RESUME_OUTCOME_INVALID, USAGE_WINDOW_EXHAUSTED, USER_ATTACHMENT_INVALID_ERROR_CODE, USER_INVOKED_SKILL_UNKNOWN_ERROR_CODE } from './engineErrorCodes.js';
4
4
  import { capForDisplay } from './fleetTaskDesc.js';
5
5
  import { effectiveWireErrorCode } from './wireErrorTriage.js';
6
6
  import { CORE_TOOL_DECLARATION_CODES } from './generated/engineFactTables.js';
7
- import { scenarioRefusalFromError } from './scenarioRefusal.js';
7
+ import { prepareRefusalNoteOf } from './prepareRefusal.js';
8
+ import { PERMISSION_RULE_ISSUE_CODES, permissionRuleIssueDetail } from './permissionRuleIssue.js';
9
+ import { ruleRefusalListText } from './ruleRefusalSentence.js';
10
+ import { msg, renderMessage } from './i18n/translate.js';
8
11
  export const CONFLICT_APPROVAL_SETTLED = 'conflict.approval_settled';
9
12
  export const CONFLICT_RUN_NOT_RUNNING = 'conflict.run_not_running';
10
13
  function ownNonEmptyStringSlot(o, key) {
@@ -26,17 +29,14 @@ export function cancelConflictFromError(err) {
26
29
  return { kind: 'run_not_running', code };
27
30
  return { kind: 'unrecognized', ...(code !== undefined ? { code } : {}) };
28
31
  }
29
- export function cancelConflictContent(detail) {
32
+ export function cancelConflictContent(detail, lang) {
30
33
  switch (detail.kind) {
31
34
  case 'approval_settled':
32
- return ('The cancel did not apply: the approval this task was waiting on has already been decided or has expired elsewhere · ' +
33
- 'Check what that decision did to the task before doing anything else');
35
+ return renderMessage(msg('notice.wireRefusal.cancel.approvalSettled'), lang);
34
36
  case 'run_not_running':
35
- return ('The cancel could not be set: the task kept switching between running and waiting while the engine tried · ' +
36
- 'Nothing was changed — send the cancel again');
37
+ return renderMessage(msg('notice.wireRefusal.cancel.runNotRunning'), lang);
37
38
  case 'unrecognized':
38
- return ('The engine refused this cancel with a conflict it did not explain · ' +
39
- 'The task may have just been decided elsewhere, or may have changed state mid-cancel — check its current state, then cancel again if it is still active');
39
+ return renderMessage(msg('notice.wireRefusal.cancel.unrecognized'), lang);
40
40
  }
41
41
  }
42
42
  function nonNegativeFinite(v) {
@@ -80,11 +80,87 @@ function humanWait(sec) {
80
80
  const mm = m % 60;
81
81
  return mm === 0 ? `${h} h` : `${h} h ${mm} min`;
82
82
  }
83
- export function usageWindowExhaustedContent(detail) {
84
- const head = "The deployment's usage window is exhausted, so the engine did not accept this request · Nothing is wrong with the request itself";
83
+ export function usageWindowExhaustedContent(detail, lang) {
84
+ const head = renderMessage(msg('notice.wireRefusal.usageWindow.head'), lang);
85
85
  return detail.retryAfterSec !== undefined
86
- ? `${head} · Send it again in about ${humanWait(detail.retryAfterSec)}`
87
- : `${head} · The engine did not say how long the window needs — send it again a little later`;
86
+ ? `${head} · ${renderMessage(msg('notice.wireRefusal.sendAgainAbout', { wait: humanWait(detail.retryAfterSec) }), lang)}`
87
+ : `${head} · ${renderMessage(msg('notice.wireRefusal.usageWindow.unknownWait'), lang)}`;
88
+ }
89
+ export function quotaExhaustedFromError(err) {
90
+ if (readThrownSlot(err, 'status', 'data') !== 429 || readThrownSlot(err, 'errorCode', 'data') !== 'quota_exhausted')
91
+ return null;
92
+ const detail = readThrownSlot(err, 'detail', 'data');
93
+ const slot = (key) => (typeof detail === 'object' && detail !== null ? readThrownSlot(detail, key, 'data') : undefined);
94
+ const windowType = slot('windowType');
95
+ const remaining = slot('remaining');
96
+ const resetAt = slot('resetAt');
97
+ const isEstimate = slot('isEstimate');
98
+ const pool = slot('pool');
99
+ const retryAfterSec = slot('retryAfterSec');
100
+ return {
101
+ ...(windowType === 'fiveHour' || windowType === 'weekly' || windowType === 'budget' ? { windowType } : {}),
102
+ ...(typeof remaining === 'number' && Number.isFinite(remaining) ? { remaining } : {}),
103
+ ...(typeof resetAt === 'string' || resetAt === null ? { resetAt } : {}),
104
+ ...(typeof isEstimate === 'boolean' ? { isEstimate } : {}),
105
+ ...(typeof pool === 'string' && pool.length > 0 ? { pool } : {}),
106
+ ...(typeof retryAfterSec === 'number' && Number.isFinite(retryAfterSec) ? { retryAfterSec } : {}),
107
+ };
108
+ }
109
+ const QUOTA_MONTH_KEYS = [
110
+ 'notice.failure.month.jan',
111
+ 'notice.failure.month.feb',
112
+ 'notice.failure.month.mar',
113
+ 'notice.failure.month.apr',
114
+ 'notice.failure.month.may',
115
+ 'notice.failure.month.jun',
116
+ 'notice.failure.month.jul',
117
+ 'notice.failure.month.aug',
118
+ 'notice.failure.month.sep',
119
+ 'notice.failure.month.oct',
120
+ 'notice.failure.month.nov',
121
+ 'notice.failure.month.dec',
122
+ ];
123
+ export function quotaResetInstantText(resetAtIso, nowMs, lang) {
124
+ const t = Date.parse(resetAtIso);
125
+ if (!Number.isFinite(t))
126
+ return undefined;
127
+ const d = new Date(t);
128
+ const now = new Date(nowMs);
129
+ const hm = `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
130
+ const sameDay = d.getFullYear() === now.getFullYear() && d.getMonth() === now.getMonth() && d.getDate() === now.getDate();
131
+ if (sameDay)
132
+ return hm;
133
+ const monthKey = QUOTA_MONTH_KEYS[d.getMonth()];
134
+ return renderMessage(msg('notice.failure.quota.instantOtherDay', { month: monthKey === undefined ? '' : msg(monthKey), day: d.getDate(), time: hm }), lang);
135
+ }
136
+ export function quotaExhaustedContent(detail, nowMs, lang) {
137
+ const part = (key, params) => renderMessage(msg(key, params), lang);
138
+ const parts = [];
139
+ if (detail.windowType === 'fiveHour')
140
+ parts.push(part('notice.failure.quota.fiveHour'));
141
+ else if (detail.windowType === 'weekly')
142
+ parts.push(part('notice.failure.quota.weekly'));
143
+ else if (detail.windowType === 'budget') {
144
+ if (detail.pool === 'personal')
145
+ parts.push(part('notice.failure.quota.budgetPersonal'));
146
+ else if (detail.pool)
147
+ parts.push(part('notice.failure.quota.budgetPool', { pool: detail.pool }));
148
+ else
149
+ parts.push(part('notice.failure.quota.budget'));
150
+ }
151
+ else
152
+ parts.push(part('notice.failure.quota.usage'));
153
+ if (typeof detail.remaining === 'number' && Number.isFinite(detail.remaining)) {
154
+ parts.push(detail.windowType === 'budget'
155
+ ? part('notice.failure.quota.remainingBudget', { amount: `$${(detail.remaining / 1_000_000).toFixed(2)}` })
156
+ : part('notice.failure.quota.remainingTokens', { count: detail.remaining.toLocaleString('en-US') }));
157
+ }
158
+ const resetText = typeof detail.resetAt === 'string' ? quotaResetInstantText(detail.resetAt, nowMs, lang) : undefined;
159
+ if (resetText)
160
+ parts.push(detail.isEstimate === false ? part('notice.failure.quota.resetAt', { time: resetText }) : part('notice.failure.quota.resetAround', { time: resetText }));
161
+ parts.push(part('notice.failure.quota.refresh'));
162
+ parts.push(part('notice.failure.quota.noBypass'));
163
+ return parts.join(part('notice.failure.quota.join'));
88
164
  }
89
165
  const positiveFinite = (v) => typeof v === 'number' && Number.isFinite(v) && v > 0;
90
166
  export function fleetLeaseUnavailableFromError(err) {
@@ -112,7 +188,7 @@ export function fleetLeaseUnavailableFromError(err) {
112
188
  ...(sec !== undefined ? { retryAfterSec: sec } : {}),
113
189
  };
114
190
  }
115
- export function fleetLeaseUnavailableContent(detail) {
191
+ export function fleetLeaseUnavailableContent(detail, lang) {
116
192
  let reason;
117
193
  let sec;
118
194
  try {
@@ -127,34 +203,24 @@ export function fleetLeaseUnavailableContent(detail) {
127
203
  catch {
128
204
  sec = undefined;
129
205
  }
130
- const head = "This deployment could not confirm your usage budget with its quota service, and it refuses billed work while it cannot check, so the engine did not accept this request · Nothing is wrong with the request itself";
206
+ const head = renderMessage(msg('notice.wireRefusal.fleetLease.head'), lang);
131
207
  const cause = reason === 'auth-rejected'
132
- ? " · The quota service rejected this engine's credentials — if this keeps happening, whoever operates the engine needs to fix them"
208
+ ? ` · ${renderMessage(msg('notice.wireRefusal.fleetLease.authRejected'), lang)}`
133
209
  : reason === 'unreachable'
134
- ? ' · The engine could not reach the quota service'
210
+ ? ` · ${renderMessage(msg('notice.wireRefusal.fleetLease.unreachable'), lang)}`
135
211
  : '';
136
212
  const wait = positiveFinite(sec)
137
- ? ` · Send it again in about ${humanWait(Math.ceil(sec))}`
138
- : ' · The engine did not say how long to wait — send it again a little later';
213
+ ? ` · ${renderMessage(msg('notice.wireRefusal.sendAgainAbout', { wait: humanWait(Math.ceil(sec)) }), lang)}`
214
+ : ` · ${renderMessage(msg('notice.wireRefusal.fleetLease.unknownWait'), lang)}`;
139
215
  return `${head}${cause}${wait}`;
140
216
  }
141
- export function scenarioAssignmentUnknownFromError(err) {
142
- const r = scenarioRefusalFromError(err);
143
- if (r === null)
144
- return null;
145
- return {
146
- code: SCENARIO_ASSIGNMENT_UNKNOWN_ERROR_CODE,
147
- ...(r.scenario !== undefined ? { scenario: r.scenario } : {}),
148
- ...(r.source !== undefined ? { source: r.source } : {}),
149
- };
150
- }
151
217
  const SETTLED_BY_NOT_IN_PROOF = 'settled_by_not_in_proof';
152
218
  const DECIDED_BY_NOT_IN_PROOF = 'decided_by_not_in_proof';
153
219
  const RETIRED_DECISION_KEY = 'settledBy';
154
220
  const APPROVAL_NON_BINDING_FIELDS = new Set(['hostDecision', 'approver']);
155
221
  export function denyAttributionRefusalFromError(err, sentAttributionKey) {
156
222
  try {
157
- if (err === null || typeof err !== 'object')
223
+ if (!isSlotCarrier(err))
158
224
  return null;
159
225
  const o = err;
160
226
  const rawStatus = readThrownStatusSlot(o);
@@ -184,26 +250,19 @@ export function denyAttributionRefusalFromError(err, sentAttributionKey) {
184
250
  return null;
185
251
  }
186
252
  }
187
- export function denyAttributionRefusalContent(detail) {
253
+ export function denyAttributionRefusalContent(detail, lang) {
188
254
  switch (detail.kind) {
189
255
  case 'not_in_proof':
190
- return ('The engine refused this refusal before judging it: this deployment signs the decisions it accepts, and the note saying ' +
191
- 'who settled this one is not part of what gets signed · Nothing was decided and the approval is still waiting — ' +
192
- 'send the same decision again without that note');
256
+ return renderMessage(msg('notice.wireRefusal.denyAttribution.notInProof'), lang);
193
257
  case 'decision_conflict':
194
- return ('The engine refused this decision before judging it: the body says a policy settled it and also asks to allow the call, ' +
195
- 'and only a person can allow one · Nothing was decided and the approval is still waiting — ' +
196
- 'send it again with the decision and the note in agreement');
258
+ return renderMessage(msg('notice.wireRefusal.denyAttribution.decisionConflict'), lang);
197
259
  case 'retired_key':
198
- return ('The engine refused this decision before judging it: the note saying who settled it was sent under a name this engine no longer accepts · ' +
199
- 'Nothing was decided and the approval is still waiting — send the decision again with who made it given under the name the engine now takes in its place');
260
+ return renderMessage(msg('notice.wireRefusal.denyAttribution.retiredKey'), lang);
200
261
  case 'attribution_rejected': {
201
262
  const named = typeof detail.field === 'string' && APPROVAL_NON_BINDING_FIELDS.has(detail.field)
202
- ? ` It named ${detail.field} as the part it would not take.`
263
+ ? renderMessage(msg('notice.wireRefusal.denyAttribution.named', { field: detail.field }), lang)
203
264
  : '';
204
- return ('The engine would not accept the settlement details this decision carried, so it refused the decision before judging it.' +
205
- `${named} · Nothing was decided and the approval is still waiting at the same coordinates — ` +
206
- 'check what that part carried (the only piece this client sets is the note saying who settled the refusal) and decide once more');
265
+ return renderMessage(msg('notice.wireRefusal.denyAttribution.attributionRejected', { named }), lang);
207
266
  }
208
267
  }
209
268
  }
@@ -234,36 +293,36 @@ export function sessionDeleteConflictFromError(err) {
234
293
  }
235
294
  const DELETE_CONFLICT_IDS_SHOWN = 3;
236
295
  const DELETE_CONFLICT_ID_MAX = 64;
237
- function sessionDeleteConflictUnrecognizedContent() {
238
- return ('The engine refused to delete this session with a conflict it did not explain · ' +
239
- 'Check whether the session is still listed and whether anything of it is still running, then try the delete again');
296
+ function sessionDeleteConflictUnrecognizedContent(lang) {
297
+ return renderMessage(msg('notice.wireRefusal.sessionDelete.unrecognized'), lang);
240
298
  }
241
- export function sessionDeleteConflictContent(detail) {
299
+ export function sessionDeleteConflictContent(detail, lang) {
242
300
  try {
243
301
  if (detail === null || typeof detail !== 'object')
244
- return sessionDeleteConflictUnrecognizedContent();
302
+ return sessionDeleteConflictUnrecognizedContent(lang);
245
303
  switch (detail.kind) {
246
304
  case 'children_alive': {
247
305
  const raw = detail.remaining;
248
306
  const ids = Array.isArray(raw) ? raw.filter((id) => typeof id === 'string' && id.length > 0) : [];
249
307
  const shown = ids.slice(0, DELETE_CONFLICT_IDS_SHOWN).map((id) => capForDisplay(id, DELETE_CONFLICT_ID_MAX));
250
- const more = ids.length > shown.length ? ` and ${ids.length - shown.length} more` : '';
251
- const which = shown.length > 0 ? ` (${shown.join(', ')}${more})` : '';
252
- return (`This session was not deleted: background agents it started are still running where this engine cannot stop them${which} · ` +
253
- 'Nothing was deleted — delete it again once they finish, or stop them where they run first');
308
+ const which = shown.length === 0
309
+ ? ''
310
+ : ids.length > shown.length
311
+ ? renderMessage(msg('notice.wireRefusal.sessionDelete.whichMore', { ids: shown.join(', '), count: ids.length - shown.length }), lang)
312
+ : renderMessage(msg('notice.wireRefusal.sessionDelete.which', { ids: shown.join(', ') }), lang);
313
+ return renderMessage(msg('notice.wireRefusal.sessionDelete.childrenAlive', { which }), lang);
254
314
  }
255
315
  case 'active_run': {
256
316
  const active = detail.activeTaskId;
257
- const run = typeof active === 'string' && active.length > 0 ? ` (run ${capForDisplay(active, DELETE_CONFLICT_ID_MAX)})` : '';
258
- return (`This session was not deleted: it still has a run in progress${run} · ` +
259
- 'Nothing was deleted — cancel that run or let it finish, then delete the session again');
317
+ const run = typeof active === 'string' && active.length > 0 ? renderMessage(msg('notice.wireRefusal.sessionDelete.runId', { id: capForDisplay(active, DELETE_CONFLICT_ID_MAX) }), lang) : '';
318
+ return renderMessage(msg('notice.wireRefusal.sessionDelete.activeRun', { run }), lang);
260
319
  }
261
320
  default:
262
- return sessionDeleteConflictUnrecognizedContent();
321
+ return sessionDeleteConflictUnrecognizedContent(lang);
263
322
  }
264
323
  }
265
324
  catch {
266
- return sessionDeleteConflictUnrecognizedContent();
325
+ return sessionDeleteConflictUnrecognizedContent(lang);
267
326
  }
268
327
  }
269
328
  const FIELD_INVALID = 'request.field_invalid';
@@ -274,86 +333,216 @@ const BUCKET_OF_FIELD = Object.freeze({
274
333
  });
275
334
  const nonNegInt = (v) => (typeof v === 'number' && Number.isSafeInteger(v) && v >= 0 ? v : undefined);
276
335
  const posInt = (v) => (typeof v === 'number' && Number.isSafeInteger(v) && v >= 1 ? v : undefined);
277
- export function settingsPermissionBucketRefusalFromError(err) {
336
+ export function fieldLimitRefusalFromError(err) {
278
337
  try {
279
338
  if (typeof err !== 'object' || err === null)
280
339
  return null;
281
- if (effectiveWireErrorCode(err) !== FIELD_INVALID)
340
+ const coded = effectiveWireCodeReading(err);
341
+ if (coded.code !== FIELD_INVALID)
282
342
  return null;
283
- let outer;
284
- try {
285
- outer = err.errorCode;
286
- }
287
- catch {
288
- return null;
289
- }
290
343
  const field = readErrorString(err, 'field');
291
- const bucket = field !== undefined && Object.hasOwn(BUCKET_OF_FIELD, field) ? BUCKET_OF_FIELD[field] : undefined;
292
- if (bucket === undefined)
344
+ if (field === undefined || field.length === 0)
293
345
  return null;
294
346
  const reason = readErrorString(err, 'reason');
295
- if (reason !== 'over_cap' && reason !== 'bad_entry')
347
+ const folded = coded.folded;
348
+ if (reason !== 'over_cap' && reason !== 'too_long' && reason !== 'bad_entry')
296
349
  return null;
297
- const folded = outer === RESUME_POLICY_FOLD_CODE;
298
- if (reason === 'over_cap') {
299
- const count = nonNegInt(readErrorNumber(err, 'count'));
300
- const cap = posInt(readErrorNumber(err, 'cap'));
301
- return Object.freeze({
350
+ if (reason === 'bad_entry') {
351
+ const index = nonNegInt(readErrorNumber(err, 'index'));
352
+ return Object.freeze({ field, reason, ...(index !== undefined ? { index } : {}), ...(folded ? { folded: true } : {}) });
353
+ }
354
+ const count = nonNegInt(readErrorNumber(err, 'count'));
355
+ const cap = posInt(readErrorNumber(err, 'cap'));
356
+ return Object.freeze({
357
+ field,
358
+ reason,
359
+ ...(count !== undefined ? { count } : {}),
360
+ ...(cap !== undefined ? { cap } : {}),
361
+ ...(folded ? { folded: true } : {}),
362
+ });
363
+ }
364
+ catch {
365
+ return null;
366
+ }
367
+ }
368
+ function hooksCoordinateOf(path) {
369
+ const lead = path !== undefined && path[0] === 'hooks';
370
+ let out = lead ? 'settings' : HOOK_MATCHER_REFUSAL_FIELD;
371
+ for (const seg of path ?? [])
372
+ out += typeof seg === 'number' ? `[${seg}]` : `.${seg}`;
373
+ return out;
374
+ }
375
+ export function fieldLimitRefusalOfSettingsHooks(refusal) {
376
+ try {
377
+ if (typeof refusal !== 'object' || refusal === null)
378
+ return null;
379
+ const reason = readOwnDataValue(refusal, 'reason');
380
+ if (reason !== 'over_cap' && reason !== 'too_long')
381
+ return null;
382
+ const rawPath = readOwnDataValue(refusal, 'path');
383
+ let path;
384
+ if (Array.isArray(rawPath)) {
385
+ const out = [];
386
+ for (let i = 0; i < rawPath.length; i++) {
387
+ const seg = Object.hasOwn(rawPath, i) ? rawPath[i] : undefined;
388
+ if (typeof seg === 'string' || (typeof seg === 'number' && Number.isSafeInteger(seg) && seg >= 0))
389
+ out.push(seg);
390
+ else {
391
+ out.length = 0;
392
+ break;
393
+ }
394
+ }
395
+ path = out.length > 0 ? out : undefined;
396
+ }
397
+ const count = nonNegInt(readOwnDataValue(refusal, 'count'));
398
+ const cap = posInt(readOwnDataValue(refusal, 'cap'));
399
+ return Object.freeze({
400
+ field: hooksCoordinateOf(path),
401
+ reason,
402
+ ...(count !== undefined ? { count } : {}),
403
+ ...(cap !== undefined ? { cap } : {}),
404
+ });
405
+ }
406
+ catch {
407
+ return null;
408
+ }
409
+ }
410
+ const FIELD_LIMIT_REFUSAL_UNKNOWN = 'The engine refused this request: a list in it has too many entries, or a text in it is too long · Nothing was trimmed or dropped — shorten it, then send the request again';
411
+ const FIELD_LIMIT_FIELD_MAX = 120;
412
+ export function fieldLimitRefusalContent(detail, lang) {
413
+ try {
414
+ if (typeof detail !== 'object' || detail === null)
415
+ return FIELD_LIMIT_REFUSAL_UNKNOWN;
416
+ const field = detail.field;
417
+ const reason = detail.reason;
418
+ if (typeof field !== 'string' || field.length === 0)
419
+ return FIELD_LIMIT_REFUSAL_UNKNOWN;
420
+ const folded = detail.folded === true;
421
+ const bucket = Object.hasOwn(BUCKET_OF_FIELD, field) ? BUCKET_OF_FIELD[field] : undefined;
422
+ if (bucket !== undefined && (reason === 'over_cap' || reason === 'bad_entry')) {
423
+ return settingsPermissionBucketRefusalContent({
302
424
  bucket,
303
425
  reason,
304
- ...(count !== undefined ? { count } : {}),
305
- ...(cap !== undefined ? { cap } : {}),
426
+ ...(reason === 'over_cap' && nonNegInt(detail.count) !== undefined ? { count: detail.count } : {}),
427
+ ...(reason === 'over_cap' && posInt(detail.cap) !== undefined ? { cap: detail.cap } : {}),
428
+ ...(reason === 'bad_entry' && nonNegInt(detail.index) !== undefined ? { index: detail.index } : {}),
306
429
  ...(folded ? { folded: true } : {}),
307
- });
430
+ }, lang);
431
+ }
432
+ if (reason !== 'over_cap' && reason !== 'too_long' && reason !== 'bad_entry')
433
+ return FIELD_LIMIT_REFUSAL_UNKNOWN;
434
+ const where = `the request field ${capForDisplay(field, FIELD_LIMIT_FIELD_MAX)}`;
435
+ const subject = folded ? 'The engine refused to continue this parked work: in the request stored for it,' : 'The engine refused this request:';
436
+ let what;
437
+ if (reason === 'bad_entry') {
438
+ const index = nonNegInt(detail.index);
439
+ what = index !== undefined ? `entry ${index + 1} of ${where} is not valid` : `${where} is not valid`;
308
440
  }
309
- const index = nonNegInt(readErrorNumber(err, 'index'));
310
- return Object.freeze({ bucket, reason, ...(index !== undefined ? { index } : {}), ...(folded ? { folded: true } : {}) });
441
+ else {
442
+ const count = nonNegInt(detail.count);
443
+ const cap = posInt(detail.cap);
444
+ const unit = reason === 'over_cap' ? 'entries' : 'characters';
445
+ what =
446
+ count !== undefined && cap !== undefined
447
+ ? count > cap
448
+ ? `${where} has ${count} ${unit}, ${count - cap} more than the ${cap} the engine accepts`
449
+ : `${where} has ${count} ${unit}, and the engine accepts at most ${cap}`
450
+ : reason === 'over_cap'
451
+ ? `${where} has more entries than the engine accepts`
452
+ : `${where} is longer than the engine accepts`;
453
+ }
454
+ const fix = reason === 'bad_entry' ? 'fix or remove that entry' : reason === 'over_cap' ? 'remove some entries or merge them' : 'shorten it';
455
+ const next = folded
456
+ ? `It cannot continue as stored, and the engine refuses rather than silently trimming — ${fix}, then submit the work again as a new request`
457
+ : `Nothing was trimmed or dropped, because the engine refuses rather than silently trimming — ${fix}, then send the request again`;
458
+ return `${subject} ${what} · ${next}`;
311
459
  }
312
460
  catch {
313
- return null;
461
+ return FIELD_LIMIT_REFUSAL_UNKNOWN;
314
462
  }
315
463
  }
316
- const BUCKET_REFUSAL_UNKNOWN = "The engine refused the permission rules in this request's settings as too many or malformed · Nothing was trimmed or dropped — fix the rule lists, then send the request again";
317
- export function settingsPermissionBucketRefusalContent(detail) {
464
+ const BUCKET_REFUSAL_UNKNOWN = 'notice.wireRefusal.bucket.unknown';
465
+ export function settingsPermissionBucketRefusalContent(detail, lang) {
318
466
  try {
319
467
  if (typeof detail !== 'object' || detail === null)
320
- return BUCKET_REFUSAL_UNKNOWN;
468
+ return renderMessage(msg(BUCKET_REFUSAL_UNKNOWN), lang);
321
469
  const bucket = detail.bucket;
322
470
  const reason = detail.reason;
323
471
  if (bucket !== 'allow' && bucket !== 'deny' && bucket !== 'ask')
324
- return BUCKET_REFUSAL_UNKNOWN;
472
+ return renderMessage(msg(BUCKET_REFUSAL_UNKNOWN), lang);
325
473
  if (reason !== 'over_cap' && reason !== 'bad_entry')
326
- return BUCKET_REFUSAL_UNKNOWN;
474
+ return renderMessage(msg(BUCKET_REFUSAL_UNKNOWN), lang);
327
475
  const folded = detail.folded === true;
328
- const subject = folded ? 'The engine refused to continue this parked work: in the request stored for it,' : 'The engine refused this request:';
329
- const list = `the ${bucket} rule list in the permission settings (permissions.${bucket})`;
476
+ const subject = renderMessage(folded ? msg('notice.wireRefusal.bucket.subject.stored') : msg('notice.wireRefusal.bucket.subject.fresh'), lang);
477
+ const list = msg('notice.wireRefusal.bucket.list', { bucket });
330
478
  let what;
331
479
  let fix;
332
480
  if (reason === 'over_cap') {
333
481
  const count = nonNegInt(detail.count);
334
482
  const cap = posInt(detail.cap);
335
- what =
336
- count !== undefined && cap !== undefined
337
- ? count > cap
338
- ? `${list} has ${count} entries, ${count - cap} more than the ${cap} the engine accepts`
339
- : `${list} has ${count} entries, and the engine accepts at most ${cap}`
340
- : `${list} has more entries than the engine accepts`;
341
- fix = 'merge rules into broader patterns or remove some';
483
+ what = renderMessage(count !== undefined && cap !== undefined
484
+ ? count > cap
485
+ ? msg('notice.wireRefusal.bucket.what.overCap.more', { list, count, excess: count - cap, cap })
486
+ : msg('notice.wireRefusal.bucket.what.overCap.atMost', { list, count, cap })
487
+ : msg('notice.wireRefusal.bucket.what.overCap.unknown', { list }), lang);
488
+ fix = renderMessage(msg('notice.wireRefusal.bucket.fix.merge'), lang);
342
489
  }
343
490
  else {
344
491
  const index = nonNegInt(detail.index);
345
- what = index !== undefined ? `entry ${index + 1} of ${list} is empty or not text` : `${list} is not a list of rules`;
346
- fix = index !== undefined ? 'fix or remove that entry, so every entry is a non-empty rule' : 'make it a list of non-empty rules';
492
+ what = renderMessage(index !== undefined ? msg('notice.wireRefusal.bucket.what.badEntry.at', { position: index + 1, list }) : msg('notice.wireRefusal.bucket.what.badEntry.notList', { list }), lang);
493
+ fix = renderMessage(msg(index !== undefined ? 'notice.wireRefusal.bucket.fix.entry' : 'notice.wireRefusal.bucket.fix.list'), lang);
347
494
  }
348
- const next = folded
349
- ? `It cannot continue as stored, and the engine refuses the list rather than silently losing rules — ${fix}, then submit the work again as a new request`
350
- : `Nothing was trimmed or dropped, because the engine refuses the list rather than silently losing rules — ${fix}, then send the request again`;
495
+ const next = renderMessage(msg(folded ? 'notice.wireRefusal.bucket.next.stored' : 'notice.wireRefusal.bucket.next.fresh', { fix }), lang);
351
496
  return `${subject} ${what} · ${next}`;
352
497
  }
353
498
  catch {
354
- return BUCKET_REFUSAL_UNKNOWN;
499
+ return renderMessage(msg(BUCKET_REFUSAL_UNKNOWN), lang);
500
+ }
501
+ }
502
+ const PAYLOAD_TOO_LARGE = 'request.payload_too_large';
503
+ const BLOB_TOO_LARGE_FOR_SQL = 'blob_too_large_for_sql';
504
+ export function admissionWallRefusalFromError(err) {
505
+ try {
506
+ if (typeof err !== 'object' || err === null)
507
+ return null;
508
+ const code = readThrownSlot(err, 'errorCode', 'data');
509
+ if (code !== PAYLOAD_TOO_LARGE && code !== BLOB_TOO_LARGE_FOR_SQL)
510
+ return null;
511
+ const wallSource = readErrorString(err, 'wallSource');
512
+ if (wallSource === 'reported' || wallSource === 'assumed')
513
+ return Object.freeze({ code, wallSource });
514
+ if (wallSource === 'operator' && code === BLOB_TOO_LARGE_FOR_SQL)
515
+ return Object.freeze({ code, wallSource });
516
+ return null;
517
+ }
518
+ catch {
519
+ return null;
355
520
  }
356
521
  }
522
+ export function admissionWallRefusalContent(detail) {
523
+ let code;
524
+ let source;
525
+ try {
526
+ code = detail.code;
527
+ source = detail.wallSource;
528
+ }
529
+ catch {
530
+ code = source = undefined;
531
+ }
532
+ const subject = code === BLOB_TOO_LARGE_FOR_SQL ? 'This snapshot file' : 'This request';
533
+ if (source === 'assumed') {
534
+ return (`${subject} was refused at the most conservative size limit, because this deployment has not read its database’s actual limit yet · ` +
535
+ 'Nothing was stored · Try again shortly; if it keeps happening, ask whoever operates the engine to let the service read the database’s size limit');
536
+ }
537
+ if (source === 'operator' && code === BLOB_TOO_LARGE_FOR_SQL) {
538
+ return ('This snapshot file is larger than the cap whoever operates the engine set for snapshots stored in the database · Nothing was stored · ' +
539
+ 'Ask them to configure object storage for large snapshots, or to raise that cap');
540
+ }
541
+ return code === BLOB_TOO_LARGE_FOR_SQL
542
+ ? 'This snapshot file is larger than this deployment’s database can store in one piece · Nothing was stored · Ask whoever operates the engine to configure object storage for large snapshots, or to raise the database’s limit'
543
+ : 'This request is larger than this deployment’s database accepts for one submitted task · Nothing was stored · ' +
544
+ 'Shrink the inline images or attachments, or ask whoever operates the engine to raise the database’s limit (the engine’s own message names which one), then send it again';
545
+ }
357
546
  export function toolDeclarationRefusalFromError(err) {
358
547
  try {
359
548
  if (typeof err !== 'object' || err === null)
@@ -367,10 +556,9 @@ export function toolDeclarationRefusalFromError(err) {
367
556
  return null;
368
557
  }
369
558
  }
370
- const TOOL_DECLARATION_REFUSAL = "The engine refused to start this run because of a tool this request declares; the engine's own message says which tool and what is wrong with it · " +
371
- 'This is a problem with the request itself, not a temporary outage — sending the same request again is refused the same way; fix or remove that tool declaration, then send it';
372
- export function toolDeclarationRefusalContent(_detail) {
373
- return TOOL_DECLARATION_REFUSAL;
559
+ const TOOL_DECLARATION_REFUSAL = 'notice.wireRefusal.toolDeclaration';
560
+ export function toolDeclarationRefusalContent(_detail, lang) {
561
+ return renderMessage(msg(TOOL_DECLARATION_REFUSAL), lang);
374
562
  }
375
563
  const BODY_SHAPE = 'request.body_shape';
376
564
  const SETTINGS_KEY_PREFIX = 'settings.';
@@ -523,33 +711,54 @@ export function hostPostureRefusalFromError(err, sentRequest) {
523
711
  return null;
524
712
  }
525
713
  }
526
- const HOST_POSTURE_NOT_LOCAL = 'This is not a problem with your local settings and not something this client can grant — whoever runs this engine decides it';
527
- const HOST_POSTURE_WHOLE_ENV = "The engine refused this request before anything ran: this deployment serves more than one user, so a request may not hand the shell this machine's whole environment · " +
528
- `${HOST_POSTURE_NOT_LOCAL}; send it again without the whole-environment setting (or with the default), and the shell gets the default environment, with credential-like variables removed`;
529
- const HOST_POSTURE_WRITE_FACE = 'The engine refused this request before anything ran: this deployment does not let a request lift the write boundary with bypassPermissions · ' +
530
- `${HOST_POSTURE_NOT_LOCAL}; send it again with another permission mode`;
531
- const HOST_POSTURE_BOTH = "The engine refused this request before anything ran: the request asked both for the shell to inherit this machine's whole environment and for bypassPermissions, and this deployment refused at least one of them; the refusal does not say which · " +
532
- `${HOST_POSTURE_NOT_LOCAL}; send it again without one or both (the whole-environment setting is honored only on a single-user deployment)`;
533
- const HOST_POSTURE_UNATTRIBUTED = "The engine refused this request before anything ran: this deployment does not accept a setting in it that only a single-user deployment may use; the engine's own message names it · " +
534
- `${HOST_POSTURE_NOT_LOCAL}; send it again without that setting`;
535
- export function hostPostureRefusalContent(detail) {
714
+ const HOST_POSTURE_NOT_LOCAL = 'notice.wireRefusal.hostPosture.notLocal';
715
+ const HOST_POSTURE_WHOLE_ENV = 'notice.wireRefusal.hostPosture.wholeEnv';
716
+ const HOST_POSTURE_WRITE_FACE = 'notice.wireRefusal.hostPosture.writeFace';
717
+ const HOST_POSTURE_BOTH = 'notice.wireRefusal.hostPosture.both';
718
+ const HOST_POSTURE_UNATTRIBUTED = 'notice.wireRefusal.hostPosture.unattributed';
719
+ export function hostPostureRefusalContent(detail, lang) {
720
+ const say = (key) => renderMessage(msg(key, { notLocal: msg(HOST_POSTURE_NOT_LOCAL) }), lang);
536
721
  try {
537
722
  const env = readProp(detail, 'askedWholeEnvironment') === true;
538
723
  const write = readProp(detail, 'askedOpenWriteFace') === true;
539
724
  if (env && write)
540
- return HOST_POSTURE_BOTH;
725
+ return say(HOST_POSTURE_BOTH);
541
726
  if (env)
542
- return HOST_POSTURE_WHOLE_ENV;
727
+ return say(HOST_POSTURE_WHOLE_ENV);
543
728
  if (write)
544
- return HOST_POSTURE_WRITE_FACE;
545
- return HOST_POSTURE_UNATTRIBUTED;
729
+ return say(HOST_POSTURE_WRITE_FACE);
730
+ return say(HOST_POSTURE_UNATTRIBUTED);
546
731
  }
547
732
  catch {
548
- return HOST_POSTURE_UNATTRIBUTED;
733
+ return say(HOST_POSTURE_UNATTRIBUTED);
549
734
  }
550
735
  }
551
736
  const HOOK_MATCHER_REFUSAL_FIELD = 'settings.hooks';
552
737
  export function hookMatcherRefusalFromError(err) {
738
+ return settingsHooksRefusalFromError(err)?.matcher;
739
+ }
740
+ function hooksRefusalPathOf(detail) {
741
+ try {
742
+ const raw = readOwnDataValue(detail, 'path');
743
+ if (!Array.isArray(raw))
744
+ return undefined;
745
+ const out = [];
746
+ for (let i = 0; i < raw.length; i++) {
747
+ if (!Object.hasOwn(raw, i))
748
+ return undefined;
749
+ const v = raw[i];
750
+ if (typeof v === 'string' || (typeof v === 'number' && Number.isSafeInteger(v) && v >= 0))
751
+ out.push(v);
752
+ else
753
+ return undefined;
754
+ }
755
+ return Object.freeze(out);
756
+ }
757
+ catch {
758
+ return undefined;
759
+ }
760
+ }
761
+ export function settingsHooksRefusalFromError(err) {
553
762
  try {
554
763
  if (typeof err !== 'object' || err === null)
555
764
  return undefined;
@@ -560,31 +769,43 @@ export function hookMatcherRefusalFromError(err) {
560
769
  const detail = readErrorRecord(err, 'detail');
561
770
  if (detail === undefined)
562
771
  return undefined;
563
- const event = readOwnNonEmptyString(detail, 'event');
564
- if (event === undefined)
565
- return undefined;
566
772
  const reasonRaw = readOwnDataValue(detail, 'reason');
773
+ const path = hooksRefusalPathOf(detail);
774
+ const withPath = (o) => Object.freeze({ ...o, ...(path !== undefined ? { path } : {}) });
775
+ const family = (reason, rest = {}) => Object.freeze({ reason, ...(path !== undefined ? { path } : {}), ...rest });
776
+ const event = readOwnNonEmptyString(detail, 'event');
567
777
  if (reasonRaw === undefined || reasonRaw === 'dead_alias') {
568
778
  const alias = readOwnNonEmptyString(detail, 'alias');
569
779
  const canonical = readOwnNonEmptyString(detail, 'canonical');
570
- if (alias === undefined || canonical === undefined)
780
+ const matcher = event !== undefined && alias !== undefined && canonical !== undefined ? withPath({ reason: 'alias_without_canonical', event, alias, canonical }) : undefined;
781
+ if (reasonRaw === undefined && matcher === undefined)
571
782
  return undefined;
572
- return Object.freeze({ reason: 'alias_without_canonical', event, alias, canonical });
783
+ return family('dead_alias', matcher !== undefined ? { matcher } : {});
573
784
  }
574
- if (reasonRaw !== 'invalid_regex' && reasonRaw !== 'over_budget')
575
- return undefined;
576
- const groupIndex = readOwnDataValue(detail, 'groupIndex');
577
- if (typeof groupIndex !== 'number' || !Number.isInteger(groupIndex) || groupIndex < 0)
785
+ if (typeof reasonRaw !== 'string' || reasonRaw.length === 0)
578
786
  return undefined;
579
- if (reasonRaw === 'invalid_regex')
580
- return Object.freeze({ reason: 'invalid_regex', event, groupIndex });
581
- const budget = readOwnDataValue(detail, 'budgetMs');
582
- return Object.freeze({
583
- reason: 'over_budget',
584
- event,
585
- groupIndex,
586
- ...(typeof budget === 'number' && Number.isFinite(budget) && budget > 0 ? { budgetMs: budget } : {}),
587
- });
787
+ if (reasonRaw === 'invalid_regex' || reasonRaw === 'over_budget' || reasonRaw === 'budget_exceeded') {
788
+ const groupIndex = readOwnDataValue(detail, 'groupIndex');
789
+ const okIndex = typeof groupIndex === 'number' && Number.isInteger(groupIndex) && groupIndex >= 0;
790
+ let matcher;
791
+ if (event !== undefined && okIndex) {
792
+ if (reasonRaw === 'invalid_regex')
793
+ matcher = withPath({ reason: 'invalid_regex', event, groupIndex });
794
+ else {
795
+ const key = reasonRaw === 'over_budget' ? 'budgetMs' : 'totalMs';
796
+ const ms = readOwnDataValue(detail, key);
797
+ const msBit = typeof ms === 'number' && Number.isFinite(ms) && ms > 0 ? { [key]: ms } : {};
798
+ matcher = reasonRaw === 'over_budget' ? withPath({ reason: 'over_budget', event, groupIndex, ...msBit }) : withPath({ reason: 'budget_exceeded', event, groupIndex, ...msBit });
799
+ }
800
+ }
801
+ return family(reasonRaw, matcher !== undefined ? { matcher } : {});
802
+ }
803
+ if (reasonRaw === 'over_cap' || reasonRaw === 'too_long') {
804
+ const count = nonNegInt(readOwnDataValue(detail, 'count'));
805
+ const cap = posInt(readOwnDataValue(detail, 'cap'));
806
+ return family(reasonRaw, { ...(count !== undefined ? { count } : {}), ...(cap !== undefined ? { cap } : {}) });
807
+ }
808
+ return family(reasonRaw);
588
809
  }
589
810
  catch {
590
811
  return undefined;
@@ -593,21 +814,184 @@ export function hookMatcherRefusalFromError(err) {
593
814
  export function autonomyLaneRefusalFromError(err) {
594
815
  return effectiveWireErrorCode(err) === REQUEST_AUTONOMY_LANE_REFUSED ? { code: REQUEST_AUTONOMY_LANE_REFUSED } : null;
595
816
  }
596
- export function autonomyLaneRefusalContent() {
597
- return ('The engine did not start this leader run: this deployment runs in plan-only autonomy, and a leader run has no way to have its plan reviewed, ' +
598
- 'so nothing was started · Submit the work as a regular run instead, or ask whoever operates the engine to change its autonomy setting');
817
+ export function autonomyLaneRefusalContent(lang) {
818
+ return renderMessage(msg('notice.wireRefusal.autonomyLane'), lang);
819
+ }
820
+ const REQUEST_UNPROCESSABLE = 'request.unprocessable';
821
+ const UNSUPPORTED_RULE_PROBLEMS_MAX = REFUSAL_PROBLEMS_READ_MAX;
822
+ const nonEmptyString = (v) => (typeof v === 'string' && v !== '' ? v : undefined);
823
+ function unsupportedRuleProblemAt(list, i) {
824
+ try {
825
+ const item = readOwnDataValue(list, String(i));
826
+ if (typeof item !== 'object' || item === null)
827
+ return undefined;
828
+ const reason = readOwnDataValue(item, 'reason');
829
+ if (typeof reason !== 'string' || !reason.startsWith('unsupported.') || !PERMISSION_RULE_ISSUE_CODES.includes(reason))
830
+ return undefined;
831
+ const field = guardedRead(() => nonEmptyString(readOwnDataValue(item, 'field')));
832
+ const entry = guardedRead(() => nonEmptyString(readOwnDataValue(item, 'entry')));
833
+ return Object.freeze({ code: reason, ...(field !== undefined ? { field } : {}), ...(entry !== undefined ? { entry } : {}) });
834
+ }
835
+ catch {
836
+ return undefined;
837
+ }
838
+ }
839
+ export function unsupportedRuleRefusalFromError(err) {
840
+ try {
841
+ if (typeof err !== 'object' || err === null)
842
+ return null;
843
+ const effective = effectiveWireCodeReading(err);
844
+ if (effective.code !== REQUEST_UNPROCESSABLE)
845
+ return null;
846
+ const detail = readErrorRecord(err, 'detail');
847
+ if (detail === undefined)
848
+ return null;
849
+ let list;
850
+ let length = 0;
851
+ try {
852
+ const raw = readOwnDataValue(detail, 'problems');
853
+ if (Array.isArray(raw)) {
854
+ list = raw;
855
+ const n = raw.length;
856
+ length = typeof n === 'number' && Number.isSafeInteger(n) && n > 0 ? Math.min(n, UNSUPPORTED_RULE_PROBLEMS_MAX) : 0;
857
+ }
858
+ }
859
+ catch {
860
+ list = undefined;
861
+ }
862
+ if (list === undefined)
863
+ return null;
864
+ const problems = [];
865
+ for (let i = 0; i < length; i += 1) {
866
+ const p = unsupportedRuleProblemAt(list, i);
867
+ if (p !== undefined)
868
+ problems.push(p);
869
+ }
870
+ const first = problems[0];
871
+ if (first === undefined)
872
+ return null;
873
+ const folded = effective.folded;
874
+ return Object.freeze({ code: first.code, problems: Object.freeze(problems), ...(folded ? { folded: true } : {}) });
875
+ }
876
+ catch {
877
+ return null;
878
+ }
879
+ }
880
+ function unsupportedRuleSentenceItems(detail, lang) {
881
+ const items = [];
882
+ const seen = new Set();
883
+ try {
884
+ const list = readOwnDataValue(detail, 'problems');
885
+ if (Array.isArray(list)) {
886
+ const len = readOwnDataValue(list, 'length');
887
+ const n = typeof len === 'number' && Number.isSafeInteger(len) && len > 0 ? Math.min(len, UNSUPPORTED_RULE_PROBLEMS_MAX) : 0;
888
+ for (let i = 0; i < n; i += 1) {
889
+ try {
890
+ const p = readOwnDataValue(list, String(i));
891
+ if (typeof p !== 'object' || p === null)
892
+ continue;
893
+ const code = readOwnDataValue(p, 'code');
894
+ if (typeof code !== 'string' || !code.startsWith('unsupported.'))
895
+ continue;
896
+ const entry = nonEmptyString(readOwnDataValue(p, 'entry'));
897
+ const key = `${entry ?? ''}\u0000${code}`;
898
+ if (seen.has(key))
899
+ continue;
900
+ seen.add(key);
901
+ appendOwnElement(items, { ...(entry !== undefined ? { rule: entry } : {}), reason: permissionRuleIssueDetail(code, undefined, undefined, lang) });
902
+ }
903
+ catch {
904
+ continue;
905
+ }
906
+ }
907
+ }
908
+ }
909
+ catch {
910
+ items.length = 0;
911
+ }
912
+ if (items.length > 0)
913
+ return items;
914
+ let code;
915
+ try {
916
+ code = readOwnDataValue(detail, 'code');
917
+ }
918
+ catch {
919
+ code = undefined;
920
+ }
921
+ return [{ reason: permissionRuleIssueDetail(code, undefined, undefined, lang) }];
922
+ }
923
+ export function unsupportedRuleRefusalContent(detail, lang) {
924
+ const subject = typeof detail === 'object' && detail !== null ? detail : { code: '' };
925
+ const items = unsupportedRuleSentenceItems(subject, lang);
926
+ let folded = false;
927
+ try {
928
+ folded = readOwnDataValue(subject, 'folded') === true;
929
+ }
930
+ catch {
931
+ folded = false;
932
+ }
933
+ const many = items.length > 1;
934
+ const list = ruleRefusalListText(items, lang);
935
+ const key = folded ? (many ? 'notice.wireRefusal.unsupportedRule.stored.other' : 'notice.wireRefusal.unsupportedRule.stored') : many ? 'notice.wireRefusal.unsupportedRule.other' : 'notice.wireRefusal.unsupportedRule';
936
+ return renderMessage(msg(key, many ? { detail: list, count: items.length } : { detail: list }), lang);
599
937
  }
600
938
  export function userAttachmentRefusalFromError(err) {
601
- return effectiveWireErrorCode(err) === USER_ATTACHMENT_INVALID_ERROR_CODE ? { code: USER_ATTACHMENT_INVALID_ERROR_CODE, retryable: false } : null;
939
+ try {
940
+ if (typeof err !== 'object' || err === null)
941
+ return null;
942
+ let facts;
943
+ const kind = readOwnDataValue(err, 'kind');
944
+ const plane = readOwnDataValue(err, 'plane');
945
+ if (kind === 'failed' && (plane === 'cause' || plane === 'flat')) {
946
+ if (readOwnDataValue(err, 'code') !== USER_ATTACHMENT_INVALID_ERROR_CODE)
947
+ return null;
948
+ const cause = readOwnDataValue(err, 'detail');
949
+ const inner = typeof cause === 'object' && cause !== null && readOwnDataValue(cause, 'kind') === 'coded' ? readOwnDataValue(cause, 'detail') : undefined;
950
+ facts = typeof inner === 'object' && inner !== null && !Array.isArray(inner) ? inner : undefined;
951
+ }
952
+ else {
953
+ if (effectiveWireErrorCode(err) !== USER_ATTACHMENT_INVALID_ERROR_CODE)
954
+ return null;
955
+ facts = readErrorRecord(err, 'detail');
956
+ }
957
+ let index;
958
+ let path;
959
+ try {
960
+ index = facts === undefined ? undefined : readOwnDataValue(facts, 'index');
961
+ }
962
+ catch {
963
+ index = undefined;
964
+ }
965
+ try {
966
+ path = facts === undefined ? undefined : readOwnDataValue(facts, 'path');
967
+ }
968
+ catch {
969
+ path = undefined;
970
+ }
971
+ return {
972
+ code: USER_ATTACHMENT_INVALID_ERROR_CODE,
973
+ retryable: false,
974
+ ...(typeof index === 'number' && Number.isSafeInteger(index) && index >= 0 ? { index } : {}),
975
+ ...(typeof path === 'string' && path.length > 0 ? { path } : {}),
976
+ };
977
+ }
978
+ catch {
979
+ return null;
980
+ }
602
981
  }
603
- export function userAttachmentRefusalContent() {
604
- return ('This message was not sent: the engine refused the files attached to it — together with the message they are more than it can take in one request on this model, ' +
605
- 'or one of them is in a form it does not accept · Nothing was started and your draft is kept · Remove some attachments or attach smaller parts, then send it again');
982
+ export function userAttachmentRefusalContent(detail) {
983
+ let index;
984
+ try {
985
+ index = detail === undefined || detail === null ? undefined : detail.index;
986
+ }
987
+ catch {
988
+ index = undefined;
989
+ }
990
+ return prepareRefusalNoteOf(USER_ATTACHMENT_INVALID_ERROR_CODE, typeof index === 'number' ? { index } : undefined);
606
991
  }
607
992
  export function userInvokedSkillRefusalFromError(err) {
608
993
  return effectiveWireErrorCode(err) === USER_INVOKED_SKILL_UNKNOWN_ERROR_CODE ? { code: USER_INVOKED_SKILL_UNKNOWN_ERROR_CODE, retryable: false } : null;
609
994
  }
610
995
  export function userInvokedSkillRefusalContent() {
611
- return ('The engine did not start this run: a skill named for it is not one this run has loaded, or skills are turned off for this run · ' +
612
- 'Nothing was started and your draft is kept · Check the skill name, or load that skill, then send it again');
996
+ return prepareRefusalNoteOf(USER_INVOKED_SKILL_UNKNOWN_ERROR_CODE);
613
997
  }