chainlesschain 0.163.7 → 0.164.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 (252) hide show
  1. package/package.json +5 -1
  2. package/scripts/macos-mcp-launcher-build.mjs +317 -0
  3. package/scripts/macos-mcp-launcher-postinstall.sh +54 -0
  4. package/scripts/macos-mcp-launcher-preinstall.sh +61 -0
  5. package/src/assets/web-panel/assets/{AIOps-axqQfwv8.js → AIOps-D2MEn7fI.js} +1 -1
  6. package/src/assets/web-panel/assets/{ActionButton-DV-Ro0By.js → ActionButton-lCW_4Gf0.js} +1 -1
  7. package/src/assets/web-panel/assets/{Analytics-Bt72WEVu.js → Analytics-Bs7i-nsS.js} +3 -3
  8. package/src/assets/web-panel/assets/{AppLayout-BtepG55E.js → AppLayout-CK7B6S_j.js} +5 -5
  9. package/src/assets/web-panel/assets/{Artifacts-B7KaJ7S_.js → Artifacts-C8ILjpyo.js} +1 -1
  10. package/src/assets/web-panel/assets/{Audit-FNFaUg7A.js → Audit-Bb9cNaWc.js} +1 -1
  11. package/src/assets/web-panel/assets/{BackgroundAgents-DFb6J2wQ.js → BackgroundAgents-sC9ooXIf.js} +1 -1
  12. package/src/assets/web-panel/assets/{Backup-CC7YBhyj.js → Backup-D-DrsplT.js} +1 -1
  13. package/src/assets/web-panel/assets/{BaseInput-RkgTNVtj.js → BaseInput-uCNZpwSK.js} +1 -1
  14. package/src/assets/web-panel/assets/{Chat-hHEmGZy-.js → Chat-CsDK1uE9.js} +6 -6
  15. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CAP9YhHv.js → ChatBubbleRenderer-OqSDt50w.js} +1 -1
  16. package/src/assets/web-panel/assets/{Checkbox-z5wXOQP1.js → Checkbox-JhTXM1-K.js} +1 -1
  17. package/src/assets/web-panel/assets/{Codegen-DVaDJnxy.js → Codegen-BbzZLnyD.js} +1 -1
  18. package/src/assets/web-panel/assets/{Col-CJmaRDR5.js → Col-D4VW4m4j.js} +1 -1
  19. package/src/assets/web-panel/assets/{Community-DF29_2bI.js → Community-BXrYawxV.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compact-DtkQkBzn.js → Compact-DCihGy1u.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compliance-xoHDxp7I.js → Compliance-DlyZ-lk8.js} +1 -1
  22. package/src/assets/web-panel/assets/{Cowork-BUm-R7ht.js → Cowork-DvGZrhbO.js} +2 -2
  23. package/src/assets/web-panel/assets/{Cron-Cgl14ZkB.js → Cron-DUncZi8h.js} +2 -2
  24. package/src/assets/web-panel/assets/{Crosschain-BNcbmoqh.js → Crosschain-C_hLuUcm.js} +1 -1
  25. package/src/assets/web-panel/assets/{DID-Bwja0Zo9.js → DID-b6YSUqxr.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dashboard-Bk5XjEdJ.js → Dashboard-uvM15Cfb.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dropdown-Ci36Oitq.js → Dropdown-D1-Nd4qY.js} +1 -1
  28. package/src/assets/web-panel/assets/{EmailListRenderer--U04ZN4q.js → EmailListRenderer-8ApvL6Zc.js} +1 -1
  29. package/src/assets/web-panel/assets/{FamilyGuardDashboard-B2gNPR2s.js → FamilyGuardDashboard-LYJt8811.js} +1 -1
  30. package/src/assets/web-panel/assets/{Federation-C4KghYn7.js → Federation-BbI3HGpv.js} +1 -1
  31. package/src/assets/web-panel/assets/{FormItemContext-QL7x_Q_0.js → FormItemContext-DSoEKuFu.js} +1 -1
  32. package/src/assets/web-panel/assets/{GenericCardRenderer-F3Ryltwm.js → GenericCardRenderer-B0S9OWd5.js} +1 -1
  33. package/src/assets/web-panel/assets/{Git-2HassK5k.js → Git-DIs9Zhf3.js} +2 -2
  34. package/src/assets/web-panel/assets/{Governance-DoBIp7oe.js → Governance-jzZXrxcl.js} +1 -1
  35. package/src/assets/web-panel/assets/{Inference--W01QhZ-.js → Inference-JUPjf2ZI.js} +1 -1
  36. package/src/assets/web-panel/assets/{KnowledgeGraph-DmvwqGpT.js → KnowledgeGraph-DxnfJvlP.js} +1 -1
  37. package/src/assets/web-panel/assets/{Logs-BBJ4yAel.js → Logs-iXiz8BEE.js} +2 -2
  38. package/src/assets/web-panel/assets/{MarkdownRenderer-BLCZMzhJ.js → MarkdownRenderer-GmB6DOr6.js} +1 -1
  39. package/src/assets/web-panel/assets/{Marketplace-D5lNngSI.js → Marketplace-Y3Xch312.js} +1 -1
  40. package/src/assets/web-panel/assets/{McpTools-CkEVOMKH.js → McpTools-D7kGGbO7.js} +4 -4
  41. package/src/assets/web-panel/assets/{Memory-B1Ow1xVE.js → Memory-Do_hVxzh.js} +2 -2
  42. package/src/assets/web-panel/assets/{MobileBridge-SgYbUfb6.js → MobileBridge-CtrR0Tas.js} +1 -1
  43. package/src/assets/web-panel/assets/MobileProjects-BL0Czcoj.js +1 -0
  44. package/src/assets/web-panel/assets/{Mtc-DcTXSSma.js → Mtc-qo5QCTGd.js} +2 -2
  45. package/src/assets/web-panel/assets/{MtcAudit-Dt3WG4oj.js → MtcAudit-cq5mnjYj.js} +2 -2
  46. package/src/assets/web-panel/assets/{Multisig-B9B38UZx.js → Multisig-Bq0MAQHw.js} +3 -3
  47. package/src/assets/web-panel/assets/{NLProgramming-B0S4GGvG.js → NLProgramming-DdWE6Vi2.js} +1 -1
  48. package/src/assets/web-panel/assets/{Notes-DZ5U58Ng.js → Notes-BxMBFcIp.js} +3 -3
  49. package/src/assets/web-panel/assets/{NotificationSettings-PjL5ZW34.js → NotificationSettings-RTrAcbUe.js} +1 -1
  50. package/src/assets/web-panel/assets/{OrderTableRenderer-DrAX2ESt.js → OrderTableRenderer-DJbpGqzT.js} +1 -1
  51. package/src/assets/web-panel/assets/{Organization-Cv1GYs-c.js → Organization-SQzIPdqC.js} +4 -4
  52. package/src/assets/web-panel/assets/{Overflow-Bbkp_PL3.js → Overflow-02yECh22.js} +1 -1
  53. package/src/assets/web-panel/assets/{P2P-BD8QUgoZ.js → P2P-BNg4pNCM.js} +2 -2
  54. package/src/assets/web-panel/assets/{PdhVaultBrowser-BO-2PeaB.js → PdhVaultBrowser-BxPJZsD3.js} +3 -3
  55. package/src/assets/web-panel/assets/{Permissions-D_OPVa02.js → Permissions-CLnDnPAz.js} +4 -4
  56. package/src/assets/web-panel/assets/{PersonalDataHub-mh-pEmaB.js → PersonalDataHub-C5m0AjGf.js} +4 -4
  57. package/src/assets/web-panel/assets/{Pipeline-6JC2EDdb.js → Pipeline-VwOf5Dhv.js} +1 -1
  58. package/src/assets/web-panel/assets/{Privacy-CUshzUAG.js → Privacy-CC0W2hZd.js} +1 -1
  59. package/src/assets/web-panel/assets/{ProjectInit-Cs2Aalri.js → ProjectInit-Dz893Bob.js} +2 -2
  60. package/src/assets/web-panel/assets/{ProjectSettings-1ak49tcj.js → ProjectSettings-CxQkvl0k.js} +2 -2
  61. package/src/assets/web-panel/assets/Projects-DDAjkUkT.js +1 -0
  62. package/src/assets/web-panel/assets/{Providers-CXXxvafH.js → Providers-DeB9IkxK.js} +1 -1
  63. package/src/assets/web-panel/assets/{QrScannerModal-PTcDsF58.js → QrScannerModal-OCeoaswn.js} +1 -1
  64. package/src/assets/web-panel/assets/{QuickAsk-CDwucrJw.js → QuickAsk-DenotaAj.js} +1 -1
  65. package/src/assets/web-panel/assets/{Recommend-CJlLVRXR.js → Recommend-Cies_jjI.js} +1 -1
  66. package/src/assets/web-panel/assets/{RemoteSession-DlN-ETsO.js → RemoteSession-Dxzl5n2T.js} +3 -3
  67. package/src/assets/web-panel/assets/{Reputation-DI23LR6m.js → Reputation-CW0mvxgZ.js} +1 -1
  68. package/src/assets/web-panel/assets/{Row-Cl7UQMrM.js → Row-SEd32qZU.js} +1 -1
  69. package/src/assets/web-panel/assets/{RssFeed-CexHNfh8.js → RssFeed-BSwnJ3Lm.js} +3 -3
  70. package/src/assets/web-panel/assets/{Search-BneBWvRN.js → Search-xe2m8bkC.js} +1 -1
  71. package/src/assets/web-panel/assets/{Security-DX7Phgrp.js → Security-Mq2F9Nro.js} +4 -4
  72. package/src/assets/web-panel/assets/{Services-BWXO8Mte.js → Services-BKGw2V3P.js} +2 -2
  73. package/src/assets/web-panel/assets/{Skeleton-DCyOjKPJ.js → Skeleton-DW95-Rxf.js} +1 -1
  74. package/src/assets/web-panel/assets/{Skills-CXqERsTB.js → Skills-CHgChCv_.js} +1 -1
  75. package/src/assets/web-panel/assets/{Sla-bhbrbz8E.js → Sla-tKh6k3R7.js} +1 -1
  76. package/src/assets/web-panel/assets/{SpeechSettings-3IPU0HBZ.js → SpeechSettings-D6UL3dA5.js} +1 -1
  77. package/src/assets/web-panel/assets/{SyncSettings-DBNTQLbM.js → SyncSettings-D0Fw8fVL.js} +2 -2
  78. package/src/assets/web-panel/assets/{Tasks-quP0bkN-.js → Tasks-20x1GB3D.js} +1 -1
  79. package/src/assets/web-panel/assets/{Templates-BouWmgho.js → Templates-DJ-lts-a.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tenant-qv0D9s7z.js → Tenant-BFdGpbs7.js} +1 -1
  81. package/src/assets/web-panel/assets/{Terminal-BxvbE8BB.js → Terminal-Xpx61vHL.js} +2 -2
  82. package/src/assets/web-panel/assets/{TimelineRenderer-D-IeLnJ2.js → TimelineRenderer-C6UIvyZQ.js} +1 -1
  83. package/src/assets/web-panel/assets/{Tokens-CFMKKyVG.js → Tokens-Dellq08f.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trigger-L8as3UuJ.js → Trigger-VKw8d0J-.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trust-MxmA4VZG.js → Trust-DNftdKT5.js} +1 -1
  86. package/src/assets/web-panel/assets/{UkeySign-C0VvJYRi.js → UkeySign-DX9VAKJI.js} +1 -1
  87. package/src/assets/web-panel/assets/{VideoEditing-Bf5QZj8N.js → VideoEditing-B2h3jO8q.js} +1 -1
  88. package/src/assets/web-panel/assets/{Wallet-BIJ9riRz.js → Wallet-CjGkof7f.js} +4 -4
  89. package/src/assets/web-panel/assets/{WebAuthn-B8p9Mhkw.js → WebAuthn-2Zfcu55P.js} +4 -4
  90. package/src/assets/web-panel/assets/{WorkflowEditor-BVsuaPen.js → WorkflowEditor-B9eZ8UxZ.js} +1 -1
  91. package/src/assets/web-panel/assets/{chat-BfkjoKpV.js → chat-CQNfD-YO.js} +1 -1
  92. package/src/assets/web-panel/assets/{colors-DeAlsWK8.js → colors-D4usyFT2.js} +1 -1
  93. package/src/assets/web-panel/assets/{compact-item-Cs97bz5j.js → compact-item-s4TpjvjX.js} +1 -1
  94. package/src/assets/web-panel/assets/{createContext-BqbG60LH.js → createContext-BRCSvYxj.js} +1 -1
  95. package/src/assets/web-panel/assets/devWarning-DKJjSWRn.js +1 -0
  96. package/src/assets/web-panel/assets/{hasIn-i_RY0b1X.js → hasIn-AdkUbkV-.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-BOVkf1K3.js → index--00U6vXZ.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-B-3tEpTc.js → index-B2V-eKfK.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-D2B4VPyP.js → index-B4JJCfQ2.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BkBi5TmC.js → index-BIoG5yYf.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-79V_zv1s.js → index-BMcimU-2.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-U4f5izHz.js → index-BPhkFZ1I.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DiSkx4UB.js → index-BQ3DXBtD.js} +3 -3
  104. package/src/assets/web-panel/assets/{index-dIHr4B_u.js → index-Bad4VNvz.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-CIG8fQ2_.js → index-BgiXR_-_.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DqBgBpgp.js → index-BtobShro.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-ZxO_-E8a.js → index-Bw2MEnUk.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DUUrv141.js → index-C1mJtE6q.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Bm7lLR4c.js → index-C484EJiS.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-COdGA-8n.js → index-C5KAQFPQ.js} +1 -1
  111. package/src/assets/web-panel/assets/index-C61cnl3K.js +1 -0
  112. package/src/assets/web-panel/assets/{index-CED2PL_y.js → index-C7Y8Aluc.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-YXgLng0K.js → index-CCsM_Ybx.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-0-agYlWL.js → index-CJCFe2Qf.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-B5UkyA3c.js → index-CJVEOa4i.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-B1CbOH1i.js → index-CJdQrZth.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-s1opAL-M.js → index-CKC1t3Ic.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-yObj1O4n.js → index-CQhAVU5t.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-CgsqdnRV.js → index-CYdoQsa1.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Dk7-v4hP.js → index-Cduu2Hhr.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-B-JVTrpr.js → index-CkwiSLhU.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-CeWoNHau.js → index-Cvyt-zhm.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-CE2VtTlp.js → index-D2GjI2oe.js} +1 -1
  124. package/src/assets/web-panel/assets/index-D4XFHxBr.js +1 -0
  125. package/src/assets/web-panel/assets/{index-DmbfhJUP.js → index-DARsAyUp.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-BESLFt4q.js → index-DVKfQ0Ux.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-PT_5sBMA.js → index-DZT36ZYq.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-gyFpvL7l.js → index-D_XBHopw.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-BYUVuwKt.js → index-DdCB70SS.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-BcUXAB2s.js → index-DzRjHxEv.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-Dk2qouAz.js → index-MMN9V6JF.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-D9evtvg2.js → index-RfMr79MW.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-BuLQobzW.js → index-_IRVsV9X.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-Cf3WCLmy.js → index-nXyk8GZ9.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-CG3PRyAL.js → index-s_buFMEG.js} +1 -1
  136. package/src/assets/web-panel/assets/{initDefaultProps-C9h9yKL3.js → initDefaultProps-Blmpk7HL.js} +1 -1
  137. package/src/assets/web-panel/assets/{motion-BvmLsPdu.js → motion-DPBJMv1n.js} +1 -1
  138. package/src/assets/web-panel/assets/{move-CoL4ekU1.js → move-ButdzCM7.js} +1 -1
  139. package/src/assets/web-panel/assets/{mtc-parser-C4pMy6xV.js → mtc-parser-cyRC_QCe.js} +1 -1
  140. package/src/assets/web-panel/assets/{omit-DPuJfNxx.js → omit-1epSV7hz.js} +1 -1
  141. package/src/assets/web-panel/assets/{pickAttrs-D0KEeaK2.js → pickAttrs-DuPY8xJs.js} +1 -1
  142. package/src/assets/web-panel/assets/{placementArrow-BpkyINxt.js → placementArrow-6XZqarhe.js} +1 -1
  143. package/src/assets/web-panel/assets/{responsiveObserve-DQI_wOq8.js → responsiveObserve-B40pXBWM.js} +1 -1
  144. package/src/assets/web-panel/assets/{slide-DYfdDiRg.js → slide-jbZ9Wu4n.js} +1 -1
  145. package/src/assets/web-panel/assets/{statusUtils-B5dtvb0D.js → statusUtils-BKQQcVy4.js} +1 -1
  146. package/src/assets/web-panel/assets/{styleChecker-CF310mSj.js → styleChecker-NiKfWjUT.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFlexGapSupport-D1Qp4BLp.js → useFlexGapSupport-bQUCvPeb.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFs-C7_iyvJK.js → useFs-CUGji7ph.js} +1 -1
  149. package/src/assets/web-panel/assets/{usePersonalDataHub-DZUt_fIm.js → usePersonalDataHub-4veyN2N2.js} +1 -1
  150. package/src/assets/web-panel/assets/{vnode-D3dsi0lZ.js → vnode-1-nLug-Z.js} +1 -1
  151. package/src/assets/web-panel/assets/{zoom-WdbOlvdQ.js → zoom-dhCeRDMo.js} +1 -1
  152. package/src/assets/web-panel/index.html +1 -1
  153. package/src/command-help-index.json +6 -6
  154. package/src/commands/automation.js +103 -1
  155. package/src/commands/cowork.js +174 -19
  156. package/src/commands/permissions.js +240 -16
  157. package/src/commands/plugin.js +1293 -56
  158. package/src/commands/session-location.js +276 -0
  159. package/src/commands/session.js +2 -0
  160. package/src/commands/team-merge-review.js +937 -0
  161. package/src/commands/team.js +2 -0
  162. package/src/data/changelog.json +27 -1
  163. package/src/gateways/ws/action-protocol.js +35 -10
  164. package/src/gateways/ws/remote-session-protocol.js +24 -1
  165. package/src/gateways/ws/ws-agent-handler.js +12 -0
  166. package/src/gateways/ws/ws-server.js +48 -12
  167. package/src/harness/jsonl-session-store.js +341 -24
  168. package/src/harness/mcp-client.js +8 -1
  169. package/src/harness/remote-session-audit.js +1 -0
  170. package/src/harness/remote-session-crypto.js +210 -2
  171. package/src/harness/remote-session-registry.js +159 -6
  172. package/src/harness/session-list-index.js +233 -14
  173. package/src/lib/agent-authority.js +6 -0
  174. package/src/lib/agent-schedule-store.js +139 -28
  175. package/src/lib/agent-team/team-merge-review-store.js +765 -0
  176. package/src/lib/agent-team/team-merge-review-transaction.js +1223 -0
  177. package/src/lib/agent-team/team-merge-review.js +1847 -0
  178. package/src/lib/automation-center-incidents.js +314 -0
  179. package/src/lib/automation-center-runtime.js +448 -0
  180. package/src/lib/automation-center.js +182 -38
  181. package/src/lib/automation-engine.js +41 -0
  182. package/src/lib/automation-execution-authority.js +241 -12
  183. package/src/lib/automation-execution-incident.js +737 -0
  184. package/src/lib/background-agent-keeper-client.js +248 -0
  185. package/src/lib/background-agent-keeper-protocol.js +147 -0
  186. package/src/lib/background-agent-supervisor.js +520 -40
  187. package/src/lib/background-interaction-resolver.js +12 -0
  188. package/src/lib/background-turn-bootstrap-protocol.js +126 -0
  189. package/src/lib/cowork-cron.js +85 -14
  190. package/src/lib/cowork-workflow.js +336 -16
  191. package/src/lib/dynamic-workflow-facade.js +648 -0
  192. package/src/lib/execution-location-contract.js +551 -0
  193. package/src/lib/execution-location-runtime.js +130 -0
  194. package/src/lib/ide-context.js +94 -6
  195. package/src/lib/mcp-stdio-package-materialization.js +166 -14
  196. package/src/lib/packer/pkg-config-generator.js +2 -0
  197. package/src/lib/permission-authority.js +77 -0
  198. package/src/lib/permission-side-effect-center.js +495 -0
  199. package/src/lib/plugin-runtime/install.js +514 -13
  200. package/src/lib/plugin-runtime/marketplace-artifact-readback.js +900 -0
  201. package/src/lib/plugin-runtime/marketplace-catalog.js +1181 -0
  202. package/src/lib/plugin-runtime/marketplace-impact.js +408 -0
  203. package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1567 -0
  204. package/src/lib/plugin-security.js +60 -3
  205. package/src/lib/process-execution-broker/index.js +1095 -57
  206. package/src/lib/process-execution-broker/linux-bwrap-descriptor-launch.js +375 -0
  207. package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +90 -16
  208. package/src/lib/process-execution-broker/linux-generic-bwrap.js +159 -18
  209. package/src/lib/process-execution-broker/macos-mcp-launcher-contract.js +278 -0
  210. package/src/lib/process-execution-broker/macos-mcp-launcher-protocol.json +23 -0
  211. package/src/lib/process-execution-broker/macos-mcp-launcher.c +1497 -0
  212. package/src/lib/process-execution-broker/mcp-fd-entry-bootstrap.js +37 -0
  213. package/src/lib/process-execution-broker/platform-sandbox.js +2330 -279
  214. package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
  215. package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
  216. package/src/lib/process-execution-broker/windows-sandbox.cs +50 -4
  217. package/src/lib/public-ide-capability-manifest.js +3 -0
  218. package/src/lib/remote-approval-bridge.js +123 -17
  219. package/src/lib/remote-membership-authority.js +632 -0
  220. package/src/lib/remote-membership-coordinator.js +2409 -0
  221. package/src/lib/remote-membership-host-store.js +1750 -0
  222. package/src/lib/scheduler-kernel/agenda-adapter.js +17 -7
  223. package/src/lib/scheduler-kernel/automation-adapter.js +105 -11
  224. package/src/lib/scheduler-kernel/automation-event-adapter.js +87 -11
  225. package/src/lib/scheduler-kernel/contract.js +91 -0
  226. package/src/lib/scheduler-kernel/cowork-cron-adapter.js +12 -1
  227. package/src/lib/scheduler-kernel/loop-adapter.js +7 -1
  228. package/src/lib/scheduler-kernel/routine-adapter.js +7 -1
  229. package/src/lib/scheduler-kernel/runtime-control-capabilities.js +31 -0
  230. package/src/lib/scheduler-kernel/runtime.js +176 -3
  231. package/src/lib/scheduler-kernel/store.js +1253 -45
  232. package/src/lib/scoped-permission-store.js +369 -0
  233. package/src/lib/session-anti-rollback-anchor.js +262 -5
  234. package/src/lib/sub-agent-context.js +4 -0
  235. package/src/lib/workflow-definition-contract.js +149 -0
  236. package/src/repl/agent-repl.js +41 -7
  237. package/src/repl/chat-repl.js +2 -0
  238. package/src/repl/clipboard-image.js +735 -16
  239. package/src/repl/ide-status.js +1 -1
  240. package/src/repl/prompt-interactions.js +59 -6
  241. package/src/runtime/agent-core.js +93 -3
  242. package/src/runtime/headless-runner.js +30 -25
  243. package/src/runtime/headless-stream.js +32 -25
  244. package/src/runtime/mcp-config.js +81 -10
  245. package/src/workers/background-agent-keeper.js +498 -0
  246. package/src/workers/background-agent-worker.js +358 -13
  247. package/src/workers/background-turn-bootstrap.js +143 -0
  248. package/src/assets/web-panel/assets/MobileProjects-BWdOvQAj.js +0 -1
  249. package/src/assets/web-panel/assets/Projects-BV4oApsm.js +0 -1
  250. package/src/assets/web-panel/assets/devWarning-DPty0mGN.js +0 -1
  251. package/src/assets/web-panel/assets/index-Bt7g0Vq_.js +0 -1
  252. package/src/assets/web-panel/assets/index-ChVT0p9u.js +0 -1
