@sema-agent/client-core 0.97.1 → 0.99.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 (353) hide show
  1. package/CHANGELOG.md +607 -0
  2. package/README.md +96 -46
  3. package/dist/adapt/arms.d.ts +1 -0
  4. package/dist/adapt/arms.js +188 -53
  5. package/dist/adapt/ids.d.ts +12 -1
  6. package/dist/adapt/ids.js +59 -8
  7. package/dist/adapt/instanceLedger.d.ts +50 -0
  8. package/dist/adapt/instanceLedger.js +147 -0
  9. package/dist/adapt/panelTasks.d.ts +1 -1
  10. package/dist/adapt/panelTasks.js +2 -2
  11. package/dist/adapt/textStream.d.ts +1 -0
  12. package/dist/adapt/textStream.js +24 -7
  13. package/dist/adapt/toolCards.d.ts +27 -5
  14. package/dist/adapt/toolCards.js +39 -6
  15. package/dist/adapt/wireShapes.js +6 -2
  16. package/dist/adapt.d.ts +2 -0
  17. package/dist/adapt.js +8 -3
  18. package/dist/adapter/activeRunSelfHeal.d.ts +9 -3
  19. package/dist/adapter/activeRunSelfHeal.js +205 -313
  20. package/dist/adapter/downstream/eventToSdkMessage.d.ts +2 -5
  21. package/dist/adapter/downstream/eventToSdkMessage.js +77 -36
  22. package/dist/adapter/downstream/terminalToSdkResult.js +11 -4
  23. package/dist/adapter/downstream/turnUsageToModelUsage.d.ts +5 -2
  24. package/dist/adapter/downstream/turnUsageToModelUsage.js +2 -0
  25. package/dist/adapter/runStream.js +79 -48
  26. package/dist/adapter/types.d.ts +4 -4
  27. package/dist/adapter/types.js +2 -1
  28. package/dist/agentSession/backgroundView.js +2 -1
  29. package/dist/agentSession/engineAgentRegistryRead.d.ts +2 -2
  30. package/dist/agentSession/engineAgentRegistryRead.js +12 -13
  31. package/dist/agentSession/engineSessionBackgroundStop.js +16 -8
  32. package/dist/agentsWireCaps.d.ts +8 -11
  33. package/dist/agentsWireCaps.js +196 -194
  34. package/dist/approvalDecidedByCapability.d.ts +0 -4
  35. package/dist/approvalDecidedByCapability.js +0 -6
  36. package/dist/approvalsStreamLiveCapability.d.ts +0 -4
  37. package/dist/approvalsStreamLiveCapability.js +0 -6
  38. package/dist/assistantInbox.d.ts +34 -0
  39. package/dist/assistantInbox.js +118 -0
  40. package/dist/centerWiringCapability.js +9 -1
  41. package/dist/clientSlice.d.ts +0 -9
  42. package/dist/clientSlice.js +0 -3
  43. package/dist/cloudConfigWireCaps.d.ts +5 -3
  44. package/dist/cloudConfigWireCaps.js +106 -64
  45. package/dist/compensations.js +1 -1
  46. package/dist/connectorStatus.d.ts +21 -0
  47. package/dist/connectorStatus.js +112 -0
  48. package/dist/controlRouter.d.ts +18 -3
  49. package/dist/controlRouter.js +106 -67
  50. package/dist/coreValuePorts.d.ts +29 -4
  51. package/dist/coreValuePorts.js +10 -0
  52. package/dist/corruptSessionCopy.d.ts +2 -1
  53. package/dist/corruptSessionCopy.js +3 -3
  54. package/dist/decideReceipt.d.ts +2 -2
  55. package/dist/decideReceipt.js +5 -2
  56. package/dist/declared/supportFloorDeclared.js +3 -3
  57. package/dist/detachWire.js +3 -2
  58. package/dist/deviceExecutorManagementCapability.d.ts +0 -4
  59. package/dist/deviceExecutorManagementCapability.js +0 -6
  60. package/dist/deviceRebind.d.ts +49 -1
  61. package/dist/deviceRebind.js +221 -3
  62. package/dist/devicesFace.d.ts +34 -0
  63. package/dist/devicesFace.js +90 -0
  64. package/dist/displayUntrusted.d.ts +2 -0
  65. package/dist/displayUntrusted.js +253 -76
  66. package/dist/engineAgentAbsence.d.ts +1 -1
  67. package/dist/engineAgentPanelStore.d.ts +12 -4
  68. package/dist/engineAgentPanelStore.js +16 -11
  69. package/dist/engineCapReader.d.ts +2 -5
  70. package/dist/engineCapReader.js +8 -10
  71. package/dist/engineCapsCache.d.ts +12 -0
  72. package/dist/engineCapsCache.js +76 -18
  73. package/dist/engineCapsChange.d.ts +2 -0
  74. package/dist/engineCapsChange.js +9 -0
  75. package/dist/engineClosedSets.d.ts +1 -0
  76. package/dist/engineClosedSets.js +4 -1
  77. package/dist/engineErrorCodes.d.ts +11 -3
  78. package/dist/engineErrorCodes.js +11 -8
  79. package/dist/engineIdentity.d.ts +1 -0
  80. package/dist/engineIdentity.js +8 -0
  81. package/dist/engineRowRef.d.ts +28 -0
  82. package/dist/engineRowRef.js +114 -0
  83. package/dist/engineSessionMessages.d.ts +68 -0
  84. package/dist/engineSessionMessages.js +370 -0
  85. package/dist/engineTargetSeat.d.ts +27 -0
  86. package/dist/engineTargetSeat.js +199 -0
  87. package/dist/engineToolDirectory.d.ts +0 -9
  88. package/dist/engineToolDirectory.js +1 -94
  89. package/dist/engineUrl.d.ts +18 -0
  90. package/dist/engineUrl.js +52 -0
  91. package/dist/engineWireFor.js +3 -8
  92. package/dist/env/uiLanguage.d.ts +11 -1
  93. package/dist/env/uiLanguage.js +38 -2
  94. package/dist/eventLeg.d.ts +100 -0
  95. package/dist/eventLeg.js +305 -0
  96. package/dist/executionLaneCapability.d.ts +0 -4
  97. package/dist/executionLaneCapability.js +3 -16
  98. package/dist/fileHistoryCaptureCapability.d.ts +2 -5
  99. package/dist/fileHistoryCaptureCapability.js +13 -21
  100. package/dist/fileHistoryLegNotice.d.ts +2 -1
  101. package/dist/fileHistoryLegNotice.js +3 -3
  102. package/dist/fleet/fleetLedger.d.ts +0 -3
  103. package/dist/fleet/fleetLedger.js +21 -36
  104. package/dist/fleet/fleetProjection.d.ts +2 -2
  105. package/dist/fleet/fleetProjection.js +10 -8
  106. package/dist/frameBinding.d.ts +8 -0
  107. package/dist/frameBinding.js +35 -0
  108. package/dist/gateFailureCodes.d.ts +2 -0
  109. package/dist/gateFailureCodes.js +15 -0
  110. package/dist/gateOutcome.d.ts +3 -1
  111. package/dist/gateOutcome.js +41 -8
  112. package/dist/gateVocabulary.d.ts +10 -4
  113. package/dist/gateVocabulary.js +107 -47
  114. package/dist/generated/engineAskFaceTables.js +2 -2
  115. package/dist/generated/engineFactTables.d.ts +22 -3
  116. package/dist/generated/engineFactTables.js +51 -4
  117. package/dist/generated/engineNoticeTables.js +18 -3
  118. package/dist/generated/settingsSchemaFns.d.ts +6 -0
  119. package/dist/generated/settingsSchemaFns.js +57 -0
  120. package/dist/generated/settingsSchemaHooksClassifier.d.ts +2 -0
  121. package/dist/generated/settingsSchemaHooksClassifier.js +254 -0
  122. package/dist/generated/settingsSchemaTables.d.ts +1 -0
  123. package/dist/generated/settingsSchemaTables.js +4 -0
  124. package/dist/generated/settingsSchemaTypes.d.ts +105 -0
  125. package/dist/generated/settingsSchemaTypes.js +1 -0
  126. package/dist/generated/toolNameTables.d.ts +1 -0
  127. package/dist/generated/toolNameTables.js +1 -0
  128. package/dist/hitl/allowRuleShadow.d.ts +8 -2
  129. package/dist/hitl/allowRuleShadow.js +36 -29
  130. package/dist/hitl/approvalCardReading.d.ts +15 -0
  131. package/dist/hitl/approvalCardReading.js +154 -0
  132. package/dist/hitl/approvalCardReasons.d.ts +14 -0
  133. package/dist/hitl/approvalCardReasons.js +119 -0
  134. package/dist/hitl/approvalHolds.d.ts +50 -15
  135. package/dist/hitl/approvalHolds.js +177 -27
  136. package/dist/hitl/approvalResolution.d.ts +51 -26
  137. package/dist/hitl/approvalResolution.js +86 -122
  138. package/dist/hitl/approvalsFeed.js +6 -18
  139. package/dist/hitl/askClassPair.d.ts +2 -0
  140. package/dist/hitl/askClassPair.js +17 -0
  141. package/dist/hitl/askGateWire.d.ts +20 -2
  142. package/dist/hitl/askGateWire.js +50 -1
  143. package/dist/hitl/askParkRowRouting.d.ts +5 -0
  144. package/dist/hitl/askParkRowRouting.js +32 -1
  145. package/dist/hitl/askSettlementLine.d.ts +28 -0
  146. package/dist/hitl/askSettlementLine.js +99 -0
  147. package/dist/hitl/automaticAnswerVerdict.d.ts +3 -2
  148. package/dist/hitl/automaticAnswerVerdict.js +29 -13
  149. package/dist/hitl/crashConverged.d.ts +11 -20
  150. package/dist/hitl/crashConverged.js +56 -0
  151. package/dist/hitl/crashConvergedNotice.d.ts +6 -3
  152. package/dist/hitl/crashConvergedNotice.js +48 -24
  153. package/dist/hitl/decisionConflict.js +3 -10
  154. package/dist/hitl/decisionRefusal.d.ts +40 -1
  155. package/dist/hitl/decisionRefusal.js +199 -42
  156. package/dist/hitl/frameRouter.d.ts +5 -2
  157. package/dist/hitl/frameRouter.js +27 -24
  158. package/dist/hitl/gateLedger.d.ts +2 -0
  159. package/dist/hitl/gateLedger.js +50 -13
  160. package/dist/hitl/hitlBridge.d.ts +2 -2
  161. package/dist/hitl/hitlBridge.js +13 -10
  162. package/dist/hitl/livePendingAsk.d.ts +3 -3
  163. package/dist/hitl/livePendingAsk.js +7 -18
  164. package/dist/hitl/parkResolver.d.ts +2 -24
  165. package/dist/hitl/parkResolver.js +61 -97
  166. package/dist/hitl/persistedRulesWire.d.ts +25 -0
  167. package/dist/hitl/persistedRulesWire.js +104 -2
  168. package/dist/hitl/planReviewWire.d.ts +31 -13
  169. package/dist/hitl/planReviewWire.js +120 -78
  170. package/dist/hitl/refusedToolNameProse.d.ts +0 -1
  171. package/dist/hitl/refusedToolNameProse.js +0 -3
  172. package/dist/hitl/replayedApproval.d.ts +4 -3
  173. package/dist/hitl/replayedApproval.js +7 -4
  174. package/dist/hitl/sessionPolicyDeliverable.d.ts +2 -0
  175. package/dist/hitl/sessionPolicyDeliverable.js +48 -7
  176. package/dist/hitl/sessionPolicyWire.d.ts +34 -21
  177. package/dist/hitl/sessionPolicyWire.js +179 -70
  178. package/dist/hitl/standingRows.d.ts +20 -2
  179. package/dist/hitl/standingRows.js +69 -8
  180. package/dist/hitl/suspendedReopen.d.ts +2 -1
  181. package/dist/hitl/suspendedReopen.js +7 -10
  182. package/dist/hitl/toolApprovalWire.d.ts +103 -156
  183. package/dist/hitl/toolApprovalWire.js +661 -411
  184. package/dist/hookMatcherVerdict.d.ts +6 -1
  185. package/dist/hookMatcherVerdict.js +14 -7
  186. package/dist/hooksWireCaps.d.ts +2 -2
  187. package/dist/hooksWireCaps.js +174 -81
  188. package/dist/host.d.ts +21 -0
  189. package/dist/hostTurnSettings.d.ts +71 -0
  190. package/dist/hostTurnSettings.js +291 -0
  191. package/dist/humanTurn.d.ts +14 -1
  192. package/dist/humanTurn.js +100 -12
  193. package/dist/humanTurnRead.d.ts +2 -0
  194. package/dist/humanTurnRead.js +22 -1
  195. package/dist/i18n/messages.en.d.ts +703 -0
  196. package/dist/i18n/messages.en.js +701 -0
  197. package/dist/i18n/messages.zh.d.ts +3 -0
  198. package/dist/i18n/messages.zh.js +837 -0
  199. package/dist/i18n/translate.d.ts +25 -0
  200. package/dist/i18n/translate.js +127 -0
  201. package/dist/index.d.ts +78 -29
  202. package/dist/index.js +54 -18
  203. package/dist/inheritEnvCapability.d.ts +32 -0
  204. package/dist/inheritEnvCapability.js +104 -0
  205. package/dist/inheritEnvWire.d.ts +3 -2
  206. package/dist/inheritEnvWire.js +12 -14
  207. package/dist/interactiveHalt.js +17 -6
  208. package/dist/liveModelCatalog.d.ts +3 -3
  209. package/dist/liveModelCatalog.js +15 -13
  210. package/dist/liveQuestionStore.d.ts +2 -21
  211. package/dist/mcpLiveness.d.ts +2 -1
  212. package/dist/mcpPanel.d.ts +10 -1
  213. package/dist/mcpPanel.js +40 -13
  214. package/dist/mcpProbeCapability.d.ts +2 -1
  215. package/dist/mcpProbeCapability.js +7 -11
  216. package/dist/mcpProbeWire.d.ts +9 -2
  217. package/dist/mcpProbeWire.js +6 -1
  218. package/dist/mcpWireCaps.d.ts +47 -2
  219. package/dist/mcpWireCaps.js +164 -16
  220. package/dist/memoryEntriesWire.d.ts +4 -9
  221. package/dist/memoryEntriesWire.js +5 -10
  222. package/dist/model/modelSupplyRules.d.ts +0 -2
  223. package/dist/model/modelSupplyRules.js +3 -12
  224. package/dist/model/modelsPolicy.d.ts +0 -5
  225. package/dist/model/modelsPolicy.js +6 -36
  226. package/dist/model/onboardJudgement.d.ts +93 -0
  227. package/dist/model/onboardJudgement.js +415 -0
  228. package/dist/model/subagentModelWord.d.ts +31 -0
  229. package/dist/model/subagentModelWord.js +261 -0
  230. package/dist/model/tierVocabulary.d.ts +2 -0
  231. package/dist/model/tierVocabulary.js +17 -5
  232. package/dist/modelCapabilityProbe.d.ts +64 -0
  233. package/dist/modelCapabilityProbe.js +600 -0
  234. package/dist/modelIdentityResolvability.d.ts +3 -0
  235. package/dist/modelIdentityResolvability.js +26 -17
  236. package/dist/notifications.d.ts +6 -0
  237. package/dist/notifications.js +71 -23
  238. package/dist/outputStyleSeatCapability.d.ts +0 -3
  239. package/dist/outputStyleSeatCapability.js +0 -3
  240. package/dist/ownKey.d.ts +22 -0
  241. package/dist/ownKey.js +94 -3
  242. package/dist/panelReduce.d.ts +21 -10
  243. package/dist/panelReduce.js +728 -550
  244. package/dist/panelStateHolder.d.ts +3 -7
  245. package/dist/panelStateHolder.js +14 -130
  246. package/dist/peerLaneCapability.d.ts +0 -4
  247. package/dist/peerLaneCapability.js +0 -6
  248. package/dist/permissionRuleIssue.js +2 -0
  249. package/dist/permissionRulesWriteCapability.d.ts +2 -5
  250. package/dist/permissionRulesWriteCapability.js +8 -12
  251. package/dist/permissionWireCaps.d.ts +2 -2
  252. package/dist/permissionWireCaps.js +2 -0
  253. package/dist/permissionsAllowGrantCapability.d.ts +0 -4
  254. package/dist/permissionsAllowGrantCapability.js +0 -6
  255. package/dist/permissionsDeclaration.d.ts +0 -11
  256. package/dist/permissionsDeclaration.js +60 -53
  257. package/dist/pluginHooksWire.d.ts +46 -3
  258. package/dist/pluginHooksWire.js +219 -16
  259. package/dist/preemptWire.d.ts +44 -0
  260. package/dist/preemptWire.js +83 -0
  261. package/dist/printModelStatus.d.ts +63 -0
  262. package/dist/printModelStatus.js +155 -0
  263. package/dist/printToolResultFrame.js +15 -4
  264. package/dist/replayBody.d.ts +3 -0
  265. package/dist/replayBody.js +14 -0
  266. package/dist/request/taskRequest.d.ts +11 -6
  267. package/dist/request/taskRequest.js +112 -19
  268. package/dist/resumeRefusalCopy.d.ts +13 -9
  269. package/dist/resumeRefusalCopy.js +81 -118
  270. package/dist/retryStatus.d.ts +45 -0
  271. package/dist/retryStatus.js +185 -1
  272. package/dist/rewindArchiveCapability.d.ts +0 -4
  273. package/dist/rewindArchiveCapability.js +2 -10
  274. package/dist/rewindArchiveReading.d.ts +0 -1
  275. package/dist/rewindArchiveReading.js +0 -3
  276. package/dist/runCancelContext.d.ts +2 -1
  277. package/dist/runCancelContext.js +4 -2
  278. package/dist/runReattachPolicy.d.ts +31 -0
  279. package/dist/runReattachPolicy.js +46 -0
  280. package/dist/runTerminal.d.ts +3 -6
  281. package/dist/runTerminal.js +8 -9
  282. package/dist/sandboxWire.d.ts +3 -1
  283. package/dist/sandboxWire.js +76 -27
  284. package/dist/scenarioRefusal.d.ts +9 -0
  285. package/dist/scenarioRefusal.js +111 -0
  286. package/dist/scenarioWire.js +1 -1
  287. package/dist/seam.d.ts +48 -2
  288. package/dist/seam.js +25 -4
  289. package/dist/seatContract.d.ts +311 -18
  290. package/dist/seatContract.js +824 -100
  291. package/dist/selfOrchestrationDenial.js +7 -19
  292. package/dist/sessionIdSegment.d.ts +6 -0
  293. package/dist/sessionIdSegment.js +24 -0
  294. package/dist/sessionMemoryStatus.js +6 -11
  295. package/dist/sessionPolicyCapability.d.ts +2 -5
  296. package/dist/sessionPolicyCapability.js +8 -12
  297. package/dist/sessionSyncFileHistoryCapability.d.ts +0 -3
  298. package/dist/sessionSyncFileHistoryCapability.js +0 -3
  299. package/dist/settingsHooksSalvage.d.ts +44 -0
  300. package/dist/settingsHooksSalvage.js +211 -0
  301. package/dist/skillToolListsCapability.d.ts +2 -4
  302. package/dist/skillToolListsCapability.js +8 -9
  303. package/dist/sqlEngineCapability.d.ts +0 -4
  304. package/dist/sqlEngineCapability.js +0 -6
  305. package/dist/sseIdleTriage.js +3 -2
  306. package/dist/steerPriorityCapability.d.ts +0 -3
  307. package/dist/steerPriorityCapability.js +0 -3
  308. package/dist/streamDrainingLegs.d.ts +4 -0
  309. package/dist/streamDrainingLegs.js +6 -1
  310. package/dist/subagent/engineCompactWire.d.ts +0 -1
  311. package/dist/subagent/engineCompactWire.js +7 -5
  312. package/dist/subagent/engineSubagentResume.js +15 -9
  313. package/dist/subagent/engineTaskHandleWire.js +4 -7
  314. package/dist/subagentContentStore.d.ts +3 -0
  315. package/dist/subagentContentStore.js +22 -10
  316. package/dist/submitReopen.d.ts +24 -0
  317. package/dist/submitReopen.js +75 -0
  318. package/dist/terminalStatuses.d.ts +3 -0
  319. package/dist/terminalStatuses.js +10 -2
  320. package/dist/toolHistoryMismatch.js +3 -2
  321. package/dist/toolResult.d.ts +10 -1
  322. package/dist/toolResult.js +34 -6
  323. package/dist/toolRoster.d.ts +3 -4
  324. package/dist/toolRoster.js +21 -22
  325. package/dist/turnFailurePresentation.d.ts +39 -0
  326. package/dist/turnFailurePresentation.js +402 -0
  327. package/dist/usageAnalytics.js +6 -11
  328. package/dist/userAttachmentEnvelope.d.ts +1 -0
  329. package/dist/userAttachmentEnvelope.js +37 -7
  330. package/dist/userAttachmentSeat.d.ts +21 -0
  331. package/dist/userAttachmentSeat.js +75 -0
  332. package/dist/userInvokedSkillsCapability.d.ts +11 -4
  333. package/dist/userInvokedSkillsCapability.js +31 -10
  334. package/dist/webSearchBackendCapability.d.ts +0 -4
  335. package/dist/webSearchBackendCapability.js +0 -6
  336. package/dist/wireErrorTriage.d.ts +7 -0
  337. package/dist/wireErrorTriage.js +26 -23
  338. package/dist/wireFailureShape.d.ts +62 -5
  339. package/dist/wireFailureShape.js +106 -5
  340. package/dist/wireRefusalCopy.d.ts +25 -3
  341. package/dist/wireRefusalCopy.js +74 -80
  342. package/dist/workflowsJournalCapability.d.ts +2 -5
  343. package/dist/workflowsJournalCapability.js +8 -12
  344. package/dist/writeProtectionCapability.d.ts +0 -4
  345. package/dist/writeProtectionCapability.js +0 -6
  346. package/docs/INTEGRATION-CLIENTS.md +1775 -56
  347. package/package.json +6 -5
  348. package/dist/attachmentSeatCapability.d.ts +0 -12
  349. package/dist/attachmentSeatCapability.js +0 -23
  350. package/dist/hitl/approvalOutcomeNote.d.ts +0 -10
  351. package/dist/hitl/approvalOutcomeNote.js +0 -29
  352. package/dist/sessionReadRedactionCapability.d.ts +0 -13
  353. package/dist/sessionReadRedactionCapability.js +0 -35