@@ -1,11 +1,28 @@
1
1
  /**
2
2
  * Clipboard-image capability boundary for terminal REPL hosts.
3
3
  *
4
- * Plain Node readline receives pasted text only; it has no portable clipboard
5
- * image event. We therefore enable image chips solely when an embedding host
6
- * supplies an explicit, testable `readImage()` binding. Standard terminals get
7
- * a truthful path-attachment fallback instead of a fake "paste succeeded".
4
+ * Plain Node readline receives pasted text only, so standard terminals need a
5
+ * guarded OS adapter to obtain image bytes. Embedded hosts may still inject the
6
+ * same narrow `readImage()` binding used by the production adapter.
8
7
  */
8
+ import {
9
+ accessSync,
10
+ constants as fsConstants,
11
+ lstatSync,
12
+ mkdtempSync,
13
+ readFileSync,
14
+ rmSync,
15
+ statSync,
16
+ writeFileSync,
17
+ } from "node:fs";
18
+ import { tmpdir } from "node:os";
19
+ import { join, posix as posixPath, win32 as win32Path } from "node:path";
20
+ import { executionBroker } from "../lib/process-execution-broker/index.js";
21
+ import {
22
+ ensurePrivateDirectory,
23
+ ensurePrivateFile,
24
+ PRIVATE_FILE_MODE,
25
+ } from "../lib/secure-fs.js";
9
26
 
10
27
  export const CLIPBOARD_IMAGE_MEDIA_TYPES = Object.freeze([
11
28
  "image/png",
@@ -14,16 +31,706 @@ export const CLIPBOARD_IMAGE_MEDIA_TYPES = Object.freeze([
14
31
  "image/webp",
15
32
  ]);
16
33
  export const MAX_CLIPBOARD_IMAGE_BYTES = 20 * 1024 * 1024;
34
+ export const MAX_CLIPBOARD_IMAGE_ATTACHMENTS = 4;
35
+ export const MAX_CLIPBOARD_IMAGE_TOTAL_BYTES = 40 * 1024 * 1024;
36
+ export const CLIPBOARD_IMAGE_READ_TIMEOUT_MS = 10_000;
37
+
38
+ const MAX_MACOS_SOURCE_BYTES = 80 * 1024 * 1024;
39
+ const MAX_MACOS_IMAGE_PIXELS = 25_000_000;
40
+ const MAX_MACOS_IMAGE_DIMENSION = 16_384;
41
+ const MAX_MACOS_DECODED_IMAGE_BYTES = 256 * 1024 * 1024;
42
+ const MACOS_CLIPBOARD_HELPER_ERROR_STAGES = new Set([
43
+ "arguments",
44
+ "pasteboard",
45
+ "png-read",
46
+ "png-check",
47
+ "tiff-read",
48
+ "tiff-check",
49
+ "tiff-length",
50
+ "tiff-source",
51
+ "tiff-count",
52
+ "tiff-image-create",
53
+ "tiff-image-layout",
54
+ "tiff-color-space",
55
+ "tiff-color-model",
56
+ "tiff-bitmap",
57
+ "tiff-encode",
58
+ "image-length",
59
+ "image-write",
60
+ ]);
61
+
62
+ const WINDOWS_CLIPBOARD_IMAGE_SCRIPT = [
63
+ "$ErrorActionPreference='Stop'",
64
+ "Add-Type -AssemblyName System.Windows.Forms",
65
+ "Add-Type -AssemblyName System.Drawing",
66
+ "$image=$null",
67
+ "for ($attempt=0; $attempt -lt 3; $attempt+=1) {",
68
+ " try { $image=[System.Windows.Forms.Clipboard]::GetImage(); break }",
69
+ " catch [System.Runtime.InteropServices.ExternalException] {",
70
+ " if ($attempt -eq 2) { throw }",
71
+ " Start-Sleep -Milliseconds 50",
72
+ " }",
73
+ "}",
74
+ "if ($null -eq $image) { exit 3 }",
75
+ "$stream=New-Object System.IO.MemoryStream",
76
+ "try {",
77
+ " $image.Save($stream,[System.Drawing.Imaging.ImageFormat]::Png)",
78
+ " $bytes=$stream.ToArray()",
79
+ " [Console]::OpenStandardOutput().Write($bytes,0,$bytes.Length)",
80
+ "} finally {",
81
+ " $stream.Dispose()",
82
+ " $image.Dispose()",
83
+ "}",
84
+ ].join("\n");
85
+
86
+ const MACOS_CLIPBOARD_IMAGE_SCRIPT = String.raw`
87
+ ObjC.import("AppKit");
88
+ ObjC.import("CoreGraphics");
89
+ ObjC.import("Foundation");
90
+ ObjC.import("ImageIO");
91
+
92
+ function isObjCNil(value) {
93
+ return value == null ||
94
+ (typeof value.isNil === "function" && value.isNil());
95
+ }
96
+
97
+ function run(argv) {
98
+ let stage = "arguments";
99
+ try {
100
+ const outputPath = String(argv[0]);
101
+ const maximumBytes = Number(argv[1]);
102
+ const maximumSourceBytes = Number(argv[2]);
103
+ const maximumPixels = Number(argv[3]);
104
+ const maximumDimension = Number(argv[4]);
105
+ const maximumDecodedBytes = Number(argv[5]);
106
+ if (
107
+ outputPath.length < 1 ||
108
+ !Number.isSafeInteger(maximumBytes) ||
109
+ !Number.isSafeInteger(maximumSourceBytes) ||
110
+ !Number.isSafeInteger(maximumPixels) ||
111
+ !Number.isSafeInteger(maximumDimension) ||
112
+ !Number.isSafeInteger(maximumDecodedBytes) ||
113
+ maximumBytes <= 0 ||
114
+ maximumSourceBytes <= 0 ||
115
+ maximumPixels <= 0 ||
116
+ maximumDimension <= 0 ||
117
+ maximumDecodedBytes <= 0
118
+ ) {
119
+ return "invalid:arguments";
120
+ }
121
+ stage = "pasteboard";
122
+ const pasteboard = $.NSPasteboard.generalPasteboard;
123
+ stage = "png-read";
124
+ let imageData = pasteboard.dataForType($.NSPasteboardTypePNG);
125
+ let imageKind = "png";
126
+ stage = "png-check";
127
+ if (isObjCNil(imageData)) {
128
+ stage = "tiff-read";
129
+ const tiffData = pasteboard.dataForType($.NSPasteboardTypeTIFF);
130
+ stage = "tiff-check";
131
+ if (isObjCNil(tiffData)) return "none";
132
+ stage = "tiff-length";
133
+ const tiffBytes = Number(tiffData.length);
134
+ if (!Number.isSafeInteger(tiffBytes) || tiffBytes <= 0) {
135
+ return "invalid:tiff-length";
136
+ }
137
+ if (tiffBytes > maximumSourceBytes) return "too-large:tiff-source";
138
+ stage = "tiff-source";
139
+ const imageSource = $.CGImageSourceCreateWithData(tiffData, $());
140
+ stage = "tiff-count";
141
+ const imageCount = isObjCNil(imageSource)
142
+ ? 0
143
+ : Number($.CGImageSourceGetCount(imageSource));
144
+ if (
145
+ isObjCNil(imageSource) ||
146
+ !Number.isSafeInteger(imageCount) ||
147
+ imageCount < 1
148
+ ) {
149
+ return "invalid:tiff-source";
150
+ }
151
+ // ImageIO defaults immediate caching to false, so the CGImage remains
152
+ // lazy through the scalar getters. Rendering/encoding is reached only
153
+ // after every layout bound below passes.
154
+ stage = "tiff-image-create";
155
+ const cgImage = $.CGImageSourceCreateImageAtIndex(imageSource, 0, $());
156
+ if (isObjCNil(cgImage)) return "invalid:tiff-image-create";
157
+ stage = "tiff-image-layout";
158
+ const imageIsMask = Number($.CGImageIsMask(cgImage));
159
+ if (
160
+ !Number.isSafeInteger(imageIsMask) ||
161
+ (imageIsMask !== 0 && imageIsMask !== 1)
162
+ ) {
163
+ return "invalid:tiff-image-layout";
164
+ }
165
+ if (imageIsMask === 1) {
166
+ return "invalid:tiff-image-mask";
167
+ }
168
+ const width = Number($.CGImageGetWidth(cgImage));
169
+ const height = Number($.CGImageGetHeight(cgImage));
170
+ const bitsPerComponent = Number($.CGImageGetBitsPerComponent(cgImage));
171
+ const bitsPerPixel = Number($.CGImageGetBitsPerPixel(cgImage));
172
+ const bytesPerRow = Number($.CGImageGetBytesPerRow(cgImage));
173
+ if (
174
+ !Number.isSafeInteger(width) ||
175
+ !Number.isSafeInteger(height) ||
176
+ !Number.isSafeInteger(bitsPerComponent) ||
177
+ !Number.isSafeInteger(bitsPerPixel) ||
178
+ !Number.isSafeInteger(bytesPerRow) ||
179
+ width <= 0 ||
180
+ height <= 0 ||
181
+ bitsPerComponent <= 0 ||
182
+ bitsPerPixel <= 0 ||
183
+ bytesPerRow <= 0
184
+ ) {
185
+ return "invalid:tiff-image-layout";
186
+ }
187
+ if (
188
+ width > maximumDimension ||
189
+ height > maximumDimension ||
190
+ width > Math.floor(maximumPixels / height) ||
191
+ bitsPerComponent > 16 ||
192
+ bitsPerPixel > 64 ||
193
+ bytesPerRow > Math.floor(maximumDecodedBytes / height)
194
+ ) {
195
+ return "too-large:tiff-image-layout";
196
+ }
197
+ if (bytesPerRow < Math.ceil((width * bitsPerPixel) / 8)) {
198
+ return "invalid:tiff-image-layout";
199
+ }
200
+ stage = "tiff-color-space";
201
+ const colorSpace = $.CGImageGetColorSpace(cgImage);
202
+ if (isObjCNil(colorSpace)) return "invalid:tiff-color-space";
203
+ stage = "tiff-color-model";
204
+ const colorModel = Number($.CGColorSpaceGetModel(colorSpace));
205
+ const isRgb = colorModel === Number($.kCGColorSpaceModelRGB);
206
+ const isMonochrome =
207
+ colorModel === Number($.kCGColorSpaceModelMonochrome);
208
+ if (!isRgb && !isMonochrome) {
209
+ return "invalid:unsupported-color-model";
210
+ }
211
+ if (bitsPerPixel < (isRgb ? 3 : 1) * bitsPerComponent) {
212
+ return "invalid:tiff-image-layout";
213
+ }
214
+ const normalizedBytesPerPixel =
215
+ (isRgb ? 4 : 2) * Math.ceil(bitsPerComponent / 8);
216
+ if (
217
+ width >
218
+ Math.floor(
219
+ maximumDecodedBytes / (height * normalizedBytesPerPixel),
220
+ )
221
+ ) {
222
+ return "too-large:tiff-image-layout";
223
+ }
224
+ stage = "tiff-bitmap";
225
+ const bitmap = $.NSBitmapImageRep.alloc.initWithCGImage(cgImage);
226
+ if (isObjCNil(bitmap)) return "invalid:tiff-bitmap";
227
+ stage = "tiff-encode";
228
+ imageData = bitmap.representationUsingTypeProperties(4, $({}));
229
+ if (isObjCNil(imageData)) return "invalid:tiff-encode";
230
+ imageKind = "tiff-png";
231
+ }
232
+ stage = "image-length";
233
+ const imageBytes = Number(imageData.length);
234
+ if (!Number.isSafeInteger(imageBytes) || imageBytes <= 0) {
235
+ return "invalid:image-length";
236
+ }
237
+ if (imageBytes > maximumBytes) return "too-large:image-bytes";
238
+ stage = "image-write";
239
+ if (!imageData.writeToFileAtomically($(outputPath), true)) {
240
+ return "invalid:image-write";
241
+ }
242
+ return imageKind;
243
+ } catch (error) {
244
+ return "error:" + stage;
245
+ }
246
+ }`;
247
+
248
+ const defaultSystemDeps = {
249
+ accessSync,
250
+ ensurePrivateDirectory,
251
+ ensurePrivateFile,
252
+ lstatSync,
253
+ mkdtempSync,
254
+ readFileSync,
255
+ rmSync,
256
+ spawnSync: (...args) => executionBroker.spawnSync(...args),
257
+ statSync,
258
+ tmpdir,
259
+ writeFileSync,
260
+ };
261
+
262
+ function canExecute(filePath, deps) {
263
+ if (!filePath) return false;
264
+ try {
265
+ deps.accessSync(filePath, fsConstants.X_OK);
266
+ return true;
267
+ } catch {
268
+ return false;
269
+ }
270
+ }
271
+
272
+ function executableFromPath(name, { env, platform, deps }) {
273
+ const pathValue = String(env.PATH || env.Path || "");
274
+ if (!pathValue) return null;
275
+ const separator = platform === "win32" ? ";" : ":";
276
+ const pathJoin = platform === "win32" ? win32Path.join : posixPath.join;
277
+ const extensions =
278
+ platform === "win32"
279
+ ? String(env.PATHEXT || ".EXE;.CMD;.BAT")
280
+ .split(";")
281
+ .filter(Boolean)
282
+ : [""];
283
+ for (const rawDirectory of pathValue.split(separator)) {
284
+ const directory = rawDirectory.trim().replace(/^"|"$/gu, "");
285
+ if (!directory) continue;
286
+ for (const extension of extensions) {
287
+ const candidate = pathJoin(directory, `${name}${extension}`);
288
+ if (canExecute(candidate, deps)) return candidate;
289
+ }
290
+ }
291
+ return null;
292
+ }
293
+
294
+ /** Resolve the guarded native tools without spawning an untrusted probe. */
295
+ export function resolveSystemClipboardImageTools(options = {}) {
296
+ const platform = options.platform || process.platform;
297
+ const env = options.env || process.env;
298
+ const deps = { ...defaultSystemDeps, ...(options.deps || {}) };
299
+ if (platform === "darwin") {
300
+ const osascript = "/usr/bin/osascript";
301
+ return canExecute(osascript, deps)
302
+ ? { supported: true, executables: { osascript } }
303
+ : {
304
+ supported: false,
305
+ reason: "macOS clipboard image helper is unavailable.",
306
+ };
307
+ }
308
+ if (platform === "win32") {
309
+ const systemRootValue = String(env.SystemRoot || env.WINDIR || "");
310
+ const systemRoot = /^[A-Za-z]:\\[^\r\n<>"|?*]+$/u.test(systemRootValue)
311
+ ? systemRootValue
312
+ : "C:\\Windows";
313
+ const windowsPowerShell = win32Path.join(
314
+ systemRoot,
315
+ "System32",
316
+ "WindowsPowerShell",
317
+ "v1.0",
318
+ "powershell.exe",
319
+ );
320
+ const powershell = canExecute(windowsPowerShell, deps)
321
+ ? windowsPowerShell
322
+ : executableFromPath("pwsh", { env, platform, deps });
323
+ return powershell
324
+ ? { supported: true, executables: { powershell } }
325
+ : {
326
+ supported: false,
327
+ reason: "Windows PowerShell clipboard image support is unavailable.",
328
+ };
329
+ }
330
+ if (platform === "linux") {
331
+ if (!env.WAYLAND_DISPLAY && !env.DISPLAY) {
332
+ return {
333
+ supported: false,
334
+ reason: "No Wayland or X11 clipboard display is available.",
335
+ };
336
+ }
337
+ const wlPaste = env.WAYLAND_DISPLAY
338
+ ? executableFromPath("wl-paste", { env, platform, deps })
339
+ : null;
340
+ const xclip = env.DISPLAY
341
+ ? executableFromPath("xclip", { env, platform, deps })
342
+ : null;
343
+ return wlPaste || xclip
344
+ ? { supported: true, executables: { wlPaste, xclip } }
345
+ : {
346
+ supported: false,
347
+ reason: "No Wayland or X11 clipboard image reader is available.",
348
+ };
349
+ }
350
+ return {
351
+ supported: false,
352
+ reason: `System clipboard image reading is unsupported on ${platform}.`,
353
+ };
354
+ }
355
+
356
+ function boundedPositiveInteger(
357
+ value,
358
+ fallback,
359
+ maximum = Number.MAX_SAFE_INTEGER,
360
+ ) {
361
+ const parsed = Number(value);
362
+ if (!Number.isSafeInteger(parsed) || parsed <= 0) return fallback;
363
+ return Math.min(parsed, maximum);
364
+ }
365
+
366
+ function commandFailure(result, tool) {
367
+ if (result?.error?.code === "ENOENT") return `${tool} is unavailable.`;
368
+ if (result?.error?.code === "ETIMEDOUT") {
369
+ return "System clipboard image read timed out.";
370
+ }
371
+ if (result?.signal) return `${tool} clipboard image helper was terminated.`;
372
+ return `${tool} clipboard image helper exited with status ${String(result?.status)}.`;
373
+ }
374
+
375
+ function isOutputLimitError(error) {
376
+ return (
377
+ error?.code === "ENOBUFS" ||
378
+ /maxbuffer/iu.test(String(error?.message || ""))
379
+ );
380
+ }
381
+
382
+ function normalizeStdout(value) {
383
+ if (Buffer.isBuffer(value)) return value;
384
+ if (value instanceof Uint8Array) return Buffer.from(value);
385
+ if (typeof value === "string") return Buffer.from(value, "binary");
386
+ return Buffer.alloc(0);
387
+ }
388
+
389
+ /** Return the media type identified by image magic bytes, or `null`. */
390
+ export function detectClipboardImageMediaType(value) {
391
+ const data = Buffer.isBuffer(value) ? value : Buffer.from(value || []);
392
+ if (
393
+ data.length >= 8 &&
394
+ data
395
+ .subarray(0, 8)
396
+ .equals(Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]))
397
+ ) {
398
+ return "image/png";
399
+ }
400
+ if (
401
+ data.length >= 3 &&
402
+ data[0] === 0xff &&
403
+ data[1] === 0xd8 &&
404
+ data[2] === 0xff
405
+ ) {
406
+ return "image/jpeg";
407
+ }
408
+ if (
409
+ data.length >= 6 &&
410
+ (data.subarray(0, 6).equals(Buffer.from("GIF87a", "ascii")) ||
411
+ data.subarray(0, 6).equals(Buffer.from("GIF89a", "ascii")))
412
+ ) {
413
+ return "image/gif";
414
+ }
415
+ if (
416
+ data.length >= 12 &&
417
+ data.subarray(0, 4).equals(Buffer.from("RIFF", "ascii")) &&
418
+ data.subarray(8, 12).equals(Buffer.from("WEBP", "ascii"))
419
+ ) {
420
+ return "image/webp";
421
+ }
422
+ return null;
423
+ }
424
+
425
+ /** Ordered binary clipboard readers for platforms that expose stdout bytes. */
426
+ export function systemClipboardImageCommands(
427
+ platform = process.platform,
428
+ executables = {},
429
+ ) {
430
+ if (platform === "win32") {
431
+ return executables.powershell
432
+ ? [
433
+ {
434
+ cmd: executables.powershell,
435
+ args: [
436
+ "-NoLogo",
437
+ "-NoProfile",
438
+ "-NonInteractive",
439
+ "-Sta",
440
+ "-Command",
441
+ WINDOWS_CLIPBOARD_IMAGE_SCRIPT,
442
+ ],
443
+ mediaType: "image/png",
444
+ noImageStatus: 3,
445
+ },
446
+ ]
447
+ : [];
448
+ }
449
+ if (platform === "linux") {
450
+ const requestedTypes = [
451
+ ["image/png", "image/png"],
452
+ ["image/jpeg", "image/jpeg"],
453
+ ["image/jpg", "image/jpeg"],
454
+ ["image/gif", "image/gif"],
455
+ ["image/webp", "image/webp"],
456
+ ];
457
+ const readers = [];
458
+ if (executables.wlPaste) {
459
+ readers.push(
460
+ ...requestedTypes.map(([requestedType, mediaType]) => ({
461
+ cmd: executables.wlPaste,
462
+ args: ["--no-newline", "--type", requestedType],
463
+ mediaType,
464
+ })),
465
+ );
466
+ }
467
+ if (executables.xclip) {
468
+ readers.push(
469
+ ...requestedTypes.map(([requestedType, mediaType]) => ({
470
+ cmd: executables.xclip,
471
+ args: ["-selection", "clipboard", "-t", requestedType, "-o"],
472
+ mediaType,
473
+ })),
474
+ );
475
+ }
476
+ return readers;
477
+ }
478
+ return [];
479
+ }
480
+
481
+ function spawnClipboardReader(deps, candidate, { maxBytes, timeoutMs }) {
482
+ return deps.spawnSync(candidate.cmd, candidate.args, {
483
+ encoding: null,
484
+ maxBuffer: maxBytes + 64 * 1024,
485
+ timeout: timeoutMs,
486
+ windowsHide: true,
487
+ origin: "repl:clipboard-image",
488
+ policy: "allow",
489
+ scope: "clipboard",
490
+ shell: false,
491
+ });
492
+ }
493
+
494
+ function readCommandClipboardImage(platform, deps, options) {
495
+ const candidates = systemClipboardImageCommands(
496
+ platform,
497
+ options.executables,
498
+ );
499
+ let commandStarted = false;
500
+ let lastFailure = "No supported system clipboard image tool is available.";
501
+ const deadline = Date.now() + options.timeoutMs;
502
+ for (const candidate of candidates) {
503
+ const remainingMs = deadline - Date.now();
504
+ if (remainingMs <= 0) {
505
+ throw new Error("System clipboard image read timed out.");
506
+ }
507
+ let result;
508
+ try {
509
+ result = spawnClipboardReader(deps, candidate, {
510
+ ...options,
511
+ timeoutMs: remainingMs,
512
+ });
513
+ } catch (error) {
514
+ if (isOutputLimitError(error)) {
515
+ throw new Error(`Clipboard image exceeds ${options.maxBytes} bytes.`);
516
+ }
517
+ if (error?.code === "ETIMEDOUT") {
518
+ throw new Error("System clipboard image read timed out.");
519
+ }
520
+ lastFailure = `${candidate.cmd} clipboard image helper could not start.`;
521
+ continue;
522
+ }
523
+ if (result?.error) {
524
+ if (isOutputLimitError(result.error)) {
525
+ throw new Error(`Clipboard image exceeds ${options.maxBytes} bytes.`);
526
+ }
527
+ if (result.error.code !== "ENOENT") commandStarted = true;
528
+ lastFailure = commandFailure(result, candidate.cmd);
529
+ if (result.error.code === "ETIMEDOUT") throw new Error(lastFailure);
530
+ continue;
531
+ }
532
+ commandStarted = true;
533
+ if (result?.status === candidate.noImageStatus) return null;
534
+ if (result?.status !== 0 || result?.signal) {
535
+ lastFailure = commandFailure(result, candidate.cmd);
536
+ continue;
537
+ }
538
+ const data = normalizeStdout(result.stdout);
539
+ if (!data.length) continue;
540
+ if (data.length > options.maxBytes) {
541
+ throw new Error(`Clipboard image exceeds ${options.maxBytes} bytes.`);
542
+ }
543
+ return { mediaType: candidate.mediaType, data, tool: candidate.cmd };
544
+ }
545
+ if (!commandStarted) throw new Error(lastFailure);
546
+ if (platform === "win32") throw new Error(lastFailure);
547
+ return null;
548
+ }
549
+
550
+ function requirePrivateRegularFile(filePath, deps) {
551
+ const fileStat = deps.lstatSync(filePath);
552
+ if (!fileStat.isFile() || fileStat.isSymbolicLink()) {
553
+ throw new Error("Clipboard helper did not produce a regular private file.");
554
+ }
555
+ deps.ensurePrivateFile(filePath, {
556
+ applyWindowsAcl: false,
557
+ failIfUnavailable: true,
558
+ });
559
+ return deps.statSync(filePath);
560
+ }
561
+
562
+ function readMacosClipboardImage(deps, options) {
563
+ let directory = null;
564
+ try {
565
+ directory = deps.mkdtempSync(join(deps.tmpdir(), "cc-clipboard-image-"));
566
+ deps.ensurePrivateDirectory(directory, {
567
+ applyWindowsAcl: false,
568
+ failIfUnavailable: true,
569
+ });
570
+ const pngPath = join(directory, "clipboard.png");
571
+ deps.writeFileSync(pngPath, Buffer.alloc(0), {
572
+ mode: PRIVATE_FILE_MODE,
573
+ });
574
+ deps.ensurePrivateFile(pngPath, {
575
+ applyWindowsAcl: false,
576
+ failIfUnavailable: true,
577
+ });
578
+
579
+ const readResult = deps.spawnSync(
580
+ options.executables.osascript,
581
+ [
582
+ "-l",
583
+ "JavaScript",
584
+ "-e",
585
+ MACOS_CLIPBOARD_IMAGE_SCRIPT,
586
+ "--",
587
+ pngPath,
588
+ String(options.maxBytes),
589
+ String(MAX_MACOS_SOURCE_BYTES),
590
+ String(MAX_MACOS_IMAGE_PIXELS),
591
+ String(MAX_MACOS_IMAGE_DIMENSION),
592
+ String(MAX_MACOS_DECODED_IMAGE_BYTES),
593
+ ],
594
+ {
595
+ encoding: "utf8",
596
+ maxBuffer: 64 * 1024,
597
+ timeout: options.timeoutMs,
598
+ windowsHide: true,
599
+ origin: "repl:clipboard-image",
600
+ policy: "allow",
601
+ scope: "clipboard",
602
+ shell: false,
603
+ },
604
+ );
605
+ if (readResult?.error || readResult?.signal || readResult?.status !== 0) {
606
+ throw new Error(commandFailure(readResult, "osascript"));
607
+ }
608
+ const imageKind = String(readResult.stdout || "")
609
+ .trim()
610
+ .toLowerCase();
611
+ if (imageKind === "none") return null;
612
+ if (imageKind === "too-large" || imageKind.startsWith("too-large:")) {
613
+ throw new Error(`Clipboard image exceeds ${options.maxBytes} bytes.`);
614
+ }
615
+ if (imageKind === "invalid" || imageKind.startsWith("invalid:")) {
616
+ const stageValue = imageKind.includes(":")
617
+ ? imageKind.slice(imageKind.indexOf(":") + 1)
618
+ : "";
619
+ const stage = /^[a-z][a-z-]{0,63}$/u.test(stageValue)
620
+ ? ` (${stageValue})`
621
+ : "";
622
+ throw new Error(
623
+ `macOS clipboard helper returned invalid image data${stage}.`,
624
+ );
625
+ }
626
+ if (imageKind.startsWith("error:")) {
627
+ const stageValue = imageKind.slice("error:".length);
628
+ const stage = MACOS_CLIPBOARD_HELPER_ERROR_STAGES.has(stageValue)
629
+ ? ` (${stageValue})`
630
+ : "";
631
+ throw new Error(`macOS clipboard helper failed${stage}.`);
632
+ }
633
+ if (imageKind !== "png" && imageKind !== "tiff-png") {
634
+ throw new Error("macOS clipboard helper returned an invalid image kind.");
635
+ }
636
+ const finalStat = requirePrivateRegularFile(pngPath, deps);
637
+ if (finalStat.size <= 0)
638
+ throw new Error("The clipboard image payload is empty.");
639
+ if (finalStat.size > options.maxBytes) {
640
+ throw new Error(`Clipboard image exceeds ${options.maxBytes} bytes.`);
641
+ }
642
+ return {
643
+ mediaType: "image/png",
644
+ data: deps.readFileSync(pngPath),
645
+ tool: imageKind === "png" ? "osascript" : "osascript+jxa-tiff",
646
+ };
647
+ } finally {
648
+ if (directory) {
649
+ try {
650
+ deps.rmSync(directory, { recursive: true, force: true });
651
+ } catch {
652
+ // The directory is owner-private; cleanup remains best effort.
653
+ }
654
+ }
655
+ }
656
+ }
657
+
658
+ /** Read one bounded image from the current user's system clipboard. */
659
+ export function readSystemClipboardImage(options = {}) {
660
+ const platform = options.platform || process.platform;
661
+ const maxBytes = boundedPositiveInteger(
662
+ options.maxBytes,
663
+ MAX_CLIPBOARD_IMAGE_BYTES,
664
+ MAX_CLIPBOARD_IMAGE_BYTES,
665
+ );
666
+ const timeoutMs = boundedPositiveInteger(
667
+ options.timeoutMs,
668
+ CLIPBOARD_IMAGE_READ_TIMEOUT_MS,
669
+ 30_000,
670
+ );
671
+ const deps = { ...defaultSystemDeps, ...(options.deps || {}) };
672
+ const resolution = options.executables
673
+ ? { supported: true, executables: options.executables }
674
+ : resolveSystemClipboardImageTools({
675
+ platform,
676
+ env: options.env || process.env,
677
+ deps,
678
+ });
679
+ if (!resolution.supported) {
680
+ throw new Error(resolution.reason);
681
+ }
682
+ const executionOptions = {
683
+ maxBytes,
684
+ timeoutMs,
685
+ executables: resolution.executables,
686
+ };
687
+ if (platform === "darwin") {
688
+ return readMacosClipboardImage(deps, executionOptions);
689
+ }
690
+ if (platform === "win32" || platform === "linux") {
691
+ return readCommandClipboardImage(platform, deps, executionOptions);
692
+ }
693
+ throw new Error(
694
+ `System clipboard image reading is unsupported on ${platform}.`,
695
+ );
696
+ }
697
+
698
+ /** Create the production binding injected into a standard terminal REPL. */
699
+ export function createSystemClipboardImageBinding(options = {}) {
700
+ const platform = options.platform || process.platform;
701
+ const deps = { ...defaultSystemDeps, ...(options.deps || {}) };
702
+ const resolution = resolveSystemClipboardImageTools({
703
+ platform,
704
+ env: options.env || process.env,
705
+ deps,
706
+ });
707
+ if (!resolution.supported) return null;
708
+ return Object.freeze({
709
+ supportsImagePaste: true,
710
+ mode: "system-clipboard",
711
+ platform,
712
+ readImage: async () =>
713
+ readSystemClipboardImage({
714
+ ...options,
715
+ platform,
716
+ deps,
717
+ executables: resolution.executables,
718
+ }),
719
+ });
720
+ }
17
721
 
18
722
  export function detectClipboardImageCapability(binding) {
19
723
  if (
20
724
  binding?.supportsImagePaste === true &&
21
725
  typeof binding.readImage === "function"
22
726
  ) {
727
+ const systemClipboard = binding.mode === "system-clipboard";
23
728
  return {
24
729
  supported: true,
25
- mode: "host-binding",
26
- reason: "The terminal host exposes clipboard image bytes.",
730
+ mode: systemClipboard ? "system-clipboard" : "host-binding",
731
+ reason: systemClipboard
732
+ ? "The CLI can read clipboard image bytes through guarded platform tools."
733
+ : "The terminal host exposes clipboard image bytes.",
27
734
  };
28
735
  }
29
736
  return {
@@ -61,15 +768,15 @@ export async function readClipboardImageChip(binding, options = {}) {
61
768
  return {
62
769
  ok: false,
63
770
  supported: true,
64
- mode: "host-binding",
65
- reason: `Clipboard image read failed: ${error.message}`,
771
+ mode: capability.mode,
772
+ reason: `Clipboard image read failed: ${error?.message || String(error)}`,
66
773
  };
67
774
  }
68
775
  if (!image) {
69
776
  return {
70
777
  ok: false,
71
778
  supported: true,
72
- mode: "host-binding",
779
+ mode: capability.mode,
73
780
  reason: "The clipboard does not currently contain an image.",
74
781
  };
75
782
  }
@@ -78,7 +785,7 @@ export async function readClipboardImageChip(binding, options = {}) {
78
785
  return {
79
786
  ok: false,
80
787
  supported: true,
81
- mode: "host-binding",
788
+ mode: capability.mode,
82
789
  reason: `Unsupported clipboard image type: ${mediaType || "unknown"}.`,
83
790
  };
84
791
  }
@@ -87,26 +794,38 @@ export async function readClipboardImageChip(binding, options = {}) {
87
794
  return {
88
795
  ok: false,
89
796
  supported: true,
90
- mode: "host-binding",
797
+ mode: capability.mode,
91
798
  reason: "The clipboard image payload is empty or invalid.",
92
799
  };
93
800
  }
94
- const maxBytes = Math.max(
95
- 1,
96
- Number(options.maxBytes) || MAX_CLIPBOARD_IMAGE_BYTES,
801
+ const maxBytes = boundedPositiveInteger(
802
+ options.maxBytes,
803
+ MAX_CLIPBOARD_IMAGE_BYTES,
804
+ MAX_CLIPBOARD_IMAGE_BYTES,
97
805
  );
98
806
  if (data.length > maxBytes) {
99
807
  return {
100
808
  ok: false,
101
809
  supported: true,
102
- mode: "host-binding",
810
+ mode: capability.mode,
103
811
  reason: `Clipboard image exceeds ${maxBytes} bytes.`,
104
812
  };
105
813
  }
814
+ const detectedMediaType = detectClipboardImageMediaType(data);
815
+ if (detectedMediaType !== mediaType) {
816
+ return {
817
+ ok: false,
818
+ supported: true,
819
+ mode: capability.mode,
820
+ reason: detectedMediaType
821
+ ? `Clipboard image signature is ${detectedMediaType}, not ${mediaType}.`
822
+ : "Clipboard image signature is invalid or unsupported.",
823
+ };
824
+ }
106
825
  return {
107
826
  ok: true,
108
827
  supported: true,
109
- mode: "host-binding",
828
+ mode: capability.mode,
110
829
  bytes: data.length,
111
830
  mediaType,
112
831
  chip: {