@@ -0,0 +1,291 @@
1
+ import { SETTINGS_CLASSIFY_HOOKS_CONFIG } from './generated/settingsSchemaFns.js';
2
+ import { hooksWirePlanShapeOf } from './pluginHooksWire.js';
3
+ export const HOST_SUPPLIED_KEYS = Object.freeze(['settings.hooks', 'settings.resolved', 'settings.webSearch', 'settings.outputStyle']);
4
+ export const HOST_SETTING_CAUSES = Object.freeze([
5
+ 'carried',
6
+ 'entries_dropped',
7
+ 'source_rejected',
8
+ 'projection_failed',
9
+ 'source_unreadable',
10
+ 'empty',
11
+ 'no_source',
12
+ 'host_port_missing',
13
+ ]);
14
+ export const HOST_SETTING_DISPOSITIONS = Object.freeze(['carry', 'carry_partial', 'withhold_notice', 'refuse_turn', 'unwired', 'nothing_to_carry']);
15
+ const HOST_SETTING_NOTICE_TEXT = {
16
+ 'HS-UNWIRED': (what) => `This app has not connected ${what} from your settings, so it is not sent with your requests.`,
17
+ 'HS-MANAGED-REJECTED': () => 'Managed settings: the hooks your administrator configured could not be loaded, so requests are not sent until the managed settings are fixed.',
18
+ 'HS-PROJECTION': () => 'The hooks for this request could not be checked before sending, so the request is not sent. Reload your settings and try again.',
19
+ 'HS-SOURCE-UNREADABLE': (what) => `This app could not read ${what} from your settings, so the request is not sent. Reload your settings and try again.`,
20
+ };
21
+ const KEY_NOUN = {
22
+ 'settings.hooks': 'the hooks',
23
+ 'settings.resolved': 'the permission rules',
24
+ 'settings.webSearch': 'the web search setup',
25
+ 'settings.outputStyle': 'the output style',
26
+ };
27
+ const BASE_DISPOSITION = {
28
+ carried: 'carry',
29
+ entries_dropped: 'carry_partial',
30
+ source_rejected: 'withhold_notice',
31
+ projection_failed: 'refuse_turn',
32
+ source_unreadable: 'refuse_turn',
33
+ empty: 'nothing_to_carry',
34
+ no_source: 'nothing_to_carry',
35
+ host_port_missing: 'unwired',
36
+ };
37
+ const freeze = (o) => Object.freeze(o);
38
+ const mint = (o) => o;
39
+ const notice = (id, plane, what = '') => freeze({ id, plane, text: HOST_SETTING_NOTICE_TEXT[id](what) });
40
+ function readSource(sources, key) {
41
+ try {
42
+ if (typeof sources !== 'object' || sources === null || !Object.hasOwn(sources, key))
43
+ return { kind: 'missing' };
44
+ const v = sources[key];
45
+ return v === undefined ? { kind: 'missing' } : { kind: 'value', value: v };
46
+ }
47
+ catch {
48
+ return { kind: 'threw' };
49
+ }
50
+ }
51
+ function unwrap(v, field) {
52
+ if (v === 'none')
53
+ return { kind: 'none' };
54
+ try {
55
+ if (typeof v !== 'object' || v === null || Array.isArray(v) || !Object.hasOwn(v, field))
56
+ return { kind: 'bad' };
57
+ return { kind: 'value', value: v[field] };
58
+ }
59
+ catch {
60
+ return { kind: 'bad' };
61
+ }
62
+ }
63
+ const isRecordShape = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
64
+ function hooksPassJudge(wire) {
65
+ try {
66
+ return isRecordShape(wire) && SETTINGS_CLASSIFY_HOOKS_CONFIG({ hooks: wire }).outcome === 'loaded';
67
+ }
68
+ catch {
69
+ return false;
70
+ }
71
+ }
72
+ function badSource(key, want) {
73
+ return new TypeError(`hostTurnSettings: sources.${key.replace(/^settings\./, '')} must be 'none' or ${want} — got something else (the value is not echoed).`);
74
+ }
75
+ const missingArm = (key) => ({
76
+ row: freeze({ key, cause: 'host_port_missing', disposition: BASE_DISPOSITION.host_port_missing }),
77
+ notices: [notice('HS-UNWIRED', 'session', KEY_NOUN[key])],
78
+ });
79
+ const unreadableArm = (key) => ({
80
+ row: freeze({ key, cause: 'source_unreadable', disposition: BASE_DISPOSITION.source_unreadable }),
81
+ notices: [notice('HS-SOURCE-UNREADABLE', 'turn', KEY_NOUN[key])],
82
+ });
83
+ const noSourceArm = (key) => ({ row: freeze({ key, cause: 'no_source', disposition: BASE_DISPOSITION.no_source }), notices: [] });
84
+ const carriedArm = (key, value) => ({ row: freeze({ key, cause: 'carried', disposition: BASE_DISPOSITION.carried }), notices: [], carried: value });
85
+ function hooksArm(src) {
86
+ const key = 'settings.hooks';
87
+ if (src.kind === 'missing')
88
+ return missingArm(key);
89
+ if (src.kind === 'threw')
90
+ return unreadableArm(key);
91
+ const u = unwrap(src.value, 'plan');
92
+ if (u.kind === 'none')
93
+ return noSourceArm(key);
94
+ if (u.kind === 'bad' || hooksWirePlanShapeOf(u.value) !== 'plan')
95
+ throw badSource(key, '{ plan } with the plan returned by hooksWirePlan() for this turn');
96
+ const plan = u.value;
97
+ let wire;
98
+ let salvageRows;
99
+ let closedBy;
100
+ try {
101
+ wire = plan.wire;
102
+ salvageRows = plan.settingsSalvage;
103
+ closedBy = plan.closedBy;
104
+ }
105
+ catch {
106
+ throw badSource(key, '{ plan } with a readable plan');
107
+ }
108
+ const rows = Array.isArray(salvageRows) ? salvageRows : [];
109
+ const layersOf = (outcome) => rows.filter((r) => isRecordShape(r) && r.outcome === outcome && typeof r.source === 'string').map((r) => r.source);
110
+ const managedRejected = layersOf('rejected').includes('policySettings');
111
+ if (managedRejected || layersOf('loaded-partial').includes('policySettings')) {
112
+ return {
113
+ row: freeze({ key, cause: managedRejected ? 'source_rejected' : 'entries_dropped', disposition: 'refuse_turn', layers: freeze(['policySettings']) }),
114
+ notices: [notice('HS-MANAGED-REJECTED', 'turn')],
115
+ plan,
116
+ };
117
+ }
118
+ if (closedBy === 'governance_unreadable')
119
+ return { ...unreadableArm(key), plan };
120
+ if (wire !== undefined && !hooksPassJudge(wire)) {
121
+ return { row: freeze({ key, cause: 'projection_failed', disposition: BASE_DISPOSITION.projection_failed }), notices: [notice('HS-PROJECTION', 'turn')], plan };
122
+ }
123
+ const carried = wire === undefined ? undefined : wire;
124
+ const rejected = layersOf('rejected');
125
+ const partial = layersOf('loaded-partial');
126
+ if (rejected.length > 0 || partial.length > 0) {
127
+ const cause = rejected.length > 0 ? 'source_rejected' : 'entries_dropped';
128
+ const layers = freeze([...new Set([...rejected, ...partial])]);
129
+ return { row: freeze({ key, cause, disposition: carried !== undefined ? 'carry_partial' : 'withhold_notice', layers }), notices: [], carried, plan };
130
+ }
131
+ if (carried === undefined)
132
+ return { row: freeze({ key, cause: 'empty', disposition: BASE_DISPOSITION.empty }), notices: [], plan };
133
+ return { ...carriedArm(key, carried), plan };
134
+ }
135
+ function passArm(key, field, src, want) {
136
+ if (src.kind === 'missing')
137
+ return missingArm(key);
138
+ if (src.kind === 'threw')
139
+ return unreadableArm(key);
140
+ const u = unwrap(src.value, field);
141
+ if (u.kind === 'none')
142
+ return noSourceArm(key);
143
+ if (u.kind === 'bad')
144
+ throw badSource(key, want);
145
+ if (u.value === undefined || u.value === null)
146
+ return { row: freeze({ key, cause: 'empty', disposition: BASE_DISPOSITION.empty }), notices: [] };
147
+ return carriedArm(key, u.value);
148
+ }
149
+ const RESOLVED_DEFERRED_ERROR = Symbol('hostTurnSettings.resolvedDeferredError');
150
+ export function rethrowHostResolvedDeferred(product) {
151
+ const rec = product;
152
+ if (!Object.hasOwn(rec, RESOLVED_DEFERRED_ERROR))
153
+ return;
154
+ const box = rec[RESOLVED_DEFERRED_ERROR];
155
+ if (box !== undefined)
156
+ throw box.error;
157
+ }
158
+ export function buildHostTurnSettings(input, materialize) {
159
+ let sources;
160
+ let sourcesThrew = false;
161
+ try {
162
+ sources = input?.sources;
163
+ }
164
+ catch {
165
+ sourcesThrew = true;
166
+ }
167
+ const read = (key) => (sourcesThrew ? { kind: 'threw' } : readSource(sources, key));
168
+ const resolved = passArm('settings.resolved', 'snapshot', read('resolved'), '{ snapshot } with the resolver snapshot');
169
+ let resolvedCarried = resolved.carried;
170
+ let resolvedError;
171
+ if (resolvedCarried !== undefined) {
172
+ try {
173
+ resolvedCarried = materialize(resolvedCarried);
174
+ }
175
+ catch (error) {
176
+ resolvedError = freeze({ error });
177
+ }
178
+ }
179
+ const hooks = hooksArm(read('hooks'));
180
+ const webSearch = passArm('settings.webSearch', 'settings', read('webSearch'), '{ settings } with the web search settings');
181
+ const outputStyle = passArm('settings.outputStyle', 'name', read('outputStyle'), '{ name } with the output style name');
182
+ const arms = [hooks, resolved, webSearch, outputStyle];
183
+ const rows = freeze(arms.map((a) => a.row));
184
+ const notices = freeze(arms.flatMap((a) => a.notices));
185
+ const refusal = arms.find((a) => a.row.disposition === 'refuse_turn');
186
+ const verdict = refusal === undefined ? freeze({ kind: 'send' }) : freeze({ kind: 'refuse', notice: refusal.notices[0] ?? notice('HS-PROJECTION', 'turn') });
187
+ const carried = freeze({
188
+ ...(hooks.carried !== undefined ? { hooks: hooks.carried } : {}),
189
+ ...(resolvedCarried !== undefined ? { resolved: resolvedCarried } : {}),
190
+ ...(webSearch.carried !== undefined ? { webSearch: webSearch.carried } : {}),
191
+ ...(outputStyle.carried !== undefined ? { outputStyle: outputStyle.carried } : {}),
192
+ });
193
+ const product = { verdict, rows, notices, hooks: hooks.plan, carried };
194
+ if (resolvedError !== undefined)
195
+ Object.defineProperty(product, RESOLVED_DEFERRED_ERROR, { value: resolvedError, enumerable: false });
196
+ return mint(freeze(product));
197
+ }
198
+ export function hostSettingsSelfCheck(product) {
199
+ try {
200
+ const rows = product.rows;
201
+ if (!Array.isArray(rows))
202
+ return HOST_SUPPLIED_KEYS;
203
+ const seen = new Set();
204
+ const out = [];
205
+ for (const r of rows) {
206
+ if (!isRecordShape(r) || typeof r.key !== 'string')
207
+ continue;
208
+ seen.add(r.key);
209
+ if (r.disposition === 'unwired' && HOST_SUPPLIED_KEYS.includes(r.key))
210
+ out.push(r.key);
211
+ }
212
+ for (const k of HOST_SUPPLIED_KEYS)
213
+ if (!seen.has(k) && !out.includes(k))
214
+ out.push(k);
215
+ return freeze(out);
216
+ }
217
+ catch {
218
+ return HOST_SUPPLIED_KEYS;
219
+ }
220
+ }
221
+ export class HostSettingsRefused extends Error {
222
+ notice;
223
+ constructor(n) {
224
+ super(n.text);
225
+ this.name = 'HostSettingsRefused';
226
+ this.notice = n;
227
+ }
228
+ }
229
+ const CARRYING = new Set(['carry', 'carry_partial']);
230
+ function shapeOf(v) {
231
+ if (v === undefined || v === null)
232
+ return UNWIRED_HOST_TURN_SETTINGS;
233
+ try {
234
+ if (!isRecordShape(v))
235
+ return undefined;
236
+ for (const k of ['verdict', 'rows', 'notices', 'hooks', 'carried'])
237
+ if (!Object.hasOwn(v, k))
238
+ return undefined;
239
+ const rows = v.rows;
240
+ if (!Array.isArray(rows) || rows.length !== HOST_SUPPLIED_KEYS.length)
241
+ return undefined;
242
+ const keys = rows.map((r) => (isRecordShape(r) ? r.key : undefined));
243
+ if (!HOST_SUPPLIED_KEYS.every((k, i) => keys[i] === k))
244
+ return undefined;
245
+ if (!isRecordShape(v.carried) || !isRecordShape(v.verdict))
246
+ return undefined;
247
+ const product = v;
248
+ return product;
249
+ }
250
+ catch {
251
+ return undefined;
252
+ }
253
+ }
254
+ export function hostTurnSettingsOf(v, depth = 'full') {
255
+ const shaped = shapeOf(v);
256
+ if (depth === 'shape' || shaped === undefined || shaped === UNWIRED_HOST_TURN_SETTINGS)
257
+ return shaped;
258
+ try {
259
+ const view = shaped;
260
+ const p = view;
261
+ const rows = p.rows;
262
+ const carried = p.carried;
263
+ const subs = HOST_SUPPLIED_KEYS.map((k) => k.slice('settings.'.length));
264
+ if (Object.keys(carried).some((k) => !subs.includes(k)))
265
+ return undefined;
266
+ let refuses = false;
267
+ for (const [i, r] of rows.entries()) {
268
+ const disposition = r.disposition;
269
+ if (!HOST_SETTING_DISPOSITIONS.includes(disposition))
270
+ return undefined;
271
+ if (disposition === 'refuse_turn')
272
+ refuses = true;
273
+ const sub = subs[i] ?? '';
274
+ const has = Object.hasOwn(carried, sub) && carried[sub] !== undefined;
275
+ if (has !== CARRYING.has(disposition))
276
+ return undefined;
277
+ }
278
+ const verdict = p.verdict;
279
+ if (verdict.kind !== (refuses ? 'refuse' : 'send'))
280
+ return undefined;
281
+ if (refuses && !(isRecordShape(verdict.notice) && typeof verdict.notice.text === 'string'))
282
+ return undefined;
283
+ if (Object.hasOwn(carried, 'hooks') && carried.hooks !== undefined && !hooksPassJudge(carried.hooks))
284
+ return undefined;
285
+ return shaped;
286
+ }
287
+ catch {
288
+ return undefined;
289
+ }
290
+ }
291
+ export const UNWIRED_HOST_TURN_SETTINGS = buildHostTurnSettings({ sources: {} }, (snapshot) => snapshot);
@@ -1,6 +1,8 @@
1
+ import type { UserAttachment } from '@sema-agent/sdk';
1
2
  import type { ImageInput } from './imagesWireCaps.js';
2
3
  import type { ImageVision } from './liveModelCatalog.js';
3
4
  import { type UserAttachmentDescriptor } from './userAttachmentEnvelope.js';
5
+ import type { UserAttachmentSeatReading } from './userAttachmentSeat.js';
4
6
  export interface HumanTurnRider {
5
7
  readonly uuid: string;
6
8
  readonly role: 'image_meta' | 'attachment' | 'skill_body' | (string & {});
@@ -34,6 +36,7 @@ export interface HumanTurnItem {
34
36
  }
35
37
  export interface HumanTurnCaps {
36
38
  readonly vision?: ImageVision;
39
+ readonly userAttachments?: UserAttachmentSeatReading;
37
40
  }
38
41
  export interface HumanTurnInput {
39
42
  readonly items: readonly HumanTurnItem[];
@@ -41,7 +44,7 @@ export interface HumanTurnInput {
41
44
  readonly caps: HumanTurnCaps;
42
45
  readonly otherBodyBytes?: number;
43
46
  }
44
- type EncoderShortfall = 'body_budget' | 'steer_admission' | 'vision_no' | 'vision_unknown' | 'image_too_large' | 'seat_count' | 'seat_total' | 'lane_has_no_image_seat' | 'lane_has_no_attachment_id_seat';
47
+ type EncoderShortfall = 'body_budget' | 'steer_admission' | 'vision_no' | 'image_too_large' | 'seat_count' | 'seat_total' | 'lane_has_no_image_seat' | 'lane_has_no_attachment_id_seat';
45
48
  export interface HumanTurnSharePart {
46
49
  readonly kind: 'text' | 'image' | 'attachment_ref' | 'attachment_id' | 'rider_text' | 'non_text';
47
50
  readonly ref?: string | number;
@@ -60,14 +63,23 @@ export interface HumanTurnDegraded {
60
63
  readonly ref?: string | number;
61
64
  readonly why: EncoderShortfall;
62
65
  }
66
+ export interface HumanTurnNotice {
67
+ readonly uuid: string;
68
+ readonly kind: 'image';
69
+ readonly ref: string;
70
+ readonly why: 'vision_unknown';
71
+ }
63
72
  export type HumanTurnEncoding = {
64
73
  readonly ok: true;
65
74
  readonly lane: 'objective';
66
75
  readonly text: string;
67
76
  readonly images: readonly ImageInput[];
68
77
  readonly attachmentIds: readonly string[];
78
+ readonly userAttachments?: readonly UserAttachment[];
79
+ readonly userAttachmentOrdinals?: readonly string[];
69
80
  readonly shares: readonly HumanTurnShare[];
70
81
  readonly degraded: readonly HumanTurnDegraded[];
82
+ readonly notices?: readonly HumanTurnNotice[];
71
83
  } | {
72
84
  readonly ok: true;
73
85
  readonly lane: 'steer';
@@ -86,6 +98,7 @@ export interface HumanTurnDelivered {
86
98
  readonly full: readonly string[];
87
99
  readonly partial: readonly string[];
88
100
  }
101
+ export declare function imageSentOnUnknownVision(notices: readonly HumanTurnNotice[] | undefined): string | undefined;
89
102
  export declare function encodeHumanTurn(input: HumanTurnInput): HumanTurnEncoding;
90
103
  export declare function deliveredUuidsOf(encoding: HumanTurnEncoding): HumanTurnDelivered;
91
104
  export {};
package/dist/humanTurn.js CHANGED
@@ -1,5 +1,5 @@
1
- import { CORE_MAX_PENDING_STEER_CHARS, CORE_MCP_IMAGE_MAX_BASE64 } from './generated/engineFactTables.js';
2
- import { mintEnvelopeOf, mintReferenceOf } from './userAttachmentEnvelope.js';
1
+ import { CORE_MAX_PENDING_STEER_CHARS, CORE_MCP_IMAGE_MAX_BASE64, CORE_USER_ATTACHMENT_LABEL_MAX } from './generated/engineFactTables.js';
2
+ import { mintEnvelopeOf, mintReferenceOf, seatTextOf } from './userAttachmentEnvelope.js';
3
3
  import { readEncodingShares, readHumanTurnInput } from './humanTurnRead.js';
4
4
  const REQUEST_BODY_MAX_BYTES = 8 * 1024 * 1024;
5
5
  const IMAGE_SEAT_MAX_COUNT = 20;
@@ -29,12 +29,14 @@ function utf8Length(s) {
29
29
  return n;
30
30
  }
31
31
  const jsonBytes = (v) => utf8Length(JSON.stringify(v));
32
- function bodyBytes(other, objective, images, ids) {
32
+ function bodyBytes(other, objective, images, ids, entries) {
33
33
  const keys = [jsonBytes('objective') + 1 + jsonBytes(objective)];
34
34
  if (images.length > 0)
35
35
  keys.push(jsonBytes('images') + 1 + jsonBytes(images));
36
36
  if (ids.length > 0)
37
37
  keys.push(jsonBytes('attachmentIds') + 1 + jsonBytes(ids));
38
+ if (entries.length > 0)
39
+ keys.push(jsonBytes('userAttachments') + 1 + jsonBytes(entries));
38
40
  const commas = other === 2 ? keys.length - 1 : keys.length;
39
41
  return other + keys.reduce((a, b) => a + b, 0) + commas;
40
42
  }
@@ -52,8 +54,27 @@ function steerRefusal(text) {
52
54
  function textOf(p) {
53
55
  if (p.form === 'reference')
54
56
  return mintReferenceOf(p.a.d);
57
+ if (p.form === 'seat')
58
+ return '';
55
59
  return mintEnvelopeOf(p.a.d, p.seated ? 'attached' : 'not-attached');
56
60
  }
61
+ const digits = (n) => String(n).length;
62
+ function renderedUpperBound(text, startLine) {
63
+ const lines = text.split('\n').length;
64
+ return text.length + lines * (digits(startLine + lines - 1) + 1);
65
+ }
66
+ function seatEntryOf(a, maxRenderedTextChars) {
67
+ const text = seatTextOf(a.d);
68
+ if (text === undefined || !('path' in a.d))
69
+ return undefined;
70
+ const name = a.d.path;
71
+ if (name.length === 0 || name.length > CORE_USER_ATTACHMENT_LABEL_MAX)
72
+ return undefined;
73
+ const startLine = a.d.kind === 'text' ? a.d.startLine : 1;
74
+ if (renderedUpperBound(text, startLine) > maxRenderedTextChars)
75
+ return undefined;
76
+ return a.d.kind === 'text' ? { name, text, startLine } : { name, text };
77
+ }
57
78
  function compose(items, placements) {
58
79
  const perItem = items.map((it, i) => [...placements.filter((p) => p.item === i).map(textOf), it.text].filter((s) => s.length > 0).join('\n\n'));
59
80
  return perItem.filter((s) => s.length > 0).join('\n');
@@ -76,7 +97,6 @@ const ENCODER_WHY_LIST = [
76
97
  'body_budget',
77
98
  'steer_admission',
78
99
  'vision_no',
79
- 'vision_unknown',
80
100
  'image_too_large',
81
101
  'seat_count',
82
102
  'seat_total',
@@ -101,7 +121,7 @@ function records(lane, items, pastedWhy, placements) {
101
121
  for (const p of placements) {
102
122
  if (p.item !== i)
103
123
  continue;
104
- push(i, p.form === 'content' ? { kind: 'attachment_ref', ref: p.a.uuid, status: 'full' } : { kind: 'attachment_ref', ref: p.a.uuid, status: 'none', why: lane === 'objective' ? 'body_budget' : 'steer_admission' });
124
+ push(i, p.form !== 'reference' ? { kind: 'attachment_ref', ref: p.a.uuid, status: 'full' } : { kind: 'attachment_ref', ref: p.a.uuid, status: 'none', why: lane === 'objective' ? 'body_budget' : 'steer_admission' });
105
125
  if (p.a.pixels !== undefined) {
106
126
  if (lane === 'steer')
107
127
  push(i, { kind: 'image', ref: p.a.uuid, status: 'none', why: 'lane_has_no_image_seat' });
@@ -142,6 +162,33 @@ function sharesAndDegraded(items, recs) {
142
162
  }
143
163
  return { shares, degraded };
144
164
  }
165
+ function noticesKey(v, items, placements) {
166
+ if (v.vision !== 'unknown')
167
+ return {};
168
+ const notices = [];
169
+ for (const p of placements) {
170
+ if (p.form === 'content' && p.seated && p.a.pixels !== undefined)
171
+ notices.push({ uuid: items[p.item].uuid, kind: 'image', ref: p.a.uuid, why: 'vision_unknown' });
172
+ }
173
+ return notices.length > 0 ? { notices } : {};
174
+ }
175
+ export function imageSentOnUnknownVision(notices) {
176
+ let n = 0;
177
+ try {
178
+ if (!Array.isArray(notices))
179
+ return undefined;
180
+ for (const x of notices)
181
+ if (x !== null && typeof x === 'object' && x.why === 'vision_unknown')
182
+ n += 1;
183
+ }
184
+ catch {
185
+ return undefined;
186
+ }
187
+ if (n === 0)
188
+ return undefined;
189
+ const what = n === 1 ? 'An @-mentioned image was' : `${n} @-mentioned images were`;
190
+ return `${what} sent with this message, although the engine's model list does not say whether the model this message uses accepts image input — if it does not, the images may be dropped or the message may be refused`;
191
+ }
145
192
  function encodeObjective(v) {
146
193
  const { items } = v;
147
194
  let count = 0;
@@ -161,10 +208,10 @@ function encodeObjective(v) {
161
208
  const placements = [];
162
209
  items.forEach((it, i) => {
163
210
  for (const a of it.attachments) {
164
- const p = { item: i, a, form: 'content', seated: false, seatWhy: undefined };
211
+ const p = { item: i, a, form: 'content', seated: false, seatWhy: undefined, entry: undefined };
165
212
  if (a.pixels !== undefined) {
166
- if (v.vision !== 'yes')
167
- p.seatWhy = v.vision === 'no' ? 'vision_no' : 'vision_unknown';
213
+ if (v.vision === 'no')
214
+ p.seatWhy = 'vision_no';
168
215
  else {
169
216
  p.seatWhy = seat(a.pixels.data.length);
170
217
  p.seated = p.seatWhy === undefined;
@@ -173,21 +220,62 @@ function encodeObjective(v) {
173
220
  placements.push(p);
174
221
  }
175
222
  });
223
+ if (v.seat !== undefined) {
224
+ let n = 0;
225
+ for (const p of placements) {
226
+ if (n >= v.seat.maxEntries)
227
+ break;
228
+ const entry = seatEntryOf(p.a, v.seat.maxRenderedTextChars);
229
+ if (entry === undefined)
230
+ continue;
231
+ p.form = 'seat';
232
+ p.entry = entry;
233
+ n += 1;
234
+ }
235
+ if (n > 0 && compose(items, placements).trim() === '') {
236
+ for (const p of placements) {
237
+ if (p.form === 'seat') {
238
+ p.form = 'content';
239
+ p.entry = undefined;
240
+ }
241
+ }
242
+ }
243
+ }
176
244
  const ids = items.flatMap((it) => it.attachmentIds);
177
245
  for (;;) {
178
246
  const text = compose(items, placements);
179
247
  const images = seatedImages(items, pastedWhy, placements);
180
- if (bodyBytes(v.otherBodyBytes, text, images, ids) <= REQUEST_BODY_MAX_BYTES) {
248
+ const seated = placements.filter((p) => p.form === 'seat');
249
+ const entries = seated.map((p) => p.entry);
250
+ if (bodyBytes(v.otherBodyBytes, text, images, ids, entries) <= REQUEST_BODY_MAX_BYTES) {
181
251
  if (text.trim() === '')
182
252
  return { ok: false, reason: 'empty' };
183
253
  const { shares, degraded } = sharesAndDegraded(items, records('objective', items, pastedWhy, placements));
184
- return { ok: true, lane: 'objective', text, images, attachmentIds: [...ids], shares, degraded };
254
+ return {
255
+ ok: true,
256
+ lane: 'objective',
257
+ text,
258
+ images,
259
+ attachmentIds: [...ids],
260
+ ...(entries.length > 0 ? { userAttachments: entries, userAttachmentOrdinals: seated.map((p) => p.a.uuid) } : {}),
261
+ shares,
262
+ degraded,
263
+ ...noticesKey(v, items, placements),
264
+ };
185
265
  }
186
266
  let pick = -1;
187
267
  let pickCost = -1;
188
268
  placements.forEach((p, k) => {
189
- if (p.form !== 'content')
269
+ if (p.form === 'reference')
190
270
  return;
271
+ if (p.form === 'seat') {
272
+ const cost = jsonBytes(p.entry) + 1;
273
+ if (cost >= pickCost) {
274
+ pick = k;
275
+ pickCost = cost;
276
+ }
277
+ return;
278
+ }
191
279
  const cost = jsonBytes(textOf(p)) + (p.seated && p.a.pixels !== undefined ? jsonBytes({ data: p.a.pixels.data, mimeType: p.a.pixels.mimeType }) : 0);
192
280
  if (cost >= pickCost) {
193
281
  pick = k;
@@ -204,7 +292,7 @@ function encodeSteer(v) {
204
292
  const placements = [];
205
293
  items.forEach((it, i) => {
206
294
  for (const a of it.attachments)
207
- placements.push({ item: i, a, form: 'content', seated: false, seatWhy: undefined });
295
+ placements.push({ item: i, a, form: 'content', seated: false, seatWhy: undefined, entry: undefined });
208
296
  });
209
297
  let text = compose(items, placements);
210
298
  let refusal = steerRefusal(text);
@@ -2,6 +2,7 @@ import type { ImageInput } from './imagesWireCaps.js';
2
2
  import type { UserAttachmentDescriptor, UserAttachmentMcpResourcePart, UserAttachmentNotIncludedReason, UserAttachmentSource } from './userAttachmentEnvelope.js';
3
3
  import type { HumanTurnAttachment, HumanTurnEncoding, HumanTurnInput, HumanTurnMissing } from './humanTurn.js';
4
4
  import type { ImageVision } from './liveModelCatalog.js';
5
+ import { type UserAttachmentSeatLimits } from './userAttachmentSeat.js';
5
6
  export interface CellView {
6
7
  cellType: string | undefined;
7
8
  source: string | undefined;
@@ -104,6 +105,7 @@ export interface ItemView {
104
105
  export interface InputView {
105
106
  lane: 'objective' | 'steer';
106
107
  vision: ImageVision;
108
+ seat: UserAttachmentSeatLimits | undefined;
107
109
  otherBodyBytes: number;
108
110
  items: ItemView[];
109
111
  }
@@ -1,3 +1,4 @@
1
+ import { userAttachmentSeatAdmits } from './userAttachmentSeat.js';
1
2
  const descriptorKindsAligned = true;
2
3
  void descriptorKindsAligned;
3
4
  const MALFORMED = Object.freeze({});
@@ -258,6 +259,25 @@ function readItem(x) {
258
259
  }),
259
260
  };
260
261
  }
262
+ function seatLimitsOf(caps) {
263
+ try {
264
+ const reading = ownData(caps, 'userAttachments');
265
+ if (reading === undefined)
266
+ return undefined;
267
+ if (userAttachmentSeatAdmits(reading) !== 'yes')
268
+ return undefined;
269
+ const limits = ownData(reading, 'limits');
270
+ if (!isPlainObject(limits))
271
+ return undefined;
272
+ const maxEntries = ownData(limits, 'maxEntries');
273
+ const maxRenderedTextChars = ownData(limits, 'maxRenderedTextChars');
274
+ const ok = (n) => typeof n === 'number' && Number.isSafeInteger(n) && n >= 1;
275
+ return ok(maxEntries) && ok(maxRenderedTextChars) ? { maxEntries, maxRenderedTextChars } : undefined;
276
+ }
277
+ catch {
278
+ return undefined;
279
+ }
280
+ }
261
281
  function readInputAny(x) {
262
282
  if (!isPlainObject(x))
263
283
  reject('malformed_input');
@@ -271,6 +291,7 @@ function readInputAny(x) {
271
291
  const vision = ownData(caps, 'vision');
272
292
  if (vision !== undefined && vision !== 'yes' && vision !== 'no' && vision !== 'unknown')
273
293
  reject('malformed_input');
294
+ const seat = seatLimitsOf(caps);
274
295
  let otherBodyBytes = 0;
275
296
  if (lane === 'objective') {
276
297
  const ob = ownData(o, 'otherBodyBytes');
@@ -316,7 +337,7 @@ function readInputAny(x) {
316
337
  }
317
338
  if (items.every((it) => it.text.length === 0 && it.images.length === 0 && it.attachments.length === 0 && it.attachmentIds.length === 0))
318
339
  reject('empty');
319
- return { lane: lane, vision: vision ?? 'unknown', otherBodyBytes, items };
340
+ return { lane: lane, vision: vision ?? 'unknown', seat, otherBodyBytes, items };
320
341
  }
321
342
  export function readHumanTurnInput(input) {
322
343
  try {